From 42aa02579bb909918ecc0cd50a6a163366c372aa Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sun, 29 Apr 2018 19:52:33 +0300 Subject: [PATCH 01/64] 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 02/64] 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 b08b24b6da17260a2a028b6a070e36093429f6a4 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 4 May 2018 21:18:48 +0300 Subject: [PATCH 03/64] 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 44bbb8700ecc1bdd652c35766bfbaa54310a5855 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 8 May 2018 00:22:11 +0300 Subject: [PATCH 04/64] 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 b9adeeb063400477e53e093438c51fb9714d9786 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 10 May 2018 21:35:26 -0300 Subject: [PATCH 05/64] 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 06/64] 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 07/64] 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 08/64] 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 09/64] 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 10/64] 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 fa403e4e2ae4a2a0ad36f5f2261239093994c2d3 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Fri, 11 May 2018 04:45:27 -0300 Subject: [PATCH 11/64] 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 41de02fc78e08513e9588a6d02090044155ed32f Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Fri, 11 May 2018 13:43:53 -0300 Subject: [PATCH 12/64] 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 13/64] 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 8a5bd27c2018e0ae4f980e77aea891f70b1ce562 Mon Sep 17 00:00:00 2001 From: ocboogie Date: Sat, 12 May 2018 16:30:29 -0700 Subject: [PATCH 14/64] 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 15/64] 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 327c7432be72ab79e882a6dc9d8e0c51d310d485 Mon Sep 17 00:00:00 2001 From: ocboogie Date: Sun, 13 May 2018 19:33:52 -0700 Subject: [PATCH 16/64] 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 17/64] 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 e802b722f053b0f375566eaee81859d07bb98178 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 14 May 2018 20:27:05 +0300 Subject: [PATCH 18/64] 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 19/64] 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 0325b1bd7ac7b9b0af4bc9f2bd210bfe00aa12bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 May 2018 19:42:30 +0900 Subject: [PATCH 20/64] 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 21/64] 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 c0c449e453d2a71043386cf120a633c40ff2c123 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 May 2018 22:53:33 +0900 Subject: [PATCH 22/64] 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 23/64] 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 24/64] 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 25/64] 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 26/64] 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 27/64] 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 28/64] 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 29/64] 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 30/64] 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 31/64] 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 32/64] 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 33/64] 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 cf44357bdb1f4f6f6f4bce4e136e3ac872a12a55 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 May 2018 13:30:48 +0900 Subject: [PATCH 34/64] 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 35/64] 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 36/64] 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 37/64] 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 38/64] 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 39/64] 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 40/64] 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 41/64] 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 42/64] 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 43/64] 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 44/64] 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 45/64] 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 46/64] 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 47/64] 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 48/64] 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 17d1759c37f53893dfdb9c1529206b0f0c2c5083 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 18 May 2018 01:01:54 +0300 Subject: [PATCH 49/64] 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 50/64] 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 51/64] 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 52/64] 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 53/64] 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 54/64] 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 55/64] 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 56/64] 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 57/64] 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 9cd0ec366e2d003e1f6c1923f414010a7208a821 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Sat, 19 May 2018 02:51:51 -0300 Subject: [PATCH 58/64] 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 59/64] 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 60/64] 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 61/64] 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 62/64] 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 63/64] 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 b7e3ea348b15e8cdae2e3963f9b8ee4a405e7ea1 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 21 May 2018 15:53:50 +0200 Subject: [PATCH 64/64] 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();