diff --git a/osu-resources b/osu-resources
index f6042e1cb3..a4418111f8 160000
--- a/osu-resources
+++ b/osu-resources
@@ -1 +1 @@
-Subproject commit f6042e1cb37cfad6c879d0e1245f7880c7fcd5f5
+Subproject commit a4418111f8ed2350a6fd46fe69258884f0757745
diff --git a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj
index c6474eae5a..c090342a4b 100644
--- a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj
+++ b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj
@@ -9,7 +9,7 @@
Properties
osu.Desktop.Deploy
osu.Desktop.Deploy
- v4.5.2
+ v4.6.1
512
true
diff --git a/osu.Desktop.Tests/Visual/TestCaseBeatmapDetails.cs b/osu.Desktop.Tests/Visual/TestCaseBeatmapDetails.cs
index 11a15cf56f..d0f631201a 100644
--- a/osu.Desktop.Tests/Visual/TestCaseBeatmapDetails.cs
+++ b/osu.Desktop.Tests/Visual/TestCaseBeatmapDetails.cs
@@ -12,50 +12,104 @@ namespace osu.Desktop.Tests.Visual
{
public override string Description => "BeatmapDetails tab of BeatmapDetailArea";
- private readonly BeatmapDetails details;
-
public TestCaseBeatmapDetails()
{
+ BeatmapDetails details;
Add(details = new BeatmapDetails
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding(150),
- Beatmap = new BeatmapInfo
+ });
+
+ AddStep("beatmap all metrics", () => details.Beatmap = new BeatmapInfo
+ {
+ Version = "All Metrics",
+ Metadata = new BeatmapMetadata
{
- Version = "VisualTest",
- Metadata = new BeatmapMetadata
- {
- Source = "Some guy",
- Tags = "beatmap metadata example with a very very long list of tags and not much creativity",
- },
- Difficulty = new BeatmapDifficulty
- {
- CircleSize = 7,
- ApproachRate = 3.5f,
- OverallDifficulty = 5.7f,
- DrainRate = 1,
- },
- StarDifficulty = 5.3f,
- Metrics = new BeatmapMetrics
- {
- Ratings = Enumerable.Range(0, 10),
- Fails = Enumerable.Range(lastRange, 100).Select(i => i % 12 - 6),
- Retries = Enumerable.Range(lastRange - 3, 100).Select(i => i % 12 - 6),
- },
+ Source = "osu!lazer",
+ Tags = "this beatmap has all the metrics",
+ },
+ Difficulty = new BeatmapDifficulty
+ {
+ CircleSize = 7,
+ DrainRate = 1,
+ OverallDifficulty = 5.7f,
+ ApproachRate = 3.5f,
+ },
+ StarDifficulty = 5.3f,
+ Metrics = new BeatmapMetrics
+ {
+ Ratings = Enumerable.Range(0, 10),
+ Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
+ Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
},
});
- AddRepeatStep("fail values", newRetryAndFailValues, 10);
- }
+ AddStep("beatmap ratings", () => details.Beatmap = new BeatmapInfo
+ {
+ Version = "Only Ratings",
+ Metadata = new BeatmapMetadata
+ {
+ Source = "osu!lazer",
+ Tags = "this beatmap has ratings metrics but not retries or fails",
+ },
+ Difficulty = new BeatmapDifficulty
+ {
+ CircleSize = 6,
+ DrainRate = 9,
+ OverallDifficulty = 6,
+ ApproachRate = 6,
+ },
+ StarDifficulty = 4.8f,
+ Metrics = new BeatmapMetrics
+ {
+ Ratings = Enumerable.Range(0, 10),
+ },
+ });
- private int lastRange = 1;
+ AddStep("beatmap fails retries", () => details.Beatmap = new BeatmapInfo
+ {
+ Version = "Only Retries and Fails",
+ Metadata = new BeatmapMetadata
+ {
+ Source = "osu!lazer",
+ Tags = "this beatmap has retries and fails but no ratings",
+ },
+ Difficulty = new BeatmapDifficulty
+ {
+ CircleSize = 3.7f,
+ DrainRate = 6,
+ OverallDifficulty = 6,
+ ApproachRate = 7,
+ },
+ StarDifficulty = 2.91f,
+ Metrics = new BeatmapMetrics
+ {
+ Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
+ Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
+ },
+ });
- private void newRetryAndFailValues()
- {
- details.Beatmap.Metrics.Fails = Enumerable.Range(lastRange, 100).Select(i => i % 12 - 6);
- details.Beatmap.Metrics.Retries = Enumerable.Range(lastRange - 3, 100).Select(i => i % 12 - 6);
- details.Beatmap = details.Beatmap;
- lastRange += 100;
+ AddStep("beatmap no metrics", () => details.Beatmap = new BeatmapInfo
+ {
+ Version = "No Metrics",
+ Metadata = new BeatmapMetadata
+ {
+ Source = "osu!lazer",
+ Tags = "this beatmap has no metrics",
+ },
+ Difficulty = new BeatmapDifficulty
+ {
+ CircleSize = 5,
+ DrainRate = 5,
+ OverallDifficulty = 5.5f,
+ ApproachRate = 6.5f,
+ },
+ StarDifficulty = 1.97f,
+ Metrics = new BeatmapMetrics(),
+ });
+
+ AddStep("null beatmap", () => details.Beatmap = null);
}
}
-}
\ No newline at end of file
+}
diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj
index 86268e6110..975af1a782 100644
--- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj
+++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj
@@ -9,7 +9,7 @@
Properties
osu.Desktop.Tests
osu.Desktop.Tests
- v4.5
+ v4.6.1
512
diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj
index 8bba59207f..33019909c6 100644
--- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj
+++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj
@@ -22,7 +22,7 @@
OnOutputUpdated
false
LocalIntranet
- v4.5
+ v4.6.1
true
publish\
true
diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj
index bbca4145c6..661c17699b 100644
--- a/osu.Desktop/osu.Desktop.csproj
+++ b/osu.Desktop/osu.Desktop.csproj
@@ -22,7 +22,7 @@
OnOutputUpdated
false
LocalIntranet
- v4.5
+ v4.6.1
true
publish\
true
diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
index 79ef5f4ba8..2ae2262ac7 100644
--- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
+++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
@@ -9,7 +9,7 @@
Properties
osu.Game.Rulesets.Catch
osu.Game.Rulesets.Catch
- v4.5
+ v4.6.1
512
diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
index 890c9116cf..5f39054d82 100644
--- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
+++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
@@ -9,7 +9,7 @@
Properties
osu.Game.Rulesets.Mania
osu.Game.Rulesets.Mania
- v4.5
+ v4.6.1
512
diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs
index 72ba421344..c6ecc3a506 100644
--- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs
+++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs
@@ -51,6 +51,7 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing
foreach (OsuDifficultyHitObject h in onScreen)
{
+ // ReSharper disable once PossibleNullReferenceException (resharper not smart enough to understand IEnumerator.MoveNext())
h.TimeUntilHit -= latest.DeltaTime;
// Calculate reading strain here
}
diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
index 0c9e53cf69..857f47f9b9 100644
--- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
+++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
@@ -9,7 +9,7 @@
Properties
osu.Game.Rulesets.Osu
osu.Game.Rulesets.Osu
- v4.5
+ v4.6.1
512
diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
index 33748a267f..e1987ec96d 100644
--- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
+++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
@@ -9,7 +9,7 @@
Properties
osu.Game.Rulesets.Taiko
osu.Game.Rulesets.Taiko
- v4.5
+ v4.6.1
512
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index 8ec68b41be..220b1aac7f 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -7,7 +7,7 @@
Library
osu.Game.Tests
osu.Game.Tests
- v4.5
+ v4.6.1
true
diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs
index 4c108e793a..8c777f491b 100644
--- a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs
+++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs
@@ -15,11 +15,7 @@ namespace osu.Game.Graphics.UserInterface.Volume
{
private readonly VolumeMeter volumeMeterMaster;
- private void volumeChanged(double newVolume)
- {
- Show();
- schedulePopOut();
- }
+ protected override bool BlockPassThroughMouse => false;
public VolumeControl()
{
@@ -85,6 +81,12 @@ namespace osu.Game.Graphics.UserInterface.Volume
return false;
}
+ private void volumeChanged(double newVolume)
+ {
+ Show();
+ schedulePopOut();
+ }
+
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs
index 0a06439c3e..64d0d628f0 100644
--- a/osu.Game/Overlays/MusicController.cs
+++ b/osu.Game/Overlays/MusicController.cs
@@ -302,8 +302,8 @@ namespace osu.Game.Overlays
else
{
//figure out the best direction based on order in playlist.
- var last = playlist.BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo.ID).Count();
- var next = beatmap == null ? -1 : playlist.BeatmapSets.TakeWhile(b => b.ID != beatmap.BeatmapSetInfo.ID).Count();
+ var last = playlist.BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count();
+ var next = beatmap == null ? -1 : playlist.BeatmapSets.TakeWhile(b => b.ID != beatmap.BeatmapSetInfo?.ID).Count();
direction = last > next ? TransformDirection.Prev : TransformDirection.Next;
}
diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs
index e2701faca0..34b079951d 100644
--- a/osu.Game/Rulesets/UI/RulesetContainer.cs
+++ b/osu.Game/Rulesets/UI/RulesetContainer.cs
@@ -77,13 +77,6 @@ namespace osu.Game.Rulesets.UI
Ruleset = ruleset;
}
- [BackgroundDependencyLoader]
- private void load()
- {
- KeyBindingInputManager = CreateInputManager();
- KeyBindingInputManager.RelativeSizeAxes = Axes.Both;
- }
-
///
/// Checks whether all HitObjects have been judged, and invokes OnAllJudged.
///
@@ -194,6 +187,9 @@ namespace osu.Game.Rulesets.UI
// Post-process the beatmap
processor.PostProcess(Beatmap);
+ KeyBindingInputManager = CreateInputManager();
+ KeyBindingInputManager.RelativeSizeAxes = Axes.Both;
+
// Add mods, should always be the last thing applied to give full control to mods
applyMods(Mods);
}
diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs
index 0f6c5984c4..d21be71785 100644
--- a/osu.Game/Screens/Play/KeyCounterCollection.cs
+++ b/osu.Game/Screens/Play/KeyCounterCollection.cs
@@ -28,6 +28,8 @@ namespace osu.Game.Screens.Play
public override void Add(KeyCounter key)
{
+ if (key == null) throw new ArgumentNullException(nameof(key));
+
base.Add(key);
key.IsCounting = IsCounting;
key.FadeTime = FadeTime;
diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs
index 47d25585ad..a676516300 100644
--- a/osu.Game/Screens/Select/BeatmapDetailArea.cs
+++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+using System;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
@@ -10,6 +11,8 @@ namespace osu.Game.Screens.Select
{
public class BeatmapDetailArea : Container
{
+ private const float details_padding = 10;
+
private readonly Container content;
protected override Container Content => content;
@@ -66,9 +69,8 @@ namespace osu.Game.Screens.Select
Details = new BeatmapDetails
{
RelativeSizeAxes = Axes.X,
- Masking = true,
- Height = 352,
Alpha = 0,
+ Margin = new MarginPadding { Top = details_padding },
},
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);
+ }
}
}
diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs
index a5486efa96..a98362e89c 100644
--- a/osu.Game/Screens/Select/BeatmapDetails.cs
+++ b/osu.Game/Screens/Select/BeatmapDetails.cs
@@ -9,71 +9,189 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
-using System.Globalization;
using System.Linq;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Framework.Threading;
using osu.Framework.Graphics.Shapes;
+using osu.Framework.Extensions.Color4Extensions;
+using osu.Game.Screens.Select.Details;
using osu.Game.Beatmaps;
namespace osu.Game.Screens.Select
{
public class BeatmapDetails : Container
{
- private readonly MetadataSegment description;
- private readonly MetadataSegment source;
- private readonly MetadataSegment tags;
+ private const float spacing = 10;
+ private const float transition_duration = 250;
- private readonly DifficultyRow circleSize;
- private readonly DifficultyRow drainRate;
- private readonly DifficultyRow overallDifficulty;
- private readonly DifficultyRow approachRate;
- private readonly DifficultyRow stars;
+ private readonly FillFlowContainer top, statsFlow;
+ private readonly AdvancedStats advanced;
+ private readonly DetailBox ratingsContainer;
+ private readonly UserRatings ratings;
+ 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 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 APIAccess api;
private ScheduledDelegate pendingBeatmapSwitch;
- private BeatmapInfo beatmap;
+ private BeatmapInfo beatmap;
public BeatmapInfo Beatmap
{
get { return beatmap; }
-
set
{
- if (beatmap == value) return;
-
+ if (value == beatmap) return;
beatmap = value;
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;
- source.Text = beatmap.Metadata.Source;
- tags.Text = beatmap.Metadata.Tags;
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colours, APIAccess api)
+ {
+ this.api = api;
+ tags.TextColour = colours.Yellow;
+ }
- circleSize.Value = beatmap.Difficulty.CircleSize;
- drainRate.Value = beatmap.Difficulty.DrainRate;
- overallDifficulty.Value = beatmap.Difficulty.OverallDifficulty;
- approachRate.Value = beatmap.Difficulty.ApproachRate;
- stars.Value = (float)beatmap.StarDifficulty;
+ protected override void UpdateAfterChildren()
+ {
+ base.UpdateAfterChildren();
- 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)
{
var lookup = new GetBeatmapDetailsRequest(requestedBeatmap);
@@ -84,413 +202,195 @@ namespace osu.Game.Screens.Select
return;
requestedBeatmap.Metrics = res;
- Schedule(() => updateMetrics(res));
+ Schedule(() => displayMetrics(res));
};
- lookup.Failure += e => Schedule(() => updateMetrics(null));
+ lookup.Failure += e => Schedule(() => displayMetrics(null));
api.Queue(lookup);
loading.Show();
}
- updateMetrics(requestedBeatmap.Metrics, false);
+ displayMetrics(requestedBeatmap.Metrics, false);
}
- ///
- /// Update displayed metrics.
- ///
- /// New metrics to overwrite the existing display. Can be null.
- /// Whether to hide the display on null or empty metrics. If false, we will dim as if waiting for further updates.
- private void updateMetrics(BeatmapMetrics metrics, bool failOnMissing = true)
+ private void displayMetrics(BeatmapMetrics metrics, bool failOnMissing = true)
{
- var hasRatings = metrics?.Ratings.Any() ?? false;
- var hasRetriesFails = (metrics?.Retries.Any() ?? false) && metrics.Fails.Any();
+ var hasRatings = metrics?.Ratings?.Any() ?? false;
+ var hasRetriesFails = (metrics?.Retries?.Any() ?? false) && (metrics.Fails?.Any() ?? false);
- if (failOnMissing)
- loading.Hide();
+ if (failOnMissing) loading.Hide();
if (hasRatings)
{
- var ratings = metrics.Ratings.ToList();
- ratingsContainer.Show();
-
- 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);
+ ratings.Metrics = metrics;
+ ratings.FadeIn(transition_duration);
}
else if (failOnMissing)
- ratingsGraph.Values = new float[10];
+ {
+ ratings.Metrics = new BeatmapMetrics
+ {
+ Ratings = new int[10],
+ };
+ }
else
- ratingsContainer.FadeColour(Color4.Gray, 500, Easing.Out);
+ {
+ ratings.FadeTo(0.25f, transition_duration);
+ }
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);
+ failRetryGraph.Metrics = metrics;
+ failRetryContainer.FadeIn(transition_duration);
}
else if (failOnMissing)
{
- failGraph.Values = new float[100];
- retryGraph.Values = new float[100];
+ failRetryGraph.Metrics = new BeatmapMetrics
+ {
+ Fails = new int[100],
+ Retries = new int[100],
+ };
}
else
- retryFailContainer.FadeColour(Color4.Gray, 500, Easing.Out);
+ {
+ failRetryContainer.FadeTo(0.25f, transition_duration);
+ }
}
- public BeatmapDetails()
+ private void clearStats()
{
- Children = new Drawable[]
+ description.Text = null;
+ source.Text = null;
+ tags.Text = null;
+ advanced.Beatmap = new BeatmapInfo
{
- new Box
+ StarDifficulty = 0,
+ Difficulty = new BeatmapDifficulty
{
- RelativeSizeAxes = Axes.Both,
- Colour = Color4.Black,
- Alpha = 0.5f,
+ CircleSize = 0,
+ DrainRate = 0,
+ OverallDifficulty = 0,
+ ApproachRate = 0,
},
- new FillFlowContainer
- {
- 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
- {
- 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()
};
+
+ loading.Hide();
+ ratingsContainer.FadeOut(transition_duration);
+ failRetryContainer.FadeOut(transition_duration);
}
- private APIAccess api;
- private readonly LoadingAnimation loading;
-
- [BackgroundDependencyLoader]
- private void load(OsuColour colour, APIAccess api)
+ private class DetailBox : Container
{
- this.api = api;
+ private readonly Container content;
+ protected override Container Content => content;
- 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
+ public DetailBox()
{
- 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[]
+
+ InternalChildren = new Drawable[]
{
- name = new OsuSpriteText
+ new Box
{
- 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 },
+ Colour = Color4.Black.Opacity(0.5f),
},
- valueText = new OsuSpriteText
+ content = new Container
{
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- Font = @"Exo2.0-Regular",
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
},
};
}
-
- [BackgroundDependencyLoader]
- private void load(OsuColour colour)
- {
- name.Colour = colour.GrayB;
- bar.BackgroundColour = colour.Gray7;
- valueText.Colour = colour.GrayB;
- }
}
- private class MetadataSegment : Container, IHasAccentColour
+ private class MetadataSection : Container
{
- private readonly OsuSpriteText header;
- private readonly FillFlowContainer content;
+ private readonly TextFlowContainer textFlow;
public string Text
{
set
{
if (string.IsNullOrEmpty(value))
- Hide();
- else
{
- Show();
- if (header.Text == "Tags")
- 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.FadeOut(transition_duration);
+ return;
}
+
+ this.FadeIn(transition_duration);
+ textFlow.Clear();
+ textFlow.AddText(value, s => s.TextSize = 14);
}
}
- public Color4 AccentColour
+ public Color4 TextColour
{
- get
- {
- return content.Colour;
- }
- set
- {
- content.Colour = value;
- }
+ get { return textFlow.Colour; }
+ set { textFlow.Colour = value; }
}
- public MetadataSegment(string headerText)
+ public MetadataSection(string title)
{
RelativeSizeAxes = Axes.X;
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 = 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[]
{
- header = new OsuSpriteText
+ new Box
{
- Font = @"Exo2.0-Bold",
- Text = headerText,
+ RelativeSizeAxes = Axes.Both,
+ Colour = Color4.Black.Opacity(0.5f),
},
- content = new FillFlowContainer
- {
- RelativeSizeAxes = Axes.X,
- AutoSizeAxes = Axes.Y,
- Direction = FillDirection.Full,
- Spacing = new Vector2(5, 0),
- Margin = new MarginPadding { Top = header.TextSize }
- }
+ loading = new LoadingAnimation(),
};
}
+
+ 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;
+ }
}
}
}
diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs
new file mode 100644
index 0000000000..d92c8ed509
--- /dev/null
+++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs
@@ -0,0 +1,152 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd .
+// 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 StatisticRow 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 ?? 0);
+ }
+ else
+ {
+ firstValue.Title = "Circle Size";
+ firstValue.Value = Beatmap?.Difficulty?.CircleSize ?? 0;
+ }
+
+ 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 StatisticRow(), //circle size/key amount
+ hpDrain = new StatisticRow { Title = "HP Drain" },
+ accuracy = new StatisticRow { Title = "Accuracy" },
+ approachRate = new StatisticRow { Title = "Approach Rate" },
+ starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" },
+ },
+ };
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colours)
+ {
+ starDifficulty.AccentColour = colours.Yellow;
+ }
+
+ private class StatisticRow : 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 ? "0.00" : "0.##");
+ }
+ }
+
+ public Color4 AccentColour
+ {
+ get { return bar.AccentColour; }
+ set { bar.AccentColour = value; }
+ }
+
+ public StatisticRow(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 = 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,
+ },
+ },
+ };
+ }
+ }
+ }
+}
diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs
new file mode 100644
index 0000000000..4d75c49d17
--- /dev/null
+++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs
@@ -0,0 +1,62 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd .
+// 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;
+ }
+ }
+}
diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs
new file mode 100644
index 0000000000..db6d932464
--- /dev/null
+++ b/osu.Game/Screens/Select/Details/UserRatings.cs
@@ -0,0 +1,122 @@
+// Copyright (c) 2007-2017 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.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 };
+ }
+ }
+}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 5e1c5426ec..d20618a2ae 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -9,7 +9,7 @@
Properties
osu.Game
osu.Game
- v4.5
+ v4.6.1
512
@@ -539,6 +539,9 @@
+
+
+