diff --git a/osu-framework b/osu-framework index 1c08c1fec4..a7c99e06ff 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 1c08c1fec496e9d64ba8f30ff0464cd5cdf567b6 +Subproject commit a7c99e06ff4c3f56fad24bec170eb93f42b1e149 diff --git a/osu-resources b/osu-resources index 12bbab717d..0d6dc29473 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 12bbab717d372dadbd3220d38da862276ac97e98 +Subproject commit 0d6dc294738d433999c6c68ff61169d3a8e6ce5f diff --git a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs index 2cb63ba7a0..2663c952cf 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs @@ -3,15 +3,12 @@ using osu.Framework.Testing; using osu.Framework.Graphics.Containers; -using osu.Framework.Threading; using osu.Game.Overlays; namespace osu.Desktop.VisualTests.Tests { internal class TestCaseChatDisplay : TestCase { - private ScheduledDelegate messageRequest; - public override string Description => @"Testing chat api and overlay"; public override void Reset() diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index cb7a3e3f84..99da7d1c73 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -112,7 +112,7 @@ namespace osu.Desktop.VisualTests.Tests Width = 150, Height = 10, SelectionColor = Color4.Orange, - Bindable = playbackSpeed + Value = playbackSpeed } } }); 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/TestCaseKeyCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs index 3dba201f5d..7e7782662b 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs @@ -57,7 +57,7 @@ namespace osu.Desktop.VisualTests.Tests Width = 150, Height = 10, SelectionColor = Color4.Orange, - Bindable = bindable + Value = bindable } } }); 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/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index aedab7e895..1a43425dda 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -14,7 +14,7 @@ namespace osu.Desktop.VisualTests.Tests { internal class TestCasePlaySongSelect : TestCase { - private BeatmapDatabase db, oldDb; + private BeatmapDatabase db; private TestStorage storage; private PlaySongSelect songSelect; @@ -44,13 +44,13 @@ namespace osu.Desktop.VisualTests.Tests AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; }); } - protected override void Dispose(bool isDisposing) - { - if (oldDb != null) - db = null; + //protected override void Dispose(bool isDisposing) + //{ + // if (oldDb != null) + // db = null; - base.Dispose(isDisposing); - } + // base.Dispose(isDisposing); + //} private BeatmapSetInfo createTestBeatmapSet(int i) { diff --git a/osu.Desktop.VisualTests/Tests/TestCaseReplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseReplay.cs index c36fc0a47d..ffdca25bb3 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseReplay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseReplay.cs @@ -1,24 +1,15 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Input.Handlers; using osu.Game.Beatmaps; using osu.Game.Modes.Mods; using osu.Game.Modes.Osu.Mods; using osu.Game.Screens.Play; -using System; -using System.IO; namespace osu.Desktop.VisualTests.Tests { internal class TestCaseReplay : TestCasePlayer { - private WorkingBeatmap beatmap; - - private InputHandler replay; - - private Func getReplayStream; - public override string Description => @"Testing replay playback."; protected override Player CreatePlayer(WorkingBeatmap beatmap) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs index 55fc969217..f3cca16678 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs @@ -22,8 +22,6 @@ namespace osu.Desktop.VisualTests.Tests int numerator = 0, denominator = 0; - bool maniaHold = false; - ScoreCounter score = new ScoreCounter(7) { Origin = Anchor.TopRight, diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs b/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs index 23e7f8a74d..2d3969b822 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs @@ -36,9 +36,9 @@ namespace osu.Desktop.VisualTests.Tests filter.PinItem(GroupMode.All); filter.PinItem(GroupMode.RecentlyPlayed); - filter.ItemChanged += (sender, mode) => + filter.SelectedItem.ValueChanged += newFilter => { - text.Text = "Currently Selected: " + mode.ToString(); + text.Text = "Currently Selected: " + newFilter.ToString(); }; } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index 7aeb75ef8d..b3cb8c3457 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -6,7 +6,7 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; namespace osu.Desktop.VisualTests.Tests { @@ -29,7 +29,6 @@ namespace osu.Desktop.VisualTests.Tests Add(new CirclePiece { Position = new Vector2(100, 100), - Width = 0, AccentColour = Color4.DarkRed, KiaiMode = kiai, Children = new[] @@ -38,10 +37,9 @@ namespace osu.Desktop.VisualTests.Tests } }); - Add(new StrongCirclePiece + Add(new CirclePiece(true) { Position = new Vector2(350, 100), - Width = 0, AccentColour = Color4.DarkRed, KiaiMode = kiai, Children = new[] @@ -53,7 +51,6 @@ namespace osu.Desktop.VisualTests.Tests Add(new CirclePiece { Position = new Vector2(100, 300), - Width = 0, AccentColour = Color4.DarkBlue, KiaiMode = kiai, Children = new[] @@ -62,10 +59,9 @@ namespace osu.Desktop.VisualTests.Tests } }); - Add(new StrongCirclePiece + Add(new CirclePiece(true) { Position = new Vector2(350, 300), - Width = 0, AccentColour = Color4.DarkBlue, KiaiMode = kiai, Children = new[] @@ -77,7 +73,6 @@ namespace osu.Desktop.VisualTests.Tests Add(new CirclePiece { Position = new Vector2(100, 500), - Width = 0, AccentColour = Color4.Orange, KiaiMode = kiai, Children = new[] @@ -86,20 +81,22 @@ namespace osu.Desktop.VisualTests.Tests } }); - Add(new CirclePiece + Add(new ElongatedCirclePiece { Position = new Vector2(575, 100), - Width = 0.25f, AccentColour = Color4.Orange, KiaiMode = kiai, + Length = 0.10f, + PlayfieldLengthReference = () => DrawSize.X }); - Add(new StrongCirclePiece + Add(new ElongatedCirclePiece(true) { Position = new Vector2(575, 300), - Width = 0.25f, AccentColour = Color4.Orange, - KiaiMode = kiai + KiaiMode = kiai, + Length = 0.10f, + PlayfieldLengthReference = () => DrawSize.X }); } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs index ecd6fe813e..d0a35b7b3e 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs @@ -5,10 +5,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using osu.Framework.Testing; +using osu.Framework.Timing; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.Taiko.Objects.Drawable; +using osu.Game.Modes.Taiko.Objects.Drawables; using osu.Game.Modes.Taiko.UI; namespace osu.Desktop.VisualTests.Tests @@ -19,6 +20,12 @@ namespace osu.Desktop.VisualTests.Tests private TaikoPlayfield playfield; + protected override double TimePerAction => default_duration * 2; + + private const double default_duration = 300; + + private const float scroll_time = 1000; + public override void Reset() { base.Reset(); @@ -27,14 +34,20 @@ namespace osu.Desktop.VisualTests.Tests AddStep("Miss :(", addMissJudgement); AddStep("DrumRoll", () => addDrumRoll(false)); AddStep("Strong DrumRoll", () => addDrumRoll(true)); - AddStep("Swell", addSwell); + AddStep("Swell", () => addSwell()); AddStep("Centre", () => addCentreHit(false)); AddStep("Strong Centre", () => addCentreHit(true)); AddStep("Rim", () => addRimHit(false)); AddStep("Strong Rim", () => addRimHit(true)); + AddStep("Add bar line", () => addBarLine(false)); + AddStep("Add major bar line", () => addBarLine(true)); + + + var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; Add(new Container { + Clock = new FramedClock(rateAdjustClock), RelativeSizeAxes = Axes.X, Y = 200, Children = new[] @@ -73,38 +86,53 @@ namespace osu.Desktop.VisualTests.Tests }); } - private void addSwell() + private void addBarLine(bool major, double delay = scroll_time) + { + BarLine bl = new BarLine + { + StartTime = playfield.Time.Current + delay, + ScrollTime = scroll_time + }; + + playfield.AddBarLine(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl)); + } + + private void addSwell(double duration = default_duration) { playfield.Add(new DrawableSwell(new Swell { - StartTime = Time.Current + 1000, - EndTime = Time.Current + 5000, - PreEmpt = 1000 + StartTime = playfield.Time.Current + scroll_time, + Duration = duration, + ScrollTime = scroll_time })); } - private void addDrumRoll(bool strong) + private void addDrumRoll(bool strong, double duration = default_duration) { + addBarLine(true); + addBarLine(true, scroll_time + duration); + var d = new DrumRoll { - StartTime = Time.Current + 1000, - Distance = 20000, - PreEmpt = 1000, + StartTime = playfield.Time.Current + scroll_time, + IsStrong = strong, + Duration = duration, + ScrollTime = scroll_time, }; - playfield.Add(strong ? new DrawableStrongDrumRoll(d) : new DrawableDrumRoll(d)); + playfield.Add(new DrawableDrumRoll(d)); } private void addCentreHit(bool strong) { Hit h = new Hit { - StartTime = Time.Current + 1000, - PreEmpt = 1000 + StartTime = playfield.Time.Current + scroll_time, + ScrollTime = scroll_time }; if (strong) - playfield.Add(new DrawableStrongCentreHit(h)); + playfield.Add(new DrawableCentreHitStrong(h)); else playfield.Add(new DrawableCentreHit(h)); } @@ -113,12 +141,12 @@ namespace osu.Desktop.VisualTests.Tests { Hit h = new Hit { - StartTime = Time.Current + 1000, - PreEmpt = 1000 + StartTime = playfield.Time.Current + scroll_time, + ScrollTime = scroll_time }; if (strong) - playfield.Add(new DrawableStrongRimHit(h)); + playfield.Add(new DrawableRimHitStrong(h)); else playfield.Add(new DrawableRimHit(h)); } 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/UI/OsuPlayfield.cs b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs index 8090263fe1..d89bbfd131 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs @@ -21,6 +21,8 @@ namespace osu.Game.Modes.Osu.UI private readonly Container judgementLayer; private readonly ConnectionRenderer connectionLayer; + public override bool ProvidingUserCursor => true; + public override Vector2 Size { get diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index d978774666..c4018b5aa3 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -8,6 +8,8 @@ using osu.Game.Modes.Taiko.Objects; using System; using System.Collections.Generic; using System.Linq; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Beatmaps.Timing; using osu.Game.Database; using osu.Game.Audio; @@ -41,6 +43,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps { return new Beatmap(original) { + TimingInfo = original is LegacyBeatmap ? new LegacyTimingInfo(original.TimingInfo) : original.TimingInfo, HitObjects = original.HitObjects.SelectMany(h => convertHitObject(h, original)).ToList() }; } @@ -100,7 +103,6 @@ namespace osu.Game.Modes.Taiko.Beatmaps StartTime = j, Samples = obj.Samples, IsStrong = strong, - VelocityMultiplier = legacy_velocity_multiplier }; } } @@ -111,9 +113,8 @@ namespace osu.Game.Modes.Taiko.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, IsStrong = strong, - Distance = distance, + Duration = taikoDuration, TickRate = beatmap.BeatmapInfo.Difficulty.SliderTickRate == 3 ? 3 : 4, - VelocityMultiplier = legacy_velocity_multiplier }; } } @@ -126,9 +127,8 @@ namespace osu.Game.Modes.Taiko.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, IsStrong = strong, - EndTime = endTimeData.EndTime, + Duration = endTimeData.Duration, RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier), - VelocityMultiplier = legacy_velocity_multiplier }; } else @@ -142,7 +142,6 @@ namespace osu.Game.Modes.Taiko.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, IsStrong = strong, - VelocityMultiplier = legacy_velocity_multiplier }; } else @@ -152,10 +151,25 @@ namespace osu.Game.Modes.Taiko.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, IsStrong = strong, - VelocityMultiplier = legacy_velocity_multiplier }; } } } + + private class LegacyTimingInfo : TimingInfo + { + public LegacyTimingInfo(TimingInfo original) + { + if (original is LegacyTimingInfo) + ControlPoints.AddRange(original.ControlPoints); + else + { + ControlPoints.AddRange(original.ControlPoints.Select(c => c.Clone())); + + foreach (var c in ControlPoints) + c.SpeedMultiplier *= legacy_velocity_multiplier; + } + } + } } } diff --git a/osu.Game.Modes.Taiko/Objects/BarLine.cs b/osu.Game.Modes.Taiko/Objects/BarLine.cs new file mode 100644 index 0000000000..ae3c03de5e --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/BarLine.cs @@ -0,0 +1,9 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Modes.Taiko.Objects +{ + public class BarLine : TaikoHitObject + { + } +} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs deleted file mode 100644 index b7509bc51d..0000000000 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using OpenTK.Input; -using osu.Game.Modes.Taiko.Judgements; -using System; -using osu.Game.Modes.Objects.Drawables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using OpenTK; -using OpenTK.Graphics; -using osu.Framework.Graphics.Sprites; - -namespace osu.Game.Modes.Taiko.Objects.Drawable -{ - public class DrawableDrumRollTick : DrawableTaikoHitObject - { - /// - /// The size of a tick. - /// - private const float tick_size = TaikoHitObject.CIRCLE_RADIUS / 2; - - /// - /// Any tick that is not the first for a drumroll is not filled, but is instead displayed - /// as a hollow circle. This is what controls the border width of that circle. - /// - private const float tick_border_width = tick_size / 4; - - private readonly DrumRollTick tick; - - private readonly CircularContainer bodyContainer; - - public DrawableDrumRollTick(DrumRollTick tick) - : base(tick) - { - this.tick = tick; - - Anchor = Anchor.CentreLeft; - Origin = Anchor.Centre; - - RelativePositionAxes = Axes.X; - Size = new Vector2(tick_size); - - Children = new[] - { - bodyContainer = new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = tick_border_width, - BorderColour = Color4.White, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = tick.FirstTick ? 1 : 0, - AlwaysPresent = true - } - } - } - }; - } - - protected override TaikoJudgement CreateJudgement() => new TaikoDrumRollTickJudgement { SecondHit = tick.IsStrong }; - - protected override void CheckJudgement(bool userTriggered) - { - if (!userTriggered) - { - if (Judgement.TimeOffset > tick.HitWindow) - Judgement.Result = HitResult.Miss; - return; - } - - if (Math.Abs(Judgement.TimeOffset) < tick.HitWindow) - { - Judgement.Result = HitResult.Hit; - Judgement.TaikoResult = TaikoHitResult.Great; - } - } - - protected override void UpdateState(ArmedState state) - { - switch (state) - { - case ArmedState.Hit: - bodyContainer.ScaleTo(0, 100, EasingTypes.OutQuint); - break; - } - } - - protected override void UpdateScrollPosition(double time) - { - // Ticks don't move - } - - protected override bool HandleKeyPress(Key key) - { - return Judgement.Result == HitResult.None && UpdateJudgement(true); - } - } -} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongDrumRoll.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongDrumRoll.cs deleted file mode 100644 index e9723a0162..0000000000 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongDrumRoll.cs +++ /dev/null @@ -1,20 +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.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; - -namespace osu.Game.Modes.Taiko.Objects.Drawable -{ - public class DrawableStrongDrumRoll : DrawableDrumRoll - { - public DrawableStrongDrumRoll(DrumRoll drumRoll) - : base(drumRoll) - { - } - - protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = true }; - - protected override CirclePiece CreateCirclePiece() => new StrongCirclePiece(); - } -} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs deleted file mode 100644 index d51c06bcad..0000000000 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs +++ /dev/null @@ -1,158 +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.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics.Backgrounds; -using OpenTK.Graphics; -using System; -using osu.Game.Graphics; - -namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces -{ - /// - /// A circle piece which is used uniformly through osu!taiko to visualise hitobjects. - /// - /// The body of this piece will overshoot its parent by to form - /// a rounded (_[-Width-]_) figure such that a regular "circle" is the result of a parent with Width = 0. - /// - /// - public class CirclePiece : Container, IHasAccentColour - { - public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f; - public const float SYMBOL_BORDER = 8; - public const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER; - - private Color4 accentColour; - /// - /// The colour of the inner circle and outer glows. - /// - public Color4 AccentColour - { - get { return accentColour; } - set - { - accentColour = value; - - background.Colour = AccentColour; - - resetEdgeEffects(); - } - } - - private bool kiaiMode; - /// - /// Whether Kiai mode effects are enabled for this circle piece. - /// - public bool KiaiMode - { - get { return kiaiMode; } - set - { - kiaiMode = value; - - resetEdgeEffects(); - } - } - - public override Anchor Origin - { - get { return Anchor.CentreLeft; } - set { throw new InvalidOperationException($"{nameof(CirclePiece)} must always use CentreLeft origin."); } - } - - protected override Container Content => SymbolContainer; - protected readonly Container SymbolContainer; - - private readonly Container background; - private readonly Container innerLayer; - - public CirclePiece() - { - RelativeSizeAxes = Axes.X; - Height = TaikoHitObject.CIRCLE_RADIUS * 2; - - // The "inner layer" is the body of the CirclePiece that overshoots it by Height/2 px on both sides - AddInternal(innerLayer = new Container - { - Name = "Inner Layer", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Children = new Framework.Graphics.Drawable[] - { - background = new CircularContainer - { - Name = "Background", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Framework.Graphics.Drawable[] - { - new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - }, - new Triangles - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - ColourLight = Color4.White, - ColourDark = Color4.White.Darken(0.1f) - } - } - }, - new CircularContainer - { - Name = "Ring", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - BorderThickness = 8, - BorderColour = Color4.White, - Masking = true, - Children = new[] - { - new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - } - }, - SymbolContainer = new Container - { - Name = "Symbol", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - } - }); - } - - protected override void Update() - { - // Add the overshoot to compensate for corner radius - innerLayer.Width = DrawWidth + DrawHeight; - } - - private void resetEdgeEffects() - { - background.EdgeEffect = new EdgeEffect - { - Type = EdgeEffectType.Glow, - Colour = AccentColour, - Radius = KiaiMode ? 50 : 8 - }; - } - } -} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/StrongCirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/StrongCirclePiece.cs deleted file mode 100644 index 319ca17cb8..0000000000 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/StrongCirclePiece.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using OpenTK; - -namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces -{ - /// - /// A type of circle piece which is drawn at a higher scale to represent a "strong" piece. - /// - public class StrongCirclePiece : CirclePiece - { - /// - /// The amount to scale up the base circle to show it as a "strong" piece. - /// - private const float strong_scale = 1.5f; - - public StrongCirclePiece() - { - SymbolContainer.Scale = new Vector2(strong_scale); - } - - public override Vector2 Size => new Vector2(base.Size.X, base.Size.Y * strong_scale); - } -} diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLine.cs new file mode 100644 index 0000000000..59f8aca867 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -0,0 +1,80 @@ +// Copyright (c) 2007-2017 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.Sprites; +using OpenTK; + +namespace osu.Game.Modes.Taiko.Objects.Drawables +{ + /// + /// A line that scrolls alongside hit objects in the playfield and visualises control points. + /// + public class DrawableBarLine : Container + { + /// + /// The width of the line tracker. + /// + private const float tracker_width = 2f; + + /// + /// Fade out time calibrated to a pre-empt of 1000ms. + /// + private const float base_fadeout_time = 100f; + + /// + /// The visual line tracker. + /// + protected Box Tracker; + + /// + /// The bar line. + /// + protected readonly BarLine BarLine; + + public DrawableBarLine(BarLine barLine) + { + BarLine = barLine; + + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + + RelativePositionAxes = Axes.X; + RelativeSizeAxes = Axes.Y; + + Width = tracker_width; + + Children = new[] + { + Tracker = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + EdgeSmoothness = new Vector2(0.5f, 0), + Alpha = 0.75f + } + }; + + LifetimeStart = BarLine.StartTime - BarLine.ScrollTime * 2; + LifetimeEnd = BarLine.StartTime + BarLine.ScrollTime; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Delay(BarLine.StartTime - Time.Current); + FadeOut(base_fadeout_time * BarLine.ScrollTime / 1000); + } + + private void updateScrollPosition(double time) => MoveToX((float)((BarLine.StartTime - time) / BarLine.ScrollTime)); + + protected override void Update() + { + base.Update(); + + updateScrollPosition(Time.Current); + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLineMajor.cs new file mode 100644 index 0000000000..73565e6948 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -0,0 +1,57 @@ +// Copyright (c) 2007-2017 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.Sprites; +using OpenTK; + +namespace osu.Game.Modes.Taiko.Objects.Drawables +{ + public class DrawableBarLineMajor : DrawableBarLine + { + /// + /// The vertical offset of the triangles from the line tracker. + /// + private const float triangle_offfset = 10f; + + /// + /// The size of the triangles. + /// + private const float triangle_size = 20f; + + public DrawableBarLineMajor(BarLine barLine) + : base(barLine) + { + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Children = new[] + { + new EquilateralTriangle + { + Name = "Top", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Position = new Vector2(0, -triangle_offfset), + Size = new Vector2(-triangle_size), + EdgeSmoothness = new Vector2(1), + }, + new EquilateralTriangle + { + Name = "Bottom", + Anchor = Anchor.BottomCentre, + Origin = Anchor.TopCentre, + Position = new Vector2(0, triangle_offfset), + Size = new Vector2(triangle_size), + EdgeSmoothness = new Vector2(1), + } + } + }); + + Tracker.Alpha = 1f; + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHit.cs similarity index 61% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHit.cs index 76eb6bb77d..ff5ac859b4 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHit.cs @@ -1,12 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; -using osu.Game.Graphics; using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { public class DrawableCentreHit : DrawableHit { @@ -15,17 +15,13 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable public DrawableCentreHit(Hit hit) : base(hit) { + MainPiece.Add(new CentreHitSymbolPiece()); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - Circle.AccentColour = colours.PinkDarker; + MainPiece.AccentColour = colours.PinkDarker; } - - protected override CirclePiece CreateCirclePiece() => new CirclePiece - { - Children = new[] { new CentreHitSymbolPiece() } - }; } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs similarity index 50% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs index bac44f48fb..bc24e2aa65 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs @@ -1,31 +1,27 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; using osu.Framework.Allocation; using osu.Game.Graphics; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { - public class DrawableStrongCentreHit : DrawableStrongHit + public class DrawableCentreHitStrong : DrawableHitStrong { protected override Key[] HitKeys { get; } = { Key.F, Key.J }; - public DrawableStrongCentreHit(Hit hit) + public DrawableCentreHitStrong(Hit hit) : base(hit) { + MainPiece.Add(new CentreHitSymbolPiece()); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - Circle.AccentColour = colours.PinkDarker; + MainPiece.AccentColour = colours.PinkDarker; } - - protected override CirclePiece CreateCirclePiece() => new StrongCirclePiece - { - Children = new[] { new CentreHitSymbolPiece() } - }; } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRoll.cs similarity index 71% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRoll.cs index ea6b0043d7..0a0098dd34 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,30 +1,25 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; +using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; -using System.Linq; +using OpenTK; +using OpenTK.Graphics; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { - public class DrawableDrumRoll : DrawableTaikoHitObject + public class DrawableDrumRoll : DrawableTaikoHitObject { /// /// Number of rolling hits required to reach the dark/final accent colour. /// private const int rolling_hits_for_dark_accent = 5; - private readonly DrumRoll drumRoll; - - private readonly CirclePiece circle; - private Color4 accentDarkColour; /// @@ -35,32 +30,32 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable public DrawableDrumRoll(DrumRoll drumRoll) : base(drumRoll) { - this.drumRoll = drumRoll; - - RelativeSizeAxes = Axes.X; - Width = (float)(drumRoll.Duration / drumRoll.PreEmpt); - - Add(circle = CreateCirclePiece()); - circle.KiaiMode = HitObject.Kiai; - foreach (var tick in drumRoll.Ticks) { var newTick = new DrawableDrumRollTick(tick) { - X = (float)((tick.StartTime - HitObject.StartTime) / drumRoll.Duration) + X = (float)((tick.StartTime - HitObject.StartTime) / HitObject.Duration) }; newTick.OnJudgement += onTickJudgement; AddNested(newTick); - Add(newTick); + MainPiece.Add(newTick); } } + protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong }; + + protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(HitObject.IsStrong) + { + Length = (float)(HitObject.Duration / HitObject.ScrollTime), + PlayfieldLengthReference = () => Parent.DrawSize.X + }; + [BackgroundDependencyLoader] private void load(OsuColour colours) { - circle.AccentColour = AccentColour = colours.YellowDark; + MainPiece.AccentColour = AccentColour = colours.YellowDark; accentDarkColour = colours.YellowDarker; } @@ -72,7 +67,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable // is further than mid point of the play field, so the time taken to scroll in should always // be greater than the time taken to scroll out to the left of the screen. // Thus, using PreEmpt here is enough for the drum roll to completely scroll out. - LifetimeEnd = drumRoll.EndTime + drumRoll.PreEmpt; + LifetimeEnd = HitObject.EndTime + HitObject.ScrollTime; } private void onTickJudgement(DrawableHitObject obj) @@ -85,7 +80,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_dark_accent); Color4 newAccent = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_dark_accent, AccentColour, accentDarkColour, 0, 1); - circle.FadeAccent(newAccent, 100); + MainPiece.FadeAccent(newAccent, 100); } protected override void CheckJudgement(bool userTriggered) @@ -98,10 +93,10 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable int countHit = NestedHitObjects.Count(o => o.Judgement.Result == HitResult.Hit); - if (countHit > drumRoll.RequiredGoodHits) + if (countHit > HitObject.RequiredGoodHits) { Judgement.Result = HitResult.Hit; - Judgement.TaikoResult = countHit >= drumRoll.RequiredGreatHits ? TaikoHitResult.Great : TaikoHitResult.Good; + Judgement.TaikoResult = countHit >= HitObject.RequiredGreatHits ? TaikoHitResult.Great : TaikoHitResult.Good; } else Judgement.Result = HitResult.Miss; @@ -110,7 +105,5 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void UpdateState(ArmedState state) { } - - protected virtual CirclePiece CreateCirclePiece() => new CirclePiece(); } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRollTick.cs new file mode 100644 index 0000000000..296affedaf --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -0,0 +1,63 @@ +// 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.Graphics; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Taiko.Judgements; +using OpenTK.Input; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; + +namespace osu.Game.Modes.Taiko.Objects.Drawables +{ + public class DrawableDrumRollTick : DrawableTaikoHitObject + { + public DrawableDrumRollTick(DrumRollTick tick) + : base(tick) + { + } + + protected override TaikoPiece CreateMainPiece() => new TickPiece + { + Filled = HitObject.FirstTick + }; + + protected override TaikoJudgement CreateJudgement() => new TaikoDrumRollTickJudgement { SecondHit = HitObject.IsStrong }; + + protected override void CheckJudgement(bool userTriggered) + { + if (!userTriggered) + { + if (Judgement.TimeOffset > HitObject.HitWindow) + Judgement.Result = HitResult.Miss; + return; + } + + if (Math.Abs(Judgement.TimeOffset) < HitObject.HitWindow) + { + Judgement.Result = HitResult.Hit; + Judgement.TaikoResult = TaikoHitResult.Great; + } + } + + protected override void UpdateState(ArmedState state) + { + switch (state) + { + case ArmedState.Hit: + Content.ScaleTo(0, 100, EasingTypes.OutQuint); + break; + } + } + + protected override void UpdateScrollPosition(double time) + { + // Ticks don't move + } + + protected override bool HandleKeyPress(Key key) + { + return Judgement.Result == HitResult.None && UpdateJudgement(true); + } + } +} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableHit.cs similarity index 56% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableHit.cs index 87f0e76f60..f325026be9 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableHit.cs @@ -1,32 +1,22 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; using System; using System.Linq; +using osu.Framework.Graphics; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Taiko.Judgements; +using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { - public abstract class DrawableHit : DrawableTaikoHitObject + public abstract class DrawableHit : DrawableTaikoHitObject { /// /// A list of keys which can result in hits for this HitObject. /// protected abstract Key[] HitKeys { get; } - protected override Container Content => bodyContainer; - - protected readonly CirclePiece Circle; - - private readonly Hit hit; - - private readonly Container bodyContainer; - /// /// Whether the last key pressed is a valid hit key. /// @@ -35,41 +25,28 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected DrawableHit(Hit hit) : base(hit) { - this.hit = hit; - - AddInternal(bodyContainer = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new[] - { - Circle = CreateCirclePiece() - } - }); - - Circle.KiaiMode = HitObject.Kiai; } protected override void CheckJudgement(bool userTriggered) { if (!userTriggered) { - if (Judgement.TimeOffset > hit.HitWindowGood) + if (Judgement.TimeOffset > HitObject.HitWindowGood) Judgement.Result = HitResult.Miss; return; } double hitOffset = Math.Abs(Judgement.TimeOffset); - if (hitOffset > hit.HitWindowMiss) + if (hitOffset > HitObject.HitWindowMiss) return; if (!validKeyPressed) Judgement.Result = HitResult.Miss; - else if (hitOffset < hit.HitWindowGood) + else if (hitOffset < HitObject.HitWindowGood) { Judgement.Result = HitResult.Hit; - Judgement.TaikoResult = hitOffset < hit.HitWindowGreat ? TaikoHitResult.Great : TaikoHitResult.Good; + Judgement.TaikoResult = hitOffset < HitObject.HitWindowGreat ? TaikoHitResult.Great : TaikoHitResult.Good; } else Judgement.Result = HitResult.Miss; @@ -92,24 +69,26 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable switch (State) { case ArmedState.Idle: - Delay(hit.HitWindowMiss); + Delay(HitObject.HitWindowMiss); break; case ArmedState.Miss: FadeOut(100); break; case ArmedState.Hit: - bodyContainer.ScaleTo(0.8f, 400, EasingTypes.OutQuad); - bodyContainer.MoveToY(-200, 250, EasingTypes.Out); - bodyContainer.Delay(250); - bodyContainer.MoveToY(0, 500, EasingTypes.In); - FadeOut(600); + + const float gravity_time = 300; + const float gravity_travel_height = 200; + + Content.ScaleTo(0.8f, gravity_time * 2, EasingTypes.OutQuad); + + MoveToY(-gravity_travel_height, gravity_time, EasingTypes.Out); + Delay(gravity_time, true); + MoveToY(gravity_travel_height * 2, gravity_time * 2, EasingTypes.In); break; } Expire(); } - - protected abstract CirclePiece CreateCirclePiece(); } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableHitStrong.cs similarity index 87% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableHitStrong.cs index a6cb6ae7fa..4ab029acb3 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableHitStrong.cs @@ -1,16 +1,17 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; using System; using System.Linq; using osu.Framework.Input; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; +using OpenTK.Input; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { - public abstract class DrawableStrongHit : DrawableHit + public abstract class DrawableHitStrong : DrawableHit { /// /// The lenience for the second key press. @@ -22,11 +23,13 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private bool firstKeyHeld; private Key firstHitKey; - protected DrawableStrongHit(Hit hit) + protected DrawableHitStrong(Hit hit) : base(hit) { } + protected override TaikoPiece CreateMainPiece() => new CirclePiece(true); + protected override TaikoJudgement CreateJudgement() => new TaikoStrongHitJudgement(); protected override void CheckJudgement(bool userTriggered) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHit.cs similarity index 61% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHit.cs index 893a6fbb4d..5a311d51ef 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHit.cs @@ -3,10 +3,10 @@ using osu.Framework.Allocation; using osu.Game.Graphics; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; using OpenTK.Input; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { public class DrawableRimHit : DrawableHit { @@ -15,17 +15,13 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable public DrawableRimHit(Hit hit) : base(hit) { + MainPiece.Add(new RimHitSymbolPiece()); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - Circle.AccentColour = colours.BlueDarker; + MainPiece.AccentColour = colours.BlueDarker; } - - protected override CirclePiece CreateCirclePiece() => new CirclePiece - { - Children = new[] { new RimHitSymbolPiece() } - }; } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHitStrong.cs similarity index 50% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHitStrong.cs index 985ba1c2df..5789dfb140 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHitStrong.cs @@ -3,29 +3,25 @@ using osu.Framework.Allocation; using osu.Game.Graphics; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; using OpenTK.Input; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { - public class DrawableStrongRimHit : DrawableStrongHit + public class DrawableRimHitStrong : DrawableHitStrong { protected override Key[] HitKeys { get; } = { Key.D, Key.K }; - public DrawableStrongRimHit(Hit hit) + public DrawableRimHitStrong(Hit hit) : base(hit) { + MainPiece.Add(new RimHitSymbolPiece()); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - Circle.AccentColour = colours.BlueDarker; + MainPiece.AccentColour = colours.BlueDarker; } - - protected override CirclePiece CreateCirclePiece() => new StrongCirclePiece - { - Children = new[] { new RimHitSymbolPiece() } - }; } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableSwell.cs similarity index 88% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableSwell.cs index ec1ab42bfc..e1a590a025 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableSwell.cs @@ -1,9 +1,8 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Input; +using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -12,13 +11,14 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; -using System; -using System.Linq; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { - public class DrawableSwell : DrawableTaikoHitObject + public class DrawableSwell : DrawableTaikoHitObject { /// /// Invoked when the swell has reached the hit target, i.e. when CurrentTime >= StartTime. @@ -31,8 +31,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private const float target_ring_scale = 5f; private const float inner_ring_alpha = 0.65f; - private readonly Swell swell; - private readonly Container bodyContainer; private readonly CircularContainer targetRing; private readonly CircularContainer expandingRing; @@ -54,13 +52,12 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable public DrawableSwell(Swell swell) : base(swell) { - this.swell = swell; - - Children = new Framework.Graphics.Drawable[] + Children = new Drawable[] { bodyContainer = new Container { - Children = new Framework.Graphics.Drawable[] + AutoSizeAxes = Axes.Both, + Children = new Drawable[] { expandingRing = new CircularContainer { @@ -89,7 +86,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable Masking = true, BorderThickness = target_ring_thick_border, BlendingMode = BlendingMode.Additive, - Children = new Framework.Graphics.Drawable[] + Children = new Drawable[] { new Box { @@ -120,6 +117,8 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable }, circlePiece = new CirclePiece { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Children = new [] { symbol = new SwellSymbolPiece() @@ -146,18 +145,18 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { userHits++; - var completion = (float)userHits / swell.RequiredHits; + var completion = (float)userHits / HitObject.RequiredHits; expandingRing.FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50); expandingRing.Delay(50); expandingRing.FadeTo(completion / 8, 2000, EasingTypes.OutQuint); expandingRing.DelayReset(); - symbol.RotateTo((float)(completion * swell.Duration / 8), 4000, EasingTypes.OutQuint); + symbol.RotateTo((float)(completion * HitObject.Duration / 8), 4000, EasingTypes.OutQuint); expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, EasingTypes.OutQuint); - if (userHits == swell.RequiredHits) + if (userHits == HitObject.RequiredHits) { Judgement.Result = HitResult.Hit; Judgement.TaikoResult = TaikoHitResult.Great; @@ -169,7 +168,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable return; //TODO: THIS IS SHIT AND CAN'T EXIST POST-TAIKO WORLD CUP - if (userHits > swell.RequiredHits / 2) + if (userHits > HitObject.RequiredHits / 2) { Judgement.Result = HitResult.Hit; Judgement.TaikoResult = TaikoHitResult.Good; @@ -189,7 +188,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable Delay(preempt, true); - Delay(Judgement.TimeOffset + swell.Duration, true); + Delay(Judgement.TimeOffset + HitObject.Duration, true); const float out_transition_time = 300; diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs similarity index 55% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 8da05d8bed..f15f2bd152 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -1,16 +1,20 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; +using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; -using System.Collections.Generic; -using osu.Framework.Input; +using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using OpenTK; +using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawable +namespace osu.Game.Modes.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : DrawableHitObject + public abstract class DrawableTaikoHitObject : DrawableHitObject + where TaikoHitType : TaikoHitObject { /// /// A list of keys which this hit object will accept. These are the standard Taiko keys for now. @@ -18,33 +22,52 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// private readonly List validKeys = new List(new[] { Key.D, Key.F, Key.J, Key.K }); - protected DrawableTaikoHitObject(TaikoHitObject hitObject) + public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); + + protected override Container Content => bodyContainer; + + protected readonly TaikoPiece MainPiece; + + private readonly Container bodyContainer; + + public new TaikoHitType HitObject; + + protected DrawableTaikoHitObject(TaikoHitType hitObject) : base(hitObject) { + HitObject = hitObject; + Anchor = Anchor.CentreLeft; - Origin = Anchor.CentreLeft; + Origin = Anchor.Custom; + + AutoSizeAxes = Axes.Both; RelativePositionAxes = Axes.X; - } - protected override void LoadComplete() - { - LifetimeStart = HitObject.StartTime - HitObject.PreEmpt * 2; + AddInternal(bodyContainer = new Container + { + AutoSizeAxes = Axes.Both, + Children = new[] + { + MainPiece = CreateMainPiece() + } + }); - base.LoadComplete(); + MainPiece.KiaiMode = HitObject.Kiai; + + LifetimeStart = HitObject.StartTime - HitObject.ScrollTime * 2; } protected override TaikoJudgement CreateJudgement() => new TaikoJudgement(); + protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(HitObject.IsStrong); + /// /// Sets the scroll position of the DrawableHitObject relative to the offset between /// a time value and the HitObject's StartTime. /// /// - protected virtual void UpdateScrollPosition(double time) - { - MoveToX((float)((HitObject.StartTime - time) / HitObject.PreEmpt)); - } + protected virtual void UpdateScrollPosition(double time) => X = (float)((HitObject.StartTime - time) / HitObject.ScrollTime); protected override void Update() { diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CentreHitSymbolPiece.cs b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs similarity index 90% rename from osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CentreHitSymbolPiece.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs index e62ca6b073..0cf4e97b41 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CentreHitSymbolPiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs @@ -1,12 +1,12 @@ // 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.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using OpenTK; -namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces +namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces { /// /// The symbol used for centre hit pieces. diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CirclePiece.cs new file mode 100644 index 0000000000..6ea1494ea7 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CirclePiece.cs @@ -0,0 +1,153 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Backgrounds; +using OpenTK.Graphics; + +namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +{ + /// + /// A circle piece which is used uniformly through osu!taiko to visualise hitobjects. + /// + /// Note that this can actually be non-circle if the width is changed. See + /// for a usage example. + /// + /// + public class CirclePiece : TaikoPiece + { + public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f; + public const float SYMBOL_BORDER = 8; + public const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER; + + /// + /// The amount to scale up the base circle to show it as a "strong" piece. + /// + private const float strong_scale = 1.5f; + + /// + /// The colour of the inner circle and outer glows. + /// + public override Color4 AccentColour + { + get { return base.AccentColour; } + set + { + base.AccentColour = value; + + background.Colour = AccentColour; + + resetEdgeEffects(); + } + } + + /// + /// Whether Kiai mode effects are enabled for this circle piece. + /// + public override bool KiaiMode + { + get { return base.KiaiMode; } + set + { + base.KiaiMode = value; + + resetEdgeEffects(); + } + } + + protected override Container Content => content; + + private readonly Container content; + + private readonly Container background; + + public CirclePiece(bool isStrong = false) + { + AddInternal(new Drawable[] + { + background = new CircularContainer + { + Name = "Background", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + }, + new Triangles + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + ColourLight = Color4.White, + ColourDark = Color4.White.Darken(0.1f) + } + } + }, + new CircularContainer + { + Name = "Ring", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + BorderThickness = 8, + BorderColour = Color4.White, + Masking = true, + Children = new[] + { + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + }, + content = new Container + { + RelativeSizeAxes = Axes.Both, + Name = "Content", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }); + + if (isStrong) + { + Size *= strong_scale; + + //default for symbols etc. + Content.Scale *= strong_scale; + } + } + + protected override void Update() + { + base.Update(); + + //we want to allow for width of content to remain mapped to the area inside us, regardless of the scale applied above. + Content.Width = 1 / Content.Scale.X; + } + + private void resetEdgeEffects() + { + background.EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Glow, + Colour = AccentColour, + Radius = KiaiMode ? 50 : 8 + }; + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs new file mode 100644 index 0000000000..5431507614 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs @@ -0,0 +1,41 @@ +// 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.Graphics.Primitives; +using osu.Game.Modes.Taiko.UI; + +namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +{ + public class ElongatedCirclePiece : CirclePiece + { + /// + /// As we are being used to define the absolute size of hits, we need to be given a relative reference of our containing . + /// + public Func PlayfieldLengthReference; + + /// + /// The length of this piece as a multiple of the value returned by + /// + public float Length; + + public ElongatedCirclePiece(bool isStrong = false) : base(isStrong) + { + } + + protected override void Update() + { + base.Update(); + + var padding = Content.DrawHeight * Content.Width / 2; + + Content.Padding = new MarginPadding + { + Left = padding, + Right = padding, + }; + + Width = (PlayfieldLengthReference?.Invoke() ?? 0) * Length + DrawHeight; + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/RimHitSymbolPiece.cs b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs similarity index 91% rename from osu.Game.Modes.Taiko/Objects/Drawable/Pieces/RimHitSymbolPiece.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs index 6999634108..6e19497978 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/RimHitSymbolPiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.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.Framework.Graphics.Containers; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces +namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces { /// /// The symbol used for rim hit pieces. diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellSymbolPiece.cs b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs similarity index 88% rename from osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellSymbolPiece.cs rename to osu.Game.Modes.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs index 2bd86406a7..e491793902 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellSymbolPiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs @@ -1,10 +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.Graphics; using osu.Framework.Graphics; +using osu.Game.Graphics; -namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces +namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces { /// /// The symbol used for swell pieces. diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs new file mode 100644 index 0000000000..a0c8865c59 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs @@ -0,0 +1,45 @@ +// 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.Game.Graphics; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +{ + public class TaikoPiece : Container, IHasAccentColour + { + private Color4 accentColour; + /// + /// The colour of the inner circle and outer glows. + /// + public virtual Color4 AccentColour + { + get { return accentColour; } + set + { + accentColour = value; + } + } + + private bool kiaiMode; + /// + /// Whether Kiai mode effects are enabled for this circle piece. + /// + public virtual bool KiaiMode + { + get { return kiaiMode; } + set + { + kiaiMode = value; + } + } + + public TaikoPiece() + { + //just a default + Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2); + } + } +} diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TickPiece.cs b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TickPiece.cs new file mode 100644 index 0000000000..697102eb22 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TickPiece.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2007-2017 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.Sprites; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +{ + public class TickPiece : TaikoPiece + { + /// + /// Any tick that is not the first for a drumroll is not filled, but is instead displayed + /// as a hollow circle. This is what controls the border width of that circle. + /// + private const float tick_border_width = TaikoHitObject.CIRCLE_RADIUS / 2 / 4; + + /// + /// The size of a tick. + /// + private const float tick_size = TaikoHitObject.CIRCLE_RADIUS / 2; + + private bool filled; + public bool Filled + { + get { return filled; } + set + { + filled = value; + fillBox.Alpha = filled ? 1 : 0; + } + } + + private readonly Box fillBox; + + public TickPiece() + { + Size = new Vector2(tick_size); + + Add(new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = tick_border_width, + BorderColour = Color4.White, + Children = new[] + { + fillBox = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + }); + } + } +} diff --git a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs index ecd887a4cf..4f26ffd3a1 100644 --- a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs @@ -11,26 +11,16 @@ using osu.Game.Audio; namespace osu.Game.Modes.Taiko.Objects { - public class DrumRoll : TaikoHitObject, IHasDistance + public class DrumRoll : TaikoHitObject, IHasEndTime { /// /// Drum roll distance that results in a duration of 1 speed-adjusted beat length. /// private const float base_distance = 100; - public double EndTime => StartTime + Distance / Velocity; + public double EndTime => StartTime + Duration; - public double Duration => EndTime - StartTime; - - /// - /// Raw length of the drum roll in positional length units. - /// - public double Distance { get; set; } - - /// - /// Velocity of the drum roll in positional length units per millisecond. - /// - public double Velocity { get; protected set; } = 5; + public double Duration { get; set; } /// /// Numer of ticks per beat length. @@ -69,9 +59,6 @@ namespace osu.Game.Modes.Taiko.Objects { base.ApplyDefaults(timing, difficulty); - double speedAdjutedBeatLength = timing.SpeedMultiplierAt(StartTime) * timing.BeatLengthAt(StartTime); - - Velocity = base_distance * difficulty.SliderMultiplier / speedAdjutedBeatLength * VelocityMultiplier; tickSpacing = timing.BeatLengthAt(StartTime) / TickRate; RequiredGoodHits = TotalTicks * Math.Min(0.15, 0.05 + 0.10 / 6 * difficulty.OverallDifficulty); @@ -86,12 +73,12 @@ namespace osu.Game.Modes.Taiko.Objects return ret; bool first = true; - for (double t = StartTime; t < EndTime + (int)tickSpacing; t += tickSpacing) + for (double t = StartTime; t < EndTime + tickSpacing / 2; t += tickSpacing) { ret.Add(new DrumRollTick { FirstTick = first, - PreEmpt = PreEmpt, + ScrollTime = ScrollTime, TickSpacing = tickSpacing, StartTime = t, IsStrong = IsStrong, diff --git a/osu.Game.Modes.Taiko/Objects/Swell.cs b/osu.Game.Modes.Taiko/Objects/Swell.cs index f55416509a..97101ea797 100644 --- a/osu.Game.Modes.Taiko/Objects/Swell.cs +++ b/osu.Game.Modes.Taiko/Objects/Swell.cs @@ -7,9 +7,9 @@ namespace osu.Game.Modes.Taiko.Objects { public class Swell : TaikoHitObject, IHasEndTime { - public double EndTime { get; set; } + public double EndTime => StartTime + Duration; - public double Duration => EndTime - StartTime; + public double Duration { get; set; } /// /// The number of hits required to complete the swell successfully. diff --git a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs index 5de7e20b67..7375ea2b0d 100644 --- a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs @@ -15,19 +15,14 @@ namespace osu.Game.Modes.Taiko.Objects public const float CIRCLE_RADIUS = 42f; /// - /// Time (in milliseconds) to scroll in the hit object with a speed-adjusted beat length of 1 second. + /// The time taken from the initial (off-screen) spawn position to the centre of the hit target for a of 1000ms. /// - private const double base_scroll_time = 6000; + private const double scroll_time = 6000; /// - /// The velocity multiplier applied to this hit object. + /// Our adjusted taking into consideration local and other speed multipliers. /// - public float VelocityMultiplier = 1; - - /// - /// The time to scroll in the HitObject. - /// - public double PreEmpt; + public double ScrollTime; /// /// Whether this HitObject is a "strong" type. @@ -44,7 +39,7 @@ namespace osu.Game.Modes.Taiko.Objects { base.ApplyDefaults(timing, difficulty); - PreEmpt = base_scroll_time / difficulty.SliderMultiplier * timing.BeatLengthAt(StartTime) * timing.SpeedMultiplierAt(StartTime) / VelocityMultiplier / 1000; + ScrollTime = scroll_time * (timing.BeatLengthAt(StartTime) / 1000) / (difficulty.SliderMultiplier * timing.SpeedMultiplierAt(StartTime)); ControlPoint overridePoint; Kiai = timing.TimingPointAt(StartTime, out overridePoint).KiaiMode; diff --git a/osu.Game.Modes.Taiko/UI/InputDrum.cs b/osu.Game.Modes.Taiko/UI/InputDrum.cs index e7470ee913..5eea08ad8b 100644 --- a/osu.Game.Modes.Taiko/UI/InputDrum.cs +++ b/osu.Game.Modes.Taiko/UI/InputDrum.cs @@ -128,17 +128,36 @@ namespace osu.Game.Modes.Taiko.UI return false; Drawable target = null; + Drawable back = null; if (args.Key == CentreKey) + { target = centreHit; + back = centre; + } else if (args.Key == RimKey) + { target = rimHit; + back = rim; + } if (target != null) { - target.FadeTo(Math.Min(target.Alpha + 0.4f, 1), 40, EasingTypes.OutQuint); - target.Delay(40); - target.FadeOut(1000, EasingTypes.OutQuint); + const float scale_amount = 0.05f; + const float alpha_amount = 0.5f; + + const float down_time = 40; + const float up_time = 1000; + + back.ScaleTo(target.Scale.X - scale_amount, down_time, EasingTypes.OutQuint); + back.Delay(down_time); + back.ScaleTo(1, up_time, EasingTypes.OutQuint); + + target.ScaleTo(target.Scale.X - scale_amount, down_time, EasingTypes.OutQuint); + target.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, EasingTypes.OutQuint); + target.Delay(down_time); + target.ScaleTo(1, up_time, EasingTypes.OutQuint); + target.FadeOut(up_time, EasingTypes.OutQuint); } return false; diff --git a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs index 5640e1df30..29fa693d58 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs @@ -1,17 +1,21 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Beatmaps; +using osu.Framework.Allocation; +using osu.Framework.MathUtils; using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Timing; using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Objects.Types; +using osu.Game.Modes.Replays; using osu.Game.Modes.Scoring; using osu.Game.Modes.Taiko.Beatmaps; using osu.Game.Modes.Taiko.Judgements; using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.Taiko.Objects.Drawable; +using osu.Game.Modes.Taiko.Objects.Drawables; using osu.Game.Modes.Taiko.Scoring; using osu.Game.Modes.UI; -using osu.Game.Modes.Replays; using osu.Game.Modes.Taiko.Replays; namespace osu.Game.Modes.Taiko.UI @@ -23,6 +27,79 @@ namespace osu.Game.Modes.Taiko.UI { } + [BackgroundDependencyLoader] + private void load() + { + loadBarLines(); + } + + private void loadBarLines() + { + var taikoPlayfield = Playfield as TaikoPlayfield; + + if (taikoPlayfield == null) + return; + + TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1]; + double lastHitTime = 1 + (lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime; + + var timingPoints = Beatmap.TimingInfo.ControlPoints.FindAll(cp => cp.TimingChange); + + if (timingPoints.Count == 0) + return; + + int currentIndex = 0; + + while (currentIndex < timingPoints.Count && Precision.AlmostEquals(timingPoints[currentIndex].BeatLength, 0)) + currentIndex++; + + double time = timingPoints[currentIndex].Time; + double measureLength = timingPoints[currentIndex].BeatLength * (int)timingPoints[currentIndex].TimeSignature; + + // Find the bar line time closest to 0 + time -= measureLength * (int)(time / measureLength); + + // Always start barlines from a positive time + while (time < 0) + time += measureLength; + + int currentBeat = 0; + while (time <= lastHitTime) + { + ControlPoint current = timingPoints[currentIndex]; + + if (time > current.Time || current.OmitFirstBarLine) + { + bool isMajor = currentBeat % (int)current.TimeSignature == 0; + + var barLine = new BarLine + { + StartTime = time, + }; + + barLine.ApplyDefaults(Beatmap.TimingInfo, Beatmap.BeatmapInfo.Difficulty); + + taikoPlayfield.AddBarLine(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); + + currentBeat++; + } + + double bl = current.BeatLength; + + if (bl < 800) + bl *= (int)current.TimeSignature; + + time += bl; + + if (currentIndex + 1 >= timingPoints.Count || time < timingPoints[currentIndex + 1].Time) + continue; + + currentBeat = 0; + currentIndex++; + time = timingPoints[currentIndex].Time; + } + } + public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); protected override IBeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); @@ -41,7 +118,7 @@ namespace osu.Game.Modes.Taiko.UI if (centreHit != null) { if (h.IsStrong) - return new DrawableStrongCentreHit(centreHit); + return new DrawableCentreHitStrong(centreHit); return new DrawableCentreHit(centreHit); } @@ -49,15 +126,13 @@ namespace osu.Game.Modes.Taiko.UI if (rimHit != null) { if (h.IsStrong) - return new DrawableStrongRimHit(rimHit); + return new DrawableRimHitStrong(rimHit); return new DrawableRimHit(rimHit); } var drumRoll = h as DrumRoll; if (drumRoll != null) { - if (h.IsStrong) - return new DrawableStrongDrumRoll(drumRoll); return new DrawableDrumRoll(drumRoll); } diff --git a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs index c23d920eda..9e7eb571a1 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs @@ -14,8 +14,8 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Primitives; -using osu.Game.Modes.Taiko.Objects.Drawable; using System.Linq; +using osu.Game.Modes.Taiko.Objects.Drawables; namespace osu.Game.Modes.Taiko.UI { @@ -40,7 +40,7 @@ namespace osu.Game.Modes.Taiko.UI protected override Container Content => hitObjectContainer; private readonly Container hitExplosionContainer; - //private Container barLineContainer; + private readonly Container barLineContainer; private readonly Container judgementContainer; private readonly Container hitObjectContainer; @@ -85,7 +85,7 @@ namespace osu.Game.Modes.Taiko.UI { new Container { - Padding = new MarginPadding { Left = hit_target_offset }, + X = hit_target_offset, RelativeSizeAxes = Axes.Both, Children = new Drawable[] { @@ -96,10 +96,10 @@ namespace osu.Game.Modes.Taiko.UI Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2), BlendingMode = BlendingMode.Additive }, - //barLineContainer = new Container - //{ - // RelativeSizeAxes = Axes.Both, - //}, + barLineContainer = new Container + { + RelativeSizeAxes = Axes.Both, + }, new HitTarget { Anchor = Anchor.CentreLeft, @@ -174,6 +174,11 @@ namespace osu.Game.Modes.Taiko.UI swell.OnStart += () => topLevelHitContainer.Add(swell.CreateProxy()); } + public void AddBarLine(DrawableBarLine barLine) + { + barLineContainer.Add(barLine); + } + public override void OnJudgement(DrawableHitObject judgedObject) { bool wasHit = judgedObject.Judgement.Result == HitResult.Hit; diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index f3f93d720a..d0981c2500 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -53,23 +53,27 @@ + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index 89399a56ff..534578337f 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -22,8 +22,9 @@ namespace osu.Game.Beatmaps.Drawables public Action GainedSelection; private readonly SpriteText title; private readonly SpriteText artist; - private OsuConfigManager config; + private Bindable preferUnicode; + private readonly WorkingBeatmap beatmap; private readonly FillFlowContainer difficultyIcons; @@ -83,24 +84,13 @@ namespace osu.Game.Beatmaps.Drawables [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - this.config = config; - preferUnicode = config.GetBindable(OsuConfig.ShowUnicode); - preferUnicode.ValueChanged += preferUnicode_changed; - preferUnicode_changed(preferUnicode, null); - } - - private void preferUnicode_changed(object sender, EventArgs e) - { - title.Text = config.GetUnicodeString(beatmap.BeatmapSetInfo.Metadata.Title, beatmap.BeatmapSetInfo.Metadata.TitleUnicode); - artist.Text = config.GetUnicodeString(beatmap.BeatmapSetInfo.Metadata.Artist, beatmap.BeatmapSetInfo.Metadata.ArtistUnicode); - } - - protected override void Dispose(bool isDisposing) - { - if (preferUnicode != null) - preferUnicode.ValueChanged -= preferUnicode_changed; - base.Dispose(isDisposing); + preferUnicode.ValueChanged += unicode => + { + title.Text = unicode ? beatmap.BeatmapSetInfo.Metadata.TitleUnicode : beatmap.BeatmapSetInfo.Metadata.Title; + artist.Text = unicode ? beatmap.BeatmapSetInfo.Metadata.ArtistUnicode : beatmap.BeatmapSetInfo.Metadata.Artist; + }; + preferUnicode.TriggerChange(); } private class PanelBackground : BufferedContainer diff --git a/osu.Game/Beatmaps/Timing/ControlPoint.cs b/osu.Game/Beatmaps/Timing/ControlPoint.cs index e79fd8bb31..ea152ccb39 100644 --- a/osu.Game/Beatmaps/Timing/ControlPoint.cs +++ b/osu.Game/Beatmaps/Timing/ControlPoint.cs @@ -5,21 +5,16 @@ namespace osu.Game.Beatmaps.Timing { public class ControlPoint { - public static ControlPoint Default = new ControlPoint - { - BeatLength = 500, - TimingChange = true, - }; - public string SampleBank; public int SampleVolume; - public TimeSignatures TimeSignature; public double Time; - public double BeatLength; - public double VelocityAdjustment; - public bool TimingChange; + public double BeatLength = 500; + public double SpeedMultiplier = 1; + public bool TimingChange = true; public bool KiaiMode; public bool OmitFirstBarLine; + + public ControlPoint Clone() => (ControlPoint)MemberwiseClone(); } } diff --git a/osu.Game/Beatmaps/Timing/TimingInfo.cs b/osu.Game/Beatmaps/Timing/TimingInfo.cs index 076618beea..19cb0816ba 100644 --- a/osu.Game/Beatmaps/Timing/TimingInfo.cs +++ b/osu.Game/Beatmaps/Timing/TimingInfo.cs @@ -10,8 +10,8 @@ namespace osu.Game.Beatmaps.Timing { public readonly List ControlPoints = new List(); - public double BPMMaximum => 60000 / (ControlPoints?.Where(c => c.BeatLength != 0).OrderBy(c => c.BeatLength).FirstOrDefault() ?? ControlPoint.Default).BeatLength; - public double BPMMinimum => 60000 / (ControlPoints?.Where(c => c.BeatLength != 0).OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? ControlPoint.Default).BeatLength; + public double BPMMaximum => 60000 / (ControlPoints?.Where(c => c.BeatLength != 0).OrderBy(c => c.BeatLength).FirstOrDefault() ?? new ControlPoint()).BeatLength; + public double BPMMinimum => 60000 / (ControlPoints?.Where(c => c.BeatLength != 0).OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? new ControlPoint()).BeatLength; public double BPMMode => BPMAt(ControlPoints.Where(c => c.BeatLength != 0).GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).First().First().Time); public double BPMAt(double time) @@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps.Timing ControlPoint overridePoint; ControlPoint timingPoint = TimingPointAt(time, out overridePoint); - return overridePoint?.VelocityAdjustment ?? timingPoint?.VelocityAdjustment ?? 1; + return overridePoint?.SpeedMultiplier ?? timingPoint?.SpeedMultiplier ?? 1; } /// @@ -74,7 +74,7 @@ namespace osu.Game.Beatmaps.Timing else break; } - return timingPoint ?? ControlPoint.Default; + return timingPoint ?? new ControlPoint(); } } } \ No newline at end of file diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6190678e1e..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; @@ -187,10 +187,6 @@ namespace osu.Game.Configuration #pragma warning restore CS0612 // Type or member is obsolete } - //todo: make a UnicodeString class/struct rather than requiring this helper method. - public string GetUnicodeString(string nonunicode, string unicode) - => Get(OsuConfig.ShowUnicode) ? unicode ?? nonunicode : nonunicode ?? unicode; - public OsuConfigManager(Storage storage) : base(storage) { } diff --git a/osu.Game/Database/BaseDifficulty.cs b/osu.Game/Database/BaseDifficulty.cs index 3db8b29644..7c9f47e7b6 100644 --- a/osu.Game/Database/BaseDifficulty.cs +++ b/osu.Game/Database/BaseDifficulty.cs @@ -9,12 +9,12 @@ namespace osu.Game.Database { [PrimaryKey, AutoIncrement] public int ID { get; set; } - public float DrainRate { get; set; } - public float CircleSize { get; set; } - public float OverallDifficulty { get; set; } - public float ApproachRate { get; set; } - public float SliderMultiplier { get; set; } - public float SliderTickRate { get; set; } + public float DrainRate { get; set; } = 5; + public float CircleSize { get; set; } = 5; + public float OverallDifficulty { get; set; } = 5; + public float ApproachRate { get; set; } = 5; + public float SliderMultiplier { get; set; } = 1; + public float SliderTickRate { get; set; } = 1; /// /// Maps a difficulty value [0, 10] to a two-piece linear range of values. diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Database/BeatmapInfo.cs index 93ef8cae4a..21fde332ff 100644 --- a/osu.Game/Database/BeatmapInfo.cs +++ b/osu.Game/Database/BeatmapInfo.cs @@ -14,6 +14,7 @@ namespace osu.Game.Database [PrimaryKey, AutoIncrement] public int ID { get; set; } + //TODO: should be in database public int BeatmapVersion; public int? OnlineBeatmapID { get; set; } diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 8dff614f6c..830d0adc97 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -60,8 +60,8 @@ namespace osu.Game.Graphics.Backgrounds protected override void LoadComplete() { base.LoadComplete(); - for (int i = 0; i < aimTriangleCount; i++) - addTriangle(true); + + addTriangles(true); } private int aimTriangleCount => (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio); @@ -83,8 +83,8 @@ namespace osu.Game.Graphics.Backgrounds t.Expire(); } - while (CreateNewTriangles && Children.Count() < aimTriangleCount) - addTriangle(false); + if (CreateNewTriangles) + addTriangles(false); } protected virtual Triangle CreateTriangle() @@ -113,12 +113,16 @@ namespace osu.Game.Graphics.Backgrounds protected virtual Color4 GetTriangleShade() => Interpolation.ValueAt(RNG.NextSingle(), ColourDark, ColourLight, 0, 1); - private void addTriangle(bool randomY) + private void addTriangles(bool randomY) { - var sprite = CreateTriangle(); - float triangleHeight = sprite.DrawHeight / DrawHeight; - sprite.Position = new Vector2(RNG.NextSingle(), randomY ? RNG.NextSingle() * (1 + triangleHeight) - triangleHeight : 1); - Add(sprite); + int addCount = aimTriangleCount - Children.Count(); + for (int i = 0; i < addCount; i++) + { + var sprite = CreateTriangle(); + float triangleHeight = sprite.DrawHeight / DrawHeight; + sprite.Position = new Vector2(RNG.NextSingle(), randomY ? RNG.NextSingle() * (1 + triangleHeight) - triangleHeight : 1); + Add(sprite); + } } } } diff --git a/osu.Game/Graphics/Cursor/GameplayCursor.cs b/osu.Game/Graphics/Cursor/GameplayCursor.cs index 3f94bbaddc..3f699219a4 100644 --- a/osu.Game/Graphics/Cursor/GameplayCursor.cs +++ b/osu.Game/Graphics/Cursor/GameplayCursor.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Game.Configuration; -using System; namespace osu.Game.Graphics.Cursor { @@ -116,14 +115,9 @@ namespace osu.Game.Graphics.Cursor }; cursorScale = config.GetBindable(OsuConfig.GameplayCursorSize); - cursorScale.ValueChanged += scaleChanged; + cursorScale.ValueChanged += newScale => cursorContainer.Scale = new Vector2((float)cursorScale); cursorScale.TriggerChange(); } - - private void scaleChanged(object sender, EventArgs e) - { - cursorContainer.Scale = new Vector2((float)cursorScale); - } } } } diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 67b17fae5c..0fb7f59212 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -131,14 +131,9 @@ namespace osu.Game.Graphics.Cursor }; cursorScale = config.GetBindable(OsuConfig.MenuCursorSize); - cursorScale.ValueChanged += scaleChanged; + cursorScale.ValueChanged += newScale => cursorContainer.Scale = new Vector2((float)newScale); cursorScale.TriggerChange(); } - - private void scaleChanged(object sender, EventArgs e) - { - cursorContainer.Scale = new Vector2((float)cursorScale); - } } } } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index fc44d80ea6..6a5151b90c 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -1,7 +1,6 @@ // 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.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -86,9 +85,9 @@ namespace osu.Game.Graphics.UserInterface }; } - private void bindableValueChanged(object sender, EventArgs e) + private void bindableValueChanged(bool isChecked) { - State = bindable.Value ? CheckboxState.Checked : CheckboxState.Unchecked; + State = isChecked ? CheckboxState.Checked : CheckboxState.Unchecked; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 6d17d79ca1..242a9a8f6a 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -21,7 +21,7 @@ namespace osu.Game.Graphics.UserInterface { protected override Dropdown CreateDropdown() => new OsuTabDropdown(); - protected override TabItem CreateTabItem(T value) => new OsuTabItem { Value = value }; + protected override TabItem CreateTabItem(T value) => new OsuTabItem(value); protected override bool InternalContains(Vector2 screenSpacePos) => base.InternalContains(screenSpacePos) || Dropdown.Contains(screenSpacePos); @@ -75,16 +75,6 @@ namespace osu.Game.Graphics.UserInterface } } - public new T Value - { - get { return base.Value; } - set - { - base.Value = value; - text.Text = (value as Enum)?.GetDescription(); - } - } - public override bool Active { get { return base.Active; } @@ -134,30 +124,31 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Blue; } - public OsuTabItem() + public OsuTabItem(T value) : base(value) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; Children = new Drawable[] { - text = new OsuSpriteText - { - Margin = new MarginPadding { Top = 5, Bottom = 5 }, - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - TextSize = 14, - Font = @"Exo2.0-Bold", // Font should only turn bold when active? - }, - box = new Box - { - RelativeSizeAxes = Axes.X, - Height = 1, - Alpha = 0, - Colour = Color4.White, - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - } + text = new OsuSpriteText + { + Margin = new MarginPadding { Top = 5, Bottom = 5 }, + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Text = (value as Enum)?.GetDescription(), + TextSize = 14, + Font = @"Exo2.0-Bold", // Font should only turn bold when active? + }, + box = new Box + { + RelativeSizeAxes = Axes.X, + Height = 1, + Alpha = 0, + Colour = Color4.White, + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + } }; } } diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index a4f6092d66..12eeb771dd 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -98,13 +98,10 @@ namespace osu.Game.Graphics.UserInterface DisplayedCount = Current; - Current.ValueChanged += currentChanged; - } - - private void currentChanged(object sender, EventArgs e) - { - if (IsLoaded) - TransformCount(displayedCount, Current); + Current.ValueChanged += newValue => + { + if (IsLoaded) TransformCount(displayedCount, newValue); + }; } protected override void LoadComplete() diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs index 374385e351..4933c170e8 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs @@ -1,7 +1,6 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -19,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface.Volume protected override bool HideOnEscape => false; - private void volumeChanged(object sender, EventArgs e) + private void volumeChanged(double newVolume) { Show(); schedulePopOut(); diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 83f800dfa8..e346a22813 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -56,13 +56,17 @@ namespace osu.Game.Modes.Objects.Drawables Samples.ForEach(s => s?.Play()); } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load() { - base.LoadComplete(); - //we may be setting a custom judgement in test cases or what not. if (Judgement == null) Judgement = CreateJudgement(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); //force application of the state that was set before we loaded. UpdateState(State); diff --git a/osu.Game/Modes/UI/ComboCounter.cs b/osu.Game/Modes/UI/ComboCounter.cs index 3629634889..8c0327fa04 100644 --- a/osu.Game/Modes/UI/ComboCounter.cs +++ b/osu.Game/Modes/UI/ComboCounter.cs @@ -66,12 +66,7 @@ namespace osu.Game.Modes.UI TextSize = 80; - Current.ValueChanged += comboChanged; - } - - private void comboChanged(object sender, System.EventArgs e) - { - updateCount(Current.Value == 0); + Current.ValueChanged += newValue => updateCount(newValue == 0); } protected override void LoadComplete() diff --git a/osu.Game/Modes/UI/HealthDisplay.cs b/osu.Game/Modes/UI/HealthDisplay.cs index 3471f4bc3f..4c8d7e4ab8 100644 --- a/osu.Game/Modes/UI/HealthDisplay.cs +++ b/osu.Game/Modes/UI/HealthDisplay.cs @@ -16,7 +16,7 @@ namespace osu.Game.Modes.UI protected HealthDisplay() { - Current.ValueChanged += (s, e) => SetHealth((float)Current); + Current.ValueChanged += newValue => SetHealth((float)newValue); } protected abstract void SetHealth(float value); diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index e36d2a101c..a958c61c68 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -42,6 +42,16 @@ namespace osu.Game.Modes.UI /// protected readonly KeyConversionInputManager KeyConversionInputManager; + /// + /// Whether we are currently providing the local user a gameplay cursor. + /// + public virtual bool ProvidingUserCursor => false; + + /// + /// Whether we have a replay loaded currently. + /// + public bool HasReplayLoaded => InputManager.ReplayInputHandler != null; + /// /// Whether all the HitObjects have been judged. /// @@ -157,6 +167,8 @@ namespace osu.Game.Modes.UI { public event Action OnJudgement; + public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor; + protected override Container Content => content; protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result != HitResult.None); diff --git a/osu.Game/Modes/UI/HudOverlay.cs b/osu.Game/Modes/UI/HudOverlay.cs index a6c54e7f3a..355b62bc57 100644 --- a/osu.Game/Modes/UI/HudOverlay.cs +++ b/osu.Game/Modes/UI/HudOverlay.cs @@ -8,13 +8,19 @@ using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play; -using System; 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; @@ -22,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(); @@ -33,36 +42,57 @@ 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 += visibilityChanged; + showKeyCounter.ValueChanged += keyCounterVisibility => + { + if (keyCounterVisibility) + KeyCounter.FadeIn(duration); + else + KeyCounter.FadeOut(duration); + }; showKeyCounter.TriggerChange(); - } - private void visibilityChanged(object sender, EventArgs e) - { - if (showKeyCounter) - KeyCounter.Show(); - else - KeyCounter.Hide(); + 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) { - //bind processor bindables to combocounter, score display etc. - //TODO: these should be bindable binds, not events! ScoreCounter?.Current.BindTo(processor.TotalScore); AccuracyCounter?.Current.BindTo(processor.Accuracy); ComboCounter?.Current.BindTo(processor.Combo); @@ -73,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/Modes/UI/Playfield.cs b/osu.Game/Modes/UI/Playfield.cs index eff06ce80f..f31ee0f189 100644 --- a/osu.Game/Modes/UI/Playfield.cs +++ b/osu.Game/Modes/UI/Playfield.cs @@ -22,6 +22,11 @@ namespace osu.Game.Modes.UI internal Container ScaledContent; + /// + /// Whether we are currently providing the local user a gameplay cursor. + /// + public virtual bool ProvidingUserCursor => false; + protected override Container Content => content; private readonly Container content; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d75f8b4d8e..7172aba3be 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -314,7 +314,7 @@ namespace osu.Game if (intro?.ChildScreen != null) intro.ChildScreen.Padding = new MarginPadding { Top = Toolbar.Position.Y + Toolbar.DrawHeight }; - Cursor.State = currentScreen == null || currentScreen.HasLocalCursorDisplayed ? Visibility.Hidden : Visibility.Visible; + Cursor.State = currentScreen?.HasLocalCursorDisplayed == false ? Visibility.Visible : Visibility.Hidden; } private void screenAdded(Screen newScreen) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f454956de7..f95e8c3ac6 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -92,7 +92,10 @@ namespace osu.Game Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Medium")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-MediumItalic")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto")); + Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Basic")); + Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Hangul")); + Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Basic")); + Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Compatibility")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Regular")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-RegularItalic")); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 0272438927..2b9f8e86a9 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -39,9 +39,9 @@ namespace osu.Game.Overlays.Mods public readonly Bindable PlayMode = new Bindable(); - private void modeChanged(object sender, EventArgs eventArgs) + private void modeChanged(PlayMode newMode) { - var ruleset = Ruleset.GetRuleset(PlayMode); + var ruleset = Ruleset.GetRuleset(newMode); foreach (ModSection section in modSectionsContainer.Children) section.Buttons = ruleset.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray(); refreshSelectedMods(); @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Mods if (osu != null) PlayMode.BindTo(osu.PlayMode); PlayMode.ValueChanged += modeChanged; - modeChanged(null, null); + PlayMode.TriggerChange(); } protected override void PopOut() diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index aa0ea1ae9b..9f3eeb47a0 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -78,8 +78,6 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load(OsuGameBase game, OsuConfigManager config, BeatmapDatabase beatmaps, OsuColour colours) { - unicodeString = config.GetUnicodeString; - Children = new Drawable[] { dragContainer = new Container @@ -210,7 +208,7 @@ namespace osu.Game.Overlays this.beatmaps = beatmaps; trackManager = game.Audio.Track; preferUnicode = config.GetBindable(OsuConfig.ShowUnicode); - preferUnicode.ValueChanged += preferUnicode_changed; + preferUnicode.ValueChanged += unicode => updateDisplay(current, TransformDirection.None); beatmapSource = game.Beatmap ?? new Bindable(); playList = beatmaps.GetAllWithChildren(); @@ -222,7 +220,8 @@ namespace osu.Game.Overlays protected override void LoadComplete() { beatmapSource.ValueChanged += workingChanged; - workingChanged(); + beatmapSource.TriggerChange(); + base.LoadComplete(); } @@ -247,17 +246,12 @@ namespace osu.Game.Overlays playButton.Icon = FontAwesome.fa_play_circle_o; } - private void preferUnicode_changed(object sender, EventArgs e) + private void workingChanged(WorkingBeatmap beatmap) { - updateDisplay(current, TransformDirection.None); - } - - private void workingChanged(object sender = null, EventArgs e = null) - { - progress.IsEnabled = beatmapSource.Value != null; - if (beatmapSource.Value == current) return; - bool audioEquals = current?.BeatmapInfo?.AudioEquals(beatmapSource?.Value?.BeatmapInfo) ?? false; - current = beatmapSource.Value; + progress.IsEnabled = beatmap != null; + if (beatmap == current) return; + bool audioEquals = current?.BeatmapInfo?.AudioEquals(beatmap?.BeatmapInfo) ?? false; + current = beatmap; updateDisplay(current, audioEquals ? TransformDirection.None : TransformDirection.Next); appendToHistory(current?.BeatmapInfo); } @@ -342,8 +336,8 @@ namespace osu.Game.Overlays else { BeatmapMetadata metadata = beatmap.Beatmap.BeatmapInfo.Metadata; - title.Text = unicodeString(metadata.Title, metadata.TitleUnicode); - artist.Text = unicodeString(metadata.Artist, metadata.ArtistUnicode); + title.Text = preferUnicode ? metadata.TitleUnicode : metadata.Title; + artist.Text = preferUnicode ? metadata.ArtistUnicode : metadata.Artist; } }); @@ -374,21 +368,12 @@ namespace osu.Game.Overlays }; } - private Func unicodeString; - private void seek(float position) { current?.Track?.Seek(current.Track.Length * position); current?.Track?.Start(); } - protected override void Dispose(bool isDisposing) - { - if (preferUnicode != null) - preferUnicode.ValueChanged -= preferUnicode_changed; - base.Dispose(isDisposing); - } - private const float transition_length = 800; protected override void PopIn() diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 77fc010e6d..663c5cf90c 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -155,7 +155,7 @@ namespace osu.Game.Overlays.Notifications public void MarkAllRead() { - notifications.Children.ForEach(n => n.Read = true); + notifications?.Children.ForEach(n => n.Read = true); } } } \ No newline at end of file diff --git a/osu.Game/Overlays/Options/OptionSlider.cs b/osu.Game/Overlays/Options/OptionSlider.cs index 772d2c37e6..8fa9bf063d 100644 --- a/osu.Game/Overlays/Options/OptionSlider.cs +++ b/osu.Game/Overlays/Options/OptionSlider.cs @@ -29,10 +29,10 @@ namespace osu.Game.Overlays.Options public BindableNumber Bindable { - get { return slider.Bindable; } + get { return slider.Value; } set { - slider.Bindable = value; + slider.Value = value; if (value?.Disabled ?? true) Alpha = 0.3f; } diff --git a/osu.Game/Overlays/Options/OptionTextBox.cs b/osu.Game/Overlays/Options/OptionTextBox.cs index 47c81e6a7e..722f24d50d 100644 --- a/osu.Game/Overlays/Options/OptionTextBox.cs +++ b/osu.Game/Overlays/Options/OptionTextBox.cs @@ -1,7 +1,6 @@ // 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.Configuration; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; @@ -41,10 +40,7 @@ namespace osu.Game.Overlays.Options bindable.Value = Text; } - private void bindableValueChanged(object sender, EventArgs e) - { - Text = bindable.Value; - } + private void bindableValueChanged(string newValue) => Text = newValue; protected override void Dispose(bool isDisposing) { 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/Overlays/Options/Sections/Graphics/LayoutOptions.cs b/osu.Game/Overlays/Options/Sections/Graphics/LayoutOptions.cs index 8c4930d99d..b04f853ec4 100644 --- a/osu.Game/Overlays/Options/Sections/Graphics/LayoutOptions.cs +++ b/osu.Game/Overlays/Options/Sections/Graphics/LayoutOptions.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -using System; namespace osu.Game.Overlays.Options.Sections.Graphics { @@ -52,9 +51,9 @@ namespace osu.Game.Overlays.Options.Sections.Graphics letterboxing.TriggerChange(); } - private void visibilityChanged(object sender, EventArgs e) + private void visibilityChanged(bool newVisibility) { - if (letterboxing) + if (newVisibility) { letterboxPositionX.Show(); letterboxPositionY.Show(); diff --git a/osu.Game/Screens/OsuGameScreen.cs b/osu.Game/Screens/OsuGameScreen.cs index a5c6cec09e..3e832b36fa 100644 --- a/osu.Game/Screens/OsuGameScreen.cs +++ b/osu.Game/Screens/OsuGameScreen.cs @@ -1,7 +1,6 @@ // 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.Allocation; using osu.Framework.Configuration; using osu.Framework.Screens; @@ -40,11 +39,6 @@ namespace osu.Game.Screens } } - private void beatmap_ValueChanged(object sender, EventArgs e) - { - OnBeatmapChanged(beatmap.Value); - } - [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuGameBase game) { @@ -57,7 +51,7 @@ namespace osu.Game.Screens beatmap.Value = localMap; } - beatmap.ValueChanged += beatmap_ValueChanged; + beatmap.ValueChanged += OnBeatmapChanged; } protected virtual void OnBeatmapChanged(WorkingBeatmap beatmap) 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 c678e9bf37..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,14 +30,14 @@ namespace osu.Game.Screens.Play internal override bool ShowOverlays => false; - internal override bool HasLocalCursorDisplayed => !hasReplayLoaded && !IsPaused; - - private bool hasReplayLoaded => HitRenderer.InputManager.ReplayInputHandler != null; + 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; @@ -58,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) @@ -118,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) @@ -156,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, + } }; } @@ -256,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) @@ -275,7 +273,8 @@ namespace osu.Game.Screens.Play Background?.FadeTo((100f - dimLevel) / 100, 1500, EasingTypes.OutQuint); Content.Alpha = 0; - dimLevel.ValueChanged += dimChanged; + + dimLevel.ValueChanged += newDim => Background?.FadeTo((100f - newDim) / 100, 800); Content.ScaleTo(0.7f); @@ -304,7 +303,7 @@ namespace osu.Game.Screens.Play { if (pauseOverlay == null) return false; - if (hasReplayLoaded) + if (HitRenderer.HasReplayLoaded) return false; if (pauseOverlay.State != Visibility.Visible && !canPause) return true; @@ -318,18 +317,11 @@ namespace osu.Game.Screens.Play { FadeOut(250); Content.ScaleTo(0.7f, 750, EasingTypes.InQuint); - - dimLevel.ValueChanged -= dimChanged; Background?.FadeTo(1f, 200); return base.OnExiting(next); } } - private void dimChanged(object sender, EventArgs e) - { - Background?.FadeTo((100f - dimLevel) / 100, 800); - } - private Bindable mouseWheelDisabled; protected override bool OnWheel(InputState state) => mouseWheelDisabled.Value && !IsPaused; diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 7443603c8b..f104bf9a37 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -179,11 +179,11 @@ namespace osu.Game.Screens.Select public void Filter(FilterCriteria newCriteria = null, bool debounce = true) { - if (!IsLoaded) return; - if (newCriteria != null) criteria = newCriteria; + if (!IsLoaded) return; + Action perform = delegate { filterTask = null; diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 088346d91f..c52d0397ed 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -61,10 +61,10 @@ namespace osu.Game.Screens.Select }, }; - tabs.ItemChanged += (sender, e) => invokeOnFilter(); + tabs.SelectedItem.ValueChanged += item => invokeOnFilter(); modsCheckbox.Action += (sender, e) => invokeOnFilter(); - tabs.SelectedItem = BeatmapDetailTab.Global; + tabs.SelectedItem.Value = BeatmapDetailTab.Global; } } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 5445847da5..6d92b35993 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -151,8 +151,8 @@ namespace osu.Game.Screens.Select groupTabs.PinItem(GroupMode.All); groupTabs.PinItem(GroupMode.RecentlyPlayed); - groupTabs.ItemChanged += (sender, value) => Group = value; - sortTabs.ItemChanged += (sender, value) => Sort = value; + groupTabs.SelectedItem.ValueChanged += val => Group = val; + sortTabs.SelectedItem.ValueChanged += val => Sort = val; } public void Deactivate() @@ -173,9 +173,9 @@ namespace osu.Game.Screens.Select { sortTabs.AccentColour = colours.GreenLight; - if (osu != null) - playMode.BindTo(osu.PlayMode); - playMode.ValueChanged += (s, e) => FilterChanged?.Invoke(CreateCriteria()); + if (osu != null) playMode.BindTo(osu.PlayMode); + playMode.ValueChanged += val => FilterChanged?.Invoke(CreateCriteria()); + playMode.TriggerChange(); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index adcf8fd042..2bac387c5c 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -157,6 +157,7 @@ namespace osu.Game.Screens.Select.Leaderboards }) { TimeBeforeLoad = 500, + RelativeSizeAxes = Axes.None, Size = new Vector2(HEIGHT - edge_margin * 2, HEIGHT - edge_margin * 2), }, new Container diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 656adf0d62..3e8ddc0f64 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; using System.Threading; using OpenTK; @@ -168,13 +167,12 @@ namespace osu.Game.Screens.Select BeatmapOptions.AddButton(@"Delete", @"Beatmap", FontAwesome.fa_trash, colours.Pink, promptDelete, Key.Number4, float.MaxValue); } - if (osu != null) - playMode.BindTo(osu.PlayMode); - playMode.ValueChanged += playMode_ValueChanged; - if (database == null) database = beatmaps; + playMode.ValueChanged += val => { if (Beatmap != null) Beatmap.PreferredPlayMode = val; }; + if (osu != null) playMode.BindTo(osu.PlayMode); + database.BeatmapSetAdded += onBeatmapSetAdded; database.BeatmapSetRemoved += onBeatmapSetRemoved; @@ -276,8 +274,6 @@ namespace osu.Game.Screens.Select initialAddSetsTask.Cancel(); } - private void playMode_ValueChanged(object sender, EventArgs e) => Beatmap.PreferredPlayMode = playMode; - private void changeBackground(WorkingBeatmap beatmap) { var backgroundModeBeatmap = Background as BackgroundScreenBeatmap; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ffa84c36d4..eb2cf4b580 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -192,8 +192,11 @@ - + + + + @@ -330,12 +333,8 @@ - - - -