From 72959691e9e2aa5958521717dd940a2601d46ee6 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 22 Jul 2018 17:16:17 +0300 Subject: [PATCH 01/59] Introduce KeyCounterMemento --- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- osu.Game/Screens/Play/KeyCounter.cs | 7 +++++++ osu.Game/Screens/Play/KeyCounterCollection.cs | 10 +++++++--- osu.Game/Screens/Play/KeyCounterMemento.cs | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Screens/Play/KeyCounterMemento.cs diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 4f3fe15211..c6a411c0bb 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -79,7 +79,7 @@ public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContain BindRulesetContainer(rulesetContainer); Progress.Objects = rulesetContainer.Objects; - Progress.AudioClock = offsetClock; + Progress.AudioClock = KeyCounter.AudioClock = offsetClock; Progress.AllowSeeking = rulesetContainer.HasReplayLoaded; Progress.OnSeek = pos => adjustableClock.Seek(pos); diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 2c31e61114..01f1d6dafd 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Timing; using osu.Game.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; @@ -55,6 +56,8 @@ protected set public Color4 KeyUpTextColor { get; set; } = Color4.White; public int FadeTime { get; set; } + public IClock AudioClock { get; set; } + protected KeyCounter(string name) { Name = name; @@ -129,5 +132,9 @@ private void updateGlowSprite(bool show) } public void ResetCount() => CountPresses = 0; + + public KeyCounterMemento SaveState() => new KeyCounterMemento(AudioClock.CurrentTime, CountPresses); + + public void RestoreState(KeyCounterMemento memento) => CountPresses = memento.CountPresses; } } diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 721d925d63..5f1e502cf7 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -3,14 +3,15 @@ using System; using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using OpenTK.Graphics; using osu.Framework.Input; -using osu.Framework.Configuration; -using osu.Framework.Allocation; +using osu.Framework.Timing; using osu.Game.Configuration; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Screens.Play { @@ -36,6 +37,7 @@ public override void Add(KeyCounter key) key.FadeTime = FadeTime; key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; + key.AudioClock = AudioClock; } public void ResetCount() @@ -117,6 +119,8 @@ public Color4 KeyUpTextColor public override bool HandleKeyboardInput => receptor == null; public override bool HandleMouseInput => receptor == null; + public IClock AudioClock { get; set; } + private Receptor receptor; public Receptor GetReceptor() diff --git a/osu.Game/Screens/Play/KeyCounterMemento.cs b/osu.Game/Screens/Play/KeyCounterMemento.cs new file mode 100644 index 0000000000..daf217cb62 --- /dev/null +++ b/osu.Game/Screens/Play/KeyCounterMemento.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Screens.Play +{ + public class KeyCounterMemento + { + public KeyCounterMemento(double currentTime, int countPresses) + { + CurrentTime = currentTime; + CountPresses = countPresses; + } + + public double CurrentTime { get; } + public int CountPresses { get; } + } +} From 0632c59e604449e197fb5b13acf88bd4ee88c3d9 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 22 Jul 2018 17:35:42 +0300 Subject: [PATCH 02/59] Save KeyCounter state when keypress happens --- osu.Game/Screens/Play/KeyCounter.cs | 6 ++++++ osu.Game/Screens/Play/KeyCounterCollection.cs | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 01f1d6dafd..99685c238f 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,6 +16,8 @@ namespace osu.Game.Screens.Play { public abstract class KeyCounter : Container { + public event Action KeyPressed; + private Sprite buttonSprite; private Sprite glowSprite; private Container textLayer; @@ -46,7 +49,10 @@ protected set isLit = value; updateGlowSprite(value); if (value && IsCounting) + { CountPresses++; + KeyPressed?.Invoke(); + } } } } diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 5f1e502cf7..e472e8d9c9 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -22,6 +23,8 @@ public class KeyCounterCollection : FillFlowContainer public readonly Bindable Visible = new Bindable(true); private readonly Bindable configVisibility = new Bindable(); + private readonly Dictionary> keyCountersState = new Dictionary>(); + public KeyCounterCollection() { Direction = FillDirection.Horizontal; @@ -38,6 +41,9 @@ public override void Add(KeyCounter key) key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; key.AudioClock = AudioClock; + + keyCountersState.Add(key.Name, new List()); + key.KeyPressed += () => keyCountersState[key.Name].Add(key.SaveState()); } public void ResetCount() From 1d9bf420821bb33d39873d51ab3ad60a8a8ab856 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 22 Jul 2018 18:38:10 +0300 Subject: [PATCH 03/59] Fix clock assigning during KeyCounterCollection creation --- osu.Game/Screens/Play/HUDOverlay.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index c6a411c0bb..b813fb7cba 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -68,7 +68,7 @@ public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContain Direction = FillDirection.Vertical, Children = new Drawable[] { - KeyCounter = CreateKeyCounter(), + KeyCounter = CreateKeyCounter(offsetClock), HoldToQuit = CreateQuitButton(), } } @@ -79,7 +79,7 @@ public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContain BindRulesetContainer(rulesetContainer); Progress.Objects = rulesetContainer.Objects; - Progress.AudioClock = KeyCounter.AudioClock = offsetClock; + Progress.AudioClock = offsetClock; Progress.AllowSeeking = rulesetContainer.HasReplayLoaded; Progress.OnSeek = pos => adjustableClock.Seek(pos); @@ -193,12 +193,13 @@ protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) Margin = new MarginPadding { Top = 20 } }; - protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection + protected virtual KeyCounterCollection CreateKeyCounter(IClock offsetClock) => new KeyCounterCollection { FadeTime = 50, Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding(10), + AudioClock = offsetClock }; protected virtual ScoreCounter CreateScoreCounter() => new ScoreCounter(6) From 7f3ad37edec8eb9df2fc4e8338fac0612b2c1ad8 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 22 Jul 2018 19:42:18 +0300 Subject: [PATCH 04/59] Restore keycounter state on replay seek --- osu.Game/Screens/Play/HUDOverlay.cs | 8 ++++++-- osu.Game/Screens/Play/KeyCounterCollection.cs | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index b813fb7cba..7fc4d637e0 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -68,7 +68,7 @@ public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContain Direction = FillDirection.Vertical, Children = new Drawable[] { - KeyCounter = CreateKeyCounter(offsetClock), + KeyCounter = CreateKeyCounter(adjustableClock), HoldToQuit = CreateQuitButton(), } } @@ -81,7 +81,11 @@ public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContain Progress.Objects = rulesetContainer.Objects; Progress.AudioClock = offsetClock; Progress.AllowSeeking = rulesetContainer.HasReplayLoaded; - Progress.OnSeek = pos => adjustableClock.Seek(pos); + Progress.OnSeek = pos => + { + adjustableClock.Seek(pos); + KeyCounter.RestoreKeyCounterState(pos); + }; ModDisplay.Current.BindTo(working.Mods); diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index e472e8d9c9..8ee3e97e54 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -46,6 +46,15 @@ public override void Add(KeyCounter key) key.KeyPressed += () => keyCountersState[key.Name].Add(key.SaveState()); } + public void RestoreKeyCounterState(double time) + { + foreach (var counter in Children) + { + var targetState = keyCountersState[counter.Name].LastOrDefault(state => state.CurrentTime <= time); + counter.RestoreState(targetState); + } + } + public void ResetCount() { foreach (var counter in Children) From ecd51d70f991bd204728c3a392ab4217c79af094 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 22 Jul 2018 23:13:06 +0300 Subject: [PATCH 05/59] Rename Memento class --- osu.Game/Screens/Play/KeyCounter.cs | 4 ++-- osu.Game/Screens/Play/KeyCounterCollection.cs | 6 +++--- osu.Game/Screens/Play/KeyCounterMemento.cs | 17 ----------------- osu.Game/Screens/Play/KeyCounterState.cs | 17 +++++++++++++++++ 4 files changed, 22 insertions(+), 22 deletions(-) delete mode 100644 osu.Game/Screens/Play/KeyCounterMemento.cs create mode 100644 osu.Game/Screens/Play/KeyCounterState.cs diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 99685c238f..7e9c04110c 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -139,8 +139,8 @@ private void updateGlowSprite(bool show) public void ResetCount() => CountPresses = 0; - public KeyCounterMemento SaveState() => new KeyCounterMemento(AudioClock.CurrentTime, CountPresses); + public KeyCounterState SaveState() => new KeyCounterState(AudioClock.CurrentTime, CountPresses); - public void RestoreState(KeyCounterMemento memento) => CountPresses = memento.CountPresses; + public void RestoreState(KeyCounterState state) => CountPresses = state.Count; } } diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 8978181ce4..cdb42ec514 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -24,7 +24,7 @@ public class KeyCounterCollection : FillFlowContainer public readonly Bindable Visible = new Bindable(true); private readonly Bindable configVisibility = new Bindable(); - private readonly Dictionary> keyCountersState = new Dictionary>(); + private readonly Dictionary> keyCountersState = new Dictionary>(); public KeyCounterCollection() { @@ -43,7 +43,7 @@ public override void Add(KeyCounter key) key.KeyUpTextColor = KeyUpTextColor; key.AudioClock = AudioClock; - keyCountersState.Add(key.Name, new List()); + keyCountersState.Add(key.Name, new List()); key.KeyPressed += () => keyCountersState[key.Name].Add(key.SaveState()); } @@ -51,7 +51,7 @@ public void RestoreKeyCounterState(double time) { foreach (var counter in Children) { - var targetState = keyCountersState[counter.Name].LastOrDefault(state => state.CurrentTime <= time); + var targetState = keyCountersState[counter.Name].LastOrDefault(state => state.Time <= time); counter.RestoreState(targetState); } } diff --git a/osu.Game/Screens/Play/KeyCounterMemento.cs b/osu.Game/Screens/Play/KeyCounterMemento.cs deleted file mode 100644 index daf217cb62..0000000000 --- a/osu.Game/Screens/Play/KeyCounterMemento.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Screens.Play -{ - public class KeyCounterMemento - { - public KeyCounterMemento(double currentTime, int countPresses) - { - CurrentTime = currentTime; - CountPresses = countPresses; - } - - public double CurrentTime { get; } - public int CountPresses { get; } - } -} diff --git a/osu.Game/Screens/Play/KeyCounterState.cs b/osu.Game/Screens/Play/KeyCounterState.cs new file mode 100644 index 0000000000..e5c0703319 --- /dev/null +++ b/osu.Game/Screens/Play/KeyCounterState.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Screens.Play +{ + public class KeyCounterState + { + public KeyCounterState(double time, int count) + { + Time = time; + Count = count; + } + + public readonly double Time; + public readonly int Count; + } +} From 332ad5bb67df65bce9dac3fe2aed748e11b8e112 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 22 Jul 2018 23:58:21 +0300 Subject: [PATCH 06/59] Move states to KeyCounter --- osu.Game/Screens/Play/KeyCounter.cs | 24 ++++++++++++++----- osu.Game/Screens/Play/KeyCounterCollection.cs | 15 +++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 7e9c04110c..f5d218b4cf 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,7 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,13 +17,13 @@ namespace osu.Game.Screens.Play { public abstract class KeyCounter : Container { - public event Action KeyPressed; - private Sprite buttonSprite; private Sprite glowSprite; private Container textLayer; private SpriteText countSpriteText; + private readonly List states = new List(); + public bool IsCounting { get; set; } = true; private int countPresses; public int CountPresses @@ -51,7 +52,7 @@ protected set if (value && IsCounting) { CountPresses++; - KeyPressed?.Invoke(); + SaveState(); } } } @@ -139,8 +140,19 @@ private void updateGlowSprite(bool show) public void ResetCount() => CountPresses = 0; - public KeyCounterState SaveState() => new KeyCounterState(AudioClock.CurrentTime, CountPresses); + public void SaveState() + { + var lastState = states.LastOrDefault(); - public void RestoreState(KeyCounterState state) => CountPresses = state.Count; + if (lastState == null || lastState.Time < AudioClock.CurrentTime) + states.Add(new KeyCounterState(AudioClock.CurrentTime, CountPresses)); + } + + public void RestoreState(double time) + { + var targetState = states.LastOrDefault(state => state.Time <= time) ?? states.LastOrDefault(); + var targetCount = targetState?.Count ?? 0; + CountPresses = targetCount; + } } } diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index cdb42ec514..c4974dbaa8 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -2,18 +2,17 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Timing; -using OpenTK.Graphics; using osu.Framework.Input.EventArgs; using osu.Framework.Input.States; +using osu.Framework.Timing; using osu.Game.Configuration; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Screens.Play { @@ -24,8 +23,6 @@ public class KeyCounterCollection : FillFlowContainer public readonly Bindable Visible = new Bindable(true); private readonly Bindable configVisibility = new Bindable(); - private readonly Dictionary> keyCountersState = new Dictionary>(); - public KeyCounterCollection() { Direction = FillDirection.Horizontal; @@ -42,18 +39,12 @@ public override void Add(KeyCounter key) key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; key.AudioClock = AudioClock; - - keyCountersState.Add(key.Name, new List()); - key.KeyPressed += () => keyCountersState[key.Name].Add(key.SaveState()); } public void RestoreKeyCounterState(double time) { foreach (var counter in Children) - { - var targetState = keyCountersState[counter.Name].LastOrDefault(state => state.Time <= time); - counter.RestoreState(targetState); - } + counter.RestoreState(time); } public void ResetCount() From 1e6220e3c0a066457d54f1ad52e0c94b2be92b3d Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 28 Jul 2018 13:22:52 +0300 Subject: [PATCH 07/59] Call KeyCounter.RestoreState itself --- osu.Game/Screens/Play/HUDOverlay.cs | 6 +----- osu.Game/Screens/Play/KeyCounter.cs | 16 ++++++++++------ osu.Game/Screens/Play/KeyCounterCollection.cs | 8 +------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 6fce7c9a70..0187a21d01 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -82,11 +82,7 @@ public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContain Progress.Objects = rulesetContainer.Objects; Progress.AudioClock = offsetClock; Progress.AllowSeeking = rulesetContainer.HasReplayLoaded; - Progress.OnSeek = pos => - { - adjustableClock.Seek(pos); - KeyCounter.RestoreKeyCounterState(pos); - }; + Progress.OnSeek = pos => adjustableClock.Seek(pos); ModDisplay.Current.BindTo(working.Mods); diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index f5d218b4cf..031fe11f88 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Timing; using osu.Game.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; @@ -23,6 +22,7 @@ public abstract class KeyCounter : Container private SpriteText countSpriteText; private readonly List states = new List(); + private KeyCounterState lastState; public bool IsCounting { get; set; } = true; private int countPresses; @@ -63,8 +63,6 @@ protected set public Color4 KeyUpTextColor { get; set; } = Color4.White; public int FadeTime { get; set; } - public IClock AudioClock { get; set; } - protected KeyCounter(string name) { Name = name; @@ -142,10 +140,16 @@ private void updateGlowSprite(bool show) public void SaveState() { - var lastState = states.LastOrDefault(); + if (lastState == null || lastState.Time < Clock.CurrentTime) + states.Add(lastState = new KeyCounterState(Clock.CurrentTime, CountPresses)); + } - if (lastState == null || lastState.Time < AudioClock.CurrentTime) - states.Add(new KeyCounterState(AudioClock.CurrentTime, CountPresses)); + protected override void Update() + { + base.Update(); + + if (lastState?.Time > Clock.CurrentTime) + RestoreState(Clock.CurrentTime); } public void RestoreState(double time) diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index c4974dbaa8..2a5ecd474d 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -38,13 +38,7 @@ public override void Add(KeyCounter key) key.FadeTime = FadeTime; key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; - key.AudioClock = AudioClock; - } - - public void RestoreKeyCounterState(double time) - { - foreach (var counter in Children) - counter.RestoreState(time); + key.Clock = (IFrameBasedClock)AudioClock; } public void ResetCount() From 8bb83a8fd982cf3a4c4708ae8e4a98c2c413f7b2 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 28 Jul 2018 22:16:14 +0300 Subject: [PATCH 08/59] Fix nullref in KeyCounterCollection --- osu.Game/Screens/Play/KeyCounterCollection.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 2a5ecd474d..f701c468e9 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -38,7 +38,8 @@ public override void Add(KeyCounter key) key.FadeTime = FadeTime; key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; - key.Clock = (IFrameBasedClock)AudioClock; + if (AudioClock != null && AudioClock is IFrameBasedClock basedClock) + key.Clock = basedClock; } public void ResetCount() From 3134e14b37b3d177f254accd935c26c0122730ec Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 28 Jul 2018 23:24:03 +0300 Subject: [PATCH 09/59] Test KeyCounter.RestoreState --- osu.Game.Tests/Visual/TestCaseKeyCounter.cs | 29 ++++++++++++++++++++- osu.Game/Screens/Play/KeyCounter.cs | 7 +---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs index b98875cd6a..931c62a64a 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs @@ -3,7 +3,9 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Input.EventArgs; using osu.Framework.MathUtils; +using osu.Framework.Timing; using osu.Game.Screens.Play; using OpenTK.Input; @@ -12,15 +14,18 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseKeyCounter : OsuTestCase { + private const Key rewind_test_key = Key.Z; + public TestCaseKeyCounter() { + KeyCounterKeyboard rewindTestKeyCounterKeyboard; KeyCounterCollection kc = new KeyCounterCollection { Origin = Anchor.Centre, Anchor = Anchor.Centre, Children = new KeyCounter[] { - new KeyCounterKeyboard(Key.Z), + rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(rewind_test_key), new KeyCounterKeyboard(Key.X), new KeyCounterMouse(MouseButton.Left), new KeyCounterMouse(MouseButton.Right), @@ -34,6 +39,28 @@ public TestCaseKeyCounter() }); AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v); + var expectedCountPresses = rewindTestKeyCounterKeyboard.CountPresses + 1; + AddStep($"Press {rewind_test_key} key", () => + { + rewindTestKeyCounterKeyboard.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = rewind_test_key, Repeat = false }); + rewindTestKeyCounterKeyboard.TriggerOnKeyUp(null, new KeyUpEventArgs { Key = rewind_test_key }); + }); + + AddAssert($"Check {rewind_test_key} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == expectedCountPresses); + + IFrameBasedClock counterClock = null; + AddStep($"Rewind {rewind_test_key} counter", () => + { + counterClock = rewindTestKeyCounterKeyboard.Clock; + rewindTestKeyCounterKeyboard.Clock = new DecoupleableInterpolatingFramedClock(); + }); + + AddAssert($"Check {rewind_test_key} counter after rewind", () => + { + rewindTestKeyCounterKeyboard.Clock = counterClock; + return rewindTestKeyCounterKeyboard.CountPresses == 0; + }); + Add(kc); } } diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 031fe11f88..cb9ff28aff 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -152,11 +152,6 @@ protected override void Update() RestoreState(Clock.CurrentTime); } - public void RestoreState(double time) - { - var targetState = states.LastOrDefault(state => state.Time <= time) ?? states.LastOrDefault(); - var targetCount = targetState?.Count ?? 0; - CountPresses = targetCount; - } + public void RestoreState(double time) => CountPresses = states.LastOrDefault(state => state.Time <= time)?.Count ?? 0; } } From 23a37d06cf7ef515d8af336d12812c4fa089567a Mon Sep 17 00:00:00 2001 From: miterosan Date: Mon, 30 Jul 2018 11:34:20 +0200 Subject: [PATCH 10/59] Implement the arrange mod. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 56 +++++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + 2 files changed, 57 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs new file mode 100644 index 0000000000..78f956416a --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using OpenTK; + +namespace osu.Game.Rulesets.Osu.Mods +{ + internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects + { + public override string Name => "Arrange"; + public override string ShortenedName => "Arrange"; + public override FontAwesome Icon => FontAwesome.fa_arrows; + public override ModType Type => ModType.DifficultyIncrease; + public override string Description => "Everything rotates. EVERYTHING"; + public override bool Ranked => true; + public override double ScoreMultiplier => 1.05; + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + drawables.ForEach(drawable => drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState); + } + + private float theta = 0; + + private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) + { + var hitObject = (OsuHitObject) drawable.HitObject; + + Vector2 origPos; + + if (hitObject is RepeatPoint rp) + { + return; + } + else + { + origPos = drawable.Position; + } + + using (drawable.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimeFadeIn - 1000, true)) + { + drawable + .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * 250) + .MoveTo(origPos, hitObject.TimeFadeIn + 1000, Easing.InOutSine); + } + + if (hitObject is HitCircle || hitObject is Slider) + theta += 0.4f; + } + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index b8ba1e2945..0d4d75d8d5 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -103,6 +103,7 @@ public override IEnumerable GetModsFor(ModType type) new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), new OsuModHidden(), new OsuModFlashlight(), + new OsuModArrange(), }; case ModType.Special: return new Mod[] From 4d306ef837884ea75337a5ea80e68e50e8e1a6be Mon Sep 17 00:00:00 2001 From: miterosan Date: Mon, 30 Jul 2018 11:39:21 +0200 Subject: [PATCH 11/59] Add comments and clean up code. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 78f956416a..b322169e76 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -31,24 +31,23 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS { var hitObject = (OsuHitObject) drawable.HitObject; - Vector2 origPos; - - if (hitObject is RepeatPoint rp) - { + // repeat points get their position data from the slider. + if (hitObject is RepeatPoint) return; - } - else - { - origPos = drawable.Position; - } - using (drawable.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimeFadeIn - 1000, true)) + Vector2 originalPosition = drawable.Position; + + // avoiding that the player can see the abroupt move. + const int pre_time_offset = 1000; + + using (drawable.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimeFadeIn - pre_time_offset, true)) { drawable .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * 250) - .MoveTo(origPos, hitObject.TimeFadeIn + 1000, Easing.InOutSine); + .MoveTo(originalPosition, hitObject.TimeFadeIn + pre_time_offset, Easing.InOutSine); } + // That way slider ticks come all from the same direction. if (hitObject is HitCircle || hitObject is Slider) theta += 0.4f; } From 5bb12b574b2ff0e8344ff5dfd878b37c95876ec2 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sat, 4 Aug 2018 00:26:06 +0200 Subject: [PATCH 12/59] The arrange mod is not ranked I think. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index b322169e76..634f2ed653 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -17,7 +17,6 @@ internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects public override FontAwesome Icon => FontAwesome.fa_arrows; public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Everything rotates. EVERYTHING"; - public override bool Ranked => true; public override double ScoreMultiplier => 1.05; public void ApplyToDrawableHitObjects(IEnumerable drawables) From 67c64ac4599bb9e75d955be105a69c8bbb29b5da Mon Sep 17 00:00:00 2001 From: miterosan Date: Sat, 4 Aug 2018 00:26:26 +0200 Subject: [PATCH 13/59] Put the arrange mod into the fun section. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 634f2ed653..df5495cf00 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -15,7 +15,7 @@ internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects public override string Name => "Arrange"; public override string ShortenedName => "Arrange"; public override FontAwesome Icon => FontAwesome.fa_arrows; - public override ModType Type => ModType.DifficultyIncrease; + public override ModType Type => ModType.Fun; public override string Description => "Everything rotates. EVERYTHING"; public override double ScoreMultiplier => 1.05; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index cac9b2db52..6d44d4993c 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -104,7 +104,6 @@ public override IEnumerable GetModsFor(ModType type) new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), new OsuModHidden(), new OsuModFlashlight(), - new OsuModArrange(), }; case ModType.Conversion: return new Mod[] @@ -118,6 +117,10 @@ public override IEnumerable GetModsFor(ModType type) new OsuModRelax(), new OsuModAutopilot(), }; + case ModType.Fun: + return new Mod[] { + new OsuModArrange(), + }; default: return new Mod[] { }; } From 159ce8e93e970478724c2de4a82dff613f1add5c Mon Sep 17 00:00:00 2001 From: miterosan Date: Sat, 4 Aug 2018 00:29:32 +0200 Subject: [PATCH 14/59] Add license header --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index df5495cf00..f7756831ac 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; From 25791b631784c386387d44b0a0f1d48ebff44ec3 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sat, 4 Aug 2018 00:30:46 +0200 Subject: [PATCH 15/59] remove space. --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 6d44d4993c..c80ecbf6df 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -117,7 +117,7 @@ public override IEnumerable GetModsFor(ModType type) new OsuModRelax(), new OsuModAutopilot(), }; - case ModType.Fun: + case ModType.Fun: return new Mod[] { new OsuModArrange(), }; From 546bdf061850b4a0ab38b915e4b1d9788223593a Mon Sep 17 00:00:00 2001 From: miterosan Date: Sat, 4 Aug 2018 00:36:59 +0200 Subject: [PATCH 16/59] remove default value init .-. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index f7756831ac..d319433b5c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -27,7 +27,7 @@ public void ApplyToDrawableHitObjects(IEnumerable drawables) drawables.ForEach(drawable => drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState); } - private float theta = 0; + private float theta; private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) { From f02d1f9013720196f4613d0307a729c5e7aabfb0 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 5 Aug 2018 15:10:42 +0200 Subject: [PATCH 17/59] move the 250 appear disance to a const var. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index d319433b5c..4a93067128 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -41,12 +41,13 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS // avoiding that the player can see the abroupt move. const int pre_time_offset = 1000; + const float appearDistance = 250; using (drawable.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimeFadeIn - pre_time_offset, true)) { drawable - .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * 250) .MoveTo(originalPosition, hitObject.TimeFadeIn + pre_time_offset, Easing.InOutSine); + .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance) } // That way slider ticks come all from the same direction. From 876d410fa1bece8a373c99b95d7fc148223c9a30 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 5 Aug 2018 15:13:04 +0200 Subject: [PATCH 18/59] Add missing ; --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 4a93067128..dec7d386d3 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -47,7 +47,7 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS { drawable .MoveTo(originalPosition, hitObject.TimeFadeIn + pre_time_offset, Easing.InOutSine); - .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance) + .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance); } // That way slider ticks come all from the same direction. From d32ffc1ebcd3fb2304ae1b1128fbcf7ba00a90fb Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 5 Aug 2018 15:14:52 +0200 Subject: [PATCH 19/59] Swtich order of the moveto and the movetooffset. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index dec7d386d3..464486884b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -46,8 +46,9 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS using (drawable.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimeFadeIn - pre_time_offset, true)) { drawable + .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance) .MoveTo(originalPosition, hitObject.TimeFadeIn + pre_time_offset, Easing.InOutSine); - .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance); + } // That way slider ticks come all from the same direction. From 7653ce80cd3b7c17d85dcc261ecf563b1791706a Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 5 Aug 2018 15:16:10 +0200 Subject: [PATCH 20/59] add a period after EVERYTHING --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 464486884b..7fae89f3dc 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -19,8 +19,8 @@ internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects public override string ShortenedName => "Arrange"; public override FontAwesome Icon => FontAwesome.fa_arrows; public override ModType Type => ModType.Fun; - public override string Description => "Everything rotates. EVERYTHING"; public override double ScoreMultiplier => 1.05; + public override string Description => "Everything rotates. EVERYTHING."; public void ApplyToDrawableHitObjects(IEnumerable drawables) { From 8ad8c2b6d0fc800648ccd95210263aa60541559c Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 5 Aug 2018 15:16:25 +0200 Subject: [PATCH 21/59] Reset the ScoreMultiplier to 1 --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 7fae89f3dc..440da5df4f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -19,8 +19,8 @@ internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects public override string ShortenedName => "Arrange"; public override FontAwesome Icon => FontAwesome.fa_arrows; public override ModType Type => ModType.Fun; - public override double ScoreMultiplier => 1.05; public override string Description => "Everything rotates. EVERYTHING."; + public override double ScoreMultiplier => 1; public void ApplyToDrawableHitObjects(IEnumerable drawables) { From d1ffb7c2d78b2fbce64954d7f8ac8f61c5aafb0d Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 5 Aug 2018 15:38:27 +0200 Subject: [PATCH 22/59] Use timepreempt and put appeartime and move duration into their own vars. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 440da5df4f..dd4bb727a2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -39,15 +39,15 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS Vector2 originalPosition = drawable.Position; - // avoiding that the player can see the abroupt move. - const int pre_time_offset = 1000; - const float appearDistance = 250; + const float appear_distance = 250; + double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; + double moveDuration = hitObject.TimePreempt + 1; - using (drawable.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimeFadeIn - pre_time_offset, true)) + using (drawable.BeginAbsoluteSequence(appearTime, true)) { drawable - .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance) - .MoveTo(originalPosition, hitObject.TimeFadeIn + pre_time_offset, Easing.InOutSine); + .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appear_distance) + .MoveTo(originalPosition, moveDuration, Easing.InOutSine); } From 89a18e4aac47644e61373862ed3492530a80a948 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 5 Aug 2018 15:39:12 +0200 Subject: [PATCH 23/59] remove nl and add comment for -1 and +1 --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index dd4bb727a2..5dabf6bfe1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -40,6 +40,8 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS Vector2 originalPosition = drawable.Position; const float appear_distance = 250; + + //the - 1 and + 1 prevents the hit explosion to appear in the wrong position. double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; double moveDuration = hitObject.TimePreempt + 1; @@ -48,7 +50,6 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS drawable .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appear_distance) .MoveTo(originalPosition, moveDuration, Easing.InOutSine); - } // That way slider ticks come all from the same direction. From 8a9b3f6459324a0af0e1f2ec2c09e51392ef4144 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Wed, 15 Aug 2018 22:18:48 +0300 Subject: [PATCH 24/59] Remove rewinded keycounter states --- osu.Game/Screens/Play/KeyCounter.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index cb9ff28aff..301c25f1fd 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -152,6 +152,15 @@ protected override void Update() RestoreState(Clock.CurrentTime); } - public void RestoreState(double time) => CountPresses = states.LastOrDefault(state => state.Time <= time)?.Count ?? 0; + public void RestoreState(double time) + { + var targetState = states.LastOrDefault(state => state.Time <= time); + var targetIndex = states.IndexOf(targetState); + + states.RemoveRange(targetIndex + 1, states.Count - (targetIndex + 1)); + + lastState = targetState; + CountPresses = targetState?.Count ?? 0; + } } } From d070a3e2d8feca209c46bf33cd791b350076544c Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 22 Aug 2018 20:46:03 +0200 Subject: [PATCH 25/59] Only affect hitcicles, slider and spinner --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 5dabf6bfe1..49e98ea861 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -24,7 +24,13 @@ internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects public void ApplyToDrawableHitObjects(IEnumerable drawables) { - drawables.ForEach(drawable => drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState); + drawables.Where(drawable => ( + drawable is DrawableHitCircle || + drawable is DrawableSlider || + drawable is DrawableSpinner + )).ForEach(drawable => + drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState + ); } private float theta; @@ -33,13 +39,10 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS { var hitObject = (OsuHitObject) drawable.HitObject; - // repeat points get their position data from the slider. - if (hitObject is RepeatPoint) - return; + float appear_distance = (float)hitObject.TimePreempt * 0.5f; Vector2 originalPosition = drawable.Position; - - const float appear_distance = 250; + Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appear_distance; //the - 1 and + 1 prevents the hit explosion to appear in the wrong position. double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; @@ -48,13 +51,11 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS using (drawable.BeginAbsoluteSequence(appearTime, true)) { drawable - .MoveToOffset(new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appear_distance) + .MoveToOffset(appearOffset) .MoveTo(originalPosition, moveDuration, Easing.InOutSine); } - // That way slider ticks come all from the same direction. - if (hitObject is HitCircle || hitObject is Slider) - theta += 0.4f; + theta += 0.4f; } } } From c374755cc88d296e00092e2a36096b2334ce47c4 Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 22 Aug 2018 21:16:45 +0200 Subject: [PATCH 26/59] only affect spinner, hitcircle and slider and nothing else. --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 49e98ea861..83f6e7843e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -22,13 +22,15 @@ internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects public override string Description => "Everything rotates. EVERYTHING."; public override double ScoreMultiplier => 1; + private readonly IReadOnlyList TargetHitObjectTypes = new List() { + typeof(HitCircle), + typeof(Slider), + typeof(Spinner), + }; + public void ApplyToDrawableHitObjects(IEnumerable drawables) { - drawables.Where(drawable => ( - drawable is DrawableHitCircle || - drawable is DrawableSlider || - drawable is DrawableSpinner - )).ForEach(drawable => + drawables.ForEach(drawable => drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState ); } @@ -39,6 +41,9 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS { var hitObject = (OsuHitObject) drawable.HitObject; + if (!TargetHitObjectTypes.Contains(hitObject.GetType())) + return; + float appear_distance = (float)hitObject.TimePreempt * 0.5f; Vector2 originalPosition = drawable.Position; From 173d12c1ec191cfcedc6398b127084720f3d1e5c Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 22 Aug 2018 21:17:18 +0200 Subject: [PATCH 27/59] rename arrange to transform --- osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs index 83f6e7843e..fd227b0285 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs @@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Osu.Mods { internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects { - public override string Name => "Arrange"; - public override string ShortenedName => "Arrange"; + public override string Name => "Transform"; + public override string ShortenedName => "TR"; public override FontAwesome Icon => FontAwesome.fa_arrows; public override ModType Type => ModType.Fun; public override string Description => "Everything rotates. EVERYTHING."; From 5c5191b9c3773e4bedbbc7d3db622bd1db29a811 Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 22 Aug 2018 21:19:28 +0200 Subject: [PATCH 28/59] Rename the mod class to transform. --- .../Mods/{OsuModArrange.cs => OsuModTransform.cs} | 6 +++++- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) rename osu.Game.Rulesets.Osu/Mods/{OsuModArrange.cs => OsuModTransform.cs} (92%) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs similarity index 92% rename from osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs rename to osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index fd227b0285..4b48e1af2c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModArrange.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; @@ -10,10 +11,13 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using OpenTK; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModArrange : Mod, IApplicableToDrawableHitObjects + internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects { public override string Name => "Transform"; public override string ShortenedName => "TR"; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index c80ecbf6df..9e3214530f 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -119,7 +119,7 @@ public override IEnumerable GetModsFor(ModType type) }; case ModType.Fun: return new Mod[] { - new OsuModArrange(), + new OsuModTransform(), }; default: return new Mod[] { }; From 6600f7b30e145d7cac2222655943d9d5961b1e04 Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 22 Aug 2018 21:27:20 +0200 Subject: [PATCH 29/59] correct the namings and styling --- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 4b48e1af2c..6fa4ed434e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -11,9 +11,6 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using OpenTK; -using osu.Game.Rulesets.Osu.UI; -using osu.Game.Rulesets.UI; -using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { @@ -26,7 +23,7 @@ internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects public override string Description => "Everything rotates. EVERYTHING."; public override double ScoreMultiplier => 1; - private readonly IReadOnlyList TargetHitObjectTypes = new List() { + private readonly IReadOnlyList targetHitObjectTypes = new List() { typeof(HitCircle), typeof(Slider), typeof(Spinner), @@ -34,7 +31,7 @@ internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects public void ApplyToDrawableHitObjects(IEnumerable drawables) { - drawables.ForEach(drawable => + drawables.ForEach(drawable => drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState ); } @@ -45,13 +42,13 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS { var hitObject = (OsuHitObject) drawable.HitObject; - if (!TargetHitObjectTypes.Contains(hitObject.GetType())) + if (!targetHitObjectTypes.Contains(hitObject.GetType())) return; - float appear_distance = (float)hitObject.TimePreempt * 0.5f; + float appearDistance = (float)hitObject.TimePreempt * 0.5f; Vector2 originalPosition = drawable.Position; - Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appear_distance; + Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance; //the - 1 and + 1 prevents the hit explosion to appear in the wrong position. double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; From 0a48f8eadd76d7e06ecf97a575aa5a49d0b382fd Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 22 Aug 2018 21:39:59 +0200 Subject: [PATCH 30/59] remove empty object ctar args --- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 6fa4ed434e..e31c7b12f9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -23,7 +23,7 @@ internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects public override string Description => "Everything rotates. EVERYTHING."; public override double ScoreMultiplier => 1; - private readonly IReadOnlyList targetHitObjectTypes = new List() { + private readonly IReadOnlyList targetHitObjectTypes = new List { typeof(HitCircle), typeof(Slider), typeof(Spinner), From 8112a51d5fc1b2e9c4d51c7224562377d7e71f04 Mon Sep 17 00:00:00 2001 From: miterosan Date: Fri, 24 Aug 2018 22:23:27 +0200 Subject: [PATCH 31/59] Only apply the transformation once and make the distance and theta dynamic. --- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 59 ++++++++----------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index e31c7b12f9..e76da68bee 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -22,46 +22,35 @@ internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects public override ModType Type => ModType.Fun; public override string Description => "Everything rotates. EVERYTHING."; public override double ScoreMultiplier => 1; - - private readonly IReadOnlyList targetHitObjectTypes = new List { - typeof(HitCircle), - typeof(Slider), - typeof(Spinner), - }; + private float theta; public void ApplyToDrawableHitObjects(IEnumerable drawables) { - drawables.ForEach(drawable => - drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState - ); - } - - private float theta; - - private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) - { - var hitObject = (OsuHitObject) drawable.HitObject; - - if (!targetHitObjectTypes.Contains(hitObject.GetType())) - return; - - float appearDistance = (float)hitObject.TimePreempt * 0.5f; - - Vector2 originalPosition = drawable.Position; - Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance; - - //the - 1 and + 1 prevents the hit explosion to appear in the wrong position. - double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; - double moveDuration = hitObject.TimePreempt + 1; - - using (drawable.BeginAbsoluteSequence(appearTime, true)) + foreach (var drawable in drawables) { - drawable - .MoveToOffset(appearOffset) - .MoveTo(originalPosition, moveDuration, Easing.InOutSine); - } + var hitObject = (OsuHitObject) drawable.HitObject; - theta += 0.4f; + float appearDistance = (float)(hitObject.TimePreempt - hitObject.TimeFadeIn) / 2; + + Vector2 originalPosition = drawable.Position; + Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance; + + //the - 1 and + 1 prevents the hit explosion to appear in the wrong position. + double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; + double moveDuration = hitObject.TimePreempt + 1; + + using (drawable.BeginAbsoluteSequence(appearTime, true)) + { + drawable + .MoveToOffset(appearOffset) + .MoveTo(originalPosition, moveDuration, Easing.InOutSine); + } + + theta += (float) hitObject.TimeFadeIn / 1000; + } } + + + } } From 8b016f05e6cb18e110de0d1bba636ae5dd360304 Mon Sep 17 00:00:00 2001 From: miterosan Date: Fri, 24 Aug 2018 22:24:57 +0200 Subject: [PATCH 32/59] Remove unessesary nl --- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index e76da68bee..4892ba8dc1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -49,8 +49,5 @@ public void ApplyToDrawableHitObjects(IEnumerable drawables) theta += (float) hitObject.TimeFadeIn / 1000; } } - - - } } From 726a51018915a55a399e67a573e70aa105b33219 Mon Sep 17 00:00:00 2001 From: miterosan Date: Fri, 24 Aug 2018 22:33:14 +0200 Subject: [PATCH 33/59] remove not needed usings --- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 4892ba8dc1..5839d51500 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -2,9 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Linq; using System.Collections.Generic; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; From 4c42d4031440623a7ac1d62a7b2201691df0c6bb Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 5 Sep 2018 21:09:09 +0200 Subject: [PATCH 34/59] Correct the comment from explosion to object --- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 5839d51500..30837d7db9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -33,7 +33,7 @@ public void ApplyToDrawableHitObjects(IEnumerable drawables) Vector2 originalPosition = drawable.Position; Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance; - //the - 1 and + 1 prevents the hit explosion to appear in the wrong position. + //the - 1 and + 1 prevents the hit objects to appear in the wrong position. double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; double moveDuration = hitObject.TimePreempt + 1; From 7a1fdd9dc8a146ffdb951c6588c001ede4d0c11e Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 6 Sep 2018 01:01:36 +0300 Subject: [PATCH 35/59] Reset KeyCounter if targetState was not found --- osu.Game/Screens/Play/KeyCounter.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 301c25f1fd..0771cc614c 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -136,7 +136,11 @@ private void updateGlowSprite(bool show) } } - public void ResetCount() => CountPresses = 0; + public void ResetCount() + { + CountPresses = 0; + states.Clear(); + } public void SaveState() { @@ -155,6 +159,12 @@ protected override void Update() public void RestoreState(double time) { var targetState = states.LastOrDefault(state => state.Time <= time); + if (targetState == null) + { + ResetCount(); + return; + } + var targetIndex = states.IndexOf(targetState); states.RemoveRange(targetIndex + 1, states.Count - (targetIndex + 1)); From dae54d252df331bd7a0dd026235e0b4035bdff54 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 7 Sep 2018 21:35:32 +0300 Subject: [PATCH 36/59] Remove redundant checks in RestoreState --- osu.Game/Screens/Play/KeyCounter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 0771cc614c..0f621e6bb3 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -170,7 +170,7 @@ public void RestoreState(double time) states.RemoveRange(targetIndex + 1, states.Count - (targetIndex + 1)); lastState = targetState; - CountPresses = targetState?.Count ?? 0; + CountPresses = targetState.Count; } } } From 125b569ccbf06ee2d488879812b761e999d58c87 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 7 Sep 2018 21:39:41 +0300 Subject: [PATCH 37/59] Change AudioClock type to IFrameBasedClock and comment its usage --- osu.Game/Screens/Play/HUDOverlay.cs | 4 ++-- osu.Game/Screens/Play/KeyCounterCollection.cs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 0187a21d01..eb137f5447 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -69,7 +69,7 @@ public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContain Direction = FillDirection.Vertical, Children = new Drawable[] { - KeyCounter = CreateKeyCounter(adjustableClock), + KeyCounter = CreateKeyCounter(adjustableClock as IFrameBasedClock), HoldToQuit = CreateQuitButton(), } } @@ -194,7 +194,7 @@ protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) Margin = new MarginPadding { Top = 20 } }; - protected virtual KeyCounterCollection CreateKeyCounter(IClock offsetClock) => new KeyCounterCollection + protected virtual KeyCounterCollection CreateKeyCounter(IFrameBasedClock offsetClock) => new KeyCounterCollection { FadeTime = 50, Anchor = Anchor.BottomRight, diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index f701c468e9..2a737d974b 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -38,8 +38,9 @@ public override void Add(KeyCounter key) key.FadeTime = FadeTime; key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; - if (AudioClock != null && AudioClock is IFrameBasedClock basedClock) - key.Clock = basedClock; + // Use the same clock object as SongProgress for saving KeyCounter state + if (AudioClock != null) + key.Clock = AudioClock; } public void ResetCount() @@ -121,7 +122,7 @@ public Color4 KeyUpTextColor public override bool HandleKeyboardInput => receptor == null; public override bool HandleMouseInput => receptor == null; - public IClock AudioClock { get; set; } + public IFrameBasedClock AudioClock { get; set; } private Receptor receptor; From 55372496d117463c11e8e79043e0f1f1c6580956 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Sep 2018 22:37:15 +0900 Subject: [PATCH 38/59] Fix thread-safety of queued events list in ArchiveModelManager --- osu.Game/Database/ArchiveModelManager.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index e9fe943f15..f4f169f27c 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -59,7 +59,7 @@ public abstract class ArchiveModelManager : ICanAcceptFiles // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) private ArchiveImportIPCChannel ipc; - private readonly List cachedEvents = new List(); + private readonly List queuedEvents = new List(); /// /// Allows delaying of outwards events until an operation is confirmed (at a database level). @@ -77,20 +77,26 @@ public abstract class ArchiveModelManager : ICanAcceptFiles /// Whether the flushed events should be performed. private void flushEvents(bool perform) { + Action[] events; + lock (queuedEvents) + { + events = queuedEvents.ToArray(); + queuedEvents.Clear(); + } + if (perform) { - foreach (var a in cachedEvents) + foreach (var a in events) a.Invoke(); } - cachedEvents.Clear(); delayingEvents = false; } private void handleEvent(Action a) { if (delayingEvents) - cachedEvents.Add(a); + lock (queuedEvents) queuedEvents.Add(a); else a.Invoke(); } From 9b0954ab81a162971103867b0d967539a53d7215 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Sep 2018 11:28:02 +0900 Subject: [PATCH 39/59] Reference whether texture is available rather than disposed --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index a2b44aab52..e0a22460ef 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -135,7 +135,7 @@ public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset) public bool BackgroundLoaded => background.IsResultAvailable; public Texture Background => background.Value; - protected virtual bool BackgroundStillValid(Texture b) => b == null || !b.IsDisposed; + protected virtual bool BackgroundStillValid(Texture b) => b == null || b.Available; protected abstract Texture GetBackground(); private readonly RecyclableLazy background; From 02313c6d6edeab0350cc22785bcb54220f6bdefa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Sep 2018 13:10:34 +0900 Subject: [PATCH 40/59] Wait longer before confirming test players are cleaned up --- osu.Game/Tests/Visual/TestCasePlayer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 9afb1dd6cd..9e499cb961 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -54,7 +54,7 @@ private void load(RulesetStore rulesets) AddStep(r.Name, () => p = loadPlayerFor(r)); AddUntilStep(() => ContinueCondition(p)); - AddAssert("no leaked beatmaps", () => + AddUntilStep(() => { p = null; @@ -64,9 +64,9 @@ private void load(RulesetStore rulesets) workingWeakReferences.ForEachAlive(_ => count++); return count == 1; - }); + }, "no leaked beatmaps"); - AddAssert("no leaked players", () => + AddUntilStep(() => { GC.Collect(); GC.WaitForPendingFinalizers(); @@ -74,7 +74,7 @@ private void load(RulesetStore rulesets) playerWeakReferences.ForEachAlive(_ => count++); return count == 1; - }); + }, "no leaked players"); } } } From 356a60b56181fdb5e2c8414bf90fc620a7aed869 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Sep 2018 15:09:10 +0900 Subject: [PATCH 41/59] Fix hitobjects in scrolling rulesets getting masked away --- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 7e3e955740..a274d9b12f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -7,6 +7,8 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.TypeExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Primitives; using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; @@ -165,6 +167,14 @@ protected override void Update() } } + public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) + { + if (!AllJudged) + return false; + + return base.UpdateSubTreeMasking(source, maskingBounds); + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); From a3c3bfb1a8628e574611c4dcf3d81c8d8d8286ba Mon Sep 17 00:00:00 2001 From: Hanamuke Date: Wed, 12 Sep 2018 19:48:35 +0200 Subject: [PATCH 42/59] Fixes hyperdash computation (for nested objects) --- .../Beatmaps/CatchBeatmapProcessor.cs | 45 ++++++++++--------- .../Objects/CatchHitObject.cs | 4 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index ab0afb08d7..34bddf425c 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -74,42 +74,43 @@ private void applyPositionOffsets() private void initialiseHyperDash(List objects) { - // todo: add difficulty adjust. - double halfCatcherWidth = CatcherArea.CATCHER_SIZE * (objects.FirstOrDefault()?.Scale ?? 1) / CatchPlayfield.BASE_WIDTH / 2; + if (objects.Count == 0) + return; + List objectWithDroplets = new List(); + + foreach (var currentObject in objects) + { + if (currentObject is Fruit) + objectWithDroplets.Add(currentObject); + if (currentObject is JuiceStream) + foreach (var currentJuiceElement in currentObject.NestedHitObjects) + if (!(currentJuiceElement is TinyDroplet)) + objectWithDroplets.Add((CatchHitObject)currentJuiceElement); + } + + double halfCatcherWidth = CatcherArea.CATCHER_SIZE * objectWithDroplets[0].Scale / CatchPlayfield.BASE_WIDTH / 2; int lastDirection = 0; double lastExcess = halfCatcherWidth; - int objCount = objects.Count; - - for (int i = 0; i < objCount - 1; i++) + for (int i = 0; i < objectWithDroplets.Count - 1; i++) { - CatchHitObject currentObject = objects[i]; - - // not needed? - // if (currentObject is TinyDroplet) continue; - - CatchHitObject nextObject = objects[i + 1]; - - // while (nextObject is TinyDroplet) - // { - // if (++i == objCount - 1) break; - // nextObject = objects[i + 1]; - // } + CatchHitObject currentObject = objectWithDroplets[i]; + CatchHitObject nextObject = objectWithDroplets[i + 1]; int thisDirection = nextObject.X > currentObject.X ? 1 : -1; - double timeToNext = nextObject.StartTime - ((currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime) - 4; + double timeToNext = nextObject.StartTime - currentObject.StartTime; double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth); - - if (timeToNext * CatcherArea.Catcher.BASE_SPEED < distanceToNext) + float distanceToHyper = (float)(timeToNext * CatcherArea.Catcher.BASE_SPEED - distanceToNext); + if (distanceToHyper < 0) { currentObject.HyperDashTarget = nextObject; lastExcess = halfCatcherWidth; } else { - //currentObject.DistanceToHyperDash = timeToNext - distanceToNext; - lastExcess = MathHelper.Clamp(timeToNext - distanceToNext, 0, halfCatcherWidth); + currentObject.DistanceToHyperDash = distanceToHyper; + lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth); } lastDirection = thisDirection; diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 621fc100c2..5eae4de9e6 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -27,7 +27,9 @@ public abstract class CatchHitObject : HitObject, IHasXPosition, IHasComboInform public int ComboIndex { get; set; } /// - /// The distance for a fruit to to next hyper if it's not a hyper. + /// The difference between the distance of the next object + /// and the distance that would have triggered hyper dashing. + /// A value close to 0 indicates a difficult jump (for SR calculation) /// public float DistanceToHyperDash { get; set; } From 067bc39185149ac34be800fdbefdba7190539356 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Sep 2018 12:47:26 +0900 Subject: [PATCH 43/59] Update nuget package --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3e16e90d06..83ab5534c6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 0be3ba946fdb4f2d02d4b60adf5c2a7231d83de5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Sep 2018 13:40:46 +0900 Subject: [PATCH 44/59] Fix system user attempting to show in profile overlay --- osu.Game/Online/Chat/InfoMessage.cs | 6 +----- osu.Game/Overlays/UserProfileOverlay.cs | 4 +++- osu.Game/Users/User.cs | 9 +++++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Chat/InfoMessage.cs b/osu.Game/Online/Chat/InfoMessage.cs index 2ff901deb1..4e14b097f7 100644 --- a/osu.Game/Online/Chat/InfoMessage.cs +++ b/osu.Game/Online/Chat/InfoMessage.cs @@ -15,11 +15,7 @@ public InfoMessage(string message) : base(infoID--) Timestamp = DateTimeOffset.Now; Content = message; - Sender = new User - { - Username = @"system", - Colour = @"0000ff", - }; + Sender = User.SystemUser; } } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index ea077ff645..f428e8cfc6 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -77,9 +77,11 @@ protected override void PopOut() public void ShowUser(User user, bool fetchOnline = true) { + if (user == User.SystemUser) return; + Show(); - if (user.Id == Header?.User.Id) + if (user.Id == Header?.User?.Id) return; userReq?.Cancel(); diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index f42df4023f..3a90605da7 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -144,5 +144,14 @@ public class RankHistoryData public Badge[] Badges; public override string ToString() => Username; + + /// + /// A user instance for displaying locally created system messages. + /// + public static User SystemUser { get; } = new User + { + Username = "system", + Id = 0 + }; } } From 4341d258af3d9ab94cf95cf20e02c921aa426894 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Sep 2018 14:03:21 +0900 Subject: [PATCH 45/59] Make readonly instead --- osu.Game/Online/Chat/InfoMessage.cs | 2 +- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- osu.Game/Users/User.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Chat/InfoMessage.cs b/osu.Game/Online/Chat/InfoMessage.cs index 4e14b097f7..103a999591 100644 --- a/osu.Game/Online/Chat/InfoMessage.cs +++ b/osu.Game/Online/Chat/InfoMessage.cs @@ -15,7 +15,7 @@ public InfoMessage(string message) : base(infoID--) Timestamp = DateTimeOffset.Now; Content = message; - Sender = User.SystemUser; + Sender = User.SYSTEM_USER; } } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index f428e8cfc6..c106446fe0 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -77,7 +77,7 @@ protected override void PopOut() public void ShowUser(User user, bool fetchOnline = true) { - if (user == User.SystemUser) return; + if (user == User.SYSTEM_USER) return; Show(); diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 3a90605da7..6c3d2bfa63 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -148,7 +148,7 @@ public class RankHistoryData /// /// A user instance for displaying locally created system messages. /// - public static User SystemUser { get; } = new User + public static readonly User SYSTEM_USER = new User { Username = "system", Id = 0 From 7d3380db665fb938c5c9c6992d76eec07a5fa6e7 Mon Sep 17 00:00:00 2001 From: Hanamuke Date: Thu, 13 Sep 2018 17:01:33 +0200 Subject: [PATCH 46/59] Fixed comment. Created static CatchArea.GetCatcheWidth method --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 5 +---- osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs | 6 +++--- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 5 +++++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 34bddf425c..d4be6564ca 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -74,9 +74,6 @@ private void applyPositionOffsets() private void initialiseHyperDash(List objects) { - if (objects.Count == 0) - return; - List objectWithDroplets = new List(); foreach (var currentObject in objects) @@ -89,7 +86,7 @@ private void initialiseHyperDash(List objects) objectWithDroplets.Add((CatchHitObject)currentJuiceElement); } - double halfCatcherWidth = CatcherArea.CATCHER_SIZE * objectWithDroplets[0].Scale / CatchPlayfield.BASE_WIDTH / 2; + double halfCatcherWidth = CatcherArea.GetCatcherSize(Beatmap.BeatmapInfo.BaseDifficulty) / 2; int lastDirection = 0; double lastExcess = halfCatcherWidth; diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 5eae4de9e6..773bf576dd 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -27,9 +27,9 @@ public abstract class CatchHitObject : HitObject, IHasXPosition, IHasComboInform public int ComboIndex { get; set; } /// - /// The difference between the distance of the next object - /// and the distance that would have triggered hyper dashing. - /// A value close to 0 indicates a difficult jump (for SR calculation) + /// Difference between the distance to the next object + /// and the distance that would have triggered a hyper dash. + /// A value close to 0 indicates a difficult jump (for difficulty calculation). /// public float DistanceToHyperDash { get; set; } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 9460512a8d..1662246b62 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -107,6 +107,11 @@ protected override void UpdateAfterChildren() public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj); + public static float GetCatcherSize(BeatmapDifficulty difficulty) + { + return (CATCHER_SIZE / CatchPlayfield.BASE_WIDTH) * (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5); + } + public class Catcher : Container, IKeyBindingHandler { /// From 7e07a07c01004655b812c3a01c1614ccf4d7303c Mon Sep 17 00:00:00 2001 From: Hanamuke Date: Thu, 13 Sep 2018 17:15:46 +0200 Subject: [PATCH 47/59] Fix HitObjects being out of order because of nested objects --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index d4be6564ca..c7ea29f8c0 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -86,6 +86,8 @@ private void initialiseHyperDash(List objects) objectWithDroplets.Add((CatchHitObject)currentJuiceElement); } + objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime)); + double halfCatcherWidth = CatcherArea.GetCatcherSize(Beatmap.BeatmapInfo.BaseDifficulty) / 2; int lastDirection = 0; double lastExcess = halfCatcherWidth; From 9b6f5c90976a41595814aec313d643349a7a8626 Mon Sep 17 00:00:00 2001 From: Hanamuke Date: Thu, 13 Sep 2018 17:29:10 +0200 Subject: [PATCH 48/59] Fix redundant paranthesis --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 1662246b62..be56ccf8c1 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -109,7 +109,7 @@ protected override void UpdateAfterChildren() public static float GetCatcherSize(BeatmapDifficulty difficulty) { - return (CATCHER_SIZE / CatchPlayfield.BASE_WIDTH) * (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5); + return CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5); } public class Catcher : Container, IKeyBindingHandler From b1f6828a1a29e7ccd7004fe15c039c8153cc29a3 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Wed, 5 Sep 2018 20:30:03 +0200 Subject: [PATCH 49/59] Added OsuModWiggle class and adjusted OsuRuleset.cs --- osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 82 ++++++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 5 ++ 2 files changed, 87 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs new file mode 100644 index 0000000000..5e6cb22ec3 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -0,0 +1,82 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using OpenTK; + +namespace osu.Game.Rulesets.Osu.Mods +{ + internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects + { + public override string Name => "Wiggle"; + public override string ShortenedName => "WG"; + public override FontAwesome Icon => FontAwesome.fa_arrows_alt; + public override ModType Type => ModType.Fun; + public override string Description => "They just won't stay still..."; + public override double ScoreMultiplier => 1; + + private readonly int wiggle_delay = 90; // (ms) Higher = fewer wiggles + private readonly int wiggle_strength = 10; // Higher = stronger wiggles + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach(var drawable in drawables) + drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState; + } + + private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) + { + var hitObject = (OsuHitObject)drawable.HitObject; + Vector2 origPos = drawable.Position; + + Random distRand = new Random(hitObject.ComboOffset); + Random angleRand = new Random(hitObject.IndexInCurrentCombo); + + // Wiggle all objects during TimePreempt + int amountWiggles = (int)hitObject.TimePreempt / wiggle_delay; + + for (int i = 0; i < amountWiggles; i++) + { + using (drawable.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt + i * wiggle_delay, true)) + { + float nextAngle = (float)(angleRand.NextDouble() * 2 * Math.PI); + float nextDist = (float)(distRand.NextDouble() * wiggle_strength); + Vector2 wiggledPos = new Vector2((float)(nextDist * Math.Cos(nextAngle) + origPos.X), (float)(nextDist * Math.Sin(nextAngle) + origPos.Y)); + drawable.MoveTo(wiggledPos, wiggle_delay); + } + } + + // Keep wiggling sliders and spinners for their duration + double objDuration; + if (hitObject is Slider slider) + { + objDuration = slider.Duration; + } + else if (hitObject is Spinner spinner) + { + objDuration = spinner.Duration; + } + else + return; + + amountWiggles = (int)(objDuration / wiggle_delay); + + for (int i = 0; i < amountWiggles; i++) + { + using (drawable.BeginAbsoluteSequence(hitObject.StartTime + i * wiggle_delay, true)) + { + float nextAngle = (float)(angleRand.NextDouble() * 2 * Math.PI); + float nextDist = (float)(distRand.NextDouble() * wiggle_strength); + Vector2 wiggledPos = new Vector2((float)(nextDist * Math.Cos(nextAngle) + origPos.X), (float)(nextDist * Math.Sin(nextAngle) + origPos.Y)); + drawable.MoveTo(wiggledPos, wiggle_delay); + } + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index fa6e9a018a..a16f6494e7 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -117,6 +117,11 @@ public override IEnumerable GetModsFor(ModType type) new OsuModRelax(), new OsuModAutopilot(), }; + case ModType.Fun: + return new Mod[] + { + new OsuModWiggle(), + }; default: return new Mod[] { }; } From 9d94aa4e6260cac120abb67f15c43ba6be3367ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Sep 2018 17:38:47 +0900 Subject: [PATCH 50/59] Fix formatting and constants --- osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index 5e6cb22ec3..d03908fef1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -21,12 +21,12 @@ internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects public override string Description => "They just won't stay still..."; public override double ScoreMultiplier => 1; - private readonly int wiggle_delay = 90; // (ms) Higher = fewer wiggles - private readonly int wiggle_strength = 10; // Higher = stronger wiggles - + private const int wiggle_delay = 90; // (ms) Higher = fewer wiggles + private const int wiggle_strength = 10; // Higher = stronger wiggles + public void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach(var drawable in drawables) + foreach (var drawable in drawables) drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState; } @@ -34,7 +34,7 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS { var hitObject = (OsuHitObject)drawable.HitObject; Vector2 origPos = drawable.Position; - + Random distRand = new Random(hitObject.ComboOffset); Random angleRand = new Random(hitObject.IndexInCurrentCombo); From 00daaef27a8885284372fcbd738df89b78454d76 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Sep 2018 17:57:27 +0900 Subject: [PATCH 51/59] Use a slightly more suiting icon --- osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index d03908fef1..46ccfc5a35 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -16,7 +16,7 @@ internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects { public override string Name => "Wiggle"; public override string ShortenedName => "WG"; - public override FontAwesome Icon => FontAwesome.fa_arrows_alt; + public override FontAwesome Icon => FontAwesome.fa_certificate; public override ModType Type => ModType.Fun; public override string Description => "They just won't stay still..."; public override double ScoreMultiplier => 1; From ef31698f5653a82219a5ad3f9d29e86da362caaf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Sep 2018 18:18:40 +0900 Subject: [PATCH 52/59] Further code tidying --- osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 55 ++++++++-------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index 46ccfc5a35..206d7e649f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -7,6 +7,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using OpenTK; @@ -21,7 +22,7 @@ internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects public override string Description => "They just won't stay still..."; public override double ScoreMultiplier => 1; - private const int wiggle_delay = 90; // (ms) Higher = fewer wiggles + private const int wiggle_duration = 90; // (ms) Higher = fewer wiggles private const int wiggle_strength = 10; // Higher = stronger wiggles public void ApplyToDrawableHitObjects(IEnumerable drawables) @@ -32,51 +33,35 @@ public void ApplyToDrawableHitObjects(IEnumerable drawables) private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) { - var hitObject = (OsuHitObject)drawable.HitObject; - Vector2 origPos = drawable.Position; + var osuObject = (OsuHitObject)drawable.HitObject; + Vector2 origin = drawable.Position; - Random distRand = new Random(hitObject.ComboOffset); - Random angleRand = new Random(hitObject.IndexInCurrentCombo); + Random distRand = new Random(osuObject.ComboOffset); + Random angleRand = new Random(osuObject.IndexInCurrentCombo); // Wiggle all objects during TimePreempt - int amountWiggles = (int)hitObject.TimePreempt / wiggle_delay; + int amountWiggles = (int)osuObject.TimePreempt / wiggle_duration; + + void wiggle() + { + float nextAngle = (float)(angleRand.NextDouble() * 2 * Math.PI); + float nextDist = (float)(distRand.NextDouble() * wiggle_strength); + drawable.MoveTo(new Vector2((float)(nextDist * Math.Cos(nextAngle) + origin.X), (float)(nextDist * Math.Sin(nextAngle) + origin.Y)), wiggle_duration); + } for (int i = 0; i < amountWiggles; i++) - { - using (drawable.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt + i * wiggle_delay, true)) - { - float nextAngle = (float)(angleRand.NextDouble() * 2 * Math.PI); - float nextDist = (float)(distRand.NextDouble() * wiggle_strength); - Vector2 wiggledPos = new Vector2((float)(nextDist * Math.Cos(nextAngle) + origPos.X), (float)(nextDist * Math.Sin(nextAngle) + origPos.Y)); - drawable.MoveTo(wiggledPos, wiggle_delay); - } - } + using (drawable.BeginAbsoluteSequence(osuObject.StartTime - osuObject.TimePreempt + i * wiggle_duration, true)) + wiggle(); // Keep wiggling sliders and spinners for their duration - double objDuration; - if (hitObject is Slider slider) - { - objDuration = slider.Duration; - } - else if (hitObject is Spinner spinner) - { - objDuration = spinner.Duration; - } - else + if (!(osuObject is IHasEndTime endTime)) return; - amountWiggles = (int)(objDuration / wiggle_delay); + amountWiggles = (int)(endTime.Duration / wiggle_duration); for (int i = 0; i < amountWiggles; i++) - { - using (drawable.BeginAbsoluteSequence(hitObject.StartTime + i * wiggle_delay, true)) - { - float nextAngle = (float)(angleRand.NextDouble() * 2 * Math.PI); - float nextDist = (float)(distRand.NextDouble() * wiggle_strength); - Vector2 wiggledPos = new Vector2((float)(nextDist * Math.Cos(nextAngle) + origPos.X), (float)(nextDist * Math.Sin(nextAngle) + origPos.Y)); - drawable.MoveTo(wiggledPos, wiggle_delay); - } - } + using (drawable.BeginAbsoluteSequence(osuObject.StartTime + i * wiggle_duration, true)) + wiggle(); } } } From ec6185cd3196776c2eacc120ebcb50e937b175db Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Sep 2018 18:20:19 +0900 Subject: [PATCH 53/59] Reduce random allocations --- osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index 206d7e649f..5b69247451 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -36,16 +36,15 @@ private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedS var osuObject = (OsuHitObject)drawable.HitObject; Vector2 origin = drawable.Position; - Random distRand = new Random(osuObject.ComboOffset); - Random angleRand = new Random(osuObject.IndexInCurrentCombo); + Random objRand = new Random((int)osuObject.StartTime); // Wiggle all objects during TimePreempt int amountWiggles = (int)osuObject.TimePreempt / wiggle_duration; void wiggle() { - float nextAngle = (float)(angleRand.NextDouble() * 2 * Math.PI); - float nextDist = (float)(distRand.NextDouble() * wiggle_strength); + float nextAngle = (float)(objRand.NextDouble() * 2 * Math.PI); + float nextDist = (float)(objRand.NextDouble() * wiggle_strength); drawable.MoveTo(new Vector2((float)(nextDist * Math.Cos(nextAngle) + origin.X), (float)(nextDist * Math.Sin(nextAngle) + origin.Y)), wiggle_duration); } From dd7f667fe3622e77bf3661b8210de806eb9ee2f2 Mon Sep 17 00:00:00 2001 From: Hanamuke Date: Sat, 15 Sep 2018 00:18:42 +0200 Subject: [PATCH 54/59] Disable scrolling speed control for osu!catch --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index d49be69856..d16f5cbb07 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -22,6 +22,7 @@ public class CatchPlayfield : ScrollingPlayfield private readonly CatcherArea catcherArea; + protected override bool UserScrollSpeedAdjustment => false; public CatchPlayfield(BeatmapDifficulty difficulty, Func> getVisualRepresentation) : base(BASE_WIDTH) { From 65b2bceef237f2ea950ec312a5a7a8d51131f0dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Sep 2018 14:51:04 +0900 Subject: [PATCH 55/59] Simplify implementation --- osu.Game/Screens/Play/KeyCounter.cs | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 0f621e6bb3..5652c1b54f 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -22,7 +22,7 @@ public abstract class KeyCounter : Container private SpriteText countSpriteText; private readonly List states = new List(); - private KeyCounterState lastState; + private KeyCounterState currentState; public bool IsCounting { get; set; } = true; private int countPresses; @@ -144,33 +144,24 @@ public void ResetCount() public void SaveState() { - if (lastState == null || lastState.Time < Clock.CurrentTime) - states.Add(lastState = new KeyCounterState(Clock.CurrentTime, CountPresses)); + if (currentState == null || currentState.Time < Clock.CurrentTime) + states.Add(currentState = new KeyCounterState(Clock.CurrentTime, CountPresses)); } protected override void Update() { base.Update(); - if (lastState?.Time > Clock.CurrentTime) - RestoreState(Clock.CurrentTime); + if (currentState?.Time > Clock.CurrentTime) + restoreStateTo(Clock.CurrentTime); } - public void RestoreState(double time) + private void restoreStateTo(double time) { - var targetState = states.LastOrDefault(state => state.Time <= time); - if (targetState == null) - { - ResetCount(); - return; - } + states.RemoveAll(state => state.Time > time); - var targetIndex = states.IndexOf(targetState); - - states.RemoveRange(targetIndex + 1, states.Count - (targetIndex + 1)); - - lastState = targetState; - CountPresses = targetState.Count; + currentState = states.LastOrDefault(); + CountPresses = currentState?.Count ?? 0; } } } From e636cfe79eb537eb77f613ba34e9074be915e6f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Sep 2018 16:24:06 +0900 Subject: [PATCH 56/59] Fix dynamic compilation not working --- osu.Game.Tests/Visual/TestCaseKeyCounter.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs index 931c62a64a..30580a3690 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -14,7 +14,12 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseKeyCounter : OsuTestCase { - private const Key rewind_test_key = Key.Z; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(KeyCounterKeyboard), + typeof(KeyCounterMouse), + typeof(KeyCounterCollection) + }; public TestCaseKeyCounter() { From 7b57439976d6af4def64b08b8753c0340dfab3b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Sep 2018 16:25:37 +0900 Subject: [PATCH 57/59] Add proper testing --- osu.Game.Tests/Visual/TestCaseKeyCounter.cs | 60 ++++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs index 30580a3690..f31a687d2d 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs @@ -1,6 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Input.EventArgs; @@ -30,13 +33,14 @@ public TestCaseKeyCounter() Anchor = Anchor.Centre, Children = new KeyCounter[] { - rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(rewind_test_key), + rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(Key.X), new KeyCounterKeyboard(Key.X), new KeyCounterMouse(MouseButton.Left), new KeyCounterMouse(MouseButton.Right), }, }; + AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); @@ -44,29 +48,57 @@ public TestCaseKeyCounter() }); AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v); - var expectedCountPresses = rewindTestKeyCounterKeyboard.CountPresses + 1; - AddStep($"Press {rewind_test_key} key", () => + Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key; + double time1 = 0; + + AddStep($"Press {testKey} key", () => { - rewindTestKeyCounterKeyboard.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = rewind_test_key, Repeat = false }); - rewindTestKeyCounterKeyboard.TriggerOnKeyUp(null, new KeyUpEventArgs { Key = rewind_test_key }); + rewindTestKeyCounterKeyboard.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = testKey, Repeat = false }); + rewindTestKeyCounterKeyboard.TriggerOnKeyUp(null, new KeyUpEventArgs { Key = testKey }); }); - AddAssert($"Check {rewind_test_key} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == expectedCountPresses); + AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 1); - IFrameBasedClock counterClock = null; - AddStep($"Rewind {rewind_test_key} counter", () => + AddStep($"Press {testKey} key", () => { - counterClock = rewindTestKeyCounterKeyboard.Clock; - rewindTestKeyCounterKeyboard.Clock = new DecoupleableInterpolatingFramedClock(); + rewindTestKeyCounterKeyboard.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = testKey, Repeat = false }); + rewindTestKeyCounterKeyboard.TriggerOnKeyUp(null, new KeyUpEventArgs { Key = testKey }); + time1 = Clock.CurrentTime; }); - AddAssert($"Check {rewind_test_key} counter after rewind", () => + AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 2); + + IFrameBasedClock oldClock = null; + + AddStep($"Rewind {testKey} counter once", () => { - rewindTestKeyCounterKeyboard.Clock = counterClock; - return rewindTestKeyCounterKeyboard.CountPresses == 0; + oldClock = rewindTestKeyCounterKeyboard.Clock; + rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(time1 - 10)); }); + AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 1); + + AddStep($"Rewind {testKey} counter to zero", () => rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(0))); + + AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 0); + + AddStep("Restore clock", () => rewindTestKeyCounterKeyboard.Clock = oldClock); + Add(kc); } + + private class FixedClock : IClock + { + private readonly double time; + + public FixedClock(double time) + { + this.time = time; + } + + public double CurrentTime => time; + public double Rate => 1; + public bool IsRunning => false; + } } } From 79b56cb35ca11bdc81eb93ccab4eb096519ea21f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Sep 2018 16:34:08 +0900 Subject: [PATCH 58/59] Make saveState private --- osu.Game/Screens/Play/KeyCounter.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 5652c1b54f..d1efe4cab7 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -52,7 +52,7 @@ protected set if (value && IsCounting) { CountPresses++; - SaveState(); + saveState(); } } } @@ -142,12 +142,6 @@ public void ResetCount() states.Clear(); } - public void SaveState() - { - if (currentState == null || currentState.Time < Clock.CurrentTime) - states.Add(currentState = new KeyCounterState(Clock.CurrentTime, CountPresses)); - } - protected override void Update() { base.Update(); @@ -156,6 +150,12 @@ protected override void Update() restoreStateTo(Clock.CurrentTime); } + private void saveState() + { + if (currentState == null || currentState.Time < Clock.CurrentTime) + states.Add(currentState = new KeyCounterState(Clock.CurrentTime, CountPresses)); + } + private void restoreStateTo(double time) { states.RemoveAll(state => state.Time > time); From 2d74c088ce70607d55c0193539b1008e8c6bdd56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Sep 2018 17:03:51 +0900 Subject: [PATCH 59/59] Add newline --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index d16f5cbb07..102ec7fb3b 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -23,6 +23,7 @@ public class CatchPlayfield : ScrollingPlayfield private readonly CatcherArea catcherArea; protected override bool UserScrollSpeedAdjustment => false; + public CatchPlayfield(BeatmapDifficulty difficulty, Func> getVisualRepresentation) : base(BASE_WIDTH) {