mirror of
https://github.com/ppy/osu.git
synced 2024-11-14 17:17:24 +08:00
Rewrite BeatmapDetails to be more modular for future code sharing.
This commit is contained in:
parent
c2b16dae10
commit
5e685ff5b1
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 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 System;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -10,6 +11,8 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
public class BeatmapDetailArea : Container
|
public class BeatmapDetailArea : Container
|
||||||
{
|
{
|
||||||
|
private const float details_padding = 10;
|
||||||
|
|
||||||
private readonly Container content;
|
private readonly Container content;
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
@ -66,9 +69,8 @@ namespace osu.Game.Screens.Select
|
|||||||
Details = new BeatmapDetails
|
Details = new BeatmapDetails
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Masking = true,
|
|
||||||
Height = 352,
|
|
||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
|
Margin = new MarginPadding { Top = details_padding },
|
||||||
},
|
},
|
||||||
Leaderboard = new Leaderboard
|
Leaderboard = new Leaderboard
|
||||||
{
|
{
|
||||||
@ -76,5 +78,12 @@ namespace osu.Game.Screens.Select
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void UpdateAfterChildren()
|
||||||
|
{
|
||||||
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
|
Details.Height = Math.Min(DrawHeight - (details_padding * 3) - BeatmapDetailAreaTabControl.HEIGHT, 450);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,71 +9,188 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Game.Screens.Select.Details;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Select
|
namespace osu.Game.Screens.Select
|
||||||
{
|
{
|
||||||
public class BeatmapDetails : Container
|
public class BeatmapDetails : Container
|
||||||
{
|
{
|
||||||
private readonly MetadataSegment description;
|
private const float spacing = 10;
|
||||||
private readonly MetadataSegment source;
|
private const float transition_duration = 250;
|
||||||
private readonly MetadataSegment tags;
|
|
||||||
|
|
||||||
private readonly DifficultyRow circleSize;
|
private readonly FillFlowContainer top, statsFlow;
|
||||||
private readonly DifficultyRow drainRate;
|
private readonly AdvancedStats advanced;
|
||||||
private readonly DifficultyRow overallDifficulty;
|
private readonly DetailBox ratingsContainer;
|
||||||
private readonly DifficultyRow approachRate;
|
private readonly UserRatings ratings;
|
||||||
private readonly DifficultyRow stars;
|
private readonly ScrollContainer metadataScroll;
|
||||||
|
private readonly MetadataSection description, source, tags;
|
||||||
|
private readonly Container failRetryContainer;
|
||||||
|
private readonly FailRetryGraph failRetryGraph;
|
||||||
|
private readonly DimmedLoadingAnimation loading;
|
||||||
|
|
||||||
private readonly Container ratingsContainer;
|
private APIAccess api;
|
||||||
private readonly Bar ratingsBar;
|
|
||||||
private readonly OsuSpriteText negativeRatings;
|
|
||||||
private readonly OsuSpriteText positiveRatings;
|
|
||||||
private readonly BarGraph ratingsGraph;
|
|
||||||
|
|
||||||
private readonly FillFlowContainer retryFailContainer;
|
|
||||||
private readonly BarGraph retryGraph;
|
|
||||||
private readonly BarGraph failGraph;
|
|
||||||
|
|
||||||
private ScheduledDelegate pendingBeatmapSwitch;
|
private ScheduledDelegate pendingBeatmapSwitch;
|
||||||
private BeatmapInfo beatmap;
|
private BeatmapInfo beatmap;
|
||||||
|
|
||||||
public BeatmapInfo Beatmap
|
public BeatmapInfo Beatmap
|
||||||
{
|
{
|
||||||
get { return beatmap; }
|
get { return beatmap; }
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (beatmap == value) return;
|
if (value == beatmap) return;
|
||||||
|
|
||||||
beatmap = value;
|
beatmap = value;
|
||||||
|
|
||||||
pendingBeatmapSwitch?.Cancel();
|
pendingBeatmapSwitch?.Cancel();
|
||||||
pendingBeatmapSwitch = Schedule(updateStats);
|
pendingBeatmapSwitch = Schedule(updateStatistics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStats()
|
public BeatmapDetails()
|
||||||
{
|
{
|
||||||
if (beatmap == null) return;
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Black.Opacity(0.5f),
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Horizontal = spacing },
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
top = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
statsFlow = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Width = 0.5f,
|
||||||
|
Spacing = new Vector2(spacing),
|
||||||
|
Padding = new MarginPadding { Right = spacing / 2 },
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new DetailBox
|
||||||
|
{
|
||||||
|
Child = advanced = new AdvancedStats
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Padding = new MarginPadding { Horizontal = spacing, Top = spacing * 2, Bottom = spacing },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ratingsContainer = new DetailBox
|
||||||
|
{
|
||||||
|
Child = ratings = new UserRatings
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 134,
|
||||||
|
Padding = new MarginPadding { Horizontal = spacing, Top = spacing },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadataScroll = new ScrollContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Width = 0.5f,
|
||||||
|
ScrollbarVisible = false,
|
||||||
|
Padding = new MarginPadding { Left = spacing / 2 },
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
LayoutDuration = transition_duration,
|
||||||
|
Spacing = new Vector2(spacing * 2),
|
||||||
|
Margin = new MarginPadding { Top = spacing * 2 },
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
description = new MetadataSection("Description")
|
||||||
|
{
|
||||||
|
TextColour = Color4.White.Opacity(0.75f),
|
||||||
|
},
|
||||||
|
source = new MetadataSection("Source")
|
||||||
|
{
|
||||||
|
TextColour = Color4.White.Opacity(0.75f),
|
||||||
|
},
|
||||||
|
tags = new MetadataSection("Tags"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
failRetryContainer = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = "Points of Failure",
|
||||||
|
Font = @"Exo2.0-Bold",
|
||||||
|
TextSize = 14,
|
||||||
|
},
|
||||||
|
failRetryGraph = new FailRetryGraph
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Top = 14 + spacing / 2 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
loading = new DimmedLoadingAnimation
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
description.Text = beatmap.Version;
|
[BackgroundDependencyLoader]
|
||||||
source.Text = beatmap.Metadata.Source;
|
private void load(OsuColour colours, APIAccess api)
|
||||||
tags.Text = beatmap.Metadata.Tags;
|
{
|
||||||
|
this.api = api;
|
||||||
|
tags.TextColour = colours.Yellow;
|
||||||
|
}
|
||||||
|
|
||||||
circleSize.Value = beatmap.Difficulty.CircleSize;
|
protected override void UpdateAfterChildren()
|
||||||
drainRate.Value = beatmap.Difficulty.DrainRate;
|
{
|
||||||
overallDifficulty.Value = beatmap.Difficulty.OverallDifficulty;
|
base.UpdateAfterChildren();
|
||||||
approachRate.Value = beatmap.Difficulty.ApproachRate;
|
|
||||||
stars.Value = (float)beatmap.StarDifficulty;
|
|
||||||
|
|
||||||
var requestedBeatmap = beatmap;
|
metadataScroll.Height = statsFlow.DrawHeight;
|
||||||
|
failRetryContainer.Height = DrawHeight - Padding.TotalVertical - (top.DrawHeight + spacing / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStatistics()
|
||||||
|
{
|
||||||
|
if (Beatmap == null)
|
||||||
|
{
|
||||||
|
clearStats();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ratingsContainer.FadeIn(transition_duration);
|
||||||
|
advanced.Beatmap = Beatmap;
|
||||||
|
description.Text = Beatmap.Version;
|
||||||
|
source.Text = Beatmap.Metadata.Source;
|
||||||
|
tags.Text = Beatmap.Metadata.Tags;
|
||||||
|
|
||||||
|
var requestedBeatmap = Beatmap;
|
||||||
if (requestedBeatmap.Metrics == null)
|
if (requestedBeatmap.Metrics == null)
|
||||||
{
|
{
|
||||||
var lookup = new GetBeatmapDetailsRequest(requestedBeatmap);
|
var lookup = new GetBeatmapDetailsRequest(requestedBeatmap);
|
||||||
@ -84,413 +201,190 @@ namespace osu.Game.Screens.Select
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
requestedBeatmap.Metrics = res;
|
requestedBeatmap.Metrics = res;
|
||||||
Schedule(() => updateMetrics(res));
|
Schedule(() => displayMetrics(res));
|
||||||
};
|
};
|
||||||
lookup.Failure += e => Schedule(() => updateMetrics(null));
|
lookup.Failure += e => Schedule(() => displayMetrics(null));
|
||||||
|
|
||||||
api.Queue(lookup);
|
api.Queue(lookup);
|
||||||
loading.Show();
|
loading.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMetrics(requestedBeatmap.Metrics, false);
|
displayMetrics(requestedBeatmap.Metrics, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void displayMetrics(BeatmapMetrics metrics, bool failOnMissing = true)
|
||||||
/// Update displayed metrics.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="metrics">New metrics to overwrite the existing display. Can be null.</param>
|
|
||||||
/// <param name="failOnMissing">Whether to hide the display on null or empty metrics. If false, we will dim as if waiting for further updates.</param>
|
|
||||||
private void updateMetrics(BeatmapMetrics metrics, bool failOnMissing = true)
|
|
||||||
{
|
{
|
||||||
var hasRatings = metrics?.Ratings.Any() ?? false;
|
var hasRatings = metrics?.Ratings.Any() ?? false;
|
||||||
var hasRetriesFails = (metrics?.Retries.Any() ?? false) && metrics.Fails.Any();
|
var hasRetriesFails = (metrics?.Retries.Any() ?? false) && metrics.Fails.Any();
|
||||||
|
|
||||||
if (failOnMissing)
|
if (failOnMissing) loading.Hide();
|
||||||
loading.Hide();
|
|
||||||
|
|
||||||
if (hasRatings)
|
if (hasRatings)
|
||||||
{
|
{
|
||||||
var ratings = metrics.Ratings.ToList();
|
ratings.Metrics = metrics;
|
||||||
ratingsContainer.Show();
|
ratings.FadeIn(transition_duration);
|
||||||
|
|
||||||
negativeRatings.Text = ratings.GetRange(0, ratings.Count / 2).Sum().ToString();
|
|
||||||
positiveRatings.Text = ratings.GetRange(ratings.Count / 2, ratings.Count / 2).Sum().ToString();
|
|
||||||
ratingsBar.Length = (float)ratings.GetRange(0, ratings.Count / 2).Sum() / ratings.Sum();
|
|
||||||
|
|
||||||
ratingsGraph.Values = ratings.Select(rating => (float)rating);
|
|
||||||
|
|
||||||
ratingsContainer.FadeColour(Color4.White, 500, Easing.Out);
|
|
||||||
}
|
|
||||||
else if (failOnMissing)
|
|
||||||
ratingsGraph.Values = new float[10];
|
|
||||||
else
|
|
||||||
ratingsContainer.FadeColour(Color4.Gray, 500, Easing.Out);
|
|
||||||
|
|
||||||
if (hasRetriesFails)
|
|
||||||
{
|
|
||||||
var retries = metrics.Retries;
|
|
||||||
var fails = metrics.Fails;
|
|
||||||
retryFailContainer.Show();
|
|
||||||
|
|
||||||
float maxValue = fails.Zip(retries, (fail, retry) => fail + retry).Max();
|
|
||||||
failGraph.MaxValue = maxValue;
|
|
||||||
retryGraph.MaxValue = maxValue;
|
|
||||||
|
|
||||||
failGraph.Values = fails.Select(fail => (float)fail);
|
|
||||||
retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue));
|
|
||||||
|
|
||||||
retryFailContainer.FadeColour(Color4.White, 500, Easing.Out);
|
|
||||||
}
|
}
|
||||||
else if (failOnMissing)
|
else if (failOnMissing)
|
||||||
{
|
{
|
||||||
failGraph.Values = new float[100];
|
ratings.FadeTo(0.25f, transition_duration);
|
||||||
retryGraph.Values = new float[100];
|
ratings.Metrics = new BeatmapMetrics
|
||||||
}
|
|
||||||
else
|
|
||||||
retryFailContainer.FadeColour(Color4.Gray, 500, Easing.Out);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BeatmapDetails()
|
|
||||||
{
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Ratings = new int[10],
|
||||||
Colour = Color4.Black,
|
|
||||||
Alpha = 0.5f,
|
|
||||||
},
|
|
||||||
new FillFlowContainer<MetadataSegment>
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Width = 0.4f,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
LayoutDuration = 200,
|
|
||||||
LayoutEasing = Easing.OutQuint,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
description = new MetadataSegment("Description"),
|
|
||||||
source = new MetadataSegment("Source"),
|
|
||||||
tags = new MetadataSegment("Tags")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Width = 0.6f,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Spacing = new Vector2(0, 15),
|
|
||||||
Padding = new MarginPadding(10) { Top = 0 },
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.Black,
|
|
||||||
Alpha = 0.5f,
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Spacing = new Vector2(0, 5),
|
|
||||||
Padding = new MarginPadding(10),
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
circleSize = new DifficultyRow("Circle Size", 7),
|
|
||||||
drainRate = new DifficultyRow("HP Drain"),
|
|
||||||
overallDifficulty = new DifficultyRow("Accuracy"),
|
|
||||||
approachRate = new DifficultyRow("Approach Rate"),
|
|
||||||
stars = new DifficultyRow("Star Difficulty"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ratingsContainer = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.Black,
|
|
||||||
Alpha = 0.5f,
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Padding = new MarginPadding
|
|
||||||
{
|
|
||||||
Top = 25,
|
|
||||||
Left = 15,
|
|
||||||
Right = 15,
|
|
||||||
},
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = "User Rating",
|
|
||||||
Font = @"Exo2.0-Medium",
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
},
|
|
||||||
ratingsBar = new Bar
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = 5,
|
|
||||||
},
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
negativeRatings = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Font = @"Exo2.0-Regular",
|
|
||||||
Text = "0",
|
|
||||||
},
|
|
||||||
positiveRatings = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Font = @"Exo2.0-Regular",
|
|
||||||
Text = "0",
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = "Rating Spread",
|
|
||||||
TextSize = 14,
|
|
||||||
Font = @"Exo2.0-Regular",
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
},
|
|
||||||
ratingsGraph = new BarGraph
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = 50,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
retryFailContainer = new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Alpha = 0,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = "Points of Failure",
|
|
||||||
Font = @"Exo2.0-Regular",
|
|
||||||
},
|
|
||||||
new Container<BarGraph>
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Size = new Vector2(1 / 0.6f, 50),
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
retryGraph = new BarGraph
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
failGraph = new BarGraph
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
loading = new LoadingAnimation()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private APIAccess api;
|
|
||||||
private readonly LoadingAnimation loading;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colour, APIAccess api)
|
|
||||||
{
|
|
||||||
this.api = api;
|
|
||||||
|
|
||||||
description.AccentColour = colour.GrayB;
|
|
||||||
source.AccentColour = colour.GrayB;
|
|
||||||
tags.AccentColour = colour.YellowLight;
|
|
||||||
|
|
||||||
stars.AccentColour = colour.Yellow;
|
|
||||||
|
|
||||||
ratingsBar.BackgroundColour = colour.Green;
|
|
||||||
ratingsBar.AccentColour = colour.YellowDark;
|
|
||||||
ratingsGraph.Colour = colour.BlueDark;
|
|
||||||
|
|
||||||
failGraph.Colour = colour.YellowDarker;
|
|
||||||
retryGraph.Colour = colour.Yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DifficultyRow : Container, IHasAccentColour
|
|
||||||
{
|
|
||||||
private readonly OsuSpriteText name;
|
|
||||||
private readonly Bar bar;
|
|
||||||
private readonly OsuSpriteText valueText;
|
|
||||||
|
|
||||||
private readonly float maxValue;
|
|
||||||
|
|
||||||
private float difficultyValue;
|
|
||||||
public float Value
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return difficultyValue;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
difficultyValue = value;
|
|
||||||
bar.Length = value / maxValue;
|
|
||||||
valueText.Text = value.ToString("N1", CultureInfo.CurrentCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return bar.AccentColour;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
bar.AccentColour = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DifficultyRow(string difficultyName, float maxValue = 10)
|
|
||||||
{
|
|
||||||
this.maxValue = maxValue;
|
|
||||||
RelativeSizeAxes = Axes.X;
|
|
||||||
AutoSizeAxes = Axes.Y;
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
name = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Font = @"Exo2.0-Regular",
|
|
||||||
Text = difficultyName,
|
|
||||||
},
|
|
||||||
bar = new Bar
|
|
||||||
{
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Size = new Vector2(1, 0.35f),
|
|
||||||
Padding = new MarginPadding { Left = 100, Right = 25 },
|
|
||||||
},
|
|
||||||
valueText = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
Font = @"Exo2.0-Regular",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
if (hasRetriesFails)
|
||||||
private void load(OsuColour colour)
|
|
||||||
{
|
{
|
||||||
name.Colour = colour.GrayB;
|
failRetryGraph.Metrics = metrics;
|
||||||
bar.BackgroundColour = colour.Gray7;
|
failRetryContainer.FadeIn(transition_duration);
|
||||||
valueText.Colour = colour.GrayB;
|
}
|
||||||
|
else if (failOnMissing)
|
||||||
|
{
|
||||||
|
failRetryContainer.FadeTo(0.25f, transition_duration);
|
||||||
|
failRetryGraph.Metrics = new BeatmapMetrics
|
||||||
|
{
|
||||||
|
Fails = new int[100],
|
||||||
|
Retries = new int[100],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MetadataSegment : Container, IHasAccentColour
|
private void clearStats()
|
||||||
{
|
{
|
||||||
private readonly OsuSpriteText header;
|
description.Text = null;
|
||||||
private readonly FillFlowContainer<OsuSpriteText> content;
|
source.Text = null;
|
||||||
|
tags.Text = null;
|
||||||
|
advanced.Beatmap = new BeatmapInfo
|
||||||
|
{
|
||||||
|
StarDifficulty = 0,
|
||||||
|
Difficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
CircleSize = 0,
|
||||||
|
DrainRate = 0,
|
||||||
|
OverallDifficulty = 0,
|
||||||
|
ApproachRate = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
loading.Hide();
|
||||||
|
ratingsContainer.FadeOut(transition_duration);
|
||||||
|
failRetryContainer.FadeOut(transition_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DetailBox : Container
|
||||||
|
{
|
||||||
|
private readonly Container content;
|
||||||
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
|
public DetailBox()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Black.Opacity(0.5f),
|
||||||
|
},
|
||||||
|
content = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MetadataSection : Container
|
||||||
|
{
|
||||||
|
private readonly OsuSpriteText title;
|
||||||
|
private readonly TextFlowContainer textFlow;
|
||||||
|
|
||||||
public string Text
|
public string Text
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value))
|
if (string.IsNullOrEmpty(value))
|
||||||
Hide();
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
Show();
|
this.FadeOut(transition_duration);
|
||||||
if (header.Text == "Tags")
|
return;
|
||||||
content.ChildrenEnumerable = value.Split(' ').Select(text => new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = text,
|
|
||||||
Font = "Exo2.0-Regular",
|
|
||||||
});
|
|
||||||
else
|
|
||||||
content.Children = new[]
|
|
||||||
{
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = value,
|
|
||||||
Font = "Exo2.0-Regular",
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.FadeIn(transition_duration);
|
||||||
|
textFlow.Clear();
|
||||||
|
textFlow.AddText(value, s => s.TextSize = 14);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color4 AccentColour
|
public Color4 TextColour
|
||||||
{
|
{
|
||||||
get
|
get { return textFlow.Colour; }
|
||||||
{
|
set { textFlow.Colour = value; }
|
||||||
return content.Colour;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
content.Colour = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetadataSegment(string headerText)
|
public MetadataSection(string title)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
AutoSizeAxes = Axes.Y;
|
AutoSizeAxes = Axes.Y;
|
||||||
Margin = new MarginPadding { Top = 10 };
|
|
||||||
|
InternalChild = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Spacing = new Vector2(spacing / 2),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Child = this.title = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = title,
|
||||||
|
Font = @"Exo2.0-Bold",
|
||||||
|
TextSize = 14,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
textFlow = new TextFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DimmedLoadingAnimation : VisibilityContainer
|
||||||
|
{
|
||||||
|
private readonly LoadingAnimation loading;
|
||||||
|
|
||||||
|
public DimmedLoadingAnimation()
|
||||||
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
header = new OsuSpriteText
|
new Box
|
||||||
{
|
{
|
||||||
Font = @"Exo2.0-Bold",
|
RelativeSizeAxes = Axes.Both,
|
||||||
Text = headerText,
|
Colour = Color4.Black.Opacity(0.5f),
|
||||||
},
|
},
|
||||||
content = new FillFlowContainer<OsuSpriteText>
|
loading = new LoadingAnimation(),
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Direction = FillDirection.Full,
|
|
||||||
Spacing = new Vector2(5, 0),
|
|
||||||
Margin = new MarginPadding { Top = header.TextSize }
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void PopIn()
|
||||||
|
{
|
||||||
|
this.FadeIn(transition_duration, Easing.OutQuint);
|
||||||
|
loading.State = Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopOut()
|
||||||
|
{
|
||||||
|
this.FadeOut(transition_duration, Easing.OutQuint);
|
||||||
|
loading.State = Visibility.Hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
152
osu.Game/Screens/Select/Details/AdvancedStats.cs
Normal file
152
osu.Game/Screens/Select/Details/AdvancedStats.cs
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using System;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Select.Details
|
||||||
|
{
|
||||||
|
public class AdvancedStats : Container
|
||||||
|
{
|
||||||
|
private readonly StatRow firstValue, hpDrain, accuracy, approachRate, starDifficulty;
|
||||||
|
|
||||||
|
private BeatmapInfo beatmap;
|
||||||
|
public BeatmapInfo Beatmap
|
||||||
|
{
|
||||||
|
get { return beatmap; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == beatmap) return;
|
||||||
|
beatmap = value;
|
||||||
|
|
||||||
|
//mania specific
|
||||||
|
if ((Beatmap?.Ruleset?.ID ?? 0) == 3)
|
||||||
|
{
|
||||||
|
firstValue.Title = "Key Amount";
|
||||||
|
firstValue.Value = (int)Math.Round(Beatmap.Difficulty.CircleSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstValue.Title = "Circle Size";
|
||||||
|
firstValue.Value = Beatmap.Difficulty.CircleSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
hpDrain.Value = beatmap.Difficulty.DrainRate;
|
||||||
|
accuracy.Value = beatmap.Difficulty.OverallDifficulty;
|
||||||
|
approachRate.Value = beatmap.Difficulty.ApproachRate;
|
||||||
|
starDifficulty.Value = (float)beatmap.StarDifficulty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdvancedStats()
|
||||||
|
{
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Spacing = new Vector2(4f),
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
firstValue = new StatRow(), //circle size/key amount
|
||||||
|
hpDrain = new StatRow { Title = "HP Drain" },
|
||||||
|
accuracy = new StatRow { Title = "Accuracy" },
|
||||||
|
approachRate = new StatRow { Title = "Approach Rate" },
|
||||||
|
starDifficulty = new StatRow(10, true) { Title = "Star Difficulty" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
starDifficulty.AccentColour = colours.Yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StatRow : Container, IHasAccentColour
|
||||||
|
{
|
||||||
|
private const float value_width = 25;
|
||||||
|
private const float name_width = 70;
|
||||||
|
|
||||||
|
private readonly float maxValue;
|
||||||
|
private readonly bool forceDecimalPlaces;
|
||||||
|
private readonly OsuSpriteText name, value;
|
||||||
|
private readonly Bar bar;
|
||||||
|
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get { return name.Text; }
|
||||||
|
set { name.Text = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private float difficultyValue;
|
||||||
|
public float Value
|
||||||
|
{
|
||||||
|
get { return difficultyValue; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
difficultyValue = value;
|
||||||
|
bar.Length = value / maxValue;
|
||||||
|
this.value.Text = value.ToString(forceDecimalPlaces ? "#.00" : "0.##");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color4 AccentColour
|
||||||
|
{
|
||||||
|
get { return bar.AccentColour; }
|
||||||
|
set { bar.AccentColour = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatRow(float maxValue = 10, bool forceDecimalPlaces = false)
|
||||||
|
{
|
||||||
|
this.maxValue = maxValue;
|
||||||
|
this.forceDecimalPlaces = forceDecimalPlaces;
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Width = name_width,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Child = this.name = new OsuSpriteText
|
||||||
|
{
|
||||||
|
TextSize = 13,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bar = new Bar
|
||||||
|
{
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 5,
|
||||||
|
BackgroundColour = Color4.White.Opacity(0.5f),
|
||||||
|
Padding = new MarginPadding { Left = name_width + 10, Right = value_width + 10 },
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
Width = value_width,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Child = value = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
TextSize = 13,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
120
osu.Game/Screens/Select/Details/BasicStats.cs
Normal file
120
osu.Game/Screens/Select/Details/BasicStats.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Select.Details
|
||||||
|
{
|
||||||
|
public class BasicStats : Container
|
||||||
|
{
|
||||||
|
private const float stat_count = 4;
|
||||||
|
|
||||||
|
private readonly Statistic length, bpm, circleCount, sliderCount;
|
||||||
|
|
||||||
|
private BeatmapInfo beatmap;
|
||||||
|
public BeatmapInfo Beatmap
|
||||||
|
{
|
||||||
|
get { return beatmap; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == beatmap) return;
|
||||||
|
beatmap = value;
|
||||||
|
|
||||||
|
//length.Value = TimeSpan.FromMilliseconds(Beatmap.OnlineInfo.Length).ToString(@"m\:ss");
|
||||||
|
//bpm.Value = Beatmap.BeatmapSet.OnlineInfo.BPM.ToString(@"0.##");
|
||||||
|
//circleCount.Value = string.Format(@"{0:n0}", beatmap.OnlineInfo.CircleCount);
|
||||||
|
//sliderCount.Value = string.Format(@"{0:n0}", beatmap.OnlineInfo.SliderCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasicStats()
|
||||||
|
{
|
||||||
|
var statWidth = 1 / stat_count;
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
length = new Statistic(FontAwesome.fa_clock_o, "Length") { Width = statWidth },
|
||||||
|
bpm = new Statistic(FontAwesome.fa_circle, "BPM") { Width = statWidth },
|
||||||
|
circleCount = new Statistic(FontAwesome.fa_circle_o, "Circle Count") { Width = statWidth },
|
||||||
|
sliderCount = new Statistic(FontAwesome.fa_circle, "Slider Count") { Width = statWidth },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Statistic : Container, IHasTooltip
|
||||||
|
{
|
||||||
|
private readonly string name;
|
||||||
|
private readonly OsuSpriteText value;
|
||||||
|
|
||||||
|
public string TooltipText => name;
|
||||||
|
public string Value
|
||||||
|
{
|
||||||
|
get { return value.Text; }
|
||||||
|
set { this.value.Text = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Statistic(FontAwesome icon, string name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Icon = FontAwesome.fa_square,
|
||||||
|
Size = new Vector2(13),
|
||||||
|
Rotation = 45,
|
||||||
|
Colour = OsuColour.FromHex(@"441288"),
|
||||||
|
},
|
||||||
|
new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Icon = icon,
|
||||||
|
Size = new Vector2(13),
|
||||||
|
Colour = OsuColour.FromHex(@"f7dd55"),
|
||||||
|
Scale = new Vector2(0.8f),
|
||||||
|
},
|
||||||
|
value = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
TextSize = 13,
|
||||||
|
Font = @"Exo2.0-Bold",
|
||||||
|
Margin = new MarginPadding { Left = 10 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colour)
|
||||||
|
{
|
||||||
|
value.Colour = colour.Yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
osu.Game/Screens/Select/Details/FailRetryGraph.cs
Normal file
62
osu.Game/Screens/Select/Details/FailRetryGraph.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Select.Details
|
||||||
|
{
|
||||||
|
public class FailRetryGraph : Container
|
||||||
|
{
|
||||||
|
private readonly BarGraph retryGraph, failGraph;
|
||||||
|
|
||||||
|
private BeatmapMetrics metrics;
|
||||||
|
public BeatmapMetrics Metrics
|
||||||
|
{
|
||||||
|
get { return metrics; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == metrics) return;
|
||||||
|
metrics = value;
|
||||||
|
|
||||||
|
var retries = Metrics.Retries;
|
||||||
|
var fails = Metrics.Fails;
|
||||||
|
|
||||||
|
float maxValue = fails.Zip(retries, (fail, retry) => fail + retry).Max();
|
||||||
|
failGraph.MaxValue = maxValue;
|
||||||
|
retryGraph.MaxValue = maxValue;
|
||||||
|
|
||||||
|
failGraph.Values = fails.Select(f => (float)f);
|
||||||
|
retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FailRetryGraph()
|
||||||
|
{
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
retryGraph = new BarGraph
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
failGraph = new BarGraph
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
retryGraph.Colour = colours.Yellow;
|
||||||
|
failGraph.Colour = colours.YellowDarker;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
114
osu.Game/Screens/Select/Details/SuccessRate.cs
Normal file
114
osu.Game/Screens/Select/Details/SuccessRate.cs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// 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.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Select.Details
|
||||||
|
{
|
||||||
|
public class SuccessRate : Container
|
||||||
|
{
|
||||||
|
private readonly FillFlowContainer header;
|
||||||
|
private readonly OsuSpriteText successRateLabel, successPercent, graphLabel;
|
||||||
|
private readonly Bar successRate;
|
||||||
|
private readonly Container percentContainer;
|
||||||
|
private readonly FailRetryGraph graph;
|
||||||
|
|
||||||
|
private BeatmapInfo beatmap;
|
||||||
|
public BeatmapInfo Beatmap
|
||||||
|
{
|
||||||
|
get { return beatmap; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == beatmap) return;
|
||||||
|
beatmap = value;
|
||||||
|
|
||||||
|
//successPercent.Text = $"{beatmap.OnlineInfo.SuccessRate}%";
|
||||||
|
//successRate.Length = (float)beatmap.OnlineInfo.SuccessRate / 100f;
|
||||||
|
|
||||||
|
graph.Metrics = Beatmap.Metrics;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuccessRate()
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
header = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
successRateLabel = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = "Success Rate",
|
||||||
|
TextSize = 13,
|
||||||
|
},
|
||||||
|
successRate = new Bar
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 5,
|
||||||
|
Margin = new MarginPadding { Top = 5 },
|
||||||
|
},
|
||||||
|
percentContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Child = successPercent = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
TextSize = 13,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graphLabel = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = "Points of Failure",
|
||||||
|
TextSize = 13,
|
||||||
|
Margin = new MarginPadding { Vertical = 20 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graph = new FailRetryGraph
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
successRateLabel.Colour = successPercent.Colour = graphLabel.Colour = colours.Gray5;
|
||||||
|
successRate.AccentColour = colours.Green;
|
||||||
|
successRate.BackgroundColour = colours.GrayD;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateAfterChildren()
|
||||||
|
{
|
||||||
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
|
graph.Padding = new MarginPadding { Top = header.DrawHeight };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
percentContainer.Width = successRate.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
122
osu.Game/Screens/Select/Details/UserRatings.cs
Normal file
122
osu.Game/Screens/Select/Details/UserRatings.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// 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.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Select.Details
|
||||||
|
{
|
||||||
|
public class UserRatings : Container
|
||||||
|
{
|
||||||
|
private readonly FillFlowContainer header;
|
||||||
|
private readonly Bar ratingsBar;
|
||||||
|
private readonly OsuSpriteText negativeRatings, positiveRatings;
|
||||||
|
private readonly Container graphContainer;
|
||||||
|
private readonly BarGraph graph;
|
||||||
|
|
||||||
|
private BeatmapMetrics metrics;
|
||||||
|
public BeatmapMetrics Metrics
|
||||||
|
{
|
||||||
|
get { return metrics; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == metrics) return;
|
||||||
|
metrics = value;
|
||||||
|
|
||||||
|
var ratings = Metrics.Ratings.ToList();
|
||||||
|
negativeRatings.Text = ratings.GetRange(0, ratings.Count / 2).Sum().ToString();
|
||||||
|
positiveRatings.Text = ratings.GetRange(ratings.Count / 2, ratings.Count / 2).Sum().ToString();
|
||||||
|
ratingsBar.Length = (float)ratings.GetRange(0, ratings.Count / 2).Sum() / ratings.Sum();
|
||||||
|
graph.Values = Metrics.Ratings.Select(r => (float)r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRatings()
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
header = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = "User Rating",
|
||||||
|
TextSize = 13,
|
||||||
|
},
|
||||||
|
ratingsBar = new Bar
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 5,
|
||||||
|
Margin = new MarginPadding { Top = 5 },
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
negativeRatings = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = "0",
|
||||||
|
TextSize = 13,
|
||||||
|
},
|
||||||
|
positiveRatings = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
Text = @"0",
|
||||||
|
TextSize = 13,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = "Rating Spread",
|
||||||
|
TextSize = 13,
|
||||||
|
Margin = new MarginPadding { Top = 10, Bottom = 5 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graphContainer = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Child = graph = new BarGraph
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
ratingsBar.BackgroundColour = colours.Green;
|
||||||
|
ratingsBar.AccentColour = colours.Yellow;
|
||||||
|
graph.Colour = colours.BlueDark;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateAfterChildren()
|
||||||
|
{
|
||||||
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
|
graphContainer.Padding = new MarginPadding { Top = header.DrawHeight };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -538,6 +538,11 @@
|
|||||||
<Compile Include="Screens\Multiplayer\ParticipantInfo.cs" />
|
<Compile Include="Screens\Multiplayer\ParticipantInfo.cs" />
|
||||||
<Compile Include="Screens\Multiplayer\ModeTypeInfo.cs" />
|
<Compile Include="Screens\Multiplayer\ModeTypeInfo.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\BeatmapSetCover.cs" />
|
<Compile Include="Beatmaps\Drawables\BeatmapSetCover.cs" />
|
||||||
|
<Compile Include="Screens\Select\Details\AdvancedStats.cs" />
|
||||||
|
<Compile Include="Screens\Select\Details\BasicStats.cs" />
|
||||||
|
<Compile Include="Screens\Select\Details\FailRetryGraph.cs" />
|
||||||
|
<Compile Include="Screens\Select\Details\SuccessRate.cs" />
|
||||||
|
<Compile Include="Screens\Select\Details\UserRatings.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||||
|
Loading…
Reference in New Issue
Block a user