diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 3cff853f92..1a466dea58 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -1069,7 +1069,7 @@ namespace osu.Game.Tests.Visual.SongSelect return Precision.AlmostEquals( carousel.ScreenSpaceDrawQuad.Centre, carousel.Items - .First(i => i.Item!.State.Value == CarouselItemState.Selected) + .First(i => i.Item?.State.Value == CarouselItemState.Selected) .ScreenSpaceDrawQuad.Centre, 100); }); } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 4a6ff7417e..12dcdbd3dc 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -770,7 +770,9 @@ namespace osu.Game.Screens.Select { updateItem(item); - if (item.Item!.Visible) + Debug.Assert(item.Item != null); + + if (item.Item.Visible) { bool isSelected = item.Item.State.Value == CarouselItemState.Selected; diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index 8667dce226..9302578038 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -10,7 +10,7 @@ namespace osu.Game.Screens.Select.Carousel /// public class CarouselGroup : CarouselItem { - public override DrawableCarouselItem CreateDrawableRepresentation() => null!; + public override DrawableCarouselItem? CreateDrawableRepresentation() => null; public IReadOnlyList Items => items; diff --git a/osu.Game/Screens/Select/Carousel/CarouselItem.cs b/osu.Game/Screens/Select/Carousel/CarouselItem.cs index 5de9f2b995..38a1d7117f 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselItem.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osu.Framework.Bindables; namespace osu.Game.Screens.Select.Carousel @@ -41,7 +42,7 @@ namespace osu.Game.Screens.Select.Carousel /// /// Create a fresh drawable version of this item. /// - public abstract DrawableCarouselItem CreateDrawableRepresentation(); + public abstract DrawableCarouselItem? CreateDrawableRepresentation(); public virtual void Filter(FilterCriteria criteria) { @@ -49,7 +50,12 @@ namespace osu.Game.Screens.Select.Carousel public virtual int CompareTo(FilterCriteria criteria, CarouselItem other) => ItemID.CompareTo(other.ItemID); - public int CompareTo(CarouselItem? other) => CarouselYPosition.CompareTo(other!.CarouselYPosition); + public int CompareTo(CarouselItem? other) + { + Debug.Assert(other != null); + + return CarouselYPosition.CompareTo(other.CarouselYPosition); + } } public enum CarouselItemState diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 88a55198b2..e05d950369 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -192,7 +192,7 @@ namespace osu.Game.Screens.Select.Carousel protected override bool OnClick(ClickEvent e) { - if (Item!.State.Value == CarouselItemState.Selected) + if (Item?.State.Value == CarouselItemState.Selected) startRequested?.Invoke(beatmapInfo); return base.OnClick(e); @@ -200,13 +200,13 @@ namespace osu.Game.Screens.Select.Carousel protected override void ApplyState() { - if (Item!.State.Value != CarouselItemState.Collapsed && Alpha == 0) + if (Item?.State.Value != CarouselItemState.Collapsed && Alpha == 0) starCounter.ReplayAnimation(); starDifficultyCancellationSource?.Cancel(); // Only compute difficulty when the item is visible. - if (Item.State.Value != CarouselItemState.Collapsed) + if (Item?.State.Value != CarouselItemState.Collapsed) { // We've potentially cancelled the computation above so a new bindable is required. starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmapInfo, (starDifficultyCancellationSource = new CancellationTokenSource()).Token); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index f0bb8b15c2..8974b173fb 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -73,10 +73,10 @@ namespace osu.Game.Screens.Select.Carousel { base.Update(); + Debug.Assert(Item != null); // position updates should not occur if the item is filtered away. // this avoids panels flying across the screen only to be eventually off-screen or faded out. - if (!Item!.Visible) - return; + if (!Item.Visible) return; float targetY = Item.CarouselYPosition; @@ -146,7 +146,9 @@ namespace osu.Game.Screens.Select.Carousel private void updateBeatmapDifficulties() { - var carouselBeatmapSet = (CarouselBeatmapSet)Item!; + if (Item == null) return; + + var carouselBeatmapSet = (CarouselBeatmapSet)Item; var visibleBeatmaps = carouselBeatmapSet.Items.Where(c => c.Visible).ToArray(); @@ -166,7 +168,7 @@ namespace osu.Game.Screens.Select.Carousel { X = 100, RelativeSizeAxes = Axes.Both, - ChildrenEnumerable = visibleBeatmaps.Select(c => c.CreateDrawableRepresentation()) + ChildrenEnumerable = visibleBeatmaps.Select(c => c.CreateDrawableRepresentation()!) }; beatmapsLoadTask = LoadComponentAsync(beatmapContainer, loaded => @@ -191,7 +193,7 @@ namespace osu.Game.Screens.Select.Carousel float yPos = DrawableCarouselBeatmap.CAROUSEL_BEATMAP_SPACING; - bool isSelected = Item!.State.Value == CarouselItemState.Selected; + bool isSelected = Item?.State.Value == CarouselItemState.Selected; foreach (var panel in beatmapContainer.Children) { @@ -213,7 +215,7 @@ namespace osu.Game.Screens.Select.Carousel List items = new List(); - if (Item!.State.Value == CarouselItemState.NotSelected) + if (Item?.State.Value == CarouselItemState.NotSelected) items.Add(new OsuMenuItem("Expand", MenuItemType.Highlighted, () => Item.State.Value = CarouselItemState.Selected)); if (beatmapSet.OnlineID > 0 && viewDetails != null) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 580dcb3471..c283cca3c8 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -103,7 +103,7 @@ namespace osu.Game.Screens.Select.Carousel protected virtual void UpdateItem() { - if (item == null || Item == null) + if (Item == null) return; Scheduler.AddOnce(ApplyState); @@ -126,9 +126,11 @@ namespace osu.Game.Screens.Select.Carousel protected virtual void ApplyState() { + if (Item == null) return; + // Use the fact that we know the precise height of the item from the model to avoid the need for AutoSize overhead. // Additionally, AutoSize doesn't work well due to content starting off-screen and being masked away. - Height = Item!.TotalHeight; + Height = Item.TotalHeight; switch (Item.State.Value) { @@ -158,7 +160,9 @@ namespace osu.Game.Screens.Select.Carousel protected override bool OnClick(ClickEvent e) { - Item!.State.Value = CarouselItemState.Selected; + Debug.Assert(Item != null); + + Item.State.Value = CarouselItemState.Selected; return true; } }