diff --git a/osu-framework b/osu-framework index e793a08417..8c4f232694 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e793a084177f53920645c4f6f70cfef91e7fd19e +Subproject commit 8c4f23269447d9ce21a5dbd3a0fd4f6caae9ab38 diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs new file mode 100644 index 0000000000..5b4af6ea8a --- /dev/null +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Catch.Objects; + +namespace osu.Game.Rulesets.Catch.Beatmaps +{ + public class CatchBeatmap : Beatmap + { + public override IEnumerable GetStatistics() + { + int fruits = HitObjects.Count(s => s is Fruit); + int juiceStreams = HitObjects.Count(s => s is JuiceStream); + int bananaShowers = HitObjects.Count(s => s is BananaShower); + + return new[] + { + new BeatmapStatistic + { + Name = @"Fruit Count", + Content = fruits.ToString(), + Icon = FontAwesome.fa_circle_o + }, + new BeatmapStatistic + { + Name = @"Juice Stream Count", + Content = juiceStreams.ToString(), + Icon = FontAwesome.fa_circle + }, + new BeatmapStatistic + { + Name = @"Banana Shower Count", + Content = bananaShowers.ToString(), + Icon = FontAwesome.fa_circle + } + }; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 4a0b120e47..f40ef67dfb 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -69,5 +69,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps X = positionData.X / CatchPlayfield.BASE_WIDTH }; } + + protected override Beatmap CreateBeatmap() => new CatchBeatmap(); } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs index 6af3719f83..ad5f8e447d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.UI; @@ -29,5 +30,27 @@ namespace osu.Game.Rulesets.Mania.Beatmaps { Stages.Add(defaultStage); } + + public override IEnumerable GetStatistics() + { + int notes = HitObjects.Count(s => s is Note); + int holdnotes = HitObjects.Count(s => s is HoldNote); + + return new[] + { + new BeatmapStatistic + { + Name = @"Note Count", + Content = notes.ToString(), + Icon = FontAwesome.fa_circle_o + }, + new BeatmapStatistic + { + Name = @"Hold Note Count", + Content = holdnotes.ToString(), + Icon = FontAwesome.fa_circle + }, + }; + } } } diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs new file mode 100644 index 0000000000..6d90c2a875 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Beatmaps +{ + public class OsuBeatmap : Beatmap + { + public override IEnumerable GetStatistics() + { + int circles = HitObjects.Count(c => c is HitCircle); + int sliders = HitObjects.Count(s => s is Slider); + int spinners = HitObjects.Count(s => s is Spinner); + + return new[] + { + new BeatmapStatistic + { + Name = @"Circle Count", + Content = circles.ToString(), + Icon = FontAwesome.fa_circle_o + }, + new BeatmapStatistic + { + Name = @"Slider Count", + Content = sliders.ToString(), + Icon = FontAwesome.fa_circle + }, + new BeatmapStatistic + { + Name = @"Spinner Count", + Content = spinners.ToString(), + Icon = FontAwesome.fa_circle + } + }; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 1cd4ec5668..5f3a909488 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -65,5 +65,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps }; } } + + protected override Beatmap CreateBeatmap() => new OsuBeatmap(); } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 927ffa2146..69a54fb533 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -9,7 +9,6 @@ using osu.Game.Rulesets.Osu.OsuDifficulty; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; using System.Collections.Generic; -using System.Linq; using osu.Framework.Graphics; using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; @@ -17,8 +16,6 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; @@ -40,36 +37,6 @@ namespace osu.Game.Rulesets.Osu new KeyBinding(InputKey.MouseRight, OsuAction.RightButton), }; - public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) - { - IEnumerable hitObjects = beatmap.Beatmap.HitObjects; - IEnumerable circles = hitObjects.Where(c => !(c is IHasEndTime)); - IEnumerable sliders = hitObjects.Where(s => s is IHasCurve); - IEnumerable spinners = hitObjects.Where(s => s is IHasEndTime && !(s is IHasCurve)); - - return new[] - { - new BeatmapStatistic - { - Name = @"Circle Count", - Content = circles.Count().ToString(), - Icon = FontAwesome.fa_circle_o - }, - new BeatmapStatistic - { - Name = @"Slider Count", - Content = sliders.Count().ToString(), - Icon = FontAwesome.fa_circle - }, - new BeatmapStatistic - { - Name = @"Spinner Count", - Content = spinners.Count().ToString(), - Icon = FontAwesome.fa_circle - } - }; - } - public override IEnumerable ConvertLegacyMods(LegacyMods mods) { if (mods.HasFlag(LegacyMods.Nightcore)) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs new file mode 100644 index 0000000000..36f6df7869 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Beatmaps +{ + public class TaikoBeatmap : Beatmap + { + public override IEnumerable GetStatistics() + { + int hits = HitObjects.Count(s => s is Hit); + int drumrolls = HitObjects.Count(s => s is DrumRoll); + int swells = HitObjects.Count(s => s is Swell); + + return new[] + { + new BeatmapStatistic + { + Name = @"Hit Count", + Content = hits.ToString(), + Icon = FontAwesome.fa_circle_o + }, + new BeatmapStatistic + { + Name = @"Drumroll Count", + Content = drumrolls.ToString(), + Icon = FontAwesome.fa_circle + }, + new BeatmapStatistic + { + Name = @"Swell Count", + Content = swells.ToString(), + Icon = FontAwesome.fa_circle + } + }; + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index eeb0fa1871..d40e8dc643 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -197,5 +197,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps } } } + + protected override Beatmap CreateBeatmap() => new TaikoBeatmap(); } } diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index efd6c36ce2..0d3e08154f 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -12,8 +12,12 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; +using osu.Game.Rulesets.Catch; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Select; using osu.Game.Tests.Beatmaps; @@ -72,13 +76,23 @@ namespace osu.Game.Tests.Visual selectBeatmap(testBeatmap); + testBeatmapLabels(ruleset); + // TODO: adjust cases once more info is shown for other gamemodes switch (ruleset) { - case OsuRuleset osu: - testOsuBeatmap(osu); + case OsuRuleset _: testInfoLabels(5); break; + case TaikoRuleset _: + testInfoLabels(5); + break; + case CatchRuleset _: + testInfoLabels(5); + break; + case ManiaRuleset _: + testInfoLabels(4); + break; default: testInfoLabels(2); break; @@ -88,7 +102,7 @@ namespace osu.Game.Tests.Visual testNullBeatmap(); } - private void testOsuBeatmap(OsuRuleset ruleset) + private void testBeatmapLabels(Ruleset ruleset) { AddAssert("check version", () => infoWedge.Info.VersionLabel.Text == $"{ruleset.ShortName}Version"); AddAssert("check title", () => infoWedge.Info.TitleLabel.Text == $"{ruleset.ShortName}Source — {ruleset.ShortName}Title"); @@ -138,7 +152,7 @@ namespace osu.Game.Tests.Visual { List objects = new List(); for (double i = 0; i < 50000; i += 1000) - objects.Add(new HitObject { StartTime = i }); + objects.Add(new TestHitObject { StartTime = i }); return new Beatmap { @@ -153,7 +167,8 @@ namespace osu.Game.Tests.Visual }, Ruleset = ruleset, StarDifficulty = 6, - Version = $"{ruleset.ShortName}Version" + Version = $"{ruleset.ShortName}Version", + BaseDifficulty = new BeatmapDifficulty() }, HitObjects = objects }; @@ -163,5 +178,12 @@ namespace osu.Game.Tests.Visual { public new BufferedWedgeInfo Info => base.Info; } + + private class TestHitObject : HitObject, IHasPosition + { + public float X { get; } = 0; + public float Y { get; } = 0; + public Vector2 Position { get; } = Vector2.Zero; + } } } diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 2df0547175..84897853d8 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -51,6 +51,8 @@ namespace osu.Game.Beatmaps IEnumerable IBeatmap.HitObjects => HitObjects; + public virtual IEnumerable GetStatistics() => Enumerable.Empty(); + IBeatmap IBeatmap.Clone() => Clone(); public Beatmap Clone() diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index 4676f056fa..fe20bce98a 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -41,6 +41,12 @@ namespace osu.Game.Beatmaps /// IEnumerable HitObjects { get; } + /// + /// Returns statistics for the contained in this beatmap. + /// + /// + IEnumerable GetStatistics(); + /// /// Creates a shallow-clone of this beatmap and returns it. /// diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index d6d1d19628..6883d319f4 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -22,8 +22,6 @@ namespace osu.Game.Rulesets { public readonly RulesetInfo RulesetInfo; - public virtual IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { }; - public IEnumerable GetAllMods() => Enum.GetValues(typeof(ModType)).Cast() // Confine all mods of each mod type into a single IEnumerable .SelectMany(GetModsFor) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index da82a49f51..236b1310e1 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -4,9 +4,11 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -21,6 +23,8 @@ using osu.Game.Rulesets.Objects.Types; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; +using osu.Game.Rulesets; +using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Select { @@ -28,6 +32,8 @@ namespace osu.Game.Screens.Select { private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0); + private readonly IBindable ruleset = new Bindable(); + protected BufferedWedgeInfo Info; public BeatmapInfoWedge() @@ -46,6 +52,14 @@ namespace osu.Game.Screens.Select }; } + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] OsuGame osuGame) + { + if (osuGame != null) + ruleset.BindTo(osuGame.Ruleset); + ruleset.ValueChanged += updateRuleset; + } + protected override bool BlockPassThroughMouse => false; protected override void PopIn() @@ -62,9 +76,19 @@ namespace osu.Game.Screens.Select this.FadeOut(500, Easing.In); } + private WorkingBeatmap beatmap; + public void UpdateBeatmap(WorkingBeatmap beatmap) { - LoadComponentAsync(new BufferedWedgeInfo(beatmap) + this.beatmap = beatmap; + loadBeatmap(); + } + + private void updateRuleset(RulesetInfo ruleset) => loadBeatmap(); + + private void loadBeatmap() + { + LoadComponentAsync(new BufferedWedgeInfo(beatmap, ruleset.Value) { Shear = -Shear, Depth = Info?.Depth + 1 ?? 0, @@ -90,9 +114,13 @@ namespace osu.Game.Screens.Select private UnicodeBindableString titleBinding; private UnicodeBindableString artistBinding; - public BufferedWedgeInfo(WorkingBeatmap working) + private readonly RulesetInfo ruleset; + + public BufferedWedgeInfo(WorkingBeatmap working, RulesetInfo userRuleset) { this.working = working; + + ruleset = userRuleset ?? working.BeatmapInfo.Ruleset; } [BackgroundDependencyLoader] @@ -211,7 +239,6 @@ namespace osu.Game.Screens.Select private InfoLabel[] getInfoLabels() { var beatmap = working.Beatmap; - var info = working.BeatmapInfo; List labels = new List(); @@ -234,8 +261,20 @@ namespace osu.Game.Screens.Select Content = getBPMRange(beatmap), })); - //get statistics from the current ruleset. - labels.AddRange(info.Ruleset.CreateInstance().GetBeatmapStatistics(working).Select(s => new InfoLabel(s))); + IBeatmap playableBeatmap; + + try + { + // Try to get the beatmap with the user's ruleset + playableBeatmap = working.GetPlayableBeatmap(ruleset); + } + catch (BeatmapInvalidForRulesetException) + { + // Can't be converted to the user's ruleset, so use the beatmap's own ruleset + playableBeatmap = working.GetPlayableBeatmap(working.BeatmapInfo.Ruleset); + } + + labels.AddRange(playableBeatmap.GetStatistics().Select(s => new InfoLabel(s))); } return labels.ToArray();