From 78a7564acd527ad54ee71cbaf003022b5b7c9630 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 24 Mar 2018 16:00:18 -0700 Subject: [PATCH 001/302] Score multiplier edits --- .../Mods/ManiaModDualStages.cs | 2 +- .../Mods/ManiaModRandom.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 2 +- osu.Game.Tests/Visual/TestCaseMods.cs | 11 ++++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 31 ++++++++++++++++--- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 +- osu.Game/Rulesets/Mods/ModRelax.cs | 2 +- 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs index a1f9e0290e..949a2c950c 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Mods public override string Name => "Dual Stages"; public override string ShortenedName => "DS"; public override string Description => @"Double the stages, double the fun!"; - public override double ScoreMultiplier => 0; + public override double ScoreMultiplier => 1; public void ApplyToBeatmapConverter(BeatmapConverter beatmapConverter) { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs index df0f9a5437..dd528cb163 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Mods public override string ShortenedName => "RD"; public override FontAwesome Icon => FontAwesome.fa_osu_dice; public override string Description => @"Shuffle around the keys!"; - public override double ScoreMultiplier => 0; + public override double ScoreMultiplier => 1; public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index 0c842143e4..c78274e453 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string ShortenedName => "AP"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot; public override string Description => @"Automatic cursor movement - just follow the rhythm."; - public override double ScoreMultiplier => 0; + public override double ScoreMultiplier => 1; public override bool Ranked => false; public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) }; } diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index 039d8bfdb6..4f841d3ee2 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual private void testManiaMods(ManiaRuleset ruleset) { - testMultiplierTextUnranked(ruleset.GetModsFor(ModType.Special).First(m => m is ManiaModRandom)); + testRankedTextUnranked(ruleset.GetModsFor(ModType.Special).First(m => m is ManiaModRandom)); } private void testSingleMod(Mod mod) @@ -182,13 +182,13 @@ namespace osu.Game.Tests.Visual checkLabelColor(Color4.White); } - private void testMultiplierTextUnranked(Mod mod) + private void testRankedTextUnranked(Mod mod) { - AddAssert("check for ranked", () => !modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix)); + AddAssert("check for ranked", () => !modSelect.RankedLabel.Text.EndsWith(unranked_suffix)); selectNext(mod); - AddAssert("check for unranked", () => modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix)); + AddAssert("check for unranked", () => modSelect.RankedLabel.Text.EndsWith(unranked_suffix)); selectPrevious(mod); - AddAssert("check for ranked", () => !modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix)); + AddAssert("check for ranked", () => !modSelect.RankedLabel.Text.EndsWith(unranked_suffix)); } private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1)); @@ -224,6 +224,7 @@ namespace osu.Game.Tests.Visual } public new OsuSpriteText MultiplierLabel => base.MultiplierLabel; + public new OsuSpriteText RankedLabel => base.RankedLabel; public new TriangleButton DeselectAllButton => base.DeselectAllButton; public new Color4 LowMultiplierColour => base.LowMultiplierColour; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index d8c95da94f..21c1082191 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -27,10 +27,11 @@ namespace osu.Game.Overlays.Mods { private const float content_width = 0.8f; - protected Color4 LowMultiplierColour, HighMultiplierColour; + protected Color4 LowMultiplierColour, HighMultiplierColour, RankedColour; protected readonly TriangleButton DeselectAllButton; protected readonly OsuSpriteText MultiplierLabel; + protected readonly OsuSpriteText RankedLabel; private readonly FillFlowContainer footerContainer; protected override bool BlockPassThroughKeyboard => false; @@ -55,8 +56,9 @@ namespace osu.Game.Overlays.Mods { SelectedMods.ValueChanged += selectedModsChanged; - LowMultiplierColour = colours.Red; + LowMultiplierColour = colours.Yellow; HighMultiplierColour = colours.Green; + RankedColour = colours.Red; if (osu != null) Ruleset.BindTo(osu.Ruleset); @@ -98,15 +100,24 @@ namespace osu.Game.Overlays.Mods } MultiplierLabel.Text = $"{multiplier:N2}x"; - if (!ranked) - MultiplierLabel.Text += " (Unranked)"; - if (multiplier > 1.0) MultiplierLabel.FadeColour(HighMultiplierColour, 200); else if (multiplier < 1.0) MultiplierLabel.FadeColour(LowMultiplierColour, 200); else MultiplierLabel.FadeColour(Color4.White, 200); + + RankedLabel.Text = null; + if (!ranked) + { + RankedLabel.Text += " (Unranked)"; + RankedLabel.FadeColour(RankedColour, 200); + } + else + { + RankedLabel.Text = null; + RankedLabel.FadeColour(Color4.White, 200); + } } protected override void PopOut() @@ -362,6 +373,16 @@ namespace osu.Game.Overlays.Mods } }, MultiplierLabel = new OsuSpriteText + { + Font = @"Exo2.0-Bold", + TextSize = 30, + Shadow = true, + Margin = new MarginPadding + { + Top = 5 + } + }, + RankedLabel = new OsuSpriteText { Font = @"Exo2.0-Bold", TextSize = 30, diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 9f45cada7e..8ab12cd30f 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mods public override string ShortenedName => "AT"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto; public override string Description => "Watch a perfect automated play through the song."; - public override double ScoreMultiplier => 0; + public override double ScoreMultiplier => 1; public bool AllowFail => false; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; } diff --git a/osu.Game/Rulesets/Mods/ModRelax.cs b/osu.Game/Rulesets/Mods/ModRelax.cs index e8328c3ac7..071f5d5a66 100644 --- a/osu.Game/Rulesets/Mods/ModRelax.cs +++ b/osu.Game/Rulesets/Mods/ModRelax.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "Relax"; public override string ShortenedName => "RX"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax; - public override double ScoreMultiplier => 0; + public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModNoFail), typeof(ModSuddenDeath) }; } } From 90d763fda51b8a5255179ee41ec466ebb9e1cc4b Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Mar 2018 10:00:30 -0700 Subject: [PATCH 002/302] Apply review changes and suggestions --- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 1 - osu.Game.Tests/Visual/TestCaseMods.cs | 12 ++++----- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 27 ++++++++++++------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index c78274e453..b5e9540eae 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -14,7 +14,6 @@ namespace osu.Game.Rulesets.Osu.Mods public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot; public override string Description => @"Automatic cursor movement - just follow the rhythm."; public override double ScoreMultiplier => 1; - public override bool Ranked => false; public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) }; } } diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index 4f841d3ee2..b194462a96 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual [Description("mod select and icon display")] public class TestCaseMods : OsuTestCase { - private const string unranked_suffix = " (Unranked)"; + private const string unranked_suffix = "(Unranked)"; private RulesetStore rulesets; private ModDisplay modDisplay; @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual private void testManiaMods(ManiaRuleset ruleset) { - testRankedTextUnranked(ruleset.GetModsFor(ModType.Special).First(m => m is ManiaModRandom)); + testRankedText(ruleset.GetModsFor(ModType.Special).First(m => m is ManiaModRandom)); } private void testSingleMod(Mod mod) @@ -182,13 +182,13 @@ namespace osu.Game.Tests.Visual checkLabelColor(Color4.White); } - private void testRankedTextUnranked(Mod mod) + private void testRankedText(Mod mod) { - AddAssert("check for ranked", () => !modSelect.RankedLabel.Text.EndsWith(unranked_suffix)); + AddAssert("check for ranked", () => !modSelect.RankedLabel.Text.Equals(unranked_suffix)); selectNext(mod); - AddAssert("check for unranked", () => modSelect.RankedLabel.Text.EndsWith(unranked_suffix)); + AddAssert("check for unranked", () => modSelect.RankedLabel.Text.Equals(unranked_suffix)); selectPrevious(mod); - AddAssert("check for ranked", () => !modSelect.RankedLabel.Text.EndsWith(unranked_suffix)); + AddAssert("check for ranked", () => !modSelect.RankedLabel.Text.Equals(unranked_suffix)); } private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1)); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 21c1082191..604e683917 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -30,6 +30,7 @@ namespace osu.Game.Overlays.Mods protected Color4 LowMultiplierColour, HighMultiplierColour, RankedColour; protected readonly TriangleButton DeselectAllButton; + protected readonly OsuSpriteText ScoreLabel; protected readonly OsuSpriteText MultiplierLabel; protected readonly OsuSpriteText RankedLabel; private readonly FillFlowContainer footerContainer; @@ -56,9 +57,9 @@ namespace osu.Game.Overlays.Mods { SelectedMods.ValueChanged += selectedModsChanged; - LowMultiplierColour = colours.Yellow; + LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; - RankedColour = colours.Red; + RankedColour = colours.Blue; if (osu != null) Ruleset.BindTo(osu.Ruleset); @@ -99,6 +100,14 @@ namespace osu.Game.Overlays.Mods ranked &= mod.Ranked; } + ScoreLabel.Text = "Score Multiplier:"; + if (multiplier > 1.0) + ScoreLabel.FadeColour(HighMultiplierColour, 200); + else if (multiplier < 1.0) + ScoreLabel.FadeColour(LowMultiplierColour, 200); + else + ScoreLabel.FadeColour(Color4.White, 200); + MultiplierLabel.Text = $"{multiplier:N2}x"; if (multiplier > 1.0) MultiplierLabel.FadeColour(HighMultiplierColour, 200); @@ -110,14 +119,11 @@ namespace osu.Game.Overlays.Mods RankedLabel.Text = null; if (!ranked) { - RankedLabel.Text += " (Unranked)"; + RankedLabel.Text = "(Unranked)"; RankedLabel.FadeColour(RankedColour, 200); } else - { - RankedLabel.Text = null; RankedLabel.FadeColour(Color4.White, 200); - } } protected override void PopOut() @@ -362,14 +368,14 @@ namespace osu.Game.Overlays.Mods Right = 20 } }, - new OsuSpriteText + ScoreLabel = new OsuSpriteText { - Text = @"Score Multiplier: ", TextSize = 30, Shadow = true, Margin = new MarginPadding { - Top = 5 + Top = 5, + Right = 10 } }, MultiplierLabel = new OsuSpriteText @@ -389,7 +395,8 @@ namespace osu.Game.Overlays.Mods Shadow = true, Margin = new MarginPadding { - Top = 5 + Top = 5, + Left = 10 } } } From ac9527147f1f81cd9fd65911cca8eb833516a78a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 27 Mar 2018 03:05:05 -0700 Subject: [PATCH 003/302] Fix transitioning of unranked label --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 604e683917..37a789190a 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -116,14 +116,13 @@ namespace osu.Game.Overlays.Mods else MultiplierLabel.FadeColour(Color4.White, 200); - RankedLabel.Text = null; + RankedLabel.Text = "(Unranked)"; + RankedLabel.FadeColour(RankedColour, 200); + RankedLabel.FadeOut(200); if (!ranked) { - RankedLabel.Text = "(Unranked)"; - RankedLabel.FadeColour(RankedColour, 200); + RankedLabel.FadeIn(200); } - else - RankedLabel.FadeColour(Color4.White, 200); } protected override void PopOut() From 5457f17e792af7bbcebfc758a40fa73eba427270 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 28 Mar 2018 19:53:15 -0700 Subject: [PATCH 004/302] Clean up code from reviews --- osu.Game.Tests/Visual/TestCaseMods.cs | 9 ++++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 29 +++++++--------------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index b194462a96..73bfe9b7bb 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -184,11 +184,14 @@ namespace osu.Game.Tests.Visual private void testRankedText(Mod mod) { - AddAssert("check for ranked", () => !modSelect.RankedLabel.Text.Equals(unranked_suffix)); + AddWaitStep(1, "wait for fade"); + AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha.Equals(0)); selectNext(mod); - AddAssert("check for unranked", () => modSelect.RankedLabel.Text.Equals(unranked_suffix)); + AddWaitStep(1, "wait for fade"); + AddAssert("check for unranked", () => !modSelect.RankedLabel.Alpha.Equals(0)); selectPrevious(mod); - AddAssert("check for ranked", () => !modSelect.RankedLabel.Text.Equals(unranked_suffix)); + AddWaitStep(1, "wait for fade"); + AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha.Equals(0)); } private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1)); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 37a789190a..f307d4c92f 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -27,12 +27,10 @@ namespace osu.Game.Overlays.Mods { private const float content_width = 0.8f; - protected Color4 LowMultiplierColour, HighMultiplierColour, RankedColour; + protected Color4 LowMultiplierColour, HighMultiplierColour; protected readonly TriangleButton DeselectAllButton; - protected readonly OsuSpriteText ScoreLabel; - protected readonly OsuSpriteText MultiplierLabel; - protected readonly OsuSpriteText RankedLabel; + protected readonly OsuSpriteText MultiplierLabel, RankedLabel; private readonly FillFlowContainer footerContainer; protected override bool BlockPassThroughKeyboard => false; @@ -59,7 +57,6 @@ namespace osu.Game.Overlays.Mods LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; - RankedColour = colours.Blue; if (osu != null) Ruleset.BindTo(osu.Ruleset); @@ -100,14 +97,6 @@ namespace osu.Game.Overlays.Mods ranked &= mod.Ranked; } - ScoreLabel.Text = "Score Multiplier:"; - if (multiplier > 1.0) - ScoreLabel.FadeColour(HighMultiplierColour, 200); - else if (multiplier < 1.0) - ScoreLabel.FadeColour(LowMultiplierColour, 200); - else - ScoreLabel.FadeColour(Color4.White, 200); - MultiplierLabel.Text = $"{multiplier:N2}x"; if (multiplier > 1.0) MultiplierLabel.FadeColour(HighMultiplierColour, 200); @@ -116,13 +105,10 @@ namespace osu.Game.Overlays.Mods else MultiplierLabel.FadeColour(Color4.White, 200); - RankedLabel.Text = "(Unranked)"; - RankedLabel.FadeColour(RankedColour, 200); - RankedLabel.FadeOut(200); - if (!ranked) - { + if (ranked) + RankedLabel.FadeOut(200); + else RankedLabel.FadeIn(200); - } } protected override void PopOut() @@ -367,8 +353,9 @@ namespace osu.Game.Overlays.Mods Right = 20 } }, - ScoreLabel = new OsuSpriteText + new OsuSpriteText { + Text = @"Score Multiplier:", TextSize = 30, Shadow = true, Margin = new MarginPadding @@ -390,7 +377,9 @@ namespace osu.Game.Overlays.Mods RankedLabel = new OsuSpriteText { Font = @"Exo2.0-Bold", + Text = @"(Unranked)", TextSize = 30, + Colour = OsuColour.FromHex(@"66ccff"), Shadow = true, Margin = new MarginPadding { From 1bebda61f8d6bd048f26d60ae5cbd6b2d508eafd Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 31 Mar 2018 10:51:44 -0700 Subject: [PATCH 005/302] Use "==" instead of "equals" --- osu.Game.Tests/Visual/TestCaseMods.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index 73bfe9b7bb..201804fa74 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -185,13 +185,13 @@ namespace osu.Game.Tests.Visual private void testRankedText(Mod mod) { AddWaitStep(1, "wait for fade"); - AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha.Equals(0)); + AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha == 0); selectNext(mod); AddWaitStep(1, "wait for fade"); - AddAssert("check for unranked", () => !modSelect.RankedLabel.Alpha.Equals(0)); + AddAssert("check for unranked", () => !(modSelect.RankedLabel.Alpha == 0)); selectPrevious(mod); AddWaitStep(1, "wait for fade"); - AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha.Equals(0)); + AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha == 0); } private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1)); From e9ec544bf65b929450c4bcd18a4ad63fe14207cb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Apr 2018 02:04:40 +0900 Subject: [PATCH 006/302] Implement joystick keybindings --- osu-framework | 2 +- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 85b3494117..3388ae24ba 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 85b3494117ccef1b396b70957e1cffaba06e2b54 +Subproject commit 3388ae24ba5cc75fc966ab1531f44701e74588a9 diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 379d25313e..81f24d2661 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -223,6 +223,26 @@ namespace osu.Game.Overlays.KeyBinding return true; } + protected override bool OnJoystickPress(InputState state, JoystickPressEventArgs args) + { + if (!HasFocus) + return false; + + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); + finalise(); + + return true; + } + + protected override bool OnJoystickRelease(InputState state, JoystickReleaseEventArgs args) + { + if (!HasFocus) + return base.OnJoystickRelease(state, args); + + finalise(); + return true; + } + private void finalise() { if (bindTarget != null) From c39fb9a200712423e0656ba2ac2170748819ec4b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Apr 2018 20:10:26 +0900 Subject: [PATCH 007/302] Update with framework changes --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 81f24d2661..9cf43c2bde 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -223,7 +223,7 @@ namespace osu.Game.Overlays.KeyBinding return true; } - protected override bool OnJoystickPress(InputState state, JoystickPressEventArgs args) + protected override bool OnJoystickPress(InputState state, Framework.Input.JoystickEventArgs args) { if (!HasFocus) return false; @@ -234,7 +234,7 @@ namespace osu.Game.Overlays.KeyBinding return true; } - protected override bool OnJoystickRelease(InputState state, JoystickReleaseEventArgs args) + protected override bool OnJoystickRelease(InputState state, Framework.Input.JoystickEventArgs args) { if (!HasFocus) return base.OnJoystickRelease(state, args); From ee7db92e6bb5aba9a792b6b84ee3a22ac9e8682c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 3 Apr 2018 21:01:02 -0700 Subject: [PATCH 008/302] Simplify negative equality expression --- osu.Game.Tests/Visual/TestCaseMods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index 201804fa74..8ee3c6e911 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha == 0); selectNext(mod); AddWaitStep(1, "wait for fade"); - AddAssert("check for unranked", () => !(modSelect.RankedLabel.Alpha == 0)); + AddAssert("check for unranked", () => modSelect.RankedLabel.Alpha != 0); selectPrevious(mod); AddWaitStep(1, "wait for fade"); AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha == 0); From dbee936748439445d049ed3ddf6a9d164d2d7429 Mon Sep 17 00:00:00 2001 From: aQaTL Date: Mon, 9 Apr 2018 18:48:47 +0200 Subject: [PATCH 009/302] Allow mapping delete key via alt+delete key combination --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 71c346d404..88005795ff 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -198,18 +198,29 @@ namespace osu.Game.Overlays.KeyBinding if (!HasFocus) return false; + KeyCombination keyCombination = KeyCombination.FromInputState(state); + switch (args.Key) { case Key.Escape: finalise(); return true; case Key.Delete: - bindTarget.UpdateKeyCombination(InputKey.None); - finalise(); - return true; + if (keyCombination.Equals(InputKey.Delete)) + { + bindTarget.UpdateKeyCombination(InputKey.None); + finalise(); + return true; + } + else if (keyCombination.Equals(new[] { InputKey.Alt, InputKey.Delete })) + { + keyCombination = InputKey.Delete; + } + + break; } - bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); + bindTarget.UpdateKeyCombination(keyCombination); if (!isModifier(args.Key)) finalise(); return true; From 38277bff35f5eb945958ecd485be489374dad3fc Mon Sep 17 00:00:00 2001 From: aQaTL Date: Tue, 10 Apr 2018 18:00:22 +0200 Subject: [PATCH 010/302] Changed mapping of deleting key binding to shift+delete --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 88005795ff..63b5e8a7c1 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -200,24 +200,17 @@ namespace osu.Game.Overlays.KeyBinding KeyCombination keyCombination = KeyCombination.FromInputState(state); - switch (args.Key) + if (keyCombination.Equals(InputKey.Escape)) { - case Key.Escape: - finalise(); - return true; - case Key.Delete: - if (keyCombination.Equals(InputKey.Delete)) - { - bindTarget.UpdateKeyCombination(InputKey.None); - finalise(); - return true; - } - else if (keyCombination.Equals(new[] { InputKey.Alt, InputKey.Delete })) - { - keyCombination = InputKey.Delete; - } + finalise(); + return true; + } - break; + if (keyCombination.Equals(new[] { InputKey.Shift, InputKey.Delete })) + { + bindTarget.UpdateKeyCombination(InputKey.None); + finalise(); + return true; } bindTarget.UpdateKeyCombination(keyCombination); From 90beff83f6cabb47a26b4fb031322f9a3ccc2b0d Mon Sep 17 00:00:00 2001 From: aQaTL Date: Wed, 11 Apr 2018 08:07:26 +0200 Subject: [PATCH 011/302] Updated KeyBindingRow sprite text, adjusted KeyBindingOverlay width --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 2 +- osu.Game/Overlays/KeyBindingOverlay.cs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 63b5e8a7c1..6926e3d966 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.KeyBinding }, pressAKey = new OsuSpriteText { - Text = "Press a key to change binding, DEL to delete, ESC to cancel.", + Text = "Press a key to change binding, SHIFT+DEL to delete, ESC to cancel.", Y = height, Margin = new MarginPadding(padding), Alpha = 0, diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index b311ee68c0..3f393851c2 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -12,6 +12,8 @@ namespace osu.Game.Overlays { public class KeyBindingOverlay : SettingsOverlay { + protected const float WIDTH = 430; + protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); [BackgroundDependencyLoader(permitNulls: true)] @@ -21,6 +23,8 @@ namespace osu.Game.Overlays foreach (var ruleset in rulesets.AvailableRulesets) AddSection(new RulesetBindingsSection(ruleset)); + + ContentContainer.Width = WIDTH; } public KeyBindingOverlay() From 1dc8986c22cec2011005cc77f5f6a0d5fa691f55 Mon Sep 17 00:00:00 2001 From: aQaTL Date: Wed, 18 Apr 2018 15:06:03 +0200 Subject: [PATCH 012/302] Switched back to switch --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 6926e3d966..4e06ce8211 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -198,22 +198,25 @@ namespace osu.Game.Overlays.KeyBinding if (!HasFocus) return false; - KeyCombination keyCombination = KeyCombination.FromInputState(state); - - if (keyCombination.Equals(InputKey.Escape)) + switch (args.Key) { - finalise(); - return true; + case Key.Escape: + finalise(); + return true; + case Key.Delete: + { + if (state.Keyboard.ShiftPressed) + { + bindTarget.UpdateKeyCombination(InputKey.None); + finalise(); + return true; + } + + break; + } } - if (keyCombination.Equals(new[] { InputKey.Shift, InputKey.Delete })) - { - bindTarget.UpdateKeyCombination(InputKey.None); - finalise(); - return true; - } - - bindTarget.UpdateKeyCombination(keyCombination); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); if (!isModifier(args.Key)) finalise(); return true; From b5a55a0dcea31751a0fc7ceebc96f53bad87e426 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Apr 2018 18:14:21 +0900 Subject: [PATCH 013/302] Make an interface for beatmaps --- osu.Game/Beatmaps/Beatmap.cs | 118 +++++++++++++--------- osu.Game/Beatmaps/BeatmapConverter.cs | 2 +- osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs | 9 -- osu.Game/Screens/Play/BreakOverlay.cs | 4 +- osu.Game/Tests/Beatmaps/TestBeatmap.cs | 8 +- 5 files changed, 79 insertions(+), 62 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 12a017f68c..541f7f85b6 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -12,24 +12,69 @@ using osu.Game.IO.Serialization.Converters; namespace osu.Game.Beatmaps { + public interface IBeatmap : IJsonSerializable + { + /// + /// This beatmap's info. + /// + BeatmapInfo BeatmapInfo { get; } + + /// + /// This beatmap's metadata. + /// + BeatmapMetadata Metadata { get; } + + /// + /// The control points in this beatmap. + /// + ControlPointInfo ControlPointInfo { get; } + + /// + /// The breaks in this beatmap. + /// + List Breaks { get; } + + /// + /// Total amount of break time in the beatmap. + /// + double TotalBreakTime { get; } + + /// + /// The hitobjects contained by this beatmap. + /// + IEnumerable HitObjects { get; } + + /// + /// Creates a shallow-clone of this beatmap and returns it. + /// + /// The shallow-cloned beatmap. + IBeatmap Clone(); + } + /// /// A Beatmap containing converted HitObjects. /// - public class Beatmap : IJsonSerializable + public class Beatmap : IBeatmap where T : HitObject { - public BeatmapInfo BeatmapInfo = new BeatmapInfo(); - public ControlPointInfo ControlPointInfo = new ControlPointInfo(); - public List Breaks = new List(); + public BeatmapInfo BeatmapInfo { get; set; } = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Artist = @"Unknown", + Title = @"Unknown", + AuthorString = @"Unknown Creator", + }, + Version = @"Normal", + BaseDifficulty = new BeatmapDifficulty() + }; [JsonIgnore] public BeatmapMetadata Metadata => BeatmapInfo?.Metadata ?? BeatmapInfo?.BeatmapSet?.Metadata; - /// - /// The HitObjects this Beatmap contains. - /// - [JsonConverter(typeof(TypedListConverter))] - public List HitObjects = new List(); + public ControlPointInfo ControlPointInfo { get; set; } = new ControlPointInfo(); + + public List Breaks { get; set; } = new List(); /// /// Total amount of break time in the beatmap. @@ -38,51 +83,26 @@ namespace osu.Game.Beatmaps public double TotalBreakTime => Breaks.Sum(b => b.Duration); /// - /// Constructs a new beatmap. + /// The HitObjects this Beatmap contains. /// - /// The original beatmap to use the parameters of. - public Beatmap(Beatmap original = null) - { - BeatmapInfo = original?.BeatmapInfo.DeepClone() ?? BeatmapInfo; - ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo; - Breaks = original?.Breaks ?? Breaks; - HitObjects = original?.HitObjects ?? HitObjects; + [JsonConverter(typeof(TypedListConverter))] + public List HitObjects = new List(); - if (original == null && Metadata == null) - { - // we may have no metadata in cases we weren't sourced from the database. - // let's fill it (and other related fields) so we don't need to null-check it in future usages. - BeatmapInfo = new BeatmapInfo - { - Metadata = new BeatmapMetadata - { - Artist = @"Unknown", - Title = @"Unknown", - AuthorString = @"Unknown Creator", - }, - Version = @"Normal", - BaseDifficulty = new BeatmapDifficulty() - }; - } - } + IEnumerable IBeatmap.HitObjects => HitObjects; + + public Beatmap Clone() => new Beatmap + { + BeatmapInfo = BeatmapInfo.DeepClone(), + ControlPointInfo = ControlPointInfo, + Breaks = Breaks, + HitObjects = HitObjects + }; + + IBeatmap IBeatmap.Clone() => Clone(); } - /// - /// A Beatmap containing un-converted HitObjects. - /// public class Beatmap : Beatmap { - /// - /// Constructs a new beatmap. - /// - /// The original beatmap to use the parameters of. - public Beatmap(Beatmap original) - : base(original) - { - } - - public Beatmap() - { - } + public new Beatmap Clone() => (Beatmap)base.Clone(); } } diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index 153cace187..f46e6abc87 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -37,7 +37,7 @@ namespace osu.Game.Beatmaps public Beatmap Convert(Beatmap original) { // We always operate on a clone of the original beatmap, to not modify it game-wide - return ConvertBeatmap(new Beatmap(original)); + return ConvertBeatmap(original.Clone()); } void IBeatmapConverter.Convert(Beatmap original) => Convert(original); diff --git a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs index eea82dac6d..4daa014804 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs @@ -8,14 +8,5 @@ namespace osu.Game.Beatmaps.Legacy /// public class LegacyBeatmap : Beatmap { - /// - /// Constructs a new beatmap. - /// - /// The original beatmap to use the parameters of. - internal LegacyBeatmap(Beatmap original = null) - : base(original) - { - HitObjects = original?.HitObjects; - } } } diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index b2df996d35..ca252dd6fd 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -18,11 +18,11 @@ namespace osu.Game.Screens.Play private const float remaining_time_container_max_size = 0.3f; private const int vertical_margin = 25; - private List breaks; + private IReadOnlyList breaks; private readonly Container fadeContainer; - public List Breaks + public IReadOnlyList Breaks { get => breaks; set diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index 09a3a7af8c..6bad08baaa 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -12,8 +12,14 @@ namespace osu.Game.Tests.Beatmaps public class TestBeatmap : Beatmap { public TestBeatmap(RulesetInfo ruleset) - : base(createTestBeatmap()) { + var baseBeatmap = createTestBeatmap(); + + BeatmapInfo = baseBeatmap.BeatmapInfo; + ControlPointInfo = baseBeatmap.ControlPointInfo; + Breaks = baseBeatmap.Breaks; + HitObjects = baseBeatmap.HitObjects; + BeatmapInfo.Ruleset = ruleset; } From ac64f9d958be5c2630dbf799b704df1f3d5e56eb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Apr 2018 18:40:01 +0900 Subject: [PATCH 014/302] Remove LegacyBeatmap --- osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs diff --git a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs deleted file mode 100644 index 4daa014804..0000000000 --- a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Beatmaps.Legacy -{ - /// - /// A type of Beatmap loaded from a legacy .osu beatmap file (version <=15). - /// - public class LegacyBeatmap : Beatmap - { - } -} From e666a82e1f01a6b6fc891b7c8b52660752d67cf8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Apr 2018 18:50:21 +0900 Subject: [PATCH 015/302] Fix cloning --- osu.Game/Beatmaps/Beatmap.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 541f7f85b6..7066432c5c 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -90,19 +90,19 @@ namespace osu.Game.Beatmaps IEnumerable IBeatmap.HitObjects => HitObjects; - public Beatmap Clone() => new Beatmap - { - BeatmapInfo = BeatmapInfo.DeepClone(), - ControlPointInfo = ControlPointInfo, - Breaks = Breaks, - HitObjects = HitObjects - }; - IBeatmap IBeatmap.Clone() => Clone(); + + public Beatmap Clone() + { + var newInstance = (Beatmap)MemberwiseClone(); + newInstance.BeatmapInfo = BeatmapInfo.DeepClone(); + + return newInstance; + } } public class Beatmap : Beatmap { - public new Beatmap Clone() => (Beatmap)base.Clone(); + public Beatmap Clone() => (Beatmap)base.Clone(); } } From 7a550e3f071f40ceded70e0dcebad8d99670ddac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Apr 2018 20:20:56 +0900 Subject: [PATCH 016/302] Revert unnecessary change for now --- osu.Game/Screens/Play/BreakOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index ca252dd6fd..b2df996d35 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -18,11 +18,11 @@ namespace osu.Game.Screens.Play private const float remaining_time_container_max_size = 0.3f; private const int vertical_margin = 25; - private IReadOnlyList breaks; + private List breaks; private readonly Container fadeContainer; - public IReadOnlyList Breaks + public List Breaks { get => breaks; set From 66b3b295e74860fe60a105decfc742732bf87256 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Apr 2018 20:44:38 +0900 Subject: [PATCH 017/302] Use IBeatmap wherever possible --- .../CatchBeatmapConversionTest.cs | 2 +- .../TestCaseAutoJuiceStream.cs | 2 +- .../TestCaseBananaShower.cs | 2 +- .../TestCaseCatchStacker.cs | 2 +- osu.Game.Rulesets.Catch.Tests/TestCaseHyperdash.cs | 2 +- .../Beatmaps/CatchBeatmapConverter.cs | 2 +- .../CatchDifficultyCalculator.cs | 4 ++-- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../Replays/CatchReplayFrame.cs | 2 +- .../ManiaBeatmapConversionTest.cs | 2 +- .../Beatmaps/ManiaBeatmapConverter.cs | 14 +++++++------- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- .../Legacy/EndTimeObjectPatternGenerator.cs | 2 +- .../Patterns/Legacy/HitObjectPatternGenerator.cs | 2 +- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 6 +++--- .../ManiaDifficultyCalculator.cs | 6 +++--- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Replays/ManiaReplayFrame.cs | 2 +- .../OsuBeatmapConversionTest.cs | 2 +- .../Beatmaps/OsuBeatmapConverter.cs | 2 +- .../OsuDifficulty/OsuDifficultyCalculator.cs | 6 +++--- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++-- osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs | 2 +- .../Scoring/OsuPerformanceCalculator.cs | 2 +- .../TaikoBeatmapConversionTest.cs | 2 +- .../Beatmaps/TaikoBeatmapConverter.cs | 4 ++-- .../Replays/TaikoReplayFrame.cs | 2 +- .../TaikoDifficultyCalculator.cs | 4 ++-- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 8 ++++---- osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs | 4 ++-- .../Visual/TestCaseEditorSeekSnapping.cs | 2 +- osu.Game/Beatmaps/Beatmap.cs | 2 +- osu.Game/Beatmaps/BeatmapConverter.cs | 12 ++++++------ osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/DifficultyCalculator.cs | 4 ++-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 4 ++-- osu.Game/Beatmaps/IBeatmapConverter.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 12 ++++++------ .../Replays/Types/IConvertibleReplayFrame.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 4 ++-- .../Rulesets/Scoring/Legacy/LegacyScoreParser.cs | 2 +- osu.Game/Rulesets/Scoring/PerformanceCalculator.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 6 +++--- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 4 ++-- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 6 +++--- osu.Game/Tests/Visual/TestCasePerformancePoints.cs | 4 ++-- osu.Game/Tests/Visual/TestCasePlayer.cs | 2 +- 50 files changed, 89 insertions(+), 89 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index bd0cc209b6..bf373867e8 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Catch.Tests } } - protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new CatchBeatmapConverter(); + protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new CatchBeatmapConverter(); } public struct ConvertValue : IEquatable diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs index bce20520d3..097750d7e0 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Tests { } - protected override Beatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(Ruleset ruleset) { var beatmap = new Beatmap { diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs index d13a6bb860..b5cf0e3d1d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Tests { } - protected override Beatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(Ruleset ruleset) { var beatmap = new Beatmap { diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs index 2b58fcc93c..8a90b48180 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Tests { } - protected override Beatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(Ruleset ruleset) { var beatmap = new Beatmap { diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseHyperdash.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseHyperdash.cs index e7f936ca2a..896582bf0a 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseHyperdash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseHyperdash.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Tests { } - protected override Beatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(Ruleset ruleset) { var beatmap = new Beatmap { BeatmapInfo = { Ruleset = ruleset.RulesetInfo } }; diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 34e5f425fd..b1b101e797 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; - protected override IEnumerable ConvertHitObject(HitObject obj, Beatmap beatmap) + protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) { var curveData = obj as IHasCurve; var positionData = obj as IHasXPosition; diff --git a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs index 876b394da0..626a3d186a 100644 --- a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs @@ -10,12 +10,12 @@ namespace osu.Game.Rulesets.Catch { public class CatchDifficultyCalculator : DifficultyCalculator { - public CatchDifficultyCalculator(Beatmap beatmap) : base(beatmap) + public CatchDifficultyCalculator(IBeatmap beatmap) : base(beatmap) { } public override double Calculate(Dictionary categoryDifficulty = null) => 0; - protected override BeatmapConverter CreateBeatmapConverter(Beatmap beatmap) => new CatchBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(); } } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index cfe0fc5cec..e2cb7b1d9b 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Catch public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o }; - public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap); + public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap); public override int? LegacyID => 2; diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs index d63d1bd331..d5c5eb844a 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Replays Dashing = dashing; } - public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap) + public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) { Position = legacyFrame.Position.X / CatchPlayfield.BASE_WIDTH; Dashing = legacyFrame.ButtonState == ReplayButtonState.Left1; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 81c537e53c..fb1fce4279 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Tests }; } - protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new ManiaBeatmapConverter(isForCurrentRuleset, beatmap); + protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(isForCurrentRuleset, beatmap); } public struct ConvertValue : IEquatable diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 60b92cb7b3..a142db8fed 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private ManiaBeatmap beatmap; - public ManiaBeatmapConverter(bool isForCurrentRuleset, Beatmap original) + public ManiaBeatmapConverter(bool isForCurrentRuleset, IBeatmap original) { IsForCurrentRuleset = isForCurrentRuleset; @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps TargetColumns = (int)Math.Max(1, roundedCircleSize); else { - float percentSliderOrSpinner = (float)original.HitObjects.Count(h => h is IHasEndTime) / original.HitObjects.Count; + float percentSliderOrSpinner = (float)original.HitObjects.Count(h => h is IHasEndTime) / original.HitObjects.Count(); if (percentSliderOrSpinner < 0.2) TargetColumns = 7; else if (percentSliderOrSpinner < 0.3 || roundedCircleSize >= 5) @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps } } - protected override Beatmap ConvertBeatmap(Beatmap original) + protected override Beatmap ConvertBeatmap(IBeatmap original) { BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override Beatmap CreateBeatmap() => beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns }); - protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) + protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) { var maniaOriginal = original as ManiaHitObject; if (maniaOriginal != null) @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// The original hit object. /// The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap. /// The hit objects generated. - private IEnumerable generateSpecific(HitObject original, Beatmap originalBeatmap) + private IEnumerable generateSpecific(HitObject original, IBeatmap originalBeatmap) { var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern, originalBeatmap); @@ -128,7 +128,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// The original hit object. /// The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap. /// The hit objects generated. - private IEnumerable generateConverted(HitObject original, Beatmap originalBeatmap) + private IEnumerable generateConverted(HitObject original, IBeatmap originalBeatmap) { var endTimeData = original as IHasEndTime; var distanceData = original as IHasDistance; @@ -165,7 +165,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator { - public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap) + public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 3b5c028bfd..afa9bdbbd7 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private PatternType convertType; - public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap) + public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { convertType = PatternType.None; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 743e230cb2..3f34afee85 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { private readonly double endTime; - public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Beatmap originalBeatmap) + public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, new Pattern(), originalBeatmap) { var endtimeData = HitObject as IHasEndTime; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 652c92dd78..cec3e18ad6 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private readonly PatternType convertType; - public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, Beatmap originalBeatmap) + public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime)); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index 02306846a3..930597c1ad 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -28,9 +28,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// /// The beatmap which is being converted from. /// - protected readonly Beatmap OriginalBeatmap; + protected readonly IBeatmap OriginalBeatmap; - protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap) + protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(hitObject, beatmap, previousPattern) { if (random == null) throw new ArgumentNullException(nameof(random)); @@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy drainTime /= 1000; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; - conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; + conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + OriginalBeatmap.HitObjects.Count() / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); return conversionDifficulty.Value; diff --git a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs index 5eea346836..24fe72faec 100644 --- a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs @@ -31,12 +31,12 @@ namespace osu.Game.Rulesets.Mania /// private readonly List difficultyHitObjects = new List(); - public ManiaDifficultyCalculator(Beatmap beatmap) + public ManiaDifficultyCalculator(IBeatmap beatmap) : base(beatmap) { } - public ManiaDifficultyCalculator(Beatmap beatmap, Mod[] mods) + public ManiaDifficultyCalculator(IBeatmap beatmap, Mod[] mods) : base(beatmap, mods) { } @@ -141,6 +141,6 @@ namespace osu.Game.Rulesets.Mania return difficulty; } - protected override BeatmapConverter CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, beatmap); + protected override BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(true, beatmap); } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 0546cbc174..d5bf1b30fc 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -182,7 +182,7 @@ namespace osu.Game.Rulesets.Mania public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o }; - public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap, mods); + public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap, mods); public override int? LegacyID => 3; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 8d86325dd9..926a3a8923 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap) + public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) { // We don't need to fully convert, just create the converter var converter = new ManiaBeatmapConverter(beatmap.BeatmapInfo.RulesetID == 3, beatmap); diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index 6ac3c016a0..a77b20e83b 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Tests }; } - protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new OsuBeatmapConverter(); + protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new OsuBeatmapConverter(); } public struct ConvertValue : IEquatable diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 1236076f48..b1a52c5469 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasPosition) }; - protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) + protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) { var curveData = original as IHasCurve; var endTimeData = original as IHasEndTime; diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs index 926a7975f3..197bc16fc1 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs @@ -17,12 +17,12 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty private const int section_length = 400; private const double difficulty_multiplier = 0.0675; - public OsuDifficultyCalculator(Beatmap beatmap) + public OsuDifficultyCalculator(IBeatmap beatmap) : base(beatmap) { } - public OsuDifficultyCalculator(Beatmap beatmap, Mod[] mods) + public OsuDifficultyCalculator(IBeatmap beatmap, Mod[] mods) : base(beatmap, mods) { } @@ -73,6 +73,6 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty return starRating; } - protected override BeatmapConverter CreateBeatmapConverter(Beatmap beatmap) => new OsuBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(); } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index e0ecee97a3..ed750882f4 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -181,9 +181,9 @@ namespace osu.Game.Rulesets.Osu public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o }; - public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods); + public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods); - public override PerformanceCalculator CreatePerformanceCalculator(Beatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score); + public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score); public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this); diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs index 6f2512cc33..4412b6efab 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap) + public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) { Position = legacyFrame.Position; if (legacyFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index 8f0feca207..c8806cbdb1 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Scoring private int count50; private int countMiss; - public OsuPerformanceCalculator(Ruleset ruleset, Beatmap beatmap, Score score) + public OsuPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) : base(ruleset, beatmap, score) { countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index aa61f2d60b..3d236af8ad 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Taiko.Tests }; } - protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new TaikoBeatmapConverter(isForCurrentRuleset); + protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(isForCurrentRuleset); } public struct ConvertValue : IEquatable diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 2f175a9922..eabe7eb91a 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps this.isForCurrentRuleset = isForCurrentRuleset; } - protected override Beatmap ConvertBeatmap(Beatmap original) + protected override Beatmap ConvertBeatmap(IBeatmap original) { // Rewrite the beatmap info to add the slider velocity multiplier BeatmapInfo info = original.BeatmapInfo.DeepClone(); @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps return converted; } - protected override IEnumerable ConvertHitObject(HitObject obj, Beatmap beatmap) + protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) { var distanceData = obj as IHasDistance; var repeatsData = obj as IHasRepeats; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs index e510b34ad7..2177a3cbdc 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap) + public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) { if (legacyFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); if (legacyFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); diff --git a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs index 58661d7881..66b8459d1f 100644 --- a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko /// private readonly List difficultyHitObjects = new List(); - public TaikoDifficultyCalculator(Beatmap beatmap) + public TaikoDifficultyCalculator(IBeatmap beatmap) : base(beatmap) { } @@ -133,6 +133,6 @@ namespace osu.Game.Rulesets.Taiko return difficulty; } - protected override BeatmapConverter CreateBeatmapConverter(Beatmap beatmap) => new TaikoBeatmapConverter(true); + protected override BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(true); } } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 06a8e44a14..e5f3b33355 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -140,7 +140,7 @@ namespace osu.Game.Rulesets.Taiko public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o }; - public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap); + public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap); public override int? LegacyID => 1; diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 6453cdbd3e..f60caf2397 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -275,13 +275,13 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID)); Assert.IsTrue(set.Beatmaps.Count > 0); var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; - Assert.IsTrue(beatmap?.HitObjects.Count > 0); + Assert.IsTrue(beatmap?.HitObjects.Any() == true); beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap; - Assert.IsTrue(beatmap?.HitObjects.Count > 0); + Assert.IsTrue(beatmap?.HitObjects.Any() == true); beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap; - Assert.IsTrue(beatmap?.HitObjects.Count > 0); + Assert.IsTrue(beatmap?.HitObjects.Any() == true); beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap; - Assert.IsTrue(beatmap?.HitObjects.Count > 0); + Assert.IsTrue(beatmap?.HitObjects.Any() == true); } private void waitForOrAssert(Func result, string failureMessage, int timeout = 60000) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index 790c4cedc3..0c5c5dba22 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual { private RulesetStore rulesets; private TestBeatmapInfoWedge infoWedge; - private readonly List beatmaps = new List(); + private readonly List beatmaps = new List(); private readonly Bindable beatmap = new Bindable(); [BackgroundDependencyLoader] @@ -130,7 +130,7 @@ namespace osu.Game.Tests.Visual }); } - private Beatmap createTestBeatmap(RulesetInfo ruleset) + private IBeatmap createTestBeatmap(RulesetInfo ruleset) { List objects = new List(); for (double i = 0; i < 50000; i += 1000) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs b/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs index 582ab5ecc9..f037d70493 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs @@ -332,7 +332,7 @@ namespace osu.Game.Tests.Visual private readonly Drawable tracker; - public TimingPointVisualiser(Beatmap beatmap, double length) + public TimingPointVisualiser(IBeatmap beatmap, double length) { this.length = length; diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 7066432c5c..6a7d2690ff 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -17,7 +17,7 @@ namespace osu.Game.Beatmaps /// /// This beatmap's info. /// - BeatmapInfo BeatmapInfo { get; } + BeatmapInfo BeatmapInfo { get; set; } /// /// This beatmap's metadata. diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index f46e6abc87..fab7860077 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -27,27 +27,27 @@ namespace osu.Game.Beatmaps /// /// The Beatmap to check. /// Whether the Beatmap can be converted using this Beatmap Converter. - public bool CanConvert(Beatmap beatmap) => ValidConversionTypes.All(t => beatmap.HitObjects.Any(t.IsInstanceOfType)); + public bool CanConvert(IBeatmap beatmap) => ValidConversionTypes.All(t => beatmap.HitObjects.Any(t.IsInstanceOfType)); /// /// Converts a Beatmap using this Beatmap Converter. /// /// The un-converted Beatmap. /// The converted Beatmap. - public Beatmap Convert(Beatmap original) + public Beatmap Convert(IBeatmap original) { // We always operate on a clone of the original beatmap, to not modify it game-wide return ConvertBeatmap(original.Clone()); } - void IBeatmapConverter.Convert(Beatmap original) => Convert(original); + void IBeatmapConverter.Convert(IBeatmap original) => Convert(original); /// /// Performs the conversion of a Beatmap using this Beatmap Converter. /// /// The un-converted Beatmap. /// The converted Beatmap. - protected virtual Beatmap ConvertBeatmap(Beatmap original) + protected virtual Beatmap ConvertBeatmap(IBeatmap original) { var beatmap = CreateBeatmap(); @@ -67,7 +67,7 @@ namespace osu.Game.Beatmaps /// The hit object to convert. /// The un-converted Beatmap. /// The converted hit object. - private IEnumerable convert(HitObject original, Beatmap beatmap) + private IEnumerable convert(HitObject original, IBeatmap beatmap) { // Check if the hitobject is already the converted type T tObject = original as T; @@ -107,6 +107,6 @@ namespace osu.Game.Beatmaps /// The hit object to convert. /// The un-converted Beatmap. /// The converted hit object. - protected abstract IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap); + protected abstract IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap); } } diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 645e52a6c6..14436fce13 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -333,7 +333,7 @@ namespace osu.Game.Beatmaps ms.Position = 0; var decoder = Decoder.GetDecoder(sr); - Beatmap beatmap = decoder.Decode(sr); + IBeatmap beatmap = decoder.Decode(sr); beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 8e09d66c42..71406c6034 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps this.audioManager = audioManager; } - protected override Beatmap GetBeatmap() + protected override IBeatmap GetBeatmap() { try { diff --git a/osu.Game/Beatmaps/DifficultyCalculator.cs b/osu.Game/Beatmaps/DifficultyCalculator.cs index 5e2d9afd23..bf252ff51f 100644 --- a/osu.Game/Beatmaps/DifficultyCalculator.cs +++ b/osu.Game/Beatmaps/DifficultyCalculator.cs @@ -22,7 +22,7 @@ namespace osu.Game.Beatmaps protected readonly Beatmap Beatmap; protected readonly Mod[] Mods; - protected DifficultyCalculator(Beatmap beatmap, Mod[] mods = null) + protected DifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) { Mods = mods ?? new Mod[0]; @@ -59,6 +59,6 @@ namespace osu.Game.Beatmaps { } - protected abstract BeatmapConverter CreateBeatmapConverter(Beatmap beatmap); + protected abstract BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap); } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 0424ff84f1..0d325284e1 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps this.game = game; } - protected override Beatmap GetBeatmap() => new Beatmap(); + protected override IBeatmap GetBeatmap() => new Beatmap(); protected override Texture GetBackground() => game.Textures.Get(@"Backgrounds/bg4"); @@ -58,7 +58,7 @@ namespace osu.Game.Beatmaps throw new NotImplementedException(); } - public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => null; + public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => null; public override string Description => "dummy"; diff --git a/osu.Game/Beatmaps/IBeatmapConverter.cs b/osu.Game/Beatmaps/IBeatmapConverter.cs index 6c25395a56..4df250ad17 100644 --- a/osu.Game/Beatmaps/IBeatmapConverter.cs +++ b/osu.Game/Beatmaps/IBeatmapConverter.cs @@ -20,6 +20,6 @@ namespace osu.Game.Beatmaps /// Converts a Beatmap using this Beatmap Converter. /// /// The un-converted Beatmap. - void Convert(Beatmap beatmap); + void Convert(IBeatmap beatmap); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 4080e34e81..fc67d2e508 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -36,7 +36,7 @@ namespace osu.Game.Beatmaps Mods.ValueChanged += mods => applyRateAdjustments(); - beatmap = new AsyncLazy(populateBeatmap); + beatmap = new AsyncLazy(populateBeatmap); background = new AsyncLazy(populateBackground, b => b == null || !b.IsDisposed); track = new AsyncLazy(populateTrack); waveform = new AsyncLazy(populateWaveform); @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps Process.Start(path); } - protected abstract Beatmap GetBeatmap(); + protected abstract IBeatmap GetBeatmap(); protected abstract Texture GetBackground(); protected abstract Track GetTrack(); protected virtual Skin GetSkin() => new DefaultSkin(); @@ -63,12 +63,12 @@ namespace osu.Game.Beatmaps protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo }; public bool BeatmapLoaded => beatmap.IsResultAvailable; - public Beatmap Beatmap => beatmap.Value.Result; - public async Task GetBeatmapAsync() => await beatmap.Value; + public IBeatmap Beatmap => beatmap.Value.Result; + public async Task GetBeatmapAsync() => await beatmap.Value; - private readonly AsyncLazy beatmap; + private readonly AsyncLazy beatmap; - private Beatmap populateBeatmap() + private IBeatmap populateBeatmap() { var b = GetBeatmap() ?? new Beatmap(); diff --git a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs index adf35ce078..fdd528f296 100644 --- a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs @@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Replays.Types /// /// The to extract values from. /// The beatmap. - void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap); + void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap); } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index cd1d030afe..3f8512eb90 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -57,9 +57,9 @@ namespace osu.Game.Rulesets /// public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset); - public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null); + public abstract DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null); - public virtual PerformanceCalculator CreatePerformanceCalculator(Beatmap beatmap, Score score) => null; + public virtual PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => null; public virtual HitObjectComposer CreateHitObjectComposer() => null; diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs index 239f200e29..d5ab856697 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Scoring.Legacy this.beatmaps = beatmaps; } - private Beatmap currentBeatmap; + private IBeatmap currentBeatmap; private Ruleset currentRuleset; public Score Parse(Stream stream) diff --git a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs index 0f115fff6b..6392d2c0ae 100644 --- a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Scoring protected readonly Beatmap Beatmap; protected readonly Score Score; - protected PerformanceCalculator(Ruleset ruleset, Beatmap beatmap, Score score) + protected PerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) { Score = score; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ec7c1a1009..32685935a1 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -96,7 +96,7 @@ namespace osu.Game.Screens.Play mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); - Beatmap beatmap; + IBeatmap beatmap; try { diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index f005261ffa..da82a49f51 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -215,7 +215,7 @@ namespace osu.Game.Screens.Select List labels = new List(); - if (beatmap?.HitObjects?.Count > 0) + if (beatmap?.HitObjects?.Any() == true) { HitObject lastObject = beatmap.HitObjects.LastOrDefault(); double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0; @@ -224,7 +224,7 @@ namespace osu.Game.Screens.Select { Name = "Length", Icon = FontAwesome.fa_clock_o, - Content = beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(endTime - beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"), + Content = TimeSpan.FromMilliseconds(endTime - beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"), })); labels.Add(new InfoLabel(new BeatmapStatistic @@ -241,7 +241,7 @@ namespace osu.Game.Screens.Select return labels.ToArray(); } - private string getBPMRange(Beatmap beatmap) + private string getBPMRange(IBeatmap beatmap) { double bpmMax = beatmap.ControlPointInfo.BPMMaximum; double bpmMin = beatmap.ControlPointInfo.BPMMinimum; diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 2850de8ba5..d02ccaff16 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Beatmaps } } - private Beatmap getBeatmap(string name) + private IBeatmap getBeatmap(string name) { using (var resStream = openResource($"{resource_namespace}.{name}.osu")) using (var stream = new StreamReader(resStream)) @@ -125,7 +125,7 @@ namespace osu.Game.Tests.Beatmaps } protected abstract IEnumerable CreateConvertValue(HitObject hitObject); - protected abstract IBeatmapConverter CreateConverter(Beatmap beatmap); + protected abstract IBeatmapConverter CreateConverter(IBeatmap beatmap); private class ConvertMapping { diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index e24fbab3ac..37693c99e8 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -17,14 +17,14 @@ namespace osu.Game.Tests.Beatmaps { } - public TestWorkingBeatmap(Beatmap beatmap) + public TestWorkingBeatmap(IBeatmap beatmap) : base(beatmap.BeatmapInfo) { this.beatmap = beatmap; } - private readonly Beatmap beatmap; - protected override Beatmap GetBeatmap() => beatmap; + private readonly IBeatmap beatmap; + protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; protected override Track GetTrack() diff --git a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs index 29132258c2..51460ecb6d 100644 --- a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs +++ b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs @@ -259,9 +259,9 @@ namespace osu.Game.Tests.Visual private readonly OsuSpriteText text; private readonly Score score; - private readonly Beatmap beatmap; + private readonly IBeatmap beatmap; - public PerformanceDisplay(Score score, Beatmap beatmap) + public PerformanceDisplay(Score score, IBeatmap beatmap) { this.score = score; this.beatmap = beatmap; diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 5ed43b2814..bda438d906 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual } } - protected virtual Beatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); + protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance()); From 03a5df84c6860738ec0723bc83df634d02666085 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Apr 2018 22:04:12 +0900 Subject: [PATCH 018/302] Initial rework of beatmap conversion process --- .../CatchBeatmapConversionTest.cs | 2 +- .../Beatmaps/CatchBeatmapConverter.cs | 5 ++ .../Beatmaps/CatchBeatmapProcessor.cs | 15 +++-- .../CatchDifficultyCalculator.cs | 6 +- osu.Game.Rulesets.Catch/CatchRuleset.cs | 3 + .../Mods/CatchModHardRock.cs | 13 +++-- .../UI/CatchRulesetContainer.cs | 5 -- .../ManiaBeatmapConversionTest.cs | 2 +- .../Beatmaps/ManiaBeatmapConverter.cs | 16 +++--- .../ManiaDifficultyCalculator.cs | 6 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 + osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs | 5 +- .../Mods/ManiaModDualStages.cs | 4 +- .../Replays/ManiaReplayFrame.cs | 2 +- .../UI/ManiaRulesetContainer.cs | 2 - .../OsuBeatmapConversionTest.cs | 2 +- .../Beatmaps/OsuBeatmapConverter.cs | 5 ++ .../Beatmaps/OsuBeatmapProcessor.cs | 13 +++-- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 9 ++- .../OsuDifficulty/OsuDifficultyCalculator.cs | 12 +--- osu.Game.Rulesets.Osu/OsuRuleset.cs | 5 +- .../Scoring/OsuPerformanceCalculator.cs | 7 +-- .../UI/OsuRulesetContainer.cs | 5 -- .../TaikoBeatmapConversionTest.cs | 7 +-- .../Beatmaps/TaikoBeatmapConverter.cs | 5 +- .../TaikoDifficultyCalculator.cs | 7 +-- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 + .../UI/TaikoRulesetContainer.cs | 3 - .../Beatmaps/IO/ImportBeatmapTest.cs | 8 +-- .../Visual/TestCaseBeatSyncedContainer.cs | 2 +- osu.Game/Beatmaps/BeatmapConverter.cs | 32 ++++++----- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/BeatmapProcessor.cs | 29 ++++++++-- osu.Game/Beatmaps/DifficultyCalculator.cs | 34 ++--------- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 13 ++++- osu.Game/Beatmaps/IBeatmapConverter.cs | 12 +++- osu.Game/Beatmaps/WorkingBeatmap.cs | 56 +++++++++++++++---- .../Containers/BeatSyncedContainer.cs | 2 +- osu.Game/Overlays/MusicController.cs | 2 +- .../Mods/IApplicableToBeatmapConverter.cs | 5 +- .../Rulesets/Mods/IApplicableToHitObject.cs | 5 +- osu.Game/Rulesets/Ruleset.cs | 4 ++ .../Scoring/Legacy/LegacyScoreParser.cs | 2 +- .../Rulesets/Scoring/PerformanceCalculator.cs | 20 +------ osu.Game/Rulesets/UI/RulesetContainer.cs | 42 +------------- .../Timelines/Summary/Parts/BreakPart.cs | 2 +- .../Summary/Parts/ControlPointPart.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageScore.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- .../Tests/Beatmaps/BeatmapConversionTest.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 +- osu.Game/Tests/Visual/EditorClockTestCase.cs | 2 +- .../Tests/Visual/TestCasePerformancePoints.cs | 4 +- 56 files changed, 230 insertions(+), 234 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index bf373867e8..a94d29ca2c 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Catch.Tests } } - protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new CatchBeatmapConverter(); + protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); } public struct ConvertValue : IEquatable diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index b1b101e797..3b22c47ac8 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -13,6 +13,11 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { public class CatchBeatmapConverter : BeatmapConverter { + public CatchBeatmapConverter(IBeatmap beatmap) + : base(beatmap) + { + } + protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index dfd10e0df7..e16f5fcb60 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -12,16 +12,21 @@ using OpenTK; namespace osu.Game.Rulesets.Catch.Beatmaps { - public class CatchBeatmapProcessor : BeatmapProcessor + public class CatchBeatmapProcessor : BeatmapProcessor { - public override void PostProcess(Beatmap beatmap) + public CatchBeatmapProcessor(IBeatmap beatmap) + : base(beatmap) { - initialiseHyperDash(beatmap.HitObjects); + } - base.PostProcess(beatmap); + public override void PostProcess() + { + initialiseHyperDash((List)Beatmap.HitObjects); + + base.PostProcess(); int index = 0; - foreach (var obj in beatmap.HitObjects) + foreach (var obj in Beatmap.HitObjects.OfType()) obj.IndexInBeatmap = index++; } diff --git a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs index 626a3d186a..f47d09fe20 100644 --- a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs @@ -2,20 +2,16 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Rulesets.Catch.Beatmaps; -using osu.Game.Rulesets.Catch.Objects; using System.Collections.Generic; namespace osu.Game.Rulesets.Catch { - public class CatchDifficultyCalculator : DifficultyCalculator + public class CatchDifficultyCalculator : DifficultyCalculator { public CatchDifficultyCalculator(IBeatmap beatmap) : base(beatmap) { } public override double Calculate(Dictionary categoryDifficulty = null) => 0; - - protected override BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(); } } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index e2cb7b1d9b..f091fbbee4 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -13,12 +13,15 @@ using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Catch.Beatmaps; namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchRulesetContainer(this, beatmap, isForCurrentRuleset); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); + public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs index df7578799f..8e19c0614a 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs @@ -6,10 +6,11 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Mods; using System; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Catch.Mods { - public class CatchModHardRock : ModHardRock, IApplicableToHitObject + public class CatchModHardRock : ModHardRock, IApplicableToHitObject { public override double ScoreMultiplier => 1.12; public override bool Ranked => true; @@ -17,9 +18,11 @@ namespace osu.Game.Rulesets.Catch.Mods private float lastStartX; private int lastStartTime; - public void ApplyToHitObject(CatchHitObject hitObject) + public void ApplyToHitObject(HitObject hitObject) { - float position = hitObject.X; + var catchObject = (CatchHitObject)hitObject; + + float position = catchObject.X; int startTime = (int)hitObject.StartTime; if (lastStartX == 0) @@ -60,7 +63,7 @@ namespace osu.Game.Rulesets.Catch.Mods position += rand; } - hitObject.X = position; + catchObject.X = position; return; } @@ -79,7 +82,7 @@ namespace osu.Game.Rulesets.Catch.Mods } } - hitObject.X = position; + catchObject.X = position; lastStartX = position; lastStartTime = startTime; diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 022a8a8b43..6e8a2c1660 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -4,7 +4,6 @@ using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Input.Handlers; -using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Replays; @@ -29,10 +28,6 @@ namespace osu.Game.Rulesets.Catch.UI protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay); - protected override BeatmapProcessor CreateBeatmapProcessor() => new CatchBeatmapProcessor(); - - protected override BeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); - protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation); public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index fb1fce4279..e52fc11518 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Tests }; } - protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(isForCurrentRuleset, beatmap); + protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); } public struct ConvertValue : IEquatable diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index a142db8fed..93feddc143 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -33,18 +33,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private ManiaBeatmap beatmap; - public ManiaBeatmapConverter(bool isForCurrentRuleset, IBeatmap original) + public ManiaBeatmapConverter(IBeatmap beatmap) + : base(beatmap) { - IsForCurrentRuleset = isForCurrentRuleset; + IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo); + + var roundedCircleSize = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize); + var roundedOverallDifficulty = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); - var roundedCircleSize = Math.Round(original.BeatmapInfo.BaseDifficulty.CircleSize); - var roundedOverallDifficulty = Math.Round(original.BeatmapInfo.BaseDifficulty.OverallDifficulty); - - if (isForCurrentRuleset) + if (beatmap.BeatmapInfo.Ruleset == new ManiaRuleset().RulesetInfo) TargetColumns = (int)Math.Max(1, roundedCircleSize); else { - float percentSliderOrSpinner = (float)original.HitObjects.Count(h => h is IHasEndTime) / original.HitObjects.Count(); + float percentSliderOrSpinner = (float)beatmap.HitObjects.Count(h => h is IHasEndTime) / beatmap.HitObjects.Count(); if (percentSliderOrSpinner < 0.2) TargetColumns = 7; else if (percentSliderOrSpinner < 0.3 || roundedCircleSize >= 5) @@ -58,6 +59,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override Beatmap ConvertBeatmap(IBeatmap original) { + BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); diff --git a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs index 24fe72faec..822ba53eeb 100644 --- a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs @@ -10,7 +10,7 @@ using System.Collections.Generic; namespace osu.Game.Rulesets.Mania { - internal class ManiaDifficultyCalculator : DifficultyCalculator + internal class ManiaDifficultyCalculator : DifficultyCalculator { private const double star_scaling_factor = 0.018; @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Mania int columnCount = (Beatmap as ManiaBeatmap)?.TotalColumns ?? 7; foreach (var hitObject in Beatmap.HitObjects) - difficultyHitObjects.Add(new ManiaHitObjectDifficulty(hitObject, columnCount)); + difficultyHitObjects.Add(new ManiaHitObjectDifficulty((ManiaHitObject)hitObject, columnCount)); // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); @@ -140,7 +140,5 @@ namespace osu.Game.Rulesets.Mania return difficulty; } - - protected override BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(true, beatmap); } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index d5bf1b30fc..75b1e38a2f 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -15,12 +15,14 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Mania.Beatmaps; namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaRulesetContainer(this, beatmap, isForCurrentRuleset); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override IEnumerable ConvertLegacyMods(LegacyMods mods) { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs index dbd30121a8..e02db68a28 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs @@ -3,19 +3,18 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods { - public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter + public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter { public override string ShortenedName => Name; public abstract int KeyCount { get; } public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier public override bool Ranked => true; - public void ApplyToBeatmapConverter(BeatmapConverter beatmapConverter) + public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter) { var mbc = (ManiaBeatmapConverter)beatmapConverter; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs index 197b37b3f5..dde8acf428 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs @@ -11,14 +11,14 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToRulesetContainer + public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToRulesetContainer { public override string Name => "Dual Stages"; public override string ShortenedName => "DS"; public override string Description => @"Double the stages, double the fun!"; public override double ScoreMultiplier => 0; - public void ApplyToBeatmapConverter(BeatmapConverter beatmapConverter) + public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter) { var mbc = (ManiaBeatmapConverter)beatmapConverter; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 926a3a8923..bc9fd6e06f 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Replays public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) { // We don't need to fully convert, just create the converter - var converter = new ManiaBeatmapConverter(beatmap.BeatmapInfo.RulesetID == 3, beatmap); + var converter = new ManiaBeatmapConverter(beatmap); // NB: Via co-op mod, osu-stable can have two stages with floor(col/2) and ceil(col/2) columns. This will need special handling // elsewhere in the game if we do choose to support the old co-op mod anyway. For now, assume that there is only one stage. diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 76afaf270f..059eaaadcd 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -85,8 +85,6 @@ namespace osu.Game.Rulesets.Mania.UI public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant); - protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(IsForCurrentRuleset, WorkingBeatmap.Beatmap); - protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) { ManiaAction action = Playfield.Columns.ElementAt(h.Column).Action; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index a77b20e83b..a8f82a112b 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Tests }; } - protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new OsuBeatmapConverter(); + protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); } public struct ConvertValue : IEquatable diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index b1a52c5469..1cd4ec5668 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -14,6 +14,11 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { internal class OsuBeatmapConverter : BeatmapConverter { + public OsuBeatmapConverter(IBeatmap beatmap) + : base(beatmap) + { + } + protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasPosition) }; protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index afa2437bf6..c7c9f4a01a 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -8,12 +8,17 @@ using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Beatmaps { - internal class OsuBeatmapProcessor : BeatmapProcessor + internal class OsuBeatmapProcessor : BeatmapProcessor { - public override void PostProcess(Beatmap beatmap) + public OsuBeatmapProcessor(IBeatmap beatmap) + : base(beatmap) { - applyStacking(beatmap); - base.PostProcess(beatmap); + } + + public override void PostProcess() + { + applyStacking((Beatmap)Beatmap); + base.PostProcess(); } private void applyStacking(Beatmap beatmap) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index cf71116d47..7a30e6b134 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -5,20 +5,23 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; using OpenTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModHardRock : ModHardRock, IApplicableToHitObject + public class OsuModHardRock : ModHardRock, IApplicableToHitObject { public override double ScoreMultiplier => 1.06; public override bool Ranked => true; - public void ApplyToHitObject(OsuHitObject hitObject) + public void ApplyToHitObject(HitObject hitObject) { - hitObject.Position = new Vector2(hitObject.Position.X, OsuPlayfield.BASE_SIZE.Y - hitObject.Y); + var osuObject = (OsuHitObject)hitObject; + + osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y); var slider = hitObject as Slider; if (slider == null) diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs index 197bc16fc1..4853cd66cd 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs @@ -5,14 +5,13 @@ using System; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing; using osu.Game.Rulesets.Osu.OsuDifficulty.Skills; namespace osu.Game.Rulesets.Osu.OsuDifficulty { - public class OsuDifficultyCalculator : DifficultyCalculator + public class OsuDifficultyCalculator : DifficultyCalculator { private const int section_length = 400; private const double difficulty_multiplier = 0.0675; @@ -27,14 +26,9 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty { } - protected override void PreprocessHitObjects() - { - new OsuBeatmapProcessor().PostProcess(Beatmap); - } - public override double Calculate(Dictionary categoryDifficulty = null) { - OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap(Beatmap.HitObjects, TimeRate); + OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap((List)Beatmap.HitObjects, TimeRate); Skill[] skills = { new Aim(), @@ -72,7 +66,5 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty return starRating; } - - protected override BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(); } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index ed750882f4..02b887f1b9 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -22,12 +22,15 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Osu.Beatmaps; namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuRulesetContainer(this, beatmap, isForCurrentRuleset); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); + public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { @@ -39,7 +42,7 @@ namespace osu.Game.Rulesets.Osu public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) { - IEnumerable hitObjects = beatmap.Beatmap.HitObjects; + IEnumerable hitObjects = beatmap.OriginalBeatmap.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)); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index c8806cbdb1..6b9214d9dc 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -6,14 +6,13 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Scoring { - public class OsuPerformanceCalculator : PerformanceCalculator + public class OsuPerformanceCalculator : PerformanceCalculator { private readonly int countHitCircles; private readonly int beatmapMaxCombo; @@ -32,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Scoring { countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); - beatmapMaxCombo = Beatmap.HitObjects.Count; + beatmapMaxCombo = Beatmap.HitObjects.Count(); beatmapMaxCombo += Beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count) + 1; } @@ -193,7 +192,5 @@ namespace osu.Game.Rulesets.Osu.Scoring private double totalHits => count300 + count100 + count50 + countMiss; private double totalSuccessfulHits => count300 + count100 + count50; - - protected override BeatmapConverter CreateBeatmapConverter() => new OsuBeatmapConverter(); } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index 22c7b719cd..603f95dc47 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -7,7 +7,6 @@ using OpenTK; using osu.Game.Beatmaps; using osu.Game.Input.Handlers; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Replays; @@ -28,10 +27,6 @@ namespace osu.Game.Rulesets.Osu.UI public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this); - protected override BeatmapConverter CreateBeatmapConverter() => new OsuBeatmapConverter(); - - protected override BeatmapProcessor CreateBeatmapProcessor() => new OsuBeatmapProcessor(); - protected override Playfield CreatePlayfield() => new OsuPlayfield(); public override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo); diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 3d236af8ad..cbab53fa75 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -18,14 +18,11 @@ namespace osu.Game.Rulesets.Taiko.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko"; - private bool isForCurrentRuleset; - [NonParallelizable] [TestCase("basic", false), Ignore("See: https://github.com/ppy/osu/issues/2152")] [TestCase("slider-generating-drumroll", false)] - public void Test(string name, bool isForCurrentRuleset) + public new void Test(string name) { - this.isForCurrentRuleset = isForCurrentRuleset; base.Test(name); } @@ -43,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Tests }; } - protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(isForCurrentRuleset); + protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); } public struct ConvertValue : IEquatable diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index eabe7eb91a..eeb0fa1871 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -42,9 +42,10 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(HitObject) }; - public TaikoBeatmapConverter(bool isForCurrentRuleset) + public TaikoBeatmapConverter(IBeatmap beatmap) + : base(beatmap) { - this.isForCurrentRuleset = isForCurrentRuleset; + isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new TaikoRuleset().RulesetInfo); } protected override Beatmap ConvertBeatmap(IBeatmap original) diff --git a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs index 66b8459d1f..f14c53f7ae 100644 --- a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs @@ -2,14 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Objects; using System.Collections.Generic; using System; namespace osu.Game.Rulesets.Taiko { - internal class TaikoDifficultyCalculator : DifficultyCalculator + internal class TaikoDifficultyCalculator : DifficultyCalculator { private const double star_scaling_factor = 0.04125; @@ -41,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko difficultyHitObjects.Clear(); foreach (var hitObject in Beatmap.HitObjects) - difficultyHitObjects.Add(new TaikoHitObjectDifficulty(hitObject)); + difficultyHitObjects.Add(new TaikoHitObjectDifficulty((TaikoHitObject)hitObject)); // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); @@ -132,7 +131,5 @@ namespace osu.Game.Rulesets.Taiko return difficulty; } - - protected override BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(true); } } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index e5f3b33355..2e27b34e69 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -13,12 +13,14 @@ using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Taiko.Beatmaps; namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoRulesetContainer(this, beatmap, isForCurrentRuleset); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 3d3c6ab2f3..0a84d74c27 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -8,7 +8,6 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Scoring; @@ -93,8 +92,6 @@ namespace osu.Game.Rulesets.Taiko.UI public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); - protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(IsForCurrentRuleset); - public override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index f60caf2397..3530ae928d 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -274,13 +274,13 @@ namespace osu.Game.Tests.Beatmaps.IO foreach (BeatmapInfo b in set.Beatmaps) Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID)); Assert.IsTrue(set.Beatmaps.Count > 0); - var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; + var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.OriginalBeatmap; Assert.IsTrue(beatmap?.HitObjects.Any() == true); - beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap; + beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.OriginalBeatmap; Assert.IsTrue(beatmap?.HitObjects.Any() == true); - beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap; + beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.OriginalBeatmap; Assert.IsTrue(beatmap?.HitObjects.Any() == true); - beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap; + beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.OriginalBeatmap; Assert.IsTrue(beatmap?.HitObjects.Any() == true); } diff --git a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs index 596b7839e0..4e3462b5ea 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs @@ -139,7 +139,7 @@ namespace osu.Game.Tests.Visual }; } - private SortedList timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; + private SortedList timingPoints => Beatmap.Value.OriginalBeatmap.ControlPointInfo.TimingPoints; private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { if (timingPoints[timingPoints.Count - 1] == current) diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index fab7860077..263a4c36ee 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -22,25 +22,27 @@ namespace osu.Game.Beatmaps remove => ObjectConverted -= value; } - /// - /// Checks if a Beatmap can be converted using this Beatmap Converter. - /// - /// The Beatmap to check. - /// Whether the Beatmap can be converted using this Beatmap Converter. - public bool CanConvert(IBeatmap beatmap) => ValidConversionTypes.All(t => beatmap.HitObjects.Any(t.IsInstanceOfType)); + public IBeatmap Beatmap { get; } - /// - /// Converts a Beatmap using this Beatmap Converter. - /// - /// The un-converted Beatmap. - /// The converted Beatmap. - public Beatmap Convert(IBeatmap original) + protected BeatmapConverter(IBeatmap beatmap) { - // We always operate on a clone of the original beatmap, to not modify it game-wide - return ConvertBeatmap(original.Clone()); + Beatmap = beatmap; } - void IBeatmapConverter.Convert(IBeatmap original) => Convert(original); + /// + /// Whether can be converted by this . + /// + public bool CanConvert => ValidConversionTypes.All(t => Beatmap.HitObjects.Any(t.IsInstanceOfType)); + + /// + /// Converts . + /// + /// The converted Beatmap. + public IBeatmap Convert() + { + // We always operate on a clone of the original beatmap, to not modify it game-wide + return ConvertBeatmap(Beatmap.Clone()); + } /// /// Performs the conversion of a Beatmap using this Beatmap Converter. diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 71406c6034..cff500fabf 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps this.audioManager = audioManager; } - protected override IBeatmap GetBeatmap() + protected override IBeatmap GetOriginalBeatmap() { try { diff --git a/osu.Game/Beatmaps/BeatmapProcessor.cs b/osu.Game/Beatmaps/BeatmapProcessor.cs index 8f5a2a4cab..bf1cd7d4ee 100644 --- a/osu.Game/Beatmaps/BeatmapProcessor.cs +++ b/osu.Game/Beatmaps/BeatmapProcessor.cs @@ -2,30 +2,47 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Beatmaps { + public interface IBeatmapProcessor + { + IBeatmap Beatmap { get; } + + /// + /// Post-processes to add mode-specific components that aren't added during conversion. + /// + /// An example of such a usage is for combo colours. + /// + /// + void PostProcess(); + } + /// /// Processes a post-converted Beatmap. /// /// The type of HitObject contained in the Beatmap. - public class BeatmapProcessor - where TObject : HitObject + public class BeatmapProcessor : IBeatmapProcessor { + public IBeatmap Beatmap { get; } + + public BeatmapProcessor(IBeatmap beatmap) + { + Beatmap = beatmap; + } + /// /// Post-processes a Beatmap to add mode-specific components that aren't added during conversion. /// /// An example of such a usage is for combo colours. /// /// - /// The Beatmap to process. - public virtual void PostProcess(Beatmap beatmap) + public virtual void PostProcess() { IHasComboInformation lastObj = null; - foreach (var obj in beatmap.HitObjects.OfType()) + foreach (var obj in Beatmap.HitObjects.OfType()) { if (obj.NewCombo) { diff --git a/osu.Game/Beatmaps/DifficultyCalculator.cs b/osu.Game/Beatmaps/DifficultyCalculator.cs index bf252ff51f..37155c09cd 100644 --- a/osu.Game/Beatmaps/DifficultyCalculator.cs +++ b/osu.Game/Beatmaps/DifficultyCalculator.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Objects; using System.Collections.Generic; using osu.Game.Rulesets.Mods; using osu.Framework.Timing; @@ -12,30 +11,17 @@ namespace osu.Game.Beatmaps { public abstract class DifficultyCalculator { - protected double TimeRate = 1; - - public abstract double Calculate(Dictionary categoryDifficulty = null); - } - - public abstract class DifficultyCalculator : DifficultyCalculator where T : HitObject - { - protected readonly Beatmap Beatmap; + protected readonly IBeatmap Beatmap; protected readonly Mod[] Mods; + protected double TimeRate = 1; + protected DifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) { + Beatmap = beatmap; Mods = mods ?? new Mod[0]; - var converter = CreateBeatmapConverter(beatmap); - - foreach (var mod in Mods.OfType>()) - mod.ApplyToBeatmapConverter(converter); - - Beatmap = converter.Convert(beatmap); - ApplyMods(Mods); - - PreprocessHitObjects(); } protected virtual void ApplyMods(Mod[] mods) @@ -43,22 +29,12 @@ namespace osu.Game.Beatmaps var clock = new StopwatchClock(); mods.OfType().ForEach(m => m.ApplyToClock(clock)); TimeRate = clock.Rate; - - foreach (var mod in Mods.OfType()) - mod.ApplyToDifficulty(Beatmap.BeatmapInfo.BaseDifficulty); - - foreach (var h in Beatmap.HitObjects) - h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty); - - foreach (var mod in mods.OfType>()) - foreach (var obj in Beatmap.HitObjects) - mod.ApplyToHitObject(obj); } protected virtual void PreprocessHitObjects() { } - protected abstract BeatmapConverter CreateBeatmapConverter(IBeatmap beatmap); + public abstract double Calculate(Dictionary categoryDifficulty = null); } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 0d325284e1..23ddc5a976 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; namespace osu.Game.Beatmaps @@ -39,7 +40,7 @@ namespace osu.Game.Beatmaps this.game = game; } - protected override IBeatmap GetBeatmap() => new Beatmap(); + protected override IBeatmap GetOriginalBeatmap() => new Beatmap(); protected override Texture GetBackground() => game.Textures.Get(@"Backgrounds/bg4"); @@ -58,6 +59,8 @@ namespace osu.Game.Beatmaps throw new NotImplementedException(); } + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new DummyBeatmapConverter { Beatmap = beatmap }; + public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => null; public override string Description => "dummy"; @@ -68,6 +71,14 @@ namespace osu.Game.Beatmaps : base(rulesetInfo) { } + + private class DummyBeatmapConverter : IBeatmapConverter + { + public event Action> ObjectConverted; + public IBeatmap Beatmap { get; set; } + public bool CanConvert => true; + public IBeatmap Convert() => Beatmap; + } } } } diff --git a/osu.Game/Beatmaps/IBeatmapConverter.cs b/osu.Game/Beatmaps/IBeatmapConverter.cs index 4df250ad17..00566093b8 100644 --- a/osu.Game/Beatmaps/IBeatmapConverter.cs +++ b/osu.Game/Beatmaps/IBeatmapConverter.cs @@ -16,10 +16,16 @@ namespace osu.Game.Beatmaps /// event Action> ObjectConverted; + IBeatmap Beatmap { get; } + /// - /// Converts a Beatmap using this Beatmap Converter. + /// Whether can be converted by this . /// - /// The un-converted Beatmap. - void Convert(IBeatmap beatmap); + bool CanConvert { get; } + + /// + /// Converts . + /// + IBeatmap Convert(); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index fc67d2e508..7d6c23dad0 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -14,6 +14,8 @@ using osu.Framework.IO.File; using System.IO; using osu.Game.IO.Serialization; using System.Diagnostics; +using osu.Game.Rulesets; +using osu.Game.Rulesets.UI; using osu.Game.Skinning; namespace osu.Game.Beatmaps @@ -36,7 +38,7 @@ namespace osu.Game.Beatmaps Mods.ValueChanged += mods => applyRateAdjustments(); - beatmap = new AsyncLazy(populateBeatmap); + originalBeatmap = new AsyncLazy(populateOriginalBeatmap); background = new AsyncLazy(populateBackground, b => b == null || !b.IsDisposed); track = new AsyncLazy(populateTrack); waveform = new AsyncLazy(populateWaveform); @@ -51,26 +53,25 @@ namespace osu.Game.Beatmaps { var path = FileSafety.GetTempPath(Guid.NewGuid().ToString().Replace("-", string.Empty) + ".json"); using (var sw = new StreamWriter(path)) - sw.WriteLine(Beatmap.Serialize()); + sw.WriteLine(OriginalBeatmap.Serialize()); Process.Start(path); } - protected abstract IBeatmap GetBeatmap(); + protected abstract IBeatmap GetOriginalBeatmap(); protected abstract Texture GetBackground(); protected abstract Track GetTrack(); protected virtual Skin GetSkin() => new DefaultSkin(); protected virtual Waveform GetWaveform() => new Waveform(); protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo }; - public bool BeatmapLoaded => beatmap.IsResultAvailable; - public IBeatmap Beatmap => beatmap.Value.Result; - public async Task GetBeatmapAsync() => await beatmap.Value; + public bool BeatmapLoaded => originalBeatmap.IsResultAvailable; + public IBeatmap OriginalBeatmap => originalBeatmap.Value.Result; + public async Task GetOriginalBeatmapAsync() => await originalBeatmap.Value; + private readonly AsyncLazy originalBeatmap; - private readonly AsyncLazy beatmap; - - private IBeatmap populateBeatmap() + private IBeatmap populateOriginalBeatmap() { - var b = GetBeatmap() ?? new Beatmap(); + var b = GetOriginalBeatmap() ?? new Beatmap(); // use the database-backed info. b.BeatmapInfo = BeatmapInfo; @@ -78,6 +79,41 @@ namespace osu.Game.Beatmaps return b; } + public IBeatmap GetBeatmap(RulesetInfo ruleset) + { + var rulesetInstance = ruleset.CreateInstance(); + + IBeatmapConverter converter = rulesetInstance.CreateBeatmapConverter(OriginalBeatmap); + + // Check if the beatmap can be converted + if (!converter.CanConvert) + throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the current ruleset (converter: {converter})."); + + // Apply conversion mods + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToBeatmapConverter(converter); + + // Convert + IBeatmap converted = converter.Convert(); + + // Apply difficulty mods + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty); + + // Post-process + rulesetInstance.CreateBeatmapProcessor(converted)?.PostProcess(); + + // Compute default values for hitobjects, including creating nested hitobjects in-case they're needed + foreach (var obj in converted.HitObjects) + obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty); + + foreach (var mod in Mods.Value.OfType()) + foreach (var obj in converted.HitObjects) + mod.ApplyToHitObject(obj); + + return converted; + } + public bool BackgroundLoaded => background.IsResultAvailable; public Texture Background => background.Value.Result; public async Task GetBackgroundAsync() => await background.Value; diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index bf16af4706..8d8717a612 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -38,7 +38,7 @@ namespace osu.Game.Graphics.Containers if (!Beatmap.Value.TrackLoaded || !Beatmap.Value.BeatmapLoaded) return; var track = Beatmap.Value.Track; - var beatmap = Beatmap.Value.Beatmap; + var beatmap = Beatmap.Value.OriginalBeatmap; if (track == null || beatmap == null) return; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index b4021f2808..eb88fe0eb4 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -343,7 +343,7 @@ namespace osu.Game.Overlays // todo: this can likely be replaced with WorkingBeatmap.GetBeatmapAsync() Task.Run(() => { - if (beatmap?.Beatmap == null) //this is not needed if a placeholder exists + if (beatmap?.OriginalBeatmap == null) //this is not needed if a placeholder exists { title.Current = null; title.Text = @"Nothing to play"; diff --git a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs index a03a003810..1b8e62b53c 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs @@ -10,13 +10,12 @@ namespace osu.Game.Rulesets.Mods /// Interface for a that applies changes to a . /// /// The type of converted . - public interface IApplicableToBeatmapConverter : IApplicableMod - where TObject : HitObject + public interface IApplicableToBeatmapConverter : IApplicableMod { /// /// Applies this to a . /// /// The to apply to. - void ApplyToBeatmapConverter(BeatmapConverter beatmapConverter); + void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter); } } diff --git a/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs b/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs index 0fd2e398c8..d6f330d9df 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs @@ -8,13 +8,12 @@ namespace osu.Game.Rulesets.Mods /// /// An interface for s that can be applied to s. /// - public interface IApplicableToHitObject : IApplicableMod - where TObject : HitObject + public interface IApplicableToHitObject : IApplicableMod { /// /// Applies this to a . /// /// The to apply to. - void ApplyToHitObject(TObject hitObject); + void ApplyToHitObject(HitObject hitObject); } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 3f8512eb90..6f117332b2 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -57,6 +57,10 @@ namespace osu.Game.Rulesets /// public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset); + public abstract IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap); + + public virtual IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => null; + public abstract DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null); public virtual PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => null; diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs index d5ab856697..3145561001 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Scoring.Legacy /* score.FileChecksum = */ var beatmapHash = sr.ReadString(); score.Beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == beatmapHash); - currentBeatmap = beatmaps.GetWorkingBeatmap(score.Beatmap).Beatmap; + currentBeatmap = beatmaps.GetWorkingBeatmap(score.Beatmap).OriginalBeatmap; /* score.PlayerName = */ score.User = new User { Username = sr.ReadString() }; diff --git a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs index 6392d2c0ae..5b8f5f0d0f 100644 --- a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs @@ -2,42 +2,28 @@ // 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.Rulesets.Mods; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Scoring { public abstract class PerformanceCalculator - { - public abstract double Calculate(Dictionary categoryDifficulty = null); - } - - public abstract class PerformanceCalculator : PerformanceCalculator - where TObject : HitObject { private readonly Dictionary attributes = new Dictionary(); protected IDictionary Attributes => attributes; - protected readonly Beatmap Beatmap; + protected readonly IBeatmap Beatmap; protected readonly Score Score; protected PerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) { Score = score; - var converter = CreateBeatmapConverter(); - - foreach (var mod in score.Mods.OfType>()) - mod.ApplyToBeatmapConverter(converter); - - Beatmap = converter.Convert(beatmap); + Beatmap = beatmap; var diffCalc = ruleset.CreateDifficultyCalculator(beatmap, score.Mods); diffCalc.Calculate(attributes); } - protected abstract BeatmapConverter CreateBeatmapConverter(); + public abstract double Calculate(Dictionary categoryDifficulty = null); } } diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index d1f1807937..074380da56 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -219,30 +219,7 @@ namespace osu.Game.Rulesets.UI RelativeSizeAxes = Axes.Both; - BeatmapConverter converter = CreateBeatmapConverter(); - BeatmapProcessor processor = CreateBeatmapProcessor(); - - // Check if the beatmap can be converted - if (!converter.CanConvert(workingBeatmap.Beatmap)) - throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the current ruleset (converter: {converter})."); - - // Apply conversion adjustments before converting - foreach (var mod in Mods.OfType>()) - mod.ApplyToBeatmapConverter(converter); - - // Convert the beatmap - Beatmap = converter.Convert(workingBeatmap.Beatmap); - - // Apply difficulty adjustments from mods before using Difficulty. - foreach (var mod in Mods.OfType()) - mod.ApplyToDifficulty(Beatmap.BeatmapInfo.BaseDifficulty); - - // Post-process the beatmap - processor.PostProcess(Beatmap); - - // Apply defaults - foreach (var h in Beatmap.HitObjects) - h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty); + Beatmap = (Beatmap)workingBeatmap.GetBeatmap(ruleset.RulesetInfo); KeyBindingInputManager = CreateInputManager(); KeyBindingInputManager.RelativeSizeAxes = Axes.Both; @@ -277,10 +254,6 @@ namespace osu.Game.Rulesets.UI if (mods == null) return; - foreach (var mod in mods.OfType>()) - foreach (var obj in Beatmap.HitObjects) - mod.ApplyToHitObject(obj); - foreach (var mod in mods.OfType>()) mod.ApplyToRulesetContainer(this); } @@ -324,13 +297,6 @@ namespace osu.Game.Rulesets.UI Playfield.Size = GetAspectAdjustedSize() * PlayfieldArea; } - /// - /// Creates a processor to perform post-processing operations - /// on HitObjects in converted Beatmaps. - /// - /// The Beatmap processor. - protected virtual BeatmapProcessor CreateBeatmapProcessor() => new BeatmapProcessor(); - /// /// Computes the size of the in relative coordinate space after aspect adjustments. /// @@ -344,12 +310,6 @@ namespace osu.Game.Rulesets.UI /// protected virtual Vector2 PlayfieldArea => new Vector2(0.75f); // A sane default - /// - /// Creates a converter to convert Beatmap to a specific mode. - /// - /// The Beatmap converter. - protected abstract BeatmapConverter CreateBeatmapConverter(); - /// /// Creates a DrawableHitObject from a HitObject. /// diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs index 1146037004..e081897339 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected override void LoadBeatmap(WorkingBeatmap beatmap) { base.LoadBeatmap(beatmap); - foreach (var breakPeriod in beatmap.Beatmap.Breaks) + foreach (var breakPeriod in beatmap.OriginalBeatmap.Breaks) Add(new BreakVisualisation(breakPeriod)); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs index 4bef22463e..faf090bfd9 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { base.LoadBeatmap(beatmap); - ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; + ControlPointInfo cpi = beatmap.OriginalBeatmap.ControlPointInfo; cpi.TimingPoints.ForEach(addTimingPoint); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index ea1d85bb5b..4ad11e6a91 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Edit { // TODO: should probably be done at a RulesetContainer level to share logic with Player. var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); - clock = new EditorClock(Beatmap.Value.Beatmap.ControlPointInfo, beatDivisor) { IsCoupled = false }; + clock = new EditorClock(Beatmap.Value.OriginalBeatmap.ControlPointInfo, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); dependencies.CacheAs(clock); diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 1f2cb915b3..bbd50d8f1b 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Menu private void updateAmplitudes() { var track = beatmap.Value.TrackLoaded ? beatmap.Value.Track : null; - var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null; + var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.OriginalBeatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null; float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes ?? new float[256]; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 32685935a1..bfc0cec18f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Play try { - beatmap = working.Beatmap; + beatmap = working.OriginalBeatmap; if (beatmap == null) throw new InvalidOperationException("Beatmap was not loaded"); diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 9d92439a4b..6d3812ac4b 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -88,7 +88,7 @@ namespace osu.Game.Screens.Ranking { RelativeSizeAxes = Axes.Both, Alpha = 0.5f, - Objects = Beatmap.Beatmap.HitObjects, + Objects = Beatmap.OriginalBeatmap.HitObjects, }, scoreCounter = new SlowScoreCounter(6) { diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index da82a49f51..2dad5a9008 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -210,7 +210,7 @@ namespace osu.Game.Screens.Select private InfoLabel[] getInfoLabels() { - var beatmap = working.Beatmap; + var beatmap = working.OriginalBeatmap; var info = working.BeatmapInfo; List labels = new List(); diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index d02ccaff16..735c0ef76c 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Beatmaps result.Mappings.Add(mapping); }; - converter.Convert(beatmap); + converter.Convert(); return result; } diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 37693c99e8..71893cfe37 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps } private readonly IBeatmap beatmap; - protected override IBeatmap GetBeatmap() => beatmap; + protected override IBeatmap GetOriginalBeatmap() => beatmap; protected override Texture GetBackground() => null; protected override Track GetTrack() diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestCase.cs index 43b20f7021..c6a98a4f43 100644 --- a/osu.Game/Tests/Visual/EditorClockTestCase.cs +++ b/osu.Game/Tests/Visual/EditorClockTestCase.cs @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(WorkingBeatmap working) { - Clock.ControlPointInfo = working.Beatmap.ControlPointInfo; + Clock.ControlPointInfo = working.OriginalBeatmap.ControlPointInfo; Clock.ChangeSource((IAdjustableClock)working.Track ?? new StopwatchClock()); Clock.ProcessFrame(); } diff --git a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs index 51460ecb6d..5d78b95c04 100644 --- a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs +++ b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs @@ -250,7 +250,7 @@ namespace osu.Game.Tests.Visual return; lastRequest = new GetScoresRequest(newBeatmap.BeatmapInfo, newBeatmap.BeatmapInfo.Ruleset); - lastRequest.Success += res => res.Scores.ForEach(s => scores.Add(new PerformanceDisplay(s, newBeatmap.Beatmap))); + lastRequest.Success += res => res.Scores.ForEach(s => scores.Add(new PerformanceDisplay(s, newBeatmap.OriginalBeatmap))); api.Queue(lastRequest); } @@ -381,7 +381,7 @@ namespace osu.Game.Tests.Visual var allMods = ruleset.GetAllMods().ToList(); Mod[] activeMods = modFlow.Where(c => c.Current.Value).Select(c => allMods.First(m => m.ShortenedName == c.LabelText)).ToArray(); - var diffCalc = ruleset.CreateDifficultyCalculator(beatmap.Beatmap, activeMods); + var diffCalc = ruleset.CreateDifficultyCalculator(beatmap.OriginalBeatmap, activeMods); if (diffCalc != null) { var categories = new Dictionary(); From c34ef42f0071a0bec598fd0b27d13f0a5bd3b729 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Fri, 20 Apr 2018 12:50:19 +0300 Subject: [PATCH 019/302] Add 'End replay' button --- osu.Game/Screens/Play/Player.cs | 2 ++ osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ec7c1a1009..84021fe8d4 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -218,6 +218,8 @@ namespace osu.Game.Screens.Play } }; + hudOverlay.PlayerSettingsOverlay.PlaybackSettings.EndReplayButton.Action = Exit; + if (ShowStoryboard) initializeStoryboard(false); diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index 13e403e899..3303ebaf97 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Play.PlayerSettings { @@ -18,6 +19,7 @@ namespace osu.Game.Screens.Play.PlayerSettings public IAdjustableClock AdjustableClock { set; get; } private readonly PlayerSliderBar sliderbar; + public readonly SettingsButton EndReplayButton; public PlaybackSettings() { @@ -55,6 +57,10 @@ namespace osu.Game.Screens.Play.PlayerSettings MaxValue = 2, Precision = 0.1, }, + }, + EndReplayButton = new SettingsButton + { + Text = "End replay" } }; From 633c775306c928088e40da8db602b7fa23f1384f Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 21 Apr 2018 18:24:31 +0300 Subject: [PATCH 020/302] Initial HoldToQuit commit --- osu.Game/Screens/Play/HUD/HoldToQuit.cs | 118 ++++++++++++++++++++++++ osu.Game/Screens/Play/HUDOverlay.cs | 9 ++ 2 files changed, 127 insertions(+) create mode 100644 osu.Game/Screens/Play/HUD/HoldToQuit.cs diff --git a/osu.Game/Screens/Play/HUD/HoldToQuit.cs b/osu.Game/Screens/Play/HUD/HoldToQuit.cs new file mode 100644 index 0000000000..55cbff4d86 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/HoldToQuit.cs @@ -0,0 +1,118 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Threading; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; +using osu.Framework.Threading; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using OpenTK; + +namespace osu.Game.Screens.Play.HUD +{ + public class HoldToQuit : Container + { + private readonly OsuSpriteText text; + private readonly HoldToQuitButton button; + + public HoldToQuit() + { + Children = new Drawable[] + { + text = new OsuSpriteText + { + Text = "Hold to Quit", + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + button = new HoldToQuitButton(text) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight + } + }; + AutoSizeAxes = Axes.Both; + } + + private class HoldToQuitButton : CircularContainer + { + private readonly OsuSpriteText text; + private SpriteIcon icon; + private CircularProgress progress; + + private Action exitAction; + private readonly Scheduler scheduler; + private ScheduledDelegate scheduledExitAction; + + private const int fade_duration = 200; + + public HoldToQuitButton(OsuSpriteText text) + { + this.text = text; + scheduler = new Scheduler(); + + // TODO provide action + exitAction = () => Thread.Sleep(1); + } + + private void hideText() => scheduler.AddDelayed(() => text.FadeOut(fade_duration), 5000); + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Masking = true; + Size = new Vector2(60); + AddRange(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray1, + Alpha = 0.8f, + }, + icon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(15), + Icon = FontAwesome.fa_close + }, + progress = new CircularProgress { RelativeSizeAxes = Axes.Both, InnerRadius = 0.1f, Current = { Value = 1 } } + }); + progress.Hide(); + hideText(); + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + icon.ScaleTo(1.5f); + text.FadeIn(fade_duration); + progress.FadeIn(1000); + scheduledExitAction = scheduler.AddDelayed(exitAction, 1000); + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + icon.ScaleTo(1f); + hideText(); + if (scheduledExitAction != null && !scheduledExitAction.Completed) + scheduledExitAction.Cancel(); + progress.FadeOut(fade_duration); + return base.OnMouseUp(state, args); + } + + protected override void Update() + { + scheduler.Update(); + base.Update(); + } + } + } +} diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 36d8bb75c0..c2471c967e 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -34,6 +34,7 @@ namespace osu.Game.Screens.Play public readonly HealthDisplay HealthDisplay; public readonly SongProgress Progress; public readonly ModDisplay ModDisplay; + public readonly HoldToQuit HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; private Bindable showHud; @@ -57,6 +58,7 @@ namespace osu.Game.Screens.Play AccuracyCounter = CreateAccuracyCounter(), HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), + HoldToQuit = CreateHoldToQuit(), ModDisplay = CreateModsContainer(), PlayerSettingsOverlay = CreatePlayerSettingsOverlay() } @@ -205,6 +207,13 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.X, }; + protected virtual HoldToQuit CreateHoldToQuit() => new HoldToQuit + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding { Bottom = Progress.Size.Y * 1.25f, Right = 5 } + }; + protected virtual ModDisplay CreateModsContainer() => new ModDisplay { Anchor = Anchor.TopRight, From 3b621db460cdf6226559eb6a25b6f6443635c935 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 21 Apr 2018 19:25:21 +0300 Subject: [PATCH 021/302] Implement CircularProgress filling --- osu.Game/Screens/Play/HUD/HoldToQuit.cs | 29 +++++++++++++++++-------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HoldToQuit.cs b/osu.Game/Screens/Play/HUD/HoldToQuit.cs index 55cbff4d86..59569aacbd 100644 --- a/osu.Game/Screens/Play/HUD/HoldToQuit.cs +++ b/osu.Game/Screens/Play/HUD/HoldToQuit.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Threading; +using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using OpenTK; @@ -47,22 +48,24 @@ namespace osu.Game.Screens.Play.HUD private CircularProgress progress; private Action exitAction; - private readonly Scheduler scheduler; private ScheduledDelegate scheduledExitAction; + private readonly Scheduler scheduler; + private readonly StopwatchClock stopwatchClock; + private const int fade_duration = 200; + private const int text_display_time = 5000; public HoldToQuitButton(OsuSpriteText text) { this.text = text; scheduler = new Scheduler(); + stopwatchClock = new StopwatchClock(); // TODO provide action exitAction = () => Thread.Sleep(1); } - private void hideText() => scheduler.AddDelayed(() => text.FadeOut(fade_duration), 5000); - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -83,34 +86,42 @@ namespace osu.Game.Screens.Play.HUD Size = new Vector2(15), Icon = FontAwesome.fa_close }, - progress = new CircularProgress { RelativeSizeAxes = Axes.Both, InnerRadius = 0.1f, Current = { Value = 1 } } + progress = new CircularProgress { RelativeSizeAxes = Axes.Both, InnerRadius = 0.1f } }); - progress.Hide(); - hideText(); + scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { icon.ScaleTo(1.5f); text.FadeIn(fade_duration); - progress.FadeIn(1000); + stopwatchClock.Restart(); scheduledExitAction = scheduler.AddDelayed(exitAction, 1000); + return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { icon.ScaleTo(1f); - hideText(); + scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); + stopwatchClock.Stop(); if (scheduledExitAction != null && !scheduledExitAction.Completed) scheduledExitAction.Cancel(); - progress.FadeOut(fade_duration); + progress.Current.SetDefault(); + return base.OnMouseUp(state, args); } protected override void Update() { scheduler.Update(); + if (stopwatchClock.IsRunning) + { + var clampedTime = MathHelper.Clamp(stopwatchClock.CurrentTime, 0, 1000); + progress.Current.Value = clampedTime / 1000; + } + base.Update(); } } From 21454d1f10848a38c71c16e77695c5a0f241dc93 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 21 Apr 2018 19:27:17 +0300 Subject: [PATCH 022/302] Revert "Add 'End replay' button" This reverts commit c34ef42f0071a0bec598fd0b27d13f0a5bd3b729. --- osu.Game/Screens/Play/Player.cs | 2 -- osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs | 6 ------ 2 files changed, 8 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 84021fe8d4..ec7c1a1009 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -218,8 +218,6 @@ namespace osu.Game.Screens.Play } }; - hudOverlay.PlayerSettingsOverlay.PlaybackSettings.EndReplayButton.Action = Exit; - if (ShowStoryboard) initializeStoryboard(false); diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index 3303ebaf97..13e403e899 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Play.PlayerSettings { @@ -19,7 +18,6 @@ namespace osu.Game.Screens.Play.PlayerSettings public IAdjustableClock AdjustableClock { set; get; } private readonly PlayerSliderBar sliderbar; - public readonly SettingsButton EndReplayButton; public PlaybackSettings() { @@ -57,10 +55,6 @@ namespace osu.Game.Screens.Play.PlayerSettings MaxValue = 2, Precision = 0.1, }, - }, - EndReplayButton = new SettingsButton - { - Text = "End replay" } }; From e6d7136a9206153a0132961efe8c2adb9bbcca1d Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 21 Apr 2018 20:21:09 +0300 Subject: [PATCH 023/302] Fix HoldToQuit appearance and set HoldToQuitButton.ExitAction --- osu.Game/Screens/Play/HUD/HoldToQuit.cs | 23 +++++++++-------------- osu.Game/Screens/Play/Player.cs | 2 ++ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HoldToQuit.cs b/osu.Game/Screens/Play/HUD/HoldToQuit.cs index 59569aacbd..f4848ff730 100644 --- a/osu.Game/Screens/Play/HUD/HoldToQuit.cs +++ b/osu.Game/Screens/Play/HUD/HoldToQuit.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,37 +16,36 @@ using OpenTK; namespace osu.Game.Screens.Play.HUD { - public class HoldToQuit : Container + public class HoldToQuit : FillFlowContainer { private readonly OsuSpriteText text; - private readonly HoldToQuitButton button; + public readonly HoldToQuitButton Button; public HoldToQuit() { + Direction = FillDirection.Horizontal; + Spacing = new Vector2(20, 0); Children = new Drawable[] { text = new OsuSpriteText { Text = "Hold to Quit", + Font = @"Exo2.0-Bold", Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }, - button = new HoldToQuitButton(text) - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight - } + Button = new HoldToQuitButton(text) }; AutoSizeAxes = Axes.Both; } - private class HoldToQuitButton : CircularContainer + public class HoldToQuitButton : CircularContainer { private readonly OsuSpriteText text; private SpriteIcon icon; private CircularProgress progress; - private Action exitAction; + public Action ExitAction { get; set; } private ScheduledDelegate scheduledExitAction; private readonly Scheduler scheduler; @@ -61,9 +59,6 @@ namespace osu.Game.Screens.Play.HUD this.text = text; scheduler = new Scheduler(); stopwatchClock = new StopwatchClock(); - - // TODO provide action - exitAction = () => Thread.Sleep(1); } [BackgroundDependencyLoader] @@ -96,7 +91,7 @@ namespace osu.Game.Screens.Play.HUD icon.ScaleTo(1.5f); text.FadeIn(fade_duration); stopwatchClock.Restart(); - scheduledExitAction = scheduler.AddDelayed(exitAction, 1000); + scheduledExitAction = scheduler.AddDelayed(ExitAction, 1000); return base.OnMouseDown(state, args); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ec7c1a1009..6c5e10c836 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -218,6 +218,8 @@ namespace osu.Game.Screens.Play } }; + hudOverlay.HoldToQuit.Button.ExitAction = Exit; + if (ShowStoryboard) initializeStoryboard(false); From 630980255ed479d391f6860bc89f762633917a70 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 21 Apr 2018 20:35:24 +0300 Subject: [PATCH 024/302] Convert HoldToQuit.text to local variable --- osu.Game/Screens/Play/HUD/HoldToQuit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HoldToQuit.cs b/osu.Game/Screens/Play/HUD/HoldToQuit.cs index f4848ff730..3f14582d50 100644 --- a/osu.Game/Screens/Play/HUD/HoldToQuit.cs +++ b/osu.Game/Screens/Play/HUD/HoldToQuit.cs @@ -18,11 +18,11 @@ namespace osu.Game.Screens.Play.HUD { public class HoldToQuit : FillFlowContainer { - private readonly OsuSpriteText text; public readonly HoldToQuitButton Button; public HoldToQuit() { + OsuSpriteText text; Direction = FillDirection.Horizontal; Spacing = new Vector2(20, 0); Children = new Drawable[] From b3cf381c5d3b883be24df2db2b8210e38e8b348c Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 28 Apr 2018 19:24:49 +0300 Subject: [PATCH 025/302] Add TestCaseHoldToQuit --- osu.Game.Tests/Visual/TestCaseHoldToQuit.cs | 56 +++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseHoldToQuit.cs diff --git a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs b/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs new file mode 100644 index 0000000000..d7f024d905 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Screens.Play.HUD; + +namespace osu.Game.Tests.Visual +{ + [Description("'Hold to Quit' UI element")] + public class TestCaseHoldToQuit : OsuTestCase + { + private bool exitAction; + + public TestCaseHoldToQuit() + { + HoldToQuit holdToQuit; + Add(holdToQuit = new HoldToQuit + { + Origin = Anchor.BottomRight, + Anchor = Anchor.BottomRight, + }); + holdToQuit.Button.ExitAction = () => exitAction = true; + + var text = holdToQuit.Children.OfType().Single(); + + AddStep("Text fade in", () => + { + exitAction = false; + holdToQuit.Button.TriggerOnMouseDown(); + holdToQuit.Button.TriggerOnMouseUp(); + }); + + AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); + + AddStep("Text fade out", () => + { + exitAction = false; + holdToQuit.Button.TriggerOnMouseDown(); + holdToQuit.Button.TriggerOnMouseUp(); + }); + + AddUntilStep(() => !text.IsPresent && !exitAction, "Text is not visible"); + + AddStep("Trigger exit action", () => + { + exitAction = false; + holdToQuit.Button.TriggerOnMouseDown(); + }); + + AddUntilStep(() => exitAction, $"{nameof(holdToQuit.Button.ExitAction)} was triggered"); + } + } +} From c78c5195f352dcb5bc657cf0e29f66cf61e6a369 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 28 Apr 2018 20:43:41 +0300 Subject: [PATCH 026/302] HoldToQuitButton cleanup --- osu.Game/Screens/Play/HUD/HoldToQuit.cs | 38 ++++--------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HoldToQuit.cs b/osu.Game/Screens/Play/HUD/HoldToQuit.cs index 3f14582d50..59338f8cdc 100644 --- a/osu.Game/Screens/Play/HUD/HoldToQuit.cs +++ b/osu.Game/Screens/Play/HUD/HoldToQuit.cs @@ -8,8 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; -using osu.Framework.Threading; -using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using OpenTK; @@ -46,20 +44,12 @@ namespace osu.Game.Screens.Play.HUD private CircularProgress progress; public Action ExitAction { get; set; } - private ScheduledDelegate scheduledExitAction; - - private readonly Scheduler scheduler; - private readonly StopwatchClock stopwatchClock; private const int fade_duration = 200; + private const int progress_duration = 1000; private const int text_display_time = 5000; - public HoldToQuitButton(OsuSpriteText text) - { - this.text = text; - scheduler = new Scheduler(); - stopwatchClock = new StopwatchClock(); - } + public HoldToQuitButton(OsuSpriteText text) => this.text = text; [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -83,15 +73,14 @@ namespace osu.Game.Screens.Play.HUD }, progress = new CircularProgress { RelativeSizeAxes = Axes.Both, InnerRadius = 0.1f } }); - scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); + Scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { icon.ScaleTo(1.5f); text.FadeIn(fade_duration); - stopwatchClock.Restart(); - scheduledExitAction = scheduler.AddDelayed(ExitAction, 1000); + progress.FillTo(1, progress_duration).OnComplete(cp => ExitAction()); return base.OnMouseDown(state, args); } @@ -99,26 +88,11 @@ namespace osu.Game.Screens.Play.HUD protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { icon.ScaleTo(1f); - scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); - stopwatchClock.Stop(); - if (scheduledExitAction != null && !scheduledExitAction.Completed) - scheduledExitAction.Cancel(); - progress.Current.SetDefault(); + Scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); + progress.FillTo(0, progress_duration / 4).OnComplete(cp => progress.Current.SetDefault()); return base.OnMouseUp(state, args); } - - protected override void Update() - { - scheduler.Update(); - if (stopwatchClock.IsRunning) - { - var clampedTime = MathHelper.Clamp(stopwatchClock.CurrentTime, 0, 1000); - progress.Current.Value = clampedTime / 1000; - } - - base.Update(); - } } } } From ca574f2345d7e355493e95e59141bc5bd7dd1c1f Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sun, 29 Apr 2018 18:36:19 +0300 Subject: [PATCH 027/302] Disable RulesetToggleButton whenever the ruleset can't be changed --- osu.Game/Overlays/Direct/FilterControl.cs | 10 +++++++--- osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index 8883dfdebb..a2da516257 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -49,14 +49,14 @@ namespace osu.Game.Overlays.Direct { private Drawable icon { - get { return iconContainer.Icon; } - set { iconContainer.Icon = value; } + get => iconContainer.Icon; + set => iconContainer.Icon = value; } private RulesetInfo ruleset; public RulesetInfo Ruleset { - get { return ruleset; } + get => ruleset; set { ruleset = value; @@ -73,6 +73,9 @@ namespace osu.Game.Overlays.Direct iconContainer.FadeTo(Ruleset.ID == obj?.ID ? 1f : 0.5f, 100); } + public override bool HandleKeyboardInput => !bindable.Disabled && base.HandleKeyboardInput; + public override bool HandleMouseInput => !bindable.Disabled && base.HandleMouseInput; + public RulesetToggleButton(Bindable bindable, RulesetInfo ruleset) { this.bindable = bindable; @@ -90,6 +93,7 @@ namespace osu.Game.Overlays.Direct Ruleset = ruleset; bindable.ValueChanged += Bindable_ValueChanged; + bindable.DisabledChanged += isDisabled => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); Bindable_ValueChanged(bindable.Value); Action = () => bindable.Value = Ruleset; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 05866f7002..1da51e4a5a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -87,8 +87,8 @@ namespace osu.Game.Overlays.Toolbar ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(); } - public override bool HandleKeyboardInput => !ruleset.Disabled; - public override bool HandleMouseInput => !ruleset.Disabled; + public override bool HandleKeyboardInput => !ruleset.Disabled && base.HandleKeyboardInput; + public override bool HandleMouseInput => !ruleset.Disabled && base.HandleMouseInput; private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); From 42aa02579bb909918ecc0cd50a6a163366c372aa Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sun, 29 Apr 2018 19:52:33 +0300 Subject: [PATCH 028/302] Add 'Back' global key binding --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index dd8f00f6cd..565d530395 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Input.Bindings { new KeyBinding(InputKey.F8, GlobalAction.ToggleChat), new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), - new KeyBinding(InputKey.F12,GlobalAction.TakeScreenshot), + new KeyBinding(InputKey.F12, GlobalAction.TakeScreenshot), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), @@ -36,6 +36,9 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Down, GlobalAction.DecreaseVolume), new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume), new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), + + new KeyBinding(InputKey.Escape, GlobalAction.Back), + new KeyBinding(InputKey.MouseButton1, GlobalAction.Back) }; public IEnumerable InGameKeyBindings => new[] @@ -76,6 +79,9 @@ namespace osu.Game.Input.Bindings QuickRetry, [Description("Take screenshot")] - TakeScreenshot + TakeScreenshot, + + [Description("Go back")] + Back } } From 804b59ee8073cf54fa475e8dc9780edab842a18d Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sun, 29 Apr 2018 20:15:09 +0300 Subject: [PATCH 029/302] Handle GlobalAction.Back --- osu.Game/Screens/Menu/ButtonSystem.cs | 42 +++++++++++++++++++++------ osu.Game/Screens/OsuScreen.cs | 35 +++++++++++++--------- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index f48e1925c5..8cf0d24f7d 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -6,22 +6,24 @@ using System.Collections.Generic; using System.Linq; using osu.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; +using osu.Framework.Input.Bindings; +using osu.Framework.Threading; using osu.Game.Graphics; +using osu.Game.Input.Bindings; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; -using osu.Framework.Audio.Sample; -using osu.Framework.Audio; -using osu.Framework.Configuration; -using osu.Framework.Threading; namespace osu.Game.Screens.Menu { - public class ButtonSystem : Container, IStateful + public class ButtonSystem : Container, IStateful, IKeyBindingHandler { public event Action StateChanged; @@ -146,7 +148,16 @@ namespace osu.Game.Screens.Menu case Key.Space: logo?.TriggerOnClick(state); return true; - case Key.Escape: + } + + return false; + } + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: switch (State) { case MenuState.TopLevel: @@ -155,14 +166,26 @@ namespace osu.Game.Screens.Menu case MenuState.Play: backButton.TriggerOnClick(); return true; + default: + return false; } - + default: return false; } - - return false; } + public bool OnReleased(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + return true; + default: + return false; + } + } + + private void onPlay() { State = MenuState.Play; @@ -337,6 +360,7 @@ namespace osu.Game.Screens.Menu logo.ScaleTo(0.5f, 200, Easing.OutQuint); break; } + break; case MenuState.EnteringMode: logoTracking = true; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 7a910574e0..5d2c46f438 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -3,22 +3,22 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; -using OpenTK; -using osu.Framework.Audio.Sample; -using osu.Framework.Audio; -using osu.Framework.Graphics; +using osu.Game.Input.Bindings; using osu.Game.Rulesets; using osu.Game.Screens.Menu; -using osu.Framework.Input; -using OpenTK.Input; +using OpenTK; namespace osu.Game.Screens { - public abstract class OsuScreen : Screen + public abstract class OsuScreen : Screen, IKeyBindingHandler { public BackgroundScreen Background { get; private set; } @@ -90,18 +90,27 @@ namespace osu.Game.Screens sampleExit = audio.Sample.Get(@"UI/screen-back"); } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public bool OnPressed(GlobalAction action) { - if (args.Repeat || !IsCurrentScreen) return false; - - switch (args.Key) + switch (action) { - case Key.Escape: + case GlobalAction.Back: Exit(); return true; + default: + return false; } + } - return base.OnKeyDown(state, args); + public bool OnReleased(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + return true; + default: + return false; + } } protected override void OnResuming(Screen last) From 3b84ce7c9f4317cf4a3f3d4e8011385579d6ec1f Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Tue, 1 May 2018 03:56:01 +0300 Subject: [PATCH 030/302] Remove redundant test step --- osu.Game.Tests/Visual/TestCaseHoldToQuit.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs b/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs index d7f024d905..04ea4249e5 100644 --- a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs +++ b/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual var text = holdToQuit.Children.OfType().Single(); - AddStep("Text fade in", () => + AddStep("Trigger text fade in/out", () => { exitAction = false; holdToQuit.Button.TriggerOnMouseDown(); @@ -34,14 +34,6 @@ namespace osu.Game.Tests.Visual }); AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); - - AddStep("Text fade out", () => - { - exitAction = false; - holdToQuit.Button.TriggerOnMouseDown(); - holdToQuit.Button.TriggerOnMouseUp(); - }); - AddUntilStep(() => !text.IsPresent && !exitAction, "Text is not visible"); AddStep("Trigger exit action", () => From 2d6b2d10f7e83376a37433b84d30254c4575d838 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 May 2018 18:26:23 +0900 Subject: [PATCH 031/302] Use bindable transforms --- osu-framework | 2 +- osu.Game/Overlays/ChatOverlay.cs | 25 +---------------- .../UI/Scrolling/ScrollingPlayfield.cs | 27 ++----------------- 3 files changed, 4 insertions(+), 50 deletions(-) diff --git a/osu-framework b/osu-framework index 0773d895d9..96ef8c43b5 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 0773d895d9aa0729995cd4a23efc28238e35ceed +Subproject commit 96ef8c43b5e6b6ae14b01c3550c480c8d9a78518 diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 331dcec4c0..a2542c537f 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -12,10 +12,8 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Transforms; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; -using osu.Framework.MathUtils; using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Graphics; @@ -181,7 +179,7 @@ namespace osu.Game.Overlays { textbox.HoldFocus = false; if (1f - ChatHeight.Value < channel_selection_min_height) - transformChatHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint); + this.TransformBindableTo(ChatHeight, 1f - channel_selection_min_height, 800, Easing.OutQuint); } else textbox.HoldFocus = true; @@ -533,26 +531,5 @@ namespace osu.Game.Overlays api.Queue(req); } - - private void transformChatHeightTo(double newChatHeight, double duration = 0, Easing easing = Easing.None) - { - this.TransformTo(this.PopulateTransform(new TransformChatHeight(), newChatHeight, duration, easing)); - } - - private class TransformChatHeight : Transform - { - private double valueAt(double time) - { - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - - public override string TargetMember => "ChatHeight.Value"; - - protected override void Apply(ChatOverlay d, double time) => d.ChatHeight.Value = valueAt(time); - protected override void ReadIntoStartValue(ChatOverlay d) => StartValue = d.ChatHeight.Value; - } } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 1e7f561aba..6f86d20295 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -4,9 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Transforms; using osu.Framework.Input; -using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; using OpenTK.Input; @@ -90,10 +88,10 @@ namespace osu.Game.Rulesets.UI.Scrolling switch (args.Key) { case Key.Minus: - transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); + this.TransformBindableTo(VisibleTimeRange, VisibleTimeRange + time_span_step, 200, Easing.OutQuint); break; case Key.Plus: - transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); + this.TransformBindableTo(VisibleTimeRange, VisibleTimeRange - time_span_step, 200, Easing.OutQuint); break; } } @@ -101,27 +99,6 @@ namespace osu.Game.Rulesets.UI.Scrolling return false; } - private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) - { - this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); - } - protected sealed override HitObjectContainer CreateHitObjectContainer() => new ScrollingHitObjectContainer(direction); - - private class TransformVisibleTimeRange : Transform - { - private double valueAt(double time) - { - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - - public override string TargetMember => "VisibleTimeRange.Value"; - - protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time); - protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; - } } } From d4ada3000cb059b1a55ea43c3f348d6a731ed4d9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 May 2018 19:37:47 +0900 Subject: [PATCH 032/302] Add keybind to disable mouse buttons --- osu.Game/Configuration/OsuConfigManager.cs | 6 ++++++ osu.Game/Input/Bindings/GlobalActionContainer.cs | 5 ++++- osu.Game/OsuGame.cs | 3 +++ osu.Game/Overlays/OnScreenDisplay.cs | 4 +++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 509622c2fe..b3082e49de 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; +using osu.Framework.Configuration.Tracking; using osu.Framework.Platform; using osu.Game.Overlays; using osu.Game.Screens.Select; @@ -95,6 +96,11 @@ namespace osu.Game.Configuration public OsuConfigManager(Storage storage) : base(storage) { } + + public override TrackedSettings CreateTrackedSettings() => new TrackedSettings + { + new TrackedSetting(OsuSetting.MouseDisableButtons, v => new SettingDescription(!v, "gameplay mouse buttons", v ? "disabled" : "enabled")) + }; } public enum OsuSetting diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index dd8f00f6cd..44e12be1dd 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -26,7 +26,8 @@ namespace osu.Game.Input.Bindings { new KeyBinding(InputKey.F8, GlobalAction.ToggleChat), new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), - new KeyBinding(InputKey.F12,GlobalAction.TakeScreenshot), + new KeyBinding(InputKey.F10, GlobalAction.ToggleMouseButtons), + new KeyBinding(InputKey.F12, GlobalAction.TakeScreenshot), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), @@ -75,6 +76,8 @@ namespace osu.Game.Input.Bindings [Description("Quick Retry (Hold)")] QuickRetry, + [Description("Toggle gameplay mouse buttons")] + ToggleMouseButtons, [Description("Take screenshot")] TakeScreenshot } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d443ed36ae..d2d47a78a6 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -466,6 +466,9 @@ namespace osu.Game case GlobalAction.ToggleDirect: direct.ToggleVisibility(); return true; + case GlobalAction.ToggleMouseButtons: + LocalConfig.Set(OsuSetting.MouseDisableButtons, !LocalConfig.Get(OsuSetting.MouseDisableButtons)); + return true; } return false; diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 3dd088891d..9882ea01f0 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Configuration; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays @@ -116,9 +117,10 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig) + private void load(FrameworkConfigManager frameworkConfig, OsuConfigManager osuConfig) { BeginTracking(this, frameworkConfig); + BeginTracking(this, osuConfig); } private readonly Dictionary<(object, IConfigManager), TrackedSettings> trackedConfigManagers = new Dictionary<(object, IConfigManager), TrackedSettings>(); From 482ae2db87e8cebec289a4b5090282b8a99c4c43 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 May 2018 19:42:03 +0900 Subject: [PATCH 033/302] Unify naming --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 4 ++-- osu.Game/OsuGame.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 44e12be1dd..2ae895785c 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Input.Bindings { new KeyBinding(InputKey.F8, GlobalAction.ToggleChat), new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), - new KeyBinding(InputKey.F10, GlobalAction.ToggleMouseButtons), + new KeyBinding(InputKey.F10, GlobalAction.ToggleGameplayMouseButtons), new KeyBinding(InputKey.F12, GlobalAction.TakeScreenshot), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), @@ -77,7 +77,7 @@ namespace osu.Game.Input.Bindings QuickRetry, [Description("Toggle gameplay mouse buttons")] - ToggleMouseButtons, + ToggleGameplayMouseButtons, [Description("Take screenshot")] TakeScreenshot } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d2d47a78a6..fe5ca4f278 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -466,7 +466,7 @@ namespace osu.Game case GlobalAction.ToggleDirect: direct.ToggleVisibility(); return true; - case GlobalAction.ToggleMouseButtons: + case GlobalAction.ToggleGameplayMouseButtons: LocalConfig.Set(OsuSetting.MouseDisableButtons, !LocalConfig.Get(OsuSetting.MouseDisableButtons)); return true; } From 89db7f81cbd9d1d4b7d452cfc584b259f98751c7 Mon Sep 17 00:00:00 2001 From: Santeri Nogelainen Date: Wed, 2 May 2018 17:11:55 +0300 Subject: [PATCH 034/302] Selecting a mod now triggers on mouseup --- osu.Game/Overlays/Mods/ModButton.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 2a4f243606..3f1541aee3 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -147,18 +147,21 @@ namespace osu.Game.Overlays.Mods public virtual Mod SelectedMod => Mods.ElementAtOrDefault(selectedIndex); - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - switch (args.Button) + // only trigger the event if we are inside the area of the button + if (Contains(ToScreenSpace(state.Mouse.Position - Position))) { - case MouseButton.Left: - SelectNext(1); - break; - case MouseButton.Right: - SelectNext(-1); - break; + switch (args.Button) + { + case MouseButton.Left: + SelectNext(1); + break; + case MouseButton.Right: + SelectNext(-1); + break; + } } - return true; } From 33e2b91cccdc470c924b85688dc6f98fc9d1e3c7 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 3 May 2018 22:59:49 +0300 Subject: [PATCH 035/302] Decouple FilterControl.Ruleset from the game-wide ruleset bindable --- osu.Game/Overlays/Direct/FilterControl.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index a2da516257..4f4348c131 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 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.Configuration; using osu.Framework.Graphics; @@ -12,6 +10,8 @@ using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Rulesets; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays.Direct { @@ -22,6 +22,7 @@ namespace osu.Game.Overlays.Direct protected override Color4 BackgroundColour => OsuColour.FromHex(@"384552"); protected override DirectSortCriteria DefaultTab => DirectSortCriteria.Ranked; + protected override Drawable CreateSupplementaryControls() { modeButtons = new FillFlowContainer @@ -38,7 +39,7 @@ namespace osu.Game.Overlays.Direct { DisplayStyleControl.Dropdown.AccentColour = colours.BlueDark; - Ruleset.BindTo(game?.Ruleset ?? new Bindable { Value = rulesets.GetRuleset(0) }); + Ruleset.Value = game?.Ruleset.Value ?? rulesets.GetRuleset(0); foreach (var r in rulesets.AvailableRulesets) { modeButtons.Add(new RulesetToggleButton(Ruleset, r)); @@ -54,6 +55,7 @@ namespace osu.Game.Overlays.Direct } private RulesetInfo ruleset; + public RulesetInfo Ruleset { get => ruleset; @@ -93,7 +95,6 @@ namespace osu.Game.Overlays.Direct Ruleset = ruleset; bindable.ValueChanged += Bindable_ValueChanged; - bindable.DisabledChanged += isDisabled => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); Bindable_ValueChanged(bindable.Value); Action = () => bindable.Value = Ruleset; } From f8630115d68b7dd610638ab037c8e69282043d00 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 3 May 2018 23:29:58 +0300 Subject: [PATCH 036/302] Do not expose HoldToQuit.HoldToQuitButton --- osu.Game.Tests/Visual/TestCaseHoldToQuit.cs | 10 +++++----- osu.Game/Screens/Play/HUD/HoldToQuit.cs | 9 +++++++-- osu.Game/Screens/Play/Player.cs | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs b/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs index 04ea4249e5..a9b391cd79 100644 --- a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs +++ b/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs @@ -22,15 +22,15 @@ namespace osu.Game.Tests.Visual Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, }); - holdToQuit.Button.ExitAction = () => exitAction = true; + holdToQuit.ExitAction = () => exitAction = true; var text = holdToQuit.Children.OfType().Single(); AddStep("Trigger text fade in/out", () => { exitAction = false; - holdToQuit.Button.TriggerOnMouseDown(); - holdToQuit.Button.TriggerOnMouseUp(); + holdToQuit.TriggerOnMouseDown(); + holdToQuit.TriggerOnMouseUp(); }); AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); @@ -39,10 +39,10 @@ namespace osu.Game.Tests.Visual AddStep("Trigger exit action", () => { exitAction = false; - holdToQuit.Button.TriggerOnMouseDown(); + holdToQuit.TriggerOnMouseDown(); }); - AddUntilStep(() => exitAction, $"{nameof(holdToQuit.Button.ExitAction)} was triggered"); + AddUntilStep(() => exitAction, $"{nameof(holdToQuit.ExitAction)} was triggered"); } } } diff --git a/osu.Game/Screens/Play/HUD/HoldToQuit.cs b/osu.Game/Screens/Play/HUD/HoldToQuit.cs index 59338f8cdc..ee67dd35f8 100644 --- a/osu.Game/Screens/Play/HUD/HoldToQuit.cs +++ b/osu.Game/Screens/Play/HUD/HoldToQuit.cs @@ -16,7 +16,12 @@ namespace osu.Game.Screens.Play.HUD { public class HoldToQuit : FillFlowContainer { - public readonly HoldToQuitButton Button; + private readonly HoldToQuitButton button; + public Action ExitAction + { + get => button.ExitAction; + set => button.ExitAction = value; + } public HoldToQuit() { @@ -32,7 +37,7 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }, - Button = new HoldToQuitButton(text) + button = new HoldToQuitButton(text) }; AutoSizeAxes = Axes.Both; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 836730e3f3..540950a853 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -216,7 +216,7 @@ namespace osu.Game.Screens.Play } }; - hudOverlay.HoldToQuit.Button.ExitAction = Exit; + hudOverlay.HoldToQuit.ExitAction = Exit; if (ShowStoryboard) initializeStoryboard(false); From 39db1e8cbb9ba539838e1ac4b117e1611cf04063 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 3 May 2018 23:50:30 +0300 Subject: [PATCH 037/302] Rename HoldToQuit to QuitButton --- osu.Game.Tests/Visual/TestCaseHoldToQuit.cs | 4 ++-- .../Play/HUD/{HoldToQuit.cs => QuitButton.cs} | 12 ++++++------ osu.Game/Screens/Play/HUDOverlay.cs | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) rename osu.Game/Screens/Play/HUD/{HoldToQuit.cs => QuitButton.cs} (91%) diff --git a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs b/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs index a9b391cd79..9a2228c23c 100644 --- a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs +++ b/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs @@ -16,8 +16,8 @@ namespace osu.Game.Tests.Visual public TestCaseHoldToQuit() { - HoldToQuit holdToQuit; - Add(holdToQuit = new HoldToQuit + QuitButton holdToQuit; + Add(holdToQuit = new QuitButton { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, diff --git a/osu.Game/Screens/Play/HUD/HoldToQuit.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs similarity index 91% rename from osu.Game/Screens/Play/HUD/HoldToQuit.cs rename to osu.Game/Screens/Play/HUD/QuitButton.cs index ee67dd35f8..aa6dc388ac 100644 --- a/osu.Game/Screens/Play/HUD/HoldToQuit.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -14,16 +14,16 @@ using OpenTK; namespace osu.Game.Screens.Play.HUD { - public class HoldToQuit : FillFlowContainer + public class QuitButton : FillFlowContainer { - private readonly HoldToQuitButton button; + private readonly Button button; public Action ExitAction { get => button.ExitAction; set => button.ExitAction = value; } - public HoldToQuit() + public QuitButton() { OsuSpriteText text; Direction = FillDirection.Horizontal; @@ -37,12 +37,12 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }, - button = new HoldToQuitButton(text) + button = new Button(text) }; AutoSizeAxes = Axes.Both; } - public class HoldToQuitButton : CircularContainer + private class Button : CircularContainer { private readonly OsuSpriteText text; private SpriteIcon icon; @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Play.HUD private const int progress_duration = 1000; private const int text_display_time = 5000; - public HoldToQuitButton(OsuSpriteText text) => this.text = text; + public Button(OsuSpriteText text) => this.text = text; [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index c2471c967e..cba5c94266 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Play public readonly HealthDisplay HealthDisplay; public readonly SongProgress Progress; public readonly ModDisplay ModDisplay; - public readonly HoldToQuit HoldToQuit; + public readonly QuitButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; private Bindable showHud; @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Play AccuracyCounter = CreateAccuracyCounter(), HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), - HoldToQuit = CreateHoldToQuit(), + HoldToQuit = CreateQuitButton(), ModDisplay = CreateModsContainer(), PlayerSettingsOverlay = CreatePlayerSettingsOverlay() } @@ -207,11 +207,11 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.X, }; - protected virtual HoldToQuit CreateHoldToQuit() => new HoldToQuit + protected virtual QuitButton CreateQuitButton() => new QuitButton { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, - Margin = new MarginPadding { Bottom = Progress.Size.Y * 1.25f, Right = 5 } + Position = new Vector2(-5, -70) }; protected virtual ModDisplay CreateModsContainer() => new ModDisplay From b0e556d83fd1367fc4156516c026255b26f5cac2 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 4 May 2018 00:01:00 +0300 Subject: [PATCH 038/302] Actualize QuitButton visual test --- ...aseHoldToQuit.cs => TestCaseQuitButton.cs} | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) rename osu.Game.Tests/Visual/{TestCaseHoldToQuit.cs => TestCaseQuitButton.cs} (60%) diff --git a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs b/osu.Game.Tests/Visual/TestCaseQuitButton.cs similarity index 60% rename from osu.Game.Tests/Visual/TestCaseHoldToQuit.cs rename to osu.Game.Tests/Visual/TestCaseQuitButton.cs index 9a2228c23c..545a8ff57b 100644 --- a/osu.Game.Tests/Visual/TestCaseHoldToQuit.cs +++ b/osu.Game.Tests/Visual/TestCaseQuitButton.cs @@ -4,33 +4,36 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual { [Description("'Hold to Quit' UI element")] - public class TestCaseHoldToQuit : OsuTestCase + public class TestCaseQuitButton : OsuTestCase { + private readonly QuitButton quitButton; + private Drawable innerButton => quitButton.Children.Single(child => child is CircularContainer); private bool exitAction; - public TestCaseHoldToQuit() + public TestCaseQuitButton() { - QuitButton holdToQuit; - Add(holdToQuit = new QuitButton + Add(quitButton = new QuitButton { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, }); - holdToQuit.ExitAction = () => exitAction = true; + quitButton.ExitAction = () => exitAction = true; - var text = holdToQuit.Children.OfType().Single(); + var text = quitButton.Children.OfType().Single(); AddStep("Trigger text fade in/out", () => { exitAction = false; - holdToQuit.TriggerOnMouseDown(); - holdToQuit.TriggerOnMouseUp(); + + innerButton.TriggerOnMouseDown(); + innerButton.TriggerOnMouseUp(); }); AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); @@ -39,10 +42,10 @@ namespace osu.Game.Tests.Visual AddStep("Trigger exit action", () => { exitAction = false; - holdToQuit.TriggerOnMouseDown(); + innerButton.TriggerOnMouseDown(); }); - AddUntilStep(() => exitAction, $"{nameof(holdToQuit.ExitAction)} was triggered"); + AddUntilStep(() => exitAction, $"{nameof(quitButton.ExitAction)} was triggered"); } } } From b08b24b6da17260a2a028b6a070e36093429f6a4 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 4 May 2018 21:18:48 +0300 Subject: [PATCH 039/302] Introduce OsuScreen.AllowBackButton property --- osu.Game/Screens/OsuScreen.cs | 24 ++++++++---------------- osu.Game/Screens/Play/PlayerLoader.cs | 1 + 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 5d2c46f438..fb5d3d12e6 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -22,6 +22,8 @@ namespace osu.Game.Screens { public BackgroundScreen Background { get; private set; } + protected virtual bool AllowBackButton => true; + /// /// Override to create a BackgroundMode for the current screen. /// Note that the instance created may not be the used instance if it matches the BackgroundMode equality clause. @@ -92,26 +94,16 @@ namespace osu.Game.Screens public bool OnPressed(GlobalAction action) { - switch (action) + if (action == GlobalAction.Back && AllowBackButton) { - case GlobalAction.Back: - Exit(); - return true; - default: - return false; + Exit(); + return true; } + + return false; } - public bool OnReleased(GlobalAction action) - { - switch (action) - { - case GlobalAction.Back: - return true; - default: - return false; - } - } + public bool OnReleased(GlobalAction action) => action == GlobalAction.Back && AllowBackButton; protected override void OnResuming(Screen last) { diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 56fbd7b6e7..6eb156914e 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -27,6 +27,7 @@ namespace osu.Game.Screens.Play private bool showOverlays = true; public override bool ShowOverlaysOnEnter => showOverlays; + protected override bool AllowBackButton => false; private Task loadTask; From f3aa9269ff3e9b2cdcde32c4c552794af0d41148 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 09:17:12 +0900 Subject: [PATCH 040/302] Fix mania-specific beatmap conversion --- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 93feddc143..acd289a9e8 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps var roundedCircleSize = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize); var roundedOverallDifficulty = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); - if (beatmap.BeatmapInfo.Ruleset == new ManiaRuleset().RulesetInfo) + if (IsForCurrentRuleset) TargetColumns = (int)Math.Max(1, roundedCircleSize); else { diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 6f117332b2..f4c78fd195 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -118,7 +118,8 @@ namespace osu.Game.Rulesets Name = Description, ShortName = ShortName, InstantiationInfo = GetType().AssemblyQualifiedName, - ID = LegacyID + ID = LegacyID, + Available = true }; } } From 20509b1cc2813a98829a31fa7e3663dc7131e3b4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 09:59:45 +0900 Subject: [PATCH 041/302] Fix non-IBeatmap usage --- osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index f6b0bb56c9..efd6c36ce2 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual AddAssert("check no infolabels", () => !infoWedge.Info.InfoLabelContainer.Children.Any()); } - private void selectBeatmap(Beatmap b) + private void selectBeatmap(IBeatmap b) { BeatmapInfoWedge.BufferedWedgeInfo infoBefore = null; From 27c8591d48d911e3884f755daabcf035e29b7e96 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:07:50 +0900 Subject: [PATCH 042/302] Fix reference to old name --- osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index efd6c36ce2..22945e726c 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual }); // select part is redundant, but wait for load isn't - selectBeatmap(beatmap.Value.Beatmap); + selectBeatmap(beatmap.Value.OriginalBeatmap); AddWaitStep(3); From 4ecdea8b2eb12282a9360b8048b3fb4cd033275b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:17:54 +0900 Subject: [PATCH 043/302] Remove now-unnecessary IsForCurrentRuleset property of RulesetContainer --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../UI/CatchRulesetContainer.cs | 4 ++-- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs | 8 ++++++-- .../UI/ManiaRulesetContainer.cs | 4 ++-- .../Edit/OsuEditRulesetContainer.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs | 4 ++-- .../TestCaseTaikoPlayfield.cs | 2 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- .../UI/TaikoRulesetContainer.cs | 4 ++-- osu.Game.Tests/Visual/TestCaseReplay.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 3 +-- osu.Game/Rulesets/UI/RulesetContainer.cs | 14 +++----------- .../UI/Scrolling/ScrollingRulesetContainer.cs | 4 ++-- osu.Game/Screens/Play/Player.cs | 4 ++-- 18 files changed, 31 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index f091fbbee4..15e51fa126 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchRulesetContainer(this, beatmap, isForCurrentRuleset); + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new CatchRulesetContainer(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 6e8a2c1660..070dc19a6f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -19,8 +19,8 @@ namespace osu.Game.Rulesets.Catch.UI { public class CatchRulesetContainer : ScrollingRulesetContainer { - public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(ruleset, beatmap, isForCurrentRuleset) + public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 75b1e38a2f..f1d65f855b 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaRulesetContainer(this, beatmap, isForCurrentRuleset); + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override IEnumerable ConvertLegacyMods(LegacyMods mods) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs index dde8acf428..7f3985b26d 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs @@ -18,12 +18,16 @@ namespace osu.Game.Rulesets.Mania.Mods public override string Description => @"Double the stages, double the fun!"; public override double ScoreMultiplier => 0; + private bool isForCurrentRuleset; + public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter) { var mbc = (ManiaBeatmapConverter)beatmapConverter; + isForCurrentRuleset = mbc.IsForCurrentRuleset; + // Although this can work, for now let's not allow keymods for mania-specific beatmaps - if (mbc.IsForCurrentRuleset) + if (isForCurrentRuleset) return; mbc.TargetColumns *= 2; @@ -34,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Mods var mrc = (ManiaRulesetContainer)rulesetContainer; // Although this can work, for now let's not allow keymods for mania-specific beatmaps - if (mrc.IsForCurrentRuleset) + if (isForCurrentRuleset) return; var newDefinitions = new List(); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 059eaaadcd..7123aab901 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -36,8 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; - public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(ruleset, beatmap, isForCurrentRuleset) + public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { // Generate the bar lines double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs index 8d4c342740..dce43f5bbb 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Edit public class OsuEditRulesetContainer : OsuRulesetContainer { public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(ruleset, beatmap, isForCurrentRuleset) + : base(ruleset, beatmap) { } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 02b887f1b9..ffc421217c 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuRulesetContainer(this, beatmap, isForCurrentRuleset); + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new OsuRulesetContainer(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index 603f95dc47..ad1052f86a 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -20,8 +20,8 @@ namespace osu.Game.Rulesets.Osu.UI { public class OsuRulesetContainer : RulesetContainer { - public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(ruleset, beatmap, isForCurrentRuleset) + public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index aa7318b863..f67726c022 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Tests RelativeSizeAxes = Axes.X, Height = 768, Clock = new FramedClock(rateAdjustClock), - Children = new[] { rulesetContainer = new TaikoRulesetContainer(rulesets.GetRuleset(1).CreateInstance(), beatmap, true) } + Children = new[] { rulesetContainer = new TaikoRulesetContainer(rulesets.GetRuleset(1).CreateInstance(), beatmap) } }); } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 2e27b34e69..102de5717f 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoRulesetContainer(this, beatmap, isForCurrentRuleset); + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new TaikoRulesetContainer(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 0a84d74c27..313c205981 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -23,8 +23,8 @@ namespace osu.Game.Rulesets.Taiko.UI { public class TaikoRulesetContainer : ScrollingRulesetContainer { - public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(ruleset, beatmap, isForCurrentRuleset) + public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } diff --git a/osu.Game.Tests/Visual/TestCaseReplay.cs b/osu.Game.Tests/Visual/TestCaseReplay.cs index 6ba671c7fc..5bc16fe420 100644 --- a/osu.Game.Tests/Visual/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/TestCaseReplay.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual // We create a dummy RulesetContainer just to get the replay - we don't want to use mods here // to simulate setting a replay rather than having the replay already set for us beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); - var dummyRulesetContainer = ruleset.CreateRulesetContainerWith(beatmap, beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo)); + var dummyRulesetContainer = ruleset.CreateRulesetContainerWith(beatmap); // We have the replay var replay = dummyRulesetContainer.Replay; diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 23ddc5a976..956034a279 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps { public override IEnumerable GetModsFor(ModType type) => new Mod[] { }; - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) { throw new NotImplementedException(); } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1820053d3d..5f1b9a6bad 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Edit private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool; - protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true); + protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap); protected abstract IReadOnlyList CompositionTools { get; } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index f4c78fd195..d6d1d19628 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -52,10 +52,9 @@ namespace osu.Game.Rulesets /// Attempt to create a hit renderer for a beatmap /// /// The beatmap to create the hit renderer for. - /// Whether the hit renderer should assume the beatmap is for the current ruleset. /// Unable to successfully load the beatmap to be usable with this ruleset. /// - public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset); + public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap); public abstract IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap); diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 074380da56..3a2e66505a 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -190,11 +190,6 @@ namespace osu.Game.Rulesets.UI /// protected readonly WorkingBeatmap WorkingBeatmap; - /// - /// Whether the specified beatmap is assumed to be specific to the current ruleset. - /// - public readonly bool IsForCurrentRuleset; - public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); protected override Container Content => content; @@ -206,14 +201,12 @@ namespace osu.Game.Rulesets.UI /// /// The ruleset being repesented. /// The beatmap to create the hit renderer for. - /// Whether to assume the beatmap is for the current ruleset. - protected RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap, bool isForCurrentRuleset) + protected RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap) : base(ruleset) { Debug.Assert(workingBeatmap != null, "RulesetContainer initialized with a null beatmap."); WorkingBeatmap = workingBeatmap; - IsForCurrentRuleset = isForCurrentRuleset; // ReSharper disable once PossibleNullReferenceException Mods = workingBeatmap.Mods.Value; @@ -337,9 +330,8 @@ namespace osu.Game.Rulesets.UI /// /// The ruleset being repesented. /// The beatmap to create the hit renderer for. - /// Whether to assume the beatmap is for the current ruleset. - protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(ruleset, beatmap, isForCurrentRuleset) + protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index 79f9eaa9e9..efd901240a 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.UI.Scrolling /// protected readonly SortedList DefaultControlPoints = new SortedList(Comparer.Default); - protected ScrollingRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(ruleset, beatmap, isForCurrentRuleset) + protected ScrollingRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d5edff3a0c..d39b28bf25 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Play try { - RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working, ruleset.ID == beatmap.BeatmapInfo.Ruleset.ID); + RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working); } catch (BeatmapInvalidForRulesetException) { @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Play // let's try again forcing the beatmap's ruleset. ruleset = beatmap.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); - RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap, true); + RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap); } if (!RulesetContainer.Objects.Any()) From b68ee39136bc5ac8359a96db294b509066a4ad71 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:18:47 +0900 Subject: [PATCH 044/302] Reword beatmap conversion error --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 7d6c23dad0..2afaaf13f9 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -87,7 +87,7 @@ namespace osu.Game.Beatmaps // Check if the beatmap can be converted if (!converter.CanConvert) - throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the current ruleset (converter: {converter})."); + throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the ruleset (ruleset: {ruleset}, converter: {converter})."); // Apply conversion mods foreach (var mod in Mods.Value.OfType()) From 7e83c75888a0b7f0ef04cc062f5f2174512cabcc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:23:32 +0900 Subject: [PATCH 045/302] Add xmldoc --- osu.Game/Beatmaps/WorkingBeatmap.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 2afaaf13f9..ae83a14d61 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -79,6 +79,13 @@ namespace osu.Game.Beatmaps return b; } + /// + /// Retrieves the resulting from the conversion of to a specific . + /// All mods have been applied to the returned . + /// + /// The to convert to. + /// The converted . + /// If could not be converted to . public IBeatmap GetBeatmap(RulesetInfo ruleset) { var rulesetInstance = ruleset.CreateInstance(); From 9128e64c9a907e5cf2990115e305c0966a3ac28e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:29:38 +0900 Subject: [PATCH 046/302] Rename OriginalBeatmap back to Beatmap --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Beatmaps/IO/ImportBeatmapTest.cs | 8 ++--- .../Visual/TestCaseBeatSyncedContainer.cs | 2 +- .../Visual/TestCaseBeatmapInfoWedge.cs | 2 +- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 30 +++++++++---------- .../Containers/BeatSyncedContainer.cs | 2 +- osu.Game/Overlays/MusicController.cs | 2 +- .../Scoring/Legacy/LegacyScoreParser.cs | 2 +- .../Timelines/Summary/Parts/BreakPart.cs | 2 +- .../Summary/Parts/ControlPointPart.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageScore.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 +- osu.Game/Tests/Visual/EditorClockTestCase.cs | 2 +- .../Tests/Visual/TestCasePerformancePoints.cs | 4 +-- 20 files changed, 38 insertions(+), 38 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index ffc421217c..927ffa2146 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) { - IEnumerable hitObjects = beatmap.OriginalBeatmap.HitObjects; + 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)); diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 3530ae928d..f60caf2397 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -274,13 +274,13 @@ namespace osu.Game.Tests.Beatmaps.IO foreach (BeatmapInfo b in set.Beatmaps) Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID)); Assert.IsTrue(set.Beatmaps.Count > 0); - var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.OriginalBeatmap; + var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Any() == true); - beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.OriginalBeatmap; + beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Any() == true); - beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.OriginalBeatmap; + beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Any() == true); - beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.OriginalBeatmap; + beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Any() == true); } diff --git a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs index 4e3462b5ea..596b7839e0 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs @@ -139,7 +139,7 @@ namespace osu.Game.Tests.Visual }; } - private SortedList timingPoints => Beatmap.Value.OriginalBeatmap.ControlPointInfo.TimingPoints; + private SortedList timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { if (timingPoints[timingPoints.Count - 1] == current) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index 22945e726c..efd6c36ce2 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual }); // select part is redundant, but wait for load isn't - selectBeatmap(beatmap.Value.OriginalBeatmap); + selectBeatmap(beatmap.Value.Beatmap); AddWaitStep(3); diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index cff500fabf..71406c6034 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps this.audioManager = audioManager; } - protected override IBeatmap GetOriginalBeatmap() + protected override IBeatmap GetBeatmap() { try { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 956034a279..da52dc7284 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -40,7 +40,7 @@ namespace osu.Game.Beatmaps this.game = game; } - protected override IBeatmap GetOriginalBeatmap() => new Beatmap(); + protected override IBeatmap GetBeatmap() => new Beatmap(); protected override Texture GetBackground() => game.Textures.Get(@"Backgrounds/bg4"); diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index ae83a14d61..e90df687e4 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -38,7 +38,7 @@ namespace osu.Game.Beatmaps Mods.ValueChanged += mods => applyRateAdjustments(); - originalBeatmap = new AsyncLazy(populateOriginalBeatmap); + beatmap = new AsyncLazy(populateBeatmap); background = new AsyncLazy(populateBackground, b => b == null || !b.IsDisposed); track = new AsyncLazy(populateTrack); waveform = new AsyncLazy(populateWaveform); @@ -47,31 +47,31 @@ namespace osu.Game.Beatmaps } /// - /// Saves the . + /// Saves the . /// public void Save() { var path = FileSafety.GetTempPath(Guid.NewGuid().ToString().Replace("-", string.Empty) + ".json"); using (var sw = new StreamWriter(path)) - sw.WriteLine(OriginalBeatmap.Serialize()); + sw.WriteLine(Beatmap.Serialize()); Process.Start(path); } - protected abstract IBeatmap GetOriginalBeatmap(); + protected abstract IBeatmap GetBeatmap(); protected abstract Texture GetBackground(); protected abstract Track GetTrack(); protected virtual Skin GetSkin() => new DefaultSkin(); protected virtual Waveform GetWaveform() => new Waveform(); protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo }; - public bool BeatmapLoaded => originalBeatmap.IsResultAvailable; - public IBeatmap OriginalBeatmap => originalBeatmap.Value.Result; - public async Task GetOriginalBeatmapAsync() => await originalBeatmap.Value; - private readonly AsyncLazy originalBeatmap; + public bool BeatmapLoaded => beatmap.IsResultAvailable; + public IBeatmap Beatmap => beatmap.Value.Result; + public async Task GetBeatmapAsync() => await beatmap.Value; + private readonly AsyncLazy beatmap; - private IBeatmap populateOriginalBeatmap() + private IBeatmap populateBeatmap() { - var b = GetOriginalBeatmap() ?? new Beatmap(); + var b = GetBeatmap() ?? new Beatmap(); // use the database-backed info. b.BeatmapInfo = BeatmapInfo; @@ -80,21 +80,21 @@ namespace osu.Game.Beatmaps } /// - /// Retrieves the resulting from the conversion of to a specific . + /// Retrieves the resulting from the conversion of to a specific . /// All mods have been applied to the returned . /// - /// The to convert to. + /// The to convert to. /// The converted . - /// If could not be converted to . + /// If could not be converted to . public IBeatmap GetBeatmap(RulesetInfo ruleset) { var rulesetInstance = ruleset.CreateInstance(); - IBeatmapConverter converter = rulesetInstance.CreateBeatmapConverter(OriginalBeatmap); + IBeatmapConverter converter = rulesetInstance.CreateBeatmapConverter(Beatmap); // Check if the beatmap can be converted if (!converter.CanConvert) - throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the ruleset (ruleset: {ruleset}, converter: {converter})."); + throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset}, converter: {converter})."); // Apply conversion mods foreach (var mod in Mods.Value.OfType()) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 8d8717a612..bf16af4706 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -38,7 +38,7 @@ namespace osu.Game.Graphics.Containers if (!Beatmap.Value.TrackLoaded || !Beatmap.Value.BeatmapLoaded) return; var track = Beatmap.Value.Track; - var beatmap = Beatmap.Value.OriginalBeatmap; + var beatmap = Beatmap.Value.Beatmap; if (track == null || beatmap == null) return; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index eb88fe0eb4..b4021f2808 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -343,7 +343,7 @@ namespace osu.Game.Overlays // todo: this can likely be replaced with WorkingBeatmap.GetBeatmapAsync() Task.Run(() => { - if (beatmap?.OriginalBeatmap == null) //this is not needed if a placeholder exists + if (beatmap?.Beatmap == null) //this is not needed if a placeholder exists { title.Current = null; title.Text = @"Nothing to play"; diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs index 3145561001..d5ab856697 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Scoring.Legacy /* score.FileChecksum = */ var beatmapHash = sr.ReadString(); score.Beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == beatmapHash); - currentBeatmap = beatmaps.GetWorkingBeatmap(score.Beatmap).OriginalBeatmap; + currentBeatmap = beatmaps.GetWorkingBeatmap(score.Beatmap).Beatmap; /* score.PlayerName = */ score.User = new User { Username = sr.ReadString() }; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs index e081897339..1146037004 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected override void LoadBeatmap(WorkingBeatmap beatmap) { base.LoadBeatmap(beatmap); - foreach (var breakPeriod in beatmap.OriginalBeatmap.Breaks) + foreach (var breakPeriod in beatmap.Beatmap.Breaks) Add(new BreakVisualisation(breakPeriod)); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs index faf090bfd9..4bef22463e 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { base.LoadBeatmap(beatmap); - ControlPointInfo cpi = beatmap.OriginalBeatmap.ControlPointInfo; + ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; cpi.TimingPoints.ForEach(addTimingPoint); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index a9324e3fb0..adb749b492 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Edit { // TODO: should probably be done at a RulesetContainer level to share logic with Player. var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); - clock = new EditorClock(Beatmap.Value.OriginalBeatmap.ControlPointInfo, beatDivisor) { IsCoupled = false }; + clock = new EditorClock(Beatmap.Value.Beatmap.ControlPointInfo, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); dependencies.CacheAs(clock); diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index bbd50d8f1b..1f2cb915b3 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Menu private void updateAmplitudes() { var track = beatmap.Value.TrackLoaded ? beatmap.Value.Track : null; - var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.OriginalBeatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null; + var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null; float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes ?? new float[256]; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d39b28bf25..f397d0c3d4 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -97,7 +97,7 @@ namespace osu.Game.Screens.Play try { - beatmap = working.OriginalBeatmap; + beatmap = working.Beatmap; if (beatmap == null) throw new InvalidOperationException("Beatmap was not loaded"); diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 862f77d219..42d8af07b9 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -88,7 +88,7 @@ namespace osu.Game.Screens.Ranking { RelativeSizeAxes = Axes.Both, Alpha = 0.5f, - Objects = Beatmap.OriginalBeatmap.HitObjects, + Objects = Beatmap.Beatmap.HitObjects, }, scoreCounter = new SlowScoreCounter(6) { diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 2dad5a9008..da82a49f51 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -210,7 +210,7 @@ namespace osu.Game.Screens.Select private InfoLabel[] getInfoLabels() { - var beatmap = working.OriginalBeatmap; + var beatmap = working.Beatmap; var info = working.BeatmapInfo; List labels = new List(); diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 71893cfe37..37693c99e8 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps } private readonly IBeatmap beatmap; - protected override IBeatmap GetOriginalBeatmap() => beatmap; + protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; protected override Track GetTrack() diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestCase.cs index c6a98a4f43..43b20f7021 100644 --- a/osu.Game/Tests/Visual/EditorClockTestCase.cs +++ b/osu.Game/Tests/Visual/EditorClockTestCase.cs @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(WorkingBeatmap working) { - Clock.ControlPointInfo = working.OriginalBeatmap.ControlPointInfo; + Clock.ControlPointInfo = working.Beatmap.ControlPointInfo; Clock.ChangeSource((IAdjustableClock)working.Track ?? new StopwatchClock()); Clock.ProcessFrame(); } diff --git a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs index 5d78b95c04..51460ecb6d 100644 --- a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs +++ b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs @@ -250,7 +250,7 @@ namespace osu.Game.Tests.Visual return; lastRequest = new GetScoresRequest(newBeatmap.BeatmapInfo, newBeatmap.BeatmapInfo.Ruleset); - lastRequest.Success += res => res.Scores.ForEach(s => scores.Add(new PerformanceDisplay(s, newBeatmap.OriginalBeatmap))); + lastRequest.Success += res => res.Scores.ForEach(s => scores.Add(new PerformanceDisplay(s, newBeatmap.Beatmap))); api.Queue(lastRequest); } @@ -381,7 +381,7 @@ namespace osu.Game.Tests.Visual var allMods = ruleset.GetAllMods().ToList(); Mod[] activeMods = modFlow.Where(c => c.Current.Value).Select(c => allMods.First(m => m.ShortenedName == c.LabelText)).ToArray(); - var diffCalc = ruleset.CreateDifficultyCalculator(beatmap.OriginalBeatmap, activeMods); + var diffCalc = ruleset.CreateDifficultyCalculator(beatmap.Beatmap, activeMods); if (diffCalc != null) { var categories = new Dictionary(); From db3e48c194ed7a0838b3390dab7152cf37ecde84 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:40:30 +0900 Subject: [PATCH 047/302] Rename GetBeatmap() to GetPlayableBeatmap() --- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 15 +++++++++------ osu.Game/Rulesets/UI/RulesetContainer.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 71406c6034..400c877d6a 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps this.audioManager = audioManager; } - protected override IBeatmap GetBeatmap() + protected override IBeatmap GetPlayableBeatmap() { try { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index da52dc7284..2c9d83fe9e 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -40,7 +40,7 @@ namespace osu.Game.Beatmaps this.game = game; } - protected override IBeatmap GetBeatmap() => new Beatmap(); + protected override IBeatmap GetPlayableBeatmap() => new Beatmap(); protected override Texture GetBackground() => game.Textures.Get(@"Backgrounds/bg4"); diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index e90df687e4..515b7c2051 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -57,7 +57,7 @@ namespace osu.Game.Beatmaps Process.Start(path); } - protected abstract IBeatmap GetBeatmap(); + protected abstract IBeatmap GetPlayableBeatmap(); protected abstract Texture GetBackground(); protected abstract Track GetTrack(); protected virtual Skin GetSkin() => new DefaultSkin(); @@ -71,7 +71,7 @@ namespace osu.Game.Beatmaps private IBeatmap populateBeatmap() { - var b = GetBeatmap() ?? new Beatmap(); + var b = GetPlayableBeatmap() ?? new Beatmap(); // use the database-backed info. b.BeatmapInfo = BeatmapInfo; @@ -80,13 +80,16 @@ namespace osu.Game.Beatmaps } /// - /// Retrieves the resulting from the conversion of to a specific . - /// All mods have been applied to the returned . + /// Constructs a playable from using the applicable converters for a specific . + /// + /// The returned is in a playable state - all and s + /// have been applied, and s have been fully constructed. + /// /// - /// The to convert to. + /// The to create a playable for. /// The converted . /// If could not be converted to . - public IBeatmap GetBeatmap(RulesetInfo ruleset) + public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset) { var rulesetInstance = ruleset.CreateInstance(); diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 3a2e66505a..e42e74c245 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -212,7 +212,7 @@ namespace osu.Game.Rulesets.UI RelativeSizeAxes = Axes.Both; - Beatmap = (Beatmap)workingBeatmap.GetBeatmap(ruleset.RulesetInfo); + Beatmap = (Beatmap)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo); KeyBindingInputManager = CreateInputManager(); KeyBindingInputManager.RelativeSizeAxes = Axes.Both; diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 37693c99e8..fbbe7d5284 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps } private readonly IBeatmap beatmap; - protected override IBeatmap GetBeatmap() => beatmap; + protected override IBeatmap GetPlayableBeatmap() => beatmap; protected override Texture GetBackground() => null; protected override Track GetTrack() From 794418432f53b9be47e3495307d0c6fd5a8f4345 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:22:25 +0900 Subject: [PATCH 048/302] Fix incorrect method name --- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 ++-- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 400c877d6a..71406c6034 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps this.audioManager = audioManager; } - protected override IBeatmap GetPlayableBeatmap() + protected override IBeatmap GetBeatmap() { try { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 2c9d83fe9e..da52dc7284 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -40,7 +40,7 @@ namespace osu.Game.Beatmaps this.game = game; } - protected override IBeatmap GetPlayableBeatmap() => new Beatmap(); + protected override IBeatmap GetBeatmap() => new Beatmap(); protected override Texture GetBackground() => game.Textures.Get(@"Backgrounds/bg4"); diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 515b7c2051..2a3eb05544 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -57,7 +57,7 @@ namespace osu.Game.Beatmaps Process.Start(path); } - protected abstract IBeatmap GetPlayableBeatmap(); + protected abstract IBeatmap GetBeatmap(); protected abstract Texture GetBackground(); protected abstract Track GetTrack(); protected virtual Skin GetSkin() => new DefaultSkin(); @@ -71,7 +71,7 @@ namespace osu.Game.Beatmaps private IBeatmap populateBeatmap() { - var b = GetPlayableBeatmap() ?? new Beatmap(); + var b = GetBeatmap() ?? new Beatmap(); // use the database-backed info. b.BeatmapInfo = BeatmapInfo; diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index fbbe7d5284..37693c99e8 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps } private readonly IBeatmap beatmap; - protected override IBeatmap GetPlayableBeatmap() => beatmap; + protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; protected override Track GetTrack() From e20323b5f6408a3bc3e5ba230a7a6e14eec7b18d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:23:29 +0900 Subject: [PATCH 049/302] Trim whitespace --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 2 +- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 3b22c47ac8..4a0b120e47 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps : base(beatmap) { } - + protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index acd289a9e8..c8a7402904 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps : base(beatmap) { IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo); - + var roundedCircleSize = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize); var roundedOverallDifficulty = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); From 268c14813b826f706de133e96ab6f4129030e01c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:38:41 +0900 Subject: [PATCH 050/302] Fix resharper warnings --- osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs | 5 +---- osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs | 2 +- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index e52fc11518..cf79feb16b 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -18,13 +18,10 @@ namespace osu.Game.Rulesets.Mania.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; - private bool isForCurrentRuleset; - [NonParallelizable] [TestCase("basic", false)] - public void Test(string name, bool isForCurrentRuleset) + public new void Test(string name) { - this.isForCurrentRuleset = isForCurrentRuleset; base.Test(name); } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs index dce43f5bbb..ea33ec9ae0 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuEditRulesetContainer : OsuRulesetContainer { - public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 7bf0651443..dce1fc2851 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Edit { } - protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new OsuEditRulesetContainer(ruleset, beatmap, true); + protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new OsuEditRulesetContainer(ruleset, beatmap); protected override IReadOnlyList CompositionTools => new ICompositionTool[] { From ad2c2a5fe6a3dbc17e1d2267506796ecc2f2f714 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 12:25:21 +0900 Subject: [PATCH 051/302] Restore star difficulty calculation --- osu.Game/Beatmaps/BeatmapManager.cs | 31 +++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 14436fce13..36fde8a319 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -9,7 +9,9 @@ using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.Extensions; +using osu.Framework.Graphics.Textures; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Beatmaps.Formats; @@ -341,9 +343,16 @@ namespace osu.Game.Beatmaps RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); - // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.Ruleset = ruleset; - beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0; + + if (ruleset != null) + { + // TODO: this should be done in a better place once we actually need to dynamically update it. + var converted = new DummyConversionBeatmap(beatmap).GetPlayableBeatmap(ruleset); + beatmap.BeatmapInfo.StarDifficulty = ruleset.CreateInstance().CreateDifficultyCalculator(converted).Calculate(); + } + else + beatmap.BeatmapInfo.StarDifficulty = 0; beatmapInfos.Add(beatmap.BeatmapInfo); } @@ -351,5 +360,23 @@ namespace osu.Game.Beatmaps return beatmapInfos; } + + /// + /// A dummy WorkingBeatmap for the purpose of retrieving a beatmap for star difficulty calculation. + /// + private class DummyConversionBeatmap : WorkingBeatmap + { + private readonly IBeatmap beatmap; + + public DummyConversionBeatmap(IBeatmap beatmap) + : base(beatmap.BeatmapInfo) + { + this.beatmap = beatmap; + } + + protected override IBeatmap GetBeatmap() => beatmap; + protected override Texture GetBackground() => null; + protected override Track GetTrack() => null; + } } } From 7ee8228a37d31b8b3803328a38a5601c5aae08ec Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 13:28:01 +0900 Subject: [PATCH 052/302] Fix testcases --- osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs | 2 +- osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index cf79feb16b..95a23f65c5 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Tests protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; [NonParallelizable] - [TestCase("basic", false)] + [TestCase("basic")] public new void Test(string name) { base.Test(name); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index f67726c022..1bf24a46bc 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Tests private Container playfieldContainer; [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) + private void load() { AddStep("Hit!", () => addHitJudgement(false)); AddStep("Kiai hit", () => addHitJudgement(true)); @@ -73,6 +73,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Title = @"Sample Beatmap", AuthorString = @"peppy", }, + Ruleset = new TaikoRuleset().RulesetInfo }, ControlPointInfo = controlPointInfo }); @@ -86,7 +87,7 @@ namespace osu.Game.Rulesets.Taiko.Tests RelativeSizeAxes = Axes.X, Height = 768, Clock = new FramedClock(rateAdjustClock), - Children = new[] { rulesetContainer = new TaikoRulesetContainer(rulesets.GetRuleset(1).CreateInstance(), beatmap) } + Children = new[] { rulesetContainer = new TaikoRulesetContainer(new TaikoRuleset(), beatmap) } }); } From 6867886f4c6bda3e43000c023b8fef7eccd80ec2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 14:04:37 +0900 Subject: [PATCH 053/302] Give conversion-tested beatmaps a ruleset --- .../CatchBeatmapConversionTest.cs | 6 +++++- .../ManiaBeatmapConversionTest.cs | 6 +++++- osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs | 6 +++++- .../TaikoBeatmapConversionTest.cs | 6 +++++- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 7 ++++++- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index a94d29ca2c..d0d623178e 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Catch.Tests { - public class CatchBeatmapConversionTest : BeatmapConversionTest + public class CatchBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Catch"; @@ -64,4 +64,8 @@ namespace osu.Game.Rulesets.Catch.Tests => Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience) && Precision.AlmostEquals(Position, other.Position, conversion_lenience); } + + public class TestCatchRuleset : CatchRuleset + { + } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 95a23f65c5..f1ee874b88 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Mania.Tests { - public class ManiaBeatmapConversionTest : BeatmapConversionTest + public class ManiaBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; @@ -54,4 +54,8 @@ namespace osu.Game.Rulesets.Mania.Tests && Precision.AlmostEquals(EndTime, other.EndTime, conversion_lenience) && Column == other.Column; } + + public class TestManiaRuleset : ManiaRuleset + { + } } diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index a8f82a112b..aa7de4ed01 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -15,7 +15,7 @@ using OpenTK; namespace osu.Game.Rulesets.Osu.Tests { - public class OsuBeatmapConversionTest : BeatmapConversionTest + public class OsuBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; @@ -67,4 +67,8 @@ namespace osu.Game.Rulesets.Osu.Tests && Precision.AlmostEquals(EndX, other.EndX, conversion_lenience) && Precision.AlmostEquals(EndY, other.EndY, conversion_lenience); } + + public class TestOsuRuleset : OsuRuleset + { + } } diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index cbab53fa75..33a5e1772e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Taiko.Tests { - public class TaikoBeatmapConversionTest : BeatmapConversionTest + public class TaikoBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko"; @@ -67,4 +67,8 @@ namespace osu.Game.Rulesets.Taiko.Tests && IsSwell == other.IsSwell && IsStrong == other.IsStrong; } + + public class TestTaikoRuleset : TaikoRuleset + { + } } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 735c0ef76c..2de38d49a9 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -10,12 +10,14 @@ using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; +using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; namespace osu.Game.Tests.Beatmaps { [TestFixture] - public abstract class BeatmapConversionTest + public abstract class BeatmapConversionTest + where TRuleset : Ruleset, new() where TConvertValue : IEquatable { private const string resource_namespace = "Testing.Beatmaps"; @@ -79,6 +81,9 @@ namespace osu.Game.Tests.Beatmaps { var beatmap = getBeatmap(name); + var rulesetInstance = new TRuleset(); + beatmap.BeatmapInfo.Ruleset = beatmap.BeatmapInfo.RulesetID == rulesetInstance.RulesetInfo.ID ? rulesetInstance.RulesetInfo : new RulesetInfo(); + var result = new ConvertResult(); var converter = CreateConverter(beatmap); From 68441f1ef0b7770d3c3754f59024b184bd676a68 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 14:28:30 +0900 Subject: [PATCH 054/302] Output ruleset instantiation info --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 2a3eb05544..9c389bbb8f 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -97,7 +97,7 @@ namespace osu.Game.Beatmaps // Check if the beatmap can be converted if (!converter.CanConvert) - throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset}, converter: {converter})."); + throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter})."); // Apply conversion mods foreach (var mod in Mods.Value.OfType()) From 30a3f4f29f2ab4bbd6d6c260382cded231d8b490 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 15:27:45 +0900 Subject: [PATCH 055/302] Fix not being able to convert beatmaps with 0 hitobjects --- osu.Game/Beatmaps/BeatmapConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index 263a4c36ee..b7a454460f 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -32,7 +32,7 @@ namespace osu.Game.Beatmaps /// /// Whether can be converted by this . /// - public bool CanConvert => ValidConversionTypes.All(t => Beatmap.HitObjects.Any(t.IsInstanceOfType)); + public bool CanConvert => !Beatmap.HitObjects.Any() || ValidConversionTypes.All(t => Beatmap.HitObjects.Any(t.IsInstanceOfType)); /// /// Converts . From 9f1efeb19df1d3a9b1c43771ec28c36f0c0ba473 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 15:41:14 +0900 Subject: [PATCH 056/302] Move keybind to last in enum --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 2ae895785c..1658bb4e79 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -76,9 +76,9 @@ namespace osu.Game.Input.Bindings [Description("Quick Retry (Hold)")] QuickRetry, + [Description("Take screenshot")] + TakeScreenshot, [Description("Toggle gameplay mouse buttons")] ToggleGameplayMouseButtons, - [Description("Take screenshot")] - TakeScreenshot } } From 5489976c20cf5d7e15600c8d2f2a53e93f5c3af7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:51:17 +0900 Subject: [PATCH 057/302] Implement ruleset-specific beatmap statistics --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs | 45 +++++++++++++++++++ .../Beatmaps/OsuBeatmapConverter.cs | 2 + osu.Game.Rulesets.Osu/OsuRuleset.cs | 33 -------------- osu.Game/Beatmaps/Beatmap.cs | 8 ++++ osu.Game/Rulesets/Ruleset.cs | 2 - osu.Game/Screens/Select/BeatmapInfoWedge.cs | 4 +- 6 files changed, 57 insertions(+), 37 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs new file mode 100644 index 0000000000..68002f73b5 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs @@ -0,0 +1,45 @@ +// 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.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Beatmaps +{ + public class OsuBeatmap : Beatmap + { + public override IEnumerable GetStatistics() + { + 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 + } + }; + } + } +} 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/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 6a7d2690ff..e323dd0241 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -44,6 +44,12 @@ namespace osu.Game.Beatmaps /// IEnumerable HitObjects { get; } + /// + /// Returns statistics of the contained in this beatmap. + /// + /// + IEnumerable GetStatistics(); + /// /// Creates a shallow-clone of this beatmap and returns it. /// @@ -90,6 +96,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/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..c0370763c0 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -234,8 +234,8 @@ 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))); + //get statistics for the current ruleset. + labels.AddRange(working.GetPlayableBeatmap(info.Ruleset).GetStatistics().Select(s => new InfoLabel(s))); } return labels.ToArray(); From accffda5321fb6314d18665eccdf285e703c0972 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:51:30 +0900 Subject: [PATCH 058/302] Add taiko statistics --- .../Beatmaps/TaikoBeatmap.cs | 49 +++++++++++++++++++ .../Beatmaps/TaikoBeatmapConverter.cs | 2 + 2 files changed, 51 insertions(+) create mode 100644 osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs new file mode 100644 index 0000000000..cbf2270c95 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs @@ -0,0 +1,49 @@ +// 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 drumrolls = HitObjects.Count(s => s is DrumRoll); + int swells = HitObjects.Count(s => s is Swell); + int notes = HitObjects.Count - drumrolls - swells; + + return new[] + { + new BeatmapStatistic + { + Name = @"Object Count", + Content = HitObjects.Count.ToString(), + Icon = FontAwesome.fa_circle + }, + new BeatmapStatistic + { + Name = @"Note Count", + Content = notes.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(); } } From 8a4717d2e9e84875f14f02f318020f8f6949d1cf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:57:01 +0900 Subject: [PATCH 059/302] Add catch statistics --- .../Beatmaps/CatchBeatmap.cs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs new file mode 100644 index 0000000000..1b65a70207 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs @@ -0,0 +1,49 @@ +// 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 juiceStreams = HitObjects.Count(s => s is JuiceStream); + int bananaShowers = HitObjects.Count(s => s is BananaShower); + int fruits = HitObjects.Count - juiceStreams - bananaShowers; + + return new[] + { + new BeatmapStatistic + { + Name = @"Object Count", + Content = HitObjects.Count.ToString(), + Icon = FontAwesome.fa_circle + }, + 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 + } + }; + } + } +} From b737644208e0008eae06bdbe3a03b5ff9a527d1a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:58:56 +0900 Subject: [PATCH 060/302] Add mania statistics --- .../Beatmaps/ManiaBeatmap.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs index 6af3719f83..22cc57d924 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,33 @@ namespace osu.Game.Rulesets.Mania.Beatmaps { Stages.Add(defaultStage); } + + public override IEnumerable GetStatistics() + { + int holdnotes = HitObjects.Count(s => s is HoldNote); + int notes = HitObjects.Count - holdnotes; + + return new[] + { + new BeatmapStatistic + { + Name = @"Object Count", + Content = HitObjects.Count.ToString(), + Icon = FontAwesome.fa_circle + }, + 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 + }, + }; + } } } From 5f74dc2c1746dec30ead8270bf58c1635146653d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 10:59:30 +0900 Subject: [PATCH 061/302] Simplify osu-ruleset statistics --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs index 68002f73b5..7b534deccf 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Beatmaps @@ -15,9 +14,9 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { public override IEnumerable GetStatistics() { - 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)); + IEnumerable circles = HitObjects.Where(c => c is HitCircle); + IEnumerable sliders = HitObjects.Where(s => s is Slider); + IEnumerable spinners = HitObjects.Where(s => s is Spinner); return new[] { From b9e4b59e46ff589a864de4da71b1fc504a1f95c0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:01:09 +0900 Subject: [PATCH 062/302] Actually construct catch beatmaps --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 2 ++ 1 file changed, 2 insertions(+) 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(); } } From 7eb64ab590ccd828a04328b5b61818e544cb48be Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:33:05 +0900 Subject: [PATCH 063/302] Remove object counts from mania/taiko/catch --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs | 8 +------- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs | 8 +------- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs | 12 +++--------- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs index 1b65a70207..5b4af6ea8a 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs @@ -13,18 +13,12 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { 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); - int fruits = HitObjects.Count - juiceStreams - bananaShowers; return new[] { - new BeatmapStatistic - { - Name = @"Object Count", - Content = HitObjects.Count.ToString(), - Icon = FontAwesome.fa_circle - }, new BeatmapStatistic { Name = @"Fruit Count", diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs index 22cc57d924..ad5f8e447d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs @@ -33,17 +33,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps public override IEnumerable GetStatistics() { + int notes = HitObjects.Count(s => s is Note); int holdnotes = HitObjects.Count(s => s is HoldNote); - int notes = HitObjects.Count - holdnotes; return new[] { - new BeatmapStatistic - { - Name = @"Object Count", - Content = HitObjects.Count.ToString(), - Icon = FontAwesome.fa_circle - }, new BeatmapStatistic { Name = @"Note Count", diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs index cbf2270c95..36f6df7869 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs @@ -13,22 +13,16 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { 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); - int notes = HitObjects.Count - drumrolls - swells; return new[] { new BeatmapStatistic { - Name = @"Object Count", - Content = HitObjects.Count.ToString(), - Icon = FontAwesome.fa_circle - }, - new BeatmapStatistic - { - Name = @"Note Count", - Content = notes.ToString(), + Name = @"Hit Count", + Content = hits.ToString(), Icon = FontAwesome.fa_circle_o }, new BeatmapStatistic From 251bdfdee8c0232235b8de4f25620ca270946fd6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:33:15 +0900 Subject: [PATCH 064/302] Simplify statistics in osu ruleset --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs index 7b534deccf..6d90c2a875 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Beatmaps @@ -14,28 +13,28 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { public override IEnumerable GetStatistics() { - IEnumerable circles = HitObjects.Where(c => c is HitCircle); - IEnumerable sliders = HitObjects.Where(s => s is Slider); - IEnumerable spinners = HitObjects.Where(s => s is Spinner); + 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.Count().ToString(), + Content = circles.ToString(), Icon = FontAwesome.fa_circle_o }, new BeatmapStatistic { Name = @"Slider Count", - Content = sliders.Count().ToString(), + Content = sliders.ToString(), Icon = FontAwesome.fa_circle }, new BeatmapStatistic { Name = @"Spinner Count", - Content = spinners.Count().ToString(), + Content = spinners.ToString(), Icon = FontAwesome.fa_circle } }; From 6a9f139d9b1fb1fb89a3ef93687e5ef8ae85507b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:33:40 +0900 Subject: [PATCH 065/302] Instantiate convertible hitobjects for beatmap info wedge --- osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index efd6c36ce2..a618e44301 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Select; using osu.Game.Tests.Beatmaps; @@ -138,7 +139,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 +154,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 +165,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; + } } } From 09c70a93625d4bf3b2f6318b95014a55d0d27f49 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:36:51 +0900 Subject: [PATCH 066/302] Add info label tests to TestCaseBeatmapInfoWedge --- .../Visual/TestCaseBeatmapInfoWedge.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index a618e44301..0d3e08154f 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -12,9 +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; @@ -73,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; @@ -89,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"); From fbd7ccc03fa732e3d6e4276f75c999538b14097f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 11:59:17 +0900 Subject: [PATCH 067/302] Make BeatmapInfoWedge display properly for converts --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 49 ++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index c0370763c0..7a8a04bd43 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,7 +76,17 @@ namespace osu.Game.Screens.Select this.FadeOut(500, Easing.In); } + private WorkingBeatmap beatmap; + public void UpdateBeatmap(WorkingBeatmap beatmap) + { + this.beatmap = beatmap; + loadBeatmap(); + } + + private void updateRuleset(RulesetInfo ruleset) => loadBeatmap(); + + private void loadBeatmap() { LoadComponentAsync(new BufferedWedgeInfo(beatmap) { @@ -90,14 +114,18 @@ namespace osu.Game.Screens.Select private UnicodeBindableString titleBinding; private UnicodeBindableString artistBinding; + private RulesetInfo ruleset; + public BufferedWedgeInfo(WorkingBeatmap working) { this.working = working; } - [BackgroundDependencyLoader] - private void load(LocalisationEngine localisation) + [BackgroundDependencyLoader(true)] + private void load([NotNull] LocalisationEngine localisation, [CanBeNull] OsuGame osuGame) { + ruleset = osuGame?.Ruleset.Value ?? working.BeatmapInfo.Ruleset; + var beatmapInfo = working.BeatmapInfo; var metadata = beatmapInfo.Metadata ?? working.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); @@ -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 for the current ruleset. - labels.AddRange(working.GetPlayableBeatmap(info.Ruleset).GetStatistics().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(); From 674e45d49bb751eef903f7264e05563fa463b23e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 May 2018 16:32:15 +0900 Subject: [PATCH 068/302] Fix beatmap/ruleset being changeable while in the editor --- osu.Game/Screens/Edit/Editor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index adb749b492..e4eaee76fc 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -27,6 +27,7 @@ namespace osu.Game.Screens.Edit protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); public override bool ShowOverlaysOnEnter => false; + public override bool AllowBeatmapRulesetChange => false; private Box bottomBackground; private Container screenContainer; From c2979a5c48de6b07318bd8c91ecf89d0922d6326 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 May 2018 22:08:45 +0900 Subject: [PATCH 069/302] Update CodeFileSanity --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 15484e4c68..69bc762f4c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,7 @@ install: - cmd: git submodule update --init --recursive --depth=5 - cmd: choco install resharper-clt -y - cmd: choco install nvika -y - - cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.2.4/CodeFileSanity.exe + - cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.2.5/CodeFileSanity.exe before_build: - cmd: CodeFileSanity.exe - cmd: nuget restore -verbosity quiet From 44bbb8700ecc1bdd652c35766bfbaa54310a5855 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 8 May 2018 00:22:11 +0300 Subject: [PATCH 070/302] Handle mouse back button using OnMouseDown override instead of using GlobalAction --- .../Input/Bindings/GlobalActionContainer.cs | 10 +---- osu.Game/Screens/Loader.cs | 1 + osu.Game/Screens/Menu/ButtonSystem.cs | 44 +++++++------------ osu.Game/Screens/Menu/MainMenu.cs | 1 + osu.Game/Screens/OsuScreen.cs | 28 ++++++++---- osu.Game/Screens/Play/PlayerLoader.cs | 1 - .../Play/ScreenWithBeatmapBackground.cs | 2 + 7 files changed, 43 insertions(+), 44 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 565d530395..dd8f00f6cd 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Input.Bindings { new KeyBinding(InputKey.F8, GlobalAction.ToggleChat), new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), - new KeyBinding(InputKey.F12, GlobalAction.TakeScreenshot), + new KeyBinding(InputKey.F12,GlobalAction.TakeScreenshot), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), @@ -36,9 +36,6 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Down, GlobalAction.DecreaseVolume), new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume), new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), - - new KeyBinding(InputKey.Escape, GlobalAction.Back), - new KeyBinding(InputKey.MouseButton1, GlobalAction.Back) }; public IEnumerable InGameKeyBindings => new[] @@ -79,9 +76,6 @@ namespace osu.Game.Input.Bindings QuickRetry, [Description("Take screenshot")] - TakeScreenshot, - - [Description("Go back")] - Back + TakeScreenshot } } diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 1d152361df..dc8dbb4421 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -18,6 +18,7 @@ namespace osu.Game.Screens private bool showDisclaimer; public override bool ShowOverlaysOnEnter => false; + protected override bool AllowBackButton => false; public Loader() { diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 8cf0d24f7d..5a1dafe404 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -13,17 +13,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; -using osu.Framework.Input.Bindings; using osu.Framework.Threading; using osu.Game.Graphics; -using osu.Game.Input.Bindings; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; namespace osu.Game.Screens.Menu { - public class ButtonSystem : Container, IStateful, IKeyBindingHandler + public class ButtonSystem : Container, IStateful { public event Action StateChanged; @@ -148,43 +146,35 @@ namespace osu.Game.Screens.Menu case Key.Space: logo?.TriggerOnClick(state); return true; + case Key.Escape: + return handleBack(); } return false; } - public bool OnPressed(GlobalAction action) + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - switch (action) - { - case GlobalAction.Back: - switch (State) - { - case MenuState.TopLevel: - State = MenuState.Initial; - return true; - case MenuState.Play: - backButton.TriggerOnClick(); - return true; - default: - return false; - } - default: - return false; - } + if (state.Mouse.IsPressed(MouseButton.Button1)) + return handleBack(); + + return base.OnMouseDown(state, args); } - public bool OnReleased(GlobalAction action) + private bool handleBack() { - switch (action) + switch (State) { - case GlobalAction.Back: + case MenuState.TopLevel: + State = MenuState.Initial; + return true; + case MenuState.Play: + backButton.TriggerOnClick(); return true; - default: - return false; } - } + return false; + } private void onPlay() { diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index f2ea6d85a8..d91ac099fd 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -25,6 +25,7 @@ namespace osu.Game.Screens.Menu private readonly ButtonSystem buttons; public override bool ShowOverlaysOnEnter => buttons.State != MenuState.Initial; + protected override bool AllowBackButton => false; private readonly BackgroundScreenDefault background; private Screen songSelect; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index fb5d3d12e6..9fa30181a1 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -7,18 +7,18 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Input.Bindings; +using osu.Framework.Input; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; -using osu.Game.Input.Bindings; using osu.Game.Rulesets; using osu.Game.Screens.Menu; using OpenTK; +using OpenTK.Input; namespace osu.Game.Screens { - public abstract class OsuScreen : Screen, IKeyBindingHandler + public abstract class OsuScreen : Screen { public BackgroundScreen Background { get; private set; } @@ -92,19 +92,31 @@ namespace osu.Game.Screens sampleExit = audio.Sample.Get(@"UI/screen-back"); } - public bool OnPressed(GlobalAction action) + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { - if (action == GlobalAction.Back && AllowBackButton) + if (args.Repeat || !IsCurrentScreen) return false; + + switch (args.Key) + { + case Key.Escape: + Exit(); + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + if (AllowBackButton && state.Mouse.IsPressed(MouseButton.Button1)) { Exit(); return true; } - return false; + return base.OnMouseDown(state, args); } - public bool OnReleased(GlobalAction action) => action == GlobalAction.Back && AllowBackButton; - protected override void OnResuming(Screen last) { sampleExit?.Play(); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6eb156914e..56fbd7b6e7 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -27,7 +27,6 @@ namespace osu.Game.Screens.Play private bool showOverlays = true; public override bool ShowOverlaysOnEnter => showOverlays; - protected override bool AllowBackButton => false; private Task loadTask; diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 1ccc5e2fe8..30ae6db346 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -17,6 +17,8 @@ namespace osu.Game.Screens.Play public override bool AllowBeatmapRulesetChange => false; + protected override bool AllowBackButton => false; + protected const float BACKGROUND_FADE_DURATION = 800; protected float BackgroundOpacity => 1 - (float)DimLevel; From dd9b9a18ac4571ffda22f5b883452d16dbabcc66 Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 8 May 2018 16:21:54 +0300 Subject: [PATCH 071/302] Prevent user from scrolling outside the timeline in the editor --- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index adb749b492..0e0f3fa9f1 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Edit { // TODO: should probably be done at a RulesetContainer level to share logic with Player. var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); - clock = new EditorClock(Beatmap.Value.Beatmap.ControlPointInfo, beatDivisor) { IsCoupled = false }; + clock = new EditorClock(Beatmap, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); dependencies.CacheAs(clock); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 67025f0620..02bf581716 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -3,8 +3,10 @@ using System; using System.Linq; +using osu.Framework.Configuration; using osu.Framework.MathUtils; using osu.Framework.Timing; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit.Screens.Compose; @@ -15,10 +17,20 @@ namespace osu.Game.Screens.Edit /// public class EditorClock : DecoupleableInterpolatingFramedClock { + public Bindable Beatmap = new Bindable(); + public ControlPointInfo ControlPointInfo; private readonly BindableBeatDivisor beatDivisor; + public EditorClock(Bindable beatmap, BindableBeatDivisor beatDivisor) + { + this.beatDivisor = beatDivisor; + + Beatmap.BindTo(beatmap); + + ControlPointInfo = Beatmap.Value.Beatmap.ControlPointInfo; + } public EditorClock(ControlPointInfo controlPointInfo, BindableBeatDivisor beatDivisor) { this.beatDivisor = beatDivisor; @@ -111,6 +123,7 @@ namespace osu.Game.Screens.Edit if (seekTime > nextTimingPoint?.Time) seekTime = nextTimingPoint.Time; + seekTime = Math.Min(Math.Max(0, seekTime), Beatmap.Value.Track.Length); // Ensure the sought point is within the song's length Seek(seekTime); } } From e44062b77a54e792fdcb84fd1c9379cec473aafc Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 8 May 2018 16:37:06 +0300 Subject: [PATCH 072/302] Fix tests and implementation --- osu.Game/Screens/Edit/EditorClock.cs | 15 +++++++++------ osu.Game/Tests/Visual/EditorClockTestCase.cs | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 02bf581716..88d8477233 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -17,7 +17,9 @@ namespace osu.Game.Screens.Edit /// public class EditorClock : DecoupleableInterpolatingFramedClock { - public Bindable Beatmap = new Bindable(); + //public Bindable Beatmap = new Bindable(); + + public double TrackLength; public ControlPointInfo ControlPointInfo; @@ -27,15 +29,15 @@ namespace osu.Game.Screens.Edit { this.beatDivisor = beatDivisor; - Beatmap.BindTo(beatmap); - - ControlPointInfo = Beatmap.Value.Beatmap.ControlPointInfo; + ControlPointInfo = beatmap.Value.Beatmap.ControlPointInfo; + TrackLength = beatmap.Value.Track.Length; } - public EditorClock(ControlPointInfo controlPointInfo, BindableBeatDivisor beatDivisor) + public EditorClock(ControlPointInfo controlPointInfo, double trackLength, BindableBeatDivisor beatDivisor) { this.beatDivisor = beatDivisor; ControlPointInfo = controlPointInfo; + TrackLength = trackLength; } /// @@ -123,7 +125,8 @@ namespace osu.Game.Screens.Edit if (seekTime > nextTimingPoint?.Time) seekTime = nextTimingPoint.Time; - seekTime = Math.Min(Math.Max(0, seekTime), Beatmap.Value.Track.Length); // Ensure the sought point is within the song's length + // Ensure the sought point is within the boundaries + seekTime = Math.Min(Math.Max(0, seekTime), TrackLength); Seek(seekTime); } } diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestCase.cs index 43b20f7021..85d3684530 100644 --- a/osu.Game/Tests/Visual/EditorClockTestCase.cs +++ b/osu.Game/Tests/Visual/EditorClockTestCase.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual protected EditorClockTestCase() { - Clock = new EditorClock(new ControlPointInfo(), BeatDivisor) { IsCoupled = false }; + Clock = new EditorClock(new ControlPointInfo(), 5000, BeatDivisor) { IsCoupled = false }; } [BackgroundDependencyLoader] From c7bc79bce34a9c7f46f738b19d93b80cfbf2dcb4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 9 May 2018 12:40:04 +0900 Subject: [PATCH 073/302] Remove explicit clock in TestCaseBreakOverlay --- osu.Game.Tests/Visual/TestCaseBreakOverlay.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs b/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs index a6a6130a8f..442ca1322a 100644 --- a/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Timing; using osu.Game.Beatmaps.Timing; using System.Collections.Generic; using NUnit.Framework; @@ -16,8 +15,6 @@ namespace osu.Game.Tests.Visual public TestCaseBreakOverlay() { - Clock = new FramedClock(); - Child = breakOverlay = new BreakOverlay(true); AddStep("2s break", () => startBreak(2000)); From 6676c55fe05f0f413b95740381f35738e13adfcd Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Wed, 9 May 2018 17:22:37 +0300 Subject: [PATCH 074/302] Introduce InputSettings --- .../Play/PlayerSettings/InputSettings.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 osu.Game/Screens/Play/PlayerSettings/InputSettings.cs diff --git a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs new file mode 100644 index 0000000000..f9dda01c8c --- /dev/null +++ b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Configuration; + +namespace osu.Game.Screens.Play.PlayerSettings +{ + public class InputSettings : PlayerSettingsGroup + { + protected override string Title => "Input settings"; + + private readonly PlayerCheckbox mouseWheelCheckbox; + private readonly PlayerCheckbox mouseButtonsCheckbox; + + public InputSettings() + { + Children = new Drawable[] + { + mouseWheelCheckbox = new PlayerCheckbox + { + LabelText = "Disable mouse wheel during gameplay" + }, + mouseButtonsCheckbox = new PlayerCheckbox + { + LabelText = "Disable mouse buttons during gameplay" + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + mouseWheelCheckbox.Bindable = config.GetBindable(OsuSetting.MouseDisableWheel); + mouseButtonsCheckbox.Bindable = config.GetBindable(OsuSetting.MouseDisableButtons); + } + } +} From ccf82cacb029784988189ab9cbf462b1f91609df Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Wed, 9 May 2018 17:31:52 +0300 Subject: [PATCH 075/302] Show InputSettings on the PlayerLoader screen --- osu.Game/Screens/Play/PlayerLoader.cs | 18 +++++++++++++----- .../Play/PlayerSettings/InputSettings.cs | 4 ++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 56fbd7b6e7..13293b6f93 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -7,15 +7,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; +using osu.Framework.Localisation; using osu.Framework.Screens; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using OpenTK; -using osu.Framework.Localisation; -using osu.Framework.Threading; using osu.Game.Screens.Menu; using osu.Game.Screens.Play.PlayerSettings; +using OpenTK; namespace osu.Game.Screens.Play { @@ -51,11 +51,19 @@ namespace osu.Game.Screens.Play Origin = Anchor.Centre, }); - Add(new VisualSettings + Add(new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Margin = new MarginPadding(25) + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Margin = new MarginPadding { Top = 100, Right = 10 }, + Children = new PlayerSettingsGroup[] + { + new VisualSettings(), + new InputSettings() + } }); loadTask = LoadComponentAsync(player); diff --git a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs index f9dda01c8c..25b6ebc2c3 100644 --- a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs @@ -20,11 +20,11 @@ namespace osu.Game.Screens.Play.PlayerSettings { mouseWheelCheckbox = new PlayerCheckbox { - LabelText = "Disable mouse wheel during gameplay" + LabelText = "Disable mouse wheel" }, mouseButtonsCheckbox = new PlayerCheckbox { - LabelText = "Disable mouse buttons during gameplay" + LabelText = "Disable mouse buttons" } }; } From 5df9f126d162ea33a8eb1af68746ec5291d4f21d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 May 2018 17:07:19 +0900 Subject: [PATCH 076/302] Implement a hold-to-confirm screen when exiting game using escape key --- osu.Game/Overlays/HoldToConfirmOverlay.cs | 59 +++++++++++++++++++++ osu.Game/Screens/Menu/ExitConfirmOverlay.cs | 34 ++++++++++++ osu.Game/Screens/Menu/MainMenu.cs | 4 ++ osu.Game/Screens/Play/HotkeyRetryOverlay.cs | 49 ++--------------- 4 files changed, 101 insertions(+), 45 deletions(-) create mode 100644 osu.Game/Overlays/HoldToConfirmOverlay.cs create mode 100644 osu.Game/Screens/Menu/ExitConfirmOverlay.cs diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs new file mode 100644 index 0000000000..4bc7154ce8 --- /dev/null +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using OpenTK.Graphics; + +namespace osu.Game.Overlays +{ + /// + /// An overlay which will display a black screen that dims over a period before confirming an exit action. + /// Action is BYO (derived class will need to call and from a user event). + /// + public abstract class HoldToConfirmOverlay : Container + { + public Action Action; + + private Box overlay; + + private const int activate_delay = 400; + private const int fadeout_delay = 200; + + private bool fired; + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Both; + AlwaysPresent = true; + + Children = new Drawable[] + { + overlay = new Box + { + Alpha = 0, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + } + }; + } + + protected void BeginConfirm() => overlay.FadeIn(activate_delay, Easing.Out); + + protected void AbortConfirm() => overlay.FadeOut(fadeout_delay, Easing.Out); + + protected override void Update() + { + base.Update(); + if (!fired && overlay.Alpha == 1) + { + fired = true; + Action?.Invoke(); + } + } + } +} diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs new file mode 100644 index 0000000000..62605da5a4 --- /dev/null +++ b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Input; +using osu.Game.Overlays; +using OpenTK.Input; + +namespace osu.Game.Screens.Menu +{ + public class ExitConfirmOverlay : HoldToConfirmOverlay + { + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Key == Key.Escape && !args.Repeat) + { + BeginConfirm(); + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + { + if (args.Key == Key.Escape) + { + AbortConfirm(); + return true; + } + + return base.OnKeyUp(state, args); + } + } +} diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index f2ea6d85a8..ce5aace50b 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -39,6 +39,10 @@ namespace osu.Game.Screens.Menu Children = new Drawable[] { + new ExitConfirmOverlay + { + Action = Exit, + }, new ParallaxContainer { ParallaxAmount = 0.01f, diff --git a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs index a018a2697a..926a96eb6c 100644 --- a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs @@ -1,50 +1,19 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; -using System; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; -using OpenTK.Graphics; +using osu.Game.Overlays; namespace osu.Game.Screens.Play { - public class HotkeyRetryOverlay : Container, IKeyBindingHandler + public class HotkeyRetryOverlay : HoldToConfirmOverlay, IKeyBindingHandler { - public Action Action; - - private Box overlay; - - private const int activate_delay = 400; - private const int fadeout_delay = 200; - - private bool fired; - - [BackgroundDependencyLoader] - private void load() - { - RelativeSizeAxes = Axes.Both; - AlwaysPresent = true; - - Children = new Drawable[] - { - overlay = new Box - { - Alpha = 0, - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, - } - }; - } - public bool OnPressed(GlobalAction action) { if (action != GlobalAction.QuickRetry) return false; - overlay.FadeIn(activate_delay, Easing.Out); + BeginConfirm(); return true; } @@ -52,18 +21,8 @@ namespace osu.Game.Screens.Play { if (action != GlobalAction.QuickRetry) return false; - overlay.FadeOut(fadeout_delay, Easing.Out); + AbortConfirm(); return true; } - - protected override void Update() - { - base.Update(); - if (!fired && overlay.Alpha == 1) - { - fired = true; - Action?.Invoke(); - } - } } } From 63e10ec3c2d2844e13e7e2b47b86984be5e4547a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 May 2018 17:10:42 +0900 Subject: [PATCH 077/302] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 96ef8c43b5..e793a08417 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 96ef8c43b5e6b6ae14b01c3550c480c8d9a78518 +Subproject commit e793a084177f53920645c4f6f70cfef91e7fd19e From fadb1a5e0b44c85b2ff132aa0ab91b9c34285621 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 May 2018 17:30:24 +0900 Subject: [PATCH 078/302] Add tests and expand functionality to ensure single fire --- .../Visual/TestCaseHoldToConfirmOverlay.cs | 62 +++++++++++++++++++ osu.Game/Overlays/HoldToConfirmOverlay.cs | 25 +++++--- 2 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs diff --git a/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs new file mode 100644 index 0000000000..ef6f44b42e --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs @@ -0,0 +1,62 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Screens.Menu; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseHoldToConfirmOverlay : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(ExitConfirmOverlay) }; + + public TestCaseHoldToConfirmOverlay() + { + bool fired = false; + + var abortText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Aborted!", + TextSize = 50, + Alpha = 0, + }; + + var overlay = new TestHoldToConfirmOverlay + { + Action = () => + { + fired = true; + abortText.FadeTo(1).Then().FadeOut(1000); + } + }; + + Children = new Drawable[] + { + overlay, + abortText + }; + + AddStep("start confirming", () => overlay.Begin()); + AddStep("abort confirming", () => overlay.Abort()); + + AddAssert("ensure aborted", () => !fired); + + AddStep("start confirming", () => overlay.Begin()); + + AddUntilStep(() => fired, "wait until confirmed"); + } + + private class TestHoldToConfirmOverlay : ExitConfirmOverlay + { + protected override bool AllowMultipleFires => true; + + public void Begin() => BeginConfirm(); + public void Abort() => AbortConfirm(); + } + } +} diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index 4bc7154ce8..a0e4bf1a39 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -25,6 +25,11 @@ namespace osu.Game.Overlays private bool fired; + /// + /// Whether the overlay should be allowed to return from a fired state. + /// + protected virtual bool AllowMultipleFires => false; + [BackgroundDependencyLoader] private void load() { @@ -42,18 +47,20 @@ namespace osu.Game.Overlays }; } - protected void BeginConfirm() => overlay.FadeIn(activate_delay, Easing.Out); - - protected void AbortConfirm() => overlay.FadeOut(fadeout_delay, Easing.Out); - - protected override void Update() + protected void BeginConfirm() { - base.Update(); - if (!fired && overlay.Alpha == 1) + if (!AllowMultipleFires && fired) return; + overlay.FadeIn(activate_delay * (1 - overlay.Alpha), Easing.Out).OnComplete(_ => { - fired = true; Action?.Invoke(); - } + fired = true; + }); + } + + protected void AbortConfirm() + { + if (!AllowMultipleFires && fired) return; + overlay.FadeOut(fadeout_delay, Easing.Out); } } } From c7443e6b3b5a19795e3b7c38f235b9e9e90c5989 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 May 2018 17:10:42 +0900 Subject: [PATCH 079/302] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 96ef8c43b5..e793a08417 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 96ef8c43b5e6b6ae14b01c3550c480c8d9a78518 +Subproject commit e793a084177f53920645c4f6f70cfef91e7fd19e From c03ab9014f1eb2276ec9057bdd1b1a608add5d03 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 10 May 2018 15:49:37 +0900 Subject: [PATCH 080/302] Improve TestCaseOnScreenDisplay Now doesn't rely on framesync. --- .../Visual/TestCaseOnScreenDisplay.cs | 104 +++++++++++++----- osu.Game/Overlays/OnScreenDisplay.cs | 23 ++-- 2 files changed, 90 insertions(+), 37 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs b/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs index 233c418d4a..123c1fe055 100644 --- a/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs @@ -4,6 +4,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Framework.Configuration.Tracking; +using osu.Framework.Graphics; using osu.Game.Overlays; namespace osu.Game.Tests.Visual @@ -11,36 +13,82 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseOnScreenDisplay : OsuTestCase { - private FrameworkConfigManager config; - private Bindable frameSyncMode; - - protected override void LoadComplete() - { - base.LoadComplete(); - - Add(new OnScreenDisplay()); - - frameSyncMode = config.GetBindable(FrameworkSetting.FrameSync); - - FrameSync initial = frameSyncMode.Value; - - AddRepeatStep(@"Change frame limiter", setNextMode, 3); - - AddStep(@"Restore frame limiter", () => frameSyncMode.Value = initial); - } - - private void setNextMode() - { - var nextMode = frameSyncMode.Value + 1; - if (nextMode > FrameSync.Unlimited) - nextMode = FrameSync.VSync; - frameSyncMode.Value = nextMode; - } - [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config) + private void load() { - this.config = config; + var config = new TestConfigManager(); + + var osd = new TestOnScreenDisplay(); + osd.BeginTracking(this, config); + Add(osd); + + AddRepeatStep("Change toggle (no bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingNoKeybind), 2); + AddRepeatStep("Change toggle (with bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingWithKeybind), 2); + AddRepeatStep("Change enum (no bind)", () => config.IncrementEnumSetting(TestConfigSetting.EnumSettingNoKeybind), 3); + AddRepeatStep("Change enum (with bind)", () => config.IncrementEnumSetting(TestConfigSetting.EnumSettingWithKeybind), 3); + } + + private class TestConfigManager : ConfigManager + { + public TestConfigManager() + { + InitialiseDefaults(); + } + + protected override void InitialiseDefaults() + { + Set(TestConfigSetting.ToggleSettingNoKeybind, false); + Set(TestConfigSetting.EnumSettingNoKeybind, EnumSetting.Setting1); + Set(TestConfigSetting.ToggleSettingWithKeybind, false); + Set(TestConfigSetting.EnumSettingWithKeybind, EnumSetting.Setting1); + + base.InitialiseDefaults(); + } + + public void ToggleSetting(TestConfigSetting setting) => Set(setting, !Get(setting)); + + public void IncrementEnumSetting(TestConfigSetting setting) + { + var nextValue = Get(setting) + 1; + if (nextValue > EnumSetting.Setting4) + nextValue = EnumSetting.Setting1; + Set(setting, nextValue); + } + + public override TrackedSettings CreateTrackedSettings() => new TrackedSettings + { + new TrackedSetting(TestConfigSetting.ToggleSettingNoKeybind, b => new SettingDescription(b, "toggle setting with no keybind", b ? "enabled" : "disabled")), + new TrackedSetting(TestConfigSetting.EnumSettingNoKeybind, v => new SettingDescription(v, "enum setting with no keybind", v.ToString())), + new TrackedSetting(TestConfigSetting.ToggleSettingWithKeybind, b => new SettingDescription(b, "toggle setting with keybind", b ? "enabled" : "disabled", "fake keybind")), + new TrackedSetting(TestConfigSetting.EnumSettingWithKeybind, v => new SettingDescription(v, "enum setting with keybind", v.ToString(), "fake keybind")), + }; + + protected override void PerformLoad() + { + } + + protected override bool PerformSave() => false; + } + + private enum TestConfigSetting + { + ToggleSettingNoKeybind, + EnumSettingNoKeybind, + ToggleSettingWithKeybind, + EnumSettingWithKeybind + } + + private enum EnumSetting + { + Setting1, + Setting2, + Setting3, + Setting4 + } + + private class TestOnScreenDisplay : OnScreenDisplay + { + protected override void Display(Drawable toDisplay) => toDisplay.FadeIn().ResizeHeightTo(110); } } } diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 9882ea01f0..a643080df8 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -102,12 +102,12 @@ namespace osu.Game.Overlays }, textLine3 = new OsuSpriteText { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Padding = new MarginPadding { Bottom = 15 }, Font = @"Exo2.0-Bold", TextSize = 12, Alpha = 0.3f, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, }, } } @@ -177,13 +177,7 @@ namespace osu.Game.Overlays textLine2.Text = description.Value; textLine3.Text = description.Shortcut.ToUpper(); - box.Animate( - b => b.FadeIn(500, Easing.OutQuint), - b => b.ResizeHeightTo(height, 500, Easing.OutQuint) - ).Then( - b => b.FadeOutFromOne(1500, Easing.InQuint), - b => b.ResizeHeightTo(height_contracted, 1500, Easing.InQuint) - ); + Display(box); int optionCount = 0; int selectedOption = -1; @@ -215,6 +209,17 @@ namespace osu.Game.Overlays }); } + protected virtual void Display(Drawable toDisplay) + { + toDisplay.Animate( + b => b.FadeIn(500, Easing.OutQuint), + b => b.ResizeHeightTo(height, 500, Easing.OutQuint) + ).Then( + b => b.FadeOutFromOne(1500, Easing.InQuint), + b => b.ResizeHeightTo(height_contracted, 1500, Easing.InQuint) + ); + } + private class OptionLight : Container { private Color4 glowingColour, idleColour; From df604c40ccd33a1b70637a89f09211f6b7de5c87 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 10 May 2018 18:49:19 +0900 Subject: [PATCH 081/302] Keep shortcut padding even when there is no shortut --- osu-framework | 2 +- osu.Game/Overlays/OnScreenDisplay.cs | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/osu-framework b/osu-framework index 0773d895d9..5c135a7360 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 0773d895d9aa0729995cd4a23efc28238e35ceed +Subproject commit 5c135a7360388dc41b1dc4387769a98ee1635d36 diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index a643080df8..8f6bf0f539 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -31,6 +31,7 @@ namespace osu.Game.Overlays private readonly SpriteText textLine3; private const float height = 110; + private const float height_notext = 98; private const float height_contracted = height * 0.9f; private readonly FillFlowContainer optionLights; @@ -100,15 +101,20 @@ namespace osu.Game.Overlays Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both }, - textLine3 = new OsuSpriteText + new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Padding = new MarginPadding { Bottom = 15 }, - Font = @"Exo2.0-Bold", - TextSize = 12, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Bottom = 15 }, Alpha = 0.3f, - }, + Child = textLine3 = new OsuSpriteText + { + Font = @"Exo2.0-Bold", + TextSize = 12, + AlwaysPresent = true + }, + } } } } From 40c1b24b3db0628bfe8f632640c413062d99562a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 May 2018 19:51:40 +0900 Subject: [PATCH 082/302] Move IBeatmap to its own file --- osu.Game/Beatmaps/Beatmap.cs | 39 --------------------------- osu.Game/Beatmaps/IBeatmap.cs | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 39 deletions(-) create mode 100644 osu.Game/Beatmaps/IBeatmap.cs diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 6a7d2690ff..2df0547175 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -12,45 +12,6 @@ using osu.Game.IO.Serialization.Converters; namespace osu.Game.Beatmaps { - public interface IBeatmap : IJsonSerializable - { - /// - /// This beatmap's info. - /// - BeatmapInfo BeatmapInfo { get; set; } - - /// - /// This beatmap's metadata. - /// - BeatmapMetadata Metadata { get; } - - /// - /// The control points in this beatmap. - /// - ControlPointInfo ControlPointInfo { get; } - - /// - /// The breaks in this beatmap. - /// - List Breaks { get; } - - /// - /// Total amount of break time in the beatmap. - /// - double TotalBreakTime { get; } - - /// - /// The hitobjects contained by this beatmap. - /// - IEnumerable HitObjects { get; } - - /// - /// Creates a shallow-clone of this beatmap and returns it. - /// - /// The shallow-cloned beatmap. - IBeatmap Clone(); - } - /// /// A Beatmap containing converted HitObjects. /// diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs new file mode 100644 index 0000000000..4676f056fa --- /dev/null +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -0,0 +1,50 @@ +// 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 osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Timing; +using osu.Game.IO.Serialization; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Beatmaps +{ + public interface IBeatmap : IJsonSerializable + { + /// + /// This beatmap's info. + /// + BeatmapInfo BeatmapInfo { get; set; } + + /// + /// This beatmap's metadata. + /// + BeatmapMetadata Metadata { get; } + + /// + /// The control points in this beatmap. + /// + ControlPointInfo ControlPointInfo { get; } + + /// + /// The breaks in this beatmap. + /// + List Breaks { get; } + + /// + /// Total amount of break time in the beatmap. + /// + double TotalBreakTime { get; } + + /// + /// The hitobjects contained by this beatmap. + /// + IEnumerable HitObjects { get; } + + /// + /// Creates a shallow-clone of this beatmap and returns it. + /// + /// The shallow-cloned beatmap. + IBeatmap Clone(); + } +} From 93029fd5482d4fec1f493bfb83f41417283dcd67 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 10 May 2018 20:38:55 +0300 Subject: [PATCH 083/302] Remove mouseWheelCheckbox from InputSettings player overlay --- osu.Game/Screens/Play/PlayerSettings/InputSettings.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs index 25b6ebc2c3..755ba468cc 100644 --- a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs @@ -11,17 +11,12 @@ namespace osu.Game.Screens.Play.PlayerSettings { protected override string Title => "Input settings"; - private readonly PlayerCheckbox mouseWheelCheckbox; private readonly PlayerCheckbox mouseButtonsCheckbox; public InputSettings() { Children = new Drawable[] { - mouseWheelCheckbox = new PlayerCheckbox - { - LabelText = "Disable mouse wheel" - }, mouseButtonsCheckbox = new PlayerCheckbox { LabelText = "Disable mouse buttons" @@ -30,10 +25,6 @@ namespace osu.Game.Screens.Play.PlayerSettings } [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - mouseWheelCheckbox.Bindable = config.GetBindable(OsuSetting.MouseDisableWheel); - mouseButtonsCheckbox.Bindable = config.GetBindable(OsuSetting.MouseDisableButtons); - } + private void load(OsuConfigManager config) => mouseButtonsCheckbox.Bindable = config.GetBindable(OsuSetting.MouseDisableButtons); } } From 86430da6d6a2321c588872a11a6c77c8da68d623 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 10 May 2018 21:08:02 +0300 Subject: [PATCH 084/302] Update CircularProgress.FillTo calls --- osu.Game/Screens/Play/HUD/QuitButton.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index aa6dc388ac..276bffb0a4 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -17,6 +17,7 @@ namespace osu.Game.Screens.Play.HUD public class QuitButton : FillFlowContainer { private readonly Button button; + public Action ExitAction { get => button.ExitAction; @@ -85,7 +86,7 @@ namespace osu.Game.Screens.Play.HUD { icon.ScaleTo(1.5f); text.FadeIn(fade_duration); - progress.FillTo(1, progress_duration).OnComplete(cp => ExitAction()); + progress.FillTo(progress.Current, 1, progress_duration).OnComplete(cp => ExitAction()); return base.OnMouseDown(state, args); } @@ -94,7 +95,7 @@ namespace osu.Game.Screens.Play.HUD { icon.ScaleTo(1f); Scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); - progress.FillTo(0, progress_duration / 4).OnComplete(cp => progress.Current.SetDefault()); + progress.FillTo(progress.Current, 0, progress_duration / 4).OnComplete(cp => progress.Current.SetDefault()); return base.OnMouseUp(state, args); } From ecb8de29a20138c057fa937ab048dc1cc32f7c2e Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 20:30:03 -0300 Subject: [PATCH 085/302] Adjust BreadcrumbControl to better match the designs. --- .../UserInterface/BreadcrumbControl.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index 3f59eeca97..f5017de639 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -14,14 +14,18 @@ namespace osu.Game.Graphics.UserInterface public class BreadcrumbControl : OsuTabControl { private const float padding = 10; + private const float item_chevron_size = 10; - protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value); + protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value) + { + AccentColour = AccentColour, + }; - protected override float StripWidth() => base.StripWidth() - (padding + 8); + protected override float StripWidth() => base.StripWidth() - (padding + item_chevron_size); public BreadcrumbControl() { - Height = 26; + Height = 32; TabContainer.Spacing = new Vector2(padding, 0f); Current.ValueChanged += tab => { @@ -47,6 +51,7 @@ namespace osu.Game.Graphics.UserInterface public override bool HandleKeyboardInput => State == Visibility.Visible; public override bool HandleMouseInput => State == Visibility.Visible; + public override bool IsRemovable => true; private Visibility state; @@ -77,13 +82,14 @@ namespace osu.Game.Graphics.UserInterface public BreadcrumbTabItem(T value) : base(value) { - Text.TextSize = 16; - Padding = new MarginPadding { Right = padding + 8 }; //padding + chevron width + Text.TextSize = 18; + Text.Margin = new MarginPadding { Vertical = 8 }; + Padding = new MarginPadding { Right = padding + item_chevron_size }; Add(Chevron = new SpriteIcon { Anchor = Anchor.CentreRight, Origin = Anchor.CentreLeft, - Size = new Vector2(12), + Size = new Vector2(item_chevron_size), Icon = FontAwesome.fa_chevron_right, Margin = new MarginPadding { Left = padding }, Alpha = 0f, From c35760fdef40981d1830e32e5d2c5d292300f9d8 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 20:39:05 -0300 Subject: [PATCH 086/302] Rename osu.Game/Screens/Multiplayer to Multi. --- osu.Game.Tests/Visual/TestCaseDrawableRoom.cs | 2 +- osu.Game.Tests/Visual/TestCaseRoomInspector.cs | 2 +- osu.Game/Screens/Menu/MainMenu.cs | 2 +- osu.Game/Screens/Multi/.DS_Store | Bin 0 -> 6148 bytes .../{Multiplayer => Multi}/DrawableGameType.cs | 2 +- .../{Multiplayer => Multi}/DrawableRoom.cs | 2 +- osu.Game/Screens/{Multiplayer => Multi}/Lobby.cs | 2 +- osu.Game/Screens/{Multiplayer => Multi}/Match.cs | 2 +- .../{Multiplayer => Multi}/MatchCreate.cs | 2 +- .../{Multiplayer => Multi}/ModeTypeInfo.cs | 2 +- .../{Multiplayer => Multi}/ParticipantInfo.cs | 2 +- .../{Multiplayer => Multi}/RoomInspector.cs | 2 +- 12 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Screens/Multi/.DS_Store rename osu.Game/Screens/{Multiplayer => Multi}/DrawableGameType.cs (96%) rename osu.Game/Screens/{Multiplayer => Multi}/DrawableRoom.cs (99%) rename osu.Game/Screens/{Multiplayer => Multi}/Lobby.cs (91%) rename osu.Game/Screens/{Multiplayer => Multi}/Match.cs (96%) rename osu.Game/Screens/{Multiplayer => Multi}/MatchCreate.cs (92%) rename osu.Game/Screens/{Multiplayer => Multi}/ModeTypeInfo.cs (98%) rename osu.Game/Screens/{Multiplayer => Multi}/ParticipantInfo.cs (99%) rename osu.Game/Screens/{Multiplayer => Multi}/RoomInspector.cs (99%) diff --git a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs index 25f8ba06c4..958dbd3c74 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multiplayer; +using osu.Game.Screens.Multi; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index 88059d2dcf..d0752cfc76 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multiplayer; +using osu.Game.Screens.Multi; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index f2ea6d85a8..b09b53063a 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Charts; using osu.Game.Screens.Direct; using osu.Game.Screens.Edit; -using osu.Game.Screens.Multiplayer; +using osu.Game.Screens.Multi; using osu.Game.Screens.Select; using osu.Game.Screens.Tournament; diff --git a/osu.Game/Screens/Multi/.DS_Store b/osu.Game/Screens/Multi/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Thu, 10 May 2018 20:44:24 -0300 Subject: [PATCH 087/302] Move multiplayer screen components to osu.Game/Screens/Multi/Components --- osu.Game.Tests/Visual/TestCaseDrawableRoom.cs | 1 + osu.Game.Tests/Visual/TestCaseRoomInspector.cs | 1 + osu.Game/Screens/Multi/.DS_Store | Bin 6148 -> 0 bytes .../Multi/{ => Components}/DrawableGameType.cs | 2 +- .../Multi/{ => Components}/DrawableRoom.cs | 6 +++--- .../Multi/{ => Components}/ModeTypeInfo.cs | 4 ++-- .../Multi/{ => Components}/ParticipantInfo.cs | 4 ++-- .../Multi/{ => Components}/RoomInspector.cs | 6 +++--- 8 files changed, 13 insertions(+), 11 deletions(-) delete mode 100644 osu.Game/Screens/Multi/.DS_Store rename osu.Game/Screens/Multi/{ => Components}/DrawableGameType.cs (96%) rename osu.Game/Screens/Multi/{ => Components}/DrawableRoom.cs (99%) rename osu.Game/Screens/Multi/{ => Components}/ModeTypeInfo.cs (98%) rename osu.Game/Screens/Multi/{ => Components}/ParticipantInfo.cs (99%) rename osu.Game/Screens/Multi/{ => Components}/RoomInspector.cs (99%) diff --git a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs index 958dbd3c74..3c61efd689 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs @@ -9,6 +9,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index d0752cfc76..4cf19924e9 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -8,6 +8,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game/Screens/Multi/.DS_Store b/osu.Game/Screens/Multi/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0. // 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.Configuration; using osu.Framework.Extensions.Color4Extensions; @@ -17,8 +15,10 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; using osu.Game.Users; +using OpenTK; +using OpenTK.Graphics; -namespace osu.Game.Screens.Multi +namespace osu.Game.Screens.Multi.Components { public class DrawableRoom : OsuClickableContainer { diff --git a/osu.Game/Screens/Multi/ModeTypeInfo.cs b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs similarity index 98% rename from osu.Game/Screens/Multi/ModeTypeInfo.cs rename to osu.Game/Screens/Multi/Components/ModeTypeInfo.cs index 1c175bad44..e3aba685a7 100644 --- a/osu.Game/Screens/Multi/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs @@ -1,14 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Online.Multiplayer; +using OpenTK; -namespace osu.Game.Screens.Multi +namespace osu.Game.Screens.Multi.Components { public class ModeTypeInfo : Container { diff --git a/osu.Game/Screens/Multi/ParticipantInfo.cs b/osu.Game/Screens/Multi/Components/ParticipantInfo.cs similarity index 99% rename from osu.Game/Screens/Multi/ParticipantInfo.cs rename to osu.Game/Screens/Multi/Components/ParticipantInfo.cs index a5d2bcd78a..ab404488f1 100644 --- a/osu.Game/Screens/Multi/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantInfo.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -11,8 +10,9 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Users; +using OpenTK; -namespace osu.Game.Screens.Multi +namespace osu.Game.Screens.Multi.Components { public class ParticipantInfo : Container { diff --git a/osu.Game/Screens/Multi/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs similarity index 99% rename from osu.Game/Screens/Multi/RoomInspector.cs rename to osu.Game/Screens/Multi/Components/RoomInspector.cs index d8c5d5ea9a..92910e8301 100644 --- a/osu.Game/Screens/Multi/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -2,8 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; @@ -20,8 +18,10 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; using osu.Game.Users; +using OpenTK; +using OpenTK.Graphics; -namespace osu.Game.Screens.Multi +namespace osu.Game.Screens.Multi.Components { public class RoomInspector : Container { From bc9ac8f72a2a281cf43510cd8b81c825a423c27f Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 20:47:25 -0300 Subject: [PATCH 088/302] Move multiplayer screens to osu.Game/Screens/Multi/Screens --- osu.Game/Screens/Menu/MainMenu.cs | 1 + osu.Game/Screens/Multi/{ => Screens}/Lobby.cs | 2 +- osu.Game/Screens/Multi/{ => Screens}/Match.cs | 6 +++--- osu.Game/Screens/Multi/{ => Screens}/MatchCreate.cs | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) rename osu.Game/Screens/Multi/{ => Screens}/Lobby.cs (90%) rename osu.Game/Screens/Multi/{ => Screens}/Match.cs (96%) rename osu.Game/Screens/Multi/{ => Screens}/MatchCreate.cs (91%) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index b09b53063a..2baa26c676 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -15,6 +15,7 @@ using osu.Game.Screens.Charts; using osu.Game.Screens.Direct; using osu.Game.Screens.Edit; using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Screens; using osu.Game.Screens.Select; using osu.Game.Screens.Tournament; diff --git a/osu.Game/Screens/Multi/Lobby.cs b/osu.Game/Screens/Multi/Screens/Lobby.cs similarity index 90% rename from osu.Game/Screens/Multi/Lobby.cs rename to osu.Game/Screens/Multi/Screens/Lobby.cs index 80e682e9f9..dcda40e0d7 100644 --- a/osu.Game/Screens/Multi/Lobby.cs +++ b/osu.Game/Screens/Multi/Screens/Lobby.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace osu.Game.Screens.Multi +namespace osu.Game.Screens.Multi.Screens { public class Lobby : ScreenWhiteBox { diff --git a/osu.Game/Screens/Multi/Match.cs b/osu.Game/Screens/Multi/Screens/Match.cs similarity index 96% rename from osu.Game/Screens/Multi/Match.cs rename to osu.Game/Screens/Multi/Screens/Match.cs index eee302a115..4ba7fe9f6a 100644 --- a/osu.Game/Screens/Multi/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match.cs @@ -3,14 +3,14 @@ using System; using System.Collections.Generic; +using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Play; -using OpenTK.Graphics; using osu.Game.Screens.Select; -using osu.Framework.Graphics; +using OpenTK.Graphics; -namespace osu.Game.Screens.Multi +namespace osu.Game.Screens.Multi.Screens { public class Match : ScreenWhiteBox { diff --git a/osu.Game/Screens/Multi/MatchCreate.cs b/osu.Game/Screens/Multi/Screens/MatchCreate.cs similarity index 91% rename from osu.Game/Screens/Multi/MatchCreate.cs rename to osu.Game/Screens/Multi/Screens/MatchCreate.cs index db528ae2a3..6b4e26d5e5 100644 --- a/osu.Game/Screens/Multi/MatchCreate.cs +++ b/osu.Game/Screens/Multi/Screens/MatchCreate.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace osu.Game.Screens.Multi +namespace osu.Game.Screens.Multi.Screens { public class MatchCreate : ScreenWhiteBox { From a86843ccc93c1a88d65f527daf011c7b12db1674 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 20:49:42 -0300 Subject: [PATCH 089/302] Remove unused usings caused by multiplayer folder restructuring. --- osu.Game.Tests/Visual/TestCaseDrawableRoom.cs | 1 - osu.Game.Tests/Visual/TestCaseRoomInspector.cs | 1 - osu.Game/Screens/Menu/MainMenu.cs | 1 - 3 files changed, 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs index 3c61efd689..bb5bf93a69 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi; using osu.Game.Screens.Multi.Components; using osu.Game.Users; diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index 4cf19924e9..cb1425ca69 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi; using osu.Game.Screens.Multi.Components; using osu.Game.Users; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 2baa26c676..907ad81111 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -14,7 +14,6 @@ using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Charts; using osu.Game.Screens.Direct; using osu.Game.Screens.Edit; -using osu.Game.Screens.Multi; using osu.Game.Screens.Multi.Screens; using osu.Game.Screens.Select; using osu.Game.Screens.Tournament; From b9adeeb063400477e53e093438c51fb9714d9786 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 21:35:26 -0300 Subject: [PATCH 090/302] Add ScreenBreadcrumbControl. --- .../Visual/TestCaseScreenBreadcrumbs.cs | 108 ++++++++++++++++++ .../UserInterface/ScreenBreadcrumbControl.cs | 78 +++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs create mode 100644 osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs new file mode 100644 index 0000000000..5055b0e114 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +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.Screens; +using OpenTK; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseScreenBreadcrumbs : OsuTestCase + { + private readonly ScreenBreadcrumbControl breadcrumbs; + + public TestCaseScreenBreadcrumbs() + { + TestScreen startScreen; + OsuSpriteText titleText; + + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), + Children = new Drawable[] + { + breadcrumbs = new ScreenBreadcrumbControl + { + RelativeSizeAxes = Axes.X, + }, + titleText = new OsuSpriteText(), + }, + }, + startScreen = new TestScreenOne(), + }; + + breadcrumbs.OnScreenChanged += s => titleText.Text = $"Changed to {s.ToString()}"; + breadcrumbs.CurrentScreen = startScreen; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + breadcrumbs.StripColour = colours.Blue; + } + + private abstract class TestScreen : OsuScreen + { + protected abstract string Title { get; } + protected abstract string NextTitle { get; } + protected abstract TestScreen CreateNextScreen(); + + public override string ToString() => Title; + + protected TestScreen() + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = Title, + }, + new TriangleButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 100, + Text = $"Push {NextTitle}", + Action = () => Push(CreateNextScreen()), + }, + }, + }; + } + } + + private class TestScreenOne : TestScreen + { + protected override string Title => @"Screen One"; + protected override string NextTitle => @"Two"; + protected override TestScreen CreateNextScreen() => new TestScreenTwo(); + } + + private class TestScreenTwo : TestScreen + { + protected override string Title => @"Screen Two"; + protected override string NextTitle => @"One"; + protected override TestScreen CreateNextScreen() => new TestScreenOne(); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs new file mode 100644 index 0000000000..fbdb27a81c --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -0,0 +1,78 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Screens; + +namespace osu.Game.Graphics.UserInterface +{ + public class ScreenBreadcrumbControl : ScreenBreadcrumbControl + { + } + + public class ScreenBreadcrumbControl : BreadcrumbControl where T : Screen + { + private T currentScreen; + public T CurrentScreen + { + get { return currentScreen; } + set + { + if (value == currentScreen) return; + + if (CurrentScreen != null) + { + CurrentScreen.Exited -= onExited; + CurrentScreen.ModePushed -= onPushed; + } + else + { + // this is the first screen in the stack, so call the initial onPushed + currentScreen = value; + onPushed(CurrentScreen); + } + + currentScreen = value; + + if (CurrentScreen != null) + { + CurrentScreen.Exited += onExited; + CurrentScreen.ModePushed += onPushed; + Current.Value = CurrentScreen; + OnScreenChanged?.Invoke(CurrentScreen); + } + } + } + + public event Action OnScreenChanged; + + public ScreenBreadcrumbControl() + { + Current.ValueChanged += s => + { + if (s != CurrentScreen) + { + CurrentScreen = s; + s.MakeCurrent(); + } + }; + } + + private void onExited(Screen screen) + { + CurrentScreen = screen as T; + } + + private void onPushed(Screen screen) + { + var newScreen = screen as T; + + Items.ToList().SkipWhile(i => i != Current.Value).Skip(1).ForEach(RemoveItem); + AddItem(newScreen); + + CurrentScreen = newScreen; + } + } +} From a294f187ee90a187604d7e3788842f46c2e592fe Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 21:52:26 -0300 Subject: [PATCH 091/302] Add steps and asserts to TestCaseScreenBreadcrumbs. --- .../Visual/TestCaseScreenBreadcrumbs.cs | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs index 5055b0e114..6bb6b09746 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs @@ -17,6 +17,7 @@ namespace osu.Game.Tests.Visual public class TestCaseScreenBreadcrumbs : OsuTestCase { private readonly ScreenBreadcrumbControl breadcrumbs; + private TestScreen currentScreen, changedScreen = null; public TestCaseScreenBreadcrumbs() { @@ -40,11 +41,29 @@ namespace osu.Game.Tests.Visual titleText = new OsuSpriteText(), }, }, - startScreen = new TestScreenOne(), + currentScreen = startScreen = new TestScreenOne(), }; - breadcrumbs.OnScreenChanged += s => titleText.Text = $"Changed to {s.ToString()}"; - breadcrumbs.CurrentScreen = startScreen; + breadcrumbs.OnScreenChanged += s => + { + titleText.Text = $"Changed to {s.ToString()}"; + changedScreen = s; + }; + + AddStep(@"make start current", () => breadcrumbs.CurrentScreen = startScreen); + assertCurrent(); + pushNext(); + assertCurrent(); + pushNext(); + assertCurrent(); + + AddStep(@"make start current", () => + { + startScreen.MakeCurrent(); + currentScreen = startScreen; + }); + + assertCurrent(); } [BackgroundDependencyLoader] @@ -53,6 +72,9 @@ namespace osu.Game.Tests.Visual breadcrumbs.StripColour = colours.Blue; } + private void pushNext() => AddStep(@"push next screen", () => currentScreen = currentScreen.PushNext()); + private void assertCurrent() => AddAssert(@"assert the current screen is correct", () => currentScreen == changedScreen); + private abstract class TestScreen : OsuScreen { protected abstract string Title { get; } @@ -61,6 +83,14 @@ namespace osu.Game.Tests.Visual public override string ToString() => Title; + public TestScreen PushNext() + { + TestScreen screen = CreateNextScreen(); + Push(screen); + + return screen; + } + protected TestScreen() { Child = new FillFlowContainer @@ -84,7 +114,7 @@ namespace osu.Game.Tests.Visual Origin = Anchor.TopCentre, Width = 100, Text = $"Push {NextTitle}", - Action = () => Push(CreateNextScreen()), + Action = () => PushNext(), }, }, }; From 6f7d0c19efe10356d91a243a08d13ed01112a2a0 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 22:02:22 -0300 Subject: [PATCH 092/302] Remove redundant default value. --- osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs index 6bb6b09746..3e0dd9e018 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual public class TestCaseScreenBreadcrumbs : OsuTestCase { private readonly ScreenBreadcrumbControl breadcrumbs; - private TestScreen currentScreen, changedScreen = null; + private TestScreen currentScreen, changedScreen; public TestCaseScreenBreadcrumbs() { From d87ac5a1cbb0afb35979f3f1a150eddef7bafb44 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 22:12:25 -0300 Subject: [PATCH 093/302] Create the drawable hierarchy for DrawableRoom in load. --- osu.Game/Screens/Multiplayer/DrawableRoom.cs | 49 +++++++++----------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/Multiplayer/DrawableRoom.cs b/osu.Game/Screens/Multiplayer/DrawableRoom.cs index d53100526f..b9f464ff78 100644 --- a/osu.Game/Screens/Multiplayer/DrawableRoom.cs +++ b/osu.Game/Screens/Multiplayer/DrawableRoom.cs @@ -29,11 +29,10 @@ namespace osu.Game.Screens.Multiplayer private const float cover_width = 145; private readonly Box sideStrip; - private readonly Container coverContainer; - private readonly OsuSpriteText name, status, beatmapTitle, beatmapDash, beatmapArtist; - private readonly FillFlowContainer beatmapInfoFlow; - private readonly ParticipantInfo participantInfo; - private readonly ModeTypeInfo modeTypeInfo; + private Container coverContainer; + private OsuSpriteText name, status, beatmapTitle, beatmapDash, beatmapArtist; + private ParticipantInfo participantInfo; + private ModeTypeInfo modeTypeInfo; private readonly Bindable nameBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); @@ -62,6 +61,19 @@ namespace osu.Game.Screens.Multiplayer Radius = 5, }; + sideStrip = new Box + { + RelativeSizeAxes = Axes.Y, + Width = side_strip_width, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, LocalisationEngine localisation) + { + this.localisation = localisation; + this.colours = colours; + Children = new Drawable[] { new Box @@ -69,11 +81,7 @@ namespace osu.Game.Screens.Multiplayer RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex(@"212121"), }, - sideStrip = new Box - { - RelativeSizeAxes = Axes.Y, - Width = side_strip_width, - }, + sideStrip, new Container { Width = cover_width, @@ -133,10 +141,11 @@ namespace osu.Game.Screens.Multiplayer TextSize = 14, Font = @"Exo2.0-Bold", }, - beatmapInfoFlow = new FillFlowContainer + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Colour = colours.Gray9, Direction = FillDirection.Horizontal, Children = new[] { @@ -170,7 +179,9 @@ namespace osu.Game.Screens.Multiplayer nameBind.ValueChanged += displayName; hostBind.ValueChanged += displayUser; + statusBind.ValueChanged += displayStatus; typeBind.ValueChanged += displayGameType; + beatmapBind.ValueChanged += displayBeatmap; participantsBind.ValueChanged += displayParticipants; nameBind.BindTo(Room.Name); @@ -181,22 +192,6 @@ namespace osu.Game.Screens.Multiplayer participantsBind.BindTo(Room.Participants); } - [BackgroundDependencyLoader] - private void load(OsuColour colours, LocalisationEngine localisation) - { - this.localisation = localisation; - this.colours = colours; - - beatmapInfoFlow.Colour = colours.Gray9; - - //binded here instead of ctor because dependencies are needed - statusBind.ValueChanged += displayStatus; - beatmapBind.ValueChanged += displayBeatmap; - - statusBind.TriggerChange(); - beatmapBind.TriggerChange(); - } - private void displayName(string value) { name.Text = value; From ec53927d8e77730bd0cc6c820d6287f004018180 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 22:48:07 -0300 Subject: [PATCH 094/302] Add selection to DrawableRoom. --- osu.Game.Tests/Visual/TestCaseDrawableRoom.cs | 3 + .../Graphics/UserInterface/SelectionState.cs | 11 + osu.Game/Rulesets/Edit/HitObjectMask.cs | 7 +- osu.Game/Screens/Multiplayer/DrawableRoom.cs | 364 +++++++++--------- 4 files changed, 206 insertions(+), 179 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/SelectionState.cs diff --git a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs index 25f8ba06c4..65e782b828 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multiplayer; @@ -111,6 +112,7 @@ namespace osu.Game.Tests.Visual } }); + AddStep(@"select", () => first.State = SelectionState.Selected); AddStep(@"change title", () => first.Room.Name.Value = @"I Changed Name"); AddStep(@"change host", () => first.Room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } }); AddStep(@"change status", () => first.Room.Status.Value = new RoomStatusPlaying()); @@ -121,6 +123,7 @@ namespace osu.Game.Tests.Visual new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 1254 } } }, new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 123189 } } }, }); + AddStep(@"deselect", () => first.State = SelectionState.NotSelected); } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/UserInterface/SelectionState.cs b/osu.Game/Graphics/UserInterface/SelectionState.cs new file mode 100644 index 0000000000..079ae343eb --- /dev/null +++ b/osu.Game/Graphics/UserInterface/SelectionState.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Graphics.UserInterface +{ + public enum SelectionState + { + NotSelected, + Selected + } +} diff --git a/osu.Game/Rulesets/Edit/HitObjectMask.cs b/osu.Game/Rulesets/Edit/HitObjectMask.cs index ad7c27ad80..61fb700dd3 100644 --- a/osu.Game/Rulesets/Edit/HitObjectMask.cs +++ b/osu.Game/Rulesets/Edit/HitObjectMask.cs @@ -6,6 +6,7 @@ using osu.Framework; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; @@ -137,10 +138,4 @@ namespace osu.Game.Rulesets.Edit /// public virtual Quad SelectionQuad => ScreenSpaceDrawQuad; } - - public enum SelectionState - { - NotSelected, - Selected - } } diff --git a/osu.Game/Screens/Multiplayer/DrawableRoom.cs b/osu.Game/Screens/Multiplayer/DrawableRoom.cs index b9f464ff78..16eb93d3f0 100644 --- a/osu.Game/Screens/Multiplayer/DrawableRoom.cs +++ b/osu.Game/Screens/Multiplayer/DrawableRoom.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using osu.Framework; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -15,24 +17,23 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Users; namespace osu.Game.Screens.Multiplayer { - public class DrawableRoom : OsuClickableContainer + public class DrawableRoom : OsuClickableContainer, IStateful { + private const float corner_radius = 5; + private const float selection_border_width = 4; private const float transition_duration = 100; private const float content_padding = 10; private const float height = 100; private const float side_strip_width = 5; private const float cover_width = 145; - private readonly Box sideStrip; - private Container coverContainer; - private OsuSpriteText name, status, beatmapTitle, beatmapDash, beatmapArtist; - private ParticipantInfo participantInfo; - private ModeTypeInfo modeTypeInfo; + private readonly Box selectionBox; private readonly Bindable nameBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); @@ -41,148 +42,227 @@ namespace osu.Game.Screens.Multiplayer private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable participantsBind = new Bindable(); - private OsuColour colours; - private LocalisationEngine localisation; - public readonly Room Room; + private SelectionState state; + + public SelectionState State + { + get { return state; } + set + { + if (value == state) return; + state = value; + + if (state == SelectionState.Selected) + selectionBox.FadeIn(transition_duration); + else + selectionBox.FadeOut(transition_duration); + + StateChanged?.Invoke(State); + } + } + + public event Action StateChanged; + public DrawableRoom(Room room) { Room = room; RelativeSizeAxes = Axes.X; - Height = height; - CornerRadius = 5; + Height = height + selection_border_width * 2; + CornerRadius = corner_radius + selection_border_width / 2; Masking = true; - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(40), - Radius = 5, - }; - sideStrip = new Box + // create selectionBox here so State can be set before being loaded + selectionBox = new Box { - RelativeSizeAxes = Axes.Y, - Width = side_strip_width, + RelativeSizeAxes = Axes.Both, + Alpha = 0f, }; } [BackgroundDependencyLoader] private void load(OsuColour colours, LocalisationEngine localisation) { - this.localisation = localisation; - this.colours = colours; + Box sideStrip; + Container coverContainer; + OsuSpriteText name, status, beatmapTitle, beatmapDash, beatmapArtist; + ParticipantInfo participantInfo; + ModeTypeInfo modeTypeInfo; Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"212121"), - }, - sideStrip, - new Container - { - Width = cover_width, - RelativeSizeAxes = Axes.Y, - Masking = true, - Margin = new MarginPadding { Left = side_strip_width }, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - coverContainer = new Container - { - RelativeSizeAxes = Axes.Both, - }, - }, - }, + selectionBox, new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding + Padding = new MarginPadding(selection_border_width), + Child = new Container { - Vertical = content_padding, - Left = side_strip_width + cover_width + content_padding, - Right = content_padding, - }, - Children = new Drawable[] - { - new FillFlowContainer + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = corner_radius, + EdgeEffect = new EdgeEffectParameters { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(5f), - Children = new Drawable[] + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(40), + Radius = 5, + }, + Children = new Drawable[] + { + new Box { - name = new OsuSpriteText - { - TextSize = 18, - }, - participantInfo = new ParticipantInfo(), + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"212121"), }, - }, - new FillFlowContainer - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + sideStrip = new Box { - status = new OsuSpriteText + RelativeSizeAxes = Axes.Y, + Width = side_strip_width, + }, + new Container + { + Width = cover_width, + RelativeSizeAxes = Axes.Y, + Masking = true, + Margin = new MarginPadding { Left = side_strip_width }, + Children = new Drawable[] { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Colour = colours.Gray9, - Direction = FillDirection.Horizontal, - Children = new[] + new Box { - beatmapTitle = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-BoldItalic", - }, - beatmapDash = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-BoldItalic", - }, - beatmapArtist = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-RegularItalic", - }, + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + coverContainer = new Container + { + RelativeSizeAxes = Axes.Both, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Vertical = content_padding, + Left = side_strip_width + cover_width + content_padding, + Right = content_padding, + }, + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(5f), + Children = new Drawable[] + { + name = new OsuSpriteText + { + TextSize = 18, + }, + participantInfo = new ParticipantInfo(), + }, + }, + new FillFlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + status = new OsuSpriteText + { + TextSize = 14, + Font = @"Exo2.0-Bold", + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Colour = colours.Gray9, + Direction = FillDirection.Horizontal, + Children = new[] + { + beatmapTitle = new OsuSpriteText + { + TextSize = 14, + Font = @"Exo2.0-BoldItalic", + }, + beatmapDash = new OsuSpriteText + { + TextSize = 14, + Font = @"Exo2.0-BoldItalic", + }, + beatmapArtist = new OsuSpriteText + { + TextSize = 14, + Font = @"Exo2.0-RegularItalic", + }, + }, + }, + }, + }, + modeTypeInfo = new ModeTypeInfo + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, }, }, }, - }, - modeTypeInfo = new ModeTypeInfo - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, }, }, }, }; - nameBind.ValueChanged += displayName; - hostBind.ValueChanged += displayUser; - statusBind.ValueChanged += displayStatus; - typeBind.ValueChanged += displayGameType; - beatmapBind.ValueChanged += displayBeatmap; - participantsBind.ValueChanged += displayParticipants; + nameBind.ValueChanged += n => name.Text = n; + hostBind.ValueChanged += h => participantInfo.Host = h; + typeBind.ValueChanged += m => modeTypeInfo.Type = m; + participantsBind.ValueChanged += p => participantInfo.Participants = p; + + statusBind.ValueChanged += s => + { + status.Text = s.Message; + + foreach (Drawable d in new Drawable[] { selectionBox, sideStrip, status }) + d.FadeColour(s.GetAppropriateColour(colours), 100); + }; + + beatmapBind.ValueChanged += b => + { + modeTypeInfo.Beatmap = b; + + if (b != null) + { + coverContainer.FadeIn(transition_duration); + + LoadComponentAsync(new BeatmapSetCover(b.BeatmapSet) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), + }, coverContainer.Add); + + beatmapTitle.Current = localisation.GetUnicodePreference(b.Metadata.TitleUnicode, b.Metadata.Title); + beatmapDash.Text = @" - "; + beatmapArtist.Current = localisation.GetUnicodePreference(b.Metadata.ArtistUnicode, b.Metadata.Artist); + } + else + { + coverContainer.FadeOut(transition_duration); + + beatmapTitle.Current = null; + beatmapArtist.Current = null; + + beatmapTitle.Text = "Changing map"; + beatmapDash.Text = beatmapArtist.Text = string.Empty; + } + }; nameBind.BindTo(Room.Name); hostBind.BindTo(Room.Host); @@ -191,67 +271,5 @@ namespace osu.Game.Screens.Multiplayer beatmapBind.BindTo(Room.Beatmap); participantsBind.BindTo(Room.Participants); } - - private void displayName(string value) - { - name.Text = value; - } - - private void displayUser(User value) - { - participantInfo.Host = value; - } - - private void displayStatus(RoomStatus value) - { - if (value == null) return; - status.Text = value.Message; - - foreach (Drawable d in new Drawable[] { sideStrip, status }) - d.FadeColour(value.GetAppropriateColour(colours), 100); - } - - private void displayGameType(GameType value) - { - modeTypeInfo.Type = value; - } - - private void displayBeatmap(BeatmapInfo value) - { - modeTypeInfo.Beatmap = value; - - if (value != null) - { - coverContainer.FadeIn(transition_duration); - - LoadComponentAsync(new BeatmapSetCover(value.BeatmapSet) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), - }, - coverContainer.Add); - - beatmapTitle.Current = localisation.GetUnicodePreference(value.Metadata.TitleUnicode, value.Metadata.Title); - beatmapDash.Text = @" - "; - beatmapArtist.Current = localisation.GetUnicodePreference(value.Metadata.ArtistUnicode, value.Metadata.Artist); - } - else - { - coverContainer.FadeOut(transition_duration); - - beatmapTitle.Current = null; - beatmapArtist.Current = null; - - beatmapTitle.Text = "Changing map"; - beatmapDash.Text = beatmapArtist.Text = string.Empty; - } - } - - private void displayParticipants(User[] value) - { - participantInfo.Participants = value; - } } } From a241ff1c051447338442ae9e30d3b2b402182b0d Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 22:50:03 -0300 Subject: [PATCH 095/302] Cleanup. --- osu.Game/Screens/Multiplayer/DrawableRoom.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Multiplayer/DrawableRoom.cs b/osu.Game/Screens/Multiplayer/DrawableRoom.cs index 16eb93d3f0..a67ead74a1 100644 --- a/osu.Game/Screens/Multiplayer/DrawableRoom.cs +++ b/osu.Game/Screens/Multiplayer/DrawableRoom.cs @@ -45,7 +45,6 @@ namespace osu.Game.Screens.Multiplayer public readonly Room Room; private SelectionState state; - public SelectionState State { get { return state; } From 2bab08c4373a96360d48a8ed183ff79c1385b3d7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 14:07:17 +0900 Subject: [PATCH 096/302] Fix post-merge errors --- osu-framework | 2 +- osu.Game/Beatmaps/Beatmap.cs | 44 ----------------------------------- osu.Game/Beatmaps/IBeatmap.cs | 6 +++++ 3 files changed, 7 insertions(+), 45 deletions(-) diff --git a/osu-framework b/osu-framework index 0773d895d9..8c4f232694 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 0773d895d9aa0729995cd4a23efc28238e35ceed +Subproject commit 8c4f23269447d9ce21a5dbd3a0fd4f6caae9ab38 diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 9517d44fcd..84897853d8 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -12,50 +12,6 @@ using osu.Game.IO.Serialization.Converters; namespace osu.Game.Beatmaps { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// /// A Beatmap containing converted HitObjects. /// 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. /// From 816ad5c4269c080611156ed6cc798207188fb86a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 14:10:53 +0900 Subject: [PATCH 097/302] Pass down ruleset to the buffered wedge --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 7a8a04bd43..c88e01562f 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -88,7 +88,7 @@ namespace osu.Game.Screens.Select private void loadBeatmap() { - LoadComponentAsync(new BufferedWedgeInfo(beatmap) + LoadComponentAsync(new BufferedWedgeInfo(beatmap, ruleset.Value) { Shear = -Shear, Depth = Info?.Depth + 1 ?? 0, @@ -114,18 +114,18 @@ namespace osu.Game.Screens.Select private UnicodeBindableString titleBinding; private UnicodeBindableString artistBinding; - private RulesetInfo ruleset; + private readonly RulesetInfo ruleset; - public BufferedWedgeInfo(WorkingBeatmap working) + public BufferedWedgeInfo(WorkingBeatmap working, RulesetInfo userRuleset) { this.working = working; + + ruleset = userRuleset ?? working.BeatmapInfo.Ruleset; } [BackgroundDependencyLoader(true)] - private void load([NotNull] LocalisationEngine localisation, [CanBeNull] OsuGame osuGame) + private void load([NotNull] LocalisationEngine localisation) { - ruleset = osuGame?.Ruleset.Value ?? working.BeatmapInfo.Ruleset; - var beatmapInfo = working.BeatmapInfo; var metadata = beatmapInfo.Metadata ?? working.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); From fd9796d08c1c3aa74d7691f8825f353fefeb5b7a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 14:13:52 +0900 Subject: [PATCH 098/302] Remove some unnecessary changes --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index c88e01562f..236b1310e1 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -123,8 +123,8 @@ namespace osu.Game.Screens.Select ruleset = userRuleset ?? working.BeatmapInfo.Ruleset; } - [BackgroundDependencyLoader(true)] - private void load([NotNull] LocalisationEngine localisation) + [BackgroundDependencyLoader] + private void load(LocalisationEngine localisation) { var beatmapInfo = working.BeatmapInfo; var metadata = beatmapInfo.Metadata ?? working.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); From 8216bc311af892c778cad4ae46366755b6fd8bda Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:30:26 +0900 Subject: [PATCH 099/302] Restructure HitWindows to allow outside setting --- osu.Game/Rulesets/Objects/HitObject.cs | 25 +++++++++++++++---------- osu.Game/Rulesets/Objects/HitWindows.cs | 4 ++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 13fa61f536..70604855e9 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -51,16 +51,10 @@ namespace osu.Game.Rulesets.Objects private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY; - private HitWindows hitWindows; - /// /// The hit windows for this . /// - public HitWindows HitWindows - { - get => hitWindows ?? (hitWindows = new HitWindows(overallDifficulty)); - protected set => hitWindows = value; - } + public HitWindows HitWindows { get; set; } private readonly SortedList nestedHitObjects = new SortedList((h1, h2) => h1.StartTime.CompareTo(h2.StartTime)); @@ -78,7 +72,11 @@ namespace osu.Game.Rulesets.Objects nestedHitObjects.Clear(); CreateNestedHitObjects(); - nestedHitObjects.ForEach(h => h.ApplyDefaults(controlPointInfo, difficulty)); + nestedHitObjects.ForEach(h => + { + h.HitWindows = HitWindows; + h.ApplyDefaults(controlPointInfo, difficulty); + }); } protected virtual void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) @@ -89,8 +87,9 @@ namespace osu.Game.Rulesets.Objects Kiai = effectPoint.KiaiMode; SampleControlPoint = samplePoint; - overallDifficulty = difficulty.OverallDifficulty; - hitWindows = null; + if (HitWindows == null) + HitWindows = CreateHitWindows(); + HitWindows?.SetDifficulty(difficulty.OverallDifficulty); } protected virtual void CreateNestedHitObjects() @@ -98,5 +97,11 @@ namespace osu.Game.Rulesets.Objects } protected void AddNested(HitObject hitObject) => nestedHitObjects.Add(hitObject); + + /// + /// Creates the for this . + /// + /// + protected virtual HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index bf0878a408..7610593d6a 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -63,10 +63,10 @@ namespace osu.Game.Rulesets.Objects public bool AllowsOk; /// - /// Constructs hit windows by fitting a parameter to a 2-part piecewise linear function for each hit window. + /// Sets hit windows with values that correspond to a difficulty parameter. /// /// The parameter. - public HitWindows(double difficulty) + public virtual void SetDifficulty(double difficulty) { Perfect = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Perfect]); Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); From faa82f17cc1edd90bfa30c6dc53473b55b219335 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:30:50 +0900 Subject: [PATCH 100/302] Pass original hitobject HitWindows during conversion --- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 4 +++- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs | 8 +++++--- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 8 +++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index c8a7402904..4f7c52860f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -59,7 +59,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override Beatmap ConvertBeatmap(IBeatmap original) { - BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); @@ -85,7 +84,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps yield break; foreach (ManiaHitObject obj in objects) + { + obj.HitWindows = original.HitWindows; yield return obj; + } } private readonly List prevNoteTimes = new List(max_notes_for_density); diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 1cd4ec5668..54720548b4 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -40,7 +40,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps RepeatSamples = curveData.RepeatSamples, RepeatCount = curveData.RepeatCount, Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false + NewCombo = comboData?.NewCombo ?? false, + HitWindows = original.HitWindows }; } else if (endTimeData != null) @@ -50,8 +51,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps StartTime = original.StartTime, Samples = original.Samples, EndTime = endTimeData.EndTime, - Position = positionData?.Position ?? OsuPlayfield.BASE_SIZE / 2, + HitWindows = original.HitWindows }; } else @@ -61,7 +62,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps StartTime = original.StartTime, Samples = original.Samples, Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false + NewCombo = comboData?.NewCombo ?? false, + HitWindows = original.HitWindows }; } } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index eeb0fa1871..58efc3336d 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -132,7 +132,8 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { StartTime = j, Samples = currentSamples, - IsStrong = strong + IsStrong = strong, + HitWindows = obj.HitWindows }; } else @@ -142,6 +143,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps StartTime = j, Samples = currentSamples, IsStrong = strong, + HitWindows = obj.HitWindows }; } @@ -157,6 +159,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps IsStrong = strong, Duration = taikoDuration, TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4, + HitWindows = obj.HitWindows }; } } @@ -171,6 +174,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps IsStrong = strong, Duration = endTimeData.Duration, RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier), + HitWindows = obj.HitWindows }; } else @@ -184,6 +188,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, IsStrong = strong, + HitWindows = obj.HitWindows }; } else @@ -193,6 +198,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, IsStrong = strong, + HitWindows = obj.HitWindows }; } } From 9c65d347ba271ff0775b96ca19c6b121681c8261 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:31:12 +0900 Subject: [PATCH 101/302] Add convert taiko HitWindows --- .../Objects/Legacy/Taiko/ConvertHit.cs | 2 ++ .../Objects/Legacy/Taiko/ConvertSlider.cs | 2 ++ .../Objects/Legacy/Taiko/ConvertSpinner.cs | 2 ++ .../Legacy/Taiko/ConvertTaikoHitWindows.cs | 28 +++++++++++++++++++ 4 files changed, 34 insertions(+) create mode 100644 osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertTaikoHitWindows.cs diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index 72d18664bf..bdcd1abf3c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -11,5 +11,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko internal sealed class ConvertHit : HitObject, IHasCombo { public bool NewCombo { get; set; } + + protected override HitWindows CreateHitWindows() => new ConvertTaikoHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index e810e687bd..0237ab9619 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -11,5 +11,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasCombo { public bool NewCombo { get; set; } + + protected override HitWindows CreateHitWindows() => new ConvertTaikoHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index 193e50aed6..899f383bee 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -13,5 +13,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko public double EndTime { get; set; } public double Duration => EndTime - StartTime; + + protected override HitWindows CreateHitWindows() => new ConvertTaikoHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertTaikoHitWindows.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertTaikoHitWindows.cs new file mode 100644 index 0000000000..d3e8718307 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertTaikoHitWindows.cs @@ -0,0 +1,28 @@ +// 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 osu.Game.Beatmaps; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Objects.Legacy.Taiko +{ + public class ConvertTaikoHitWindows : HitWindows + { + private static readonly IReadOnlyDictionary base_ranges = new Dictionary + { + { HitResult.Great, (100, 70, 40) }, + { HitResult.Good, (240, 160, 100) }, + { HitResult.Meh, (270, 190, 140) }, + { HitResult.Miss, (400, 400, 400) }, + }; + + public override void SetDifficulty(double difficulty) + { + Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); + Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); + Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]); + Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); + } + } +} From c052ee71c10b222a979b4449054f829b4d806f7c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:31:36 +0900 Subject: [PATCH 102/302] Add convert osu HitWindows --- .../Rulesets/Objects/Legacy/Osu/ConvertHit.cs | 2 ++ .../Legacy/Osu/ConvertOsuHitWindows.cs | 28 +++++++++++++++++++ .../Objects/Legacy/Osu/ConvertSlider.cs | 2 ++ .../Objects/Legacy/Osu/ConvertSpinner.cs | 2 ++ 4 files changed, 34 insertions(+) create mode 100644 osu.Game/Rulesets/Objects/Legacy/Osu/ConvertOsuHitWindows.cs diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index f83173f498..bb5b0393e5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -18,5 +18,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public float Y => Position.Y; public bool NewCombo { get; set; } + + protected override HitWindows CreateHitWindows() => new ConvertOsuHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertOsuHitWindows.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertOsuHitWindows.cs new file mode 100644 index 0000000000..07d90f7012 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertOsuHitWindows.cs @@ -0,0 +1,28 @@ +// 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 osu.Game.Beatmaps; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Objects.Legacy.Osu +{ + public class ConvertOsuHitWindows : HitWindows + { + private static readonly IReadOnlyDictionary base_ranges = new Dictionary + { + { HitResult.Great, (160, 100, 40) }, + { HitResult.Good, (280, 200, 120) }, + { HitResult.Meh, (400, 300, 200) }, + { HitResult.Miss, (400, 400, 400) }, + }; + + public override void SetDifficulty(double difficulty) + { + Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); + Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); + Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]); + Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); + } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index c6033d482c..cbe044605b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -18,5 +18,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public float Y => Position.Y; public bool NewCombo { get; set; } + + protected override HitWindows CreateHitWindows() => new ConvertOsuHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index 28aac6862e..b580c5d1b3 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -20,5 +20,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public float X => Position.X; public float Y => Position.Y; + + protected override HitWindows CreateHitWindows() => new ConvertOsuHitWindows(); } } From 856329179612d679f3da8f1ae4f34341a8c080d0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:32:00 +0900 Subject: [PATCH 103/302] Add convert mania HitWindows --- .../Objects/Legacy/Mania/ConvertHit.cs | 2 ++ .../Objects/Legacy/Mania/ConvertHold.cs | 2 ++ .../Legacy/Mania/ConvertManiaHitWindows.cs | 32 +++++++++++++++++++ .../Objects/Legacy/Mania/ConvertSlider.cs | 2 ++ .../Objects/Legacy/Mania/ConvertSpinner.cs | 2 ++ 5 files changed, 40 insertions(+) create mode 100644 osu.Game/Rulesets/Objects/Legacy/Mania/ConvertManiaHitWindows.cs diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 0db5a1dff1..6bf28c5e45 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -13,5 +13,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public float X { get; set; } public bool NewCombo { get; set; } + + protected override HitWindows CreateHitWindows() => new ConvertManiaHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index e3b35e2f8e..087e5d5c12 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -12,5 +12,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public double EndTime { get; set; } public double Duration => EndTime - StartTime; + + protected override HitWindows CreateHitWindows() => new ConvertManiaHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertManiaHitWindows.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertManiaHitWindows.cs new file mode 100644 index 0000000000..072b45dc64 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertManiaHitWindows.cs @@ -0,0 +1,32 @@ +// 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 osu.Game.Beatmaps; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Objects.Legacy.Mania +{ + public class ConvertManiaHitWindows : HitWindows + { + private static readonly IReadOnlyDictionary base_ranges = new Dictionary + { + { HitResult.Perfect, (44.8, 38.8, 27.8) }, + { HitResult.Great, (128, 98, 68 ) }, + { HitResult.Good, (194, 164, 134) }, + { HitResult.Ok, (254, 224, 194) }, + { HitResult.Meh, (302, 272, 242) }, + { HitResult.Miss, (376, 346, 316) }, + }; + + public override void SetDifficulty(double difficulty) + { + Perfect = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Perfect]); + Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); + Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); + Ok = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Ok]); + Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]); + Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); + } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index 32fb197c62..08ce465619 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -13,5 +13,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public float X { get; set; } public bool NewCombo { get; set; } + + protected override HitWindows CreateHitWindows() => new ConvertManiaHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index c9b3046698..031ba54c59 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -15,5 +15,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public double Duration => EndTime - StartTime; public float X { get; set; } + + protected override HitWindows CreateHitWindows() => new ConvertManiaHitWindows(); } } From 0cdd39b8b8b06487339891af566d42d43cd36550 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:32:13 +0900 Subject: [PATCH 104/302] Add todo because TailNote shouldn't hardcore lenience --- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 4cf22ccd39..12e3d2de51 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -103,6 +103,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// /// Lenience of release hit windows. This is to make cases where the hold note release /// is timed alongside presses of other hit objects less awkward. + /// Todo: This shouldn't exist for non-LegacyBeatmapDecoder beatmaps /// private const double release_window_lenience = 1.5; From 5245d2d4268633565006069190bd14776e3d03eb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:36:53 +0900 Subject: [PATCH 105/302] Add info about when CreateHitWindows is invoked --- osu.Game/Rulesets/Objects/HitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 70604855e9..d7d827bc97 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -100,8 +100,8 @@ namespace osu.Game.Rulesets.Objects /// /// Creates the for this . + /// This will only be invoked if hasn't been set externally (e.g. from a . /// - /// protected virtual HitWindows CreateHitWindows() => null; } } From bfad101d17ad04d8ee1093e730fa3cc2ce6bff52 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:42:34 +0900 Subject: [PATCH 106/302] Standardise naming --- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs | 2 +- .../Mania/{ConvertManiaHitWindows.cs => ConvertHitWindows.cs} | 2 +- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs | 2 +- .../Osu/{ConvertOsuHitWindows.cs => ConvertHitWindows.cs} | 2 +- osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs | 2 +- .../Taiko/{ConvertTaikoHitWindows.cs => ConvertHitWindows.cs} | 2 +- osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) rename osu.Game/Rulesets/Objects/Legacy/Mania/{ConvertManiaHitWindows.cs => ConvertHitWindows.cs} (96%) rename osu.Game/Rulesets/Objects/Legacy/Osu/{ConvertOsuHitWindows.cs => ConvertHitWindows.cs} (95%) rename osu.Game/Rulesets/Objects/Legacy/Taiko/{ConvertTaikoHitWindows.cs => ConvertHitWindows.cs} (95%) diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 6bf28c5e45..939d3b9c93 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertManiaHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertManiaHitWindows.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitWindows.cs similarity index 96% rename from osu.Game/Rulesets/Objects/Legacy/Mania/ConvertManiaHitWindows.cs rename to osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitWindows.cs index 072b45dc64..131492ea12 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertManiaHitWindows.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitWindows.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Mania { - public class ConvertManiaHitWindows : HitWindows + public class ConvertHitWindows : HitWindows { private static readonly IReadOnlyDictionary base_ranges = new Dictionary { diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index 087e5d5c12..22abc64b60 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public double Duration => EndTime - StartTime; - protected override HitWindows CreateHitWindows() => new ConvertManiaHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index 08ce465619..6bca5b717c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertManiaHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index 031ba54c59..1dc826af9b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public float X { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertManiaHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index bb5b0393e5..23955b2d23 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertOsuHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertOsuHitWindows.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitWindows.cs similarity index 95% rename from osu.Game/Rulesets/Objects/Legacy/Osu/ConvertOsuHitWindows.cs rename to osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitWindows.cs index 07d90f7012..fd86173372 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertOsuHitWindows.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitWindows.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Osu { - public class ConvertOsuHitWindows : HitWindows + public class ConvertHitWindows : HitWindows { private static readonly IReadOnlyDictionary base_ranges = new Dictionary { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index cbe044605b..35b8c1c7dd 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertOsuHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index b580c5d1b3..73b8369aca 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -21,6 +21,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public float Y => Position.Y; - protected override HitWindows CreateHitWindows() => new ConvertOsuHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index bdcd1abf3c..11db086778 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko { public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertTaikoHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertTaikoHitWindows.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitWindows.cs similarity index 95% rename from osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertTaikoHitWindows.cs rename to osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitWindows.cs index d3e8718307..6fbf7e122f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertTaikoHitWindows.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitWindows.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Taiko { - public class ConvertTaikoHitWindows : HitWindows + public class ConvertHitWindows : HitWindows { private static readonly IReadOnlyDictionary base_ranges = new Dictionary { diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index 0237ab9619..95c69222b5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko { public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertTaikoHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index 899f383bee..7baea212ea 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko public double Duration => EndTime - StartTime; - protected override HitWindows CreateHitWindows() => new ConvertTaikoHitWindows(); + protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); } } From 97a523584da0b8b686961cccc71763cb8189b50f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 15:52:51 +0900 Subject: [PATCH 107/302] Make HitWindows not return null by default --- osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs | 2 ++ osu.Game/Rulesets/Objects/HitObject.cs | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 95ffd41518..548813fbd2 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -47,6 +47,8 @@ namespace osu.Game.Rulesets.Catch.Objects Scale = 1.0f - 0.7f * (difficulty.CircleSize - 5) / 5; } + + protected override HitWindows CreateHitWindows() => null; } public enum FruitVisualRepresentation diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index d7d827bc97..cd612a5387 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -100,8 +100,11 @@ namespace osu.Game.Rulesets.Objects /// /// Creates the for this . + /// This can be null to indicate that the has no . + /// /// This will only be invoked if hasn't been set externally (e.g. from a . + /// /// - protected virtual HitWindows CreateHitWindows() => null; + protected virtual HitWindows CreateHitWindows() => new HitWindows(); } } From 3e7fa45ad18b168fe3a0268f635143c8bbe9b05e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 16:12:56 +0900 Subject: [PATCH 108/302] Fix tests --- .../TestCaseManiaHitObjects.cs | 16 ++++++++++++---- .../Beatmaps/Formats/OsuJsonDecoderTest.cs | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs index 281c2789af..dd81d015f1 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects; using osu.Game.Tests.Visual; using OpenTK; using OpenTK.Graphics; @@ -17,6 +18,9 @@ namespace osu.Game.Rulesets.Mania.Tests { public TestCaseManiaHitObjects() { + var hitWindows = new HitWindows(); + hitWindows.SetDifficulty(5); + Add(new FillFlowContainer { Anchor = Anchor.Centre, @@ -43,14 +47,14 @@ namespace osu.Game.Rulesets.Mania.Tests RelativeChildSize = new Vector2(1, 10000), Children = new[] { - new DrawableNote(new Note(), ManiaAction.Key1) + new DrawableNote(new Note { HitWindows = hitWindows }, ManiaAction.Key1) { Y = 5000, LifetimeStart = double.MinValue, LifetimeEnd = double.MaxValue, AccentColour = Color4.Red }, - new DrawableNote(new Note(), ManiaAction.Key1) + new DrawableNote(new Note { HitWindows = hitWindows }, ManiaAction.Key1) { Y = 6000, LifetimeStart = double.MinValue, @@ -77,13 +81,17 @@ namespace osu.Game.Rulesets.Mania.Tests RelativeChildSize = new Vector2(1, 10000), Children = new[] { - new DrawableHoldNote(new HoldNote { Duration = 1000 } , ManiaAction.Key1) + new DrawableHoldNote(new HoldNote + { + Duration = 1000, + HitWindows = hitWindows + } , ManiaAction.Key1) { Y = 5000, Height = 1000, LifetimeStart = double.MinValue, LifetimeEnd = double.MaxValue, - AccentColour = Color4.Red + AccentColour = Color4.Red, } } } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 6e0cf6be2e..489c38c420 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -9,6 +9,7 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO.Serialization; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Tests.Resources; using OpenTK; @@ -117,7 +118,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestParity(string beatmap) { var legacy = decode(beatmap, out Beatmap json); - json.ShouldDeepEqual(legacy); + json.WithDeepEqual(legacy).IgnoreProperty(r => r.DeclaringType == typeof(HitWindows)).Assert(); } /// From fa403e4e2ae4a2a0ad36f5f2261239093994c2d3 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Fri, 11 May 2018 04:45:27 -0300 Subject: [PATCH 109/302] Add test step to test pushing after a previous screen is made current. --- osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs | 3 +++ osu.Game/Graphics/UserInterface/BreadcrumbControl.cs | 1 + 2 files changed, 4 insertions(+) diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs index 3e0dd9e018..f477a0b97e 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -64,6 +65,8 @@ namespace osu.Game.Tests.Visual }); assertCurrent(); + pushNext(); + AddAssert(@"assert there are only 2 items", () => breadcrumbs.Items.Count() == 2); } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index 3f59eeca97..6b7f235b34 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -47,6 +47,7 @@ namespace osu.Game.Graphics.UserInterface public override bool HandleKeyboardInput => State == Visibility.Visible; public override bool HandleMouseInput => State == Visibility.Visible; + public override bool IsRemovable => true; private Visibility state; From 4fc887b25f1addd4cc08d7cdcb6e93df23c3ad16 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 May 2018 21:40:36 +0900 Subject: [PATCH 110/302] Add a pressing effect to make mouse up response feel good --- osu.Game/Overlays/Mods/ModButton.cs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 3f1541aee3..1d012b1288 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -116,6 +116,7 @@ namespace osu.Game.Overlays.Mods } private Mod mod; + private Container scaleContainer; public Mod Mod { @@ -147,8 +148,16 @@ namespace osu.Game.Overlays.Mods public virtual Mod SelectedMod => Mods.ElementAtOrDefault(selectedIndex); + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + scaleContainer.ScaleTo(0.9f, 800, Easing.Out); + return base.OnMouseDown(state, args); + } + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { + scaleContainer.ScaleTo(1, 500, Easing.OutElastic); + // only trigger the event if we are inside the area of the button if (Contains(ToScreenSpace(state.Mouse.Position - Position))) { @@ -162,6 +171,7 @@ namespace osu.Game.Overlays.Mods break; } } + return true; } @@ -179,7 +189,8 @@ namespace osu.Game.Overlays.Mods start = Mods.Length - 1; for (int i = start; i < Mods.Length && i >= 0; i += direction) - if (SelectAt(i)) return; + if (SelectAt(i)) + return; Deselect(); } @@ -245,8 +256,14 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Children = new Drawable[] { - iconsContainer = new Container + scaleContainer = new Container { + Child = iconsContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + }, RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, From 7cb0d328e60fbccc495b419fc69eed730b348881 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 May 2018 21:40:48 +0900 Subject: [PATCH 111/302] Make mods screen dynamically testable --- osu.Game.Tests/Visual/TestCaseMods.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index dad8fb8fed..d3d21509fd 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -17,6 +18,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.UI; using OpenTK.Graphics; namespace osu.Game.Tests.Visual @@ -24,6 +26,19 @@ namespace osu.Game.Tests.Visual [Description("mod select and icon display")] public class TestCaseMods : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ModSelectOverlay), + typeof(ModDisplay), + typeof(ModSection), + typeof(ModIcon), + typeof(ModButton), + typeof(ModButtonEmpty), + typeof(DifficultyReductionSection), + typeof(DifficultyIncreaseSection), + typeof(SpecialSection), + }; + private const string unranked_suffix = " (Unranked)"; private RulesetStore rulesets; @@ -66,7 +81,8 @@ namespace osu.Game.Tests.Visual Ruleset ruleset = rulesetInfo.CreateInstance(); AddStep($"switch to {ruleset.Description}", () => modSelect.Ruleset.Value = rulesetInfo); - switch (ruleset) { + switch (ruleset) + { case OsuRuleset or: testOsuMods(or); break; From aa5d5ab2a844c5834134b159c1960b2c3f397dca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 May 2018 21:48:35 +0900 Subject: [PATCH 112/302] Fix readonly field --- osu.Game/Overlays/Mods/ModButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 1d012b1288..f4e0e3db04 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Mods } private Mod mod; - private Container scaleContainer; + private readonly Container scaleContainer; public Mod Mod { From 8ca67f63ece8c3469557ebe6278f67e22d6f5a57 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 20:31:57 +0900 Subject: [PATCH 113/302] Fix score statistics not being read --- .../Scoring/Legacy/LegacyScoreParser.cs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs index d5ab856697..1cc30afe7b 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs @@ -49,18 +49,21 @@ namespace osu.Game.Rulesets.Scoring.Legacy score.User = new User { Username = sr.ReadString() }; /* var localScoreChecksum = */ sr.ReadString(); - /* score.Count300 = */ - sr.ReadUInt16(); - /* score.Count100 = */ - sr.ReadUInt16(); - /* score.Count50 = */ - sr.ReadUInt16(); - /* score.CountGeki = */ - sr.ReadUInt16(); - /* score.CountKatu = */ - sr.ReadUInt16(); - /* score.CountMiss = */ - sr.ReadUInt16(); + + var count300 = sr.ReadUInt16(); + var count100 = sr.ReadUInt16(); + var count50 = sr.ReadUInt16(); + var countGeki = sr.ReadUInt16(); + var countKatu = sr.ReadUInt16(); + var countMiss = sr.ReadUInt16(); + + score.Statistics[HitResult.Great] = count300; + score.Statistics[HitResult.Good] = count100; + score.Statistics[HitResult.Meh] = count50; + score.Statistics[HitResult.Perfect] = countGeki; + score.Statistics[HitResult.Ok] = countKatu; + score.Statistics[HitResult.Miss] = countMiss; + score.TotalScore = sr.ReadInt32(); score.MaxCombo = sr.ReadUInt16(); /* score.Perfect = */ From 7e7a5f8964972a045cf4f6ef2f47332937a49f82 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 20:32:06 +0900 Subject: [PATCH 114/302] Fix score accuracy not being populated --- .../Scoring/Legacy/LegacyScoreParser.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs index 1cc30afe7b..38873c4df1 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs @@ -84,6 +84,34 @@ namespace osu.Game.Rulesets.Scoring.Legacy /*OnlineId =*/ sr.ReadInt32(); + switch (score.Ruleset.ID) + { + case 0: + { + int totalHits = count50 + count100 + count300 + countMiss; + score.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + count300 * 300) / (totalHits * 300) : 1; + break; + } + case 1: + { + int totalHits = count50 + count100 + count300 + countMiss; + score.Accuracy = totalHits > 0 ? (double)(count100 * 150 + count300 * 300) / (totalHits * 300) : 1; + break; + } + case 2: + { + int totalHits = count50 + count100 + count300 + countMiss + countKatu; + score.Accuracy = totalHits > 0 ? (double)(count50 + count100 + count300 ) / totalHits : 1; + break; + } + case 3: + { + int totalHits = count50 + count100 + count300 + countMiss + countGeki + countKatu; + score.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + countKatu * 200 + (count300 + countGeki) * 300) / (totalHits * 300) : 1; + break; + } + } + using (var replayInStream = new MemoryStream(compressedReplay)) { byte[] properties = new byte[5]; From 224f1a0810f75b6d292ee49fa0d0a0c02be60579 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 21:48:10 +0900 Subject: [PATCH 115/302] Fix incorrect osu! difficulty calculator combo count --- osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index 6b9214d9dc..103fdeadea 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Scoring countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); beatmapMaxCombo = Beatmap.HitObjects.Count(); - beatmapMaxCombo += Beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count) + 1; + beatmapMaxCombo += Beatmap.HitObjects.OfType().Count(); } public override double Calculate(Dictionary categoryRatings = null) From a33724899973bd46204dfa981d6bc82ba66f0526 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 May 2018 22:06:16 +0900 Subject: [PATCH 116/302] Fix incorrect count --- osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index 103fdeadea..b4324c77fc 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -32,7 +32,8 @@ namespace osu.Game.Rulesets.Osu.Scoring countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); beatmapMaxCombo = Beatmap.HitObjects.Count(); - beatmapMaxCombo += Beatmap.HitObjects.OfType().Count(); + // Add the ticks + tail of the slider. 1 is subtracted because the "headcircle" would be counted twice (once for the slider itself in the line above) + beatmapMaxCombo += Beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count - 1); } public override double Calculate(Dictionary categoryRatings = null) From cfa18bdf1fa2823dd6ead2b9c37a3ce67be4b746 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 May 2018 22:09:53 +0900 Subject: [PATCH 117/302] Fix song progress time counters wrapping after an hour Resolves #2466. Supersedes and closes #2487. --- osu.Game/Screens/Play/SongProgressInfo.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/SongProgressInfo.cs b/osu.Game/Screens/Play/SongProgressInfo.cs index 5cc4b30950..b79c212ade 100644 --- a/osu.Game/Screens/Play/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/SongProgressInfo.cs @@ -85,11 +85,13 @@ namespace osu.Game.Screens.Play if (currentSecond != previousSecond && songCurrentTime < songLength) { - timeCurrent.Text = TimeSpan.FromSeconds(currentSecond).ToString(songCurrentTime < 0 ? @"\-m\:ss" : @"m\:ss"); - timeLeft.Text = TimeSpan.FromMilliseconds(endTime - AudioClock.CurrentTime).ToString(@"\-m\:ss"); + timeCurrent.Text = formatTime(TimeSpan.FromSeconds(currentSecond)); + timeLeft.Text = formatTime(TimeSpan.FromMilliseconds(endTime - AudioClock.CurrentTime)); previousSecond = currentSecond; } } + + private string formatTime(TimeSpan timeSpan) => $"{(timeSpan < TimeSpan.Zero ? "-" : "")}{timeSpan.Duration().TotalMinutes:N0}:{timeSpan.Duration().Seconds:D2}"; } } From a14531b9a4d0f4b101d5af1e91df2eb2877bcc1c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 May 2018 22:57:36 +0900 Subject: [PATCH 118/302] Fix crash on startup when adjusting volume before volume control loaded --- osu.Game/Overlays/VolumeOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index da63495fec..f922c507f7 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -100,6 +100,8 @@ namespace osu.Game.Overlays public bool Adjust(GlobalAction action) { + if (!IsLoaded) return false; + switch (action) { case GlobalAction.DecreaseVolume: From 41de02fc78e08513e9588a6d02090044155ed32f Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Fri, 11 May 2018 13:43:53 -0300 Subject: [PATCH 119/302] Make DrawableRooms select when they are clicked. --- osu.Game/Screens/Multi/Components/DrawableRoom.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index f3ce3dcd8e..994b0e886b 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -9,6 +9,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; @@ -79,6 +80,8 @@ namespace osu.Game.Screens.Multi.Components RelativeSizeAxes = Axes.Both, Alpha = 0f, }; + + Action += () => State = SelectionState.Selected; } [BackgroundDependencyLoader] From 937ff50a5a4269431973066233d776fc16ace442 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Fri, 11 May 2018 13:56:27 -0300 Subject: [PATCH 120/302] Remove unused using. --- osu.Game/Screens/Multi/Components/DrawableRoom.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 994b0e886b..88a253d719 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -9,7 +9,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; From 6ebe9f88e78b1c222fcecb6ba4b3ec5f0e003eed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 12 May 2018 11:11:09 +0900 Subject: [PATCH 121/302] Update framework with upstream fixes --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 8c4f232694..f807997301 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 8c4f23269447d9ce21a5dbd3a0fd4f6caae9ab38 +Subproject commit f8079973011b54e84e5c0e677fe2b56e55947666 From 416ed725977527718f4c5fe744e0a60181c0cd8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 12 May 2018 15:46:25 +0900 Subject: [PATCH 122/302] Port osu-performance changes into OsuPerformanceCalculator --- osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index 6b9214d9dc..a06e71e20c 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Osu.Scoring aimValue *= approachRateFactor; if (mods.Any(h => h is OsuModHidden)) - aimValue *= 1.18f; + aimValue *= 1.03f; if (mods.Any(h => h is OsuModFlashlight)) { @@ -152,6 +152,9 @@ namespace osu.Game.Rulesets.Osu.Scoring if (beatmapMaxCombo > 0) speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); + if (mods.Any(m => m is OsuModHidden)) + speedValue *= 1.18f; + // Scale the speed value with accuracy _slightly_ speedValue *= 0.5f + accuracy / 2.0f; // It is important to also consider accuracy difficulty when doing that From 2a90686da622cbf9d6619bb787e3cc370de07906 Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Sat, 12 May 2018 15:09:53 +0300 Subject: [PATCH 123/302] Simplify expression --- osu-framework | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu-framework b/osu-framework index 0773d895d9..e793a08417 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 0773d895d9aa0729995cd4a23efc28238e35ceed +Subproject commit e793a084177f53920645c4f6f70cfef91e7fd19e diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 88d8477233..6cae4d9187 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -9,6 +9,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit.Screens.Compose; +using OpenTK; namespace osu.Game.Screens.Edit { @@ -126,7 +127,7 @@ namespace osu.Game.Screens.Edit seekTime = nextTimingPoint.Time; // Ensure the sought point is within the boundaries - seekTime = Math.Min(Math.Max(0, seekTime), TrackLength); + seekTime = MathHelper.Clamp(seekTime, 0, TrackLength); Seek(seekTime); } } From df43fc6ff8defe26d52b002f19ebd20bb8515a90 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 13 May 2018 01:31:17 +0900 Subject: [PATCH 124/302] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index eaa640972c..fac688633b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit eaa640972ca9c67f0ea15a942035b5b3a78f1570 +Subproject commit fac688633b8fcf34ae5d0514c26b03e217161eb4 From 8a5bd27c2018e0ae4f980e77aea891f70b1ce562 Mon Sep 17 00:00:00 2001 From: ocboogie Date: Sat, 12 May 2018 16:30:29 -0700 Subject: [PATCH 125/302] Add global key bindings for changing current ruleset --- .../Overlays/Toolbar/ToolbarModeSelector.cs | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 1da51e4a5a..4855c004c4 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -1,11 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; using OpenTK; using OpenTK.Graphics; using osu.Framework.Configuration; @@ -14,7 +17,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.Toolbar { - public class ToolbarModeSelector : Container + public class ToolbarModeSelector : KeyBindingContainer { private const float padding = 10; @@ -22,6 +25,7 @@ namespace osu.Game.Overlays.Toolbar private readonly Drawable modeButtonLine; private ToolbarModeButton activeButton; + private int rulesetCount; private readonly Bindable ruleset = new Bindable(); public ToolbarModeSelector() @@ -64,9 +68,50 @@ namespace osu.Game.Overlays.Toolbar }; } + public override IEnumerable DefaultKeyBindings + { + get + { + var keybinds = new List(); + for (int i = 0; i < Math.Min(rulesetCount, 10); i++) + { + InputKey numberKey; + if (i == 9) + numberKey = InputKey.Number0; + else + numberKey = (InputKey)i + 110; + + keybinds.Add(new osu.Framework.Input.Bindings.KeyBinding(new[] { InputKey.Control, numberKey }, i)); + } + return keybinds; + } + } + + private class RulesetSwitcherInputHandler : Container, IKeyBindingHandler + { + private Bindable ruleset; + private RulesetStore rulesets; + + public RulesetSwitcherInputHandler(Bindable ruleset, RulesetStore rulesets) + { + this.ruleset = ruleset; + this.rulesets = rulesets; + } + + public bool OnPressed(int action) + { + ruleset.Value = rulesets.GetRuleset(action); + + return true; + } + + public bool OnReleased(int action) => false; + } + [BackgroundDependencyLoader(true)] private void load(RulesetStore rulesets, OsuGame game) { + this.rulesetCount = rulesets.AvailableRulesets.Count(); foreach (var r in rulesets.AvailableRulesets) { modeButtons.Add(new ToolbarModeButton @@ -85,6 +130,8 @@ namespace osu.Game.Overlays.Toolbar ruleset.BindTo(game.Ruleset); else ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(); + + Add(new RulesetSwitcherInputHandler(ruleset, rulesets)); } public override bool HandleKeyboardInput => !ruleset.Disabled && base.HandleKeyboardInput; From 26f06a9ae1612e19bdc372873fd17ed84f70179e Mon Sep 17 00:00:00 2001 From: ocboogie Date: Sat, 12 May 2018 17:25:15 -0700 Subject: [PATCH 126/302] Resolve linting issues in ToolbarModeSelector.cs --- osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 4855c004c4..889cf8885e 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -89,8 +89,8 @@ namespace osu.Game.Overlays.Toolbar private class RulesetSwitcherInputHandler : Container, IKeyBindingHandler { - private Bindable ruleset; - private RulesetStore rulesets; + private readonly Bindable ruleset; + private readonly RulesetStore rulesets; public RulesetSwitcherInputHandler(Bindable ruleset, RulesetStore rulesets) { @@ -111,7 +111,7 @@ namespace osu.Game.Overlays.Toolbar [BackgroundDependencyLoader(true)] private void load(RulesetStore rulesets, OsuGame game) { - this.rulesetCount = rulesets.AvailableRulesets.Count(); + rulesetCount = rulesets.AvailableRulesets.Count(); foreach (var r in rulesets.AvailableRulesets) { modeButtons.Add(new ToolbarModeButton From db0470243ad2f3e19da40b1f8dcd67d353872173 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 13 May 2018 12:55:54 +0900 Subject: [PATCH 127/302] Fix nullref when changing ruleset at main menu --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 236b1310e1..97f6371cb2 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -88,17 +88,27 @@ namespace osu.Game.Screens.Select private void loadBeatmap() { + void updateState() + { + State = beatmap == null ? Visibility.Hidden : Visibility.Visible; + + Info?.FadeOut(250); + Info?.Expire(); + } + + if (beatmap == null) + { + updateState(); + return; + } + LoadComponentAsync(new BufferedWedgeInfo(beatmap, ruleset.Value) { Shear = -Shear, Depth = Info?.Depth + 1 ?? 0, }, newInfo => { - State = beatmap == null ? Visibility.Hidden : Visibility.Visible; - - Info?.FadeOut(250); - Info?.Expire(); - + updateState(); Add(Info = newInfo); }); } From e1b8a1589bae578864766632fe7d6da7b77b9354 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 11:15:14 +0900 Subject: [PATCH 128/302] Fix TimeRate not being considered for performance calculation --- .../Scoring/OsuPerformanceCalculator.cs | 24 +++++++++++++++---- osu.Game/Beatmaps/DifficultyCalculator.cs | 2 +- .../Rulesets/Scoring/PerformanceCalculator.cs | 15 ++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index a12bdf7f20..aa94572cb4 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -18,7 +18,17 @@ namespace osu.Game.Rulesets.Osu.Scoring private readonly int beatmapMaxCombo; private Mod[] mods; + + /// + /// Approach rate adjusted by mods. + /// private double realApproachRate; + + /// + /// Overall difficulty adjusted by mods. + /// + private double realOverallDifficulty; + private double accuracy; private int scoreMaxCombo; private int count300; @@ -58,9 +68,13 @@ namespace osu.Game.Rulesets.Osu.Scoring ar = Math.Min(10, ar * 1.4); if (mods.Any(m => m is OsuModEasy)) ar = Math.Max(0, ar / 2); - double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450); - realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; + double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate; + double hitWindow300 = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + + realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; + realOverallDifficulty = (80 - 0.5 - hitWindow300) / 6; + // Custom multipliers for NoFail and SpunOut. double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things @@ -133,7 +147,7 @@ namespace osu.Game.Rulesets.Osu.Scoring // Scale the aim value with accuracy _slightly_ aimValue *= 0.5f + accuracy / 2.0f; // It is important to also consider accuracy difficulty when doing that - aimValue *= 0.98f + Math.Pow(Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 2) / 2500; + aimValue *= 0.98f + Math.Pow(realOverallDifficulty, 2) / 2500; return aimValue; } @@ -159,7 +173,7 @@ namespace osu.Game.Rulesets.Osu.Scoring // Scale the speed value with accuracy _slightly_ speedValue *= 0.5f + accuracy / 2.0f; // It is important to also consider accuracy difficulty when doing that - speedValue *= 0.98f + Math.Pow(Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 2) / 2500; + speedValue *= 0.98f + Math.Pow(realOverallDifficulty, 2) / 2500; return speedValue; } @@ -181,7 +195,7 @@ namespace osu.Game.Rulesets.Osu.Scoring // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Pow(1.52163f, Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f; + double accuracyValue = Math.Pow(1.52163f, realOverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer accuracyValue *= Math.Min(1.15f, Math.Pow(amountHitObjectsWithAccuracy / 1000.0f, 0.3f)); diff --git a/osu.Game/Beatmaps/DifficultyCalculator.cs b/osu.Game/Beatmaps/DifficultyCalculator.cs index 37155c09cd..5cac9ed923 100644 --- a/osu.Game/Beatmaps/DifficultyCalculator.cs +++ b/osu.Game/Beatmaps/DifficultyCalculator.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps protected readonly IBeatmap Beatmap; protected readonly Mod[] Mods; - protected double TimeRate = 1; + protected double TimeRate { get; private set; } = 1; protected DifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) { diff --git a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs index 5b8f5f0d0f..b23e06e15c 100644 --- a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs @@ -2,7 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Scoring { @@ -14,6 +18,8 @@ namespace osu.Game.Rulesets.Scoring protected readonly IBeatmap Beatmap; protected readonly Score Score; + protected double TimeRate { get; private set; } = 1; + protected PerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) { Score = score; @@ -22,6 +28,15 @@ namespace osu.Game.Rulesets.Scoring var diffCalc = ruleset.CreateDifficultyCalculator(beatmap, score.Mods); diffCalc.Calculate(attributes); + + ApplyMods(score.Mods); + } + + protected virtual void ApplyMods(Mod[] mods) + { + var clock = new StopwatchClock(); + mods.OfType().ForEach(m => m.ApplyToClock(clock)); + TimeRate = clock.Rate; } public abstract double Calculate(Dictionary categoryDifficulty = null); From ce6b4cc2d30d60480793d1c94838f0f0e6500680 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 11:15:37 +0900 Subject: [PATCH 129/302] Add more attributes to OsuPerformanceCalculator's output --- osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index aa94572cb4..e927cc946e 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -99,6 +99,9 @@ namespace osu.Game.Rulesets.Osu.Scoring categoryRatings.Add("Aim", aimValue); categoryRatings.Add("Speed", speedValue); categoryRatings.Add("Accuracy", accuracyValue); + categoryRatings.Add("OD", realOverallDifficulty); + categoryRatings.Add("AR", realApproachRate); + categoryRatings.Add("Max Combo", beatmapMaxCombo); } return totalValue; From 8c86f170a928404e63800d552179fff236bb10e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 11:33:23 +0900 Subject: [PATCH 130/302] Fix mania testcases --- .../TestCaseManiaHitObjects.cs | 22 +++++---- .../TestCaseManiaPlayfield.cs | 47 +++++++++---------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs index dd81d015f1..a4109722d4 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs @@ -4,9 +4,10 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Objects; using osu.Game.Tests.Visual; using OpenTK; using OpenTK.Graphics; @@ -18,8 +19,13 @@ namespace osu.Game.Rulesets.Mania.Tests { public TestCaseManiaHitObjects() { - var hitWindows = new HitWindows(); - hitWindows.SetDifficulty(5); + Note note1 = new Note(); + Note note2 = new Note(); + HoldNote holdNote = new HoldNote { StartTime = 1000 }; + + note1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + note2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); Add(new FillFlowContainer { @@ -47,14 +53,14 @@ namespace osu.Game.Rulesets.Mania.Tests RelativeChildSize = new Vector2(1, 10000), Children = new[] { - new DrawableNote(new Note { HitWindows = hitWindows }, ManiaAction.Key1) + new DrawableNote(note1, ManiaAction.Key1) { Y = 5000, LifetimeStart = double.MinValue, LifetimeEnd = double.MaxValue, AccentColour = Color4.Red }, - new DrawableNote(new Note { HitWindows = hitWindows }, ManiaAction.Key1) + new DrawableNote(note2, ManiaAction.Key1) { Y = 6000, LifetimeStart = double.MinValue, @@ -81,11 +87,7 @@ namespace osu.Game.Rulesets.Mania.Tests RelativeChildSize = new Vector2(1, 10000), Children = new[] { - new DrawableHoldNote(new HoldNote - { - Duration = 1000, - HitWindows = hitWindows - } , ManiaAction.Key1) + new DrawableHoldNote(holdNote, ManiaAction.Key1) { Y = 5000, Height = 1000, diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs index 053f478027..dff2b2d56a 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs @@ -8,6 +8,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Configuration; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; @@ -83,13 +85,16 @@ namespace osu.Game.Rulesets.Mania.Tests int col = rng.Next(0, 4); - var note = new DrawableNote(new Note { Column = col }, ManiaAction.Key1) + var note = new Note { Column = col }; + note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + var drawableNote = new DrawableNote(note, ManiaAction.Key1) { AccentColour = playfield.Columns.ElementAt(col).AccentColour }; - playfield.OnJudgement(note, new ManiaJudgement { Result = HitResult.Perfect }); - playfield.Columns[col].OnJudgement(note, new ManiaJudgement { Result = HitResult.Perfect }); + playfield.OnJudgement(drawableNote, new ManiaJudgement { Result = HitResult.Perfect }); + playfield.Columns[col].OnJudgement(drawableNote, new ManiaJudgement { Result = HitResult.Perfect }); }); } @@ -162,32 +167,24 @@ namespace osu.Game.Rulesets.Mania.Tests for (double t = start_time; t <= start_time + duration; t += 100) { - playfield.Add(new DrawableNote(new Note - { - StartTime = t, - Column = 0 - }, ManiaAction.Key1)); + var note1 = new Note { StartTime = t, Column = 0 }; + var note2 = new Note { StartTime = t, Column = 3 }; - playfield.Add(new DrawableNote(new Note - { - StartTime = t, - Column = 3 - }, ManiaAction.Key4)); + note1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + note2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + playfield.Add(new DrawableNote(note1, ManiaAction.Key1)); + playfield.Add(new DrawableNote(note2, ManiaAction.Key4)); } - playfield.Add(new DrawableHoldNote(new HoldNote - { - StartTime = start_time, - Duration = duration, - Column = 1 - }, ManiaAction.Key2)); + var holdNote1 = new HoldNote { StartTime = start_time, Duration = duration, Column = 1 }; + var holdNote2 = new HoldNote { StartTime = start_time, Duration = duration, Column = 2 }; - playfield.Add(new DrawableHoldNote(new HoldNote - { - StartTime = start_time, - Duration = duration, - Column = 2 - }, ManiaAction.Key3)); + holdNote1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + holdNote2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + playfield.Add(new DrawableHoldNote(holdNote1, ManiaAction.Key2)); + playfield.Add(new DrawableHoldNote(holdNote2, ManiaAction.Key3)); } } } From 327c7432be72ab79e882a6dc9d8e0c51d310d485 Mon Sep 17 00:00:00 2001 From: ocboogie Date: Sun, 13 May 2018 19:33:52 -0700 Subject: [PATCH 131/302] Use OnKeyDown instead of a IKeyBindingHandler --- .../Overlays/Toolbar/ToolbarModeSelector.cs | 66 ++++++------------- 1 file changed, 21 insertions(+), 45 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 889cf8885e..7286cf3f1c 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -4,12 +4,14 @@ using System; using System.Linq; using System.Collections.Generic; +using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Bindings; +using osu.Framework.Input; using OpenTK; +using OpenTK.Input; using OpenTK.Graphics; using osu.Framework.Configuration; using osu.Framework.Graphics.Shapes; @@ -17,7 +19,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.Toolbar { - public class ToolbarModeSelector : KeyBindingContainer + public class ToolbarModeSelector : Container { private const float padding = 10; @@ -25,7 +27,7 @@ namespace osu.Game.Overlays.Toolbar private readonly Drawable modeButtonLine; private ToolbarModeButton activeButton; - private int rulesetCount; + private RulesetStore rulesets; private readonly Bindable ruleset = new Bindable(); public ToolbarModeSelector() @@ -68,50 +70,10 @@ namespace osu.Game.Overlays.Toolbar }; } - public override IEnumerable DefaultKeyBindings - { - get - { - var keybinds = new List(); - for (int i = 0; i < Math.Min(rulesetCount, 10); i++) - { - InputKey numberKey; - if (i == 9) - numberKey = InputKey.Number0; - else - numberKey = (InputKey)i + 110; - - keybinds.Add(new osu.Framework.Input.Bindings.KeyBinding(new[] { InputKey.Control, numberKey }, i)); - } - return keybinds; - } - } - - private class RulesetSwitcherInputHandler : Container, IKeyBindingHandler - { - private readonly Bindable ruleset; - private readonly RulesetStore rulesets; - - public RulesetSwitcherInputHandler(Bindable ruleset, RulesetStore rulesets) - { - this.ruleset = ruleset; - this.rulesets = rulesets; - } - - public bool OnPressed(int action) - { - ruleset.Value = rulesets.GetRuleset(action); - - return true; - } - - public bool OnReleased(int action) => false; - } - [BackgroundDependencyLoader(true)] private void load(RulesetStore rulesets, OsuGame game) { - rulesetCount = rulesets.AvailableRulesets.Count(); + this.rulesets = rulesets; foreach (var r in rulesets.AvailableRulesets) { modeButtons.Add(new ToolbarModeButton @@ -130,8 +92,22 @@ namespace osu.Game.Overlays.Toolbar ruleset.BindTo(game.Ruleset); else ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(); + } - Add(new RulesetSwitcherInputHandler(ruleset, rulesets)); + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + base.OnKeyDown(state, args); + if (!state.Keyboard.ControlPressed || args.Repeat || (int)args.Key < 109 || (int)args.Key > 118) { + return false; + } + + RulesetInfo targetRuleset = rulesets.GetRuleset(args.Key == Key.Number0 ? 9 : (int)args.Key - 110); + if (targetRuleset == null || targetRuleset == ruleset.Value) { + return false; + } + + ruleset.Value = targetRuleset; + return true; } public override bool HandleKeyboardInput => !ruleset.Disabled && base.HandleKeyboardInput; From ebd9d1a0376becee8ee0f71e93cca67daf9799e7 Mon Sep 17 00:00:00 2001 From: ocboogie Date: Sun, 13 May 2018 19:43:26 -0700 Subject: [PATCH 132/302] Resolve linting issues in ToolbarModeSelector.cs --- osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 7286cf3f1c..eeaa15d58a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -1,10 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; -using System.Collections.Generic; -using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; From a81921118dac58379808e0c55a0b281c02ffdf5b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 11:52:22 +0900 Subject: [PATCH 133/302] Strip whitespaces --- .../Scoring/OsuPerformanceCalculator.cs | 12 ++++++------ osu.Game/Rulesets/Scoring/PerformanceCalculator.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index e927cc946e..4942a55004 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -18,17 +18,17 @@ namespace osu.Game.Rulesets.Osu.Scoring private readonly int beatmapMaxCombo; private Mod[] mods; - + /// /// Approach rate adjusted by mods. /// private double realApproachRate; - + /// /// Overall difficulty adjusted by mods. /// private double realOverallDifficulty; - + private double accuracy; private int scoreMaxCombo; private int count300; @@ -70,11 +70,11 @@ namespace osu.Game.Rulesets.Osu.Scoring ar = Math.Max(0, ar / 2); double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate; - double hitWindow300 = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; - + double hitWindow300 = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; realOverallDifficulty = (80 - 0.5 - hitWindow300) / 6; - + // Custom multipliers for NoFail and SpunOut. double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things diff --git a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs index b23e06e15c..f2c495fa5d 100644 --- a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Scoring ApplyMods(score.Mods); } - + protected virtual void ApplyMods(Mod[] mods) { var clock = new StopwatchClock(); From 7d027098ec1c0fc5920ba85b8f85797127cf99b0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 14:13:07 +0900 Subject: [PATCH 134/302] Fix drumroll completions always giving GREAT judgements Due to requiredgoodhits/requiredgreathits being calculated prior to nested hitobjects. --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 64219c7b52..4c9ec5473b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -40,6 +40,8 @@ namespace osu.Game.Rulesets.Taiko.Objects /// private double tickSpacing = 100; + private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY; + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -47,9 +49,7 @@ namespace osu.Game.Rulesets.Taiko.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); tickSpacing = timingPoint.BeatLength / TickRate; - - RequiredGoodHits = NestedHitObjects.Count * Math.Min(0.15, 0.05 + 0.10 / 6 * difficulty.OverallDifficulty); - RequiredGreatHits = NestedHitObjects.Count * Math.Min(0.30, 0.10 + 0.20 / 6 * difficulty.OverallDifficulty); + overallDifficulty = difficulty.OverallDifficulty; } protected override void CreateNestedHitObjects() @@ -57,6 +57,9 @@ namespace osu.Game.Rulesets.Taiko.Objects base.CreateNestedHitObjects(); createTicks(); + + RequiredGoodHits = NestedHitObjects.Count * Math.Min(0.15, 0.05 + 0.10 / 6 * overallDifficulty); + RequiredGreatHits = NestedHitObjects.Count * Math.Min(0.30, 0.10 + 0.20 / 6 * overallDifficulty); } private void createTicks() From f5068804d5c2dcf87493cd75bbfd7c929654993a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 15:14:29 +0900 Subject: [PATCH 135/302] Re-enable slider distance overflow Fixes #2467. --- osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs | 24 +++++++++++++++++++ osu.Game/Rulesets/Objects/SliderCurve.cs | 10 ++++---- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs index f7f73f74a5..cb1ea5cc5f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs @@ -93,12 +93,36 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("Big Single, Large StackOffset", () => testSimpleBigLargeStackOffset()); AddStep("Big 1 Repeat, Large StackOffset", () => testSimpleBigLargeStackOffset(1)); + + AddStep("Distance Overflow", () => testDistanceOverflow()); + AddStep("Distance Overflow 1 Repeat", () => testDistanceOverflow(1)); } private void testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); private void testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10); + private void testDistanceOverflow(int repeats = 0) + { + var slider = new Slider + { + StartTime = Time.Current + 1000, + Position = new Vector2(239, 176), + ControlPoints = new List + { + Vector2.Zero, + new Vector2(154, 28), + new Vector2(52, -34) + }, + Distance = 700, + RepeatCount = repeats, + RepeatSamples = createEmptySamples(repeats), + StackHeight = 10 + }; + + addSlider(slider, 2, 2); + } + private void testSimpleMedium(int repeats = 0) => createSlider(5, repeats: repeats); private void testSimpleSmall(int repeats = 0) => createSlider(7, repeats: repeats); diff --git a/osu.Game/Rulesets/Objects/SliderCurve.cs b/osu.Game/Rulesets/Objects/SliderCurve.cs index 86fe74f9af..3932d8ed9d 100644 --- a/osu.Game/Rulesets/Objects/SliderCurve.cs +++ b/osu.Game/Rulesets/Objects/SliderCurve.cs @@ -99,11 +99,9 @@ namespace osu.Game.Rulesets.Objects cumulativeLength.Add(l); } - //TODO: Figure out if the following code is needed in some cases. Judging by the map - // "Transform" http://osu.ppy.sh/s/484689 it seems like we should _not_ be doing this. // Lengthen slider curves that are too short compared to what's // in the .osu file. - /*if (l < Length && calculatedPath.Count > 1) + if (l < Distance && calculatedPath.Count > 1) { Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2]; double d = diff.Length; @@ -111,9 +109,9 @@ namespace osu.Game.Rulesets.Objects if (d <= 0) return; - calculatedPath[calculatedPath.Count - 1] += diff * (float)((Length - l) / d); - cumulativeLength[calculatedPath.Count - 1] = Length; - }*/ + calculatedPath[calculatedPath.Count - 1] += diff * (float)((Distance - l) / d); + cumulativeLength[calculatedPath.Count - 1] = Distance; + } } public void Calculate() From 43409127b73d3721f7edb5d5b915489ff14dbb8b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 15:36:42 +0900 Subject: [PATCH 136/302] Place break overlay underneath the hud --- osu.Game/Screens/Play/Player.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f397d0c3d4..af5021a7eb 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -174,6 +174,13 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Child = RulesetContainer }, + new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, scoreProcessor) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + ProcessCustomClock = false, + Breaks = beatmap.Breaks + }, new SkipOverlay(firstObjectTime) { Clock = Clock, // skip button doesn't want to use the audio clock directly @@ -187,13 +194,6 @@ namespace osu.Game.Screens.Play ProcessCustomClock = false, Anchor = Anchor.Centre, Origin = Anchor.Centre - }, - new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, scoreProcessor) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - ProcessCustomClock = false, - Breaks = beatmap.Breaks } } }, From 64fba5f6d1ed525a1ea4a0f1f844e1e8352f9159 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 15:36:56 +0900 Subject: [PATCH 137/302] Proxy the ruleset cursor above the break overlay --- osu.Game/Screens/Play/Player.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index af5021a7eb..f748d5236d 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -149,6 +149,8 @@ namespace osu.Game.Screens.Play scoreProcessor = RulesetContainer.CreateScoreProcessor(); + Drawable rulesetCursor = RulesetContainer.Cursor?.CreateProxy() ?? new Container(); + Children = new Drawable[] { pauseContainer = new PauseContainer(offsetClock, adjustableClock) @@ -162,7 +164,7 @@ namespace osu.Game.Screens.Play hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused; }, OnResume = () => hudOverlay.KeyCounter.IsCounting = true, - Children = new Drawable[] + Children = new[] { storyboardContainer = new Container { @@ -181,6 +183,7 @@ namespace osu.Game.Screens.Play ProcessCustomClock = false, Breaks = beatmap.Breaks }, + rulesetCursor, new SkipOverlay(firstObjectTime) { Clock = Clock, // skip button doesn't want to use the audio clock directly From fe1c1fec0d37ecacbeb5ff328237307b95843706 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 May 2018 15:42:27 +0900 Subject: [PATCH 138/302] Stop overlays from handling DragStart This was causing weird behaviour with the key configuration section and back button in settings. --- .../Containers/OsuFocusedOverlayContainer.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 2a30e0d032..f657c0cae5 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -44,19 +44,6 @@ namespace osu.Game.Graphics.Containers return base.OnClick(state); } - protected override bool OnDragStart(InputState state) - { - if (!base.ReceiveMouseInputAt(state.Mouse.NativeState.Position)) - { - State = Visibility.Hidden; - return true; - } - - return base.OnDragStart(state); - } - - protected override bool OnDrag(InputState state) => State == Visibility.Hidden; - private void onStateChanged(Visibility visibility) { switch (visibility) From 6eb7590ab0151b86a047e157b4369bdf59978691 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 17:41:35 +0900 Subject: [PATCH 139/302] Make MusicController handle all movement to previous/next tracks --- osu.Game/Overlays/Music/PlaylistList.cs | 95 +++++++++------------- osu.Game/Overlays/Music/PlaylistOverlay.cs | 77 +++--------------- osu.Game/Overlays/MusicController.cs | 49 +++++++++-- 3 files changed, 90 insertions(+), 131 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index d63babf3b6..8c8ff89420 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -4,7 +4,8 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -16,7 +17,8 @@ namespace osu.Game.Overlays.Music { public class PlaylistList : CompositeDrawable { - public Action OnSelect; + public Action Selected; + public Action OrderChanged; private readonly ItemsScrollContainer items; @@ -25,7 +27,8 @@ namespace osu.Game.Overlays.Music InternalChild = items = new ItemsScrollContainer { RelativeSizeAxes = Axes.Both, - OnSelect = set => OnSelect?.Invoke(set) + Selected = set => Selected?.Invoke(set), + OrderChanged = (s, i) => OrderChanged?.Invoke(s, i) }; } @@ -35,34 +38,20 @@ namespace osu.Game.Overlays.Music set { base.Padding = value; } } - public IEnumerable BeatmapSets - { - get { return items.Sets; } - set { items.Sets = value; } - } - public BeatmapSetInfo FirstVisibleSet => items.FirstVisibleSet; - public BeatmapSetInfo NextSet => items.NextSet; - public BeatmapSetInfo PreviousSet => items.PreviousSet; - - public BeatmapSetInfo SelectedSet - { - get { return items.SelectedSet; } - set { items.SelectedSet = value; } - } - - public void AddBeatmapSet(BeatmapSetInfo beatmapSet) => items.AddBeatmapSet(beatmapSet); - public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => items.RemoveBeatmapSet(beatmapSet); public void Filter(string searchTerm) => items.SearchTerm = searchTerm; private class ItemsScrollContainer : OsuScrollContainer { - public Action OnSelect; + public Action Selected; + public Action OrderChanged; private readonly SearchContainer search; private readonly FillFlowContainer items; + private readonly IBindable beatmapBacking = new Bindable(); + public ItemsScrollContainer() { Children = new Drawable[] @@ -83,14 +72,36 @@ namespace osu.Game.Overlays.Music }; } - public IEnumerable Sets + [BackgroundDependencyLoader] + private void load(BeatmapManager beatmaps, OsuGameBase osuGame) { - get { return items.Select(x => x.BeatmapSetInfo).ToList(); } - set - { - items.Clear(); - value.ForEach(AddBeatmapSet); - } + beatmaps.GetAllUsableBeatmapSets().ForEach(addBeatmapSet); + beatmaps.ItemAdded += addBeatmapSet; + beatmaps.ItemRemoved += removeBeatmapSet; + + beatmapBacking.BindTo(osuGame.Beatmap); + beatmapBacking.ValueChanged += _ => updateSelectedSet(); + } + + private void addBeatmapSet(BeatmapSetInfo obj) + { + var newItem = new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }; + + items.Add(newItem); + items.SetLayoutPosition(newItem, items.Count - 1); + } + + private void removeBeatmapSet(BeatmapSetInfo obj) + { + var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == obj.ID); + if (itemToRemove != null) + items.Remove(itemToRemove); + } + + private void updateSelectedSet() + { + foreach (PlaylistItem s in items.Children) + s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo.ID; } public string SearchTerm @@ -99,34 +110,7 @@ namespace osu.Game.Overlays.Music set { search.SearchTerm = value; } } - public void AddBeatmapSet(BeatmapSetInfo beatmapSet) - { - var newItem = new PlaylistItem(beatmapSet) { OnSelect = set => OnSelect?.Invoke(set) }; - - items.Add(newItem); - items.SetLayoutPosition(newItem, items.Count); - } - - public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) - { - var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == beatmapSet.ID); - if (itemToRemove != null) - items.Remove(itemToRemove); - } - - public BeatmapSetInfo SelectedSet - { - get { return items.FirstOrDefault(i => i.Selected)?.BeatmapSetInfo; } - set - { - foreach (PlaylistItem s in items.Children) - s.Selected = s.BeatmapSetInfo.ID == value?.ID; - } - } - public BeatmapSetInfo FirstVisibleSet => items.FirstOrDefault(i => i.MatchingFilter)?.BeatmapSetInfo; - public BeatmapSetInfo NextSet => (items.SkipWhile(i => !i.Selected).Skip(1).FirstOrDefault() ?? items.FirstOrDefault())?.BeatmapSetInfo; - public BeatmapSetInfo PreviousSet => (items.TakeWhile(i => !i.Selected).LastOrDefault() ?? items.LastOrDefault())?.BeatmapSetInfo; private Vector2 nativeDragPosition; private PlaylistItem draggedItem; @@ -227,6 +211,7 @@ namespace osu.Game.Overlays.Music } items.SetLayoutPosition(draggedItem, dstIndex); + OrderChanged?.Invoke(draggedItem.BeatmapSetInfo, dstIndex); } private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 3496c044fb..76c2222f8b 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -1,7 +1,7 @@ // 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; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -19,18 +19,16 @@ namespace osu.Game.Overlays.Music public class PlaylistOverlay : OverlayContainer { private const float transition_duration = 600; - private const float playlist_height = 510; + public Action OrderChanged; + + private BeatmapManager beatmaps; private FilterControl filter; private PlaylistList list; - private BeatmapManager beatmaps; - private readonly Bindable beatmapBacking = new Bindable(); - public IEnumerable BeatmapSets => list.BeatmapSets; - [BackgroundDependencyLoader] private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours) { @@ -60,7 +58,8 @@ namespace osu.Game.Overlays.Music { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = 95, Bottom = 10, Right = 10 }, - OnSelect = itemSelected, + Selected = itemSelected, + OrderChanged = (s, i) => OrderChanged?.Invoke(s, i) }, filter = new FilterControl { @@ -74,30 +73,16 @@ namespace osu.Game.Overlays.Music }, }; - beatmaps.ItemAdded += handleBeatmapAdded; - beatmaps.ItemRemoved += handleBeatmapRemoved; - - list.BeatmapSets = beatmaps.GetAllUsableBeatmapSets(); - beatmapBacking.BindTo(game.Beatmap); filter.Search.OnCommit = (sender, newText) => { - var beatmap = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); - if (beatmap != null) playSpecified(beatmap); + BeatmapInfo beatmap = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); + if (beatmap != null) + beatmapBacking.Value = beatmaps.GetWorkingBeatmap(beatmap); }; } - protected override void LoadComplete() - { - base.LoadComplete(); - beatmapBacking.ValueChanged += b => list.SelectedSet = b?.BeatmapSetInfo; - beatmapBacking.TriggerChange(); - } - - private void handleBeatmapAdded(BeatmapSetInfo setInfo) => Schedule(() => list.AddBeatmapSet(setInfo)); - private void handleBeatmapRemoved(BeatmapSetInfo setInfo) => Schedule(() => list.RemoveBeatmapSet(setInfo)); - protected override void PopIn() { filter.Search.HoldFocus = true; @@ -123,49 +108,7 @@ namespace osu.Game.Overlays.Music return; } - playSpecified(set.Beatmaps.First()); - } - - public void PlayPrevious() - { - var playable = list.PreviousSet; - - if (playable != null) - { - playSpecified(playable.Beatmaps.First()); - list.SelectedSet = playable; - } - } - - public void PlayNext() - { - var playable = list.NextSet; - - if (playable != null) - { - playSpecified(playable.Beatmaps.First()); - list.SelectedSet = playable; - } - } - - private void playSpecified(BeatmapInfo info) - { - beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - - var track = beatmapBacking.Value.Track; - - track.Restart(); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (beatmaps != null) - { - beatmaps.ItemAdded -= handleBeatmapAdded; - beatmaps.ItemRemoved -= handleBeatmapRemoved; - } + beatmapBacking.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First()); } } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index b4021f2808..c348a8f7d5 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; @@ -50,7 +51,10 @@ namespace osu.Game.Overlays private LocalisationEngine localisation; + private BeatmapManager beatmaps; private readonly Bindable beatmapBacking = new Bindable(); + private List beatmapSets; + private BeatmapSetInfo currentSet; private Container dragContainer; private Container playerContainer; @@ -93,8 +97,9 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuGameBase game, OsuColour colours, LocalisationEngine localisation) + private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours, LocalisationEngine localisation) { + this.beatmaps = beatmaps; this.localisation = localisation; Children = new Drawable[] @@ -111,6 +116,7 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.X, Y = player_height + 10, + OrderChanged = playlistOrderChanged }, playerContainer = new Container { @@ -185,7 +191,7 @@ namespace osu.Game.Overlays { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = next, + Action = () => next(), Icon = FontAwesome.fa_step_forward, }, } @@ -214,11 +220,24 @@ namespace osu.Game.Overlays } }; + beatmapSets = beatmaps.GetAllUsableBeatmapSets(); + beatmaps.ItemAdded += handleBeatmapAdded; + beatmaps.ItemRemoved += handleBeatmapRemoved; + beatmapBacking.BindTo(game.Beatmap); playlist.StateChanged += s => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); } + private void playlistOrderChanged(BeatmapSetInfo beatmapSetInfo, int index) + { + beatmapSets.Remove(beatmapSetInfo); + beatmapSets.Insert(index, beatmapSetInfo); + } + + private void handleBeatmapAdded(BeatmapSetInfo obj) => beatmapSets.Add(obj); + private void handleBeatmapRemoved(BeatmapSetInfo obj) => beatmapSets.RemoveAll(s => s.ID == obj.ID); + protected override void LoadComplete() { beatmapBacking.ValueChanged += beatmapChanged; @@ -257,7 +276,7 @@ namespace osu.Game.Overlays playButton.Icon = track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o; - if (track.HasCompleted && !track.Looping && !beatmapBacking.Disabled && playlist.BeatmapSets.Any()) + if (track.HasCompleted && !track.Looping && !beatmapBacking.Disabled && beatmapSets.Any()) next(); } else @@ -271,7 +290,7 @@ namespace osu.Game.Overlays if (track == null) { if (!beatmapBacking.Disabled) - playlist.PlayNext(); + next(true); return; } @@ -284,13 +303,25 @@ namespace osu.Game.Overlays private void prev() { queuedDirection = TransformDirection.Prev; - playlist.PlayPrevious(); + + var playable = beatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? beatmapSets.LastOrDefault(); + if (playable != null) + playSpecified(playable.Beatmaps.First()); } - private void next() + private void next(bool instant = false) { queuedDirection = TransformDirection.Next; - playlist.PlayNext(); + + var playable = beatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? beatmapSets.FirstOrDefault(); + if (playable != null) + playSpecified(playable.Beatmaps.First()); + } + + private void playSpecified(BeatmapInfo info) + { + beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); + beatmapBacking.Value.Track.Restart(); } private WorkingBeatmap current; @@ -314,8 +345,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 = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); + var next = beatmap == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.BeatmapSetInfo?.ID).Count(); direction = last > next ? TransformDirection.Prev : TransformDirection.Next; } From 4ceae6ba1f806f4cae2983c32e58c867d74ddad4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 17:45:11 +0900 Subject: [PATCH 140/302] Inline method --- osu.Game/Overlays/MusicController.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index c348a8f7d5..d7884bf53a 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -306,7 +306,10 @@ namespace osu.Game.Overlays var playable = beatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? beatmapSets.LastOrDefault(); if (playable != null) - playSpecified(playable.Beatmaps.First()); + { + beatmapBacking.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmapBacking); + beatmapBacking.Value.Track.Restart(); + } } private void next(bool instant = false) @@ -315,13 +318,10 @@ namespace osu.Game.Overlays var playable = beatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? beatmapSets.FirstOrDefault(); if (playable != null) - playSpecified(playable.Beatmaps.First()); - } - - private void playSpecified(BeatmapInfo info) - { - beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - beatmapBacking.Value.Track.Restart(); + { + beatmapBacking.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmapBacking); + beatmapBacking.Value.Track.Restart(); + } } private WorkingBeatmap current; From 027f6c3fa4a55e2dafb6b15588d282de465e14eb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 17:47:38 +0900 Subject: [PATCH 141/302] Fix instant movement not doing anything --- osu.Game/Overlays/MusicController.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index d7884bf53a..fb4e278b0c 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -314,7 +314,8 @@ namespace osu.Game.Overlays private void next(bool instant = false) { - queuedDirection = TransformDirection.Next; + if (!instant) + queuedDirection = TransformDirection.Next; var playable = beatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? beatmapSets.FirstOrDefault(); if (playable != null) From 115c2dc239e734d3c6f1c2161c5a80dddc84a22f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 18:02:18 +0900 Subject: [PATCH 142/302] Move hud below the skip button --- osu.Game/Screens/Play/Player.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f748d5236d..2d7e0e8f9e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -183,6 +183,13 @@ namespace osu.Game.Screens.Play ProcessCustomClock = false, Breaks = beatmap.Breaks }, + hudOverlay = new HUDOverlay(scoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) + { + Clock = Clock, // hud overlay doesn't want to use the audio clock directly + ProcessCustomClock = false, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }, rulesetCursor, new SkipOverlay(firstObjectTime) { @@ -191,13 +198,6 @@ namespace osu.Game.Screens.Play AdjustableClock = adjustableClock, FramedClock = offsetClock, }, - hudOverlay = new HUDOverlay(scoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) - { - Clock = Clock, // hud overlay doesn't want to use the audio clock directly - ProcessCustomClock = false, - Anchor = Anchor.Centre, - Origin = Anchor.Centre - } } }, failOverlay = new FailOverlay From 9536c324fa3853bfeff8c29b54d3258ad1998509 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 19:08:00 +0900 Subject: [PATCH 143/302] Rename aborted -> fired --- osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs index ef6f44b42e..6fa49c4edb 100644 --- a/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs @@ -17,11 +17,11 @@ namespace osu.Game.Tests.Visual { bool fired = false; - var abortText = new OsuSpriteText + var firedText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = "Aborted!", + Text = "Fired!", TextSize = 50, Alpha = 0, }; @@ -31,14 +31,14 @@ namespace osu.Game.Tests.Visual Action = () => { fired = true; - abortText.FadeTo(1).Then().FadeOut(1000); + firedText.FadeTo(1).Then().FadeOut(1000); } }; Children = new Drawable[] { overlay, - abortText + firedText }; AddStep("start confirming", () => overlay.Begin()); From 0234bbc37f08354910ed746624e546746b0c3165 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 May 2018 19:14:17 +0900 Subject: [PATCH 144/302] Move definition inline --- osu.Game/Screens/Play/Player.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2d7e0e8f9e..4a46279d30 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -149,8 +149,6 @@ namespace osu.Game.Screens.Play scoreProcessor = RulesetContainer.CreateScoreProcessor(); - Drawable rulesetCursor = RulesetContainer.Cursor?.CreateProxy() ?? new Container(); - Children = new Drawable[] { pauseContainer = new PauseContainer(offsetClock, adjustableClock) @@ -190,7 +188,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre }, - rulesetCursor, + RulesetContainer.Cursor?.CreateProxy() ?? new Container(), new SkipOverlay(firstObjectTime) { Clock = Clock, // skip button doesn't want to use the audio clock directly From 17861c2a162f1d562aa79fb4bc3e267e96dbe530 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 19:20:53 +0900 Subject: [PATCH 145/302] Display "no key bound" when no shortcut --- osu.Game/Overlays/OnScreenDisplay.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 8f6bf0f539..1c80f2e626 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -101,20 +101,15 @@ namespace osu.Game.Overlays Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both }, - new Container + textLine3 = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Bottom = 15 }, + Font = @"Exo2.0-Bold", + TextSize = 12, Alpha = 0.3f, - Child = textLine3 = new OsuSpriteText - { - Font = @"Exo2.0-Bold", - TextSize = 12, - AlwaysPresent = true - }, - } + }, } } } @@ -183,6 +178,9 @@ namespace osu.Game.Overlays textLine2.Text = description.Value; textLine3.Text = description.Shortcut.ToUpper(); + if (string.IsNullOrEmpty(textLine3.Text)) + textLine3.Text = "NO KEY BOUND"; + Display(box); int optionCount = 0; From 47cf4f27fbd800371a531cd396b059c0e27c30fa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 May 2018 19:39:23 +0900 Subject: [PATCH 146/302] Fix possibility of test rulesets being discovered from assemblies --- osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs | 6 +++--- osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs | 6 +++--- osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs | 6 +++--- osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs | 6 +++--- osu.Game/Rulesets/RulesetStore.cs | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index d0d623178e..808faa511b 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Catch.Tests { - public class CatchBeatmapConversionTest : BeatmapConversionTest + internal class CatchBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Catch"; @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Tests protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); } - public struct ConvertValue : IEquatable + internal struct ConvertValue : IEquatable { /// /// A sane value to account for osu!stable using ints everwhere. @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Tests && Precision.AlmostEquals(Position, other.Position, conversion_lenience); } - public class TestCatchRuleset : CatchRuleset + internal class TestCatchRuleset : CatchRuleset { } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index f1ee874b88..bd67a7d96a 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Mania.Tests { - public class ManiaBeatmapConversionTest : BeatmapConversionTest + internal class ManiaBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Tests protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); } - public struct ConvertValue : IEquatable + internal struct ConvertValue : IEquatable { /// /// A sane value to account for osu!stable using ints everwhere. @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Tests && Column == other.Column; } - public class TestManiaRuleset : ManiaRuleset + internal class TestManiaRuleset : ManiaRuleset { } } diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index aa7de4ed01..3d54043027 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -15,7 +15,7 @@ using OpenTK; namespace osu.Game.Rulesets.Osu.Tests { - public class OsuBeatmapConversionTest : BeatmapConversionTest + internal class OsuBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Tests protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); } - public struct ConvertValue : IEquatable + internal struct ConvertValue : IEquatable { /// /// A sane value to account for osu!stable using ints everwhere. @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Tests && Precision.AlmostEquals(EndY, other.EndY, conversion_lenience); } - public class TestOsuRuleset : OsuRuleset + internal class TestOsuRuleset : OsuRuleset { } } diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 33a5e1772e..ca4fc3ec57 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Taiko.Tests { - public class TaikoBeatmapConversionTest : BeatmapConversionTest + internal class TaikoBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko"; @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Taiko.Tests protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); } - public struct ConvertValue : IEquatable + internal struct ConvertValue : IEquatable { /// /// A sane value to account for osu!stable using ints everwhere. @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.Tests && IsStrong == other.IsStrong; } - public class TestTaikoRuleset : TaikoRuleset + internal class TestTaikoRuleset : TaikoRuleset { } } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 67a9a59d4a..1847b63658 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets try { var assembly = Assembly.LoadFrom(file); - loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsSubclassOf(typeof(Ruleset))); + loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); } catch (Exception) { From addb864d1047202af87541763e24a116a4e3cd04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 May 2018 15:41:31 +0900 Subject: [PATCH 147/302] Allow help text to wrap --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 14 ++++++++------ osu.Game/Overlays/KeyBindingOverlay.cs | 4 ---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 41f23a8cd0..7406a9ec4f 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Input; using OpenTK.Graphics; @@ -43,7 +44,7 @@ namespace osu.Game.Overlays.KeyBinding } private OsuSpriteText text; - private OsuSpriteText pressAKey; + private OsuTextFlowContainer pressAKey; private FillFlowContainer buttons; @@ -95,10 +96,11 @@ namespace osu.Game.Overlays.KeyBinding Anchor = Anchor.TopRight, Origin = Anchor.TopRight }, - pressAKey = new OsuSpriteText + pressAKey = new OsuTextFlowContainer { - Text = "Press a key to change binding, SHIFT+DEL to delete, ESC to cancel.", - Y = height, + Text = "Press a key to change binding, Shift+Delete to delete, Escape to cancel.", + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Margin = new MarginPadding(padding), Alpha = 0, Colour = colours.YellowDark @@ -268,7 +270,7 @@ namespace osu.Game.Overlays.KeyBinding GetContainingInputManager().ChangeFocus(null); pressAKey.FadeOut(300, Easing.OutQuint); - pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; + pressAKey.Padding = new MarginPadding { Top = height, Bottom = -pressAKey.DrawHeight }; } protected override void OnFocus(InputState state) @@ -277,7 +279,7 @@ namespace osu.Game.Overlays.KeyBinding AutoSizeEasing = Easing.OutQuint; pressAKey.FadeIn(300, Easing.OutQuint); - pressAKey.Padding = new MarginPadding(); + pressAKey.Padding = new MarginPadding { Top = height }; updateBindTarget(); base.OnFocus(state); diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index bd9c8c20de..06432cfcea 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -12,8 +12,6 @@ namespace osu.Game.Overlays { public class KeyBindingOverlay : SettingsOverlay { - protected const float WIDTH = 430; - protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); [BackgroundDependencyLoader(permitNulls: true)] @@ -23,8 +21,6 @@ namespace osu.Game.Overlays foreach (var ruleset in rulesets.AvailableRulesets) AddSection(new RulesetBindingsSection(ruleset)); - - ContentContainer.Width = WIDTH; } public KeyBindingOverlay() From e802b722f053b0f375566eaee81859d07bb98178 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 14 May 2018 20:27:05 +0300 Subject: [PATCH 148/302] Revert "Handle mouse back button using OnMouseDown override instead of using GlobalAction" This reverts commit 44bbb8700ecc1bdd652c35766bfbaa54310a5855. --- .../Input/Bindings/GlobalActionContainer.cs | 10 +++- osu.Game/Screens/Loader.cs | 1 - osu.Game/Screens/Menu/ButtonSystem.cs | 52 +++++++++++-------- osu.Game/Screens/Menu/MainMenu.cs | 1 - osu.Game/Screens/OsuScreen.cs | 28 +++------- osu.Game/Screens/Play/PlayerLoader.cs | 1 + .../Play/ScreenWithBeatmapBackground.cs | 2 - 7 files changed, 48 insertions(+), 47 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index dd8f00f6cd..565d530395 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Input.Bindings { new KeyBinding(InputKey.F8, GlobalAction.ToggleChat), new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), - new KeyBinding(InputKey.F12,GlobalAction.TakeScreenshot), + new KeyBinding(InputKey.F12, GlobalAction.TakeScreenshot), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), @@ -36,6 +36,9 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Down, GlobalAction.DecreaseVolume), new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume), new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), + + new KeyBinding(InputKey.Escape, GlobalAction.Back), + new KeyBinding(InputKey.MouseButton1, GlobalAction.Back) }; public IEnumerable InGameKeyBindings => new[] @@ -76,6 +79,9 @@ namespace osu.Game.Input.Bindings QuickRetry, [Description("Take screenshot")] - TakeScreenshot + TakeScreenshot, + + [Description("Go back")] + Back } } diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index dc8dbb4421..1d152361df 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -18,7 +18,6 @@ namespace osu.Game.Screens private bool showDisclaimer; public override bool ShowOverlaysOnEnter => false; - protected override bool AllowBackButton => false; public Loader() { diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 5a1dafe404..8cf0d24f7d 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -13,15 +13,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Threading; using osu.Game.Graphics; +using osu.Game.Input.Bindings; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; namespace osu.Game.Screens.Menu { - public class ButtonSystem : Container, IStateful + public class ButtonSystem : Container, IStateful, IKeyBindingHandler { public event Action StateChanged; @@ -146,36 +148,44 @@ namespace osu.Game.Screens.Menu case Key.Space: logo?.TriggerOnClick(state); return true; - case Key.Escape: - return handleBack(); } return false; } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + public bool OnPressed(GlobalAction action) { - if (state.Mouse.IsPressed(MouseButton.Button1)) - return handleBack(); - - return base.OnMouseDown(state, args); - } - - private bool handleBack() - { - switch (State) + switch (action) { - case MenuState.TopLevel: - State = MenuState.Initial; - return true; - case MenuState.Play: - backButton.TriggerOnClick(); - return true; + case GlobalAction.Back: + switch (State) + { + case MenuState.TopLevel: + State = MenuState.Initial; + return true; + case MenuState.Play: + backButton.TriggerOnClick(); + return true; + default: + return false; + } + default: + return false; } - - return false; } + public bool OnReleased(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + return true; + default: + return false; + } + } + + private void onPlay() { State = MenuState.Play; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index d91ac099fd..f2ea6d85a8 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -25,7 +25,6 @@ namespace osu.Game.Screens.Menu private readonly ButtonSystem buttons; public override bool ShowOverlaysOnEnter => buttons.State != MenuState.Initial; - protected override bool AllowBackButton => false; private readonly BackgroundScreenDefault background; private Screen songSelect; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 9fa30181a1..fb5d3d12e6 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -7,18 +7,18 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; using osu.Game.Rulesets; using osu.Game.Screens.Menu; using OpenTK; -using OpenTK.Input; namespace osu.Game.Screens { - public abstract class OsuScreen : Screen + public abstract class OsuScreen : Screen, IKeyBindingHandler { public BackgroundScreen Background { get; private set; } @@ -92,31 +92,19 @@ namespace osu.Game.Screens sampleExit = audio.Sample.Get(@"UI/screen-back"); } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public bool OnPressed(GlobalAction action) { - if (args.Repeat || !IsCurrentScreen) return false; - - switch (args.Key) - { - case Key.Escape: - Exit(); - return true; - } - - return base.OnKeyDown(state, args); - } - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - if (AllowBackButton && state.Mouse.IsPressed(MouseButton.Button1)) + if (action == GlobalAction.Back && AllowBackButton) { Exit(); return true; } - return base.OnMouseDown(state, args); + return false; } + public bool OnReleased(GlobalAction action) => action == GlobalAction.Back && AllowBackButton; + protected override void OnResuming(Screen last) { sampleExit?.Play(); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 56fbd7b6e7..6eb156914e 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -27,6 +27,7 @@ namespace osu.Game.Screens.Play private bool showOverlays = true; public override bool ShowOverlaysOnEnter => showOverlays; + protected override bool AllowBackButton => false; private Task loadTask; diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 30ae6db346..1ccc5e2fe8 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -17,8 +17,6 @@ namespace osu.Game.Screens.Play public override bool AllowBeatmapRulesetChange => false; - protected override bool AllowBackButton => false; - protected const float BACKGROUND_FADE_DURATION = 800; protected float BackgroundOpacity => 1 - (float)DimLevel; From f2f2fb8c73670a02dc6cb877fec342423ff27b9b Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 14 May 2018 22:09:09 +0300 Subject: [PATCH 149/302] Use both OnKeyDown and GlobalAction.Back --- osu.Game/Screens/Loader.cs | 2 ++ osu.Game/Screens/Menu/MainMenu.cs | 2 ++ osu.Game/Screens/OsuScreen.cs | 16 ++++++++++++++++ .../Screens/Play/ScreenWithBeatmapBackground.cs | 1 + 4 files changed, 21 insertions(+) diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 1d152361df..555c497d92 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -19,6 +19,8 @@ namespace osu.Game.Screens public override bool ShowOverlaysOnEnter => false; + protected override bool AllowBackButton => false; + public Loader() { ValidForResume = false; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index f2ea6d85a8..f9f62b764b 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -26,6 +26,8 @@ namespace osu.Game.Screens.Menu public override bool ShowOverlaysOnEnter => buttons.State != MenuState.Initial; + protected override bool AllowBackButton => buttons.State != MenuState.Initial; + private readonly BackgroundScreenDefault background; private Screen songSelect; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index fb5d3d12e6..24945ea347 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -15,6 +16,7 @@ using osu.Game.Input.Bindings; using osu.Game.Rulesets; using osu.Game.Screens.Menu; using OpenTK; +using OpenTK.Input; namespace osu.Game.Screens { @@ -105,6 +107,20 @@ namespace osu.Game.Screens public bool OnReleased(GlobalAction action) => action == GlobalAction.Back && AllowBackButton; + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat || !IsCurrentScreen) return false; + + switch (args.Key) + { + case Key.Escape: + Exit(); + return true; + } + + return base.OnKeyDown(state, args); + } + protected override void OnResuming(Screen last) { sampleExit?.Play(); diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 1ccc5e2fe8..f29f5b328a 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -16,6 +16,7 @@ namespace osu.Game.Screens.Play protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); public override bool AllowBeatmapRulesetChange => false; + protected override bool AllowBackButton => false; protected const float BACKGROUND_FADE_DURATION = 800; From fe2ea17e7f8a4ef7952409ac82be57c20d42d687 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 11:42:40 +0900 Subject: [PATCH 150/302] Allow subclasses of LegacyScoreParser to specify beatmap/ruleset retrieval --- .../Rulesets/Scoring/Legacy/LegacyScoreParser.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs index 38873c4df1..f7ab9df52a 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs @@ -25,6 +25,10 @@ namespace osu.Game.Rulesets.Scoring.Legacy this.beatmaps = beatmaps; } + protected LegacyScoreParser() + { + } + private IBeatmap currentBeatmap; private Ruleset currentRuleset; @@ -34,16 +38,15 @@ namespace osu.Game.Rulesets.Scoring.Legacy using (SerializationReader sr = new SerializationReader(stream)) { - score = new Score { Ruleset = rulesets.GetRuleset(sr.ReadByte()) }; - currentRuleset = score.Ruleset.CreateInstance(); + currentRuleset = GetRuleset(sr.ReadByte()); + score = new Score { Ruleset = currentRuleset.RulesetInfo }; /* score.Pass = true;*/ var version = sr.ReadInt32(); /* score.FileChecksum = */ - var beatmapHash = sr.ReadString(); - score.Beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == beatmapHash); - currentBeatmap = beatmaps.GetWorkingBeatmap(score.Beatmap).Beatmap; + currentBeatmap = GetBeatmap(sr.ReadString()).Beatmap; + score.Beatmap = currentBeatmap.BeatmapInfo; /* score.PlayerName = */ score.User = new User { Username = sr.ReadString() }; @@ -181,5 +184,8 @@ namespace osu.Game.Rulesets.Scoring.Legacy return frame; } + + protected virtual Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId).CreateInstance(); + protected virtual WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash)); } } From 10e2f7453802b5166f7cb924924033f15d4ddd75 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 11:53:11 +0900 Subject: [PATCH 151/302] Port osu-performance HD AR fix --- osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index 4942a55004..793060197d 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -138,8 +138,9 @@ namespace osu.Game.Rulesets.Osu.Scoring aimValue *= approachRateFactor; + // We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR. if (mods.Any(h => h is OsuModHidden)) - aimValue *= 1.03f; + aimValue *= 1.02 + (11.0f - realApproachRate) / 50.0; // Gives a 1.04 bonus for AR10, a 1.06 bonus for AR9, a 1.02 bonus for AR11. if (mods.Any(h => h is OsuModFlashlight)) { From 1ee68c1c545662321b8404d899da1136b799991d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 15:27:57 +0900 Subject: [PATCH 152/302] Make LegacyScoreParser abstract --- .../Legacy/DatabasedLegacyScoreParser.cs | 26 ++++++++++++++++ .../Scoring/Legacy/LegacyScoreParser.cs | 30 +++++++++---------- osu.Game/Rulesets/Scoring/ScoreStore.cs | 2 +- 3 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 osu.Game/Rulesets/Scoring/Legacy/DatabasedLegacyScoreParser.cs diff --git a/osu.Game/Rulesets/Scoring/Legacy/DatabasedLegacyScoreParser.cs b/osu.Game/Rulesets/Scoring/Legacy/DatabasedLegacyScoreParser.cs new file mode 100644 index 0000000000..bfb2b7c13b --- /dev/null +++ b/osu.Game/Rulesets/Scoring/Legacy/DatabasedLegacyScoreParser.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; + +namespace osu.Game.Rulesets.Scoring.Legacy +{ + /// + /// A which retrieves the applicable and + /// for the score from the database. + /// + public class DatabasedLegacyScoreParser : LegacyScoreParser + { + private readonly RulesetStore rulesets; + private readonly BeatmapManager beatmaps; + + public DatabasedLegacyScoreParser(RulesetStore rulesets, BeatmapManager beatmaps) + { + this.rulesets = rulesets; + this.beatmaps = beatmaps; + } + + protected override Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId).CreateInstance(); + protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash)); + } +} diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs index f7ab9df52a..a90cd79186 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs @@ -14,21 +14,8 @@ using System.Linq; namespace osu.Game.Rulesets.Scoring.Legacy { - public class LegacyScoreParser + public abstract class LegacyScoreParser { - private readonly RulesetStore rulesets; - private readonly BeatmapManager beatmaps; - - public LegacyScoreParser(RulesetStore rulesets, BeatmapManager beatmaps) - { - this.rulesets = rulesets; - this.beatmaps = beatmaps; - } - - protected LegacyScoreParser() - { - } - private IBeatmap currentBeatmap; private Ruleset currentRuleset; @@ -185,7 +172,18 @@ namespace osu.Game.Rulesets.Scoring.Legacy return frame; } - protected virtual Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId).CreateInstance(); - protected virtual WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash)); + /// + /// Retrieves the for a specific id. + /// + /// The id. + /// The . + protected abstract Ruleset GetRuleset(int rulesetId); + + /// + /// Retrieves the corresponding to an MD5 hash. + /// + /// The MD5 hash. + /// The . + protected abstract WorkingBeatmap GetBeatmap(string md5Hash); } } diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs index 957fd037e0..69d25fcb67 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Scoring public Score ReadReplayFile(string replayFilename) { using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename))) - return new LegacyScoreParser(rulesets, beatmaps).Parse(s); + return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(s); } } } From 9fd972e0a3a3b582fd4d30935c1e7bd8af9ef74c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 17:36:29 +0900 Subject: [PATCH 153/302] Rename OsuDifficulty -> Difficulty --- .../OsuDifficultyCalculator.cs | 6 +++--- .../Preprocessing/OsuDifficultyBeatmap.cs | 2 +- .../Preprocessing/OsuDifficultyHitObject.cs | 4 ++-- .../{OsuDifficulty => Difficulty}/Skills/Aim.cs | 4 ++-- .../{OsuDifficulty => Difficulty}/Skills/Skill.cs | 6 +++--- .../{OsuDifficulty => Difficulty}/Skills/Speed.cs | 4 ++-- .../{OsuDifficulty => Difficulty}/Utils/History.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) rename osu.Game.Rulesets.Osu/{OsuDifficulty => Difficulty}/OsuDifficultyCalculator.cs (93%) rename osu.Game.Rulesets.Osu/{OsuDifficulty => Difficulty}/Preprocessing/OsuDifficultyBeatmap.cs (98%) rename osu.Game.Rulesets.Osu/{OsuDifficulty => Difficulty}/Preprocessing/OsuDifficultyHitObject.cs (98%) rename osu.Game.Rulesets.Osu/{OsuDifficulty => Difficulty}/Skills/Aim.cs (85%) rename osu.Game.Rulesets.Osu/{OsuDifficulty => Difficulty}/Skills/Skill.cs (96%) rename osu.Game.Rulesets.Osu/{OsuDifficulty => Difficulty}/Skills/Speed.cs (93%) rename osu.Game.Rulesets.Osu/{OsuDifficulty => Difficulty}/Utils/History.cs (98%) diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs similarity index 93% rename from osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs rename to osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 4853cd66cd..875f1f6097 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -5,11 +5,11 @@ using System; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Difficulty.Skills; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing; -using osu.Game.Rulesets.Osu.OsuDifficulty.Skills; -namespace osu.Game.Rulesets.Osu.OsuDifficulty +namespace osu.Game.Rulesets.Osu.Difficulty { public class OsuDifficultyCalculator : DifficultyCalculator { diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs similarity index 98% rename from osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs rename to osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs index 5c8ab0f3d4..e97042a9aa 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs @@ -5,7 +5,7 @@ using System.Collections; using System.Collections.Generic; using osu.Game.Rulesets.Osu.Objects; -namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing +namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing { /// /// An enumerable container wrapping input as diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs similarity index 98% rename from osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs rename to osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 415f76ced8..f95426466b 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -3,10 +3,10 @@ using System; using System.Linq; -using OpenTK; using osu.Game.Rulesets.Osu.Objects; +using OpenTK; -namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing +namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing { /// /// A wrapper around extending it with additional data required for difficulty calculation. diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs similarity index 85% rename from osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs rename to osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index 5c736d7bb5..0a45c62671 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -2,9 +2,9 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; -namespace osu.Game.Rulesets.Osu.OsuDifficulty.Skills +namespace osu.Game.Rulesets.Osu.Difficulty.Skills { /// /// Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances. diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs similarity index 96% rename from osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs rename to osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs index 983599432f..47037c1503 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs @@ -3,11 +3,11 @@ using System; using System.Collections.Generic; +using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Difficulty.Utils; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing; -using osu.Game.Rulesets.Osu.OsuDifficulty.Utils; -namespace osu.Game.Rulesets.Osu.OsuDifficulty.Skills +namespace osu.Game.Rulesets.Osu.Difficulty.Skills { /// /// Used to processes strain values of s, keep track of strain levels caused by the processed objects diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs similarity index 93% rename from osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs rename to osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index ae3caa1e66..b807f20037 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; -namespace osu.Game.Rulesets.Osu.OsuDifficulty.Skills +namespace osu.Game.Rulesets.Osu.Difficulty.Skills { /// /// Represents the skill required to press keys with regards to keeping up with the speed at which objects need to be hit. diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs b/osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs similarity index 98% rename from osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs rename to osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs index f6933a3e5d..55bd950209 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs @@ -5,7 +5,7 @@ using System; using System.Collections; using System.Collections.Generic; -namespace osu.Game.Rulesets.Osu.OsuDifficulty.Utils +namespace osu.Game.Rulesets.Osu.Difficulty.Utils { /// /// An indexed stack with Push() only, which disposes items at the bottom after the capacity is full. diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 69a54fb533..b5dc9063af 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -5,7 +5,6 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Rulesets.Osu.OsuDifficulty; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; using System.Collections.Generic; @@ -20,6 +19,7 @@ using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Difficulty; namespace osu.Game.Rulesets.Osu { From 995fda9b6f9a9d3bde52c9e943592e376dc6271f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 17:38:04 +0900 Subject: [PATCH 154/302] Move base classes to osu.Game.Rulesets.Difficulty namespace --- osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs | 1 + osu.Game.Rulesets.Catch/CatchRuleset.cs | 1 + osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs | 1 + osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 + .../Difficulty/OsuDifficultyCalculator.cs | 1 + osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs | 1 + osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs | 1 + osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 + osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 1 + .../Difficulty}/DifficultyCalculator.cs | 7 ++++--- .../{Scoring => Difficulty}/PerformanceCalculator.cs | 3 ++- osu.Game/Rulesets/Ruleset.cs | 1 + 13 files changed, 17 insertions(+), 4 deletions(-) rename osu.Game/{Beatmaps => Rulesets/Difficulty}/DifficultyCalculator.cs (94%) rename osu.Game/Rulesets/{Scoring => Difficulty}/PerformanceCalculator.cs (95%) diff --git a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs index f47d09fe20..1ea70c54c9 100644 --- a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs @@ -3,6 +3,7 @@ using osu.Game.Beatmaps; using System.Collections.Generic; +using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Catch { diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 15e51fa126..c4342ec4b0 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Catch.Beatmaps; +using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Catch { diff --git a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs index 822ba53eeb..d5ae568bc4 100644 --- a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs @@ -7,6 +7,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; +using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Mania { diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index f1d65f855b..2672486460 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -15,6 +15,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mania.Beatmaps; namespace osu.Game.Rulesets.Mania diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 875f1f6097..bd8d18af41 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Skills; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index b5dc9063af..a2423ffbe5 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Difficulty; diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index 793060197d..938060a664 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs index f14c53f7ae..1c49118d32 100644 --- a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs @@ -5,6 +5,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Taiko.Objects; using System.Collections.Generic; using System; +using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Taiko { diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 102de5717f..154b66f4ad 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -13,6 +13,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Taiko.Beatmaps; namespace osu.Game.Rulesets.Taiko diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index da52dc7284..8094abe5ed 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; diff --git a/osu.Game/Beatmaps/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs similarity index 94% rename from osu.Game/Beatmaps/DifficultyCalculator.cs rename to osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 5cac9ed923..070bc7ddb0 100644 --- a/osu.Game/Beatmaps/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -2,12 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using osu.Game.Rulesets.Mods; -using osu.Framework.Timing; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; -namespace osu.Game.Beatmaps +namespace osu.Game.Rulesets.Difficulty { public abstract class DifficultyCalculator { diff --git a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs similarity index 95% rename from osu.Game/Rulesets/Scoring/PerformanceCalculator.cs rename to osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index f2c495fa5d..9fd7a0156d 100644 --- a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -7,8 +7,9 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; -namespace osu.Game.Rulesets.Scoring +namespace osu.Game.Rulesets.Difficulty { public abstract class PerformanceCalculator { diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 6883d319f4..395eeab419 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets { From 803200ff6a724e1c7143c0901776b7a95756b76d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 17:40:19 +0900 Subject: [PATCH 155/302] Apply similar changes to other rulesets --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 1 + .../{ => Difficulty}/CatchDifficultyCalculator.cs | 4 ++-- .../{ => Difficulty}/ManiaDifficultyCalculator.cs | 8 ++++---- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 + .../{ => Difficulty}/TaikoDifficultyCalculator.cs | 8 ++++---- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 + 6 files changed, 13 insertions(+), 10 deletions(-) rename osu.Game.Rulesets.Catch/{ => Difficulty}/CatchDifficultyCalculator.cs (92%) rename osu.Game.Rulesets.Mania/{ => Difficulty}/ManiaDifficultyCalculator.cs (99%) rename osu.Game.Rulesets.Taiko/{ => Difficulty}/TaikoDifficultyCalculator.cs (99%) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index c4342ec4b0..2325a8cad9 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Catch.Beatmaps; +using osu.Game.Rulesets.Catch.Difficulty; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Catch diff --git a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs similarity index 92% rename from osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs rename to osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 1ea70c54c9..f8351b7519 100644 --- a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -1,11 +1,11 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Beatmaps; using System.Collections.Generic; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; -namespace osu.Game.Rulesets.Catch +namespace osu.Game.Rulesets.Catch.Difficulty { public class CatchDifficultyCalculator : DifficultyCalculator { diff --git a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs similarity index 99% rename from osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs rename to osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index d5ae568bc4..ac45130fd8 100644 --- a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -1,15 +1,15 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; -using System; -using System.Collections.Generic; -using osu.Game.Rulesets.Difficulty; -namespace osu.Game.Rulesets.Mania +namespace osu.Game.Rulesets.Mania.Difficulty { internal class ManiaDifficultyCalculator : DifficultyCalculator { diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 2672486460..b1702de537 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Difficulty; namespace osu.Game.Rulesets.Mania { diff --git a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs similarity index 99% rename from osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs rename to osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 1c49118d32..acff0d286d 100644 --- a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -1,13 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Taiko.Objects; -using System.Collections.Generic; using System; +using System.Collections.Generic; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Taiko.Objects; -namespace osu.Game.Rulesets.Taiko +namespace osu.Game.Rulesets.Taiko.Difficulty { internal class TaikoDifficultyCalculator : DifficultyCalculator { diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 154b66f4ad..35dc17c0e2 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Taiko.Beatmaps; +using osu.Game.Rulesets.Taiko.Difficulty; namespace osu.Game.Rulesets.Taiko { From 0325b1bd7ac7b9b0af4bc9f2bd210bfe00aa12bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 May 2018 19:42:30 +0900 Subject: [PATCH 156/302] Remove unused class --- osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index fbdb27a81c..ae03a06b4f 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -8,10 +8,6 @@ using osu.Framework.Screens; namespace osu.Game.Graphics.UserInterface { - public class ScreenBreadcrumbControl : ScreenBreadcrumbControl - { - } - public class ScreenBreadcrumbControl : BreadcrumbControl where T : Screen { private T currentScreen; From 28df77e83887d2eae75454bdd6de5b3a8afca46a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 May 2018 21:08:55 +0900 Subject: [PATCH 157/302] Simplify code and remove generic --- ....cs => TestCaseScreenBreadcrumbControl.cs} | 18 ++--- .../UserInterface/ScreenBreadcrumbControl.cs | 75 +++++++------------ 2 files changed, 36 insertions(+), 57 deletions(-) rename osu.Game.Tests/Visual/{TestCaseScreenBreadcrumbs.cs => TestCaseScreenBreadcrumbControl.cs} (89%) diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs similarity index 89% rename from osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs rename to osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs index f477a0b97e..a64e60dbd6 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbs.cs +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -15,18 +16,19 @@ using OpenTK; namespace osu.Game.Tests.Visual { [TestFixture] - public class TestCaseScreenBreadcrumbs : OsuTestCase + public class TestCaseScreenBreadcrumbControl : OsuTestCase { - private readonly ScreenBreadcrumbControl breadcrumbs; - private TestScreen currentScreen, changedScreen; + private readonly ScreenBreadcrumbControl breadcrumbs; + private Screen currentScreen, changedScreen; - public TestCaseScreenBreadcrumbs() + public TestCaseScreenBreadcrumbControl() { TestScreen startScreen; OsuSpriteText titleText; Children = new Drawable[] { + changedScreen = currentScreen = startScreen = new TestScreenOne(), new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -35,23 +37,21 @@ namespace osu.Game.Tests.Visual Spacing = new Vector2(10), Children = new Drawable[] { - breadcrumbs = new ScreenBreadcrumbControl + breadcrumbs = new ScreenBreadcrumbControl(startScreen) { RelativeSizeAxes = Axes.X, }, titleText = new OsuSpriteText(), }, }, - currentScreen = startScreen = new TestScreenOne(), }; - breadcrumbs.OnScreenChanged += s => + breadcrumbs.Current.ValueChanged += s => { titleText.Text = $"Changed to {s.ToString()}"; changedScreen = s; }; - AddStep(@"make start current", () => breadcrumbs.CurrentScreen = startScreen); assertCurrent(); pushNext(); assertCurrent(); @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual breadcrumbs.StripColour = colours.Blue; } - private void pushNext() => AddStep(@"push next screen", () => currentScreen = currentScreen.PushNext()); + private void pushNext() => AddStep(@"push next screen", () => currentScreen = ((TestScreen)currentScreen).PushNext()); private void assertCurrent() => AddAssert(@"assert the current screen is correct", () => currentScreen == changedScreen); private abstract class TestScreen : OsuScreen diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index ae03a06b4f..49d854ccd2 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -8,67 +8,46 @@ using osu.Framework.Screens; namespace osu.Game.Graphics.UserInterface { - public class ScreenBreadcrumbControl : BreadcrumbControl where T : Screen + /// + /// A which follows the active screen (and allows navigation) in a stack. + /// + public class ScreenBreadcrumbControl : BreadcrumbControl { - private T currentScreen; - public T CurrentScreen + private Screen last; + + public ScreenBreadcrumbControl(Screen initialScreen) { - get { return currentScreen; } - set + Current.ValueChanged += newScreen => { - if (value == currentScreen) return; - - if (CurrentScreen != null) - { - CurrentScreen.Exited -= onExited; - CurrentScreen.ModePushed -= onPushed; - } - else - { - // this is the first screen in the stack, so call the initial onPushed - currentScreen = value; - onPushed(CurrentScreen); - } - - currentScreen = value; - - if (CurrentScreen != null) - { - CurrentScreen.Exited += onExited; - CurrentScreen.ModePushed += onPushed; - Current.Value = CurrentScreen; - OnScreenChanged?.Invoke(CurrentScreen); - } - } - } - - public event Action OnScreenChanged; - - public ScreenBreadcrumbControl() - { - Current.ValueChanged += s => - { - if (s != CurrentScreen) - { - CurrentScreen = s; - s.MakeCurrent(); - } + if (last != newScreen && !newScreen.IsCurrentScreen) + newScreen.MakeCurrent(); }; + + onPushed(initialScreen); } - private void onExited(Screen screen) + private void screenChanged(Screen newScreen) { - CurrentScreen = screen as T; + if (last != null) + { + last.Exited -= screenChanged; + last.ModePushed -= onPushed; + } + + last = newScreen; + + newScreen.Exited += screenChanged; + newScreen.ModePushed += onPushed; + + Current.Value = newScreen; } private void onPushed(Screen screen) { - var newScreen = screen as T; - Items.ToList().SkipWhile(i => i != Current.Value).Skip(1).ForEach(RemoveItem); - AddItem(newScreen); + AddItem(screen); - CurrentScreen = newScreen; + screenChanged(screen); } } } From 49c36787d7d1365c6eda1fcae9b4fb5e77b496de Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 21:22:57 +0900 Subject: [PATCH 158/302] Remove triangle pattern and remove not-implemented reading strain --- .../Preprocessing/OsuDifficultyBeatmap.cs | 58 ++----------------- .../Preprocessing/OsuDifficultyHitObject.cs | 19 +++--- 2 files changed, 11 insertions(+), 66 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs index 5c8ab0f3d4..867a11f280 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs @@ -14,7 +14,6 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing public class OsuDifficultyBeatmap : IEnumerable { private readonly IEnumerator difficultyObjects; - private readonly Queue onScreen = new Queue(); /// /// Creates an enumerator, which preprocesses a list of s recieved as input, wrapping them as @@ -30,65 +29,16 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing /// /// Returns an enumerator that enumerates all s in the . - /// The inner loop adds objects that appear on screen into a queue until we need to hit the next object. - /// The outer loop returns objects from this queue one at a time, only after they had to be hit, and should no longer be on screen. - /// This means that we can loop through every object that is on screen at the time when a new one appears, - /// allowing us to determine a reading strain for the object that just appeared. /// - public IEnumerator GetEnumerator() - { - while (true) - { - // Add upcoming objects to the queue until we have at least one object that had been hit and can be dequeued. - // This means there is always at least one object in the queue unless we reached the end of the map. - do - { - if (!difficultyObjects.MoveNext()) - break; // New objects can't be added anymore, but we still need to dequeue and return the ones already on screen. - - OsuDifficultyHitObject latest = difficultyObjects.Current; - // Calculate flow values here - - 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 - } - - onScreen.Enqueue(latest); - } - while (onScreen.Peek().TimeUntilHit > 0); // Keep adding new objects on screen while there is still time before we have to hit the next one. - - if (onScreen.Count == 0) break; // We have reached the end of the map and enumerated all the objects. - yield return onScreen.Dequeue(); // Remove and return objects one by one that had to be hit before the latest one appeared. - } - } - + public IEnumerator GetEnumerator() => difficultyObjects; IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); private IEnumerator createDifficultyObjectEnumerator(List objects, double timeRate) { - // We will process OsuHitObjects in groups of three to form a triangle, so we can calculate an angle for each object. - OsuHitObject[] triangle = new OsuHitObject[3]; - - // OsuDifficultyHitObject construction requires three components, an extra copy of the first OsuHitObject is used at the beginning. - if (objects.Count > 1) - { - triangle[1] = objects[0]; // This copy will get shifted to the last spot in the triangle. - triangle[0] = objects[0]; // This component corresponds to the real first OsuHitOject. - } - - // The final component of the first triangle will be the second OsuHitOject of the map, which forms the first jump. + // The first jump is formed by the first two hitobjects of the map. // If the map has less than two OsuHitObjects, the enumerator will not return anything. - for (int i = 1; i < objects.Count; ++i) - { - triangle[2] = triangle[1]; - triangle[1] = triangle[0]; - triangle[0] = objects[i]; - - yield return new OsuDifficultyHitObject(triangle, timeRate); - } + for (int i = 1; i < objects.Count; i++) + yield return new OsuDifficultyHitObject(objects[i], objects[i - 1], timeRate); } } } diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs index 415f76ced8..c096e9a464 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -28,26 +28,22 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing /// public double DeltaTime { get; private set; } - /// - /// Number of milliseconds until the has to be hit. - /// - public double TimeUntilHit { get; set; } private const int normalized_radius = 52; + private readonly OsuHitObject lastObject; private readonly double timeRate; - private readonly OsuHitObject[] t; - /// /// Initializes the object calculating extra data required for difficulty calculation. /// - public OsuDifficultyHitObject(OsuHitObject[] triangle, double timeRate) + public OsuDifficultyHitObject(OsuHitObject currentObject, OsuHitObject lastObject, double timeRate) { + this.lastObject = lastObject; this.timeRate = timeRate; - t = triangle; - BaseObject = t[0]; + BaseObject = currentObject; + setDistances(); setTimingValues(); // Calculate angle here @@ -63,10 +59,10 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing scalingFactor *= 1 + smallCircleBonus; } - Vector2 lastCursorPosition = t[1].StackedPosition; + Vector2 lastCursorPosition = lastObject.StackedPosition; float lastTravelDistance = 0; - var lastSlider = t[1] as Slider; + var lastSlider = lastObject as Slider; if (lastSlider != null) { computeSliderCursorPosition(lastSlider); @@ -81,7 +77,6 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing { // Every timing inverval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure. DeltaTime = Math.Max(40, (t[0].StartTime - t[1].StartTime) / timeRate); - TimeUntilHit = 450; // BaseObject.PreEmpt; } private void computeSliderCursorPosition(Slider slider) From 1b5c151e0edf7f528ca344516f47977908f04a75 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 21:25:02 +0900 Subject: [PATCH 159/302] Fix DeltaTime being capped incorrectly --- .../OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs index c096e9a464..d06518df53 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing private void setTimingValues() { // Every timing inverval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure. - DeltaTime = Math.Max(40, (t[0].StartTime - t[1].StartTime) / timeRate); + DeltaTime = Math.Max(50, (BaseObject.StartTime - lastObject.StartTime) / timeRate); } private void computeSliderCursorPosition(Slider slider) From 1acfc1bbabf365c15401b121a6c2f1eab9b46c1f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 21:25:20 +0900 Subject: [PATCH 160/302] Fix ModHardRock not properly clamping Drain/OD --- osu.Game/Rulesets/Mods/ModHardRock.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 090bc737dd..1629945c87 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -21,8 +21,8 @@ namespace osu.Game.Rulesets.Mods const float ratio = 1.4f; difficulty.CircleSize *= 1.3f; // CS uses a custom 1.3 ratio. difficulty.ApproachRate = Math.Min(difficulty.ApproachRate * ratio, 10.0f); - difficulty.DrainRate *= ratio; - difficulty.OverallDifficulty *= ratio; + difficulty.DrainRate = Math.Min(difficulty.DrainRate * ratio, 10.0f); + difficulty.OverallDifficulty = Math.Min(difficulty.OverallDifficulty * ratio, 10.0f); } } } From bc197a88e17f745344efd688f65e520d1f814565 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 21:25:33 +0900 Subject: [PATCH 161/302] Fix slider length calculation including slider head --- .../OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs index d06518df53..1624b936c8 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -102,7 +102,8 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing } }); - var scoringTimes = slider.NestedHitObjects.Select(t => t.StartTime); + // Skip the head circle + var scoringTimes = slider.NestedHitObjects.Skip(1).Select(t => t.StartTime); foreach (var time in scoringTimes) computeVertex(time); computeVertex(slider.EndTime); From 22f3bee55ae10fa62c0cb7ef9ede89946149529a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 21:26:06 +0900 Subject: [PATCH 162/302] Fix incorrect iteration over difficulty sections --- .../OsuDifficulty/OsuDifficultyCalculator.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs index 4853cd66cd..92cfb77faa 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs @@ -35,18 +35,22 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty new Speed() }; - double sectionEnd = section_length / TimeRate; + double sectionLength = section_length * TimeRate; + + // The first object doesn't generate a strain, so we begin with an incremented section end + double currentSectionEnd = 2 * sectionLength; + foreach (OsuDifficultyHitObject h in beatmap) { - while (h.BaseObject.StartTime > sectionEnd) + while (h.BaseObject.StartTime > currentSectionEnd) { foreach (Skill s in skills) { s.SaveCurrentPeak(); - s.StartNewSectionFrom(sectionEnd); + s.StartNewSectionFrom(currentSectionEnd); } - sectionEnd += section_length; + currentSectionEnd += sectionLength; } foreach (Skill s in skills) From cf08293be15de809bf79c3051278babbd164033b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 21:44:45 +0900 Subject: [PATCH 163/302] Remove extra newline --- .../Difficulty/Preprocessing/OsuDifficultyHitObject.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 595e2d7e3e..29de23406b 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -13,6 +13,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing /// public class OsuDifficultyHitObject { + private const int normalized_radius = 52; + /// /// The this refers to. /// @@ -28,9 +30,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing /// public double DeltaTime { get; private set; } - - private const int normalized_radius = 52; - private readonly OsuHitObject lastObject; private readonly double timeRate; From 3f67d044291d081df01a259aa40e57ff3274fb82 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 May 2018 21:57:08 +0900 Subject: [PATCH 164/302] Cap CS to 10 also --- osu.Game/Rulesets/Mods/ModHardRock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 1629945c87..6379be9bfc 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToDifficulty(BeatmapDifficulty difficulty) { const float ratio = 1.4f; - difficulty.CircleSize *= 1.3f; // CS uses a custom 1.3 ratio. + difficulty.CircleSize = Math.Min(difficulty.CircleSize * 1.3f, 10.0f); // CS uses a custom 1.3 ratio. difficulty.ApproachRate = Math.Min(difficulty.ApproachRate * ratio, 10.0f); difficulty.DrainRate = Math.Min(difficulty.DrainRate * ratio, 10.0f); difficulty.OverallDifficulty = Math.Min(difficulty.OverallDifficulty * ratio, 10.0f); From c0c449e453d2a71043386cf120a633c40ff2c123 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 May 2018 22:53:33 +0900 Subject: [PATCH 165/302] Remove unused using --- osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index 49d854ccd2..ba3927b771 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Screens; From 4019683f6ce6231c3cf04d437adccc8d48e1b651 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 01:24:53 +0900 Subject: [PATCH 166/302] Implement osu!mania performance calculation --- .../Difficulty/ManiaDifficultyCalculator.cs | 3 +- .../Difficulty/ManiaPerformanceCalculator.cs | 122 ++++++++++++++++++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 + 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index ac45130fd8..8458e63fca 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -60,7 +60,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty double starRating = calculateDifficulty() * star_scaling_factor; - categoryDifficulty?.Add("Strain", starRating); + if (categoryDifficulty != null) + categoryDifficulty["Strain"] = starRating; return starRating; } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs new file mode 100644 index 0000000000..1704d924f8 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -0,0 +1,122 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mania.Difficulty +{ + public class ManiaPerformanceCalculator : PerformanceCalculator + { + private Mod[] mods; + private int countGeki; + private int countKatu; + private int count300; + private int count100; + private int count50; + private int countMiss; + + public ManiaPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) + : base(ruleset, beatmap, score) + { + } + + public override double Calculate(Dictionary categoryDifficulty = null) + { + mods = Score.Mods; + countGeki = Convert.ToInt32(Score.Statistics[HitResult.Perfect]); + countKatu = Convert.ToInt32(Score.Statistics[HitResult.Ok]); + count300 = Convert.ToInt32(Score.Statistics[HitResult.Great]); + count100 = Convert.ToInt32(Score.Statistics[HitResult.Good]); + count50 = Convert.ToInt32(Score.Statistics[HitResult.Meh]); + countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); + + if (mods.Any(m => !m.Ranked)) + return 0; + + // Custom multipliers for NoFail + double multiplier = 1.1; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things + + if (mods.Any(m => m is ModNoFail)) + multiplier *= 0.9; + if (mods.Any(m => m is ModEasy)) + multiplier *= 0.5; + + double strainValue = computeStrainValue(); + double accValue = computeAccuracyValue(); + double totalValue = + Math.Pow( + Math.Pow(strainValue, 1.1) + + Math.Pow(accValue, 1.1), 1.0 / 1.1 + ) * multiplier; + + if (categoryDifficulty != null) + { + categoryDifficulty["Strain"] = strainValue; + categoryDifficulty["Accuracy"] = accValue; + + } + + return totalValue; + } + + private double computeStrainValue() + { + IEnumerable scoreIncreaseMods = new ManiaRuleset().GetModsFor(ModType.DifficultyIncrease); + + double scoreMultiplier = 1.0; + foreach (var m in mods.Where(m => !scoreIncreaseMods.Contains(m))) + scoreMultiplier *= m.ScoreMultiplier; + + // Score after being scaled by non-difficulty-increasing mods + double scaledScore = Score.TotalScore; + + // Scale score up, so it's comparable to other keymods + scaledScore *= 1.0 / scoreMultiplier; + + // Obtain strain difficulty + double strainValue = Math.Pow(5 * Math.Max(1, Attributes["Strain"] / 0.0825) - 4.0, 3.0) / 110000.0; + + // Longer maps are worth more + strainValue *= 1.0 + 0.1 * Math.Min(1.0, totalHits / 1500.0); + + if (scaledScore <= 500000) + strainValue = 0; + else if (scaledScore <= 600000) + strainValue *= (scaledScore - 500000) / 100000 * 0.3; + else if (scaledScore <= 700000) + strainValue *= 0.3 + (scaledScore - 600000) / 100000 * 0.35; + else if (scaledScore <= 800000) + strainValue *= 0.65 + (scaledScore - 700000) / 100000 * 0.20; + else if (scaledScore <= 900000) + strainValue *= 0.85 + (scaledScore - 800000) / 100000 * 0.1; + else + strainValue *= 0.95 + (scaledScore - 900000) / 100000 * 0.05; + + return strainValue; + } + + private double computeAccuracyValue() + { + double hitWindow300 = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + if (hitWindow300 <= 0) + return 0; + + // Lots of arbitrary values from testing. + // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution + double accuracyValue = Math.Pow(150.0 / hitWindow300 * Math.Pow(Score.Accuracy, 16), 1.8) * 2.5; + + // Bonus for many hitcircles - it's harder to keep good accuracy up for longer + accuracyValue *= Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); + + return accuracyValue; + } + + private double totalHits => countGeki + countKatu + count300 + count100 + count50 + countMiss; + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index b1702de537..02ecb3afda 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -18,6 +18,7 @@ using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Difficulty; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania { @@ -25,6 +26,7 @@ namespace osu.Game.Rulesets.Mania { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); + public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new ManiaPerformanceCalculator(this, beatmap, score); public override IEnumerable ConvertLegacyMods(LegacyMods mods) { From 1fdc77d5791cd03af2e69fe62b1a68c57e1589c0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 01:34:07 +0900 Subject: [PATCH 167/302] Update with the rebalance changes --- .../Difficulty/ManiaPerformanceCalculator.cs | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 1704d924f8..3337d4df75 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -14,6 +14,10 @@ namespace osu.Game.Rulesets.Mania.Difficulty public class ManiaPerformanceCalculator : PerformanceCalculator { private Mod[] mods; + + // Score after being scaled by non-difficulty-increasing mods + private double scaledScore; + private int countGeki; private int countKatu; private int count300; @@ -29,6 +33,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty public override double Calculate(Dictionary categoryDifficulty = null) { mods = Score.Mods; + scaledScore = Score.TotalScore; countGeki = Convert.ToInt32(Score.Statistics[HitResult.Perfect]); countKatu = Convert.ToInt32(Score.Statistics[HitResult.Ok]); count300 = Convert.ToInt32(Score.Statistics[HitResult.Great]); @@ -39,8 +44,18 @@ namespace osu.Game.Rulesets.Mania.Difficulty if (mods.Any(m => !m.Ranked)) return 0; - // Custom multipliers for NoFail - double multiplier = 1.1; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things + IEnumerable scoreIncreaseMods = new ManiaRuleset().GetModsFor(ModType.DifficultyIncrease); + + double scoreMultiplier = 1.0; + foreach (var m in mods.Where(m => !scoreIncreaseMods.Contains(m))) + scoreMultiplier *= m.ScoreMultiplier; + + // Scale score up, so it's comparable to other keymods + scaledScore *= 1.0 / scoreMultiplier; + + // Arbitrary initial value for scaling pp in order to standardize distributions across game modes. + // The specific number has no intrinsic meaning and can be adjusted as needed. + double multiplier = 0.8; if (mods.Any(m => m is ModNoFail)) multiplier *= 0.9; @@ -48,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty multiplier *= 0.5; double strainValue = computeStrainValue(); - double accValue = computeAccuracyValue(); + double accValue = computeAccuracyValue(strainValue); double totalValue = Math.Pow( Math.Pow(strainValue, 1.1) + @@ -67,20 +82,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty private double computeStrainValue() { - IEnumerable scoreIncreaseMods = new ManiaRuleset().GetModsFor(ModType.DifficultyIncrease); - - double scoreMultiplier = 1.0; - foreach (var m in mods.Where(m => !scoreIncreaseMods.Contains(m))) - scoreMultiplier *= m.ScoreMultiplier; - - // Score after being scaled by non-difficulty-increasing mods - double scaledScore = Score.TotalScore; - - // Scale score up, so it's comparable to other keymods - scaledScore *= 1.0 / scoreMultiplier; - // Obtain strain difficulty - double strainValue = Math.Pow(5 * Math.Max(1, Attributes["Strain"] / 0.0825) - 4.0, 3.0) / 110000.0; + double strainValue = Math.Pow(5 * Math.Max(1, Attributes["Strain"] / 0.2) - 4.0, 2.2) / 135.0; // Longer maps are worth more strainValue *= 1.0 + 0.1 * Math.Min(1.0, totalHits / 1500.0); @@ -90,18 +93,18 @@ namespace osu.Game.Rulesets.Mania.Difficulty else if (scaledScore <= 600000) strainValue *= (scaledScore - 500000) / 100000 * 0.3; else if (scaledScore <= 700000) - strainValue *= 0.3 + (scaledScore - 600000) / 100000 * 0.35; + strainValue *= 0.3 + (scaledScore - 600000) / 100000 * 0.25; else if (scaledScore <= 800000) - strainValue *= 0.65 + (scaledScore - 700000) / 100000 * 0.20; + strainValue *= 0.55 + (scaledScore - 700000) / 100000 * 0.20; else if (scaledScore <= 900000) - strainValue *= 0.85 + (scaledScore - 800000) / 100000 * 0.1; + strainValue *= 0.75 + (scaledScore - 800000) / 100000 * 0.15; else - strainValue *= 0.95 + (scaledScore - 900000) / 100000 * 0.05; + strainValue *= 0.90 + (scaledScore - 900000) / 100000 * 0.1; return strainValue; } - private double computeAccuracyValue() + private double computeAccuracyValue(double strainValue) { double hitWindow300 = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; if (hitWindow300 <= 0) @@ -109,10 +112,12 @@ namespace osu.Game.Rulesets.Mania.Difficulty // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Pow(150.0 / hitWindow300 * Math.Pow(Score.Accuracy, 16), 1.8) * 2.5; + double accuracyValue = Math.Max(0.0, 0.2 - (hitWindow300 - 34) * 0.006667) + * strainValue + * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); // Bonus for many hitcircles - it's harder to keep good accuracy up for longer - accuracyValue *= Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); + // accuracyValue *= Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); return accuracyValue; } From ed902d9325eb6c7435e106224bd517a08ab9aa4c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 01:36:28 +0900 Subject: [PATCH 168/302] Cleanup --- osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 3337d4df75..024362f5d2 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -74,7 +74,6 @@ namespace osu.Game.Rulesets.Mania.Difficulty { categoryDifficulty["Strain"] = strainValue; categoryDifficulty["Accuracy"] = accValue; - } return totalValue; From de63a1b578d422a1c39b6212018ed3448c806ec5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 01:43:58 +0900 Subject: [PATCH 169/302] Remove construction of new ruleset --- .../Difficulty/ManiaPerformanceCalculator.cs | 2 +- osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 024362f5d2..f5f815d9fb 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty if (mods.Any(m => !m.Ranked)) return 0; - IEnumerable scoreIncreaseMods = new ManiaRuleset().GetModsFor(ModType.DifficultyIncrease); + IEnumerable scoreIncreaseMods = Ruleset.GetModsFor(ModType.DifficultyIncrease); double scoreMultiplier = 1.0; foreach (var m in mods.Where(m => !scoreIncreaseMods.Contains(m))) diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 9fd7a0156d..07d9c80061 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Difficulty private readonly Dictionary attributes = new Dictionary(); protected IDictionary Attributes => attributes; + protected readonly Ruleset Ruleset; protected readonly IBeatmap Beatmap; protected readonly Score Score; @@ -23,9 +24,9 @@ namespace osu.Game.Rulesets.Difficulty protected PerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) { - Score = score; - + Ruleset = ruleset; Beatmap = beatmap; + Score = score; var diffCalc = ruleset.CreateDifficultyCalculator(beatmap, score.Mods); diffCalc.Calculate(attributes); From b9d99b5f4049531bcb9c255d78c088652c094b29 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 15 May 2018 19:42:50 -0300 Subject: [PATCH 170/302] Fix nullref when exiting the last screen. --- osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index ba3927b771..adcf401546 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -27,6 +27,8 @@ namespace osu.Game.Graphics.UserInterface private void screenChanged(Screen newScreen) { + if (newScreen == null) return; + if (last != null) { last.Exited -= screenChanged; From f67ad7b8e879be7c789e9c763a335f966e4b786a Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 15 May 2018 19:52:28 -0300 Subject: [PATCH 171/302] Add exit test. --- osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs index a64e60dbd6..edd2e9fd11 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs @@ -66,7 +66,9 @@ namespace osu.Game.Tests.Visual assertCurrent(); pushNext(); - AddAssert(@"assert there are only 2 items", () => breadcrumbs.Items.Count() == 2); + AddAssert(@"only 2 items", () => breadcrumbs.Items.Count() == 2); + AddStep(@"exit current", () => changedScreen.Exit()); + AddAssert(@"current screen is first", () => startScreen == changedScreen); } [BackgroundDependencyLoader] @@ -76,7 +78,7 @@ namespace osu.Game.Tests.Visual } private void pushNext() => AddStep(@"push next screen", () => currentScreen = ((TestScreen)currentScreen).PushNext()); - private void assertCurrent() => AddAssert(@"assert the current screen is correct", () => currentScreen == changedScreen); + private void assertCurrent() => AddAssert(@"current screen is correct", () => currentScreen == changedScreen); private abstract class TestScreen : OsuScreen { From dda253758bfb4ade3bc3f6686cb2fccac6e17fc3 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 15 May 2018 19:56:47 -0300 Subject: [PATCH 172/302] Cleanup test step wording. --- osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs index edd2e9fd11..7a743655f4 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual Children = new Drawable[] { - changedScreen = currentScreen = startScreen = new TestScreenOne(), + currentScreen = startScreen = new TestScreenOne(), new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -52,6 +52,8 @@ namespace osu.Game.Tests.Visual changedScreen = s; }; + breadcrumbs.Current.TriggerChange(); + assertCurrent(); pushNext(); assertCurrent(); @@ -78,7 +80,7 @@ namespace osu.Game.Tests.Visual } private void pushNext() => AddStep(@"push next screen", () => currentScreen = ((TestScreen)currentScreen).PushNext()); - private void assertCurrent() => AddAssert(@"current screen is correct", () => currentScreen == changedScreen); + private void assertCurrent() => AddAssert(@"changedScreen correct", () => currentScreen == changedScreen); private abstract class TestScreen : OsuScreen { From 1450bf64f5c57f08ab85bc2900876c904d03c08e Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 15 May 2018 20:34:14 -0300 Subject: [PATCH 173/302] Add multiplayer screen header. --- osu.Game.Tests/Visual/TestCaseMultiHeader.cs | 27 +++++ osu.Game/Screens/Multi/Header.cs | 101 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseMultiHeader.cs create mode 100644 osu.Game/Screens/Multi/Header.cs diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs new file mode 100644 index 0000000000..af51a6221f --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Screens; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseMultiHeader : OsuTestCase + { + public TestCaseMultiHeader() + { + Lobby lobby; + Children = new Drawable[] + { + lobby = new Lobby + { + Padding = new MarginPadding { Top = Header.HEIGHT }, + }, + new Header(lobby), + }; + } + } +} diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs new file mode 100644 index 0000000000..03996f5309 --- /dev/null +++ b/osu.Game/Screens/Multi/Header.cs @@ -0,0 +1,101 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Screens; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.SearchableList; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Screens.Multi +{ + public class Header : Container + { + public const float HEIGHT = 121; + + private readonly OsuSpriteText screenTitle; + private readonly ScreenBreadcrumbControl breadcrumbs; + + public Header(Screen initialScreen) + { + RelativeSizeAxes = Axes.X; + Height = HEIGHT; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"2f2043"), + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Children = new Drawable[] + { + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomLeft, + Position = new Vector2(-35f, 5f), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10f, 0f), + Children = new Drawable[] + { + new SpriteIcon + { + Size = new Vector2(25), + Icon = FontAwesome.fa_osu_multi, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] + { + new OsuSpriteText + { + Text = "multiplayer ", + TextSize = 25, + }, + screenTitle = new OsuSpriteText + { + TextSize = 25, + Font = @"Exo2.0-Light", + }, + }, + }, + }, + }, + breadcrumbs = new ScreenBreadcrumbControl(initialScreen) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + }, + }, + }, + }; + + breadcrumbs.OnLoadComplete = d => breadcrumbs.AccentColour = Color4.White; + + breadcrumbs.Current.ValueChanged += s => screenTitle.Text = s.ToString(); + breadcrumbs.Current.TriggerChange(); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + screenTitle.Colour = colours.Yellow; + breadcrumbs.StripColour = colours.Green; + } + } +} From 1a78ac3d10629a12302133f6d26d209c60adfc3d Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 15 May 2018 21:14:10 -0300 Subject: [PATCH 174/302] Add Multiplayer screen. --- osu.Game.Tests/Visual/TestCaseMultiScreen.cs | 17 ++++ osu.Game/Screens/Menu/MainMenu.cs | 4 +- osu.Game/Screens/Multi/Multiplayer.cs | 100 +++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseMultiScreen.cs create mode 100644 osu.Game/Screens/Multi/Multiplayer.cs diff --git a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs new file mode 100644 index 0000000000..2dd3e81ee1 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Game.Screens.Multi; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseMultiScreen : OsuTestCase + { + public TestCaseMultiScreen() + { + Child = new Multiplayer(); + } + } +} diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index e564ab786d..600fad8da5 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Charts; using osu.Game.Screens.Direct; using osu.Game.Screens.Edit; -using osu.Game.Screens.Multi.Screens; +using osu.Game.Screens.Multi; using osu.Game.Screens.Select; using osu.Game.Screens.Tournament; @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Menu OnDirect = delegate { Push(new OnlineListing()); }, OnEdit = delegate { Push(new Editor()); }, OnSolo = delegate { Push(consumeSongSelect()); }, - OnMulti = delegate { Push(new Lobby()); }, + OnMulti = delegate { Push(new Multiplayer()); }, OnExit = Exit, } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs new file mode 100644 index 0000000000..b3d393209c --- /dev/null +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -0,0 +1,100 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Screens; +using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.Containers; +using osu.Game.Screens.Multi.Screens; + +namespace osu.Game.Screens.Multi +{ + public class Multiplayer : OsuScreen + { + private readonly MultiplayerWaveContainer waves; + + protected override Container Content => waves; + + public Multiplayer() + { + InternalChild = waves = new MultiplayerWaveContainer + { + RelativeSizeAxes = Axes.Both, + }; + + Lobby lobby; + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"3e3a44"), + }, + new Triangles + { + RelativeSizeAxes = Axes.Both, + ColourLight = OsuColour.FromHex(@"3c3842"), + ColourDark = OsuColour.FromHex(@"393540"), + TriangleScale = 5, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = Header.HEIGHT }, + Child = lobby = new Lobby(), + }, + new Header(lobby), + }; + + lobby.Exited += s => Exit(); + } + + protected override void OnEntering(Screen last) + { + base.OnEntering(last); + waves.Show(); + } + + protected override bool OnExiting(Screen next) + { + waves.Hide(); + return base.OnExiting(next); + } + + protected override void OnResuming(Screen last) + { + base.OnResuming(last); + waves.Show(); + } + + protected override void OnSuspending(Screen next) + { + base.OnSuspending(next); + waves.Hide(); + } + + private class MultiplayerWaveContainer : WaveContainer + { + protected override bool StartHidden => true; + + public MultiplayerWaveContainer() + { + FirstWaveColour = OsuColour.FromHex(@"654d8c"); + SecondWaveColour = OsuColour.FromHex(@"554075"); + ThirdWaveColour = OsuColour.FromHex(@"44325e"); + FourthWaveColour = OsuColour.FromHex(@"392850"); + } + } + } +} From 8e053f2166a00f96865713d7c8b1d6a5532972ac Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 15 May 2018 21:20:34 -0300 Subject: [PATCH 175/302] Add multiplayer screen test steps. --- osu.Game.Tests/Visual/TestCaseMultiScreen.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs index 2dd3e81ee1..6c22fb020f 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs @@ -11,7 +11,11 @@ namespace osu.Game.Tests.Visual { public TestCaseMultiScreen() { - Child = new Multiplayer(); + Multiplayer multi = new Multiplayer(); + + AddStep(@"show", () => Add(multi)); + AddWaitStep(5); + AddStep(@"exit", multi.Exit); } } } From edbb3a5a57448e1bde365f7df4a7265d8610c07a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 12:44:11 +0900 Subject: [PATCH 176/302] Rename to use new hit result namings --- .../Difficulty/ManiaPerformanceCalculator.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index f5f815d9fb..e6e3028d62 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -18,11 +18,11 @@ namespace osu.Game.Rulesets.Mania.Difficulty // Score after being scaled by non-difficulty-increasing mods private double scaledScore; - private int countGeki; - private int countKatu; - private int count300; - private int count100; - private int count50; + private int countPerfect; + private int countGreat; + private int countGood; + private int countOk; + private int countMeh; private int countMiss; public ManiaPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) @@ -34,11 +34,11 @@ namespace osu.Game.Rulesets.Mania.Difficulty { mods = Score.Mods; scaledScore = Score.TotalScore; - countGeki = Convert.ToInt32(Score.Statistics[HitResult.Perfect]); - countKatu = Convert.ToInt32(Score.Statistics[HitResult.Ok]); - count300 = Convert.ToInt32(Score.Statistics[HitResult.Great]); - count100 = Convert.ToInt32(Score.Statistics[HitResult.Good]); - count50 = Convert.ToInt32(Score.Statistics[HitResult.Meh]); + countPerfect = Convert.ToInt32(Score.Statistics[HitResult.Perfect]); + countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); + countOk = Convert.ToInt32(Score.Statistics[HitResult.Ok]); + countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); if (mods.Any(m => !m.Ranked)) @@ -105,13 +105,13 @@ namespace osu.Game.Rulesets.Mania.Difficulty private double computeAccuracyValue(double strainValue) { - double hitWindow300 = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; - if (hitWindow300 <= 0) + double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + if (hitWindowGreat <= 0) return 0; // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Max(0.0, 0.2 - (hitWindow300 - 34) * 0.006667) + double accuracyValue = Math.Max(0.0, 0.2 - (hitWindowGreat - 34) * 0.006667) * strainValue * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); @@ -121,6 +121,6 @@ namespace osu.Game.Rulesets.Mania.Difficulty return accuracyValue; } - private double totalHits => countGeki + countKatu + count300 + count100 + count50 + countMiss; + private double totalHits => countPerfect + countOk + countGreat + countGood + countMeh + countMiss; } } From c1d9fcc140509ec4022f7c6d44449f31d8a0fbab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 12:46:31 +0900 Subject: [PATCH 177/302] Make OsuPerformanceCalculator use the new hitresult namings --- .../Scoring/OsuPerformanceCalculator.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index 938060a664..84a83d331b 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -32,9 +32,9 @@ namespace osu.Game.Rulesets.Osu.Scoring private double accuracy; private int scoreMaxCombo; - private int count300; - private int count100; - private int count50; + private int countGreat; + private int countGood; + private int countMeh; private int countMiss; public OsuPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) @@ -52,9 +52,9 @@ namespace osu.Game.Rulesets.Osu.Scoring mods = Score.Mods; accuracy = Score.Accuracy; scoreMaxCombo = Score.MaxCombo; - count300 = Convert.ToInt32(Score.Statistics[HitResult.Great]); - count100 = Convert.ToInt32(Score.Statistics[HitResult.Good]); - count50 = Convert.ToInt32(Score.Statistics[HitResult.Meh]); + countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); + countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); // Don't count scores made with supposedly unranked mods @@ -71,10 +71,10 @@ namespace osu.Game.Rulesets.Osu.Scoring ar = Math.Max(0, ar / 2); double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate; - double hitWindow300 = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; - realOverallDifficulty = (80 - 0.5 - hitWindow300) / 6; + realOverallDifficulty = (80 - 0.5 - hitWindowGreat) / 6; // Custom multipliers for NoFail and SpunOut. double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things @@ -190,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Scoring int amountHitObjectsWithAccuracy = countHitCircles; if (amountHitObjectsWithAccuracy > 0) - betterAccuracyPercentage = ((count300 - (totalHits - amountHitObjectsWithAccuracy)) * 6 + count100 * 2 + count50) / (amountHitObjectsWithAccuracy * 6); + betterAccuracyPercentage = ((countGreat - (totalHits - amountHitObjectsWithAccuracy)) * 6 + countGood * 2 + countMeh) / (amountHitObjectsWithAccuracy * 6); else betterAccuracyPercentage = 0; @@ -213,7 +213,7 @@ namespace osu.Game.Rulesets.Osu.Scoring return accuracyValue; } - private double totalHits => count300 + count100 + count50 + countMiss; - private double totalSuccessfulHits => count300 + count100 + count50; + private double totalHits => countGreat + countGood + countMeh + countMiss; + private double totalSuccessfulHits => countGreat + countGood + countMeh; } } From 8d8b7e6fa2d3332575a2280704ddeb493a1f81cc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 13:09:48 +0900 Subject: [PATCH 178/302] Fix conversion tests for ruleset-specific beatmaps not working TRuleset was a mistake. This resulted in cases that checked whether the beatmap was for the current ruleset (TaikoBeatmapConverter and ManiaBeatmapConverter) failing due to TestXRuleset != XRuleset... --- .../CatchBeatmapConversionTest.cs | 10 ++-------- .../ManiaBeatmapConversionTest.cs | 10 ++-------- .../OsuBeatmapConversionTest.cs | 10 ++-------- .../TaikoBeatmapConversionTest.cs | 10 ++-------- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 9 ++++----- 5 files changed, 12 insertions(+), 37 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 808faa511b..5b34e46247 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects; @@ -14,7 +12,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Catch.Tests { - internal class CatchBeatmapConversionTest : BeatmapConversionTest + internal class CatchBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Catch"; @@ -47,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Tests } } - protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); + protected override Ruleset CreateRuleset() => new CatchRuleset(); } internal struct ConvertValue : IEquatable @@ -64,8 +62,4 @@ namespace osu.Game.Rulesets.Catch.Tests => Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience) && Precision.AlmostEquals(Position, other.Position, conversion_lenience); } - - internal class TestCatchRuleset : CatchRuleset - { - } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index bd67a7d96a..5ae899f6d6 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -14,7 +12,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Mania.Tests { - internal class ManiaBeatmapConversionTest : BeatmapConversionTest + internal class ManiaBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; @@ -35,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Tests }; } - protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); + protected override Ruleset CreateRuleset() => new ManiaRuleset(); } internal struct ConvertValue : IEquatable @@ -54,8 +52,4 @@ namespace osu.Game.Rulesets.Mania.Tests && Precision.AlmostEquals(EndTime, other.EndTime, conversion_lenience) && Column == other.Column; } - - internal class TestManiaRuleset : ManiaRuleset - { - } } diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index 3d54043027..386ae5eb05 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -5,17 +5,15 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Tests.Beatmaps; using OpenTK; namespace osu.Game.Rulesets.Osu.Tests { - internal class OsuBeatmapConversionTest : BeatmapConversionTest + internal class OsuBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; @@ -42,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Tests }; } - protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); + protected override Ruleset CreateRuleset() => new OsuRuleset(); } internal struct ConvertValue : IEquatable @@ -67,8 +65,4 @@ namespace osu.Game.Rulesets.Osu.Tests && Precision.AlmostEquals(EndX, other.EndX, conversion_lenience) && Precision.AlmostEquals(EndY, other.EndY, conversion_lenience); } - - internal class TestOsuRuleset : OsuRuleset - { - } } diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index ca4fc3ec57..93f1b7faf7 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -5,16 +5,14 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Taiko.Tests { - internal class TaikoBeatmapConversionTest : BeatmapConversionTest + internal class TaikoBeatmapConversionTest : BeatmapConversionTest { protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko"; @@ -40,7 +38,7 @@ namespace osu.Game.Rulesets.Taiko.Tests }; } - protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); + protected override Ruleset CreateRuleset() => new TaikoRuleset(); } internal struct ConvertValue : IEquatable @@ -67,8 +65,4 @@ namespace osu.Game.Rulesets.Taiko.Tests && IsSwell == other.IsSwell && IsStrong == other.IsStrong; } - - internal class TestTaikoRuleset : TaikoRuleset - { - } } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 2de38d49a9..7470f6ebed 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -16,8 +16,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Tests.Beatmaps { [TestFixture] - public abstract class BeatmapConversionTest - where TRuleset : Ruleset, new() + public abstract class BeatmapConversionTest where TConvertValue : IEquatable { private const string resource_namespace = "Testing.Beatmaps"; @@ -81,12 +80,12 @@ namespace osu.Game.Tests.Beatmaps { var beatmap = getBeatmap(name); - var rulesetInstance = new TRuleset(); + var rulesetInstance = CreateRuleset(); beatmap.BeatmapInfo.Ruleset = beatmap.BeatmapInfo.RulesetID == rulesetInstance.RulesetInfo.ID ? rulesetInstance.RulesetInfo : new RulesetInfo(); var result = new ConvertResult(); - var converter = CreateConverter(beatmap); + var converter = rulesetInstance.CreateBeatmapConverter(beatmap); converter.ObjectConverted += (orig, converted) => { converted.ForEach(h => h.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty)); @@ -130,7 +129,7 @@ namespace osu.Game.Tests.Beatmaps } protected abstract IEnumerable CreateConvertValue(HitObject hitObject); - protected abstract IBeatmapConverter CreateConverter(IBeatmap beatmap); + protected abstract Ruleset CreateRuleset(); private class ConvertMapping { From cf44357bdb1f4f6f6f4bce4e136e3ac872a12a55 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 13:30:48 +0900 Subject: [PATCH 179/302] Use a stable sort for hitobjects --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 655355913c..7317c7a135 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -56,7 +56,7 @@ namespace osu.Game.Beatmaps.Formats // objects may be out of order *only* if a user has manually edited an .osu file. // unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828). - this.beatmap.HitObjects.Sort((x, y) => x.StartTime.CompareTo(y.StartTime)); + this.beatmap.HitObjects = this.beatmap.HitObjects.OrderBy(h => h.StartTime).ToList(); foreach (var hitObject in this.beatmap.HitObjects) hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.BeatmapInfo.BaseDifficulty); From 0f817d18d4cfb1e17ff7a547ad284819cdb4829a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 13:59:51 +0900 Subject: [PATCH 180/302] Add explanatory comment --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 7317c7a135..2aee419d20 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -54,8 +54,10 @@ namespace osu.Game.Beatmaps.Formats base.ParseStreamInto(stream, beatmap); - // objects may be out of order *only* if a user has manually edited an .osu file. - // unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828). + // Objects may be out of order *only* if a user has manually edited an .osu file. + // Unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828). + // OrderBy is used to guarantee that the parsing order of hitobjects with equal start times is maintained (stably-sorted) + // The parsing order of hitobjects matters in mania difficulty calculation this.beatmap.HitObjects = this.beatmap.HitObjects.OrderBy(h => h.StartTime).ToList(); foreach (var hitObject in this.beatmap.HitObjects) From 5aadc35a25ebdd5f9233e7d16c93378fdbfa26df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 14:47:28 +0900 Subject: [PATCH 181/302] Stably-sort difficulty hitobjects to prevent future issues --- .../Difficulty/ManiaDifficultyCalculator.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index ac45130fd8..1483283283 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mania.Beatmaps; @@ -49,11 +50,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty int columnCount = (Beatmap as ManiaBeatmap)?.TotalColumns ?? 7; - foreach (var hitObject in Beatmap.HitObjects) - difficultyHitObjects.Add(new ManiaHitObjectDifficulty((ManiaHitObject)hitObject, columnCount)); - // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. - difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); + // Note: Stable sort is done so that the ordering of hitobjects with equal start times doesn't change + difficultyHitObjects.AddRange(Beatmap.HitObjects.Select(h => new ManiaHitObjectDifficulty((ManiaHitObject)h, columnCount)).OrderBy(h => h.BaseHitObject.StartTime)); if (!calculateStrainValues()) return 0; From 2fc1939d650f8187d97155455a2dff4350f9a76e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 19:43:01 +0900 Subject: [PATCH 182/302] Fix hold notes never dying --- .../Judgements/HoldNoteJudgement.cs | 13 +++++++++++++ .../Objects/Drawables/DrawableHoldNote.cs | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs new file mode 100644 index 0000000000..9630ba9273 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mania.Judgements +{ + public class HoldNoteJudgement : ManiaJudgement + { + public override bool AffectsCombo => false; + protected override int NumericResultFor(HitResult result) => 0; + } +} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index f8b2311a13..3661c0be04 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -99,6 +99,19 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void UpdateState(ArmedState state) { + switch (state) + { + case ArmedState.Hit: + // Good enough for now, we just want them to have a lifetime end + this.Delay(2000).Expire(); + break; + } + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (tail.AllJudged) + AddJudgement(new HoldNoteJudgement { Result = HitResult.Perfect }); } protected override void Update() From c67f37256023dfdef5bfabba951adbac330785a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 12:29:33 +0900 Subject: [PATCH 183/302] Don't create nested hitobjects unless absolutely required --- osu.Game/Rulesets/Objects/HitObject.cs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index cd612a5387..15c24e2975 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.Extensions.IEnumerableExtensions; @@ -56,10 +57,10 @@ namespace osu.Game.Rulesets.Objects /// public HitWindows HitWindows { get; set; } - private readonly SortedList nestedHitObjects = new SortedList((h1, h2) => h1.StartTime.CompareTo(h2.StartTime)); + private readonly Lazy> nestedHitObjects = new Lazy>(() => new SortedList((h1, h2) => h1.StartTime.CompareTo(h2.StartTime))); [JsonIgnore] - public IReadOnlyList NestedHitObjects => nestedHitObjects; + public IReadOnlyList NestedHitObjects => nestedHitObjects.Value; /// /// Applies default values to this HitObject. @@ -70,13 +71,19 @@ namespace osu.Game.Rulesets.Objects { ApplyDefaultsToSelf(controlPointInfo, difficulty); - nestedHitObjects.Clear(); + if (nestedHitObjects.IsValueCreated) + nestedHitObjects.Value.Clear(); + CreateNestedHitObjects(); - nestedHitObjects.ForEach(h => + + if (nestedHitObjects.IsValueCreated) { - h.HitWindows = HitWindows; - h.ApplyDefaults(controlPointInfo, difficulty); - }); + nestedHitObjects.Value.ForEach(h => + { + h.HitWindows = HitWindows; + h.ApplyDefaults(controlPointInfo, difficulty); + }); + } } protected virtual void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) @@ -96,7 +103,7 @@ namespace osu.Game.Rulesets.Objects { } - protected void AddNested(HitObject hitObject) => nestedHitObjects.Add(hitObject); + protected void AddNested(HitObject hitObject) => nestedHitObjects.Value.Add(hitObject); /// /// Creates the for this . From 397d93660aad78e1ba4a759c48d28b54ba99d7cd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 12:59:48 +0900 Subject: [PATCH 184/302] Don't deep-clone beatmapinfo/control points --- .../Beatmaps/TaikoBeatmapConverter.cs | 6 +++--- osu.Game/Beatmaps/Beatmap.cs | 11 ++--------- osu.Game/Beatmaps/BeatmapConverter.cs | 2 -- osu.Game/Beatmaps/BeatmapDifficulty.cs | 5 +++++ osu.Game/Beatmaps/BeatmapInfo.cs | 5 +++++ osu.Game/IO/Serialization/IJsonSerializable.cs | 2 -- .../UI/Scrolling/ScrollingRulesetContainer.cs | 3 +-- 7 files changed, 16 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index b450e4d26c..abb2193235 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -8,7 +8,6 @@ using osu.Game.Rulesets.Taiko.Objects; using System; using System.Collections.Generic; using System.Linq; -using osu.Game.IO.Serialization; using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; @@ -51,8 +50,9 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps protected override Beatmap ConvertBeatmap(IBeatmap original) { // Rewrite the beatmap info to add the slider velocity multiplier - BeatmapInfo info = original.BeatmapInfo.DeepClone(); - info.BaseDifficulty.SliderMultiplier *= legacy_velocity_multiplier; + original.BeatmapInfo = original.BeatmapInfo.Clone(); + original.BeatmapInfo.BaseDifficulty = original.BeatmapInfo.BaseDifficulty.Clone(); + original.BeatmapInfo.BaseDifficulty.SliderMultiplier *= legacy_velocity_multiplier; Beatmap converted = base.ConvertBeatmap(original); diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 84897853d8..9aabb434a3 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Objects; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.IO.Serialization; using Newtonsoft.Json; using osu.Game.IO.Serialization.Converters; @@ -55,17 +54,11 @@ namespace osu.Game.Beatmaps IBeatmap IBeatmap.Clone() => Clone(); - public Beatmap Clone() - { - var newInstance = (Beatmap)MemberwiseClone(); - newInstance.BeatmapInfo = BeatmapInfo.DeepClone(); - - return newInstance; - } + public Beatmap Clone() => (Beatmap)MemberwiseClone(); } public class Beatmap : Beatmap { - public Beatmap Clone() => (Beatmap)base.Clone(); + public new Beatmap Clone() => (Beatmap)base.Clone(); } } diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index b7a454460f..a1bb70135a 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -53,8 +53,6 @@ namespace osu.Game.Beatmaps { var beatmap = CreateBeatmap(); - // todo: this *must* share logic (or directly use) Beatmap's constructor. - // right now this isn't easily possible due to generic entanglement. beatmap.BeatmapInfo = original.BeatmapInfo; beatmap.ControlPointInfo = original.ControlPointInfo; beatmap.HitObjects = original.HitObjects.SelectMany(h => convert(h, original)).ToList(); diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index 855e8fe881..508232dbfe 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -32,6 +32,11 @@ namespace osu.Game.Beatmaps public double SliderMultiplier { get; set; } = 1; public double SliderTickRate { get; set; } = 1; + /// + /// Returns a shallow-clone of this . + /// + public BeatmapDifficulty Clone() => (BeatmapDifficulty)MemberwiseClone(); + /// /// Maps a difficulty value [0, 10] to a two-piece linear range of values. /// diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index a1b97afc6c..40d62103a8 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -143,5 +143,10 @@ namespace osu.Game.Beatmaps public bool BackgroundEquals(BeatmapInfo other) => other != null && BeatmapSet != null && other.BeatmapSet != null && BeatmapSet.Hash == other.BeatmapSet.Hash && (Metadata ?? BeatmapSet.Metadata).BackgroundFile == (other.Metadata ?? other.BeatmapSet.Metadata).BackgroundFile; + + /// + /// Returns a shallow-clone of this . + /// + public BeatmapInfo Clone() => (BeatmapInfo)MemberwiseClone(); } } diff --git a/osu.Game/IO/Serialization/IJsonSerializable.cs b/osu.Game/IO/Serialization/IJsonSerializable.cs index c9727725ef..ce6ff7c82d 100644 --- a/osu.Game/IO/Serialization/IJsonSerializable.cs +++ b/osu.Game/IO/Serialization/IJsonSerializable.cs @@ -18,8 +18,6 @@ namespace osu.Game.IO.Serialization public static void DeserializeInto(this string objString, T target) => JsonConvert.PopulateObject(objString, target, CreateGlobalSettings()); - public static T DeepClone(this T obj) where T : IJsonSerializable => Deserialize(Serialize(obj)); - /// /// Creates the default that should be used for all s. /// diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index efd901240a..3fc67e4e34 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -8,7 +8,6 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Lists; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.IO.Serialization; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; @@ -104,7 +103,7 @@ namespace osu.Game.Rulesets.UI.Scrolling if (index < 0) return new MultiplierControlPoint(time); - return new MultiplierControlPoint(time, DefaultControlPoints[index].DeepClone()); + return new MultiplierControlPoint(time, DefaultControlPoints[index]); } } } From f67d2635960ac1ca37a7297f02b255b3f47ac413 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 13:35:06 +0900 Subject: [PATCH 185/302] Move ruleset-specific hitwindows to post-converted hitobjects --- .../Beatmaps/ManiaBeatmapConverter.cs | 3 --- .../Objects/ManiaHitObject.cs | 10 +--------- .../Objects/ManiaHitWindows.cs | 8 ++++++-- .../Beatmaps/OsuBeatmapConverter.cs | 9 +++------ osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 2 ++ .../Objects/OsuHitWindows.cs | 5 +++-- .../Beatmaps/TaikoBeatmapConverter.cs | 18 ++++++------------ .../Objects/TaikoHitObject.cs | 2 ++ .../Objects/TaikoHitWindows.cs | 5 +++-- .../Objects/Legacy/Mania/ConvertHit.cs | 2 +- .../Objects/Legacy/Mania/ConvertHold.cs | 2 +- .../Objects/Legacy/Mania/ConvertSlider.cs | 2 +- .../Objects/Legacy/Mania/ConvertSpinner.cs | 2 +- .../Rulesets/Objects/Legacy/Osu/ConvertHit.cs | 2 +- .../Objects/Legacy/Osu/ConvertSlider.cs | 2 +- .../Objects/Legacy/Osu/ConvertSpinner.cs | 2 +- .../Objects/Legacy/Taiko/ConvertHit.cs | 2 +- .../Objects/Legacy/Taiko/ConvertSlider.cs | 2 +- .../Objects/Legacy/Taiko/ConvertSpinner.cs | 2 +- 19 files changed, 36 insertions(+), 46 deletions(-) rename osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitWindows.cs => osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs (88%) rename osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitWindows.cs => osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs (90%) rename osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitWindows.cs => osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs (90%) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 4f7c52860f..19fef9eb54 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -84,10 +84,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps yield break; foreach (ManiaHitObject obj in objects) - { - obj.HitWindows = original.HitWindows; yield return obj; - } } private readonly List prevNoteTimes = new List(max_notes_for_density); diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index 4f0e02ff0d..e183098a51 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects.Types; using osu.Game.Rulesets.Objects; @@ -12,12 +10,6 @@ namespace osu.Game.Rulesets.Mania.Objects { public virtual int Column { get; set; } - protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) - { - base.ApplyDefaultsToSelf(controlPointInfo, difficulty); - - HitWindows.AllowsPerfect = true; - HitWindows.AllowsOk = true; - } + protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitWindows.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs similarity index 88% rename from osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitWindows.cs rename to osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs index 131492ea12..063b626af1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitWindows.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs @@ -3,11 +3,12 @@ using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; -namespace osu.Game.Rulesets.Objects.Legacy.Mania +namespace osu.Game.Rulesets.Mania.Objects { - public class ConvertHitWindows : HitWindows + public class ManiaHitWindows : HitWindows { private static readonly IReadOnlyDictionary base_ranges = new Dictionary { @@ -21,6 +22,9 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public override void SetDifficulty(double difficulty) { + AllowsPerfect = true; + AllowsOk = true; + Perfect = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Perfect]); Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 4369a31b2c..80eb808f6e 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -40,8 +40,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps RepeatSamples = curveData.RepeatSamples, RepeatCount = curveData.RepeatCount, Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false, - HitWindows = original.HitWindows + NewCombo = comboData?.NewCombo ?? false }; } else if (endTimeData != null) @@ -51,8 +50,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps StartTime = original.StartTime, Samples = original.Samples, EndTime = endTimeData.EndTime, - Position = positionData?.Position ?? OsuPlayfield.BASE_SIZE / 2, - HitWindows = original.HitWindows + Position = positionData?.Position ?? OsuPlayfield.BASE_SIZE / 2 }; } else @@ -62,8 +60,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps StartTime = original.StartTime, Samples = original.Samples, Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false, - HitWindows = original.HitWindows + NewCombo = comboData?.NewCombo ?? false }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 2b7b7783e2..54126b934f 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -71,5 +71,7 @@ namespace osu.Game.Rulesets.Osu.Objects } public virtual void OffsetPosition(Vector2 offset) => Position += offset; + + protected override HitWindows CreateHitWindows() => new OsuHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitWindows.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs similarity index 90% rename from osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitWindows.cs rename to osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs index fd86173372..8405498554 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitWindows.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs @@ -3,11 +3,12 @@ using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; -namespace osu.Game.Rulesets.Objects.Legacy.Osu +namespace osu.Game.Rulesets.Osu.Objects { - public class ConvertHitWindows : HitWindows + public class OsuHitWindows : HitWindows { private static readonly IReadOnlyDictionary base_ranges = new Dictionary { diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index b450e4d26c..a84b1a64a0 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -132,8 +132,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { StartTime = j, Samples = currentSamples, - IsStrong = strong, - HitWindows = obj.HitWindows + IsStrong = strong }; } else @@ -142,8 +141,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { StartTime = j, Samples = currentSamples, - IsStrong = strong, - HitWindows = obj.HitWindows + IsStrong = strong }; } @@ -158,8 +156,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps Samples = obj.Samples, IsStrong = strong, Duration = taikoDuration, - TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4, - HitWindows = obj.HitWindows + TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4 }; } } @@ -173,8 +170,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps Samples = obj.Samples, IsStrong = strong, Duration = endTimeData.Duration, - RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier), - HitWindows = obj.HitWindows + RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier) }; } else @@ -187,8 +183,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { StartTime = obj.StartTime, Samples = obj.Samples, - IsStrong = strong, - HitWindows = obj.HitWindows + IsStrong = strong }; } else @@ -197,8 +192,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { StartTime = obj.StartTime, Samples = obj.Samples, - IsStrong = strong, - HitWindows = obj.HitWindows + IsStrong = strong }; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 63de096238..ffbbe28f2e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -27,5 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Objects /// Strong hit objects give more points for hitting the hit object with both keys. /// public bool IsStrong; + + protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitWindows.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs similarity index 90% rename from osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitWindows.cs rename to osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs index 6fbf7e122f..289f084a45 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs @@ -3,11 +3,12 @@ using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; -namespace osu.Game.Rulesets.Objects.Legacy.Taiko +namespace osu.Game.Rulesets.Taiko.Objects { - public class ConvertHitWindows : HitWindows + public class TaikoHitWindows : HitWindows { private static readonly IReadOnlyDictionary base_ranges = new Dictionary { diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 939d3b9c93..ea4e7f6907 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index 22abc64b60..86a10fd363 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public double Duration => EndTime - StartTime; - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index 6bca5b717c..a8d7b23df1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index 1dc826af9b..5a443c2ac2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public float X { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index 23955b2d23..f015272b2c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index 35b8c1c7dd..ec5a002bbb 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index 73b8369aca..0141785f31 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -21,6 +21,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public float Y => Position.Y; - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index 11db086778..5e9786c84a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko { public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index 95c69222b5..8a9a0db0a7 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko { public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index 7baea212ea..4c8807a1d3 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko public double Duration => EndTime - StartTime; - protected override HitWindows CreateHitWindows() => new ConvertHitWindows(); + protected override HitWindows CreateHitWindows() => null; } } From 43cdbec0a3f78d612e901b703803abfb67e3e685 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 13:59:04 +0900 Subject: [PATCH 186/302] Fix hold note hitwindow lenience --- .../Objects/Drawables/DrawableHoldNote.cs | 10 ++++++ osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 22 +----------- osu.Game/Rulesets/Objects/HitWindows.cs | 34 ------------------- 3 files changed, 11 insertions(+), 55 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index f8b2311a13..59808c5643 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -191,6 +191,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// private class DrawableTailNote : DrawableNote { + /// + /// Lenience of release hit windows. This is to make cases where the hold note release + /// is timed alongside presses of other hit objects less awkward. + /// Todo: This shouldn't exist for non-LegacyBeatmapDecoder beatmaps + /// + private const double release_window_lenience = 1.5; + private readonly DrawableHoldNote holdNote; public DrawableTailNote(DrawableHoldNote holdNote, ManiaAction action) @@ -203,6 +210,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { + // Factor in the release lenience + timeOffset /= release_window_lenience; + if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 12e3d2de51..22fa93a308 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// /// The tail note of the hold. /// - public readonly Note Tail = new TailNote(); + public readonly Note Tail = new Note(); /// /// The time between ticks of this hold. @@ -94,25 +94,5 @@ namespace osu.Game.Rulesets.Mania.Objects }); } } - - /// - /// The tail of the hold note. - /// - private class TailNote : Note - { - /// - /// Lenience of release hit windows. This is to make cases where the hold note release - /// is timed alongside presses of other hit objects less awkward. - /// Todo: This shouldn't exist for non-LegacyBeatmapDecoder beatmaps - /// - private const double release_window_lenience = 1.5; - - protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) - { - base.ApplyDefaultsToSelf(controlPointInfo, difficulty); - - HitWindows *= release_window_lenience; - } - } } } diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index 7610593d6a..3717209860 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -135,39 +135,5 @@ namespace osu.Game.Rulesets.Objects /// The time offset. /// Whether the can be hit at any point in the future from this time offset. public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(HitResult.Meh); - - /// - /// Multiplies all hit windows by a value. - /// - /// The hit windows to multiply. - /// The value to multiply each hit window by. - public static HitWindows operator *(HitWindows windows, double value) - { - windows.Perfect *= value; - windows.Great *= value; - windows.Good *= value; - windows.Ok *= value; - windows.Meh *= value; - windows.Miss *= value; - - return windows; - } - - /// - /// Divides all hit windows by a value. - /// - /// The hit windows to divide. - /// The value to divide each hit window by. - public static HitWindows operator /(HitWindows windows, double value) - { - windows.Perfect /= value; - windows.Great /= value; - windows.Good /= value; - windows.Ok /= value; - windows.Meh /= value; - windows.Miss /= value; - - return windows; - } } } From b9ed9769546fd05cb8c1413c480054762042a84f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 14:44:30 +0900 Subject: [PATCH 187/302] Fix taiko slider multiplier being applied twice --- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index abb2193235..304fd290fc 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -98,12 +98,12 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps double distance = distanceData.Distance * spans * legacy_velocity_multiplier; // The velocity of the taiko hit object - calculated as the velocity of a drum roll - double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier * legacy_velocity_multiplier / speedAdjustedBeatLength; + double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; // The duration of the taiko hit object double taikoDuration = distance / taikoVelocity; // The velocity of the osu! hit object - calculated as the velocity of a slider - double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier * legacy_velocity_multiplier / speedAdjustedBeatLength; + double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; // The duration of the osu! hit object double osuDuration = distance / osuVelocity; From 532d65f6e8aa5c8383413e3c4726d5200429c1aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 15:17:47 +0900 Subject: [PATCH 188/302] Re-enable basic taiko beatmap conversion tests --- osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 93f1b7faf7..11586e340b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -17,8 +17,8 @@ namespace osu.Game.Rulesets.Taiko.Tests protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko"; [NonParallelizable] - [TestCase("basic", false), Ignore("See: https://github.com/ppy/osu/issues/2152")] - [TestCase("slider-generating-drumroll", false)] + [TestCase("basic")] + [TestCase("slider-generating-drumroll")] public new void Test(string name) { base.Test(name); From eba1d309b674eb42d16486ea603859a4e94174ed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 16:58:22 +0900 Subject: [PATCH 189/302] Fix incorrect namespace of OsuPerformanceCalculator --- .../{Scoring => Difficulty}/OsuPerformanceCalculator.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) rename osu.Game.Rulesets.Osu/{Scoring => Difficulty}/OsuPerformanceCalculator.cs (99%) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs similarity index 99% rename from osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs rename to osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 84a83d331b..eeb776fa6e 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; -namespace osu.Game.Rulesets.Osu.Scoring +namespace osu.Game.Rulesets.Osu.Difficulty { public class OsuPerformanceCalculator : PerformanceCalculator { diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index a2423ffbe5..c455bb2af6 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics; using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; 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.Osu.Replays; From d20011ba58a849c0cca543b13149458d03f05f39 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 May 2018 17:56:25 +0900 Subject: [PATCH 190/302] Fix an endless feedback loop --- osu.Game/Screens/Select/MatchSongSelect.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 4e252eac75..3ffac591f3 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -7,7 +7,12 @@ namespace osu.Game.Screens.Select { protected override bool OnSelectionFinalised() { - Exit(); + Schedule(() => + { + // needs to be scheduled else we enter an infinite feedback loop. + if (IsCurrentScreen) Exit(); + }); + return true; } } From 450d54eea9ccafce0df2ec8f1ad0c816be4fa6a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 17:12:28 +0900 Subject: [PATCH 191/302] Fix taiko difficulty calculator never considering mods --- .../Difficulty/TaikoDifficultyCalculator.cs | 6 ++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index acff0d286d..d33150d739 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Difficulty @@ -35,6 +36,11 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { } + public TaikoDifficultyCalculator(IBeatmap beatmap, Mod[] mods) + : base(beatmap, mods) + { + } + public override double Calculate(Dictionary categoryDifficulty = null) { // Fill our custom DifficultyHitObject class, that carries additional information diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 35dc17c0e2..04b513866a 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.Taiko public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o }; - public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap); + public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap, mods); public override int? LegacyID => 1; From 3091d3a01450a1185ba346d813f46c0de1658f18 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 May 2018 17:40:46 +0900 Subject: [PATCH 192/302] Implement the taiko performance calculator --- .../Difficulty/TaikoDifficultyCalculator.cs | 5 +- .../Difficulty/TaikoPerformanceCalculator.cs | 111 ++++++++++++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 3 + 3 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index d33150d739..57e1e65064 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -57,10 +57,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty double starRating = calculateDifficulty() * star_scaling_factor; if (categoryDifficulty != null) - { - categoryDifficulty.Add("Strain", starRating); - categoryDifficulty.Add("Hit window 300", 35 /*HitObjectManager.HitWindow300*/ / TimeRate); - } + categoryDifficulty["Strain"] = starRating; return starRating; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs new file mode 100644 index 0000000000..9c9cd1f0fb --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -0,0 +1,111 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Difficulty +{ + public class TaikoPerformanceCalculator : PerformanceCalculator + { + private readonly int beatmapMaxCombo; + + private Mod[] mods; + private int countGreat; + private int countGood; + private int countMeh; + private int countMiss; + + public TaikoPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) + : base(ruleset, beatmap, score) + { + beatmapMaxCombo = beatmap.HitObjects.Count(h => h is Hit); + } + + public override double Calculate(Dictionary categoryDifficulty = null) + { + mods = Score.Mods; + countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); + countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); + countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); + + // Don't count scores made with supposedly unranked mods + if (mods.Any(m => !m.Ranked)) + return 0; + + // Custom multipliers for NoFail and SpunOut. + double multiplier = 1.1; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things + + if (mods.Any(m => m is ModNoFail)) + multiplier *= 0.90; + + if (mods.Any(m => m is ModHidden)) + multiplier *= 1.10; + + double strainValue = computeStrainValue(); + double accuracyValue = computeAccuracyValue(); + double totalValue = + Math.Pow( + Math.Pow(strainValue, 1.1) + + Math.Pow(accuracyValue, 1.1), 1.0 / 1.1 + ) * multiplier; + + if (categoryDifficulty != null) + { + categoryDifficulty["Strain"] = strainValue; + categoryDifficulty["Accuracy"] = accuracyValue; + } + + return totalValue; + } + + private double computeStrainValue() + { + double strainValue = Math.Pow(5.0 * Math.Max(1.0, Attributes["Strain"] / 0.0075) - 4.0, 2.0) / 100000.0; + + // Longer maps are worth more + double lengthBonus = 1 + 0.1f * Math.Min(1.0, totalHits / 1500.0); + strainValue *= lengthBonus; + + // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available + strainValue *= Math.Pow(0.985, countMiss); + + // Combo scaling + if (beatmapMaxCombo > 0) + strainValue *= Math.Min(Math.Pow(Score.MaxCombo, 0.5) / Math.Pow(beatmapMaxCombo, 0.5), 1.0); + + if (mods.Any(m => m is ModHidden)) + strainValue *= 1.025; + + if (mods.Any(m => m is ModFlashlight)) + // Apply length bonus again if flashlight is on simply because it becomes a lot harder on longer maps. + strainValue *= 1.05 * lengthBonus; + + // Scale the speed value with accuracy _slightly_ + return strainValue * Score.Accuracy; + } + + private double computeAccuracyValue() + { + double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + if (hitWindowGreat <= 0) + return 0; + + // Lots of arbitrary values from testing. + // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution + double accValue = Math.Pow(150.0 / hitWindowGreat, 1.1) * Math.Pow(Score.Accuracy, 15) * 22.0; + + // Bonus for many hitcircles - it's harder to keep good accuracy up for longer + return accValue * Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); + } + + private int totalHits => countGreat + countGood + countMeh + countMiss; + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 04b513866a..abaa8db597 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Difficulty; @@ -146,6 +147,8 @@ namespace osu.Game.Rulesets.Taiko public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap, mods); + public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new TaikoPerformanceCalculator(this, beatmap, score); + public override int? LegacyID => 1; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new TaikoReplayFrame(); From ebfbe58abb20c13a36ce18cf1b8ba91a9b413400 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 17 May 2018 06:19:55 -0300 Subject: [PATCH 193/302] Move Header breadcrumbs to a subclass. --- osu.Game/Screens/Multi/Header.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 03996f5309..db8898495f 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Multi public const float HEIGHT = 121; private readonly OsuSpriteText screenTitle; - private readonly ScreenBreadcrumbControl breadcrumbs; + private readonly HeaderBreadcrumbControl breadcrumbs; public Header(Screen initialScreen) { @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Multi }, }, }, - breadcrumbs = new ScreenBreadcrumbControl(initialScreen) + breadcrumbs = new HeaderBreadcrumbControl(initialScreen) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -85,8 +85,6 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.OnLoadComplete = d => breadcrumbs.AccentColour = Color4.White; - breadcrumbs.Current.ValueChanged += s => screenTitle.Text = s.ToString(); breadcrumbs.Current.TriggerChange(); } @@ -97,5 +95,18 @@ namespace osu.Game.Screens.Multi screenTitle.Colour = colours.Yellow; breadcrumbs.StripColour = colours.Green; } + + private class HeaderBreadcrumbControl : ScreenBreadcrumbControl + { + public HeaderBreadcrumbControl(Screen initialScreen) : base(initialScreen) + { + } + + protected override void LoadComplete() + { + base.LoadComplete(); + AccentColour = Color4.White; + } + } } } From 6f94c110a56e975c74417548efbc9841e67c6315 Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Thu, 17 May 2018 23:09:13 +0300 Subject: [PATCH 194/302] Fix submodule conflict --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index e793a08417..fac688633b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e793a084177f53920645c4f6f70cfef91e7fd19e +Subproject commit fac688633b8fcf34ae5d0514c26b03e217161eb4 From 17d1759c37f53893dfdb9c1529206b0f0c2c5083 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 18 May 2018 01:01:54 +0300 Subject: [PATCH 195/302] Get rid of multiple blank lines in a row --- osu.Game/Screens/Menu/ButtonSystem.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 8cf0d24f7d..997002327a 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -185,7 +185,6 @@ namespace osu.Game.Screens.Menu } } - private void onPlay() { State = MenuState.Play; From e2389ad7a4a4e02938bd6eb2157d36cd19e30741 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 May 2018 13:30:36 +0900 Subject: [PATCH 196/302] Allow using back button on PlayerLoader and Replay --- osu.Game/Screens/Play/Player.cs | 2 ++ osu.Game/Screens/Play/PlayerLoader.cs | 1 - osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 4a46279d30..46919e25e1 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -45,6 +45,8 @@ namespace osu.Game.Screens.Play public bool AllowLeadIn { get; set; } = true; public bool AllowResults { get; set; } = true; + protected override bool AllowBackButton => false; + private Bindable mouseWheelDisabled; private Bindable userAudioOffset; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6eb156914e..56fbd7b6e7 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -27,7 +27,6 @@ namespace osu.Game.Screens.Play private bool showOverlays = true; public override bool ShowOverlaysOnEnter => showOverlays; - protected override bool AllowBackButton => false; private Task loadTask; diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index f29f5b328a..1ccc5e2fe8 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -16,7 +16,6 @@ namespace osu.Game.Screens.Play protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); public override bool AllowBeatmapRulesetChange => false; - protected override bool AllowBackButton => false; protected const float BACKGROUND_FADE_DURATION = 800; From d75fe4009afd0663ffcf6198014de748e22a9fef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 May 2018 13:40:35 +0900 Subject: [PATCH 197/302] Add back action support to settings back button --- osu.Game/Overlays/MainSettings.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index 09b5be6a85..99a86f19a1 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -6,9 +6,11 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Input.Bindings; using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings.Sections; using osu.Game.Screens.Ranking; @@ -96,7 +98,7 @@ namespace osu.Game.Overlays }); } - private class BackButton : OsuClickableContainer + private class BackButton : OsuClickableContainer, IKeyBindingHandler { private AspectContainer aspect; @@ -146,6 +148,20 @@ namespace osu.Game.Overlays aspect.ScaleTo(1, 1000, Easing.OutElastic); return base.OnMouseUp(state, args); } + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + TriggerOnClick(); + return true; + } + + return false; + } + + public bool OnReleased(GlobalAction action) => false; } } } From 67db5391729cb62a3461eb3eb448152dc9bc1580 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Fri, 18 May 2018 07:57:12 +0200 Subject: [PATCH 198/302] prevent Overlays from showing in intro/outro sequences --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index f657c0cae5..c26adc8a3d 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using OpenTK; +using osu.Framework.Configuration; namespace osu.Game.Graphics.Containers { @@ -15,13 +16,17 @@ namespace osu.Game.Graphics.Containers private SampleChannel samplePopIn; private SampleChannel samplePopOut; + protected BindableBool ShowOverlays = new BindableBool(); + [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load(OsuGame osuGame, AudioManager audio) { samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in"); samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out"); StateChanged += onStateChanged; + + ShowOverlays.BindTo(osuGame.ShowOverlays); } /// @@ -46,6 +51,9 @@ namespace osu.Game.Graphics.Containers private void onStateChanged(Visibility visibility) { + if (!ShowOverlays) + State = Visibility.Hidden; + switch (visibility) { case Visibility.Visible: From e6e37583045e6981b3c63517be44a1bb08338394 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 May 2018 18:11:52 +0900 Subject: [PATCH 199/302] Fix HR mod affecting original beatmap difficulty Fixes #2575. --- osu.Game/Beatmaps/WorkingBeatmap.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 9c389bbb8f..66a6206c16 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -107,8 +107,14 @@ namespace osu.Game.Beatmaps IBeatmap converted = converter.Convert(); // Apply difficulty mods - foreach (var mod in Mods.Value.OfType()) - mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty); + if (Mods.Value.Any(m => m is IApplicableToDifficulty)) + { + converted.BeatmapInfo = converted.BeatmapInfo.Clone(); + converted.BeatmapInfo.BaseDifficulty = converted.BeatmapInfo.BaseDifficulty.Clone(); + + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty); + } // Post-process rulesetInstance.CreateBeatmapProcessor(converted)?.PostProcess(); From 33baaf8243d04efc276e30a006118a78d68332df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 May 2018 18:44:42 +0900 Subject: [PATCH 200/302] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index fac688633b..80e78fd45b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit fac688633b8fcf34ae5d0514c26b03e217161eb4 +Subproject commit 80e78fd45bb79ca4bc46ecc05deb6058f3879faa From 4b2b2086df821b5889892abe9bae3775f55a2a5e Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Sat, 19 May 2018 01:26:39 -0300 Subject: [PATCH 201/302] Create drawable hierarchy for RoomInspector in load, remove display* methods. --- .../Screens/Multi/Components/RoomInspector.cs | 191 ++++++++---------- 1 file changed, 85 insertions(+), 106 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index 92910e8301..b103624dfb 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -28,14 +28,6 @@ namespace osu.Game.Screens.Multi.Components private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private const float transition_duration = 100; - private readonly Box statusStrip; - private readonly Container coverContainer; - private readonly FillFlowContainer topFlow, participantsFlow; - private readonly ModeTypeInfo modeTypeInfo; - private readonly OsuSpriteText participants, participantsSlash, maxParticipants, name, status, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor; - private readonly ParticipantInfo participantInfo; - private readonly ScrollContainer participantsScroll; - private readonly Bindable nameBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); @@ -44,11 +36,10 @@ namespace osu.Game.Screens.Multi.Components private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable participantsBind = new Bindable(); - private OsuColour colours; - private LocalisationEngine localisation; + private FillFlowContainer topFlow; + private ScrollContainer participantsScroll; private Room room; - public Room Room { get { return room; } @@ -71,6 +62,17 @@ namespace osu.Game.Screens.Multi.Components { Width = 520; RelativeSizeAxes = Axes.Y; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, LocalisationEngine localisation) + { + Box statusStrip; + Container coverContainer; + FillFlowContainer participantsFlow; + ModeTypeInfo modeTypeInfo; + OsuSpriteText participants, participantsSlash, maxParticipants, name, status, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor; + ParticipantInfo participantInfo; Children = new Drawable[] { @@ -229,6 +231,7 @@ namespace osu.Game.Screens.Multi.Components Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, TextSize = 14, + Colour = colours.Gray9, }, }, }, @@ -269,27 +272,83 @@ namespace osu.Game.Screens.Multi.Components }, }; - nameBind.ValueChanged += displayName; - hostBind.ValueChanged += displayUser; - typeBind.ValueChanged += displayGameType; - maxParticipantsBind.ValueChanged += displayMaxParticipants; - participantsBind.ValueChanged += displayParticipants; - } + nameBind.ValueChanged += n => name.Text = n; + hostBind.ValueChanged += h => participantInfo.Host = h; + typeBind.ValueChanged += t => modeTypeInfo.Type = t; - [BackgroundDependencyLoader] - private void load(OsuColour colours, LocalisationEngine localisation) - { - this.localisation = localisation; - this.colours = colours; + statusBind.ValueChanged += s => + { + status.Text = s.Message; - beatmapAuthor.Colour = colours.Gray9; + foreach (Drawable d in new Drawable[] { statusStrip, status }) + d.FadeColour(s.GetAppropriateColour(colours), transition_duration); + }; - //binded here instead of ctor because dependencies are needed - statusBind.ValueChanged += displayStatus; - beatmapBind.ValueChanged += displayBeatmap; + beatmapBind.ValueChanged += b => + { + modeTypeInfo.Beatmap = b; + if (b != null) + { + coverContainer.FadeIn(transition_duration); + + LoadComponentAsync(new BeatmapSetCover(b.BeatmapSet) + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), + }, + coverContainer.Add); + + beatmapTitle.Current = localisation.GetUnicodePreference(b.Metadata.TitleUnicode, b.Metadata.Title); + beatmapDash.Text = @" - "; + beatmapArtist.Current = localisation.GetUnicodePreference(b.Metadata.ArtistUnicode, b.Metadata.Artist); + beatmapAuthor.Text = $"mapped by {b.Metadata.Author}"; + } + else + { + coverContainer.FadeOut(transition_duration); + + beatmapTitle.Current = null; + beatmapArtist.Current = null; + + beatmapTitle.Text = "Changing map"; + beatmapDash.Text = beatmapArtist.Text = beatmapAuthor.Text = string.Empty; + } + }; + + maxParticipantsBind.ValueChanged += m => + { + if (m == null) + { + participantsSlash.FadeOut(transition_duration); + maxParticipants.FadeOut(transition_duration); + } + else + { + participantsSlash.FadeIn(transition_duration); + maxParticipants.FadeIn(transition_duration); + maxParticipants.Text = m.ToString(); + } + }; + + participantsBind.ValueChanged += p => + { + participants.Text = p.Length.ToString(); + participantInfo.Participants = p; + participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u)); + }; + + // trigger incase a room was set before we were loaded + nameBind.TriggerChange(); + hostBind.TriggerChange(); statusBind.TriggerChange(); + typeBind.TriggerChange(); beatmapBind.TriggerChange(); + maxParticipantsBind.TriggerChange(); + participantsBind.TriggerChange(); } protected override void UpdateAfterChildren() @@ -299,86 +358,6 @@ namespace osu.Game.Screens.Multi.Components participantsScroll.Height = DrawHeight - topFlow.DrawHeight; } - private void displayName(string value) - { - name.Text = value; - } - - private void displayUser(User value) - { - participantInfo.Host = value; - } - - private void displayStatus(RoomStatus value) - { - status.Text = value.Message; - - foreach (Drawable d in new Drawable[] { statusStrip, status }) - d.FadeColour(value.GetAppropriateColour(colours), transition_duration); - } - - private void displayGameType(GameType value) - { - modeTypeInfo.Type = value; - } - - private void displayBeatmap(BeatmapInfo value) - { - modeTypeInfo.Beatmap = value; - - if (value != null) - { - coverContainer.FadeIn(transition_duration); - - LoadComponentAsync(new BeatmapSetCover(value.BeatmapSet) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), - }, - coverContainer.Add); - - beatmapTitle.Current = localisation.GetUnicodePreference(value.Metadata.TitleUnicode, value.Metadata.Title); - beatmapDash.Text = @" - "; - beatmapArtist.Current = localisation.GetUnicodePreference(value.Metadata.ArtistUnicode, value.Metadata.Artist); - beatmapAuthor.Text = $"mapped by {value.Metadata.Author}"; - } - else - { - coverContainer.FadeOut(transition_duration); - - beatmapTitle.Current = null; - beatmapArtist.Current = null; - - beatmapTitle.Text = "Changing map"; - beatmapDash.Text = beatmapArtist.Text = beatmapAuthor.Text = string.Empty; - } - } - - private void displayMaxParticipants(int? value) - { - if (value == null) - { - participantsSlash.FadeOut(transition_duration); - maxParticipants.FadeOut(transition_duration); - } - else - { - participantsSlash.FadeIn(transition_duration); - maxParticipants.FadeIn(transition_duration); - maxParticipants.Text = value.ToString(); - } - } - - private void displayParticipants(User[] value) - { - participants.Text = value.Length.ToString(); - participantInfo.Participants = value; - participantsFlow.ChildrenEnumerable = value.Select(u => new UserTile(u)); - } - private class UserTile : Container, IHasTooltip { private readonly User user; From ad878003f7ef6a83cb88d7e98a3d45f1d4f0aeb2 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Sat, 19 May 2018 02:23:09 -0300 Subject: [PATCH 202/302] Add null room support to RoomInspector. --- .../Visual/TestCaseRoomInspector.cs | 8 +- .../Screens/Multi/Components/RoomInspector.cs | 116 ++++++++++++------ 2 files changed, 81 insertions(+), 43 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index cb1425ca69..48756c907b 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual { base.LoadComplete(); - var room = new Room + Room room = new Room { Name = { Value = @"My Awesome Room" }, Host = { Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" } } }, @@ -71,9 +71,11 @@ namespace osu.Game.Tests.Visual { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Room = room, }); + AddStep(@"set room", () => inspector.Room = room); + AddStep(@"null room", () => inspector.Room = null); + AddStep(@"set room", () => inspector.Room = room); AddStep(@"change title", () => room.Name.Value = @"A Better Room Than The Above"); AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } }); AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying()); @@ -88,7 +90,7 @@ namespace osu.Game.Tests.Visual AddStep(@"change room", () => { - var newRoom = new Room + Room newRoom = new Room { Name = { Value = @"My New, Better Than Ever Room" }, Host = { Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" } } }, diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index b103624dfb..b3a6d90e39 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -5,6 +5,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -25,9 +26,9 @@ namespace osu.Game.Screens.Multi.Components { public class RoomInspector : Container { - private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private const float transition_duration = 100; + private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private readonly Bindable nameBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); @@ -36,8 +37,13 @@ namespace osu.Game.Screens.Multi.Components private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable participantsBind = new Bindable(); - private FillFlowContainer topFlow; + private OsuColour colours; + private Box statusStrip; + private Container coverContainer; + private FillFlowContainer topFlow, participantsFlow, participantNumbersFlow, infoPanelFlow; + private OsuSpriteText name, status; private ScrollContainer participantsScroll; + private ParticipantInfo participantInfo; private Room room; public Room Room @@ -48,13 +54,26 @@ namespace osu.Game.Screens.Multi.Components if (value == room) return; room = value; - nameBind.BindTo(Room.Name); - hostBind.BindTo(Room.Host); - statusBind.BindTo(Room.Status); - typeBind.BindTo(Room.Type); - beatmapBind.BindTo(Room.Beatmap); - maxParticipantsBind.BindTo(Room.MaxParticipants); - participantsBind.BindTo(Room.Participants); + nameBind.UnbindBindings(); + hostBind.UnbindBindings(); + statusBind.UnbindBindings(); + typeBind.UnbindBindings(); + beatmapBind.UnbindBindings(); + maxParticipantsBind.UnbindBindings(); + participantsBind.UnbindBindings(); + + if (Room != null) + { + nameBind.BindTo(Room.Name); + hostBind.BindTo(Room.Host); + statusBind.BindTo(Room.Status); + typeBind.BindTo(Room.Type); + beatmapBind.BindTo(Room.Beatmap); + maxParticipantsBind.BindTo(Room.MaxParticipants); + participantsBind.BindTo(Room.Participants); + } + + updateState(); } } @@ -67,12 +86,10 @@ namespace osu.Game.Screens.Multi.Components [BackgroundDependencyLoader] private void load(OsuColour colours, LocalisationEngine localisation) { - Box statusStrip; - Container coverContainer; - FillFlowContainer participantsFlow; + this.colours = colours; + ModeTypeInfo modeTypeInfo; - OsuSpriteText participants, participantsSlash, maxParticipants, name, status, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor; - ParticipantInfo participantInfo; + OsuSpriteText participants, participantsSlash, maxParticipants, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor; Children = new Drawable[] { @@ -122,7 +139,7 @@ namespace osu.Game.Screens.Multi.Components Padding = new MarginPadding(20), Children = new Drawable[] { - new FillFlowContainer + participantNumbersFlow = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -180,6 +197,7 @@ namespace osu.Game.Screens.Multi.Components RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, + LayoutDuration = transition_duration, Padding = contentPadding, Spacing = new Vector2(0f, 5f), Children = new Drawable[] @@ -189,7 +207,7 @@ namespace osu.Game.Screens.Multi.Components TextSize = 14, Font = @"Exo2.0-Bold", }, - new FillFlowContainer + infoPanelFlow = new FillFlowContainer { AutoSizeAxes = Axes.X, Height = 30, @@ -275,14 +293,7 @@ namespace osu.Game.Screens.Multi.Components nameBind.ValueChanged += n => name.Text = n; hostBind.ValueChanged += h => participantInfo.Host = h; typeBind.ValueChanged += t => modeTypeInfo.Type = t; - - statusBind.ValueChanged += s => - { - status.Text = s.Message; - - foreach (Drawable d in new Drawable[] { statusStrip, status }) - d.FadeColour(s.GetAppropriateColour(colours), transition_duration); - }; + statusBind.ValueChanged += displayStatus; beatmapBind.ValueChanged += b => { @@ -293,14 +304,13 @@ namespace osu.Game.Screens.Multi.Components coverContainer.FadeIn(transition_duration); LoadComponentAsync(new BeatmapSetCover(b.BeatmapSet) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), - }, - coverContainer.Add); + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), + }, coverContainer.Add); beatmapTitle.Current = localisation.GetUnicodePreference(b.Metadata.TitleUnicode, b.Metadata.Title); beatmapDash.Text = @" - "; @@ -341,14 +351,7 @@ namespace osu.Game.Screens.Multi.Components participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u)); }; - // trigger incase a room was set before we were loaded - nameBind.TriggerChange(); - hostBind.TriggerChange(); - statusBind.TriggerChange(); - typeBind.TriggerChange(); - beatmapBind.TriggerChange(); - maxParticipantsBind.TriggerChange(); - participantsBind.TriggerChange(); + updateState(); } protected override void UpdateAfterChildren() @@ -358,6 +361,33 @@ namespace osu.Game.Screens.Multi.Components participantsScroll.Height = DrawHeight - topFlow.DrawHeight; } + private void displayStatus(RoomStatus s) + { + status.Text = s.Message; + + foreach (Drawable d in new Drawable[] { statusStrip, status }) + d.FadeColour(s.GetAppropriateColour(colours), transition_duration); + } + + private void updateState() + { + if (Room == null) + { + foreach (Drawable d in new Drawable[] { coverContainer, participantsFlow, participantNumbersFlow, infoPanelFlow, name, participantInfo }) + d.FadeOut(transition_duration); + + displayStatus(new RoomStatusNoneSelected()); + } + else + { + foreach (Drawable d in new Drawable[] { participantsFlow, participantNumbersFlow, infoPanelFlow, name, participantInfo }) + d.FadeIn(transition_duration); + + statusBind.TriggerChange(); + beatmapBind.TriggerChange(); + } + } + private class UserTile : Container, IHasTooltip { private readonly User user; @@ -386,5 +416,11 @@ namespace osu.Game.Screens.Multi.Components }; } } + + private class RoomStatusNoneSelected : RoomStatus + { + public override string Message => @"No Room Selected"; + public override Color4 GetAppropriateColour(OsuColour colours) => colours.Gray8; + } } } From 136c57b824d477e3af4370681e987358ed35b5b6 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Sat, 19 May 2018 02:27:33 -0300 Subject: [PATCH 203/302] Don't set size in ctor. --- osu.Game.Tests/Visual/TestCaseRoomInspector.cs | 2 ++ osu.Game/Screens/Multi/Components/RoomInspector.cs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index 48756c907b..06b9c4a6f9 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -71,6 +71,8 @@ namespace osu.Game.Tests.Visual { Anchor = Anchor.Centre, Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Width = 0.5f, }); AddStep(@"set room", () => inspector.Room = room); diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index b3a6d90e39..3de1611b77 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -79,8 +79,6 @@ namespace osu.Game.Screens.Multi.Components public RoomInspector() { - Width = 520; - RelativeSizeAxes = Axes.Y; } [BackgroundDependencyLoader] From 1f37dca7b7ea0ce8a19ae1ea7b426b1e7a4547c8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 19 May 2018 14:47:06 +0900 Subject: [PATCH 204/302] Fix HR / EZ being applied twice to AR --- .../Difficulty/OsuPerformanceCalculator.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index eeb776fa6e..ae74f12339 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -61,17 +61,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (mods.Any(m => !m.Ranked)) return 0; - // Todo: In the future we should apply changes to PreEmpt/AR at an OsuHitObject/BaseDifficulty level, but this is done - // locally for now as doing so would modify animations and other things unexpectedly - // DO NOT MODIFY THIS - double ar = Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate; - if (mods.Any(m => m is OsuModHardRock)) - ar = Math.Min(10, ar * 1.4); - if (mods.Any(m => m is OsuModEasy)) - ar = Math.Max(0, ar / 2); - - double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate; double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + double preEmpt = BeatmapDifficulty.DifficultyRange(Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / TimeRate; realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; realOverallDifficulty = (80 - 0.5 - hitWindowGreat) / 6; From 9cd0ec366e2d003e1f6c1923f414010a7208a821 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Sat, 19 May 2018 02:51:51 -0300 Subject: [PATCH 205/302] Cleanup. --- .../Screens/Multi/Components/RoomInspector.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index 3de1611b77..ea12b5dbde 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -5,7 +5,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -77,10 +76,6 @@ namespace osu.Game.Screens.Multi.Components } } - public RoomInspector() - { - } - [BackgroundDependencyLoader] private void load(OsuColour colours, LocalisationEngine localisation) { @@ -363,23 +358,31 @@ namespace osu.Game.Screens.Multi.Components { status.Text = s.Message; - foreach (Drawable d in new Drawable[] { statusStrip, status }) - d.FadeColour(s.GetAppropriateColour(colours), transition_duration); + Color4 c = s.GetAppropriateColour(colours); + statusStrip.FadeColour(c, transition_duration); + status.FadeColour(c, transition_duration); } private void updateState() { if (Room == null) { - foreach (Drawable d in new Drawable[] { coverContainer, participantsFlow, participantNumbersFlow, infoPanelFlow, name, participantInfo }) - d.FadeOut(transition_duration); + coverContainer.FadeOut(transition_duration); + participantsFlow.FadeOut(transition_duration); + participantNumbersFlow.FadeOut(transition_duration); + infoPanelFlow.FadeOut(transition_duration); + name.FadeOut(transition_duration); + participantInfo.FadeOut(transition_duration); displayStatus(new RoomStatusNoneSelected()); } else { - foreach (Drawable d in new Drawable[] { participantsFlow, participantNumbersFlow, infoPanelFlow, name, participantInfo }) - d.FadeIn(transition_duration); + participantsFlow.FadeIn(transition_duration); + participantNumbersFlow.FadeIn(transition_duration); + infoPanelFlow.FadeIn(transition_duration); + name.FadeIn(transition_duration); + participantInfo.FadeIn(transition_duration); statusBind.TriggerChange(); beatmapBind.TriggerChange(); From 4d528c4e6703da6e93418e59f3d11db2b13e8031 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sun, 20 May 2018 10:57:15 +0200 Subject: [PATCH 206/302] fix VisualTests and Samples still playing --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index c26adc8a3d..1005794742 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -16,9 +16,9 @@ namespace osu.Game.Graphics.Containers private SampleChannel samplePopIn; private SampleChannel samplePopOut; - protected BindableBool ShowOverlays = new BindableBool(); + protected BindableBool ShowOverlays = new BindableBool(true); - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(OsuGame osuGame, AudioManager audio) { samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in"); @@ -26,7 +26,8 @@ namespace osu.Game.Graphics.Containers StateChanged += onStateChanged; - ShowOverlays.BindTo(osuGame.ShowOverlays); + if (osuGame != null) + ShowOverlays.BindTo(osuGame.ShowOverlays); } /// @@ -52,7 +53,10 @@ namespace osu.Game.Graphics.Containers private void onStateChanged(Visibility visibility) { if (!ShowOverlays) + { State = Visibility.Hidden; + return; + } switch (visibility) { From aaca7e92b483f847fb8605f203088e76909effb3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 May 2018 03:56:59 +0900 Subject: [PATCH 207/302] Avoid excessive property lookups --- .../Screens/Multi/Components/RoomInspector.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index ea12b5dbde..3bd054b042 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -61,15 +61,15 @@ namespace osu.Game.Screens.Multi.Components maxParticipantsBind.UnbindBindings(); participantsBind.UnbindBindings(); - if (Room != null) + if (room != null) { - nameBind.BindTo(Room.Name); - hostBind.BindTo(Room.Host); - statusBind.BindTo(Room.Status); - typeBind.BindTo(Room.Type); - beatmapBind.BindTo(Room.Beatmap); - maxParticipantsBind.BindTo(Room.MaxParticipants); - participantsBind.BindTo(Room.Participants); + nameBind.BindTo(room.Name); + hostBind.BindTo(room.Host); + statusBind.BindTo(room.Status); + typeBind.BindTo(room.Type); + beatmapBind.BindTo(room.Beatmap); + maxParticipantsBind.BindTo(room.MaxParticipants); + participantsBind.BindTo(room.Participants); } updateState(); From 46c6c1d07e6edd0dc778d22a9ecf4e87c686a0dd Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 20 May 2018 20:25:39 -0700 Subject: [PATCH 208/302] Allow drag clicking footer and filter on song select --- osu.Game/Screens/Select/FilterControl.cs | 2 -- osu.Game/Screens/Select/Footer.cs | 2 -- 2 files changed, 4 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index ee458a13a4..f9f3db3827 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -190,7 +190,5 @@ namespace osu.Game.Screens.Select protected override bool OnMouseMove(InputState state) => true; protected override bool OnClick(InputState state) => true; - - protected override bool OnDragStart(InputState state) => true; } } diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 363249ab63..8f07e0a763 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -141,7 +141,5 @@ namespace osu.Game.Screens.Select protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; protected override bool OnClick(InputState state) => true; - - protected override bool OnDragStart(InputState state) => true; } } From 42519e3723e5abcde81c0c04005dae38a657aeb8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 May 2018 14:45:44 +0900 Subject: [PATCH 209/302] Rewrite code for clarity This also uses the AvailableRulesets list rather than private IDs --- .../Overlays/Toolbar/ToolbarModeSelector.cs | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index eeaa15d58a..3078c44844 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -76,15 +76,13 @@ namespace osu.Game.Overlays.Toolbar modeButtons.Add(new ToolbarModeButton { Ruleset = r, - Action = delegate - { - ruleset.Value = r; - } + Action = delegate { ruleset.Value = r; } }); } ruleset.ValueChanged += rulesetChanged; ruleset.DisabledChanged += disabledChanged; + if (game != null) ruleset.BindTo(game.Ruleset); else @@ -94,17 +92,18 @@ namespace osu.Game.Overlays.Toolbar protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { base.OnKeyDown(state, args); - if (!state.Keyboard.ControlPressed || args.Repeat || (int)args.Key < 109 || (int)args.Key > 118) { - return false; + + if (state.Keyboard.ControlPressed && !args.Repeat && args.Key >= Key.Number1 && args.Key <= Key.Number9) + { + int requested = args.Key - Key.Number1; + + RulesetInfo found = rulesets.AvailableRulesets.Skip(requested).FirstOrDefault(); + if (found != null) + ruleset.Value = found; + return true; } - RulesetInfo targetRuleset = rulesets.GetRuleset(args.Key == Key.Number0 ? 9 : (int)args.Key - 110); - if (targetRuleset == null || targetRuleset == ruleset.Value) { - return false; - } - - ruleset.Value = targetRuleset; - return true; + return false; } public override bool HandleKeyboardInput => !ruleset.Disabled && base.HandleKeyboardInput; From 1482bca147a7e152bd109eaf8094ac16d39ffb51 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 21 May 2018 09:42:29 +0200 Subject: [PATCH 210/302] Rename for better understanding ShowOverlays -> AllowOverlays ShowOverlaysOnEnter -> HideOverlaysOnEnter --- .../Containers/OsuFocusedOverlayContainer.cs | 33 +++++++++---------- osu.Game/OsuGame.cs | 6 ++-- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Loader.cs | 2 +- osu.Game/Screens/Menu/ButtonSystem.cs | 10 +++--- osu.Game/Screens/Menu/Disclaimer.cs | 2 +- osu.Game/Screens/Menu/Intro.cs | 2 +- osu.Game/Screens/Menu/MainMenu.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 10 +++--- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 6 ++-- osu.Game/Screens/Tournament/Drawings.cs | 2 +- 12 files changed, 40 insertions(+), 39 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 1005794742..9c36eb8c18 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -16,18 +16,18 @@ namespace osu.Game.Graphics.Containers private SampleChannel samplePopIn; private SampleChannel samplePopOut; - protected BindableBool ShowOverlays = new BindableBool(true); + protected BindableBool AllowOverlays = new BindableBool(true); [BackgroundDependencyLoader(true)] private void load(OsuGame osuGame, AudioManager audio) { + if (osuGame != null) + AllowOverlays.BindTo(osuGame.AllowOverlays); + samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in"); samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out"); StateChanged += onStateChanged; - - if (osuGame != null) - ShowOverlays.BindTo(osuGame.ShowOverlays); } /// @@ -52,21 +52,20 @@ namespace osu.Game.Graphics.Containers private void onStateChanged(Visibility visibility) { - if (!ShowOverlays) + if (AllowOverlays) { + switch (visibility) + { + case Visibility.Visible: + samplePopIn?.Play(); + break; + case Visibility.Hidden: + samplePopOut?.Play(); + break; + } + } + else State = Visibility.Hidden; - return; - } - - switch (visibility) - { - case Visibility.Visible: - samplePopIn?.Play(); - break; - case Visibility.Hidden: - samplePopOut?.Play(); - break; - } } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fe5ca4f278..b3da2831cd 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -77,7 +77,7 @@ namespace osu.Game public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight; - public readonly BindableBool ShowOverlays = new BindableBool(); + public readonly BindableBool AllowOverlays = new BindableBool(); private OsuScreen screenStack; @@ -367,9 +367,9 @@ namespace osu.Game settings.StateChanged += _ => updateScreenOffset(); notifications.StateChanged += _ => updateScreenOffset(); - notifications.Enabled.BindTo(ShowOverlays); + notifications.Enabled.BindTo(AllowOverlays); - ShowOverlays.ValueChanged += show => + AllowOverlays.ValueChanged += show => { //central game screen change logic. if (!show) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index e4eaee76fc..8049ea2738 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Edit { protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); - public override bool ShowOverlaysOnEnter => false; + public override bool HideOverlaysOnEnter => true; public override bool AllowBeatmapRulesetChange => false; private Box bottomBackground; diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 555c497d92..e49fb08087 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens { private bool showDisclaimer; - public override bool ShowOverlaysOnEnter => false; + public override bool HideOverlaysOnEnter => true; protected override bool AllowBackButton => false; diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 997002327a..9ca1a1ce19 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Menu { public event Action StateChanged; - private readonly BindableBool showOverlays = new BindableBool(); + private readonly BindableBool allowOverlays = new BindableBool(); public Action OnEdit; public Action OnExit; @@ -135,7 +135,9 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader(true)] private void load(AudioManager audio, OsuGame game) { - if (game != null) showOverlays.BindTo(game.ShowOverlays); + if (game != null) + allowOverlays.BindTo(game.AllowOverlays); + sampleBack = audio.Sample.Get(@"Menu/button-back-select"); } @@ -322,7 +324,7 @@ namespace osu.Game.Screens.Menu logoDelayedAction = Scheduler.AddDelayed(() => { - showOverlays.Value = false; + allowOverlays.Value = false; logo.ClearTransforms(targetMember: nameof(Position)); logo.RelativePositionAxes = Axes.Both; @@ -351,7 +353,7 @@ namespace osu.Game.Screens.Menu logoTracking = true; logo.Impact(); - showOverlays.Value = true; + allowOverlays.Value = true; }, 200); break; default: diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 5af634b02d..bd32792f3f 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Menu private readonly SpriteIcon icon; private Color4 iconColour; - public override bool ShowOverlaysOnEnter => false; + public override bool HideOverlaysOnEnter => true; public override bool CursorVisible => false; public Disclaimer() diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 4de76e530a..019f0432f6 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Menu private SampleChannel welcome; private SampleChannel seeya; - public override bool ShowOverlaysOnEnter => false; + public override bool HideOverlaysOnEnter => true; public override bool CursorVisible => false; protected override BackgroundScreen CreateBackground() => new BackgroundScreenEmpty(); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 3b519c5259..0dd05fa0ad 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Menu { private readonly ButtonSystem buttons; - public override bool ShowOverlaysOnEnter => buttons.State != MenuState.Initial; + public override bool HideOverlaysOnEnter => buttons.State == MenuState.Initial; protected override bool AllowBackButton => buttons.State != MenuState.Initial; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 24945ea347..f94087869a 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -32,12 +32,12 @@ namespace osu.Game.Screens /// protected virtual BackgroundScreen CreateBackground() => null; - protected BindableBool ShowOverlays = new BindableBool(); + protected BindableBool AllowOverlays = new BindableBool(); /// - /// Whether overlays should be shown when this screen is entered or resumed. + /// Whether overlays should be hidden when this screen is entered or resumed. /// - public virtual bool ShowOverlaysOnEnter => true; + public virtual bool HideOverlaysOnEnter => false; /// /// Whether this allows the cursor to be displayed. @@ -88,7 +88,7 @@ namespace osu.Game.Screens if (osuGame != null) { Ruleset.BindTo(osuGame.Ruleset); - ShowOverlays.BindTo(osuGame.ShowOverlays); + AllowOverlays.BindTo(osuGame.AllowOverlays); } sampleExit = audio.Sample.Get(@"UI/screen-back"); @@ -220,7 +220,7 @@ namespace osu.Game.Screens if (backgroundParallaxContainer != null) backgroundParallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * BackgroundParallaxAmount; - ShowOverlays.Value = ShowOverlaysOnEnter; + AllowOverlays.Value = !HideOverlaysOnEnter; } private void onExitingLogo() diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 46919e25e1..44112609f8 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play { protected override float BackgroundParallaxAmount => 0.1f; - public override bool ShowOverlaysOnEnter => false; + public override bool HideOverlaysOnEnter => true; public Action RestartRequested; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 56fbd7b6e7..fcb2a19c58 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -25,8 +25,8 @@ namespace osu.Game.Screens.Play private BeatmapMetadataDisplay info; - private bool showOverlays = true; - public override bool ShowOverlaysOnEnter => showOverlays; + private bool allowOverlays = true; + public override bool HideOverlaysOnEnter => !allowOverlays; private Task loadTask; @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Play player.RestartRequested = () => { - showOverlays = false; + allowOverlays = false; ValidForResume = true; }; } diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 1ef0b6cca0..ca806ce73e 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Tournament { private const string results_filename = "drawings_results.txt"; - public override bool ShowOverlaysOnEnter => false; + public override bool HideOverlaysOnEnter => true; protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); From a54bda6ce1f15c98643014534e1be914834fa2ae Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Mon, 21 May 2018 13:23:39 +0300 Subject: [PATCH 211/302] Apply requested changes --- osu-framework | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu-framework b/osu-framework index fac688633b..80e78fd45b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit fac688633b8fcf34ae5d0514c26b03e217161eb4 +Subproject commit 80e78fd45bb79ca4bc46ecc05deb6058f3879faa diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 6cae4d9187..72fb91e7df 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -18,9 +18,7 @@ namespace osu.Game.Screens.Edit /// public class EditorClock : DecoupleableInterpolatingFramedClock { - //public Bindable Beatmap = new Bindable(); - - public double TrackLength; + public readonly double TrackLength; public ControlPointInfo ControlPointInfo; @@ -33,6 +31,7 @@ namespace osu.Game.Screens.Edit ControlPointInfo = beatmap.Value.Beatmap.ControlPointInfo; TrackLength = beatmap.Value.Track.Length; } + public EditorClock(ControlPointInfo controlPointInfo, double trackLength, BindableBeatDivisor beatDivisor) { this.beatDivisor = beatDivisor; From b7e3ea348b15e8cdae2e3963f9b8ee4a405e7ea1 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 21 May 2018 15:53:50 +0200 Subject: [PATCH 212/302] expose two Bindables with split logic instead of one with mixed logic --- .../Containers/OsuFocusedOverlayContainer.cs | 6 +++--- osu.Game/OsuGame.cs | 9 +++++---- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Loader.cs | 2 +- osu.Game/Screens/Menu/ButtonSystem.cs | 13 ++++++++----- osu.Game/Screens/Menu/Disclaimer.cs | 3 ++- osu.Game/Screens/Menu/Intro.cs | 4 +++- osu.Game/Screens/Menu/MainMenu.cs | 3 ++- osu.Game/Screens/OsuScreen.cs | 17 +++++++++++++---- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 6 +++--- osu.Game/Screens/Tournament/Drawings.cs | 2 +- 12 files changed, 43 insertions(+), 26 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 9c36eb8c18..11a2034a8f 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -16,13 +16,13 @@ namespace osu.Game.Graphics.Containers private SampleChannel samplePopIn; private SampleChannel samplePopOut; - protected BindableBool AllowOverlays = new BindableBool(true); + private readonly BindableBool allowOpeningOverlays = new BindableBool(true); [BackgroundDependencyLoader(true)] private void load(OsuGame osuGame, AudioManager audio) { if (osuGame != null) - AllowOverlays.BindTo(osuGame.AllowOverlays); + allowOpeningOverlays.BindTo(osuGame.AllowOpeningOverlays); samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in"); samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out"); @@ -52,7 +52,7 @@ namespace osu.Game.Graphics.Containers private void onStateChanged(Visibility visibility) { - if (AllowOverlays) + if (allowOpeningOverlays) { switch (visibility) { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b3da2831cd..ec93b1ae46 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -77,7 +77,8 @@ namespace osu.Game public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight; - public readonly BindableBool AllowOverlays = new BindableBool(); + public readonly BindableBool HideOverlaysOnEnter = new BindableBool(); + public readonly BindableBool AllowOpeningOverlays = new BindableBool(true); private OsuScreen screenStack; @@ -367,12 +368,12 @@ namespace osu.Game settings.StateChanged += _ => updateScreenOffset(); notifications.StateChanged += _ => updateScreenOffset(); - notifications.Enabled.BindTo(AllowOverlays); + notifications.Enabled.BindTo(AllowOpeningOverlays); - AllowOverlays.ValueChanged += show => + HideOverlaysOnEnter.ValueChanged += hide => { //central game screen change logic. - if (!show) + if (hide) { hideAllOverlays(); musicController.State = Visibility.Hidden; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 8049ea2738..b657fe5597 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Edit { protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); - public override bool HideOverlaysOnEnter => true; + protected override bool HideOverlaysOnEnter => true; public override bool AllowBeatmapRulesetChange => false; private Box bottomBackground; diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index e49fb08087..fb5c5ca84b 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens { private bool showDisclaimer; - public override bool HideOverlaysOnEnter => true; + protected override bool HideOverlaysOnEnter => true; protected override bool AllowBackButton => false; diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 9ca1a1ce19..d1d388ae1f 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -27,7 +27,8 @@ namespace osu.Game.Screens.Menu { public event Action StateChanged; - private readonly BindableBool allowOverlays = new BindableBool(); + private readonly BindableBool hideOverlaysOnEnter = new BindableBool(); + private readonly BindableBool allowOpeningOverlays = new BindableBool(); public Action OnEdit; public Action OnExit; @@ -136,7 +137,10 @@ namespace osu.Game.Screens.Menu private void load(AudioManager audio, OsuGame game) { if (game != null) - allowOverlays.BindTo(game.AllowOverlays); + { + hideOverlaysOnEnter.BindTo(game.HideOverlaysOnEnter); + allowOpeningOverlays.BindTo(game.AllowOpeningOverlays); + } sampleBack = audio.Sample.Get(@"Menu/button-back-select"); } @@ -324,8 +328,6 @@ namespace osu.Game.Screens.Menu logoDelayedAction = Scheduler.AddDelayed(() => { - allowOverlays.Value = false; - logo.ClearTransforms(targetMember: nameof(Position)); logo.RelativePositionAxes = Axes.Both; @@ -353,7 +355,8 @@ namespace osu.Game.Screens.Menu logoTracking = true; logo.Impact(); - allowOverlays.Value = true; + hideOverlaysOnEnter.Value = false; + allowOpeningOverlays.Value = true; }, 200); break; default: diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index bd32792f3f..9a671cf780 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -18,7 +18,8 @@ namespace osu.Game.Screens.Menu private readonly SpriteIcon icon; private Color4 iconColour; - public override bool HideOverlaysOnEnter => true; + protected override bool HideOverlaysOnEnter => true; + public override bool CursorVisible => false; public Disclaimer() diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 019f0432f6..c174e2d470 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -31,7 +31,9 @@ namespace osu.Game.Screens.Menu private SampleChannel welcome; private SampleChannel seeya; - public override bool HideOverlaysOnEnter => true; + protected override bool HideOverlaysOnEnter => true; + protected override bool AllowOpeningOverlays => false; + public override bool CursorVisible => false; protected override BackgroundScreen CreateBackground() => new BackgroundScreenEmpty(); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 0dd05fa0ad..d5f3b11467 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -24,7 +24,8 @@ namespace osu.Game.Screens.Menu { private readonly ButtonSystem buttons; - public override bool HideOverlaysOnEnter => buttons.State == MenuState.Initial; + protected override bool HideOverlaysOnEnter => buttons.State == MenuState.Initial; + protected override bool AllowOpeningOverlays => buttons.State != MenuState.Initial; protected override bool AllowBackButton => buttons.State != MenuState.Initial; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index f94087869a..4b1562291b 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -32,12 +32,19 @@ namespace osu.Game.Screens /// protected virtual BackgroundScreen CreateBackground() => null; - protected BindableBool AllowOverlays = new BindableBool(); + private readonly BindableBool hideOverlaysOnEnter = new BindableBool(); /// /// Whether overlays should be hidden when this screen is entered or resumed. /// - public virtual bool HideOverlaysOnEnter => false; + protected virtual bool HideOverlaysOnEnter => hideOverlaysOnEnter; + + private readonly BindableBool allowOpeningOverlays = new BindableBool(); + + /// + /// Whether overlays should be able to be opened while this screen is active. + /// + protected virtual bool AllowOpeningOverlays => allowOpeningOverlays; /// /// Whether this allows the cursor to be displayed. @@ -88,7 +95,8 @@ namespace osu.Game.Screens if (osuGame != null) { Ruleset.BindTo(osuGame.Ruleset); - AllowOverlays.BindTo(osuGame.AllowOverlays); + hideOverlaysOnEnter.BindTo(osuGame.HideOverlaysOnEnter); + allowOpeningOverlays.BindTo(osuGame.AllowOpeningOverlays); } sampleExit = audio.Sample.Get(@"UI/screen-back"); @@ -220,7 +228,8 @@ namespace osu.Game.Screens if (backgroundParallaxContainer != null) backgroundParallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * BackgroundParallaxAmount; - AllowOverlays.Value = !HideOverlaysOnEnter; + hideOverlaysOnEnter.Value = HideOverlaysOnEnter; + allowOpeningOverlays.Value = AllowOpeningOverlays; } private void onExitingLogo() diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 44112609f8..ec7a99145e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play { protected override float BackgroundParallaxAmount => 0.1f; - public override bool HideOverlaysOnEnter => true; + protected override bool HideOverlaysOnEnter => true; public Action RestartRequested; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index fcb2a19c58..734837a4f1 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -25,8 +25,8 @@ namespace osu.Game.Screens.Play private BeatmapMetadataDisplay info; - private bool allowOverlays = true; - public override bool HideOverlaysOnEnter => !allowOverlays; + private bool hideOverlays; + protected override bool HideOverlaysOnEnter => hideOverlays; private Task loadTask; @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Play player.RestartRequested = () => { - allowOverlays = false; + hideOverlays = true; ValidForResume = true; }; } diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index ca806ce73e..29301899d5 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Tournament { private const string results_filename = "drawings_results.txt"; - public override bool HideOverlaysOnEnter => true; + protected override bool HideOverlaysOnEnter => true; protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); From d109522bf790bc9e111ff54df5d8b247199f09d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 May 2018 23:09:00 +0900 Subject: [PATCH 213/302] Fix escape not working to go backwards in menus before finally exiting the game Resolves #2596. --- osu.Game/Screens/Menu/ButtonSystem.cs | 29 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 997002327a..98c1cfbf07 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -148,6 +148,8 @@ namespace osu.Game.Screens.Menu case Key.Space: logo?.TriggerOnClick(state); return true; + case Key.Escape: + return goBack(); } return false; @@ -158,17 +160,22 @@ namespace osu.Game.Screens.Menu switch (action) { case GlobalAction.Back: - switch (State) - { - case MenuState.TopLevel: - State = MenuState.Initial; - return true; - case MenuState.Play: - backButton.TriggerOnClick(); - return true; - default: - return false; - } + return goBack(); + default: + return false; + } + } + + private bool goBack() + { + switch (State) + { + case MenuState.TopLevel: + State = MenuState.Initial; + return true; + case MenuState.Play: + backButton.TriggerOnClick(); + return true; default: return false; } From 3d9d40448ded833eb6ecaf960b047817ca3db5ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 00:01:40 +0900 Subject: [PATCH 214/302] Fix incorrect syntax --- osu.Game/Screens/Play/HUD/QuitButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 276bffb0a4..db24400f30 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Play.HUD { icon.ScaleTo(1.5f); text.FadeIn(fade_duration); - progress.FillTo(progress.Current, 1, progress_duration).OnComplete(cp => ExitAction()); + progress.FillTo(1, progress_duration).OnComplete(cp => ExitAction()); return base.OnMouseDown(state, args); } @@ -95,7 +95,7 @@ namespace osu.Game.Screens.Play.HUD { icon.ScaleTo(1f); Scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); - progress.FillTo(progress.Current, 0, progress_duration / 4).OnComplete(cp => progress.Current.SetDefault()); + progress.FillTo(0, progress_duration / 4f).OnComplete(cp => progress.Current.SetDefault()); return base.OnMouseUp(state, args); } From d5afccd610f268096c6fe968213d71ec97fb3aa1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 00:02:03 +0900 Subject: [PATCH 215/302] Make hint text display briefly at initial display, then on hover --- osu.Game/Screens/Play/HUD/QuitButton.cs | 35 ++++++++++++++++++------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index db24400f30..61925108ae 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -16,6 +16,8 @@ namespace osu.Game.Screens.Play.HUD { public class QuitButton : FillFlowContainer { + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => button.ReceiveMouseInputAt(screenSpacePos); + private readonly Button button; public Action ExitAction @@ -24,28 +26,47 @@ namespace osu.Game.Screens.Play.HUD set => button.ExitAction = value; } + OsuSpriteText text; + public QuitButton() { - OsuSpriteText text; Direction = FillDirection.Horizontal; Spacing = new Vector2(20, 0); + Margin = new MarginPadding(10); Children = new Drawable[] { text = new OsuSpriteText { - Text = "Hold to Quit", + Text = "hold to quit", Font = @"Exo2.0-Bold", Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }, - button = new Button(text) + button = new Button() }; AutoSizeAxes = Axes.Both; } + protected override void LoadComplete() + { + text.FadeInFromZero(500, Easing.OutQuint).Delay(1500).FadeOut(500, Easing.OutQuint); + base.LoadComplete(); + } + + protected override bool OnHover(InputState state) + { + text.FadeIn(500, Easing.OutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + text.FadeOut(500, Easing.OutQuint); + base.OnHoverLost(state); + } + private class Button : CircularContainer { - private readonly OsuSpriteText text; private SpriteIcon icon; private CircularProgress progress; @@ -53,9 +74,6 @@ namespace osu.Game.Screens.Play.HUD private const int fade_duration = 200; private const int progress_duration = 1000; - private const int text_display_time = 5000; - - public Button(OsuSpriteText text) => this.text = text; [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -79,13 +97,11 @@ namespace osu.Game.Screens.Play.HUD }, progress = new CircularProgress { RelativeSizeAxes = Axes.Both, InnerRadius = 0.1f } }); - Scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { icon.ScaleTo(1.5f); - text.FadeIn(fade_duration); progress.FillTo(1, progress_duration).OnComplete(cp => ExitAction()); return base.OnMouseDown(state, args); @@ -94,7 +110,6 @@ namespace osu.Game.Screens.Play.HUD protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { icon.ScaleTo(1f); - Scheduler.AddDelayed(() => text.FadeOut(fade_duration), text_display_time); progress.FillTo(0, progress_duration / 4f).OnComplete(cp => progress.Current.SetDefault()); return base.OnMouseUp(state, args); From cee8d21542713dd2e3eadc3983d9c611ddf7dd21 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 21 May 2018 17:24:57 +0200 Subject: [PATCH 216/302] hide overlays when going back to initial menu state --- osu.Game/Screens/Menu/ButtonSystem.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index d1d388ae1f..2e757c256e 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -328,6 +328,9 @@ namespace osu.Game.Screens.Menu logoDelayedAction = Scheduler.AddDelayed(() => { + hideOverlaysOnEnter.Value = true; + allowOpeningOverlays.Value = false; + logo.ClearTransforms(targetMember: nameof(Position)); logo.RelativePositionAxes = Axes.Both; @@ -355,6 +358,7 @@ namespace osu.Game.Screens.Menu logoTracking = true; logo.Impact(); + hideOverlaysOnEnter.Value = false; allowOpeningOverlays.Value = true; }, 200); From f9c162dee95617e22cd8666cc35d3fe03b6941a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 00:49:33 +0900 Subject: [PATCH 217/302] Adjust design and feel --- osu.Game/Screens/Play/HUD/QuitButton.cs | 58 +++++++++++++++++++++---- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 61925108ae..939966f0e5 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; +using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using OpenTK; @@ -26,7 +27,7 @@ namespace osu.Game.Screens.Play.HUD set => button.ExitAction = value; } - OsuSpriteText text; + private readonly OsuSpriteText text; public QuitButton() { @@ -65,15 +66,32 @@ namespace osu.Game.Screens.Play.HUD base.OnHoverLost(state); } + protected override void Update() + { + base.Update(); + + float adjust = Vector2.Distance(GetContainingInputManager().CurrentState.Mouse.NativeState.Position, button.ScreenSpaceDrawQuad.Centre) / 200; + double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); + + bool stayVisible = text.Alpha > 0 || button.Progress > 0 || IsHovered; + + Alpha = stayVisible ? 1 : Interpolation.ValueAt(elapsed, Alpha, MathHelper.Clamp(1 - adjust, 0.04f, 1), 0, 200, Easing.OutQuint); + } + private class Button : CircularContainer { private SpriteIcon icon; private CircularProgress progress; + private Circle innerCircle; + + private bool triggered; public Action ExitAction { get; set; } + public double Progress => progress.Current.Value; + private const int fade_duration = 200; - private const int progress_duration = 1000; + private const int progress_duration = 600; [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -86,31 +104,55 @@ namespace osu.Game.Screens.Play.HUD { RelativeSizeAxes = Axes.Both, Colour = colours.Gray1, - Alpha = 0.8f, + Alpha = 0.5f, + }, + progress = new CircularProgress + { + RelativeSizeAxes = Axes.Both, + InnerRadius = 1 + }, + innerCircle = new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray1, + Size = new Vector2(0.9f), }, icon = new SpriteIcon { + Shadow = false, Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(15), Icon = FontAwesome.fa_close }, - progress = new CircularProgress { RelativeSizeAxes = Axes.Both, InnerRadius = 0.1f } }); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - icon.ScaleTo(1.5f); - progress.FillTo(1, progress_duration).OnComplete(cp => ExitAction()); + if (state.Mouse.Buttons.Count > 1 || triggered) + return true; + + icon.ScaleTo(1.4f, progress_duration); + progress.FillTo(1, progress_duration, Easing.OutSine).OnComplete(_ => + { + innerCircle.ScaleTo(0, 100).Then().FadeOut().ScaleTo(1).FadeIn(500); + triggered = true; + ExitAction(); + }); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - icon.ScaleTo(1f); - progress.FillTo(0, progress_duration / 4f).OnComplete(cp => progress.Current.SetDefault()); + if (state.Mouse.Buttons.Count > 0 || triggered) + return true; + + icon.ScaleTo(1, 800, Easing.OutElastic); + progress.FillTo(0, progress_duration, Easing.OutQuint).OnComplete(cp => progress.Current.SetDefault()); return base.OnMouseUp(state, args); } From 30956b64aa394fa51bc2b23084519b23fd9b2417 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 21 May 2018 18:57:01 +0300 Subject: [PATCH 218/302] Do not change Margin for player settings groups on the PlayerLoader screen --- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 13293b6f93..06c1503fd1 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Play AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Spacing = new Vector2(0, 20), - Margin = new MarginPadding { Top = 100, Right = 10 }, + Margin = new MarginPadding(25), Children = new PlayerSettingsGroup[] { new VisualSettings(), From ebda287e8186fea7c7ebf82ac9c1e70175bcd7b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 01:44:06 +0900 Subject: [PATCH 219/302] Share code with HoldToConfirm implementations elsewhere --- osu-framework | 2 +- osu.Game.Tests/Visual/TestCaseQuitButton.cs | 42 ++++--- .../Containers/HoldToCofirmContainer.cs | 52 ++++++++ osu.Game/Overlays/HoldToConfirmOverlay.cs | 33 +---- osu.Game/Screens/Play/HUD/QuitButton.cs | 116 ++++++++---------- osu.Game/Screens/Play/Player.cs | 2 +- 6 files changed, 135 insertions(+), 112 deletions(-) create mode 100644 osu.Game/Graphics/Containers/HoldToCofirmContainer.cs diff --git a/osu-framework b/osu-framework index fac688633b..b4d5c766f5 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit fac688633b8fcf34ae5d0514c26b03e217161eb4 +Subproject commit b4d5c766f5698540a7b1bbbae7290ac7dafc2813 diff --git a/osu.Game.Tests/Visual/TestCaseQuitButton.cs b/osu.Game.Tests/Visual/TestCaseQuitButton.cs index 545a8ff57b..f0f8d41074 100644 --- a/osu.Game.Tests/Visual/TestCaseQuitButton.cs +++ b/osu.Game.Tests/Visual/TestCaseQuitButton.cs @@ -3,49 +3,55 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Screens.Play.HUD; +using OpenTK; +using OpenTK.Input; namespace osu.Game.Tests.Visual { [Description("'Hold to Quit' UI element")] - public class TestCaseQuitButton : OsuTestCase + public class TestCaseQuitButton : ManualInputManagerTestCase { - private readonly QuitButton quitButton; - private Drawable innerButton => quitButton.Children.Single(child => child is CircularContainer); private bool exitAction; - public TestCaseQuitButton() + [BackgroundDependencyLoader] + private void load() { + QuitButton quitButton; + Add(quitButton = new QuitButton { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, - }); - quitButton.ExitAction = () => exitAction = true; - - var text = quitButton.Children.OfType().Single(); - - AddStep("Trigger text fade in/out", () => - { - exitAction = false; - - innerButton.TriggerOnMouseDown(); - innerButton.TriggerOnMouseUp(); + Action = () => exitAction = true }); + var text = quitButton.Children.OfType().First(); + + // initial display AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); AddUntilStep(() => !text.IsPresent && !exitAction, "Text is not visible"); + AddStep("Trigger text fade in", () => InputManager.MoveMouseTo(quitButton)); + AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); + AddStep("Trigger text fade out", () => InputManager.MoveMouseTo(Vector2.One)); + AddUntilStep(() => !text.IsPresent && !exitAction, "Text is not visible"); + AddStep("Trigger exit action", () => { exitAction = false; - innerButton.TriggerOnMouseDown(); + InputManager.MoveMouseTo(quitButton); + InputManager.ButtonDown(MouseButton.Left); }); - AddUntilStep(() => exitAction, $"{nameof(quitButton.ExitAction)} was triggered"); + AddStep("Early release", () => InputManager.ButtonUp(MouseButton.Left)); + AddAssert("action not triggered", () => !exitAction); + + AddStep("Trigger exit action", () => InputManager.ButtonDown(MouseButton.Left)); + AddUntilStep(() => exitAction, $"{nameof(quitButton.Action)} was triggered"); } } } diff --git a/osu.Game/Graphics/Containers/HoldToCofirmContainer.cs b/osu.Game/Graphics/Containers/HoldToCofirmContainer.cs new file mode 100644 index 0000000000..eb2b2ca51b --- /dev/null +++ b/osu.Game/Graphics/Containers/HoldToCofirmContainer.cs @@ -0,0 +1,52 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Graphics.Containers +{ + public abstract class HoldToCofirmContainer : Container + { + public Action Action; + + private const int activate_delay = 400; + private const int fadeout_delay = 200; + + private bool fired; + private bool confirming; + + /// + /// Whether the overlay should be allowed to return from a fired state. + /// + protected virtual bool AllowMultipleFires => false; + + public Bindable Progress = new BindableDouble(); + + protected void BeginConfirm() + { + if (confirming || !AllowMultipleFires && fired) return; + + confirming = true; + + this.TransformBindableTo(Progress, 1, activate_delay * (1 - Progress.Value), Easing.Out).OnComplete(_ => Confirm()); + } + + protected virtual void Confirm() + { + Action?.Invoke(); + fired = true; + } + + protected void AbortConfirm() + { + if (!AllowMultipleFires && fired) return; + + confirming = false; + + this.TransformBindableTo(Progress, 0, fadeout_delay, Easing.Out); + } + } +} diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index a0e4bf1a39..afd3e2016f 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -1,11 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; using OpenTK.Graphics; namespace osu.Game.Overlays @@ -14,22 +13,10 @@ namespace osu.Game.Overlays /// An overlay which will display a black screen that dims over a period before confirming an exit action. /// Action is BYO (derived class will need to call and from a user event). /// - public abstract class HoldToConfirmOverlay : Container + public abstract class HoldToConfirmOverlay : HoldToCofirmContainer { - public Action Action; - private Box overlay; - private const int activate_delay = 400; - private const int fadeout_delay = 200; - - private bool fired; - - /// - /// Whether the overlay should be allowed to return from a fired state. - /// - protected virtual bool AllowMultipleFires => false; - [BackgroundDependencyLoader] private void load() { @@ -45,22 +32,8 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, } }; - } - protected void BeginConfirm() - { - if (!AllowMultipleFires && fired) return; - overlay.FadeIn(activate_delay * (1 - overlay.Alpha), Easing.Out).OnComplete(_ => - { - Action?.Invoke(); - fired = true; - }); - } - - protected void AbortConfirm() - { - if (!AllowMultipleFires && fired) return; - overlay.FadeOut(fadeout_delay, Easing.Out); + Progress.ValueChanged += v => overlay.Alpha = (float)v; } } } diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 939966f0e5..867558ad93 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.MathUtils; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using OpenTK; @@ -21,10 +22,9 @@ namespace osu.Game.Screens.Play.HUD private readonly Button button; - public Action ExitAction + public Action Action { - get => button.ExitAction; - set => button.ExitAction = value; + set => button.Action = value; } private readonly OsuSpriteText text; @@ -73,88 +73,80 @@ namespace osu.Game.Screens.Play.HUD float adjust = Vector2.Distance(GetContainingInputManager().CurrentState.Mouse.NativeState.Position, button.ScreenSpaceDrawQuad.Centre) / 200; double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); - bool stayVisible = text.Alpha > 0 || button.Progress > 0 || IsHovered; + bool stayVisible = text.Alpha > 0 || button.Progress.Value > 0 || IsHovered; Alpha = stayVisible ? 1 : Interpolation.ValueAt(elapsed, Alpha, MathHelper.Clamp(1 - adjust, 0.04f, 1), 0, 200, Easing.OutQuint); } - private class Button : CircularContainer + private class Button : HoldToCofirmContainer { private SpriteIcon icon; private CircularProgress progress; private Circle innerCircle; - private bool triggered; - - public Action ExitAction { get; set; } - - public double Progress => progress.Current.Value; - - private const int fade_duration = 200; - private const int progress_duration = 600; - [BackgroundDependencyLoader] private void load(OsuColour colours) { - Masking = true; Size = new Vector2(60); - AddRange(new Drawable[] + + Child = new CircularContainer { - new Box + Masking = true, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = colours.Gray1, - Alpha = 0.5f, - }, - progress = new CircularProgress - { - RelativeSizeAxes = Axes.Both, - InnerRadius = 1 - }, - innerCircle = new Circle - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = colours.Gray1, - Size = new Vector2(0.9f), - }, - icon = new SpriteIcon - { - Shadow = false, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(15), - Icon = FontAwesome.fa_close - }, - }); + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray1, + Alpha = 0.5f, + }, + progress = new CircularProgress + { + RelativeSizeAxes = Axes.Both, + InnerRadius = 1 + }, + innerCircle = new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray1, + Size = new Vector2(0.9f), + }, + icon = new SpriteIcon + { + Shadow = false, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(15), + Icon = FontAwesome.fa_close + }, + } + }; + + Progress.BindTo(progress.Current); + Progress.ValueChanged += v => icon.Scale = new Vector2(1 + (float)v * 0.4f); + } + + protected override void Confirm() + { + base.Confirm(); + innerCircle.ScaleTo(0, 100).Then().FadeOut().ScaleTo(1).FadeIn(500); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - if (state.Mouse.Buttons.Count > 1 || triggered) - return true; - - icon.ScaleTo(1.4f, progress_duration); - progress.FillTo(1, progress_duration, Easing.OutSine).OnComplete(_ => - { - innerCircle.ScaleTo(0, 100).Then().FadeOut().ScaleTo(1).FadeIn(500); - triggered = true; - ExitAction(); - }); - - return base.OnMouseDown(state, args); + if (state.Mouse.Buttons.Count == 1) + BeginConfirm(); + return true; } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - if (state.Mouse.Buttons.Count > 0 || triggered) - return true; - - icon.ScaleTo(1, 800, Easing.OutElastic); - progress.FillTo(0, progress_duration, Easing.OutQuint).OnComplete(cp => progress.Current.SetDefault()); - - return base.OnMouseUp(state, args); + if (state.Mouse.Buttons.Count == 0) + AbortConfirm(); + return true; } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5fb3fb778c..37176aa327 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -219,7 +219,7 @@ namespace osu.Game.Screens.Play } }; - hudOverlay.HoldToQuit.ExitAction = Exit; + hudOverlay.HoldToQuit.Action = Exit; if (ShowStoryboard) initializeStoryboard(false); From 946a75ddb273bd84a71b1f3bce73dfed9dea7fe8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 02:05:08 +0900 Subject: [PATCH 220/302] Block hover to use UI cursor instead of gameplay cursor --- osu.Game/Screens/Play/HUD/QuitButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 867558ad93..1533f6a9af 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Play.HUD protected override bool OnHover(InputState state) { text.FadeIn(500, Easing.OutQuint); - return base.OnHover(state); + return true; } protected override void OnHoverLost(InputState state) From 156d7fb25a15458e23fa8458a717fd33a856c359 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 02:08:21 +0900 Subject: [PATCH 221/302] Change depth of HUD Yes, this is intentional. --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 37176aa327..0150d76251 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -183,6 +183,7 @@ namespace osu.Game.Screens.Play ProcessCustomClock = false, Breaks = beatmap.Breaks }, + RulesetContainer.Cursor?.CreateProxy() ?? new Container(), hudOverlay = new HUDOverlay(scoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) { Clock = Clock, // hud overlay doesn't want to use the audio clock directly @@ -190,7 +191,6 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre }, - RulesetContainer.Cursor?.CreateProxy() ?? new Container(), new SkipOverlay(firstObjectTime) { Clock = Clock, // skip button doesn't want to use the audio clock directly From 323aa189b63269329f5f32db31893859bf90e1ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 02:08:44 +0900 Subject: [PATCH 222/302] Make on-confirmation animation more robust --- osu.Game/Screens/Play/HUD/QuitButton.cs | 31 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 1533f6a9af..d6060e01a3 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -81,9 +81,11 @@ namespace osu.Game.Screens.Play.HUD private class Button : HoldToCofirmContainer { private SpriteIcon icon; - private CircularProgress progress; + private CircularProgress circularProgress; private Circle innerCircle; + protected override bool AllowMultipleFires => true; + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -101,7 +103,7 @@ namespace osu.Game.Screens.Play.HUD Colour = colours.Gray1, Alpha = 0.5f, }, - progress = new CircularProgress + circularProgress = new CircularProgress { RelativeSizeAxes = Axes.Both, InnerRadius = 1 @@ -125,19 +127,38 @@ namespace osu.Game.Screens.Play.HUD } }; - Progress.BindTo(progress.Current); + bind(); + } + + private void bind() + { + circularProgress.Current.BindTo(Progress); Progress.ValueChanged += v => icon.Scale = new Vector2(1 + (float)v * 0.4f); } + private bool pendingAnimation; + protected override void Confirm() { base.Confirm(); - innerCircle.ScaleTo(0, 100).Then().FadeOut().ScaleTo(1).FadeIn(500); + + // temporarily unbind as to not look weird during flash animation. + Progress.UnbindAll(); + pendingAnimation = true; + + innerCircle.ScaleTo(0, 100) + .Then().FadeOut().ScaleTo(1).FadeIn(500) + .OnComplete(a => circularProgress.FadeOut(100).OnComplete(_ => + { + bind(); + circularProgress.FadeIn(); + pendingAnimation = false; + })); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - if (state.Mouse.Buttons.Count == 1) + if (!pendingAnimation && state.Mouse.Buttons.Count == 1) BeginConfirm(); return true; } From 5a892e4d082fa8042b053d2a870bd851226198af Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 02:09:52 +0900 Subject: [PATCH 223/302] This quit button don't quit --- osu.Game/Screens/Play/HUD/QuitButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index d6060e01a3..e829d26aab 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play.HUD { text = new OsuSpriteText { - Text = "hold to quit", + Text = "hold for menu", Font = @"Exo2.0-Bold", Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft From 1210368e29bdf8ebfb159894067cb9679add1fae Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 21 May 2018 23:00:02 -0300 Subject: [PATCH 224/302] Add MultiplayerScreen base class. --- osu.Game/Screens/Multi/Header.cs | 3 +- .../Multi/Screens/MultiplayerScreen.cs | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index db8898495f..f6b7bbfcef 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.SearchableList; +using osu.Game.Screens.Multi.Screens; using OpenTK; using OpenTK.Graphics; @@ -85,7 +86,7 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => screenTitle.Text = s.ToString(); + breadcrumbs.Current.ValueChanged += s => screenTitle.Text = s is MultiplayerScreen m ? m.Title : s.ToString(); breadcrumbs.Current.TriggerChange(); } diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs new file mode 100644 index 0000000000..5a17a32d8c --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs @@ -0,0 +1,57 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Screens; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Screens.Multi.Screens +{ + public abstract class MultiplayerScreen : OsuScreen + { + private const Easing in_easing = Easing.OutQuint; + private const Easing out_easing = Easing.InSine; + + protected virtual Container TransitionContent => Content; + + public abstract string Title { get; } + public abstract string Name { get; } + + public override string ToString() => Name; + + protected override void OnEntering(Screen last) + { + base.OnEntering(last); + + TransitionContent.MoveToX(200); + + TransitionContent.FadeInFromZero(WaveContainer.APPEAR_DURATION, in_easing); + TransitionContent.MoveToX(0, WaveContainer.APPEAR_DURATION, in_easing); + } + + protected override bool OnExiting(Screen next) + { + Content.FadeOut(WaveContainer.DISAPPEAR_DURATION, out_easing); + TransitionContent.MoveToX(200, WaveContainer.DISAPPEAR_DURATION, out_easing); + + return base.OnExiting(next); + } + + protected override void OnResuming(Screen last) + { + base.OnResuming(last); + + Content.FadeIn(WaveContainer.APPEAR_DURATION, in_easing); + TransitionContent.MoveToX(0, WaveContainer.APPEAR_DURATION, in_easing); + } + + protected override void OnSuspending(Screen next) + { + base.OnSuspending(next); + + Content.FadeOut(WaveContainer.DISAPPEAR_DURATION, out_easing); + TransitionContent.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, out_easing); + } + } +} From cae09492c30749096e2b6c54351234527f47be27 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 22 May 2018 00:07:04 -0300 Subject: [PATCH 225/302] Basic Lounge functionality. --- osu.Game.Tests/Visual/TestCaseLounge.cs | 158 ++++++++++++++++++ osu.Game.Tests/Visual/TestCaseMultiHeader.cs | 6 +- .../Screens/Multi/Components/DrawableRoom.cs | 33 +++- osu.Game/Screens/Multi/Multiplayer.cs | 8 +- osu.Game/Screens/Multi/Screens/Lobby.cs | 16 -- osu.Game/Screens/Multi/Screens/Lounge.cs | 115 +++++++++++++ osu.Game/Screens/Multi/Screens/Match.cs | 5 + 7 files changed, 312 insertions(+), 29 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseLounge.cs delete mode 100644 osu.Game/Screens/Multi/Screens/Lobby.cs create mode 100644 osu.Game/Screens/Multi/Screens/Lounge.cs diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs new file mode 100644 index 0000000000..b621899949 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseLounge.cs @@ -0,0 +1,158 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Screens.Multi.Screens; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseLounge : OsuTestCase + { + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + Lounge lounge = new Lounge(); + + Room[] rooms = + { + new Room + { + Name = { Value = @"Just Another Room" }, + Host = { Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } } }, + Status = { Value = new RoomStatusPlaying() }, + Type = { Value = new GameTypeTagTeam() }, + Beatmap = + { + Value = new BeatmapInfo + { + StarDifficulty = 5.65, + Ruleset = rulesets.GetRuleset(0), + Metadata = new BeatmapMetadata + { + Title = @"Sidetracked Day (Short Ver.)", + Artist = @"VINXIS", + AuthorString = @"Hobbes2", + }, + BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/767600/covers/cover.jpg?1526243446", + }, + }, + }, + } + }, + MaxParticipants = { Value = 10 }, + Participants = + { + Value = new[] + { + new User { Username = @"flyte", Id = 3103765, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 142 } } }, + new User { Username = @"Cookiezi", Id = 124493, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 546 } } }, + new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 287 } } }, + new User { Username = @"Rafis", Id = 2558286, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 468 } } }, + new User { Username = @"hvick225", Id = 50265, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 325 } } }, + new User { Username = @"peppy", Id = 2, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 625 } } }, + } + } + }, + new Room + { + Name = { Value = @"Not Just Any Room" }, + Host = { Value = new User { Username = @"Monstrata", Id = 2706438, Country = new Country { FlagName = @"CA" } } }, + Status = { Value = new RoomStatusOpen() }, + Type = { Value = new GameTypeTeamVersus() }, + Beatmap = + { + Value = new BeatmapInfo + { + StarDifficulty = 2.73, + Ruleset = rulesets.GetRuleset(0), + Metadata = new BeatmapMetadata + { + Title = @"lit(var)", + Artist = @"kensuke ushio", + AuthorString = @"Monstrata", + }, + BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/623972/covers/cover.jpg?1521167183", + }, + }, + }, + } + }, + Participants = + { + Value = new[] + { + new User { Username = @"Jeby", Id = 3136279, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 3497 } } }, + new User { Username = @"DualAkira", Id = 5220933, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 643 } } }, + new User { Username = @"Datenshi Yohane", Id = 7171857, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 10555 } } }, + } + } + }, + new Room + { + Name = { Value = @"room THE FINAL" }, + Host = { Value = new User { Username = @"Delis", Id = 1603923, Country = new Country { FlagName = @"JP" } } }, + Status = { Value = new RoomStatusPlaying() }, + Type = { Value = new GameTypeTagTeam() }, + Beatmap = + { + Value = new BeatmapInfo + { + StarDifficulty = 4.48, + Ruleset = rulesets.GetRuleset(3), + Metadata = new BeatmapMetadata + { + Title = @"663098", + Artist = @"OISHII", + AuthorString = @"Mentholzzz", + }, + BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/663098/covers/cover.jpg?1521898837", + }, + }, + }, + } + }, + MaxParticipants = { Value = 30 }, + Participants = + { + Value = new[] + { + new User { Username = @"KizuA", Id = 6510442, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 5372 } } }, + new User { Username = @"Colored", Id = 827563, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 810 } } }, + new User { Username = @"Beryl", Id = 3817591, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 10096 } } }, + } + } + }, + }; + + AddStep(@"show", () => Add(lounge)); + AddStep(@"set rooms", () => lounge.Rooms = rooms); + AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {}); + AddStep(@"set rooms", () => lounge.Rooms = rooms); + AddStep(@"exit", lounge.Exit); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs index af51a6221f..4406676aca 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs @@ -13,14 +13,14 @@ namespace osu.Game.Tests.Visual { public TestCaseMultiHeader() { - Lobby lobby; + Lounge lounge; Children = new Drawable[] { - lobby = new Lobby + lounge = new Lounge { Padding = new MarginPadding { Top = Header.HEIGHT }, }, - new Header(lobby), + new Header(lounge), }; } } diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 88a253d719..e5ba1a87cf 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -9,6 +9,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; @@ -25,8 +26,8 @@ namespace osu.Game.Screens.Multi.Components { public class DrawableRoom : OsuClickableContainer, IStateful { + public const float SELECTION_BORDER_WIDTH = 4; private const float corner_radius = 5; - private const float selection_border_width = 4; private const float transition_duration = 100; private const float content_padding = 10; private const float height = 100; @@ -62,6 +63,17 @@ namespace osu.Game.Screens.Multi.Components } } + private Action action; + public new Action Action + { + get { return action; } + set + { + action = value; + Enabled.Value = action != null; + } + } + public event Action StateChanged; public DrawableRoom(Room room) @@ -69,8 +81,8 @@ namespace osu.Game.Screens.Multi.Components Room = room; RelativeSizeAxes = Axes.X; - Height = height + selection_border_width * 2; - CornerRadius = corner_radius + selection_border_width / 2; + Height = height + SELECTION_BORDER_WIDTH * 2; + CornerRadius = corner_radius + SELECTION_BORDER_WIDTH / 2; Masking = true; // create selectionBox here so State can be set before being loaded @@ -79,8 +91,6 @@ namespace osu.Game.Screens.Multi.Components RelativeSizeAxes = Axes.Both, Alpha = 0f, }; - - Action += () => State = SelectionState.Selected; } [BackgroundDependencyLoader] @@ -98,7 +108,7 @@ namespace osu.Game.Screens.Multi.Components new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(selection_border_width), + Padding = new MarginPadding(SELECTION_BORDER_WIDTH), Child = new Container { RelativeSizeAxes = Axes.Both, @@ -272,5 +282,16 @@ namespace osu.Game.Screens.Multi.Components beatmapBind.BindTo(Room.Beatmap); participantsBind.BindTo(Room.Participants); } + + protected override bool OnClick(InputState state) + { + if (Enabled.Value) + { + Action?.Invoke(this); + State = SelectionState.Selected; + } + + return true; + } } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index b3d393209c..347a12dd56 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Multi RelativeSizeAxes = Axes.Both, }; - Lobby lobby; + Lounge lounge; Children = new Drawable[] { new Container @@ -52,12 +52,12 @@ namespace osu.Game.Screens.Multi { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = lobby = new Lobby(), + Child = lounge = new Lounge(), }, - new Header(lobby), + new Header(lounge), }; - lobby.Exited += s => Exit(); + lounge.Exited += s => Exit(); } protected override void OnEntering(Screen last) diff --git a/osu.Game/Screens/Multi/Screens/Lobby.cs b/osu.Game/Screens/Multi/Screens/Lobby.cs deleted file mode 100644 index dcda40e0d7..0000000000 --- a/osu.Game/Screens/Multi/Screens/Lobby.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; - -namespace osu.Game.Screens.Multi.Screens -{ - public class Lobby : ScreenWhiteBox - { - protected override IEnumerable PossibleChildren => new[] { - typeof(MatchCreate), - typeof(Match) - }; - } -} diff --git a/osu.Game/Screens/Multi/Screens/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge.cs new file mode 100644 index 0000000000..b2ce94dd64 --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/Lounge.cs @@ -0,0 +1,115 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using System.Collections.Generic; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osu.Game.Overlays.SearchableList; +using osu.Game.Screens.Multi.Components; +using OpenTK; + +namespace osu.Game.Screens.Multi.Screens +{ + public class Lounge : MultiplayerScreen + { + private readonly Container content; + private readonly FillFlowContainer roomsFlow; + private readonly RoomInspector roomInspector; + + protected override Container TransitionContent => content; + + public override string Title => "lounge"; + public override string Name => "Lounge"; + + private IEnumerable rooms; + public IEnumerable Rooms + { + get { return rooms; } + set + { + if (Equals(value, rooms)) return; + rooms = value; + + var enumerable = rooms.ToList(); + + roomsFlow.Children = enumerable.Select(r => new DrawableRoom(r) + { + Action = didSelect, + }).ToList(); + + if (!enumerable.Contains(roomInspector.Room)) + roomInspector.Room = null; + } + } + + public Lounge() + { + Children = new Drawable[] + { + content = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new ScrollContainer + { + RelativeSizeAxes = Axes.Both, + Width = 0.55f, + Padding = new MarginPadding + { + Vertical = 35 - DrawableRoom.SELECTION_BORDER_WIDTH, + Right = 20 - DrawableRoom.SELECTION_BORDER_WIDTH + }, + Child = roomsFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + LayoutEasing = Easing.OutQuint, + LayoutDuration = 200, + Spacing = new Vector2(10 - DrawableRoom.SELECTION_BORDER_WIDTH * 2), + }, + }, + roomInspector = new RoomInspector + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Both, + Width = 0.45f, + }, + }, + }, + }; + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + content.Padding = new MarginPadding + { + Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH, + Right = SearchableListOverlay.WIDTH_PADDING, + }; + } + + private void didSelect(DrawableRoom room) + { + roomsFlow.Children.ForEach(c => + { + if (c != room) + c.State = SelectionState.NotSelected; + }); + + roomInspector.Room = room.Room; + + // open the room if its selected and is clicked again + if (room.State == SelectionState.Selected) + Push(new Match(room.Room)); + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Match.cs b/osu.Game/Screens/Multi/Screens/Match.cs index 4ba7fe9f6a..f6178d5691 100644 --- a/osu.Game/Screens/Multi/Screens/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Screens; +using osu.Game.Online.Multiplayer; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Play; using osu.Game.Screens.Select; @@ -21,6 +22,10 @@ namespace osu.Game.Screens.Multi.Screens protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); + public Match(Room room) + { + } + protected override void OnEntering(Screen last) { base.OnEntering(last); From f7a4a4eeef45c7afc392729949b70ecd12231b40 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 22 May 2018 00:24:39 -0300 Subject: [PATCH 226/302] Add Lounge FilterControl. --- osu.Game.Tests/Visual/TestCaseLounge.cs | 2 +- osu.Game.Tests/Visual/TestCaseMultiHeader.cs | 2 +- osu.Game/Online/Multiplayer/Room.cs | 1 + .../Online/Multiplayer/RoomAvailability.cs | 18 +++++++++ osu.Game/Screens/Multi/Multiplayer.cs | 2 +- .../Multi/Screens/Lounge/FilterControl.cs | 27 +++++++++++++ .../Multi/Screens/{ => Lounge}/Lounge.cs | 40 ++++++++++++++++++- 7 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Online/Multiplayer/RoomAvailability.cs create mode 100644 osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs rename osu.Game/Screens/Multi/Screens/{ => Lounge}/Lounge.cs (78%) diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs index b621899949..9dbc4012d5 100644 --- a/osu.Game.Tests/Visual/TestCaseLounge.cs +++ b/osu.Game.Tests/Visual/TestCaseLounge.cs @@ -6,7 +6,7 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Screens; +using osu.Game.Screens.Multi.Screens.Lounge; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs index 4406676aca..d27a447077 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Multi; -using osu.Game.Screens.Multi.Screens; +using osu.Game.Screens.Multi.Screens.Lounge; namespace osu.Game.Tests.Visual { diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index f1c23e9e84..ae3fb5ec6e 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -12,6 +12,7 @@ namespace osu.Game.Online.Multiplayer public Bindable Name = new Bindable(); public Bindable Host = new Bindable(); public Bindable Status = new Bindable(); + public Bindable Availability = new Bindable(); public Bindable Type = new Bindable(); public Bindable Beatmap = new Bindable(); public Bindable MaxParticipants = new Bindable(); diff --git a/osu.Game/Online/Multiplayer/RoomAvailability.cs b/osu.Game/Online/Multiplayer/RoomAvailability.cs new file mode 100644 index 0000000000..6c154207ff --- /dev/null +++ b/osu.Game/Online/Multiplayer/RoomAvailability.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel; + +namespace osu.Game.Online.Multiplayer +{ + public enum RoomAvailability + { + Public, + + [Description(@"Friends Only")] + FriendsOnly, + + [Description(@"Invite Only")] + InviteOnly, + } +} diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 347a12dd56..ddaeb26806 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -8,7 +8,7 @@ using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; -using osu.Game.Screens.Multi.Screens; +using osu.Game.Screens.Multi.Screens.Lounge; namespace osu.Game.Screens.Multi { diff --git a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs b/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs new file mode 100644 index 0000000000..421c89479a --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osu.Game.Online.Multiplayer; +using osu.Game.Overlays.SearchableList; +using OpenTK.Graphics; + +namespace osu.Game.Screens.Multi.Screens.Lounge +{ + public class FilterControl : SearchableListFilterControl + { + protected override Color4 BackgroundColour => OsuColour.FromHex(@"362e42"); + protected override LoungeTab DefaultTab => LoungeTab.Public; + + public FilterControl() + { + DisplayStyleControl.Hide(); + } + } + + public enum LoungeTab + { + Public = RoomAvailability.Public, + Private = RoomAvailability.FriendsOnly, + } +} diff --git a/osu.Game/Screens/Multi/Screens/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs similarity index 78% rename from osu.Game/Screens/Multi/Screens/Lounge.cs rename to osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index b2ce94dd64..39aa1d73e7 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -1,21 +1,24 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using System.Collections.Generic; +using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Framework.Screens; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osu.Game.Screens.Multi.Components; using OpenTK; -namespace osu.Game.Screens.Multi.Screens +namespace osu.Game.Screens.Multi.Screens.Lounge { public class Lounge : MultiplayerScreen { + private readonly FilterControl filter; private readonly Container content; private readonly FillFlowContainer roomsFlow; private readonly RoomInspector roomInspector; @@ -50,6 +53,7 @@ namespace osu.Game.Screens.Multi.Screens { Children = new Drawable[] { + filter = new FilterControl(), content = new Container { RelativeSizeAxes = Axes.Both, @@ -84,6 +88,8 @@ namespace osu.Game.Screens.Multi.Screens }, }, }; + + filter.Search.Exit += Exit; } protected override void UpdateAfterChildren() @@ -92,11 +98,41 @@ namespace osu.Game.Screens.Multi.Screens content.Padding = new MarginPadding { + Top = filter.DrawHeight, Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH, Right = SearchableListOverlay.WIDTH_PADDING, }; } + protected override void OnFocus(InputState state) + { + GetContainingInputManager().ChangeFocus(filter.Search); + } + + protected override void OnEntering(Screen last) + { + base.OnEntering(last); + filter.Search.HoldFocus = true; + } + + protected override bool OnExiting(Screen next) + { + filter.Search.HoldFocus = false; + return base.OnExiting(next); + } + + protected override void OnResuming(Screen last) + { + base.OnResuming(last); + filter.Search.HoldFocus = true; + } + + protected override void OnSuspending(Screen next) + { + base.OnSuspending(next); + filter.Search.HoldFocus = false; + } + private void didSelect(DrawableRoom room) { roomsFlow.Children.ForEach(c => From 6aac4269e6c4e458a41ee5ebf64d0adca01d07ac Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 22 May 2018 00:33:41 -0300 Subject: [PATCH 227/302] Add filtering. --- .../Screens/Multi/Components/DrawableRoom.cs | 18 ++++++- .../Screens/Multi/Screens/Lounge/Lounge.cs | 52 ++++++++++++++++--- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index e5ba1a87cf..94f5f95062 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -24,7 +25,7 @@ using OpenTK.Graphics; namespace osu.Game.Screens.Multi.Components { - public class DrawableRoom : OsuClickableContainer, IStateful + public class DrawableRoom : OsuClickableContainer, IStateful, IFilterable { public const float SELECTION_BORDER_WIDTH = 4; private const float corner_radius = 5; @@ -63,6 +64,21 @@ namespace osu.Game.Screens.Multi.Components } } + public IEnumerable FilterTerms => new[] { Room.Name.Value }; + + private bool matchingFilter; + public bool MatchingFilter + { + get { return matchingFilter; } + set + { + if (value == matchingFilter) return; + matchingFilter = value; + + this.FadeTo(MatchingFilter ? 1 : 0, 200); + } + } + private Action action; public new Action Action { diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 39aa1d73e7..26c4acdcfd 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -20,7 +20,8 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { private readonly FilterControl filter; private readonly Container content; - private readonly FillFlowContainer roomsFlow; + private readonly SearchContainer search; + private readonly RoomsFilterContainer roomsFlow; private readonly RoomInspector roomInspector; protected override Container TransitionContent => content; @@ -46,6 +47,8 @@ namespace osu.Game.Screens.Multi.Screens.Lounge if (!enumerable.Contains(roomInspector.Room)) roomInspector.Room = null; + + filterRooms(); } } @@ -68,14 +71,17 @@ namespace osu.Game.Screens.Multi.Screens.Lounge Vertical = 35 - DrawableRoom.SELECTION_BORDER_WIDTH, Right = 20 - DrawableRoom.SELECTION_BORDER_WIDTH }, - Child = roomsFlow = new FillFlowContainer + Child = search = new SearchContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - LayoutEasing = Easing.OutQuint, - LayoutDuration = 200, - Spacing = new Vector2(10 - DrawableRoom.SELECTION_BORDER_WIDTH * 2), + Child = roomsFlow = new RoomsFilterContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10 - DrawableRoom.SELECTION_BORDER_WIDTH * 2), + }, }, }, roomInspector = new RoomInspector @@ -89,6 +95,8 @@ namespace osu.Game.Screens.Multi.Screens.Lounge }, }; + filter.Search.Current.ValueChanged += s => filterRooms(); + filter.Tabs.Current.ValueChanged += t => filterRooms(); filter.Search.Exit += Exit; } @@ -133,6 +141,17 @@ namespace osu.Game.Screens.Multi.Screens.Lounge filter.Search.HoldFocus = false; } + private void filterRooms() + { + search.SearchTerm = filter.Search.Current.Value ?? string.Empty; + + foreach (DrawableRoom r in roomsFlow.Children) + { + r.MatchingFilter = r.MatchingFilter && + r.Room.Availability.Value == (RoomAvailability)filter.Tabs.Current.Value; + } + } + private void didSelect(DrawableRoom room) { roomsFlow.Children.ForEach(c => @@ -147,5 +166,26 @@ namespace osu.Game.Screens.Multi.Screens.Lounge if (room.State == SelectionState.Selected) Push(new Match(room.Room)); } + + private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren + { + public IEnumerable FilterTerms => new string[] { }; + public IEnumerable FilterableChildren => Children; + + public bool MatchingFilter + { + set + { + if (value) + InvalidateLayout(); + } + } + + public RoomsFilterContainer() + { + LayoutDuration = 200; + LayoutEasing = Easing.OutQuint; + } + } } } From 662559d3c993859a9fd24c3aaab74c690edbdf82 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 22 May 2018 01:22:23 -0300 Subject: [PATCH 228/302] More test steps. --- osu.Game.Tests/Visual/TestCaseLounge.cs | 58 ++++++++++++++++++- .../Screens/Multi/Components/DrawableRoom.cs | 2 - .../Screens/Multi/Screens/Lounge/Lounge.cs | 48 +++++++-------- 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs index 9dbc4012d5..a89c12a1be 100644 --- a/osu.Game.Tests/Visual/TestCaseLounge.cs +++ b/osu.Game.Tests/Visual/TestCaseLounge.cs @@ -1,23 +1,29 @@ // 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 NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; +using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Screens.Lounge; using osu.Game.Users; +using OpenTK.Input; namespace osu.Game.Tests.Visual { [TestFixture] - public class TestCaseLounge : OsuTestCase + public class TestCaseLounge : ManualInputManagerTestCase { + private TestLounge lounge; + [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - Lounge lounge = new Lounge(); + lounge = new TestLounge(); Room[] rooms = { @@ -26,6 +32,7 @@ namespace osu.Game.Tests.Visual Name = { Value = @"Just Another Room" }, Host = { Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } } }, Status = { Value = new RoomStatusPlaying() }, + Availability = { Value = RoomAvailability.Public }, Type = { Value = new GameTypeTagTeam() }, Beatmap = { @@ -70,6 +77,7 @@ namespace osu.Game.Tests.Visual Name = { Value = @"Not Just Any Room" }, Host = { Value = new User { Username = @"Monstrata", Id = 2706438, Country = new Country { FlagName = @"CA" } } }, Status = { Value = new RoomStatusOpen() }, + Availability = { Value = RoomAvailability.FriendsOnly }, Type = { Value = new GameTypeTeamVersus() }, Beatmap = { @@ -110,6 +118,7 @@ namespace osu.Game.Tests.Visual Name = { Value = @"room THE FINAL" }, Host = { Value = new User { Username = @"Delis", Id = 1603923, Country = new Country { FlagName = @"JP" } } }, Status = { Value = new RoomStatusPlaying() }, + Availability = { Value = RoomAvailability.Public }, Type = { Value = new GameTypeTagTeam() }, Beatmap = { @@ -150,9 +159,54 @@ namespace osu.Game.Tests.Visual AddStep(@"show", () => Add(lounge)); AddStep(@"set rooms", () => lounge.Rooms = rooms); + selectAssert(0); + AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {}); + AddAssert(@"no room selected", () => lounge.SelectedRoom == null); + AddStep(@"set rooms", () => lounge.Rooms = rooms); + selectAssert(1); + AddStep(@"open room 1", () => clickRoom(1)); + AddStep(@"make lounge current", lounge.MakeCurrent); + filterAssert(@"THE FINAL", LoungeTab.Public, 1); + filterAssert(string.Empty, LoungeTab.Public, 2); + filterAssert(string.Empty, LoungeTab.Private, 1); + filterAssert(string.Empty, LoungeTab.Public, 2); + filterAssert(@"no matches", LoungeTab.Public, 0); AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {}); AddStep(@"set rooms", () => lounge.Rooms = rooms); + AddAssert(@"no matches after clear", () => lounge.MatchedCount == 0); + filterAssert(string.Empty, LoungeTab.Public, 2); AddStep(@"exit", lounge.Exit); } + + private void clickRoom(int n) + { + InputManager.MoveMouseTo(lounge.ChildRooms[n]); + InputManager.Click(MouseButton.Left); + } + + private void selectAssert(int n) + { + AddStep($@"select room {n}", () => clickRoom(n)); + AddAssert($@"room {n} selected", () => lounge.SelectedRoom == lounge.ChildRooms[n].Room); + } + + private void filterAssert(string filter, LoungeTab tab, int endCount) + { + AddStep($@"filter '{filter}', {tab}", () => lounge.SetFilter(filter, tab)); + AddAssert(@"filtered correctly", () => lounge.MatchedCount == endCount); + } + + private class TestLounge : Lounge + { + public IReadOnlyList ChildRooms => RoomsContainer.Children; + public Room SelectedRoom => Inspector.Room; + public int MatchedCount => ChildRooms.Count(r => r.MatchingFilter); + + public void SetFilter(string filter, LoungeTab tab) + { + Filter.Search.Current.Value = filter; + Filter.Tabs.Current.Value = tab; + } + } } } diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 94f5f95062..d11d4a4795 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -72,9 +72,7 @@ namespace osu.Game.Screens.Multi.Components get { return matchingFilter; } set { - if (value == matchingFilter) return; matchingFilter = value; - this.FadeTo(MatchingFilter ? 1 : 0, 200); } } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 26c4acdcfd..30ca897c1a 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -18,16 +18,16 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { public class Lounge : MultiplayerScreen { - private readonly FilterControl filter; private readonly Container content; private readonly SearchContainer search; - private readonly RoomsFilterContainer roomsFlow; - private readonly RoomInspector roomInspector; - protected override Container TransitionContent => content; + protected readonly FilterControl Filter; + protected readonly FillFlowContainer RoomsContainer; + protected readonly RoomInspector Inspector; public override string Title => "lounge"; public override string Name => "Lounge"; + protected override Container TransitionContent => content; private IEnumerable rooms; public IEnumerable Rooms @@ -40,13 +40,13 @@ namespace osu.Game.Screens.Multi.Screens.Lounge var enumerable = rooms.ToList(); - roomsFlow.Children = enumerable.Select(r => new DrawableRoom(r) + RoomsContainer.Children = enumerable.Select(r => new DrawableRoom(r) { Action = didSelect, }).ToList(); - if (!enumerable.Contains(roomInspector.Room)) - roomInspector.Room = null; + if (!enumerable.Contains(Inspector.Room)) + Inspector.Room = null; filterRooms(); } @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { Children = new Drawable[] { - filter = new FilterControl(), + Filter = new FilterControl(), content = new Container { RelativeSizeAxes = Axes.Both, @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = roomsFlow = new RoomsFilterContainer + Child = RoomsContainer = new RoomsFilterContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge }, }, }, - roomInspector = new RoomInspector + Inspector = new RoomInspector { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -95,9 +95,9 @@ namespace osu.Game.Screens.Multi.Screens.Lounge }, }; - filter.Search.Current.ValueChanged += s => filterRooms(); - filter.Tabs.Current.ValueChanged += t => filterRooms(); - filter.Search.Exit += Exit; + Filter.Search.Current.ValueChanged += s => filterRooms(); + Filter.Tabs.Current.ValueChanged += t => filterRooms(); + Filter.Search.Exit += Exit; } protected override void UpdateAfterChildren() @@ -106,7 +106,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge content.Padding = new MarginPadding { - Top = filter.DrawHeight, + Top = Filter.DrawHeight, Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH, Right = SearchableListOverlay.WIDTH_PADDING, }; @@ -114,53 +114,53 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected override void OnFocus(InputState state) { - GetContainingInputManager().ChangeFocus(filter.Search); + GetContainingInputManager().ChangeFocus(Filter.Search); } protected override void OnEntering(Screen last) { base.OnEntering(last); - filter.Search.HoldFocus = true; + Filter.Search.HoldFocus = true; } protected override bool OnExiting(Screen next) { - filter.Search.HoldFocus = false; + Filter.Search.HoldFocus = false; return base.OnExiting(next); } protected override void OnResuming(Screen last) { base.OnResuming(last); - filter.Search.HoldFocus = true; + Filter.Search.HoldFocus = true; } protected override void OnSuspending(Screen next) { base.OnSuspending(next); - filter.Search.HoldFocus = false; + Filter.Search.HoldFocus = false; } private void filterRooms() { - search.SearchTerm = filter.Search.Current.Value ?? string.Empty; + search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; - foreach (DrawableRoom r in roomsFlow.Children) + foreach (DrawableRoom r in RoomsContainer.Children) { r.MatchingFilter = r.MatchingFilter && - r.Room.Availability.Value == (RoomAvailability)filter.Tabs.Current.Value; + r.Room.Availability.Value == (RoomAvailability)Filter.Tabs.Current.Value; } } private void didSelect(DrawableRoom room) { - roomsFlow.Children.ForEach(c => + RoomsContainer.Children.ForEach(c => { if (c != room) c.State = SelectionState.NotSelected; }); - roomInspector.Room = room.Room; + Inspector.Room = room.Room; // open the room if its selected and is clicked again if (room.State == SelectionState.Selected) From fba79a4de651a3cab48ceb58b8acd2cd120df4fc Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 22 May 2018 01:31:01 -0300 Subject: [PATCH 229/302] Test typo. --- osu.Game.Tests/Visual/TestCaseLounge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs index a89c12a1be..8a3bc79e8d 100644 --- a/osu.Game.Tests/Visual/TestCaseLounge.cs +++ b/osu.Game.Tests/Visual/TestCaseLounge.cs @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual Ruleset = rulesets.GetRuleset(3), Metadata = new BeatmapMetadata { - Title = @"663098", + Title = @"ONIGIRI FREEWAY", Artist = @"OISHII", AuthorString = @"Mentholzzz", }, From 3cc5bb516e6c875f415ca7d519ed78468eed2665 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 22 May 2018 01:39:25 -0300 Subject: [PATCH 230/302] Remove unused Match ctor param. --- osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs | 2 +- osu.Game/Screens/Multi/Screens/Match.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 30ca897c1a..01a7510f76 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -164,7 +164,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge // open the room if its selected and is clicked again if (room.State == SelectionState.Selected) - Push(new Match(room.Room)); + Push(new Match()); } private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren diff --git a/osu.Game/Screens/Multi/Screens/Match.cs b/osu.Game/Screens/Multi/Screens/Match.cs index f6178d5691..d57f43fcd1 100644 --- a/osu.Game/Screens/Multi/Screens/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Screens; -using osu.Game.Online.Multiplayer; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Play; using osu.Game.Screens.Select; @@ -22,7 +21,7 @@ namespace osu.Game.Screens.Multi.Screens protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); - public Match(Room room) + public Match() { } From 349b0a33221acf335cb9bae3a99178fc2522036b Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 22 May 2018 01:46:08 -0300 Subject: [PATCH 231/302] Remove empty ctor. --- osu.Game/Screens/Multi/Screens/Match.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Screens/Match.cs b/osu.Game/Screens/Multi/Screens/Match.cs index d57f43fcd1..4ba7fe9f6a 100644 --- a/osu.Game/Screens/Multi/Screens/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match.cs @@ -21,10 +21,6 @@ namespace osu.Game.Screens.Multi.Screens protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); - public Match() - { - } - protected override void OnEntering(Screen last) { base.OnEntering(last); From 0b19b7d9e56f64032207c9c36ea0a4382919e781 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 22 May 2018 02:08:50 -0300 Subject: [PATCH 232/302] Fix test case. --- osu.Game.Tests/Visual/TestCaseLounge.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs index 8a3bc79e8d..b96d705d5c 100644 --- a/osu.Game.Tests/Visual/TestCaseLounge.cs +++ b/osu.Game.Tests/Visual/TestCaseLounge.cs @@ -173,34 +173,33 @@ namespace osu.Game.Tests.Visual filterAssert(@"no matches", LoungeTab.Public, 0); AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {}); AddStep(@"set rooms", () => lounge.Rooms = rooms); - AddAssert(@"no matches after clear", () => lounge.MatchedCount == 0); + AddAssert(@"no matches after clear", () => !lounge.ChildRooms.Any()); filterAssert(string.Empty, LoungeTab.Public, 2); AddStep(@"exit", lounge.Exit); } private void clickRoom(int n) { - InputManager.MoveMouseTo(lounge.ChildRooms[n]); + InputManager.MoveMouseTo(lounge.ChildRooms.ElementAt(n)); InputManager.Click(MouseButton.Left); } private void selectAssert(int n) { AddStep($@"select room {n}", () => clickRoom(n)); - AddAssert($@"room {n} selected", () => lounge.SelectedRoom == lounge.ChildRooms[n].Room); + AddAssert($@"room {n} selected", () => lounge.SelectedRoom == lounge.ChildRooms.ElementAt(n).Room); } private void filterAssert(string filter, LoungeTab tab, int endCount) { AddStep($@"filter '{filter}', {tab}", () => lounge.SetFilter(filter, tab)); - AddAssert(@"filtered correctly", () => lounge.MatchedCount == endCount); + AddAssert(@"filtered correctly", () => lounge.ChildRooms.Count() == endCount); } private class TestLounge : Lounge { - public IReadOnlyList ChildRooms => RoomsContainer.Children; + public IEnumerable ChildRooms => RoomsContainer.Children.Where(r => r.MatchingFilter); public Room SelectedRoom => Inspector.Room; - public int MatchedCount => ChildRooms.Count(r => r.MatchingFilter); public void SetFilter(string filter, LoungeTab tab) { From 2ce2bd9788aabec4ca0db917a057c710f1ba9719 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 15:58:00 +0900 Subject: [PATCH 233/302] Add comment for pendingAnimation --- osu.Game/Screens/Play/HUD/QuitButton.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index e829d26aab..a26e0a2aae 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -144,6 +144,8 @@ namespace osu.Game.Screens.Play.HUD // temporarily unbind as to not look weird during flash animation. Progress.UnbindAll(); + + // avoid starting a new confirm call until we finish animating. pendingAnimation = true; innerCircle.ScaleTo(0, 100) From ef55c3c1971de6e7ed8e329223673c9bd11d701c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 15:58:17 +0900 Subject: [PATCH 234/302] Fix icon scale not resetting due to no implicit triggering --- osu.Game/Screens/Play/HUD/QuitButton.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index a26e0a2aae..defaf002b8 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -133,7 +133,9 @@ namespace osu.Game.Screens.Play.HUD private void bind() { circularProgress.Current.BindTo(Progress); + Progress.ValueChanged += v => icon.Scale = new Vector2(1 + (float)v * 0.4f); + Progress.TriggerChange(); } private bool pendingAnimation; From 58ae54574701520ce54cbc8065f254549a02c233 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 15:59:53 +0900 Subject: [PATCH 235/302] innerCircle -> overlayCircle --- osu.Game/Screens/Play/HUD/QuitButton.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index defaf002b8..2ee1b97136 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Play.HUD { private SpriteIcon icon; private CircularProgress circularProgress; - private Circle innerCircle; + private Circle overlayCircle; protected override bool AllowMultipleFires => true; @@ -108,7 +108,7 @@ namespace osu.Game.Screens.Play.HUD RelativeSizeAxes = Axes.Both, InnerRadius = 1 }, - innerCircle = new Circle + overlayCircle = new Circle { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -150,7 +150,7 @@ namespace osu.Game.Screens.Play.HUD // avoid starting a new confirm call until we finish animating. pendingAnimation = true; - innerCircle.ScaleTo(0, 100) + overlayCircle.ScaleTo(0, 100) .Then().FadeOut().ScaleTo(1).FadeIn(500) .OnComplete(a => circularProgress.FadeOut(100).OnComplete(_ => { From 8fbda9d57ea02add62558f60571a5e00f1442620 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 16:04:07 +0900 Subject: [PATCH 236/302] Improve comment --- osu.Game/Screens/Play/HUD/QuitButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 2ee1b97136..bbd6075332 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -144,7 +144,7 @@ namespace osu.Game.Screens.Play.HUD { base.Confirm(); - // temporarily unbind as to not look weird during flash animation. + // temporarily unbind as to not look weird if releasing during confirm animation (can see the unwind of progress). Progress.UnbindAll(); // avoid starting a new confirm call until we finish animating. From 5f8eb6d8231cd2ab53f8d2031d372606406720eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 16:04:36 +0900 Subject: [PATCH 237/302] Fix class name --- .../{HoldToCofirmContainer.cs => HoldToConfirmContainer.cs} | 2 +- osu.Game/Overlays/HoldToConfirmOverlay.cs | 2 +- osu.Game/Screens/Play/HUD/QuitButton.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Graphics/Containers/{HoldToCofirmContainer.cs => HoldToConfirmContainer.cs} (95%) diff --git a/osu.Game/Graphics/Containers/HoldToCofirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs similarity index 95% rename from osu.Game/Graphics/Containers/HoldToCofirmContainer.cs rename to osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index eb2b2ca51b..adfc258f61 100644 --- a/osu.Game/Graphics/Containers/HoldToCofirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Graphics.Containers { - public abstract class HoldToCofirmContainer : Container + public abstract class HoldToConfirmContainer : Container { public Action Action; diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index afd3e2016f..7e2f6f5891 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays /// An overlay which will display a black screen that dims over a period before confirming an exit action. /// Action is BYO (derived class will need to call and from a user event). /// - public abstract class HoldToConfirmOverlay : HoldToCofirmContainer + public abstract class HoldToConfirmOverlay : HoldToConfirmContainer { private Box overlay; diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index bbd6075332..924c8d35ee 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Play.HUD Alpha = stayVisible ? 1 : Interpolation.ValueAt(elapsed, Alpha, MathHelper.Clamp(1 - adjust, 0.04f, 1), 0, 200, Easing.OutQuint); } - private class Button : HoldToCofirmContainer + private class Button : HoldToConfirmContainer { private SpriteIcon icon; private CircularProgress circularProgress; From babb7d5158d860123b00bb76c58d0a0d395df8c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 16:23:05 +0900 Subject: [PATCH 238/302] Fix white ring flash when holding button post-confirmation --- osu.Game/Screens/Play/HUD/QuitButton.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 924c8d35ee..9f59d4164f 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -151,13 +151,16 @@ namespace osu.Game.Screens.Play.HUD pendingAnimation = true; overlayCircle.ScaleTo(0, 100) - .Then().FadeOut().ScaleTo(1).FadeIn(500) - .OnComplete(a => circularProgress.FadeOut(100).OnComplete(_ => - { - bind(); - circularProgress.FadeIn(); - pendingAnimation = false; - })); + .Then().FadeOut().ScaleTo(1).FadeIn(500) + .OnComplete(a => circularProgress.FadeOut(100).OnComplete(_ => + { + Progress.Value = 0; + + bind(); + + circularProgress.FadeIn(); + pendingAnimation = false; + })); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) From 7b770d03c5b99a83434e636dc37ae08f71abb41b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 16:26:11 +0900 Subject: [PATCH 239/302] Use OnMouseMove instead of Update logic --- osu.Game/Screens/Play/HUD/QuitButton.cs | 47 ++++++++++++++++--------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 9f59d4164f..8c59427edb 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Play.HUD { public class QuitButton : FillFlowContainer { - public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => button.ReceiveMouseInputAt(screenSpacePos); + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; private readonly Button button; @@ -43,7 +43,11 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }, - button = new Button() + button = new Button + { + HoverGained = () => text.FadeIn(500, Easing.OutQuint), + HoverLost = () => text.FadeOut(500, Easing.OutQuint) + } }; AutoSizeAxes = Axes.Both; } @@ -54,28 +58,24 @@ namespace osu.Game.Screens.Play.HUD base.LoadComplete(); } - protected override bool OnHover(InputState state) - { - text.FadeIn(500, Easing.OutQuint); - return true; - } + private float positionalAdjust; - protected override void OnHoverLost(InputState state) + protected override bool OnMouseMove(InputState state) { - text.FadeOut(500, Easing.OutQuint); - base.OnHoverLost(state); + positionalAdjust = Vector2.Distance(state.Mouse.NativeState.Position, button.ScreenSpaceDrawQuad.Centre) / 200; + return base.OnMouseMove(state); } protected override void Update() { base.Update(); - float adjust = Vector2.Distance(GetContainingInputManager().CurrentState.Mouse.NativeState.Position, button.ScreenSpaceDrawQuad.Centre) / 200; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); - - bool stayVisible = text.Alpha > 0 || button.Progress.Value > 0 || IsHovered; - - Alpha = stayVisible ? 1 : Interpolation.ValueAt(elapsed, Alpha, MathHelper.Clamp(1 - adjust, 0.04f, 1), 0, 200, Easing.OutQuint); + if (text.Alpha > 0 || button.Progress.Value > 0 || button.IsHovered) + Alpha = 1; + else + Alpha = Interpolation.ValueAt( + MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), + Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); } private class Button : HoldToConfirmContainer @@ -86,6 +86,9 @@ namespace osu.Game.Screens.Play.HUD protected override bool AllowMultipleFires => true; + public Action HoverGained; + public Action HoverLost; + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -163,6 +166,18 @@ namespace osu.Game.Screens.Play.HUD })); } + protected override bool OnHover(InputState state) + { + HoverGained?.Invoke(); + return true; + } + + protected override void OnHoverLost(InputState state) + { + HoverLost?.Invoke(); + base.OnHoverLost(state); + } + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { if (!pendingAnimation && state.Mouse.Buttons.Count == 1) From 436067c01f52c8a3f91c48637d86caef65f936d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 16:44:37 +0900 Subject: [PATCH 240/302] Handle scale back in a nicer way --- osu.Game/Screens/Play/HUD/QuitButton.cs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 8c59427edb..43a24a3ba8 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -136,9 +136,7 @@ namespace osu.Game.Screens.Play.HUD private void bind() { circularProgress.Current.BindTo(Progress); - - Progress.ValueChanged += v => icon.Scale = new Vector2(1 + (float)v * 0.4f); - Progress.TriggerChange(); + Progress.ValueChanged += v => icon.Scale = new Vector2(1 + (float)v * 0.2f); } private bool pendingAnimation; @@ -155,15 +153,19 @@ namespace osu.Game.Screens.Play.HUD overlayCircle.ScaleTo(0, 100) .Then().FadeOut().ScaleTo(1).FadeIn(500) - .OnComplete(a => circularProgress.FadeOut(100).OnComplete(_ => + .OnComplete(a => { - Progress.Value = 0; + icon.ScaleTo(1, 100); + circularProgress.FadeOut(100).OnComplete(_ => + { + Progress.Value = 0; - bind(); + bind(); - circularProgress.FadeIn(); - pendingAnimation = false; - })); + circularProgress.FadeIn(); + pendingAnimation = false; + }); + }); } protected override bool OnHover(InputState state) From d43e4af8ea2136d0b1a0be3f6edb3c5ac9c502cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 16:45:42 +0900 Subject: [PATCH 241/302] Fix overlap between quit button at key input overlay --- osu.Game/Screens/Play/HUDOverlay.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index cba5c94266..f920b20649 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -52,15 +52,26 @@ namespace osu.Game.Screens.Play Children = new Drawable[] { - KeyCounter = CreateKeyCounter(), ComboCounter = CreateComboCounter(), ScoreCounter = CreateScoreCounter(), AccuracyCounter = CreateAccuracyCounter(), HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), - HoldToQuit = CreateQuitButton(), ModDisplay = CreateModsContainer(), - PlayerSettingsOverlay = CreatePlayerSettingsOverlay() + PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), + new FillFlowContainer + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + KeyCounter = CreateKeyCounter(), + HoldToQuit = CreateQuitButton(), + } + } } }); @@ -189,7 +200,6 @@ namespace osu.Game.Screens.Play Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding(10), - Y = -TwoLayerButton.SIZE_RETRACTED.Y, }; protected virtual ScoreCounter CreateScoreCounter() => new ScoreCounter(6) @@ -211,7 +221,6 @@ namespace osu.Game.Screens.Play { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, - Position = new Vector2(-5, -70) }; protected virtual ModDisplay CreateModsContainer() => new ModDisplay From 39de807445eeb353a8843b93dfd6fc72c640ccd7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 May 2018 16:46:55 +0900 Subject: [PATCH 242/302] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index b4d5c766f5..eb076a3301 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit b4d5c766f5698540a7b1bbbae7290ac7dafc2813 +Subproject commit eb076a3301231eb73917073499051e49a9b12978 From 0e122468dba15da4f5932d224249b303cea07ea5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 22 May 2018 18:06:40 +0900 Subject: [PATCH 243/302] Fix progress easing to 0 if aborting after confirmation --- osu.Game/Screens/Play/HUD/QuitButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/QuitButton.cs b/osu.Game/Screens/Play/HUD/QuitButton.cs index 43a24a3ba8..d0aa0dad92 100644 --- a/osu.Game/Screens/Play/HUD/QuitButton.cs +++ b/osu.Game/Screens/Play/HUD/QuitButton.cs @@ -151,6 +151,8 @@ namespace osu.Game.Screens.Play.HUD // avoid starting a new confirm call until we finish animating. pendingAnimation = true; + Progress.Value = 0; + overlayCircle.ScaleTo(0, 100) .Then().FadeOut().ScaleTo(1).FadeIn(500) .OnComplete(a => @@ -158,8 +160,6 @@ namespace osu.Game.Screens.Play.HUD icon.ScaleTo(1, 100); circularProgress.FadeOut(100).OnComplete(_ => { - Progress.Value = 0; - bind(); circularProgress.FadeIn(); From be0fc24ad409fb0583c79edb423110ec79484961 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Tue, 22 May 2018 20:51:37 +0800 Subject: [PATCH 244/302] Fixed banana generation on catch specific maps --- osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index 9dfe12f25e..5f9439534b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs @@ -8,8 +8,9 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch /// /// Legacy osu!catch Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime + internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasXPosition { + public float X { get; set; } public double EndTime { get; set; } public double Duration => EndTime - StartTime; From b324337fa1457dcf4019c28036535f0406cf9a14 Mon Sep 17 00:00:00 2001 From: jorolf Date: Tue, 22 May 2018 15:29:52 +0200 Subject: [PATCH 245/302] Add icon next to beatmap title/username to open in browser --- .../Visual/TestCaseExternalLinkButton.cs | 20 +++++++ .../UserInterface/ExternalLinkButton.cs | 58 +++++++++++++++++++ osu.Game/Overlays/BeatmapSet/Header.cs | 24 +++++++- osu.Game/Overlays/Profile/ProfileHeader.cs | 45 +++++++------- 4 files changed, 119 insertions(+), 28 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs create mode 100644 osu.Game/Graphics/UserInterface/ExternalLinkButton.cs diff --git a/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs b/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs new file mode 100644 index 0000000000..bdb077ce5a --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using osu.Game.Graphics.UserInterface; +using OpenTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseExternalLinkButton : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(ExternalLinkButton) }; + + public TestCaseExternalLinkButton() + { + Child = new ExternalLinkButton("https://osu.ppy.sh/home") + { + Size = new Vector2(50) + }; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs new file mode 100644 index 0000000000..800f77f547 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -0,0 +1,58 @@ +using System.Diagnostics; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Input; +using OpenTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public class ExternalLinkButton : CompositeDrawable, IHasTooltip + { + public string Link { get; set; } + + private Color4 hoverColour; + + public ExternalLinkButton(string link = null) + { + Link = link; + InternalChild = new SpriteIcon + { + Icon = FontAwesome.fa_external_link, + RelativeSizeAxes = Axes.Both + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoverColour = colours.Yellow; + } + + protected override bool OnHover(InputState state) + { + InternalChild.FadeColour(hoverColour, 500, Easing.OutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + InternalChild.FadeColour(Color4.White, 500, Easing.OutQuint); + base.OnHoverLost(state); + } + + protected override bool OnClick(InputState state) + { + if(Link != null) + Process.Start(new ProcessStartInfo + { + FileName = Link, + UseShellExecute = true //see https://github.com/dotnet/corefx/issues/10361 + }); + return true; + } + + public string TooltipText => "View in browser"; + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 9b25d61f58..7d07816d11 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.BeatmapSet.Buttons; using OpenTK; using OpenTK.Graphics; @@ -93,6 +94,7 @@ namespace osu.Game.Overlays.BeatmapSet public Header() { + ExternalLinkButton externalLink; RelativeSizeAxes = Axes.X; Height = 400; Masking = true; @@ -160,10 +162,25 @@ namespace osu.Game.Overlays.BeatmapSet Height = 113, Child = Picker = new BeatmapPicker(), }, - title = new OsuSpriteText + new FillFlowContainer { - Font = @"Exo2.0-BoldItalic", - TextSize = 37, + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + title = new OsuSpriteText + { + Font = @"Exo2.0-BoldItalic", + TextSize = 37, + }, + externalLink = new ExternalLinkButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Left = 3, Bottom = 4 }, //To better lineup with the font + Size = new Vector2(18), + }, + } }, artist = new OsuSpriteText { @@ -247,6 +264,7 @@ namespace osu.Game.Overlays.BeatmapSet }; Picker.Beatmap.ValueChanged += b => Details.Beatmap = b; + Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet?.OnlineBeatmapSetID}#{b?.Ruleset.ShortName}/{b?.OnlineBeatmapID}"; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 4c411b3210..1a4a00da2b 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Diagnostics; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -10,13 +9,13 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; @@ -105,11 +104,29 @@ namespace osu.Game.Overlays.Profile Y = -75, Size = new Vector2(25, 25) }, - new ProfileLink(user) + new FillFlowContainer { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Y = -48, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = user.Username, + Font = @"Exo2.0-RegularItalic", + TextSize = 30, + }, + new ExternalLinkButton($@"https://osu.ppy.sh/users/{user.Id}") + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Left = 3, Bottom = 3 }, //To better lineup with the font + Size = new Vector2(18), + }, + } }, countryFlag = new DrawableFlag(user.Country) { @@ -455,28 +472,6 @@ namespace osu.Game.Overlays.Profile infoTextRight.NewLine(); } - private class ProfileLink : OsuHoverContainer, IHasTooltip - { - public string TooltipText => "View Profile in Browser"; - - public override bool HandleMouseInput => true; - - public ProfileLink(User user) - { - Action = () => Process.Start($@"https://osu.ppy.sh/users/{user.Id}"); - - AutoSizeAxes = Axes.Both; - - Child = new OsuSpriteText - { - Text = user.Username, - Font = @"Exo2.0-RegularItalic", - TextSize = 30, - }; - } - } - - private class GradeBadge : Container { private const float width = 50; From 8fbda5bc59a736ca837f33e369812791202f8caf Mon Sep 17 00:00:00 2001 From: jorolf Date: Tue, 22 May 2018 15:41:10 +0200 Subject: [PATCH 246/302] add license header --- osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs | 5 ++++- osu.Game/Graphics/UserInterface/ExternalLinkButton.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs b/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs index bdb077ce5a..7d8535f428 100644 --- a/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs +++ b/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using System.Collections.Generic; using osu.Game.Graphics.UserInterface; using OpenTK; diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs index 800f77f547..025874a1a2 100644 --- a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -1,4 +1,7 @@ -using System.Diagnostics; +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From 76fbc656a18587d3299c04b858a91b155c79eb99 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Tue, 22 May 2018 17:53:36 +0200 Subject: [PATCH 247/302] fix disclaimer allowing notifications --- osu.Game/Screens/Menu/Disclaimer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 9a671cf780..b8cb7f2a4a 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -19,6 +19,7 @@ namespace osu.Game.Screens.Menu private Color4 iconColour; protected override bool HideOverlaysOnEnter => true; + protected override bool AllowOpeningOverlays => false; public override bool CursorVisible => false; From f894d73501d813d1999fb39d73bd193257b4f611 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 May 2018 14:36:09 +0900 Subject: [PATCH 248/302] Fix possible MusicController nullref --- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 8c8ff89420..966f09975d 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -101,7 +101,7 @@ namespace osu.Game.Overlays.Music private void updateSelectedSet() { foreach (PlaylistItem s in items.Children) - s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo.ID; + s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value?.BeatmapSetInfo?.ID; } public string SearchTerm From 28ad5398cc928deb58ec68fbb3d0d24313bec175 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Wed, 23 May 2018 13:46:12 +0800 Subject: [PATCH 249/302] Remove the changes in convert spinner --- osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index 5f9439534b..9dfe12f25e 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs @@ -8,9 +8,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch /// /// Legacy osu!catch Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasXPosition + internal sealed class ConvertSpinner : HitObject, IHasEndTime { - public float X { get; set; } public double EndTime { get; set; } public double Duration => EndTime - StartTime; From fda7025ac3793c575da44ca4620edf1a31d7ddab Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Wed, 23 May 2018 13:47:33 +0800 Subject: [PATCH 250/302] Re-order positionData judgement for correct banana creation --- .../Beatmaps/CatchBeatmapConverter.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index f40ef67dfb..60671d9383 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -28,7 +28,20 @@ namespace osu.Game.Rulesets.Catch.Beatmaps var endTime = obj as IHasEndTime; if (positionData == null) + { + if (endTime != null) + { + yield return new BananaShower + { + StartTime = obj.StartTime, + Samples = obj.Samples, + Duration = endTime.Duration, + NewCombo = comboData?.NewCombo ?? false + }; + + } yield break; + } if (curveData != null) { @@ -48,19 +61,6 @@ namespace osu.Game.Rulesets.Catch.Beatmaps yield break; } - if (endTime != null) - { - yield return new BananaShower - { - StartTime = obj.StartTime, - Samples = obj.Samples, - Duration = endTime.Duration, - NewCombo = comboData?.NewCombo ?? false - }; - - yield break; - } - yield return new Fruit { StartTime = obj.StartTime, From fb78854485072b1a919c8a4318b261a799349286 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 May 2018 19:41:13 +0900 Subject: [PATCH 251/302] Fix audio playback getting paused if playlist changes beatmap --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 76c2222f8b..085a44ecba 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -79,7 +79,10 @@ namespace osu.Game.Overlays.Music { BeatmapInfo beatmap = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); if (beatmap != null) + { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(beatmap); + beatmapBacking.Value.Track.Restart(); + } }; } @@ -109,6 +112,7 @@ namespace osu.Game.Overlays.Music } beatmapBacking.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First()); + beatmapBacking.Value.Track.Restart(); } } From 0c0f86fe26ec1785b67d52d50d9ad4fa9d62c8d7 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Wed, 23 May 2018 16:23:03 +0200 Subject: [PATCH 252/302] fix incorrect default values keeping overlays in wrong state --- osu.Game/Screens/OsuScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 4b1562291b..a188b7aa64 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -37,14 +37,14 @@ namespace osu.Game.Screens /// /// Whether overlays should be hidden when this screen is entered or resumed. /// - protected virtual bool HideOverlaysOnEnter => hideOverlaysOnEnter; + protected virtual bool HideOverlaysOnEnter => false; private readonly BindableBool allowOpeningOverlays = new BindableBool(); /// /// Whether overlays should be able to be opened while this screen is active. /// - protected virtual bool AllowOpeningOverlays => allowOpeningOverlays; + protected virtual bool AllowOpeningOverlays => true; /// /// Whether this allows the cursor to be displayed. From 568d4882c681b187d80e4bba3b99d0b00abeaaae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 May 2018 11:00:56 +0900 Subject: [PATCH 253/302] Remove unnecessary null coalesce --- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 966f09975d..d4bc8c5b27 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -101,7 +101,7 @@ namespace osu.Game.Overlays.Music private void updateSelectedSet() { foreach (PlaylistItem s in items.Children) - s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value?.BeatmapSetInfo?.ID; + s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo?.ID; } public string SearchTerm From 5e4f83b80b158cdf0ddadd60db430a0fc1d83a15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 May 2018 17:29:52 +0900 Subject: [PATCH 254/302] Add more correct catch playfield sizing --- osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 070dc19a6f..52763e09af 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -32,6 +32,8 @@ namespace osu.Game.Rulesets.Catch.UI public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); + protected override Vector2 PlayfieldArea => new Vector2(0.86f); // matches stable's vertical offset for catcher plate + protected override DrawableHitObject GetVisualRepresentation(CatchHitObject h) { switch (h) From 3fe25fe67d67d17eb5f0f6bca374317e97a17c96 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 May 2018 17:32:07 +0900 Subject: [PATCH 255/302] Fix catcher sizing to (roughly) match stable --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 34 ++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 181536a91e..59d5ecd07f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.UI { public class CatcherArea : Container { - public const float CATCHER_SIZE = 172; + public const float CATCHER_SIZE = 84; protected readonly Catcher MovableCatcher; @@ -99,8 +99,6 @@ namespace osu.Game.Rulesets.Catch.UI public class Catcher : Container, IKeyBindingHandler { - private Texture texture; - private Container caughtFruit; public Container ExplodingFruitTarget; @@ -121,10 +119,8 @@ namespace osu.Game.Rulesets.Catch.UI } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load() { - texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); - Children = new Drawable[] { caughtFruit = new Container @@ -196,13 +192,7 @@ namespace osu.Game.Rulesets.Catch.UI Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50); } - private Sprite createCatcherSprite() => new Sprite - { - Size = new Vector2(CATCHER_SIZE), - FillMode = FillMode.Fill, - Texture = texture, - OriginPosition = new Vector2(-3, 10) // temporary until the sprite is aligned correctly. - }; + private Sprite createCatcherSprite() => new CatcherSprite(); /// /// Add a caught fruit to the catcher's stack. @@ -411,6 +401,24 @@ namespace osu.Game.Rulesets.Catch.UI f.Expire(); } } + + private class CatcherSprite : Sprite + { + public CatcherSprite() + { + Size = new Vector2(CATCHER_SIZE); + FillMode = FillMode.Fill; + + // Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling. + OriginPosition = new Vector2(-0.02f, 0.06f) * CATCHER_SIZE; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); + } + } } } } From bf25e81c945398bbada55b44ebf29413c25363c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 May 2018 17:32:22 +0900 Subject: [PATCH 256/302] Make drawable bananas testable --- .../TestCaseCatcherArea.cs | 2 +- .../TestCaseFruitObjects.cs | 20 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index f239290ed4..5119260c53 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Catch.Tests Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) { Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomLeft + Origin = Anchor.TopLeft }, }; } diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs index 275752523d..e77dd76353 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Catch.Tests typeof(DrawableCatchHitObject), typeof(DrawableFruit), typeof(DrawableDroplet), + typeof(BananaShower), typeof(Pulp), }; @@ -53,12 +54,19 @@ namespace osu.Game.Rulesets.Catch.Tests private DrawableFruit createDrawable(int index) { - var fruit = new Fruit - { - StartTime = 1000000000000, - IndexInBeatmap = index, - Scale = 1.5f, - }; + Fruit fruit = index == 5 + ? new BananaShower.Banana + { + StartTime = 1000000000000, + IndexInBeatmap = index, + Scale = 1.5f, + } + : new Fruit + { + StartTime = 1000000000000, + IndexInBeatmap = index, + Scale = 1.5f, + }; return new DrawableFruit(fruit) { From f5ab93a712933f6540c852aa8cda691470221e98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 May 2018 17:33:05 +0900 Subject: [PATCH 257/302] Make all drawable fruit absolute values easily scalable --- .../Objects/Drawable/DrawableFruit.cs | 41 +++++++++---------- .../Objects/Drawable/Pieces/Pulp.cs | 24 +++++++---- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 41792b10a4..4603148114 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -18,12 +18,19 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { private Circle border; + private const float drawable_radius = (float)CatchHitObject.OBJECT_RADIUS * radius_adjust; + + /// + /// Because we're adding a border around the fruit, we need to scale down some. + /// + private const float radius_adjust = 1.1f; + public DrawableFruit(Fruit h) : base(h) { Origin = Anchor.Centre; - Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS); + Size = new Vector2(drawable_radius); Masking = false; Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; @@ -44,14 +51,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { Hollow = !HitObject.HyperDash, Type = EdgeEffectType.Glow, - Radius = 4, + Radius = 4 * radius_adjust, Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Darken(1).Opacity(0.6f) }, - Size = new Vector2(Height * 1.5f), + Size = new Vector2(Height), Anchor = Anchor.Centre, Origin = Anchor.Centre, BorderColour = Color4.White, - BorderThickness = 4f, + BorderThickness = 3f * radius_adjust, Children = new Framework.Graphics.Drawable[] { new Box @@ -82,8 +89,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable private Framework.Graphics.Drawable createPulp(FruitVisualRepresentation representation) { - const float large_pulp_3 = 13f; - const float distance_from_centre_3 = 0.23f; + const float large_pulp_3 = 8f * radius_adjust; + const float distance_from_centre_3 = 0.15f; const float large_pulp_4 = large_pulp_3 * 0.925f; const float distance_from_centre_4 = distance_from_centre_3 / 0.925f; @@ -106,11 +113,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, AccentColour = AccentColour, Size = new Vector2(small_pulp), - Y = 0.05f, + Y = -0.34f, }, new Pulp { @@ -146,11 +151,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, AccentColour = AccentColour, Size = new Vector2(small_pulp), - Y = 0.1f, + Y = -0.3f, }, new Pulp { @@ -186,11 +189,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, AccentColour = AccentColour, Size = new Vector2(small_pulp), - Y = -0.1f, + Y = -0.33f, }, new Pulp { @@ -220,10 +221,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, AccentColour = AccentColour, Size = new Vector2(small_pulp), + Y = -0.25f, }, new Pulp { @@ -253,16 +253,15 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, AccentColour = AccentColour, Size = new Vector2(small_pulp), - Y = -0.15f + Y = -0.3f }, new Pulp { AccentColour = AccentColour, - Size = new Vector2(large_pulp_4 * 1.2f, large_pulp_4 * 3), + Size = new Vector2(large_pulp_4 * 0.8f, large_pulp_4 * 2.5f), + Y = 0.05f, }, } }; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs index d17a72a165..250dc8c7f1 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs @@ -29,14 +29,24 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces set { accentColour = value; - - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Radius = 8, - Colour = accentColour.Darken(0.2f).Opacity(0.75f) - }; + if (IsLoaded) updateAccentColour(); } } + + private void updateAccentColour() + { + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = Size.X / 2, + Colour = accentColour.Darken(0.2f).Opacity(0.75f) + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateAccentColour(); + } } } From 7d06a08c3a3f3da1871cac6108c057afac4b5990 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 May 2018 17:44:56 +0900 Subject: [PATCH 258/302] Fix quit button test occasionally failing --- osu.Game.Tests/Visual/TestCaseQuitButton.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseQuitButton.cs b/osu.Game.Tests/Visual/TestCaseQuitButton.cs index f0f8d41074..fd0d602ffd 100644 --- a/osu.Game.Tests/Visual/TestCaseQuitButton.cs +++ b/osu.Game.Tests/Visual/TestCaseQuitButton.cs @@ -31,10 +31,6 @@ namespace osu.Game.Tests.Visual var text = quitButton.Children.OfType().First(); - // initial display - AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); - AddUntilStep(() => !text.IsPresent && !exitAction, "Text is not visible"); - AddStep("Trigger text fade in", () => InputManager.MoveMouseTo(quitButton)); AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); AddStep("Trigger text fade out", () => InputManager.MoveMouseTo(Vector2.One)); From 1cb7d50407e10b09ded9a4f0ea9ef086488e3efc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 May 2018 18:51:57 +0900 Subject: [PATCH 259/302] Add and use default size (smaller than before) --- osu.Game/Graphics/UserInterface/ExternalLinkButton.cs | 2 ++ osu.Game/Overlays/BeatmapSet/Header.cs | 1 - osu.Game/Overlays/Profile/ProfileHeader.cs | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs index 025874a1a2..77079894cc 100644 --- a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Graphics.UserInterface @@ -20,6 +21,7 @@ namespace osu.Game.Graphics.UserInterface public ExternalLinkButton(string link = null) { Link = link; + Size = new Vector2(12); InternalChild = new SpriteIcon { Icon = FontAwesome.fa_external_link, diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 7d07816d11..8833a89479 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -178,7 +178,6 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Margin = new MarginPadding { Left = 3, Bottom = 4 }, //To better lineup with the font - Size = new Vector2(18), }, } }, diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 1a4a00da2b..067144c26e 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -124,7 +124,6 @@ namespace osu.Game.Overlays.Profile Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Margin = new MarginPadding { Left = 3, Bottom = 3 }, //To better lineup with the font - Size = new Vector2(18), }, } }, From 897767008839c64e56d29d92c4e19cdb85ab962d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 May 2018 19:08:46 +0900 Subject: [PATCH 260/302] Update framework --- osu-framework | 2 +- osu.Game.Tests/Visual/TestCaseQuitButton.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu-framework b/osu-framework index eb076a3301..a191c104b8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit eb076a3301231eb73917073499051e49a9b12978 +Subproject commit a191c104b8e254e81a1a7bb1c200ccdf02628796 diff --git a/osu.Game.Tests/Visual/TestCaseQuitButton.cs b/osu.Game.Tests/Visual/TestCaseQuitButton.cs index f0f8d41074..c2ddc5fef5 100644 --- a/osu.Game.Tests/Visual/TestCaseQuitButton.cs +++ b/osu.Game.Tests/Visual/TestCaseQuitButton.cs @@ -44,13 +44,13 @@ namespace osu.Game.Tests.Visual { exitAction = false; InputManager.MoveMouseTo(quitButton); - InputManager.ButtonDown(MouseButton.Left); + InputManager.PressButton(MouseButton.Left); }); - AddStep("Early release", () => InputManager.ButtonUp(MouseButton.Left)); + AddStep("Early release", () => InputManager.ReleaseButton(MouseButton.Left)); AddAssert("action not triggered", () => !exitAction); - AddStep("Trigger exit action", () => InputManager.ButtonDown(MouseButton.Left)); + AddStep("Trigger exit action", () => InputManager.PressButton(MouseButton.Left)); AddUntilStep(() => exitAction, $"{nameof(quitButton.Action)} was triggered"); } } From 765a50d00737643039cf2789ad17f9605e0d0723 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 May 2018 20:05:53 +0900 Subject: [PATCH 261/302] Remove 0.5 offsets Checked up against DB values + server-side build versions, and these 0.5s don't seem to exist. Brings calculations more in-line with osu!stable. --- .../Difficulty/ManiaPerformanceCalculator.cs | 2 +- .../Difficulty/OsuPerformanceCalculator.cs | 6 +++--- .../Difficulty/TaikoPerformanceCalculator.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index e6e3028d62..bebe07cdee 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty private double computeAccuracyValue(double strainValue) { - double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + double hitWindowGreat = Beatmap.HitObjects.First().HitWindows.Great / 2 / TimeRate; if (hitWindowGreat <= 0) return 0; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index ae74f12339..9803ebaf52 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -61,11 +61,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (mods.Any(m => !m.Ranked)) return 0; - double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; - double preEmpt = BeatmapDifficulty.DifficultyRange(Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / TimeRate; + double hitWindowGreat = Beatmap.HitObjects.First().HitWindows.Great / 2 / TimeRate; + double preEmpt = (int)BeatmapDifficulty.DifficultyRange(Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / TimeRate; realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; - realOverallDifficulty = (80 - 0.5 - hitWindowGreat) / 6; + realOverallDifficulty = (80 - hitWindowGreat) / 6; // Custom multipliers for NoFail and SpunOut. double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 9c9cd1f0fb..b1d73fc1ff 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private double computeAccuracyValue() { - double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate; + double hitWindowGreat = Beatmap.HitObjects.First().HitWindows.Great / 2 / TimeRate; if (hitWindowGreat <= 0) return 0; From 215cc9fba7fedbf46d4c05b86eb677454a6a8e6b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 May 2018 20:07:14 +0900 Subject: [PATCH 262/302] Change all performance calculators to use int hitwindows Has a pretty large (>6) effect on pp for some maps. --- .../Difficulty/ManiaPerformanceCalculator.cs | 1 + osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs | 1 + .../Difficulty/TaikoPerformanceCalculator.cs | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index bebe07cdee..e1f5f38da7 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -105,6 +105,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty private double computeAccuracyValue(double strainValue) { + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future double hitWindowGreat = Beatmap.HitObjects.First().HitWindows.Great / 2 / TimeRate; if (hitWindowGreat <= 0) return 0; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 9803ebaf52..0158af87d8 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -61,6 +61,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (mods.Any(m => !m.Ranked)) return 0; + // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future double hitWindowGreat = Beatmap.HitObjects.First().HitWindows.Great / 2 / TimeRate; double preEmpt = (int)BeatmapDifficulty.DifficultyRange(Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / TimeRate; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index b1d73fc1ff..6b1a25d667 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -94,7 +94,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private double computeAccuracyValue() { - double hitWindowGreat = Beatmap.HitObjects.First().HitWindows.Great / 2 / TimeRate; + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future + double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; if (hitWindowGreat <= 0) return 0; From e2d840c2dea4c880924c5cc3bfa3a71a858c801a Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 25 May 2018 21:13:40 +0200 Subject: [PATCH 263/302] Rename CursorOverrideContainer to MenuCursorContainer --- osu.Game.Tests/Visual/TestCaseCursors.cs | 12 ++++++------ osu.Game/Graphics/Cursor/CursorOverrideContainer.cs | 4 ++-- osu.Game/OsuGame.cs | 6 +++--- osu.Game/OsuGameBase.cs | 10 +++++----- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseCursors.cs b/osu.Game.Tests/Visual/TestCaseCursors.cs index 977f241f7a..0aa8e9691e 100644 --- a/osu.Game.Tests/Visual/TestCaseCursors.cs +++ b/osu.Game.Tests/Visual/TestCaseCursors.cs @@ -19,12 +19,12 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseCursors : ManualInputManagerTestCase { - private readonly CursorOverrideContainer cursorOverrideContainer; + private readonly MenuCursorContainer menuCursorContainer; private readonly CustomCursorBox[] cursorBoxes = new CustomCursorBox[6]; public TestCaseCursors() { - Child = cursorOverrideContainer = new CursorOverrideContainer + Child = menuCursorContainer = new MenuCursorContainer { RelativeSizeAxes = Axes.Both, Children = new[] @@ -99,7 +99,7 @@ namespace osu.Game.Tests.Visual AddAssert("Check green cursor at mouse", () => checkAtMouse(cursorBoxes[0].Cursor)); AddStep("Move out", moveOut); AddAssert("Check green cursor invisible", () => !checkVisible(cursorBoxes[0].Cursor)); - AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(menuCursorContainer.Cursor)); } /// @@ -112,11 +112,11 @@ namespace osu.Game.Tests.Visual AddStep("Move to purple area", () => InputManager.MoveMouseTo(cursorBoxes[3])); AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor)); - AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); - AddAssert("Check global cursor at mouse", () => checkAtMouse(cursorOverrideContainer.Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(menuCursorContainer.Cursor)); + AddAssert("Check global cursor at mouse", () => checkAtMouse(menuCursorContainer.Cursor)); AddStep("Move out", moveOut); AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); - AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(menuCursorContainer.Cursor)); } /// diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs index 1e56cb6052..5823fad93a 100644 --- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -12,7 +12,7 @@ namespace osu.Game.Graphics.Cursor /// /// A container which provides a which can be overridden by hovered s. /// - public class CursorOverrideContainer : Container, IProvideCursor + public class MenuCursorContainer : Container, IProvideCursor { protected override Container Content => content; private readonly Container content; @@ -25,7 +25,7 @@ namespace osu.Game.Graphics.Cursor public CursorContainer Cursor { get; } public bool ProvidingUserCursor => true; - public CursorOverrideContainer() + public MenuCursorContainer() { AddRangeInternal(new Drawable[] { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ec93b1ae46..a43c1507b6 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -212,7 +212,7 @@ namespace osu.Game protected override void LoadComplete() { - // this needs to be cached before base.LoadComplete as it is used by CursorOverrideContainer. + // this needs to be cached before base.LoadComplete as it is used by MenuCursorContainer. dependencies.Cache(screenshotManager = new ScreenshotManager()); base.LoadComplete(); @@ -220,7 +220,7 @@ namespace osu.Game // The next time this is updated is in UpdateAfterChildren, which occurs too late and results // in the cursor being shown for a few frames during the intro. // This prevents the cursor from showing until we have a screen with CursorVisible = true - CursorOverrideContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; + MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; // hook up notifications to components. SkinManager.PostNotification = n => notifications?.Post(n); @@ -548,7 +548,7 @@ namespace osu.Game mainContent.Padding = new MarginPadding { Top = ToolbarOffset }; - CursorOverrideContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; + MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; } private void screenAdded(Screen newScreen) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 487cb50c9a..a3a081d6d1 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -57,7 +57,7 @@ namespace osu.Game protected SettingsStore SettingsStore; - protected CursorOverrideContainer CursorOverrideContainer; + protected MenuCursorContainer MenuCursorContainer; protected override string MainResourceFile => @"osu.Game.Resources.dll"; @@ -191,14 +191,14 @@ namespace osu.Game GlobalActionContainer globalBinding; - CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both }; - CursorOverrideContainer.Child = globalBinding = new GlobalActionContainer(this) + MenuCursorContainer = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }; + MenuCursorContainer.Child = globalBinding = new GlobalActionContainer(this) { RelativeSizeAxes = Axes.Both, - Child = content = new OsuTooltipContainer(CursorOverrideContainer.Cursor) { RelativeSizeAxes = Axes.Both } + Child = content = new OsuTooltipContainer(MenuCursorContainer.Cursor) { RelativeSizeAxes = Axes.Both } }; - base.Content.Add(new DrawSizePreservingFillContainer { Child = CursorOverrideContainer }); + base.Content.Add(new DrawSizePreservingFillContainer { Child = MenuCursorContainer }); KeyBindingStore.Register(globalBinding); dependencies.Cache(globalBinding); From 63fb9ddec4f7364e41f6ed11e48973ffe1ed70dc Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 25 May 2018 21:20:42 +0200 Subject: [PATCH 264/302] Forgot file name --- .../Cursor/{CursorOverrideContainer.cs => MenuCursorContainer.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game/Graphics/Cursor/{CursorOverrideContainer.cs => MenuCursorContainer.cs} (100%) diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs similarity index 100% rename from osu.Game/Graphics/Cursor/CursorOverrideContainer.cs rename to osu.Game/Graphics/Cursor/MenuCursorContainer.cs From d850e34003b2a7b307c93ae3c692c48aa88fe49c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 26 May 2018 09:25:16 +0900 Subject: [PATCH 265/302] Actually cast to int --- .../Difficulty/ManiaPerformanceCalculator.cs | 2 +- osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index e1f5f38da7..93652f7610 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -106,7 +106,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty private double computeAccuracyValue(double strainValue) { // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - double hitWindowGreat = Beatmap.HitObjects.First().HitWindows.Great / 2 / TimeRate; + double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; if (hitWindowGreat <= 0) return 0; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 0158af87d8..57cf962fa7 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty return 0; // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - double hitWindowGreat = Beatmap.HitObjects.First().HitWindows.Great / 2 / TimeRate; + double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; double preEmpt = (int)BeatmapDifficulty.DifficultyRange(Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / TimeRate; realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; From 8b2a6b8ccefd62aa32e399a5ace23c26917af793 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 May 2018 12:38:33 +0900 Subject: [PATCH 266/302] Fix formatting --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 60671d9383..ad500606ed 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -38,8 +38,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps Duration = endTime.Duration, NewCombo = comboData?.NewCombo ?? false }; - } + yield break; } From 975ce82177f819a4dfdf1656f1b28ae90862a97e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 May 2018 14:46:05 +0900 Subject: [PATCH 267/302] Ensure autoplay tests actually increase score above zero --- osu.Game.Tests/Visual/TestCaseAutoplay.cs | 16 +++++++++++++++- osu.Game/Screens/Play/Player.cs | 18 +++++++++--------- osu.Game/Tests/Visual/TestCasePlayer.cs | 6 ++++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/TestCaseAutoplay.cs index cecb327b6c..bf7aa725e5 100644 --- a/osu.Game.Tests/Visual/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/TestCaseAutoplay.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual @@ -15,7 +16,20 @@ namespace osu.Game.Tests.Visual protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset) { beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); - return base.CreatePlayer(beatmap, ruleset); + return new ScoreAccessiblePlayer + { + InitialBeatmap = beatmap, + AllowPause = false, + AllowLeadIn = false, + AllowResults = false, + }; + } + + protected override bool ContinueCondition(Player player) => base.ContinueCondition(player) && ((ScoreAccessiblePlayer)player).ScoreProcessor.TotalScore > 0; + + private class ScoreAccessiblePlayer : Player + { + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0150d76251..9985a24cab 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -70,7 +70,7 @@ namespace osu.Game.Screens.Play private SampleChannel sampleRestart; - private ScoreProcessor scoreProcessor; + protected ScoreProcessor ScoreProcessor; protected RulesetContainer RulesetContainer; private HUDOverlay hudOverlay; @@ -149,7 +149,7 @@ namespace osu.Game.Screens.Play userAudioOffset.ValueChanged += v => offsetClock.Offset = v; userAudioOffset.TriggerChange(); - scoreProcessor = RulesetContainer.CreateScoreProcessor(); + ScoreProcessor = RulesetContainer.CreateScoreProcessor(); Children = new Drawable[] { @@ -176,7 +176,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Child = RulesetContainer }, - new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, scoreProcessor) + new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -184,7 +184,7 @@ namespace osu.Game.Screens.Play Breaks = beatmap.Breaks }, RulesetContainer.Cursor?.CreateProxy() ?? new Container(), - hudOverlay = new HUDOverlay(scoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) + hudOverlay = new HUDOverlay(ScoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) { Clock = Clock, // hud overlay doesn't want to use the audio clock directly ProcessCustomClock = false, @@ -225,11 +225,11 @@ namespace osu.Game.Screens.Play initializeStoryboard(false); // Bind ScoreProcessor to ourselves - scoreProcessor.AllJudged += onCompletion; - scoreProcessor.Failed += onFail; + ScoreProcessor.AllJudged += onCompletion; + ScoreProcessor.Failed += onFail; foreach (var mod in Beatmap.Value.Mods.Value.OfType()) - mod.ApplyToScoreProcessor(scoreProcessor); + mod.ApplyToScoreProcessor(ScoreProcessor); } private void applyRateFromMods() @@ -254,7 +254,7 @@ namespace osu.Game.Screens.Play private void onCompletion() { // Only show the completion screen if the player hasn't failed - if (scoreProcessor.HasFailed || onCompletionEvent != null) + if (ScoreProcessor.HasFailed || onCompletionEvent != null) return; ValidForResume = false; @@ -272,7 +272,7 @@ namespace osu.Game.Screens.Play Beatmap = Beatmap.Value.BeatmapInfo, Ruleset = ruleset }; - scoreProcessor.PopulateScore(score); + ScoreProcessor.PopulateScore(score); score.User = RulesetContainer.Replay?.User ?? api.LocalUser.Value; Push(new Results(score)); }); diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index bda438d906..bf6236e4d5 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual { Player p = null; AddStep(ruleset.RulesetInfo.Name, () => p = loadPlayerFor(ruleset)); - AddUntilStep(() => p.IsLoaded); + AddUntilStep(() => ContinueCondition(p)); } else { @@ -52,11 +52,13 @@ namespace osu.Game.Tests.Visual { Player p = null; AddStep(r.Name, () => p = loadPlayerFor(r)); - AddUntilStep(() => p.IsLoaded); + AddUntilStep(() => ContinueCondition(p)); } } } + protected virtual bool ContinueCondition(Player player) => player.IsLoaded; + protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance()); From 95315e46f06dfc70acebf3cce07f03b166128150 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 27 May 2018 14:12:20 +0900 Subject: [PATCH 268/302] Make drawable rooms fade in when first displayed Stops filtered rooms from briefly displaying. --- osu.Game/Screens/Multi/Components/DrawableRoom.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index d11d4a4795..8e93fda68f 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -297,6 +297,12 @@ namespace osu.Game.Screens.Multi.Components participantsBind.BindTo(Room.Participants); } + protected override void LoadComplete() + { + base.LoadComplete(); + this.FadeInFromZero(transition_duration); + } + protected override bool OnClick(InputState state) { if (Enabled.Value) From 4f0d7bd63ef09798dcbd6aa9ff59cae9533166a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 27 May 2018 15:14:25 +0900 Subject: [PATCH 269/302] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index a191c104b8..84fdfc77a8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit a191c104b8e254e81a1a7bb1c200ccdf02628796 +Subproject commit 84fdfc77a86d581638e69f5e8061c118de4b30f9 From 0ca6d73f0ec7d43773b404d66666cd89c77657e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 May 2018 12:28:11 +0900 Subject: [PATCH 270/302] Add a delay before the osu! logo appears when exiting multiplayer --- osu.Game/Screens/Multi/Multiplayer.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index ddaeb26806..7822fa68dc 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -8,6 +8,7 @@ using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; +using osu.Game.Screens.Menu; using osu.Game.Screens.Multi.Screens.Lounge; namespace osu.Game.Screens.Multi @@ -84,6 +85,13 @@ namespace osu.Game.Screens.Multi waves.Hide(); } + protected override void LogoExiting(OsuLogo logo) + { + // the wave overlay transition takes longer than expected to run. + logo.Delay(WaveContainer.DISAPPEAR_DURATION / 2).FadeOut(); + base.LogoExiting(logo); + } + private class MultiplayerWaveContainer : WaveContainer { protected override bool StartHidden => true; From 02c37ebc1f928d96fbeaa79df5337e3cd1a1703e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 May 2018 13:02:06 +0900 Subject: [PATCH 271/302] Move screen titles to OsuScreen --- .../Visual/TestCaseScreenBreadcrumbControl.cs | 7 ++----- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 3 ++- osu.Game/Screens/Multi/Header.cs | 2 +- osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs | 2 +- osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs | 5 ----- osu.Game/Screens/OsuScreen.cs | 10 +++++++++- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs index 7a743655f4..83bbbfddd1 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs @@ -84,12 +84,9 @@ namespace osu.Game.Tests.Visual private abstract class TestScreen : OsuScreen { - protected abstract string Title { get; } protected abstract string NextTitle { get; } protected abstract TestScreen CreateNextScreen(); - public override string ToString() => Title; - public TestScreen PushNext() { TestScreen screen = CreateNextScreen(); @@ -130,14 +127,14 @@ namespace osu.Game.Tests.Visual private class TestScreenOne : TestScreen { - protected override string Title => @"Screen One"; + public override string Title => @"Screen One"; protected override string NextTitle => @"Two"; protected override TestScreen CreateNextScreen() => new TestScreenTwo(); } private class TestScreenTwo : TestScreen { - protected override string Title => @"Screen Two"; + public override string Title => @"Screen Two"; protected override string NextTitle => @"One"; protected override TestScreen CreateNextScreen() => new TestScreenOne(); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index fc14a9c6ba..d015a563f6 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -6,6 +6,7 @@ using System.Linq; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -157,7 +158,7 @@ namespace osu.Game.Graphics.UserInterface Margin = new MarginPadding { Top = 5, Bottom = 5 }, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, - Text = (value as Enum)?.GetDescription() ?? value.ToString(), + Text = (value as IHasDescription)?.Description ?? (value as Enum)?.GetDescription() ?? value.ToString(), TextSize = 14, Font = @"Exo2.0-Bold", // Font should only turn bold when active? }, diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index f6b7bbfcef..de71b20007 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => screenTitle.Text = s is MultiplayerScreen m ? m.Title : s.ToString(); + breadcrumbs.Current.ValueChanged += s => screenTitle.Text = ((MultiplayerScreen)s).Title; breadcrumbs.Current.TriggerChange(); } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 01a7510f76..60ffe2c0b9 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected readonly RoomInspector Inspector; public override string Title => "lounge"; - public override string Name => "Lounge"; + protected override Container TransitionContent => content; private IEnumerable rooms; diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs index 5a17a32d8c..191fe66037 100644 --- a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs @@ -15,11 +15,6 @@ namespace osu.Game.Screens.Multi.Screens protected virtual Container TransitionContent => Content; - public abstract string Title { get; } - public abstract string Name { get; } - - public override string ToString() => Name; - protected override void OnEntering(Screen last) { base.OnEntering(last); diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index a188b7aa64..cd9cbe119f 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -20,10 +21,17 @@ using OpenTK.Input; namespace osu.Game.Screens { - public abstract class OsuScreen : Screen, IKeyBindingHandler + public abstract class OsuScreen : Screen, IKeyBindingHandler, IHasDescription { public BackgroundScreen Background { get; private set; } + /// + /// A user-facing title for this screen. + /// + public virtual string Title => GetType().ShortDisplayName(); + + public string Description => Title; + protected virtual bool AllowBackButton => true; /// From ed7c8608028149b4549026f09efe7de500cffc49 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 May 2018 13:02:15 +0900 Subject: [PATCH 272/302] Adjust transitions of DrawableRoom --- osu.Game/Screens/Multi/Components/DrawableRoom.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 8e93fda68f..1851f4618e 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Multi.Components { public const float SELECTION_BORDER_WIDTH = 4; private const float corner_radius = 5; - private const float transition_duration = 100; + private const float transition_duration = 60; private const float content_padding = 10; private const float height = 100; private const float side_strip_width = 5; @@ -254,7 +254,7 @@ namespace osu.Game.Screens.Multi.Components status.Text = s.Message; foreach (Drawable d in new Drawable[] { selectionBox, sideStrip, status }) - d.FadeColour(s.GetAppropriateColour(colours), 100); + d.FadeColour(s.GetAppropriateColour(colours), transition_duration); }; beatmapBind.ValueChanged += b => From 31cbec99a1ea272a82951187355d536ab4a03e33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 28 May 2018 18:12:49 +0900 Subject: [PATCH 273/302] Fix mania hold notes displaying judgements --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 2 ++ osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 8791e8ed86..f7de503fb3 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public class DrawableHoldNote : DrawableManiaHitObject, IKeyBindingHandler { + public override bool DisplayJudgement => false; + private readonly DrawableNote head; private readonly DrawableNote tail; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 52d514221d..28cd1b6b39 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -213,7 +213,7 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { - if (!judgement.IsHit) + if (!judgement.IsHit || !judgedObject.DisplayJudgement) return; explosionContainer.Add(new HitExplosion(judgedObject)); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 904be3a9e3..605794c795 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -171,6 +171,9 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { + if (!judgedObject.DisplayJudgement) + return; + judgements.Clear(); judgements.Add(new DrawableManiaJudgement(judgement, judgedObject) { From 5be46307fdeda27cdc5556d0ca1303cff98285dc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 28 May 2018 19:43:59 +0900 Subject: [PATCH 274/302] Fix results screen parallax being cut off Alternative to / closes #2549. Didn't want to reference the toolbar as was done, also wanted to remove the awkward scaling factors so rather than scaling down the inner one, we scale up the outer one. --- osu.Game/Screens/Ranking/Results.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 32161a0b8e..7cbd2e4403 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -57,6 +57,7 @@ namespace osu.Game.Screens.Ranking { base.OnEntering(last); (Background as BackgroundScreenBeatmap)?.BlurTo(background_blur, 2500, Easing.OutQuint); + Background.ScaleTo(1.1f, transition_time, Easing.OutQuint); allCircles.ForEach(c => { @@ -102,6 +103,8 @@ namespace osu.Game.Screens.Ranking c.ScaleTo(0, transition_time, Easing.OutSine); }); + Background.ScaleTo(1f, transition_time / 4, Easing.OutQuint); + Content.FadeOut(transition_time / 4); return base.OnExiting(next); @@ -160,7 +163,6 @@ namespace osu.Game.Screens.Ranking { RelativeSizeAxes = Axes.Both, ParallaxAmount = 0.01f, - Scale = new Vector2(1 / circle_outer_scale / overscan), Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] From 4f73f6e0e02a62bfa6a10f0d2053a0c38ac2cc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 29 May 2018 08:18:54 +0200 Subject: [PATCH 275/302] Add build tasks for visual tests and fix broken launch tasks --- .vscode/launch.json | 10 +++++----- .vscode/tasks.json | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index df5b11f63a..11141dc182 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -66,7 +66,7 @@ "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.0/osu.Game.Tests.dll" ], "cwd": "${workspaceRoot}", - "preLaunchTask": "Build (Debug, dotnet)", + "preLaunchTask": "Build tests (Debug, dotnet)", "env": {}, "console": "internalConsole" }, @@ -76,10 +76,10 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.0/osu.Game.Tests.dll" + "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.0/osu.Game.Tests.dll" ], "cwd": "${workspaceRoot}", - "preLaunchTask": "Build (Release, dotnet)", + "preLaunchTask": "Build tests (Release, dotnet)", "env": {}, "console": "internalConsole" }, @@ -92,7 +92,7 @@ "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp2.0/osu!.dll", ], "cwd": "${workspaceRoot}", - "preLaunchTask": "Build (Debug, dotnet)", + "preLaunchTask": "Build osu! (Debug, dotnet)", "env": {}, "console": "internalConsole" }, @@ -105,7 +105,7 @@ "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp2.0/osu!.dll", ], "cwd": "${workspaceRoot}", - "preLaunchTask": "Build (Release, dotnet)", + "preLaunchTask": "Build osu! (Release, dotnet)", "env": {}, "console": "internalConsole" } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 7144a584f3..0908ff6108 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -31,7 +31,7 @@ "problemMatcher": "$msCompile" }, { - "label": "Build (Debug, dotnet)", + "label": "Build osu! (Debug, dotnet)", "type": "shell", "command": "dotnet", "args": [ @@ -47,7 +47,7 @@ "problemMatcher": "$msCompile" }, { - "label": "Build (Release, dotnet)", + "label": "Build osu! (Release, dotnet)", "type": "shell", "command": "dotnet", "args": [ @@ -63,6 +63,39 @@ "group": "build", "problemMatcher": "$msCompile" }, + { + "label": "Build tests (Debug, dotnet)", + "type": "shell", + "command": "dotnet", + "args": [ + "build", + "--no-restore", + "osu.Game.Tests", + "/p:TargetFramework=netcoreapp2.0", + "/p:GenerateFullPaths=true", + "/m", + "/verbosity:m" + ], + "group": "build", + "problemMatcher": "$msCompile" + }, + { + "label": "Build tests (Release, dotnet)", + "type": "shell", + "command": "dotnet", + "args": [ + "build", + "--no-restore", + "osu.Game.Tests", + "/p:TargetFramework=netcoreapp2.0", + "/p:Configuration=Release", + "/p:GenerateFullPaths=true", + "/m", + "/verbosity:m" + ], + "group": "build", + "problemMatcher": "$msCompile" + }, { "label": "Restore (net471)", "type": "shell", From 2a87b851fae5d3fb783c936782155968006f1900 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 May 2018 18:38:42 +0900 Subject: [PATCH 276/302] Add proper transaction rollback logic on exception --- osu.Game/Database/DatabaseWriteUsage.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/DatabaseWriteUsage.cs b/osu.Game/Database/DatabaseWriteUsage.cs index 7858c1a0d1..07bebbf0c3 100644 --- a/osu.Game/Database/DatabaseWriteUsage.cs +++ b/osu.Game/Database/DatabaseWriteUsage.cs @@ -28,8 +28,19 @@ namespace osu.Game.Database if (isDisposed) return; isDisposed = true; - PerformedWrite |= Context.SaveChanges(transaction) > 0; - usageCompleted?.Invoke(this); + try + { + PerformedWrite |= Context.SaveChanges(transaction) > 0; + } + catch (Exception e) + { + transaction?.Rollback(); + throw; + } + finally + { + usageCompleted?.Invoke(this); + } } public void Dispose() From d4e7f08c20ce4311e9dba4ff1a6feade891d50aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 May 2018 18:43:53 +0900 Subject: [PATCH 277/302] Bring entity framework up-to-date and re-enable transactions --- osu.Desktop/osu.Desktop.csproj | 6 +++--- osu.Game/Database/OsuDbContext.cs | 3 +-- osu.Game/osu.Game.csproj | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 3d64cab84e..3a35568f8f 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -1,4 +1,4 @@ - + net471;netcoreapp2.0 @@ -30,10 +30,10 @@ - + - + \ No newline at end of file diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 1979ce3648..06503ffc5f 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -106,8 +106,7 @@ namespace osu.Game.Database public IDbContextTransaction BeginTransaction() { - // return Database.BeginTransaction(); - return null; + return Database.BeginTransaction(); } public int SaveChanges(IDbContextTransaction transaction = null) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1a75f1979a..afb656a260 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -17,7 +17,7 @@ - + From bcb04f616895f166cdfff223e781d11dda77aba0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 May 2018 19:56:27 +0900 Subject: [PATCH 278/302] Improve transaction handling flexibility --- osu.Game/Database/ArchiveModelManager.cs | 66 +++++++++++++++++---- osu.Game/Database/DatabaseContextFactory.cs | 23 ++++++- osu.Game/Database/DatabaseWriteUsage.cs | 16 +++-- osu.Game/Database/OsuDbContext.cs | 13 ---- 4 files changed, 84 insertions(+), 34 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index e04559d547..28c25c873f 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -56,13 +56,42 @@ namespace osu.Game.Database // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) private ArchiveImportIPCChannel ipc; + private readonly List cachedEvents = new List(); + + private bool delayingEvents; + + private void cacheEvents() + { + delayingEvents = true; + } + + private void flushEvents(bool perform) + { + if (perform) + { + foreach (var a in cachedEvents) + a.Invoke(); + } + + cachedEvents.Clear(); + delayingEvents = false; + } + + private void handleEvent(Action a) + { + if (delayingEvents) + cachedEvents.Add(a); + else + a.Invoke(); + } + protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStore modelStore, IIpcHost importHost = null) { ContextFactory = contextFactory; ModelStore = modelStore; - ModelStore.ItemAdded += s => ItemAdded?.Invoke(s); - ModelStore.ItemRemoved += s => ItemRemoved?.Invoke(s); + ModelStore.ItemAdded += s => handleEvent(() => ItemAdded?.Invoke(s)); + ModelStore.ItemRemoved += s => handleEvent(() => ItemRemoved?.Invoke(s)); Files = new FileStore(contextFactory, storage); @@ -138,24 +167,37 @@ namespace osu.Game.Database /// The archive to be imported. public TModel Import(ArchiveReader archive) { - using (ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes. + TModel item = null; + cacheEvents(); + + try { - // create a new model (don't yet add to database) - var item = CreateModel(archive); + using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes. + { + if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}"); - var existing = CheckForExisting(item); + // create a new model (don't yet add to database) + item = CreateModel(archive); - if (existing != null) return existing; + var existing = CheckForExisting(item); - item.Files = createFileInfos(archive, Files); + if (existing != null) return existing; - Populate(item, archive); + item.Files = createFileInfos(archive, Files); - // import to store - ModelStore.Add(item); + Populate(item, archive); - return item; + // import to store + ModelStore.Add(item); + } } + catch + { + item = null; + } + + flushEvents(item != null); + return item; } /// diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index 71960303b5..65a19e23c0 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using System.Threading; +using Microsoft.EntityFrameworkCore.Storage; using osu.Framework.Platform; namespace osu.Game.Database @@ -17,8 +19,12 @@ namespace osu.Game.Database private readonly object writeLock = new object(); private bool currentWriteDidWrite; + private bool currentWriteDidError; + private int currentWriteUsages; + private IDbContextTransaction currentWriteTransaction; + public DatabaseContextFactory(GameHost host) { this.host = host; @@ -40,9 +46,12 @@ namespace osu.Game.Database { Monitor.Enter(writeLock); + if (currentWriteTransaction == null) + currentWriteTransaction = threadContexts.Value.Database.BeginTransaction(); + Interlocked.Increment(ref currentWriteUsages); - return new DatabaseWriteUsage(threadContexts.Value, usageCompleted); + return new DatabaseWriteUsage(threadContexts.Value, usageCompleted) { IsTransactionLeader = currentWriteUsages == 1 }; } private void usageCompleted(DatabaseWriteUsage usage) @@ -52,16 +61,24 @@ namespace osu.Game.Database try { currentWriteDidWrite |= usage.PerformedWrite; + currentWriteDidError |= usage.Errors.Any(); if (usages > 0) return; + if (currentWriteDidError) + currentWriteTransaction.Rollback(); + else + currentWriteTransaction.Commit(); + + currentWriteTransaction = null; + currentWriteDidWrite = false; + currentWriteDidError = false; + if (currentWriteDidWrite) { // explicitly dispose to ensure any outstanding flushes happen as soon as possible (and underlying resources are purged). usage.Context.Dispose(); - currentWriteDidWrite = false; - // once all writes are complete, we want to refresh thread-specific contexts to make sure they don't have stale local caches. recycleThreadContexts(); } diff --git a/osu.Game/Database/DatabaseWriteUsage.cs b/osu.Game/Database/DatabaseWriteUsage.cs index 07bebbf0c3..8216c04b22 100644 --- a/osu.Game/Database/DatabaseWriteUsage.cs +++ b/osu.Game/Database/DatabaseWriteUsage.cs @@ -2,26 +2,31 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using Microsoft.EntityFrameworkCore.Storage; +using System.Collections.Generic; namespace osu.Game.Database { public class DatabaseWriteUsage : IDisposable { public readonly OsuDbContext Context; - private readonly IDbContextTransaction transaction; private readonly Action usageCompleted; public DatabaseWriteUsage(OsuDbContext context, Action onCompleted) { Context = context; - transaction = Context.BeginTransaction(); usageCompleted = onCompleted; } public bool PerformedWrite { get; private set; } private bool isDisposed; + public List Errors = new List(); + + /// + /// Whether this write usage will commit a transaction on completion. + /// If false, there is a parent usage responsible for transaction commit. + /// + public bool IsTransactionLeader = false; protected void Dispose(bool disposing) { @@ -30,12 +35,11 @@ namespace osu.Game.Database try { - PerformedWrite |= Context.SaveChanges(transaction) > 0; + PerformedWrite |= Context.SaveChanges() > 0; } catch (Exception e) { - transaction?.Rollback(); - throw; + Errors.Add(e); } finally { diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 06503ffc5f..0ae197d62d 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -3,7 +3,6 @@ using System; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; using osu.Framework.Logging; @@ -104,18 +103,6 @@ namespace osu.Game.Database modelBuilder.Entity().HasOne(b => b.BaseDifficulty); } - public IDbContextTransaction BeginTransaction() - { - return Database.BeginTransaction(); - } - - public int SaveChanges(IDbContextTransaction transaction = null) - { - var ret = base.SaveChanges(); - if (ret > 0) transaction?.Commit(); - return ret; - } - private class OsuDbLoggerFactory : ILoggerFactory { #region Disposal From 7b8211e6db51cd8b1d9a43f2172b55fd974c8a73 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 04:23:29 -0300 Subject: [PATCH 279/302] Add MultiplayerScreen.Type --- osu.Game/Screens/Multi/Header.cs | 8 ++++---- osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs | 3 ++- osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs | 5 +++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index de71b20007..fb4da45aca 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Multi { public const float HEIGHT = 121; - private readonly OsuSpriteText screenTitle; + private readonly OsuSpriteText screenType; private readonly HeaderBreadcrumbControl breadcrumbs; public Header(Screen initialScreen) @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Multi Text = "multiplayer ", TextSize = 25, }, - screenTitle = new OsuSpriteText + screenType = new OsuSpriteText { TextSize = 25, Font = @"Exo2.0-Light", @@ -86,14 +86,14 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => screenTitle.Text = ((MultiplayerScreen)s).Title; + breadcrumbs.Current.ValueChanged += s => screenType.Text = ((MultiplayerScreen)s).Type; breadcrumbs.Current.TriggerChange(); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - screenTitle.Colour = colours.Yellow; + screenType.Colour = colours.Yellow; breadcrumbs.StripColour = colours.Green; } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 60ffe2c0b9..f0c93b1146 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -25,7 +25,8 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected readonly FillFlowContainer RoomsContainer; protected readonly RoomInspector Inspector; - public override string Title => "lounge"; + public override string Type => "lounge"; + public override string Title => "Lounge"; protected override Container TransitionContent => content; diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs index 191fe66037..cdfa17a7a6 100644 --- a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs @@ -15,6 +15,11 @@ namespace osu.Game.Screens.Multi.Screens protected virtual Container TransitionContent => Content; + /// + /// The type to display in the title of the . + /// + public abstract string Type { get; } + protected override void OnEntering(Screen last) { base.OnEntering(last); From a3287b8cf2e3734e606b20490c9f2f8d5ab4a962 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 May 2018 21:45:05 +0900 Subject: [PATCH 280/302] Correctly rollback failed imports --- osu.Game/Database/ArchiveModelManager.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 28c25c873f..86af2fd0ed 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -58,13 +58,20 @@ namespace osu.Game.Database private readonly List cachedEvents = new List(); + /// + /// Allows delaying of outwards events until an operation is confirmed (at a database level). + /// private bool delayingEvents; - private void cacheEvents() - { - delayingEvents = true; - } + /// + /// Begin delaying outwards events. + /// + private void delayEvents() => delayingEvents = true; + /// + /// Flush delayed events and disable delaying. + /// + /// Whether the flushed events should be performed. private void flushEvents(bool perform) { if (perform) @@ -167,8 +174,8 @@ namespace osu.Game.Database /// The archive to be imported. public TModel Import(ArchiveReader archive) { - TModel item = null; - cacheEvents(); + TModel item; + delayEvents(); try { @@ -196,6 +203,7 @@ namespace osu.Game.Database item = null; } + // we only want to flush events after we've confirmed the write context didn't have any errors. flushEvents(item != null); return item; } From 80806be0471d1547e4b6af8b7b6f2ec520e780f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 10:59:39 +0900 Subject: [PATCH 281/302] Don't start transactions for migration It looks like transactions are used internally during migration. --- osu.Game/Database/DatabaseContextFactory.cs | 11 ++++++----- osu.Game/Database/IDatabaseContextFactory.cs | 3 ++- osu.Game/Database/SingletonContextFactory.cs | 2 +- osu.Game/OsuGameBase.cs | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index 65a19e23c0..ec408456e3 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -41,17 +41,18 @@ namespace osu.Game.Database /// Request a context for write usage. Can be consumed in a nested fashion (and will return the same underlying context). /// This method may block if a write is already active on a different thread. /// + /// Whether to start a transaction for this write. /// A usage containing a usable context. - public DatabaseWriteUsage GetForWrite() + public DatabaseWriteUsage GetForWrite(bool withTransaction = true) { Monitor.Enter(writeLock); - if (currentWriteTransaction == null) + if (currentWriteTransaction == null && withTransaction) currentWriteTransaction = threadContexts.Value.Database.BeginTransaction(); Interlocked.Increment(ref currentWriteUsages); - return new DatabaseWriteUsage(threadContexts.Value, usageCompleted) { IsTransactionLeader = currentWriteUsages == 1 }; + return new DatabaseWriteUsage(threadContexts.Value, usageCompleted) { IsTransactionLeader = currentWriteTransaction != null && currentWriteUsages == 1 }; } private void usageCompleted(DatabaseWriteUsage usage) @@ -66,9 +67,9 @@ namespace osu.Game.Database if (usages > 0) return; if (currentWriteDidError) - currentWriteTransaction.Rollback(); + currentWriteTransaction?.Rollback(); else - currentWriteTransaction.Commit(); + currentWriteTransaction?.Commit(); currentWriteTransaction = null; currentWriteDidWrite = false; diff --git a/osu.Game/Database/IDatabaseContextFactory.cs b/osu.Game/Database/IDatabaseContextFactory.cs index 372e1770e4..d38d15b252 100644 --- a/osu.Game/Database/IDatabaseContextFactory.cs +++ b/osu.Game/Database/IDatabaseContextFactory.cs @@ -14,7 +14,8 @@ namespace osu.Game.Database /// Request a context for write usage. Can be consumed in a nested fashion (and will return the same underlying context). /// This method may block if a write is already active on a different thread. /// + /// Whether to start a transaction for this write. /// A usage containing a usable context. - DatabaseWriteUsage GetForWrite(); + DatabaseWriteUsage GetForWrite(bool withTransaction = true); } } diff --git a/osu.Game/Database/SingletonContextFactory.cs b/osu.Game/Database/SingletonContextFactory.cs index 74951e8433..ce3fbf6881 100644 --- a/osu.Game/Database/SingletonContextFactory.cs +++ b/osu.Game/Database/SingletonContextFactory.cs @@ -14,6 +14,6 @@ namespace osu.Game.Database public OsuDbContext Get() => context; - public DatabaseWriteUsage GetForWrite() => new DatabaseWriteUsage(context, null); + public DatabaseWriteUsage GetForWrite(bool withTransaction = true) => new DatabaseWriteUsage(context, null); } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index a3a081d6d1..b9d32a6322 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -208,7 +208,7 @@ namespace osu.Game { try { - using (var db = contextFactory.GetForWrite()) + using (var db = contextFactory.GetForWrite(false)) db.Context.Migrate(); } catch (MigrationFailedException e) @@ -220,7 +220,7 @@ namespace osu.Game contextFactory.ResetDatabase(); Logger.Log("Database purged successfully.", LoggingTarget.Database, LogLevel.Important); - using (var db = contextFactory.GetForWrite()) + using (var db = contextFactory.GetForWrite(false)) db.Context.Migrate(); } } From 72da640059e8aa05f193d0d3800bc0d6fee50cf6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 11:37:47 +0900 Subject: [PATCH 282/302] Change order of event firing in Update calls A remove event should not be fired before the update is successful. --- osu.Game/Database/MutableDatabaseBackedStore.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Database/MutableDatabaseBackedStore.cs b/osu.Game/Database/MutableDatabaseBackedStore.cs index 8569d81f01..69a1f57cc4 100644 --- a/osu.Game/Database/MutableDatabaseBackedStore.cs +++ b/osu.Game/Database/MutableDatabaseBackedStore.cs @@ -50,11 +50,10 @@ namespace osu.Game.Database /// The item to update. public void Update(T item) { - ItemRemoved?.Invoke(item); - using (var usage = ContextFactory.GetForWrite()) usage.Context.Update(item); + ItemRemoved?.Invoke(item); ItemAdded?.Invoke(item); } From 015fd9d0e7d256410dea6fe583b3e5e7c0043a02 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 11:44:42 +0900 Subject: [PATCH 283/302] Fix loading test method returning oldest import rather than newest --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index f60caf2397..740692395a 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -219,7 +219,7 @@ namespace osu.Game.Tests.Beatmaps.IO waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000); - return imported.FirstOrDefault(); + return imported.LastOrDefault(); } private void deleteBeatmapSet(BeatmapSetInfo imported, OsuGameBase osu) From cc081cad5a0d78367420b31bfdb8b7a2baff0686 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 11:57:11 +0900 Subject: [PATCH 284/302] Simplify test osz instantiation --- .../Beatmaps/IO/ImportBeatmapTest.cs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 740692395a..38fd6e649b 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -162,8 +162,7 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = loadOsu(host); - var temp = prepareTempCopy(osz_path); - Assert.IsTrue(File.Exists(temp)); + var temp = createTemporaryBeatmap(); var importer = new ArchiveImportIPCChannel(client); if (!importer.ImportAsync(temp).Wait(10000)) @@ -188,8 +187,7 @@ namespace osu.Game.Tests.Beatmaps.IO try { var osu = loadOsu(host); - var temp = prepareTempCopy(osz_path); - Assert.IsTrue(File.Exists(temp), "Temporary file copy never substantiated"); + var temp = createTemporaryBeatmap(); using (File.OpenRead(temp)) osu.Dependencies.Get().Import(temp); ensureLoaded(osu); @@ -203,11 +201,16 @@ namespace osu.Game.Tests.Beatmaps.IO } } - private BeatmapSetInfo loadOszIntoOsu(OsuGameBase osu) + private string createTemporaryBeatmap() { - var temp = prepareTempCopy(osz_path); - + var temp = new FileInfo(osz_path).CopyTo(Path.GetTempFileName(), true).FullName; Assert.IsTrue(File.Exists(temp)); + return temp; + } + + private BeatmapSetInfo loadOszIntoOsu(OsuGameBase osu, string path = null) + { + var temp = path ?? createTemporaryBeatmap(); var manager = osu.Dependencies.Get(); @@ -232,12 +235,6 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(manager.QueryBeatmapSets(_ => true).First().DeletePending); } - private string prepareTempCopy(string path) - { - var temp = Path.GetTempFileName(); - return new FileInfo(path).CopyTo(temp, true).FullName; - } - private OsuGameBase loadOsu(GameHost host) { var osu = new OsuGameBase(); From 3d3026a80cdce1dc15f04b88f242120ec09cfffc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 13:48:14 +0900 Subject: [PATCH 285/302] Report any error during import to the write context to allow for rollback --- osu.Game/Database/ArchiveModelManager.cs | 26 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 86af2fd0ed..99f1e9f581 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -181,21 +181,29 @@ namespace osu.Game.Database { using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes. { - if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}"); + try + { + if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}"); - // create a new model (don't yet add to database) - item = CreateModel(archive); + // create a new model (don't yet add to database) + item = CreateModel(archive); - var existing = CheckForExisting(item); + var existing = CheckForExisting(item); - if (existing != null) return existing; + if (existing != null) return existing; - item.Files = createFileInfos(archive, Files); + item.Files = createFileInfos(archive, Files); - Populate(item, archive); + Populate(item, archive); - // import to store - ModelStore.Add(item); + // import to store + ModelStore.Add(item); + } + catch (Exception e) + { + write.Errors.Add(e); + throw; + } } } catch From 203691b1c776728fb48564c51bef60a20bc0d499 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 13:48:27 +0900 Subject: [PATCH 286/302] Add import rollback test --- .../Beatmaps/IO/ImportBeatmapTest.cs | 75 +++++++++++++++++-- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 38fd6e649b..586217a05f 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -12,6 +12,7 @@ using osu.Framework.Platform; using osu.Game.IPC; using osu.Framework.Allocation; using osu.Game.Beatmaps; +using SharpCompress.Archives.Zip; namespace osu.Game.Tests.Beatmaps.IO { @@ -77,8 +78,69 @@ namespace osu.Game.Tests.Beatmaps.IO var manager = osu.Dependencies.Get(); - Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 1); - Assert.IsTrue(manager.QueryBeatmapSets(_ => true).ToList().Count == 1); + Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); + Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); + } + finally + { + host.Exit(); + } + } + } + + [Test] + public void TestRollbackOnFailure() + { + //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestRollbackOnFailure")) + { + try + { + var osu = loadOsu(host); + var manager = osu.Dependencies.Get(); + + int fireCount = 0; + + // ReSharper disable once AccessToModifiedClosure + manager.ItemAdded += _ => fireCount++; + manager.ItemRemoved += _ => fireCount++; + + var imported = loadOszIntoOsu(osu); + + Assert.AreEqual(0, fireCount -= 1); + + imported.Hash += "-changed"; + manager.Update(imported); + + Assert.AreEqual(0, fireCount -= 2); + + var breakTemp = createTemporaryBeatmap(); + + MemoryStream brokenOsu = new MemoryStream(new byte[] { 1, 3, 3, 7 }); + MemoryStream brokenOsz = new MemoryStream(File.ReadAllBytes(breakTemp)); + + File.Delete(breakTemp); + + using (var outStream = File.Open(breakTemp, FileMode.CreateNew)) + using (var zip = ZipArchive.Open(brokenOsz)) + { + zip.AddEntry("broken.osu", brokenOsu, false); + zip.SaveTo(outStream, SharpCompress.Common.CompressionType.Deflate); + } + + Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); + Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); + Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); + + // this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu. + manager.Import(breakTemp); + + // no events should be fired in the case of a rollback. + Assert.AreEqual(0, fireCount); + + Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); + Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); + Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); } finally { @@ -100,18 +162,17 @@ namespace osu.Game.Tests.Beatmaps.IO var imported = loadOszIntoOsu(osu); - //var change = manager.QueryBeatmapSets(_ => true).First(); imported.Hash += "-changed"; manager.Update(imported); var importedSecondTime = loadOszIntoOsu(osu); - // check the newly "imported" beatmap is actually just the restored previous import. since it matches hash. Assert.IsTrue(imported.ID != importedSecondTime.ID); Assert.IsTrue(imported.Beatmaps.First().ID < importedSecondTime.Beatmaps.First().ID); - Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 1); - Assert.IsTrue(manager.QueryBeatmapSets(_ => true).ToList().Count == 1); + // only one beatmap will exist as the online set ID matched, causing purging of the first import. + Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); + Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); } finally { @@ -231,7 +292,7 @@ namespace osu.Game.Tests.Beatmaps.IO manager.Delete(imported); Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 0); - Assert.IsTrue(manager.QueryBeatmapSets(_ => true).ToList().Count == 1); + Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); Assert.IsTrue(manager.QueryBeatmapSets(_ => true).First().DeletePending); } From c1f416b1ccb6cea656d90c128c120048d9619a81 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 14:25:27 +0900 Subject: [PATCH 287/302] Add back missing rethrow --- osu.Game/Database/DatabaseWriteUsage.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Database/DatabaseWriteUsage.cs b/osu.Game/Database/DatabaseWriteUsage.cs index 8216c04b22..64ab24e824 100644 --- a/osu.Game/Database/DatabaseWriteUsage.cs +++ b/osu.Game/Database/DatabaseWriteUsage.cs @@ -40,6 +40,7 @@ namespace osu.Game.Database catch (Exception e) { Errors.Add(e); + throw; } finally { From de8c4e6d564da5f2cc4aa55518cd8210985260c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 16:13:02 +0900 Subject: [PATCH 288/302] Remove unique constraints on hash columns We are going to allow multiple instances of the same beatmap info hash as they could be in different beatmap sets. --- osu.Game/Database/OsuDbContext.cs | 4 +- ...54_RemoveUniqueHashConstraints.Designer.cs | 377 ++++++++++++++++++ ...80529055154_RemoveUniqueHashConstraints.cs | 53 +++ .../Migrations/OsuDbContextModelSnapshot.cs | 16 +- 4 files changed, 441 insertions(+), 9 deletions(-) create mode 100644 osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs create mode 100644 osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.cs diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 0ae197d62d..7758b3eb25 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -82,8 +82,8 @@ namespace osu.Game.Database base.OnModelCreating(modelBuilder); modelBuilder.Entity().HasIndex(b => b.OnlineBeatmapID).IsUnique(); - modelBuilder.Entity().HasIndex(b => b.MD5Hash).IsUnique(); - modelBuilder.Entity().HasIndex(b => b.Hash).IsUnique(); + modelBuilder.Entity().HasIndex(b => b.MD5Hash); + modelBuilder.Entity().HasIndex(b => b.Hash); modelBuilder.Entity().HasIndex(b => b.OnlineBeatmapSetID).IsUnique(); modelBuilder.Entity().HasIndex(b => b.DeletePending); diff --git a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs new file mode 100644 index 0000000000..f28408bfb3 --- /dev/null +++ b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs @@ -0,0 +1,377 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using osu.Game.Database; +using System; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20180529055154_RemoveUniqueHashConstraints")] + partial class RemoveUniqueHashConstraints + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.3-rtm-10026"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntKey") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.cs b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.cs new file mode 100644 index 0000000000..fe8c983a3f --- /dev/null +++ b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.cs @@ -0,0 +1,53 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace osu.Game.Migrations +{ + public partial class RemoveUniqueHashConstraints : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_BeatmapInfo_Hash", + table: "BeatmapInfo"); + + migrationBuilder.DropIndex( + name: "IX_BeatmapInfo_MD5Hash", + table: "BeatmapInfo"); + + migrationBuilder.CreateIndex( + name: "IX_BeatmapInfo_Hash", + table: "BeatmapInfo", + column: "Hash"); + + migrationBuilder.CreateIndex( + name: "IX_BeatmapInfo_MD5Hash", + table: "BeatmapInfo", + column: "MD5Hash"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_BeatmapInfo_Hash", + table: "BeatmapInfo"); + + migrationBuilder.DropIndex( + name: "IX_BeatmapInfo_MD5Hash", + table: "BeatmapInfo"); + + migrationBuilder.CreateIndex( + name: "IX_BeatmapInfo_Hash", + table: "BeatmapInfo", + column: "Hash", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_BeatmapInfo_MD5Hash", + table: "BeatmapInfo", + column: "MD5Hash", + unique: true); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 2abbe7785f..d750d50b5b 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -1,7 +1,11 @@ // using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; using osu.Game.Database; +using System; namespace osu.Game.Migrations { @@ -12,7 +16,7 @@ namespace osu.Game.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.0.0-rtm-26452"); + .HasAnnotation("ProductVersion", "2.0.3-rtm-10026"); modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => { @@ -27,9 +31,9 @@ namespace osu.Game.Migrations b.Property("OverallDifficulty"); - b.Property("SliderMultiplier"); + b.Property("SliderMultiplier"); - b.Property("SliderTickRate"); + b.Property("SliderTickRate"); b.HasKey("ID"); @@ -91,11 +95,9 @@ namespace osu.Game.Migrations b.HasIndex("BeatmapSetInfoID"); - b.HasIndex("Hash") - .IsUnique(); + b.HasIndex("Hash"); - b.HasIndex("MD5Hash") - .IsUnique(); + b.HasIndex("MD5Hash"); b.HasIndex("MetadataID"); From 47d88a48a246064a753499882cbc07e1ed721250 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 16:14:09 +0900 Subject: [PATCH 289/302] Add logging on import processes --- osu.Game/Beatmaps/BeatmapManager.cs | 3 ++- osu.Game/Database/ArchiveModelManager.cs | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 36fde8a319..b7bece9492 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -107,6 +107,7 @@ namespace osu.Game.Beatmaps { Delete(existingOnlineId); beatmaps.PurgeDeletable(s => s.ID == existingOnlineId.ID); + Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({model.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database); } } @@ -303,7 +304,7 @@ namespace osu.Game.Beatmaps { // let's make sure there are actually .osu files to import. string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu")); - if (string.IsNullOrEmpty(mapName)) throw new InvalidOperationException("No beatmap files found in the map folder."); + if (string.IsNullOrEmpty(mapName)) throw new InvalidOperationException("No beatmap files found in this beatmap archive."); BeatmapMetadata metadata; using (var stream = new StreamReader(reader.GetStream(mapName))) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 99f1e9f581..74c7b3df5d 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -190,7 +190,11 @@ namespace osu.Game.Database var existing = CheckForExisting(item); - if (existing != null) return existing; + if (existing != null) + { + Logger.Log($"Found existing {typeof(TModel)} for {archive.Name} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); + return existing; + } item.Files = createFileInfos(archive, Files); @@ -205,9 +209,12 @@ namespace osu.Game.Database throw; } } + + Logger.Log($"Import of {archive.Name} successfully completed!", LoggingTarget.Database); } catch { + Logger.Log($"Import of {archive.Name} failed and has been rolled back.", LoggingTarget.Database); item = null; } From 0adc16f9bd4836030dde06cae1248d35a07f384f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 16:15:44 +0900 Subject: [PATCH 290/302] Handle online ID mismatches and clashes on beatmap import --- osu.Game/Beatmaps/BeatmapManager.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b7bece9492..abc0351a82 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -81,7 +81,7 @@ namespace osu.Game.Beatmaps protected override void Populate(BeatmapSetInfo model, ArchiveReader archive) { - model.Beatmaps = createBeatmapDifficulties(archive); + model.Beatmaps = createBeatmapDifficulties(model, archive); // remove metadata from difficulties where it matches the set foreach (BeatmapInfo b in model.Beatmaps) @@ -322,7 +322,7 @@ namespace osu.Game.Beatmaps /// /// Create all required s for the provided archive. /// - private List createBeatmapDifficulties(ArchiveReader reader) + private List createBeatmapDifficulties(BeatmapSetInfo model, ArchiveReader reader) { var beatmapInfos = new List(); @@ -342,6 +342,14 @@ namespace osu.Game.Beatmaps beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash(); + // ensure we have the same online set ID as the set itself. + beatmap.BeatmapInfo.OnlineBeatmapSetID = model.OnlineBeatmapSetID; + beatmap.BeatmapInfo.Metadata.OnlineBeatmapSetID = model.OnlineBeatmapSetID; + + // check that no existing beatmap exists that is imported with the same online beatmap ID. if so, give it precedence. + if (beatmap.BeatmapInfo.OnlineBeatmapID.HasValue && QueryBeatmap(b => b.OnlineBeatmapID.Value == beatmap.BeatmapInfo.OnlineBeatmapID.Value) != null) + beatmap.BeatmapInfo.OnlineBeatmapID = null; + RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); beatmap.BeatmapInfo.Ruleset = ruleset; From 749a69567b7bf5a26123b361b0be743f38d7ebe3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 16:18:20 +0900 Subject: [PATCH 291/302] Add EF tooling references --- osu.Desktop/osu.Desktop.csproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 3a35568f8f..af027da2fc 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -20,6 +20,8 @@ osu.Desktop.Program + + @@ -36,4 +38,8 @@ + + + + \ No newline at end of file From 6f72e5a876762bb5d10b28b4d8da24ae5b5ddb71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 29 May 2018 10:27:21 +0200 Subject: [PATCH 292/302] Fix Debug mode instead of Release mode for mono debug target --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 11141dc182..32c82685c0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -22,7 +22,7 @@ }, "type": "mono", "request": "launch", - "program": "${workspaceRoot}/osu.Game.Tests/bin/Debug/net471/osu.Game.Tests.exe", + "program": "${workspaceRoot}/osu.Game.Tests/bin/Release/net471/osu.Game.Tests.exe", "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release, msbuild)", "runtimeExecutable": null, From 4a18951cce0279731bf7afae07f330dda4d2d37f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 18:37:45 +0900 Subject: [PATCH 293/302] Report full error to log file --- osu.Game/Database/ArchiveModelManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 99f1e9f581..6a31182370 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -206,8 +206,9 @@ namespace osu.Game.Database } } } - catch + catch (Exception e) { + Logger.Error(e, $"Import of {archive.Name} failed and has been rolled back.", LoggingTarget.Database); item = null; } From 31ab6f240841b5be96077c72e7761109e690c5e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 May 2018 19:43:52 +0900 Subject: [PATCH 294/302] Fix event flushing sticking on early return --- osu.Game/Database/ArchiveModelManager.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 6a31182370..62d8c16946 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -174,7 +174,7 @@ namespace osu.Game.Database /// The archive to be imported. public TModel Import(ArchiveReader archive) { - TModel item; + TModel item = null; delayEvents(); try @@ -211,9 +211,12 @@ namespace osu.Game.Database Logger.Error(e, $"Import of {archive.Name} failed and has been rolled back.", LoggingTarget.Database); item = null; } + finally + { + // we only want to flush events after we've confirmed the write context didn't have any errors. + flushEvents(item != null); + } - // we only want to flush events after we've confirmed the write context didn't have any errors. - flushEvents(item != null); return item; } From e23e2bd3485045eb079b4c69f71b5cdf50b98260 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 May 2018 13:37:52 +0900 Subject: [PATCH 295/302] Fix recycling never being performed due to incorrect ordering --- osu.Game/Database/DatabaseContextFactory.cs | 33 +++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index ec408456e3..f57246453e 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -64,24 +64,25 @@ namespace osu.Game.Database currentWriteDidWrite |= usage.PerformedWrite; currentWriteDidError |= usage.Errors.Any(); - if (usages > 0) return; - - if (currentWriteDidError) - currentWriteTransaction?.Rollback(); - else - currentWriteTransaction?.Commit(); - - currentWriteTransaction = null; - currentWriteDidWrite = false; - currentWriteDidError = false; - - if (currentWriteDidWrite) + if (usages == 0) { - // explicitly dispose to ensure any outstanding flushes happen as soon as possible (and underlying resources are purged). - usage.Context.Dispose(); + if (currentWriteDidError) + currentWriteTransaction?.Rollback(); + else + currentWriteTransaction?.Commit(); - // once all writes are complete, we want to refresh thread-specific contexts to make sure they don't have stale local caches. - recycleThreadContexts(); + if (currentWriteDidWrite || currentWriteDidError) + { + // explicitly dispose to ensure any outstanding flushes happen as soon as possible (and underlying resources are purged). + usage.Context.Dispose(); + + // once all writes are complete, we want to refresh thread-specific contexts to make sure they don't have stale local caches. + recycleThreadContexts(); + } + + currentWriteTransaction = null; + currentWriteDidWrite = false; + currentWriteDidError = false; } } finally From 4a7de043e080aeb087de9d67eb7b3627a3471bf7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 May 2018 13:43:25 +0900 Subject: [PATCH 296/302] Recycle all contexts on beginning a write operation for the time being --- osu.Game/Database/DatabaseContextFactory.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index f57246453e..a1d371f431 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -48,7 +48,14 @@ namespace osu.Game.Database Monitor.Enter(writeLock); if (currentWriteTransaction == null && withTransaction) + { + // this mitigates the fact that changes on tracked entities will not be rolled back with the transaction by ensuring write operations are always executed in isolated contexts. + // if this results in sub-optimal efficiency, we may need to look into removing Database-level transactions in favour of running SaveChanges where we currently commit the transaction. + if (threadContexts.IsValueCreated) + recycleThreadContexts(); + currentWriteTransaction = threadContexts.Value.Database.BeginTransaction(); + } Interlocked.Increment(ref currentWriteUsages); From eb893174947ae5cf8d050d932b27658cfab990cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 May 2018 13:43:43 +0900 Subject: [PATCH 297/302] Remove performance optimisation tracking disables to keep things simple for now --- osu.Game/Database/ArchiveModelManager.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 62d8c16946..1505ac0549 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -240,12 +240,8 @@ namespace osu.Game.Database /// The item to delete. public void Delete(TModel item) { - using (var usage = ContextFactory.GetForWrite()) + using (ContextFactory.GetForWrite()) { - var context = usage.Context; - - context.ChangeTracker.AutoDetectChangesEnabled = false; - // re-fetch the model on the import context. var foundModel = queryModel().Include(s => s.Files).ThenInclude(f => f.FileInfo).First(s => s.ID == item.ID); @@ -253,8 +249,6 @@ namespace osu.Game.Database if (ModelStore.Delete(foundModel)) Files.Dereference(foundModel.Files.Select(f => f.FileInfo).ToArray()); - - context.ChangeTracker.AutoDetectChangesEnabled = true; } } From ff93a54a64de5f81039f31f4faa7f08f2d0b432c Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Wed, 30 May 2018 23:16:54 -0300 Subject: [PATCH 298/302] Default Type to Title, use ToLower for the screen type title. --- osu.Game/Screens/Multi/Header.cs | 2 +- osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs | 1 - osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index fb4da45aca..46610a36d8 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => screenType.Text = ((MultiplayerScreen)s).Type; + breadcrumbs.Current.ValueChanged += s => screenType.Text = ((MultiplayerScreen)s).Type.ToLower(); breadcrumbs.Current.TriggerChange(); } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index f0c93b1146..016babcaa5 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -25,7 +25,6 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected readonly FillFlowContainer RoomsContainer; protected readonly RoomInspector Inspector; - public override string Type => "lounge"; public override string Title => "Lounge"; protected override Container TransitionContent => content; diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs index cdfa17a7a6..fa9b40684c 100644 --- a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Multi.Screens /// /// The type to display in the title of the . /// - public abstract string Type { get; } + public virtual string Type => Title; protected override void OnEntering(Screen last) { From 319faf12f7a9b4e010b318a8f470db825dadbd04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 May 2018 12:39:56 +0900 Subject: [PATCH 299/302] Fix incorrect naming of label --- osu.Game.Tests/Visual/TestCaseMods.cs | 8 ++++---- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index cf26230868..3255478bea 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -199,13 +199,13 @@ namespace osu.Game.Tests.Visual private void testRankedText(Mod mod) { AddWaitStep(1, "wait for fade"); - AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha == 0); + AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); selectNext(mod); AddWaitStep(1, "wait for fade"); - AddAssert("check for unranked", () => modSelect.RankedLabel.Alpha != 0); + AddAssert("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); selectPrevious(mod); AddWaitStep(1, "wait for fade"); - AddAssert("check for ranked", () => modSelect.RankedLabel.Alpha == 0); + AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); } private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1)); @@ -241,7 +241,7 @@ namespace osu.Game.Tests.Visual } public new OsuSpriteText MultiplierLabel => base.MultiplierLabel; - public new OsuSpriteText RankedLabel => base.RankedLabel; + public new OsuSpriteText UnrankedLabel => base.UnrankedLabel; public new TriangleButton DeselectAllButton => base.DeselectAllButton; public new Color4 LowMultiplierColour => base.LowMultiplierColour; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 69f409c3d2..3c44532627 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Mods protected Color4 LowMultiplierColour, HighMultiplierColour; protected readonly TriangleButton DeselectAllButton; - protected readonly OsuSpriteText MultiplierLabel, RankedLabel; + protected readonly OsuSpriteText MultiplierLabel, UnrankedLabel; private readonly FillFlowContainer footerContainer; protected override bool BlockPassThroughKeyboard => false; @@ -107,9 +107,9 @@ namespace osu.Game.Overlays.Mods MultiplierLabel.FadeColour(Color4.White, 200); if (ranked) - RankedLabel.FadeOut(200); + UnrankedLabel.FadeOut(200); else - RankedLabel.FadeIn(200); + UnrankedLabel.FadeIn(200); } protected override void PopOut() @@ -373,7 +373,7 @@ namespace osu.Game.Overlays.Mods Top = 5 } }, - RankedLabel = new OsuSpriteText + UnrankedLabel = new OsuSpriteText { Font = @"Exo2.0-Bold", Text = @"(Unranked)", From 205aa1a3cdd5adf2927e78dcd9187306bf4f8889 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 May 2018 12:44:11 +0900 Subject: [PATCH 300/302] Fetch colour from OsuColour palette --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 3c44532627..5eb507c67c 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -58,6 +58,7 @@ namespace osu.Game.Overlays.Mods LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; + UnrankedLabel.Colour = colours.Blue; if (osu != null) Ruleset.BindTo(osu.Ruleset); @@ -378,7 +379,6 @@ namespace osu.Game.Overlays.Mods Font = @"Exo2.0-Bold", Text = @"(Unranked)", TextSize = 30, - Colour = OsuColour.FromHex(@"66ccff"), Shadow = true, Margin = new MarginPadding { From 0f6c623ebb15b222cb21076a8d9d98a85d2ae3a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 May 2018 12:44:59 +0900 Subject: [PATCH 301/302] Tidy up some unnecessary lines --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 5eb507c67c..f1624721da 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -107,10 +107,7 @@ namespace osu.Game.Overlays.Mods else MultiplierLabel.FadeColour(Color4.White, 200); - if (ranked) - UnrankedLabel.FadeOut(200); - else - UnrankedLabel.FadeIn(200); + UnrankedLabel.FadeTo(ranked ? 0 : 1, 200); } protected override void PopOut() @@ -357,7 +354,6 @@ namespace osu.Game.Overlays.Mods { Text = @"Score Multiplier:", TextSize = 30, - Shadow = true, Margin = new MarginPadding { Top = 5, @@ -368,7 +364,6 @@ namespace osu.Game.Overlays.Mods { Font = @"Exo2.0-Bold", TextSize = 30, - Shadow = true, Margin = new MarginPadding { Top = 5 @@ -379,7 +374,6 @@ namespace osu.Game.Overlays.Mods Font = @"Exo2.0-Bold", Text = @"(Unranked)", TextSize = 30, - Shadow = true, Margin = new MarginPadding { Top = 5, From b7511251d99ee6158e918725a35a26134c5e3529 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 May 2018 12:50:01 +0900 Subject: [PATCH 302/302] Remove pointless FillMode specification --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 59d5ecd07f..d8c7b5130d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -407,7 +407,6 @@ namespace osu.Game.Rulesets.Catch.UI public CatcherSprite() { Size = new Vector2(CATCHER_SIZE); - FillMode = FillMode.Fill; // Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling. OriginPosition = new Vector2(-0.02f, 0.06f) * CATCHER_SIZE;