diff --git a/osu.Desktop.VisualTests/Tests/TestCaseInGameOverlays.cs b/osu.Desktop.VisualTests/Tests/TestCaseInGameOverlays.cs new file mode 100644 index 0000000000..ca59c9faeb --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCaseInGameOverlays.cs @@ -0,0 +1,65 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; +using osu.Framework.Testing; +using osu.Game.Screens.Play; + +namespace osu.Desktop.VisualTests.Tests +{ + internal class TestCaseInGameOverlays : TestCase + { + public override string Description => @"Tests pause and fail overlays"; + + private PauseOverlay pauseOverlay; + private FailOverlay failOverlay; + private int retryCount; + + public override void Reset() + { + base.Reset(); + + pauseOverlay = new PauseOverlay + { + Depth = -1, + OnResume = () => Logger.Log(@"Resume"), + OnRetry = () => Logger.Log(@"Retry"), + OnQuit = () => Logger.Log(@"Quit"), + }; + + failOverlay = new FailOverlay + { + Depth = -1, + OnRetry = () => Logger.Log(@"Retry"), + OnQuit = () => Logger.Log(@"Quit"), + }; + + Add(pauseOverlay); + Add(failOverlay); + + AddStep(@"Pause", delegate { + if(failOverlay.State == Visibility.Visible) + { + failOverlay.Hide(); + } + pauseOverlay.Show(); + }); + AddStep("Fail", delegate { + if (pauseOverlay.State == Visibility.Visible) + { + pauseOverlay.Hide(); + } + failOverlay.Show(); + }); + AddStep("Add Retry", delegate + { + retryCount++; + pauseOverlay.Retries = retryCount; + failOverlay.Retries = retryCount; + }); + + retryCount = 0; + } + } +} diff --git a/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs deleted file mode 100644 index ebf6e0c350..0000000000 --- a/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Logging; -using osu.Framework.Testing; -using osu.Game.Screens.Play; - -namespace osu.Desktop.VisualTests.Tests -{ - internal class TestCasePauseOverlay : TestCase - { - public override string Description => @"Tests the pause overlay"; - - private PauseOverlay pauseOverlay; - private int retryCount; - - public override void Reset() - { - base.Reset(); - - Add(pauseOverlay = new PauseOverlay - { - Depth = -1, - OnResume = () => Logger.Log(@"Resume"), - OnRetry = () => Logger.Log(@"Retry"), - OnQuit = () => Logger.Log(@"Quit") - }); - AddStep("Pause", pauseOverlay.Show); - AddStep("Add Retry", delegate - { - retryCount++; - pauseOverlay.Retries = retryCount; - }); - - retryCount = 0; - } - } -} diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index 1baf322750..ea83b0d71a 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -189,6 +189,7 @@ + @@ -206,7 +207,6 @@ - diff --git a/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapConverter.cs index fec675be54..bae12a98e3 100644 --- a/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -43,7 +43,7 @@ namespace osu.Game.Modes.Osu.Beatmaps return new Slider { StartTime = original.StartTime, - Sample = original.Sample, + Samples = original.Samples, CurveObject = curveData, Position = positionData?.Position ?? Vector2.Zero, NewCombo = comboData?.NewCombo ?? false @@ -55,7 +55,7 @@ namespace osu.Game.Modes.Osu.Beatmaps return new Spinner { StartTime = original.StartTime, - Sample = original.Sample, + Samples = original.Samples, Position = new Vector2(512, 384) / 2, EndTime = endTimeData.EndTime }; @@ -64,7 +64,7 @@ namespace osu.Game.Modes.Osu.Beatmaps return new HitCircle { StartTime = original.StartTime, - Sample = original.Sample, + Samples = original.Samples, Position = positionData?.Position ?? Vector2.Zero, NewCombo = comboData?.NewCombo ?? false }; diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs index e8f2154d7f..be326751ba 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs @@ -67,7 +67,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables ComboIndex = s.ComboIndex, Scale = s.Scale, ComboColour = s.ComboColour, - Sample = s.Sample, + Samples = s.Samples, }), }; @@ -111,7 +111,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables if (repeat > currentRepeat) { if (repeat < slider.RepeatCount && ball.Tracking) - PlaySample(); + PlaySamples(); currentRepeat = repeat; } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs index be66689054..245809c584 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -2,12 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Beatmaps.Samples; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Judgements; using OpenTK; @@ -53,22 +49,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables }; } - private SampleChannel sample; - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - string sampleSet = (HitObject.Sample?.Set ?? SampleSet.Normal).ToString().ToLower(); - - sample = audio.Sample.Get($@"Gameplay/{sampleSet}-slidertick"); - } - - protected override void PlaySample() - { - sample?.Play(); - } - - protected override void CheckJudgement(bool userTriggered) { if (Judgement.TimeOffset >= 0) diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Modes.Osu/Objects/Slider.cs index 38d1dfda5d..a01c517cb2 100644 --- a/osu.Game.Modes.Osu/Objects/Slider.cs +++ b/osu.Game.Modes.Osu/Objects/Slider.cs @@ -2,13 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Game.Beatmaps.Samples; using osu.Game.Beatmaps.Timing; using osu.Game.Modes.Objects.Types; using System; using System.Collections.Generic; using osu.Game.Modes.Objects; using osu.Game.Database; +using System.Linq; +using osu.Game.Audio; namespace osu.Game.Modes.Osu.Objects { @@ -95,11 +96,12 @@ namespace osu.Game.Modes.Osu.Objects StackHeight = StackHeight, Scale = Scale, ComboColour = ComboColour, - Sample = new HitSampleInfo + Samples = Samples.Select(s => new SampleInfo { - Type = SampleType.None, - Set = SampleSet.Soft, - }, + Bank = s.Bank, + Name = @"slidertick", + Volume = s.Volume + }).ToList() }; } } diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 4828d80339..898ace935e 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Samples; using osu.Game.Modes.Objects; using osu.Game.Modes.Objects.Types; using osu.Game.Modes.Taiko.Objects; @@ -11,6 +10,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Database; using osu.Game.IO.Serialization; +using osu.Game.Audio; namespace osu.Game.Modes.Taiko.Beatmaps { @@ -62,9 +62,9 @@ namespace osu.Game.Modes.Taiko.Beatmaps var endTimeData = obj as IHasEndTime; // Old osu! used hit sounding to determine various hit type information - SampleType sample = obj.Sample?.Type ?? SampleType.None; + List samples = obj.Samples; - bool strong = (sample & SampleType.Finish) > 0; + bool strong = samples.Any(s => s.Name == SampleInfo.HIT_FINISH); if (distanceData != null) { @@ -103,7 +103,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps yield return new CentreHit { StartTime = j, - Sample = obj.Sample, + Samples = obj.Samples, IsStrong = strong, }; } @@ -113,7 +113,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps yield return new DrumRoll { StartTime = obj.StartTime, - Sample = obj.Sample, + Samples = obj.Samples, IsStrong = strong, Duration = taikoDuration, TickRate = beatmap.BeatmapInfo.Difficulty.SliderTickRate == 3 ? 3 : 4, @@ -127,7 +127,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps yield return new Swell { StartTime = obj.StartTime, - Sample = obj.Sample, + Samples = obj.Samples, IsStrong = strong, Duration = endTimeData.Duration, RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier), @@ -135,23 +135,23 @@ namespace osu.Game.Modes.Taiko.Beatmaps } else { - bool isCentre = (sample & ~(SampleType.Finish | SampleType.Normal)) == 0; + bool isRim = samples.Any(s => s.Name == SampleInfo.HIT_CLAP || s.Name == SampleInfo.HIT_WHISTLE); - if (isCentre) + if (isRim) { - yield return new CentreHit + yield return new RimHit { StartTime = obj.StartTime, - Sample = obj.Sample, + Samples = obj.Samples, IsStrong = strong, }; } else { - yield return new RimHit + yield return new CentreHit { StartTime = obj.StartTime, - Sample = obj.Sample, + Samples = obj.Samples, IsStrong = strong, }; } diff --git a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs index 3a66c55ea5..4f26ffd3a1 100644 --- a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs @@ -1,13 +1,13 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Beatmaps.Samples; using osu.Game.Modes.Objects.Types; using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps.Timing; using osu.Game.Database; +using osu.Game.Audio; namespace osu.Game.Modes.Taiko.Objects { @@ -82,11 +82,12 @@ namespace osu.Game.Modes.Taiko.Objects TickSpacing = tickSpacing, StartTime = t, IsStrong = IsStrong, - Sample = new HitSampleInfo + Samples = Samples.Select(s => new SampleInfo { - Type = SampleType.None, - Set = SampleSet.Soft - } + Bank = s.Bank, + Name = @"slidertick", + Volume = s.Volume + }).ToList() }); first = false; diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs index 356fa5a6c1..8183bc952e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs @@ -6,11 +6,12 @@ using NUnit.Framework; using OpenTK; using OpenTK.Graphics; using osu.Game.Beatmaps.Formats; -using osu.Game.Beatmaps.Samples; using osu.Game.Modes; using osu.Game.Tests.Resources; using osu.Game.Modes.Osu; using osu.Game.Modes.Objects.Legacy; +using System.Linq; +using osu.Game.Audio; namespace osu.Game.Tests.Beatmaps.Formats { @@ -55,7 +56,6 @@ namespace osu.Game.Tests.Beatmaps.Formats var beatmapInfo = decoder.Decode(new StreamReader(stream)).BeatmapInfo; Assert.AreEqual(0, beatmapInfo.AudioLeadIn); Assert.AreEqual(false, beatmapInfo.Countdown); - Assert.AreEqual(SampleSet.Soft, beatmapInfo.SampleSet); Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); Assert.AreEqual(false, beatmapInfo.SpecialStyle); Assert.AreEqual(PlayMode.Osu, beatmapInfo.Mode); @@ -137,12 +137,12 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsNotNull(slider); Assert.AreEqual(new Vector2(192, 168), slider.Position); Assert.AreEqual(956, slider.StartTime); - Assert.AreEqual(SampleType.None, slider.Sample.Type); + Assert.IsTrue(slider.Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL)); var hit = beatmap.HitObjects[1] as LegacyHit; Assert.IsNotNull(hit); Assert.AreEqual(new Vector2(304, 56), hit.Position); Assert.AreEqual(1285, hit.StartTime); - Assert.AreEqual(SampleType.Clap, hit.Sample.Type); + Assert.IsTrue(hit.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP)); } } } diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs new file mode 100644 index 0000000000..171a1bdf75 --- /dev/null +++ b/osu.Game/Audio/SampleInfo.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Audio +{ + public class SampleInfo + { + public const string HIT_WHISTLE = @"hitwhistle"; + public const string HIT_FINISH = @"hitfinish"; + public const string HIT_NORMAL = @"hitnormal"; + public const string HIT_CLAP = @"hitclap"; + + /// + /// The bank to load the sample from. + /// + public string Bank; + + /// + /// The name of the sample to load. + /// + public string Name; + + /// + /// The sample volume. + /// + public int Volume; + } +} diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 2bf282346a..35d81311d2 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -6,7 +6,6 @@ using System.Globalization; using System.IO; using OpenTK.Graphics; using osu.Game.Beatmaps.Events; -using osu.Game.Beatmaps.Samples; using osu.Game.Beatmaps.Timing; using osu.Game.Modes; using osu.Game.Modes.Objects; @@ -31,6 +30,9 @@ namespace osu.Game.Beatmaps.Formats // TODO: Not sure how far back to go, or differences between versions } + private LegacySampleBank defaultSampleBank; + private int defaultSampleVolume = 100; + private readonly int beatmapVersion; public OsuLegacyDecoder() @@ -73,7 +75,10 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.Countdown = int.Parse(val) == 1; break; case @"SampleSet": - beatmap.BeatmapInfo.SampleSet = (SampleSet)Enum.Parse(typeof(SampleSet), val); + defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), val); + break; + case @"SampleVolume": + defaultSampleVolume = int.Parse(val); break; case @"StackLeniency": beatmap.BeatmapInfo.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo); @@ -203,28 +208,56 @@ namespace osu.Game.Beatmaps.Formats private void handleTimingPoints(Beatmap beatmap, string val) { - ControlPoint cp = null; - string[] split = val.Split(','); - if (split.Length > 2) + double time = double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo); + double beatLength = double.Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo); + + TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple; + if (split.Length >= 3) + timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)int.Parse(split[2]); + + LegacySampleBank sampleSet = defaultSampleBank; + if (split.Length >= 4) + sampleSet = (LegacySampleBank)int.Parse(split[3]); + + //SampleBank sampleBank = SampleBank.Default; + //if (split.Length >= 5) + // sampleBank = (SampleBank)int.Parse(split[4]); + + int sampleVolume = defaultSampleVolume; + if (split.Length >= 6) + sampleVolume = int.Parse(split[5]); + + bool timingChange = true; + if (split.Length >= 7) + timingChange = split[6][0] == '1'; + + bool kiaiMode = false; + bool omitFirstBarSignature = false; + if (split.Length >= 8) { - int effectFlags = split.Length > 7 ? Convert.ToInt32(split[7], NumberFormatInfo.InvariantInfo) : 0; - double beatLength = double.Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo); - cp = new ControlPoint - { - Time = double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo), - BeatLength = beatLength > 0 ? beatLength : 0, - SpeedMultiplier = beatLength < 0 ? -beatLength / 100.0 : 1, - TimingChange = split.Length <= 6 || split[6][0] == '1', - KiaiMode = (effectFlags & 1) > 0, - OmitFirstBarLine = (effectFlags & 8) > 0, - TimeSignature = (TimeSignatures)int.Parse(split[2]) - }; + int effectFlags = int.Parse(split[7]); + kiaiMode = (effectFlags & 1) > 0; + omitFirstBarSignature = (effectFlags & 8) > 0; } - if (cp != null) - beatmap.TimingInfo.ControlPoints.Add(cp); + string stringSampleSet = sampleSet.ToString().ToLower(); + if (stringSampleSet == @"none") + stringSampleSet = @"normal"; + + beatmap.TimingInfo.ControlPoints.Add(new ControlPoint + { + Time = time, + BeatLength = beatLength, + SpeedMultiplier = beatLength < 0 ? -beatLength / 100.0 : 1, + TimingChange = timingChange, + TimeSignature = timeSignature, + SampleBank = stringSampleSet, + SampleVolume = sampleVolume, + KiaiMode = kiaiMode, + OmitFirstBarLine = omitFirstBarSignature + }); } private void handleColours(Beatmap beatmap, string key, string val, ref bool hasCustomColours) @@ -271,7 +304,7 @@ namespace osu.Game.Beatmaps.Formats { beatmap.BeatmapInfo.BeatmapVersion = beatmapVersion; - HitObjectParser parser = null; + HitObjectParser parser = new LegacyHitObjectParser(); Section section = Section.None; bool hasCustomColours = false; @@ -305,7 +338,6 @@ namespace osu.Game.Beatmaps.Formats { case Section.General: handleGeneral(beatmap, key, val); - parser = new LegacyHitObjectParser(); break; case Section.Editor: handleEditor(beatmap, key, val); @@ -326,7 +358,7 @@ namespace osu.Game.Beatmaps.Formats handleColours(beatmap, key, val, ref hasCustomColours); break; case Section.HitObjects: - var obj = parser?.Parse(val); + var obj = parser.Parse(val); if (obj != null) beatmap.HitObjects.Add(obj); @@ -335,5 +367,13 @@ namespace osu.Game.Beatmaps.Formats } } } + + internal enum LegacySampleBank + { + None = 0, + Normal = 1, + Soft = 2, + Drum = 3 + } } } diff --git a/osu.Game/Beatmaps/Samples/HitSampleInfo.cs b/osu.Game/Beatmaps/Samples/HitSampleInfo.cs deleted file mode 100644 index c1cf1bd5e5..0000000000 --- a/osu.Game/Beatmaps/Samples/HitSampleInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Beatmaps.Samples -{ - public class HitSampleInfo : SampleInfo - { - public SampleType Type { get; set; } - } -} diff --git a/osu.Game/Beatmaps/Samples/SampleBank.cs b/osu.Game/Beatmaps/Samples/SampleBank.cs deleted file mode 100644 index 2154713cff..0000000000 --- a/osu.Game/Beatmaps/Samples/SampleBank.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Beatmaps.Samples -{ - public enum SampleBank - { - Default = 0, - Custom1 = 1, - Custom2 = 2 - } -} \ No newline at end of file diff --git a/osu.Game/Beatmaps/Samples/SampleInfo.cs b/osu.Game/Beatmaps/Samples/SampleInfo.cs deleted file mode 100644 index 5f9572c871..0000000000 --- a/osu.Game/Beatmaps/Samples/SampleInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Beatmaps.Samples -{ - public class SampleInfo - { - public SampleBank Bank; - public SampleSet Set; - } -} diff --git a/osu.Game/Beatmaps/Samples/SampleSet.cs b/osu.Game/Beatmaps/Samples/SampleSet.cs deleted file mode 100644 index 72f97d9e0e..0000000000 --- a/osu.Game/Beatmaps/Samples/SampleSet.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Beatmaps.Samples -{ - public enum SampleSet - { - None = 0, - Normal = 1, - Soft = 2, - Drum = 3 - } -} \ No newline at end of file diff --git a/osu.Game/Beatmaps/Samples/SampleType.cs b/osu.Game/Beatmaps/Samples/SampleType.cs deleted file mode 100644 index 0a18a65201..0000000000 --- a/osu.Game/Beatmaps/Samples/SampleType.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; - -namespace osu.Game.Beatmaps.Samples -{ - [Flags] - public enum SampleType - { - None = 0, - Normal = 1, - Whistle = 2, - Finish = 4, - Clap = 8 - }; -} \ No newline at end of file diff --git a/osu.Game/Beatmaps/Timing/ControlPoint.cs b/osu.Game/Beatmaps/Timing/ControlPoint.cs index e306796d24..ea152ccb39 100644 --- a/osu.Game/Beatmaps/Timing/ControlPoint.cs +++ b/osu.Game/Beatmaps/Timing/ControlPoint.cs @@ -5,6 +5,8 @@ namespace osu.Game.Beatmaps.Timing { public class ControlPoint { + public string SampleBank; + public int SampleVolume; public TimeSignatures TimeSignature; public double Time; public double BeatLength = 500; diff --git a/osu.Game/Beatmaps/Timing/SampleChange.cs b/osu.Game/Beatmaps/Timing/SampleChange.cs deleted file mode 100644 index 2946fd749b..0000000000 --- a/osu.Game/Beatmaps/Timing/SampleChange.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Beatmaps.Samples; - -namespace osu.Game.Beatmaps.Timing -{ - public class SampleChange : ControlPoint - { - public SampleInfo Sample; - } -} diff --git a/osu.Game/Beatmaps/Timing/TimingChange.cs b/osu.Game/Beatmaps/Timing/TimingChange.cs deleted file mode 100644 index b759fcd01c..0000000000 --- a/osu.Game/Beatmaps/Timing/TimingChange.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Beatmaps.Timing -{ - internal class TimingChange : ControlPoint - { - public TimingChange(double beatLength) - { - BeatLength = beatLength; - } - - public double BPM => 60000 / BeatLength; - } -} diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index a4a960a7bc..9a2cda2d80 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -35,6 +35,7 @@ namespace osu.Game.Configuration Set(OsuConfig.MenuParallax, true); + Set(OsuConfig.ShowInterface, true); Set(OsuConfig.KeyOverlay, false); //todo: implement all settings below this line (remove the Disabled set when doing so). @@ -89,7 +90,6 @@ namespace osu.Game.Configuration Set(OsuConfig.LastVersionPermissionsFailed, string.Empty).Disabled = true; Set(OsuConfig.LoadSubmittedThread, true).Disabled = true; Set(OsuConfig.LobbyPlayMode, -1).Disabled = true; - Set(OsuConfig.ShowInterface, true).Disabled = true; Set(OsuConfig.ShowInterfaceDuringRelax, false).Disabled = true; Set(OsuConfig.LobbyShowExistingOnly, false).Disabled = true; Set(OsuConfig.LobbyShowFriendsOnly, false).Disabled = true; diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Database/BeatmapInfo.cs index b9ec0c69af..dbc975bd74 100644 --- a/osu.Game/Database/BeatmapInfo.cs +++ b/osu.Game/Database/BeatmapInfo.cs @@ -49,7 +49,6 @@ namespace osu.Game.Database // General public int AudioLeadIn { get; set; } public bool Countdown { get; set; } - public SampleSet SampleSet { get; set; } public float StackLeniency { get; set; } public bool SpecialStyle { get; set; } public PlayMode Mode { get; set; } diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index c0b1645b79..e346a22813 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -7,11 +7,11 @@ using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Game.Beatmaps.Samples; using osu.Game.Modes.Judgements; using Container = osu.Framework.Graphics.Containers.Container; using osu.Game.Modes.Objects.Types; using OpenTK.Graphics; +using osu.Game.Audio; namespace osu.Game.Modes.Objects.Drawables { @@ -45,15 +45,15 @@ namespace osu.Game.Modes.Objects.Drawables UpdateState(state); if (State == ArmedState.Hit) - PlaySample(); + PlaySamples(); } } - protected SampleChannel Sample; + protected List Samples = new List(); - protected virtual void PlaySample() + protected void PlaySamples() { - Sample?.Play(); + Samples.ForEach(s => s?.Play()); } [BackgroundDependencyLoader] @@ -156,13 +156,16 @@ namespace osu.Game.Modes.Objects.Drawables [BackgroundDependencyLoader] private void load(AudioManager audio) { - SampleType type = HitObject.Sample?.Type ?? SampleType.None; - if (type == SampleType.None) - type = SampleType.Normal; + foreach (SampleInfo sample in HitObject.Samples) + { + SampleChannel channel = audio.Sample.Get($@"Gameplay/{sample.Bank}-{sample.Name}"); - SampleSet sampleSet = HitObject.Sample?.Set ?? SampleSet.Normal; + if (channel == null) + continue; - Sample = audio.Sample.Get($@"Gameplay/{sampleSet.ToString().ToLower()}-hit{type.ToString().ToLower()}"); + channel.Volume.Value = sample.Volume; + Samples.Add(channel); + } } private List> nestedHitObjects; diff --git a/osu.Game/Modes/Objects/HitObject.cs b/osu.Game/Modes/Objects/HitObject.cs index f2712d92ba..f362d6de63 100644 --- a/osu.Game/Modes/Objects/HitObject.cs +++ b/osu.Game/Modes/Objects/HitObject.cs @@ -1,9 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Beatmaps.Samples; +using osu.Game.Audio; using osu.Game.Beatmaps.Timing; using osu.Game.Database; +using System.Collections.Generic; namespace osu.Game.Modes.Objects { @@ -21,15 +22,31 @@ namespace osu.Game.Modes.Objects public double StartTime { get; set; } /// - /// The sample to be played when this HitObject is hit. + /// The samples to be played when this hit object is hit. /// - public HitSampleInfo Sample { get; set; } + public List Samples = new List(); /// /// Applies default values to this HitObject. /// /// The difficulty settings to use. /// The timing settings to use. - public virtual void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) { } + public virtual void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) + { + ControlPoint overridePoint; + ControlPoint timingPoint = timing.TimingPointAt(StartTime, out overridePoint); + + foreach (var sample in Samples) + { + if (sample.Volume == 0) + sample.Volume = (overridePoint ?? timingPoint)?.SampleVolume ?? 0; + + // If the bank is not assigned a name, assign it from the control point + if (!string.IsNullOrEmpty(sample.Bank)) + continue; + + sample.Bank = (overridePoint ?? timingPoint)?.SampleBank ?? @"normal"; + } + } } } diff --git a/osu.Game/Modes/Objects/LegacyHitObjectParser.cs b/osu.Game/Modes/Objects/LegacyHitObjectParser.cs index ccc5f18822..2316e5dc5d 100644 --- a/osu.Game/Modes/Objects/LegacyHitObjectParser.cs +++ b/osu.Game/Modes/Objects/LegacyHitObjectParser.cs @@ -2,12 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Game.Beatmaps.Samples; using osu.Game.Modes.Objects.Types; using System; using System.Collections.Generic; using System.Globalization; using osu.Game.Modes.Objects.Legacy; +using osu.Game.Beatmaps.Formats; +using osu.Game.Audio; namespace osu.Game.Modes.Objects { @@ -20,6 +21,10 @@ namespace osu.Game.Modes.Objects bool combo = type.HasFlag(LegacyHitObjectType.NewCombo); type &= ~LegacyHitObjectType.NewCombo; + int sampleVolume = 0; + string normalSampleBank = null; + string addSampleBank = null; + HitObject result; if ((type & LegacyHitObjectType.Circle) > 0) @@ -29,6 +34,9 @@ namespace osu.Game.Modes.Objects Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])), NewCombo = combo }; + + if (split.Length > 5) + readCustomSampleBanks(split[5], ref normalSampleBank, ref addSampleBank, ref sampleVolume); } else if ((type & LegacyHitObjectType.Slider) > 0) { @@ -84,6 +92,9 @@ namespace osu.Game.Modes.Objects Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])), NewCombo = combo }; + + if (split.Length > 10) + readCustomSampleBanks(split[10], ref normalSampleBank, ref addSampleBank, ref sampleVolume); } else if ((type & LegacyHitObjectType.Spinner) > 0) { @@ -91,10 +102,17 @@ namespace osu.Game.Modes.Objects { EndTime = Convert.ToDouble(split[5], CultureInfo.InvariantCulture) }; + + if (split.Length > 6) + readCustomSampleBanks(split[6], ref normalSampleBank, ref addSampleBank, ref sampleVolume); } else if ((type & LegacyHitObjectType.Hold) > 0) { // Note: Hold is generated by BMS converts + + // Todo: Apparently end time is determined by samples?? + // Shouldn't need implementation until mania + result = new LegacyHold { Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])), @@ -105,15 +123,82 @@ namespace osu.Game.Modes.Objects throw new InvalidOperationException($@"Unknown hit object type {type}"); result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture); - result.Sample = new HitSampleInfo - { - Type = (SampleType)int.Parse(split[4]), - Set = SampleSet.Soft, - }; - // TODO: "addition" field + var soundType = (LegacySoundType)int.Parse(split[4]); + + result.Samples.Add(new SampleInfo + { + Bank = normalSampleBank, + Name = SampleInfo.HIT_NORMAL, + Volume = sampleVolume + }); + + if ((soundType & LegacySoundType.Finish) > 0) + { + result.Samples.Add(new SampleInfo + { + Bank = addSampleBank, + Name = SampleInfo.HIT_FINISH, + Volume = sampleVolume + }); + } + + if ((soundType & LegacySoundType.Whistle) > 0) + { + result.Samples.Add(new SampleInfo + { + Bank = addSampleBank, + Name = SampleInfo.HIT_WHISTLE, + Volume = sampleVolume + }); + } + + if ((soundType & LegacySoundType.Clap) > 0) + { + result.Samples.Add(new SampleInfo + { + Bank = addSampleBank, + Name = SampleInfo.HIT_CLAP, + Volume = sampleVolume + }); + } return result; } + + private void readCustomSampleBanks(string str, ref string normalSampleBank, ref string addSampleBank, ref int sampleVolume) + { + if (string.IsNullOrEmpty(str)) + return; + + string[] split = str.Split(':'); + + var bank = (OsuLegacyDecoder.LegacySampleBank)Convert.ToInt32(split[0]); + var addbank = (OsuLegacyDecoder.LegacySampleBank)Convert.ToInt32(split[1]); + + // Let's not implement this for now, because this doesn't fit nicely into the bank structure + //string sampleFile = split2.Length > 4 ? split2[4] : string.Empty; + + string stringBank = bank.ToString().ToLower(); + if (stringBank == @"none") + stringBank = null; + string stringAddBank = addbank.ToString().ToLower(); + if (stringAddBank == @"none") + stringAddBank = null; + + normalSampleBank = stringBank; + addSampleBank = stringAddBank; + sampleVolume = split.Length > 3 ? int.Parse(split[3]) : 0; + } + + [Flags] + private enum LegacySoundType + { + None = 0, + Normal = 1, + Whistle = 2, + Finish = 4, + Clap = 8 + } } } diff --git a/osu.Game/Modes/UI/HudOverlay.cs b/osu.Game/Modes/UI/HudOverlay.cs index 45dce8b332..355b62bc57 100644 --- a/osu.Game/Modes/UI/HudOverlay.cs +++ b/osu.Game/Modes/UI/HudOverlay.cs @@ -9,11 +9,18 @@ using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play; using osu.Game.Modes.Scoring; +using osu.Framework.Input; +using OpenTK.Input; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; namespace osu.Game.Modes.UI { public abstract class HudOverlay : Container { + private const int duration = 100; + + private readonly Container content; public readonly KeyCounterCollection KeyCounter; public readonly ComboCounter ComboCounter; public readonly ScoreCounter ScoreCounter; @@ -21,6 +28,9 @@ namespace osu.Game.Modes.UI public readonly HealthDisplay HealthDisplay; private Bindable showKeyCounter; + private Bindable showHud; + + private static bool hasShownNotificationOnce; protected abstract KeyCounterCollection CreateKeyCounter(); protected abstract ComboCounter CreateComboCounter(); @@ -32,28 +42,53 @@ namespace osu.Game.Modes.UI { RelativeSizeAxes = Axes.Both; - Children = new Drawable[] + Add(content = new Container { - KeyCounter = CreateKeyCounter(), - ComboCounter = CreateComboCounter(), - ScoreCounter = CreateScoreCounter(), - AccuracyCounter = CreateAccuracyCounter(), - HealthDisplay = CreateHealthDisplay(), - }; + RelativeSizeAxes = Axes.Both, + + Children = new Drawable[] + { + KeyCounter = CreateKeyCounter(), + ComboCounter = CreateComboCounter(), + ScoreCounter = CreateScoreCounter(), + AccuracyCounter = CreateAccuracyCounter(), + HealthDisplay = CreateHealthDisplay(), + } + }); } - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + [BackgroundDependencyLoader(true)] + private void load(OsuConfigManager config, NotificationManager notificationManager) { showKeyCounter = config.GetBindable(OsuConfig.KeyOverlay); - showKeyCounter.ValueChanged += visibility => + showKeyCounter.ValueChanged += keyCounterVisibility => { - if (visibility) - KeyCounter.Show(); + if (keyCounterVisibility) + KeyCounter.FadeIn(duration); else - KeyCounter.Hide(); + KeyCounter.FadeOut(duration); }; showKeyCounter.TriggerChange(); + + showHud = config.GetBindable(OsuConfig.ShowInterface); + showHud.ValueChanged += hudVisibility => + { + if (hudVisibility) + content.FadeIn(duration); + else + content.FadeOut(duration); + }; + showHud.TriggerChange(); + + if (!showHud && !hasShownNotificationOnce) + { + hasShownNotificationOnce = true; + + notificationManager?.Post(new SimpleNotification + { + Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab." + }); + } } public void BindProcessor(ScoreProcessor processor) @@ -68,5 +103,22 @@ namespace osu.Game.Modes.UI { hitRenderer.InputManager.Add(KeyCounter.GetReceptor()); } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) return false; + + if (state.Keyboard.ShiftPressed) + { + switch (args.Key) + { + case Key.Tab: + showHud.Value = !showHud.Value; + return true; + } + } + + return base.OnKeyDown(state, args); + } } } diff --git a/osu.Game/Overlays/Options/Sections/Gameplay/GeneralOptions.cs b/osu.Game/Overlays/Options/Sections/Gameplay/GeneralOptions.cs index 70a2c52322..ee6778a47a 100644 --- a/osu.Game/Overlays/Options/Sections/Gameplay/GeneralOptions.cs +++ b/osu.Game/Overlays/Options/Sections/Gameplay/GeneralOptions.cs @@ -39,6 +39,11 @@ namespace osu.Game.Overlays.Options.Sections.Gameplay Bindable = (BindableDouble)config.GetBindable(OsuConfig.ScoreMeterScale) }, new OsuCheckbox + { + LabelText = "Show score overlay", + Bindable = config.GetBindable(OsuConfig.ShowInterface) + }, + new OsuCheckbox { LabelText = "Always show key overlay", Bindable = config.GetBindable(OsuConfig.KeyOverlay) diff --git a/osu.Game/Screens/Play/FailDialog.cs b/osu.Game/Screens/Play/FailDialog.cs deleted file mode 100644 index 4bdd9d94d3..0000000000 --- a/osu.Game/Screens/Play/FailDialog.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Screens; -using osu.Framework.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Screens.Backgrounds; -using OpenTK; -using OpenTK.Graphics; - -namespace osu.Game.Screens.Play -{ - internal class FailDialog : OsuScreen - { - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); - - private static readonly Vector2 background_blur = new Vector2(20); - - public FailDialog() - { - Add(new OsuSpriteText - { - Text = "You failed!", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - TextSize = 50 - }); - } - - protected override void OnEntering(Screen last) - { - base.OnEntering(last); - Background.Schedule(() => (Background as BackgroundScreenBeatmap)?.BlurTo(background_blur, 1000)); - } - - protected override bool OnExiting(Screen next) - { - Background.Schedule(() => Background.FadeColour(Color4.White, 500)); - return base.OnExiting(next); - } - } -} diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs new file mode 100644 index 0000000000..7a32e19338 --- /dev/null +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using OpenTK.Input; +using osu.Game.Graphics; +using OpenTK.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Screens.Play +{ + public class FailOverlay : MenuOverlay + { + + public override string Header => "failed"; + public override string Description => "you're dead, try again?"; + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Key == Key.Escape) + { + if (State == Visibility.Hidden) return false; + OnQuit(); + return true; + } + + return base.OnKeyDown(state, args); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AddButton("Retry", colours.YellowDark, OnRetry); + AddButton("Quit", new Color4(170, 27, 39, 255), OnQuit); + } + } +} diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/MenuOverlay.cs new file mode 100644 index 0000000000..ede49065a7 --- /dev/null +++ b/osu.Game/Screens/Play/MenuOverlay.cs @@ -0,0 +1,194 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using osu.Game.Graphics.Sprites; +using osu.Game.Screens.Play.Pause; +using OpenTK; +using OpenTK.Graphics; +using osu.Game.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Screens.Play +{ + public abstract class MenuOverlay : OverlayContainer + { + private const int transition_duration = 200; + private const int button_height = 70; + private const float background_alpha = 0.75f; + + protected override bool HideOnEscape => false; + + public Action OnRetry; + public Action OnQuit; + + public abstract string Header { get; } + public abstract string Description { get; } + + private FillFlowContainer buttons; + + public int Retries + { + set + { + if (retryCounterContainer != null) + { + // "You've retried 1,065 times in this session" + // "You've retried 1 time in this session" + + retryCounterContainer.Children = new Drawable[] + { + new OsuSpriteText + { + Text = "You've retried ", + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f), + TextSize = 18 + }, + new OsuSpriteText + { + Text = $"{value:n0}", + Font = @"Exo2.0-Bold", + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f), + TextSize = 18 + }, + new OsuSpriteText + { + Text = $" time{(value == 1 ? "" : "s")} in this session", + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f), + TextSize = 18 + } + }; + } + } + } + + private FillFlowContainer retryCounterContainer; + + public override bool HandleInput => State == Visibility.Visible; + + protected override void PopIn() => FadeIn(transition_duration, EasingTypes.In); + protected override void PopOut() => FadeOut(transition_duration, EasingTypes.In); + + // Don't let mouse down events through the overlay or people can click circles while paused. + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; + + protected override bool OnMouseMove(InputState state) => true; + + protected void AddButton(string text, Color4 colour, Action action) + { + buttons.Add(new PauseButton + { + Text = text, + ButtonColour = colour, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Height = button_height, + Action = delegate { + action?.Invoke(); + Hide(); + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = background_alpha, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 50), + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Children = new Drawable[] + { + new FillFlowContainer + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Children = new Drawable[] + { + new OsuSpriteText + { + Text = Header, + Font = @"Exo2.0-Medium", + Spacing = new Vector2(5, 0), + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + TextSize = 30, + Colour = colours.Yellow, + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f) + }, + new OsuSpriteText + { + Text = Description, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f) + } + } + }, + buttons = new FillFlowContainer + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Masking = true, + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.6f), + Radius = 50 + }, + }, + retryCounterContainer = new FillFlowContainer + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + } + } + }, + new PauseProgressBar + { + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + Width = 1f + } + }; + + Retries = 0; + } + + protected MenuOverlay() + { + AlwaysReceiveInput = true; + RelativeSizeAxes = Axes.Both; + } + } +} diff --git a/osu.Game/Screens/Play/Pause/QuitButton.cs b/osu.Game/Screens/Play/Pause/PauseButton.cs similarity index 63% rename from osu.Game/Screens/Play/Pause/QuitButton.cs rename to osu.Game/Screens/Play/Pause/PauseButton.cs index 7b71b4b2fc..7698913ea5 100644 --- a/osu.Game/Screens/Play/Pause/QuitButton.cs +++ b/osu.Game/Screens/Play/Pause/PauseButton.cs @@ -4,23 +4,16 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Game.Graphics.UserInterface; -using OpenTK.Graphics; namespace osu.Game.Screens.Play.Pause { - public class QuitButton : DialogButton + public class PauseButton : DialogButton { [BackgroundDependencyLoader] private void load(AudioManager audio) { - ButtonColour = new Color4(170, 27, 39, 255); // The red from the design isn't in the palette so it's used directly SampleHover = audio.Sample.Get(@"Menu/menuclick"); SampleClick = audio.Sample.Get(@"Menu/menuback"); } - - public QuitButton() - { - Text = @"Quit to Main Menu"; - } } } diff --git a/osu.Game/Screens/Play/Pause/ResumeButton.cs b/osu.Game/Screens/Play/Pause/ResumeButton.cs deleted file mode 100644 index d4f7555d3c..0000000000 --- a/osu.Game/Screens/Play/Pause/ResumeButton.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Screens.Play.Pause -{ - public class ResumeButton : DialogButton - { - [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuColour colours) - { - ButtonColour = colours.Green; - SampleHover = audio.Sample.Get(@"Menu/menuclick"); - SampleClick = audio.Sample.Get(@"Menu/menuback"); - } - - public ResumeButton() - { - Text = @"Continue"; - } - } -} diff --git a/osu.Game/Screens/Play/Pause/RetryButton.cs b/osu.Game/Screens/Play/Pause/RetryButton.cs deleted file mode 100644 index 8f660525c3..0000000000 --- a/osu.Game/Screens/Play/Pause/RetryButton.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Screens.Play.Pause -{ - public class RetryButton : DialogButton - { - [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuColour colours) - { - ButtonColour = colours.YellowDark; - SampleHover = audio.Sample.Get(@"Menu/menuclick"); - SampleClick = audio.Sample.Get(@"Menu/menu-play-click"); - } - - public RetryButton() - { - Text = @"Retry"; - } - } -} diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index ae6b12e319..f9706d263e 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -2,89 +2,28 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Screens.Play.Pause; -using OpenTK; -using OpenTK.Graphics; using OpenTK.Input; +using osu.Framework.Graphics.Containers; +using OpenTK.Graphics; +using osu.Framework.Allocation; namespace osu.Game.Screens.Play { - public class PauseOverlay : OverlayContainer + public class PauseOverlay : MenuOverlay { - private const int transition_duration = 200; - private const int button_height = 70; - private const float background_alpha = 0.75f; - - protected override bool HideOnEscape => false; - public Action OnResume; - public Action OnRetry; - public Action OnQuit; - public int Retries - { - set - { - if (retryCounterContainer != null) - { - // "You've retried 1,065 times in this session" - // "You've retried 1 time in this session" - - retryCounterContainer.Children = new Drawable[] - { - new OsuSpriteText - { - Text = "You've retried ", - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 - }, - new OsuSpriteText - { - Text = $"{value:n0}", - Font = @"Exo2.0-Bold", - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 - }, - new OsuSpriteText - { - Text = $" time{(value == 1 ? "" : "s")} in this session", - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 - } - }; - } - } - } - - private FillFlowContainer retryCounterContainer; - - public override bool HandleInput => State == Visibility.Visible; - - protected override void PopIn() => FadeIn(transition_duration, EasingTypes.In); - protected override void PopOut() => FadeOut(transition_duration, EasingTypes.In); - - // Don't let mouse down events through the overlay or people can click circles while paused. - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; - - protected override bool OnMouseMove(InputState state) => true; + public override string Header => "paused"; + public override string Description => "you're not going to do what i think you're going to do, are ya?"; protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { if (args.Key == Key.Escape) { if (State == Visibility.Hidden) return false; - resume(); + OnResume(); return true; } @@ -94,131 +33,10 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(OsuColour colours) { - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = background_alpha, - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 50), - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Children = new Drawable[] - { - new FillFlowContainer - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Children = new Drawable[] - { - new OsuSpriteText - { - Text = @"paused", - Font = @"Exo2.0-Medium", - Spacing = new Vector2(5, 0), - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - TextSize = 30, - Colour = colours.Yellow, - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f) - }, - new OsuSpriteText - { - Text = @"you're not going to do what i think you're going to do, are ya?", - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f) - } - } - }, - new FillFlowContainer - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Masking = true, - EdgeEffect = new EdgeEffect - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.6f), - Radius = 50 - }, - Children = new Drawable[] - { - new ResumeButton - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Height = button_height, - Action = resume - }, - new RetryButton - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Height = button_height, - Action = delegate - { - OnRetry?.Invoke(); - Hide(); - } - }, - new QuitButton - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Height = button_height, - Action = delegate - { - OnQuit?.Invoke(); - Hide(); - } - } - } - }, - retryCounterContainer = new FillFlowContainer - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, - } - } - }, - new PauseProgressBar - { - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - Width = 1f - } - }; - - Retries = 0; - } - - private void resume() - { - OnResume?.Invoke(); - Hide(); - } - - public PauseOverlay() - { - AlwaysReceiveInput = true; - RelativeSizeAxes = Axes.Both; + AddButton("Continue", colours.Green, OnResume); + AddButton("Retry", colours.YellowDark, OnRetry); + AddButton("Quit", new Color4(170, 27, 39, 255), OnQuit); } } } + \ No newline at end of file diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f160563c3b..d645c0c1f3 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -31,12 +30,14 @@ namespace osu.Game.Screens.Play internal override bool ShowOverlays => false; - internal override bool HasLocalCursorDisplayed => !IsPaused && HitRenderer.ProvidingUserCursor; + internal override bool HasLocalCursorDisplayed => !IsPaused && !HasFailed && HitRenderer.ProvidingUserCursor; public BeatmapInfo BeatmapInfo; public bool IsPaused { get; private set; } + public bool HasFailed { get; private set; } + public int RestartCount; private const double pause_cooldown = 1000; @@ -56,6 +57,7 @@ namespace osu.Game.Screens.Play private HudOverlay hudOverlay; private PauseOverlay pauseOverlay; + private FailOverlay failOverlay; [BackgroundDependencyLoader] private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config) @@ -116,20 +118,6 @@ namespace osu.Game.Screens.Play hudOverlay = new StandardHudOverlay(); hudOverlay.KeyCounter.Add(ruleset.CreateGameplayKeys()); hudOverlay.BindProcessor(scoreProcessor); - - pauseOverlay = new PauseOverlay - { - Depth = -1, - OnResume = delegate - { - Delay(400); - Schedule(Resume); - }, - OnRetry = Restart, - OnQuit = Exit - }; - - hudOverlay.BindHitRenderer(HitRenderer); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) @@ -154,7 +142,21 @@ namespace osu.Game.Screens.Play } }, hudOverlay, - pauseOverlay + pauseOverlay = new PauseOverlay + { + OnResume = delegate + { + Delay(400); + Schedule(Resume); + }, + OnRetry = Restart, + OnQuit = Exit, + }, + failOverlay = new FailOverlay + { + OnRetry = Restart, + OnQuit = Exit, + } }; } @@ -254,15 +256,13 @@ namespace osu.Game.Screens.Play private void onFail() { - Content.FadeColour(Color4.Red, 500); sourceClock.Stop(); Delay(500); - Schedule(delegate - { - ValidForResume = false; - Push(new FailDialog()); - }); + + HasFailed = true; + failOverlay.Retries = RestartCount; + failOverlay.Show(); } protected override void OnEntering(Screen last) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b2d8aedb7f..1577ed2229 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -71,6 +71,7 @@ + @@ -149,14 +150,7 @@ - - - - - - - @@ -199,8 +193,11 @@ - + + + + @@ -337,12 +334,8 @@ - - - -