From 1be2571d33b9561267398042b02d1f30dd25b600 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Apr 2018 16:04:02 +0900 Subject: [PATCH 1/3] Make BeatmapSetOverlay accept nulls everywhere --- .../Visual/TestCaseBeatmapScoresContainer.cs | 4 +- .../Visual/TestCaseBeatmapSetOverlay.cs | 27 +++++ osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 56 ++++++---- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 27 ++++- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 33 ++++-- .../{ => Buttons}/DownloadButton.cs | 2 +- .../{ => Buttons}/FavouriteButton.cs | 2 +- .../BeatmapSet/{ => Buttons}/HeaderButton.cs | 4 +- .../BeatmapSet/{ => Buttons}/PreviewButton.cs | 8 +- osu.Game/Overlays/BeatmapSet/Details.cs | 20 +++- osu.Game/Overlays/BeatmapSet/Header.cs | 36 +++++-- osu.Game/Overlays/BeatmapSet/Info.cs | 11 +- .../BeatmapSet/Scores/ScoresContainer.cs | 102 +++++++++++------- osu.Game/Overlays/BeatmapSet/SuccessRate.cs | 26 +++-- osu.Game/Overlays/BeatmapSetOverlay.cs | 43 +++----- osu.Game/Overlays/Direct/PlayButton.cs | 16 +-- .../Sections/BeatmapMetadataContainer.cs | 2 +- .../Carousel/DrawableCarouselBeatmapSet.cs | 2 +- .../Screens/Select/Details/AdvancedStats.cs | 8 +- .../Screens/Select/Details/FailRetryGraph.cs | 6 +- .../Screens/Select/Details/UserRatings.cs | 25 +++-- osu.Game/Users/UpdateableAvatar.cs | 22 ++-- 23 files changed, 322 insertions(+), 162 deletions(-) rename osu.Game/Overlays/BeatmapSet/{ => Buttons}/DownloadButton.cs (97%) rename osu.Game/Overlays/BeatmapSet/{ => Buttons}/FavouriteButton.cs (98%) rename osu.Game/Overlays/BeatmapSet/{ => Buttons}/HeaderButton.cs (94%) rename osu.Game/Overlays/BeatmapSet/{ => Buttons}/PreviewButton.cs (97%) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs index 6cb6a342a8..85f3364039 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs @@ -47,9 +47,7 @@ namespace osu.Game.Tests.Visual AddStep("scores pack 1", () => scoresContainer.Scores = scores); AddStep("scores pack 2", () => scoresContainer.Scores = anotherScores); AddStep("only top score", () => scoresContainer.Scores = new[] { topScore }); - AddStep("remove scores", scoresContainer.CleanAllScores); - AddStep("turn on loading", () => scoresContainer.IsLoading = true); - AddStep("turn off loading", () => scoresContainer.IsLoading = false); + AddStep("remove scores", () => scoresContainer.Scores = null); AddStep("resize to big", () => container.ResizeWidthTo(1, 300)); AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300)); diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs index 69955a90c4..025562f75f 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs @@ -8,6 +8,9 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapSet; +using osu.Game.Overlays.BeatmapSet.Buttons; +using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets; using osu.Game.Users; @@ -18,6 +21,26 @@ namespace osu.Game.Tests.Visual { private readonly BeatmapSetOverlay overlay; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Header), + typeof(ClickableUsername), + typeof(DrawableScore), + typeof(DrawableTopScore), + typeof(ScoresContainer), + typeof(AuthorInfo), + typeof(BasicStats), + typeof(BeatmapPicker), + typeof(Details), + typeof(DownloadButton), + typeof(FavouriteButton), + typeof(Header), + typeof(HeaderButton), + typeof(Info), + typeof(PreviewButton), + typeof(SuccessRate), + }; + public TestCaseBeatmapSetOverlay() { Add(overlay = new BeatmapSetOverlay()); @@ -29,6 +52,10 @@ namespace osu.Game.Tests.Visual var mania = rulesets.GetRuleset(3); var taiko = rulesets.GetRuleset(1); + AddStep(@"show loading", () => overlay.ShowBeatmapSet(null)); + + AddStep(@"show online", () => overlay.FetchAndShowBeatmapSet(55)); + AddStep(@"show first", () => { overlay.ShowBeatmapSet(new BeatmapSetInfo diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f69135e5c9..578d88bd89 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -158,7 +158,7 @@ namespace osu.Game /// Show a beatmap set as an overlay. /// /// The set to display. - public void ShowBeatmapSet(int setId) => beatmapSetOverlay.ShowBeatmapSet(setId); + public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId); /// /// Show a user's profile as an overlay. diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 8b19bca671..66e3148065 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -23,9 +23,8 @@ namespace osu.Game.Overlays.BeatmapSet private readonly ClickableArea clickableArea; private readonly FillFlowContainer fields; - private UserProfileOverlay profile; - private BeatmapSetInfo beatmapSet; + public BeatmapSetInfo BeatmapSet { get { return beatmapSet; } @@ -34,28 +33,36 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmapSet) return; beatmapSet = value; - var i = BeatmapSet.OnlineInfo; + updateDisplay(); + } + } - avatar.User = BeatmapSet.Metadata.Author; - clickableArea.Action = () => profile?.ShowUser(avatar.User); + private void updateDisplay() + { + avatar.User = BeatmapSet?.Metadata.Author; - fields.Children = new Drawable[] - { - new Field("made by", BeatmapSet.Metadata.Author.Username, @"Exo2.0-RegularItalic"), - new Field("submitted on", i.Submitted.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold") - { - Margin = new MarginPadding { Top = 5 }, - }, - }; + fields.Clear(); + if (BeatmapSet == null) + return; - if (i.Ranked.HasValue) + var online = BeatmapSet.OnlineInfo; + + fields.Children = new Drawable[] + { + new Field("made by", BeatmapSet.Metadata.Author.Username, @"Exo2.0-RegularItalic"), + new Field("submitted on", online.Submitted.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold") { - fields.Add(new Field("ranked on ", i.Ranked.Value.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold")); - } - else if (i.LastUpdated.HasValue) - { - fields.Add(new Field("last updated on ", i.LastUpdated.Value.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold")); - } + Margin = new MarginPadding { Top = 5 }, + }, + }; + + if (online.Ranked.HasValue) + { + fields.Add(new Field("ranked on ", online.Ranked.Value.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold")); + } + else if (online.LastUpdated.HasValue) + { + fields.Add(new Field("last updated on ", online.LastUpdated.Value.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold")); } } @@ -73,6 +80,7 @@ namespace osu.Game.Overlays.BeatmapSet Masking = true, Child = avatar = new UpdateableAvatar { + ShowGuestOnNull = false, Size = new Vector2(height), }, EdgeEffect = new EdgeEffectParameters @@ -95,8 +103,12 @@ namespace osu.Game.Overlays.BeatmapSet [BackgroundDependencyLoader(true)] private void load(UserProfileOverlay profile) { - this.profile = profile; - clickableArea.Action = () => profile?.ShowUser(avatar.User); + clickableArea.Action = () => + { + if (avatar.User != null) profile?.ShowUser(avatar.User); + }; + + updateDisplay(); } private class Field : FillFlowContainer diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 8fd34914a7..a7b6b16dcc 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays.BeatmapSet private readonly Statistic length, bpm, circleCount, sliderCount; private BeatmapSetInfo beatmapSet; + public BeatmapSetInfo BeatmapSet { get { return beatmapSet; } @@ -26,11 +27,12 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmapSet) return; beatmapSet = value; - bpm.Value = BeatmapSet.OnlineInfo.BPM.ToString(@"0.##"); + updateDisplay(); } } private BeatmapInfo beatmap; + public BeatmapInfo Beatmap { get { return beatmap; } @@ -39,6 +41,22 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmap) return; beatmap = value; + updateDisplay(); + } + } + + private void updateDisplay() + { + bpm.Value = BeatmapSet?.OnlineInfo.BPM.ToString(@"0.##") ?? "-"; + + if (beatmap == null) + { + length.Value = string.Empty; + circleCount.Value = string.Empty; + sliderCount.Value = string.Empty; + } + else + { length.Value = TimeSpan.FromSeconds(beatmap.OnlineInfo.Length).ToString(@"m\:ss"); circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString(); sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToString(); @@ -62,12 +80,19 @@ namespace osu.Game.Overlays.BeatmapSet }; } + [BackgroundDependencyLoader] + private void load() + { + updateDisplay(); + } + private class Statistic : Container, IHasTooltip { private readonly string name; private readonly OsuSpriteText value; public string TooltipText => name; + public string Value { get { return value.Text; } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 87dc9b104b..6b75ac095d 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -41,9 +41,16 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmapSet) return; beatmapSet = value; - Beatmap.Value = BeatmapSet.Beatmaps.First(); - plays.Value = BeatmapSet.OnlineInfo.PlayCount; - favourites.Value = BeatmapSet.OnlineInfo.FavouriteCount; + updateDisplay(); + } + } + + private void updateDisplay() + { + difficulties.Clear(); + + if (BeatmapSet != null) + { difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty).Select(b => new DifficultySelectorButton(b) { State = DifficultySelectorState.NotSelected, @@ -53,14 +60,16 @@ namespace osu.Game.Overlays.BeatmapSet starRating.Text = beatmap.StarDifficulty.ToString("Star Difficulty 0.##"); starRating.FadeIn(100); }, - OnClicked = beatmap => - { - Beatmap.Value = beatmap; - }, + OnClicked = beatmap => { Beatmap.Value = beatmap; }, }); - - updateDifficultyButtons(); } + + starRating.FadeOut(100); + Beatmap.Value = BeatmapSet?.Beatmaps.FirstOrDefault(); + plays.Value = BeatmapSet?.OnlineInfo.PlayCount ?? 0; + favourites.Value = BeatmapSet?.OnlineInfo.FavouriteCount ?? 0; + + updateDifficultyButtons(); } public BeatmapPicker() @@ -140,6 +149,7 @@ namespace osu.Game.Overlays.BeatmapSet private void load(OsuColour colours) { starRating.Colour = colours.Yellow; + updateDisplay(); } protected override void LoadComplete() @@ -150,7 +160,10 @@ namespace osu.Game.Overlays.BeatmapSet Beatmap.TriggerChange(); } - private void showBeatmap(BeatmapInfo beatmap) => version.Text = beatmap.Version; + private void showBeatmap(BeatmapInfo beatmap) + { + version.Text = beatmap?.Version; + } private void updateDifficultyButtons() { diff --git a/osu.Game/Overlays/BeatmapSet/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs similarity index 97% rename from osu.Game/Overlays/BeatmapSet/DownloadButton.cs rename to osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 0c6414c718..c699ae2328 100644 --- a/osu.Game/Overlays/BeatmapSet/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using OpenTK; -namespace osu.Game.Overlays.BeatmapSet +namespace osu.Game.Overlays.BeatmapSet.Buttons { public class DownloadButton : HeaderButton { diff --git a/osu.Game/Overlays/BeatmapSet/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs similarity index 98% rename from osu.Game/Overlays/BeatmapSet/FavouriteButton.cs rename to osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 29bc00038c..3821c96369 100644 --- a/osu.Game/Overlays/BeatmapSet/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using OpenTK; -namespace osu.Game.Overlays.BeatmapSet +namespace osu.Game.Overlays.BeatmapSet.Buttons { public class FavouriteButton : HeaderButton { diff --git a/osu.Game/Overlays/BeatmapSet/HeaderButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs similarity index 94% rename from osu.Game/Overlays/BeatmapSet/HeaderButton.cs rename to osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs index e1c4f5cc67..b46b5d2a0e 100644 --- a/osu.Game/Overlays/BeatmapSet/HeaderButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs @@ -1,12 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; -using osu.Framework.Allocation; -namespace osu.Game.Overlays.BeatmapSet +namespace osu.Game.Overlays.BeatmapSet.Buttons { public class HeaderButton : TriangleButton { diff --git a/osu.Game/Overlays/BeatmapSet/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs similarity index 97% rename from osu.Game/Overlays/BeatmapSet/PreviewButton.cs rename to osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 6b5ffa57ad..08a99f1aea 100644 --- a/osu.Game/Overlays/BeatmapSet/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio.Track; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -11,12 +12,11 @@ using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Overlays.Direct; using OpenTK; using OpenTK.Graphics; -using osu.Game.Overlays.Direct; -using osu.Framework.Configuration; -namespace osu.Game.Overlays.BeatmapSet +namespace osu.Game.Overlays.BeatmapSet.Buttons { public class PreviewButton : OsuClickableContainer { @@ -85,6 +85,8 @@ namespace osu.Game.Overlays.BeatmapSet // prevent negative (potential infinite) width if a track without length was loaded progress.Width = preview.Length > 0 ? (float)(preview.CurrentTime / preview.Length) : 0f; } + else + progress.Width = 0; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 7f3b6d1584..5264caf936 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -1,11 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; +using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Screens.Select.Details; using OpenTK; using OpenTK.Graphics; @@ -20,6 +22,7 @@ namespace osu.Game.Overlays.BeatmapSet private readonly UserRatings ratings; private BeatmapSetInfo beatmapSet; + public BeatmapSetInfo BeatmapSet { get { return beatmapSet; } @@ -33,19 +36,24 @@ namespace osu.Game.Overlays.BeatmapSet } private BeatmapInfo beatmap; + public BeatmapInfo Beatmap { get { return beatmap; } set { if (value == beatmap) return; - beatmap = value; - basic.Beatmap = advanced.Beatmap = Beatmap; - ratings.Metrics = Beatmap.Metrics; + basic.Beatmap = advanced.Beatmap = beatmap = value; + updateDisplay(); } } + private void updateDisplay() + { + ratings.Metrics = Beatmap?.Metrics; + } + public Details() { Width = BeatmapSetOverlay.RIGHT_WIDTH; @@ -88,6 +96,12 @@ namespace osu.Game.Overlays.BeatmapSet }; } + [BackgroundDependencyLoader] + private void load() + { + updateDisplay(); + } + public void StopPreview() => preview.Playing.Value = false; private class DetailBox : Container diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 755039e7bc..9b25d61f58 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.BeatmapSet.Buttons; using OpenTK; using OpenTK.Graphics; @@ -18,7 +19,7 @@ namespace osu.Game.Overlays.BeatmapSet { public class Header : Container { - private const float transition_duration = 250; + private const float transition_duration = 200; private const float tabs_height = 50; private const float buttons_height = 45; private const float buttons_spacing = 5; @@ -34,12 +35,13 @@ namespace osu.Game.Overlays.BeatmapSet public Details Details; private BeatmapManager beatmaps; - private DelayedLoadWrapper cover; public readonly BeatmapPicker Picker; private BeatmapSetInfo beatmapSet; + private readonly FavouriteButton favouriteButton; + public BeatmapSetInfo BeatmapSet { get { return beatmapSet; } @@ -49,15 +51,26 @@ namespace osu.Game.Overlays.BeatmapSet beatmapSet = value; Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = BeatmapSet; - title.Text = BeatmapSet.Metadata.Title; - artist.Text = BeatmapSet.Metadata.Artist; - onlineStatusPill.Status = BeatmapSet.OnlineInfo.Status; - downloadButtonsContainer.FadeIn(); + updateDisplay(); + } + } + + private void updateDisplay() + { + title.Text = BeatmapSet?.Metadata.Title ?? string.Empty; + artist.Text = BeatmapSet?.Metadata.Artist ?? string.Empty; + onlineStatusPill.Status = BeatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None; + + cover?.FadeOut(400, Easing.Out); + if (BeatmapSet != null) + { + downloadButtonsContainer.FadeIn(transition_duration); + favouriteButton.FadeIn(transition_duration); + noVideoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 0 : 1, transition_duration); videoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 1 : 0, transition_duration); - cover?.FadeOut(400, Easing.Out); coverContainer.Add(cover = new DelayedLoadWrapper( new BeatmapSetCover(BeatmapSet) { @@ -71,6 +84,11 @@ namespace osu.Game.Overlays.BeatmapSet RelativeSizeAxes = Axes.Both, }); } + else + { + downloadButtonsContainer.FadeOut(transition_duration); + favouriteButton.FadeOut(transition_duration); + } } public Header() @@ -166,7 +184,7 @@ namespace osu.Game.Overlays.BeatmapSet Margin = new MarginPadding { Top = 10 }, Children = new Drawable[] { - new FavouriteButton(), + favouriteButton = new FavouriteButton(), downloadButtonsContainer = new Container { RelativeSizeAxes = Axes.Both, @@ -238,6 +256,8 @@ namespace osu.Game.Overlays.BeatmapSet this.beatmaps = beatmaps; beatmaps.ItemAdded += handleBeatmapAdd; + + updateDisplay(); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 9a402515ae..cd0b7386e8 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -34,11 +34,16 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmapSet) return; beatmapSet = value; - source.Text = BeatmapSet.Metadata.Source; - tags.Text = BeatmapSet.Metadata.Tags; + updateDisplay(); } } + private void updateDisplay() + { + source.Text = BeatmapSet?.Metadata.Source ?? string.Empty; + tags.Text = BeatmapSet?.Metadata.Tags ?? string.Empty; + } + public BeatmapInfo Beatmap { get { return successRate.Beatmap; } @@ -132,6 +137,8 @@ namespace osu.Game.Overlays.BeatmapSet successRateBackground.Colour = colours.GrayE; source.TextColour = description.TextColour = colours.Gray5; tags.TextColour = colours.BlueDark; + + updateDisplay(); } private class MetadataSection : FillFlowContainer diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index d5c5bd8ddd..185282bec9 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -2,15 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using OpenTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Online.API; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -22,49 +22,75 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly FillFlowContainer flow; private readonly DrawableTopScore topScore; private readonly LoadingAnimation loadingAnimation; - private readonly Box foreground; - private bool isLoading; - public bool IsLoading + private bool loading { - get { return isLoading; } - set - { - if (isLoading == value) return; - isLoading = value; - - foreground.FadeTo(isLoading ? 1 : 0, fade_duration); - loadingAnimation.FadeTo(isLoading ? 1 : 0, fade_duration); - } + set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); } private IEnumerable scores; + private BeatmapInfo beatmap; + public IEnumerable Scores { get { return scores; } set { + getScoresRequest?.Cancel(); scores = value; - var scoresAmount = scores.Count(); - if (scoresAmount == 0) - { - CleanAllScores(); - return; - } - topScore.Score = scores.FirstOrDefault(); - topScore.Show(); - - flow.Clear(); - - if (scoresAmount < 2) - return; - - for (int i = 1; i < scoresAmount; i++) - flow.Add(new DrawableScore(i, scores.ElementAt(i))); + updateDisplay(); } } + private GetScoresRequest getScoresRequest; + private APIAccess api; + + public BeatmapInfo Beatmap + { + get => beatmap; + set + { + beatmap = value; + + Scores = null; + + if (beatmap?.OnlineBeatmapID.HasValue != true) + return; + + loading = true; + + getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); + getScoresRequest.Success += r => Scores = r.Scores; + api.Queue(getScoresRequest); + } + } + + private void updateDisplay() + { + loading = false; + + var scoreCount = scores?.Count() ?? 0; + + if (scoreCount == 0) + { + topScore.Hide(); + flow.Clear(); + return; + } + + topScore.Score = scores.FirstOrDefault(); + topScore.Show(); + + flow.Clear(); + + if (scoreCount < 2) + return; + + for (int i = 1; i < scoreCount; i++) + flow.Add(new DrawableScore(i, scores.ElementAt(i))); + } + public ScoresContainer() { RelativeSizeAxes = Axes.X; @@ -93,23 +119,19 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }, } }, - foreground = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.7f), - Alpha = 0, - }, loadingAnimation = new LoadingAnimation { Alpha = 0, + Margin = new MarginPadding(20) }, }; } - public void CleanAllScores() + [BackgroundDependencyLoader] + private void load(APIAccess api) { - topScore.Hide(); - flow.Clear(); + this.api = api; + updateDisplay(); } } } diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index c64d3988a6..6572e520bd 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -29,18 +29,23 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmap) return; beatmap = value; - int passCount = beatmap.OnlineInfo.PassCount; - int playCount = beatmap.OnlineInfo.PlayCount; - - var rate = playCount != 0 ? (float)passCount / playCount : 0; - successPercent.Text = rate.ToString("P0"); - successRate.Length = rate; - percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic); - - graph.Metrics = Beatmap.Metrics; + updateDisplay(); } } + private void updateDisplay() + { + int passCount = beatmap?.OnlineInfo.PassCount ?? 0; + int playCount = beatmap?.OnlineInfo.PlayCount ?? 0; + + var rate = playCount != 0 ? (float)passCount / playCount : 0; + successPercent.Text = rate.ToString("P0"); + successRate.Length = rate; + percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic); + + graph.Metrics = beatmap?.Metrics; + } + public SuccessRate() { Children = new Drawable[] @@ -74,7 +79,6 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.TopRight, Origin = Anchor.TopCentre, - Text = @"0%", TextSize = 13, }, }, @@ -103,6 +107,8 @@ namespace osu.Game.Overlays.BeatmapSet successRateLabel.Colour = successPercent.Colour = graphLabel.Colour = colours.Gray5; successRate.AccentColour = colours.Green; successRate.BackgroundColour = colours.GrayD; + + updateDisplay(); } protected override void UpdateAfterChildren() diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index d2cf0a6ef1..74550e3a9b 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -27,19 +27,31 @@ namespace osu.Game.Overlays private readonly Header header; private readonly Info info; - private readonly ScoresContainer scores; - private APIAccess api; private RulesetStore rulesets; - private GetScoresRequest getScoresRequest; private readonly ScrollContainer scroll; + private BeatmapSetInfo beatmapSet; + + public BeatmapSetInfo BeatmapSet + { + get => beatmapSet; + set + { + if (value == beatmapSet) + return; + + header.BeatmapSet = info.BeatmapSet = beatmapSet = value; + } + } + // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; public BeatmapSetOverlay() { + ScoresContainer scores; Waves.FirstWaveColour = OsuColour.Gray(0.4f); Waves.SecondWaveColour = OsuColour.Gray(0.3f); Waves.ThirdWaveColour = OsuColour.Gray(0.2f); @@ -88,31 +100,10 @@ namespace osu.Game.Overlays header.Picker.Beatmap.ValueChanged += b => { info.Beatmap = b; - updateScores(b); + scores.Beatmap = b; }; } - private void updateScores(BeatmapInfo beatmap) - { - getScoresRequest?.Cancel(); - - if (!beatmap.OnlineBeatmapID.HasValue) - { - scores.CleanAllScores(); - return; - } - - scores.IsLoading = true; - - getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += r => - { - scores.Scores = r.Scores; - scores.IsLoading = false; - }; - api.Queue(getScoresRequest); - } - [BackgroundDependencyLoader] private void load(APIAccess api, RulesetStore rulesets) { @@ -139,7 +130,7 @@ namespace osu.Game.Overlays return true; } - public void ShowBeatmapSet(int beatmapSetId) + public void FetchAndShowBeatmapSet(int beatmapSetId) { // todo: display the overlay while we are loading here. we need to support setting BeatmapSet to null for this to work. var req = new GetBeatmapSetRequest(beatmapSetId); diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 44e24d8157..4913b11ae1 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -78,12 +78,7 @@ namespace osu.Game.Overlays.Direct loadingAnimation = new LoadingAnimation(), }); - Playing.ValueChanged += playing => - { - icon.Icon = playing ? FontAwesome.fa_pause : FontAwesome.fa_play; - icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); - updatePreviewTrack(playing); - }; + Playing.ValueChanged += updatePreviewTrack; } [BackgroundDependencyLoader] @@ -125,6 +120,15 @@ namespace osu.Game.Overlays.Direct private void updatePreviewTrack(bool playing) { + if (playing && BeatmapSet == null) + { + Playing.Value = false; + return; + } + + icon.Icon = playing ? FontAwesome.fa_pause : FontAwesome.fa_play; + icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); + if (playing) { if (Preview == null) diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index da08c08179..97079c77f3 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Profile.Sections { Action = () => { - if (beatmap.OnlineBeatmapSetID.HasValue) beatmapSetOverlay?.ShowBeatmapSet(beatmap.OnlineBeatmapSetID.Value); + if (beatmap.OnlineBeatmapSetID.HasValue) beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmap.OnlineBeatmapSetID.Value); }; Child = new FillFlowContainer diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index ad7588edde..d554a22735 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Select.Carousel restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); dialogOverlay = overlay; if (beatmapOverlay != null) - viewDetails = beatmapOverlay.ShowBeatmapSet; + viewDetails = beatmapOverlay.FetchAndShowBeatmapSet; Children = new Drawable[] { diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index cad7ed7d81..852e4f190f 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -40,10 +40,10 @@ namespace osu.Game.Screens.Select.Details firstValue.Value = Beatmap?.BaseDifficulty?.CircleSize ?? 0; } - hpDrain.Value = beatmap.BaseDifficulty?.DrainRate ?? 0; - accuracy.Value = beatmap.BaseDifficulty?.OverallDifficulty ?? 0; - approachRate.Value = beatmap.BaseDifficulty?.ApproachRate ?? 0; - starDifficulty.Value = (float)beatmap.StarDifficulty; + hpDrain.Value = Beatmap?.BaseDifficulty?.DrainRate ?? 0; + accuracy.Value = Beatmap?.BaseDifficulty?.OverallDifficulty ?? 0; + approachRate.Value = Beatmap?.BaseDifficulty?.ApproachRate ?? 0; + starDifficulty.Value = (float)(Beatmap?.StarDifficulty ?? 0); } } diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index a33cee21ed..bf4eb07108 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -25,10 +25,10 @@ namespace osu.Game.Screens.Select.Details if (value == metrics) return; metrics = value; - var retries = Metrics.Retries; - var fails = Metrics.Fails; + var retries = Metrics?.Retries ?? new int[0]; + var fails = Metrics?.Fails ?? new int[0]; - float maxValue = fails.Zip(retries, (fail, retry) => fail + retry).Max(); + float maxValue = fails.Any() ? fails.Zip(retries, (fail, retry) => fail + retry).Max() : 0; failGraph.MaxValue = maxValue; retryGraph.MaxValue = maxValue; diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index bf50217048..787b22f965 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -21,6 +21,7 @@ namespace osu.Game.Screens.Select.Details private readonly BarGraph graph; private BeatmapMetrics metrics; + public BeatmapMetrics Metrics { get { return metrics; } @@ -31,15 +32,25 @@ namespace osu.Game.Screens.Select.Details const int rating_range = 10; - var ratings = Metrics.Ratings.Skip(1).Take(rating_range); // adjust for API returning weird empty data at 0. + if (metrics == null) + { + negativeRatings.Text = "0"; + positiveRatings.Text = "0"; + ratingsBar.Length = 0; + graph.Values = new float[rating_range]; + } + else + { + var ratings = Metrics.Ratings.Skip(1).Take(rating_range); // adjust for API returning weird empty data at 0. - var negativeCount = ratings.Take(rating_range / 2).Sum(); - var totalCount = ratings.Sum(); + var negativeCount = ratings.Take(rating_range / 2).Sum(); + var totalCount = ratings.Sum(); - negativeRatings.Text = negativeCount.ToString(); - positiveRatings.Text = (totalCount - negativeCount).ToString(); - ratingsBar.Length = totalCount == 0 ? 0 : (float)negativeCount / totalCount; - graph.Values = ratings.Take(rating_range).Select(r => (float)r); + negativeRatings.Text = negativeCount.ToString(); + positiveRatings.Text = (totalCount - negativeCount).ToString(); + ratingsBar.Length = totalCount == 0 ? 0 : (float)negativeCount / totalCount; + graph.Values = ratings.Take(rating_range).Select(r => (float)r); + } } } diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index 31455801da..6c0b841abf 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -15,6 +15,11 @@ namespace osu.Game.Users private User user; + /// + /// Whether to show a default guest representation on null user (as opposed to nothing). + /// + public bool ShowGuestOnNull = true; + public User User { get { return user; } @@ -40,13 +45,16 @@ namespace osu.Game.Users { displayedAvatar?.FadeOut(300); displayedAvatar?.Expire(); - Add(displayedAvatar = new DelayedLoadWrapper( - new Avatar(user) - { - RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), - }) - ); + if (user != null || ShowGuestOnNull) + { + Add(displayedAvatar = new DelayedLoadWrapper( + new Avatar(user) + { + RelativeSizeAxes = Axes.Both, + OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), + }) + ); + } } } } From 0356e5e6bf9a31ed35a3741d64d5649cf39093e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Apr 2018 21:00:22 +0900 Subject: [PATCH 2/3] Remove unused property --- osu.Game/Overlays/BeatmapSetOverlay.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 74550e3a9b..366c34eae3 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -32,20 +32,6 @@ namespace osu.Game.Overlays private readonly ScrollContainer scroll; - private BeatmapSetInfo beatmapSet; - - public BeatmapSetInfo BeatmapSet - { - get => beatmapSet; - set - { - if (value == beatmapSet) - return; - - header.BeatmapSet = info.BeatmapSet = beatmapSet = value; - } - } - // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; From 77af8ce556cde3b36c32fe7771404cb5daa87f30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Apr 2018 21:11:16 +0900 Subject: [PATCH 3/3] Add back online load test for BeatmapScoresContainer --- osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs index 85f3364039..5be7386238 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs @@ -14,6 +14,8 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Users; using System.Collections.Generic; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Osu; namespace osu.Game.Tests.Visual { @@ -50,6 +52,8 @@ namespace osu.Game.Tests.Visual AddStep("remove scores", () => scoresContainer.Scores = null); AddStep("resize to big", () => container.ResizeWidthTo(1, 300)); AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300)); + AddStep("online scores", () => scoresContainer.Beatmap = new BeatmapInfo { OnlineBeatmapSetID = 1, OnlineBeatmapID = 75, Ruleset = new OsuRuleset().RulesetInfo }); + scores = new[] {