1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-16 01:17:27 +08:00

Make BeatmapSetOverlay accept nulls everywhere

This commit is contained in:
Dean Herbert 2018-04-18 15:58:45 +09:00
parent 7e5d5a197b
commit 1728dd6502
24 changed files with 312 additions and 191 deletions

View File

@ -47,9 +47,7 @@ namespace osu.Game.Tests.Visual
AddStep("scores pack 1", () => scoresContainer.Scores = scores); AddStep("scores pack 1", () => scoresContainer.Scores = scores);
AddStep("scores pack 2", () => scoresContainer.Scores = anotherScores); AddStep("scores pack 2", () => scoresContainer.Scores = anotherScores);
AddStep("only top score", () => scoresContainer.Scores = new[] { topScore }); AddStep("only top score", () => scoresContainer.Scores = new[] { topScore });
AddStep("remove scores", scoresContainer.CleanAllScores); AddStep("remove scores", () => scoresContainer.Scores = null);
AddStep("turn on loading", () => scoresContainer.IsLoading = true);
AddStep("turn off loading", () => scoresContainer.IsLoading = false);
AddStep("resize to big", () => container.ResizeWidthTo(1, 300)); AddStep("resize to big", () => container.ResizeWidthTo(1, 300));
AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300)); AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300));

View File

@ -8,6 +8,9 @@ using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Overlays; 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.Rulesets;
using osu.Game.Users; using osu.Game.Users;
@ -18,6 +21,26 @@ namespace osu.Game.Tests.Visual
{ {
private readonly BeatmapSetOverlay overlay; private readonly BeatmapSetOverlay overlay;
public override IReadOnlyList<Type> 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() public TestCaseBeatmapSetOverlay()
{ {
Add(overlay = new BeatmapSetOverlay()); Add(overlay = new BeatmapSetOverlay());
@ -29,6 +52,10 @@ namespace osu.Game.Tests.Visual
var mania = rulesets.GetRuleset(3); var mania = rulesets.GetRuleset(3);
var taiko = rulesets.GetRuleset(1); var taiko = rulesets.GetRuleset(1);
AddStep(@"show loading", () => overlay.ShowBeatmapSet(null));
AddStep(@"show online", () => overlay.FetchAndShowBeatmapSet(55));
AddStep(@"show first", () => AddStep(@"show first", () =>
{ {
overlay.ShowBeatmapSet(new BeatmapSetInfo overlay.ShowBeatmapSet(new BeatmapSetInfo

View File

@ -158,7 +158,7 @@ namespace osu.Game
/// Show a beatmap set as an overlay. /// Show a beatmap set as an overlay.
/// </summary> /// </summary>
/// <param name="setId">The set to display.</param> /// <param name="setId">The set to display.</param>
public void ShowBeatmapSet(int setId) => beatmapSetOverlay.ShowBeatmapSet(setId); public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId);
/// <summary> /// <summary>
/// Show a user's profile as an overlay. /// Show a user's profile as an overlay.
@ -170,7 +170,7 @@ namespace osu.Game
/// Show a beatmap's set as an overlay, displaying the given beatmap. /// Show a beatmap's set as an overlay, displaying the given beatmap.
/// </summary> /// </summary>
/// <param name="beatmapId">The beatmap to show.</param> /// <param name="beatmapId">The beatmap to show.</param>
public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.ShowBeatmap(beatmapId); public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId);
protected void LoadScore(Score s) protected void LoadScore(Score s)
{ {

View File

@ -23,9 +23,8 @@ namespace osu.Game.Overlays.BeatmapSet
private readonly ClickableArea clickableArea; private readonly ClickableArea clickableArea;
private readonly FillFlowContainer fields; private readonly FillFlowContainer fields;
private UserProfileOverlay profile;
private BeatmapSetInfo beatmapSet; private BeatmapSetInfo beatmapSet;
public BeatmapSetInfo BeatmapSet public BeatmapSetInfo BeatmapSet
{ {
get { return beatmapSet; } get { return beatmapSet; }
@ -34,28 +33,36 @@ namespace osu.Game.Overlays.BeatmapSet
if (value == beatmapSet) return; if (value == beatmapSet) return;
beatmapSet = value; beatmapSet = value;
var i = BeatmapSet.OnlineInfo; updateDisplay();
}
}
avatar.User = BeatmapSet.Metadata.Author; private void updateDisplay()
clickableArea.Action = () => profile?.ShowUser(avatar.User); {
avatar.User = BeatmapSet?.Metadata.Author;
fields.Children = new Drawable[] fields.Clear();
{ if (BeatmapSet == null)
new Field("made by", BeatmapSet.Metadata.Author.Username, @"Exo2.0-RegularItalic"), return;
new Field("submitted on", i.Submitted.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold")
{
Margin = new MarginPadding { Top = 5 },
},
};
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")); Margin = new MarginPadding { Top = 5 },
} },
else if (i.LastUpdated.HasValue) };
{
fields.Add(new Field("last updated on ", i.LastUpdated.Value.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold")); 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, Masking = true,
Child = avatar = new UpdateableAvatar Child = avatar = new UpdateableAvatar
{ {
ShowGuestOnNull = false,
Size = new Vector2(height), Size = new Vector2(height),
}, },
EdgeEffect = new EdgeEffectParameters EdgeEffect = new EdgeEffectParameters
@ -95,8 +103,12 @@ namespace osu.Game.Overlays.BeatmapSet
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(UserProfileOverlay profile) private void load(UserProfileOverlay profile)
{ {
this.profile = profile; clickableArea.Action = () =>
clickableArea.Action = () => profile?.ShowUser(avatar.User); {
if (avatar.User != null) profile?.ShowUser(avatar.User);
};
updateDisplay();
} }
private class Field : FillFlowContainer private class Field : FillFlowContainer

View File

@ -18,6 +18,7 @@ namespace osu.Game.Overlays.BeatmapSet
private readonly Statistic length, bpm, circleCount, sliderCount; private readonly Statistic length, bpm, circleCount, sliderCount;
private BeatmapSetInfo beatmapSet; private BeatmapSetInfo beatmapSet;
public BeatmapSetInfo BeatmapSet public BeatmapSetInfo BeatmapSet
{ {
get { return beatmapSet; } get { return beatmapSet; }
@ -26,11 +27,12 @@ namespace osu.Game.Overlays.BeatmapSet
if (value == beatmapSet) return; if (value == beatmapSet) return;
beatmapSet = value; beatmapSet = value;
bpm.Value = BeatmapSet.OnlineInfo.BPM.ToString(@"0.##"); updateDisplay();
} }
} }
private BeatmapInfo beatmap; private BeatmapInfo beatmap;
public BeatmapInfo Beatmap public BeatmapInfo Beatmap
{ {
get { return beatmap; } get { return beatmap; }
@ -39,6 +41,22 @@ namespace osu.Game.Overlays.BeatmapSet
if (value == beatmap) return; if (value == beatmap) return;
beatmap = value; 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"); length.Value = TimeSpan.FromSeconds(beatmap.OnlineInfo.Length).ToString(@"m\:ss");
circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString(); circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString();
sliderCount.Value = beatmap.OnlineInfo.SliderCount.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 class Statistic : Container, IHasTooltip
{ {
private readonly string name; private readonly string name;
private readonly OsuSpriteText value; private readonly OsuSpriteText value;
public string TooltipText => name; public string TooltipText => name;
public string Value public string Value
{ {
get { return value.Text; } get { return value.Text; }

View File

@ -41,9 +41,16 @@ namespace osu.Game.Overlays.BeatmapSet
if (value == beatmapSet) return; if (value == beatmapSet) return;
beatmapSet = value; beatmapSet = value;
Beatmap.Value = BeatmapSet.Beatmaps.First(); updateDisplay();
plays.Value = BeatmapSet.OnlineInfo.PlayCount; }
favourites.Value = BeatmapSet.OnlineInfo.FavouriteCount; }
private void updateDisplay()
{
difficulties.Clear();
if (BeatmapSet != null)
{
difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty).Select(b => new DifficultySelectorButton(b) difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty).Select(b => new DifficultySelectorButton(b)
{ {
State = DifficultySelectorState.NotSelected, State = DifficultySelectorState.NotSelected,
@ -53,14 +60,16 @@ namespace osu.Game.Overlays.BeatmapSet
starRating.Text = beatmap.StarDifficulty.ToString("Star Difficulty 0.##"); starRating.Text = beatmap.StarDifficulty.ToString("Star Difficulty 0.##");
starRating.FadeIn(100); starRating.FadeIn(100);
}, },
OnClicked = beatmap => OnClicked = beatmap => { Beatmap.Value = 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() public BeatmapPicker()
@ -140,6 +149,7 @@ namespace osu.Game.Overlays.BeatmapSet
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
starRating.Colour = colours.Yellow; starRating.Colour = colours.Yellow;
updateDisplay();
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -150,7 +160,10 @@ namespace osu.Game.Overlays.BeatmapSet
Beatmap.TriggerChange(); Beatmap.TriggerChange();
} }
private void showBeatmap(BeatmapInfo beatmap) => version.Text = beatmap?.Version; private void showBeatmap(BeatmapInfo beatmap)
{
version.Text = beatmap?.Version;
}
private void updateDifficultyButtons() private void updateDifficultyButtons()
{ {

View File

@ -7,7 +7,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using OpenTK; using OpenTK;
namespace osu.Game.Overlays.BeatmapSet namespace osu.Game.Overlays.BeatmapSet.Buttons
{ {
public class DownloadButton : HeaderButton public class DownloadButton : HeaderButton
{ {

View File

@ -10,7 +10,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Backgrounds;
using OpenTK; using OpenTK;
namespace osu.Game.Overlays.BeatmapSet namespace osu.Game.Overlays.BeatmapSet.Buttons
{ {
public class FavouriteButton : HeaderButton public class FavouriteButton : HeaderButton
{ {

View File

@ -1,12 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Framework.Allocation;
namespace osu.Game.Overlays.BeatmapSet namespace osu.Game.Overlays.BeatmapSet.Buttons
{ {
public class HeaderButton : TriangleButton public class HeaderButton : TriangleButton
{ {

View File

@ -3,6 +3,7 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Configuration;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -11,12 +12,11 @@ using osu.Framework.Input;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Overlays.Direct;
using OpenTK; using OpenTK;
using OpenTK.Graphics; 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 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 // prevent negative (potential infinite) width if a track without length was loaded
progress.Width = preview.Length > 0 ? (float)(preview.CurrentTime / preview.Length) : 0f; progress.Width = preview.Length > 0 ? (float)(preview.CurrentTime / preview.Length) : 0f;
} }
else
progress.Width = 0;
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -1,11 +1,13 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // 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.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Overlays.BeatmapSet.Buttons;
using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Details;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -20,6 +22,7 @@ namespace osu.Game.Overlays.BeatmapSet
private readonly UserRatings ratings; private readonly UserRatings ratings;
private BeatmapSetInfo beatmapSet; private BeatmapSetInfo beatmapSet;
public BeatmapSetInfo BeatmapSet public BeatmapSetInfo BeatmapSet
{ {
get { return beatmapSet; } get { return beatmapSet; }
@ -33,19 +36,24 @@ namespace osu.Game.Overlays.BeatmapSet
} }
private BeatmapInfo beatmap; private BeatmapInfo beatmap;
public BeatmapInfo Beatmap public BeatmapInfo Beatmap
{ {
get { return beatmap; } get { return beatmap; }
set set
{ {
if (value == beatmap) return; if (value == beatmap) return;
beatmap = value;
basic.Beatmap = advanced.Beatmap = Beatmap; basic.Beatmap = advanced.Beatmap = beatmap = value;
ratings.Metrics = Beatmap.Metrics; updateDisplay();
} }
} }
private void updateDisplay()
{
ratings.Metrics = Beatmap?.Metrics;
}
public Details() public Details()
{ {
Width = BeatmapSetOverlay.RIGHT_WIDTH; 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; public void StopPreview() => preview.Playing.Value = false;
private class DetailBox : Container private class DetailBox : Container

View File

@ -11,6 +11,7 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables; using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Overlays.BeatmapSet.Buttons;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -18,7 +19,7 @@ namespace osu.Game.Overlays.BeatmapSet
{ {
public class Header : Container 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 tabs_height = 50;
private const float buttons_height = 45; private const float buttons_height = 45;
private const float buttons_spacing = 5; private const float buttons_spacing = 5;
@ -34,12 +35,13 @@ namespace osu.Game.Overlays.BeatmapSet
public Details Details; public Details Details;
private BeatmapManager beatmaps; private BeatmapManager beatmaps;
private DelayedLoadWrapper cover; private DelayedLoadWrapper cover;
public readonly BeatmapPicker Picker; public readonly BeatmapPicker Picker;
private BeatmapSetInfo beatmapSet; private BeatmapSetInfo beatmapSet;
private readonly FavouriteButton favouriteButton;
public BeatmapSetInfo BeatmapSet public BeatmapSetInfo BeatmapSet
{ {
get { return beatmapSet; } get { return beatmapSet; }
@ -48,19 +50,27 @@ namespace osu.Game.Overlays.BeatmapSet
if (value == beatmapSet) return; if (value == beatmapSet) return;
beatmapSet = value; beatmapSet = value;
if (beatmapSet == null)
return;
Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = BeatmapSet; 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); noVideoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 0 : 1, transition_duration);
videoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 1 : 0, transition_duration); videoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 1 : 0, transition_duration);
cover?.FadeOut(400, Easing.Out);
coverContainer.Add(cover = new DelayedLoadWrapper( coverContainer.Add(cover = new DelayedLoadWrapper(
new BeatmapSetCover(BeatmapSet) new BeatmapSetCover(BeatmapSet)
{ {
@ -74,6 +84,11 @@ namespace osu.Game.Overlays.BeatmapSet
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}); });
} }
else
{
downloadButtonsContainer.FadeOut(transition_duration);
favouriteButton.FadeOut(transition_duration);
}
} }
public Header() public Header()
@ -169,7 +184,7 @@ namespace osu.Game.Overlays.BeatmapSet
Margin = new MarginPadding { Top = 10 }, Margin = new MarginPadding { Top = 10 },
Children = new Drawable[] Children = new Drawable[]
{ {
new FavouriteButton(), favouriteButton = new FavouriteButton(),
downloadButtonsContainer = new Container downloadButtonsContainer = new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -241,6 +256,8 @@ namespace osu.Game.Overlays.BeatmapSet
this.beatmaps = beatmaps; this.beatmaps = beatmaps;
beatmaps.ItemAdded += handleBeatmapAdd; beatmaps.ItemAdded += handleBeatmapAdd;
updateDisplay();
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -34,14 +34,16 @@ namespace osu.Game.Overlays.BeatmapSet
if (value == beatmapSet) return; if (value == beatmapSet) return;
beatmapSet = value; beatmapSet = value;
if (beatmapSet == null) updateDisplay();
return;
source.Text = BeatmapSet.Metadata.Source;
tags.Text = BeatmapSet.Metadata.Tags;
} }
} }
private void updateDisplay()
{
source.Text = BeatmapSet?.Metadata.Source ?? string.Empty;
tags.Text = BeatmapSet?.Metadata.Tags ?? string.Empty;
}
public BeatmapInfo Beatmap public BeatmapInfo Beatmap
{ {
get { return successRate.Beatmap; } get { return successRate.Beatmap; }
@ -135,6 +137,8 @@ namespace osu.Game.Overlays.BeatmapSet
successRateBackground.Colour = colours.GrayE; successRateBackground.Colour = colours.GrayE;
source.TextColour = description.TextColour = colours.Gray5; source.TextColour = description.TextColour = colours.Gray5;
tags.TextColour = colours.BlueDark; tags.TextColour = colours.BlueDark;
updateDisplay();
} }
private class MetadataSection : FillFlowContainer private class MetadataSection : FillFlowContainer

View File

@ -2,15 +2,15 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK; using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
namespace osu.Game.Overlays.BeatmapSet.Scores namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
@ -22,49 +22,75 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
private readonly FillFlowContainer flow; private readonly FillFlowContainer flow;
private readonly DrawableTopScore topScore; private readonly DrawableTopScore topScore;
private readonly LoadingAnimation loadingAnimation; private readonly LoadingAnimation loadingAnimation;
private readonly Box foreground;
private bool isLoading; private bool loading
public bool IsLoading
{ {
get { return isLoading; } set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration);
set
{
if (isLoading == value) return;
isLoading = value;
foreground.FadeTo(isLoading ? 1 : 0, fade_duration);
loadingAnimation.FadeTo(isLoading ? 1 : 0, fade_duration);
}
} }
private IEnumerable<OnlineScore> scores; private IEnumerable<OnlineScore> scores;
private BeatmapInfo beatmap;
public IEnumerable<OnlineScore> Scores public IEnumerable<OnlineScore> Scores
{ {
get { return scores; } get { return scores; }
set set
{ {
getScoresRequest?.Cancel();
scores = value; scores = value;
var scoresAmount = scores.Count();
if (scoresAmount == 0)
{
CleanAllScores();
return;
}
topScore.Score = scores.FirstOrDefault(); updateDisplay();
topScore.Show();
flow.Clear();
if (scoresAmount < 2)
return;
for (int i = 1; i < scoresAmount; i++)
flow.Add(new DrawableScore(i, scores.ElementAt(i)));
} }
} }
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() public ScoresContainer()
{ {
RelativeSizeAxes = Axes.X; 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 loadingAnimation = new LoadingAnimation
{ {
Alpha = 0, Alpha = 0,
Margin = new MarginPadding(20)
}, },
}; };
} }
public void CleanAllScores() [BackgroundDependencyLoader]
private void load(APIAccess api)
{ {
topScore.Hide(); this.api = api;
flow.Clear(); updateDisplay();
} }
} }
} }

View File

@ -29,18 +29,23 @@ namespace osu.Game.Overlays.BeatmapSet
if (value == beatmap) return; if (value == beatmap) return;
beatmap = value; beatmap = value;
int passCount = beatmap.OnlineInfo.PassCount; updateDisplay();
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;
} }
} }
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() public SuccessRate()
{ {
Children = new Drawable[] Children = new Drawable[]
@ -74,7 +79,6 @@ namespace osu.Game.Overlays.BeatmapSet
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Text = @"0%",
TextSize = 13, TextSize = 13,
}, },
}, },
@ -103,6 +107,8 @@ namespace osu.Game.Overlays.BeatmapSet
successRateLabel.Colour = successPercent.Colour = graphLabel.Colour = colours.Gray5; successRateLabel.Colour = successPercent.Colour = graphLabel.Colour = colours.Gray5;
successRate.AccentColour = colours.Green; successRate.AccentColour = colours.Green;
successRate.BackgroundColour = colours.GrayD; successRate.BackgroundColour = colours.GrayD;
updateDisplay();
} }
protected override void UpdateAfterChildren() protected override void UpdateAfterChildren()

View File

@ -18,7 +18,6 @@ using osu.Game.Overlays.BeatmapSet;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Overlays.BeatmapSet.Scores;
using System.Linq; using System.Linq;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays namespace osu.Game.Overlays
{ {
@ -31,12 +30,9 @@ namespace osu.Game.Overlays
private readonly Header header; private readonly Header header;
private readonly Info info; private readonly Info info;
private readonly ScoresContainer scores;
private readonly LoadingAnimation loading;
private APIAccess api; private APIAccess api;
private RulesetStore rulesets; private RulesetStore rulesets;
private GetScoresRequest getScoresRequest;
private readonly ScrollContainer scroll; private readonly ScrollContainer scroll;
@ -50,18 +46,7 @@ namespace osu.Game.Overlays
if (value == beatmapSet) if (value == beatmapSet)
return; return;
beatmapSet = value; header.BeatmapSet = info.BeatmapSet = beatmapSet = value;
if (beatmapSet == null)
{
scroll.FadeOut(fade_duration);
loading.Show();
return;
}
header.BeatmapSet = info.BeatmapSet = beatmapSet;
loading.Hide();
scroll.FadeIn(fade_duration);
} }
} }
@ -70,6 +55,7 @@ namespace osu.Game.Overlays
public BeatmapSetOverlay() public BeatmapSetOverlay()
{ {
ScoresContainer scores;
Waves.FirstWaveColour = OsuColour.Gray(0.4f); Waves.FirstWaveColour = OsuColour.Gray(0.4f);
Waves.SecondWaveColour = OsuColour.Gray(0.3f); Waves.SecondWaveColour = OsuColour.Gray(0.3f);
Waves.ThirdWaveColour = OsuColour.Gray(0.2f); Waves.ThirdWaveColour = OsuColour.Gray(0.2f);
@ -96,15 +82,10 @@ namespace osu.Game.Overlays
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(0.2f) Colour = OsuColour.Gray(0.2f)
}, },
loading = new LoadingAnimation
{
State = Visibility.Visible,
},
scroll = new ScrollContainer scroll = new ScrollContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
ScrollbarVisible = false, ScrollbarVisible = false,
Alpha = 0,
Child = new ReverseChildIDFillFlowContainer<Drawable> Child = new ReverseChildIDFillFlowContainer<Drawable>
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
@ -123,33 +104,10 @@ namespace osu.Game.Overlays
header.Picker.Beatmap.ValueChanged += b => header.Picker.Beatmap.ValueChanged += b =>
{ {
info.Beatmap = b; info.Beatmap = b;
scores.Beatmap = b;
if (b != null)
updateScores(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] [BackgroundDependencyLoader]
private void load(APIAccess api, RulesetStore rulesets) private void load(APIAccess api, RulesetStore rulesets)
{ {
@ -178,7 +136,7 @@ namespace osu.Game.Overlays
return true; return true;
} }
public void ShowBeatmap(int beatmapId) public void FetchAndShowBeatmap(int beatmapId)
{ {
BeatmapSet = null; BeatmapSet = null;
var req = new GetBeatmapSetRequest(beatmapId, BeatmapSetLookupType.BeatmapId); var req = new GetBeatmapSetRequest(beatmapId, BeatmapSetLookupType.BeatmapId);
@ -191,7 +149,7 @@ namespace osu.Game.Overlays
Show(); Show();
} }
public void ShowBeatmapSet(int beatmapSetId) public void FetchAndShowBeatmapSet(int beatmapSetId)
{ {
BeatmapSet = null; BeatmapSet = null;
var req = new GetBeatmapSetRequest(beatmapSetId); var req = new GetBeatmapSetRequest(beatmapSetId);

View File

@ -78,12 +78,7 @@ namespace osu.Game.Overlays.Direct
loadingAnimation = new LoadingAnimation(), loadingAnimation = new LoadingAnimation(),
}); });
Playing.ValueChanged += playing => Playing.ValueChanged += updatePreviewTrack;
{
icon.Icon = playing ? FontAwesome.fa_pause : FontAwesome.fa_play;
icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint);
updatePreviewTrack(playing);
};
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -125,6 +120,15 @@ namespace osu.Game.Overlays.Direct
private void updatePreviewTrack(bool playing) 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 (playing)
{ {
if (Preview == null) if (Preview == null)

View File

@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Profile.Sections
{ {
Action = () => Action = () =>
{ {
if (beatmap.OnlineBeatmapSetID.HasValue) beatmapSetOverlay?.ShowBeatmapSet(beatmap.OnlineBeatmapSetID.Value); if (beatmap.OnlineBeatmapSetID.HasValue) beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmap.OnlineBeatmapSetID.Value);
}; };
Child = new FillFlowContainer Child = new FillFlowContainer

View File

@ -178,7 +178,7 @@ namespace osu.Game.Screens.Select.Carousel
new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap)), new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap)),
new OsuMenuItem("Details", MenuItemType.Standard, () => new OsuMenuItem("Details", MenuItemType.Standard, () =>
{ {
if (beatmap.OnlineBeatmapID.HasValue) beatmapOverlay?.ShowBeatmap(beatmap.OnlineBeatmapID.Value); if (beatmap.OnlineBeatmapID.HasValue) beatmapOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value);
}), }),
}; };
} }

View File

@ -46,7 +46,7 @@ namespace osu.Game.Screens.Select.Carousel
restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore);
dialogOverlay = overlay; dialogOverlay = overlay;
if (beatmapOverlay != null) if (beatmapOverlay != null)
viewDetails = beatmapOverlay.ShowBeatmapSet; viewDetails = beatmapOverlay.FetchAndShowBeatmapSet;
Children = new Drawable[] Children = new Drawable[]
{ {

View File

@ -40,10 +40,10 @@ namespace osu.Game.Screens.Select.Details
firstValue.Value = Beatmap?.BaseDifficulty?.CircleSize ?? 0; firstValue.Value = Beatmap?.BaseDifficulty?.CircleSize ?? 0;
} }
hpDrain.Value = beatmap.BaseDifficulty?.DrainRate ?? 0; hpDrain.Value = Beatmap?.BaseDifficulty?.DrainRate ?? 0;
accuracy.Value = beatmap.BaseDifficulty?.OverallDifficulty ?? 0; accuracy.Value = Beatmap?.BaseDifficulty?.OverallDifficulty ?? 0;
approachRate.Value = beatmap.BaseDifficulty?.ApproachRate ?? 0; approachRate.Value = Beatmap?.BaseDifficulty?.ApproachRate ?? 0;
starDifficulty.Value = (float)beatmap.StarDifficulty; starDifficulty.Value = (float)(Beatmap?.StarDifficulty ?? 0);
} }
} }

View File

@ -25,10 +25,10 @@ namespace osu.Game.Screens.Select.Details
if (value == metrics) return; if (value == metrics) return;
metrics = value; metrics = value;
var retries = Metrics.Retries; var retries = Metrics?.Retries ?? new int[0];
var fails = Metrics.Fails; 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; failGraph.MaxValue = maxValue;
retryGraph.MaxValue = maxValue; retryGraph.MaxValue = maxValue;

View File

@ -21,6 +21,7 @@ namespace osu.Game.Screens.Select.Details
private readonly BarGraph graph; private readonly BarGraph graph;
private BeatmapMetrics metrics; private BeatmapMetrics metrics;
public BeatmapMetrics Metrics public BeatmapMetrics Metrics
{ {
get { return metrics; } get { return metrics; }
@ -31,15 +32,25 @@ namespace osu.Game.Screens.Select.Details
const int rating_range = 10; 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 negativeCount = ratings.Take(rating_range / 2).Sum();
var totalCount = ratings.Sum(); var totalCount = ratings.Sum();
negativeRatings.Text = negativeCount.ToString(); negativeRatings.Text = negativeCount.ToString();
positiveRatings.Text = (totalCount - negativeCount).ToString(); positiveRatings.Text = (totalCount - negativeCount).ToString();
ratingsBar.Length = totalCount == 0 ? 0 : (float)negativeCount / totalCount; ratingsBar.Length = totalCount == 0 ? 0 : (float)negativeCount / totalCount;
graph.Values = ratings.Take(rating_range).Select(r => (float)r); graph.Values = ratings.Take(rating_range).Select(r => (float)r);
}
} }
} }

View File

@ -15,6 +15,11 @@ namespace osu.Game.Users
private User user; private User user;
/// <summary>
/// Whether to show a default guest representation on null user (as opposed to nothing).
/// </summary>
public bool ShowGuestOnNull = true;
public User User public User User
{ {
get { return user; } get { return user; }
@ -40,13 +45,16 @@ namespace osu.Game.Users
{ {
displayedAvatar?.FadeOut(300); displayedAvatar?.FadeOut(300);
displayedAvatar?.Expire(); displayedAvatar?.Expire();
Add(displayedAvatar = new DelayedLoadWrapper( if (user != null || ShowGuestOnNull)
new Avatar(user) {
{ Add(displayedAvatar = new DelayedLoadWrapper(
RelativeSizeAxes = Axes.Both, new Avatar(user)
OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), {
}) RelativeSizeAxes = Axes.Both,
); OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint),
})
);
}
} }
} }
} }