diff --git a/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs new file mode 100644 index 0000000000..089d6f3ebd --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs @@ -0,0 +1,28 @@ +using System; +using osu.Framework.GameModes.Testing; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; +using OpenTK.Input; +using osu.Game.Overlays.Pause; +using osu.Framework.Graphics.Containers; + + +namespace osu.Desktop.VisualTests.Tests +{ + class TestCasePauseOverlay : TestCase + { + public override string Name => @"PauseOverlay"; + + public override string Description => @"Tests the pause overlay"; + + private PauseOverlay pauseOverlay; + + public override void Reset() + { + base.Reset(); + + Children = new[] { pauseOverlay = new PauseOverlay() }; + pauseOverlay.ToggleVisibility(); + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Pause/PauseButton.cs b/osu.Game/Overlays/Pause/PauseButton.cs new file mode 100644 index 0000000000..cddf9a8bef --- /dev/null +++ b/osu.Game/Overlays/Pause/PauseButton.cs @@ -0,0 +1,54 @@ +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics.Transformations; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; + +namespace osu.Game.Overlays.Pause +{ + public class PauseButton : Button + { + private float height = 100; + private float width = 300; + private float expandedWidth = 350; + + private AudioSample sampleClick; + private AudioSample sampleHover; + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + // Placeholder till the actual samples are added to osu-resources + sampleClick = audio.Sample.Get(@"Menu/menuhit"); + sampleHover = audio.Sample.Get(@"Menu/menuclick"); + } + + protected override bool OnMouseDown(Framework.Input.InputState state, Framework.Graphics.MouseDownEventArgs args) + { + sampleClick.Play(); + + return true; + } + + protected override bool OnHover(Framework.Input.InputState state) + { + sampleHover.Play(); + ResizeTo(new Vector2(expandedWidth, height), 500, EasingTypes.OutElastic); + + return true; + } + + protected override void OnHoverLost(Framework.Input.InputState state) + { + ResizeTo(new Vector2(width, height), 500, EasingTypes.OutElastic); + } + + public PauseButton() + { Size = new Vector2(width, height); + Colour = Color4.Black; + Shear = new Vector2(0.1f, 0); + } + } +} diff --git a/osu.Game/Overlays/Pause/PauseOverlay.cs b/osu.Game/Overlays/Pause/PauseOverlay.cs new file mode 100644 index 0000000000..9bc5d802ba --- /dev/null +++ b/osu.Game/Overlays/Pause/PauseOverlay.cs @@ -0,0 +1,114 @@ +using System; +using OpenTK; +using OpenTK.Input; +using OpenTK.Graphics; +using osu.Game.Screens; +using osu.Game.Graphics; +using osu.Framework.Input; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics.Transformations; + + +namespace osu.Game.Overlays.Pause +{ + public class PauseOverlay : OverlayContainer + { + private bool paused = false; + + public event Action OnPause; + public event Action OnPlay; + public event Action OnRetry; + public event Action OnQuit; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, + }, + new PauseButton + { + Text = @"Resume", + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Position = new Vector2(0, -200), + Action = Play + }, + new PauseButton + { + Text = @"Retry", + Origin = Anchor.Centre, + Anchor = Anchor.Centre + }, + new PauseButton + { + Text = @"Quit", + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Position = new Vector2(0, 200) + } + }; + } + + protected override void PopIn() + { + this.FadeTo(1, 100, EasingTypes.In); + } + + protected override void PopOut() + { + this.FadeTo(0, 100, EasingTypes.In); + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + switch (args.Key) + { + case Key.Escape: + paused = !paused; + (paused ? (Action)Pause : Play)?.Invoke(); + return true; + } + return base.OnKeyDown(state, args); + } + + private void Pause() + { + paused = true; + Show(); + OnPause?.Invoke(); + } + + private void Play() + { + paused = false; + Hide(); + OnPlay?.Invoke(); + } + + private void Retry() + { + OnRetry?.Invoke(); + } + + private void Quit() + { + OnQuit?.Invoke(); + } + + public PauseOverlay() + { + RelativeSizeAxes = Axes.Both; + AutoSizeAxes = Axes.Both; + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d6594dd2be..61e9e66036 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -15,6 +15,7 @@ using osu.Game.Modes; using osu.Game.Modes.Objects; using osu.Game.Modes.Objects.Drawables; using osu.Game.Screens.Backgrounds; +using osu.Game.Overlays.Pause; using OpenTK.Input; using MouseState = osu.Framework.Input.MouseState; using OpenTK; @@ -39,7 +40,7 @@ namespace osu.Game.Screens.Play public BeatmapInfo BeatmapInfo; public PlayMode PreferredPlayMode; - + private IAdjustableClock sourceClock; private Ruleset ruleset; @@ -48,6 +49,9 @@ namespace osu.Game.Screens.Play private HitRenderer hitRenderer; private Bindable dimLevel; + private PauseOverlay pauseOverlay; + private ScoreOverlay scoreOverlay; + [BackgroundDependencyLoader] private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuGameBase game, OsuConfigManager config) { @@ -92,9 +96,13 @@ namespace osu.Game.Screens.Play ruleset = Ruleset.GetRuleset(usablePlayMode); - var scoreOverlay = ruleset.CreateScoreOverlay(); + scoreOverlay = ruleset.CreateScoreOverlay(); scoreOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor(beatmap.HitObjects.Count)); + pauseOverlay = new PauseOverlay(); + pauseOverlay.OnPause += onPause; + pauseOverlay.OnPlay += onPlay; + hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) @@ -119,6 +127,7 @@ namespace osu.Game.Screens.Play } }, scoreOverlay, + pauseOverlay }; } @@ -163,12 +172,25 @@ namespace osu.Game.Screens.Play }); } + private void onPause() + { + scoreOverlay.KeyCounter.IsCounting = false; + + sourceClock.Stop(); + } + + private void onPlay() + { + scoreOverlay.KeyCounter.IsCounting = true; + sourceClock.Start(); + } + protected override void OnEntering(GameMode last) { base.OnEntering(last); (Background as BackgroundModeBeatmap)?.BlurTo(Vector2.Zero, 1000); - Background?.FadeTo((100f- dimLevel)/100, 1000); + Background?.FadeTo((100f - dimLevel) / 100, 1000); Content.Alpha = 0; dimLevel.ValueChanged += dimChanged; @@ -181,6 +203,17 @@ namespace osu.Game.Screens.Play return base.OnExiting(next); } + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Key != Key.Escape) + { + return base.OnKeyDown(state, args); + } + else { + return pauseOverlay.TriggerKeyDown(state, args); + } + } + private void dimChanged(object sender, EventArgs e) { Background?.FadeTo((100f - dimLevel) / 100, 800);