From 3d8b27abfaa698c7ff8e4ba2b07a3dbb48f7a798 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 8 Sep 2019 16:13:36 +0300 Subject: [PATCH 01/11] RotationAbsolute -> BidirectionalRotation --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 5 +++-- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 3ed3f3e981..5d7acb77bb 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && Time.Current > Spinner.StartTime + Spinner.Duration / 2 && Progress < 1) { // force completion only once to not break human interaction - Disc.RotationAbsolute = Spinner.SpinsRequired * 360; + Disc.BidirectionalRotation = Spinner.SpinsRequired * 360; auto = false; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 49aaa2aaea..c7bcf2526a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => MathHelper.Clamp(Disc.BidirectionalRotation / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { @@ -188,7 +189,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Rotation = Disc.Rotation; Ticks.Rotation = Disc.Rotation; - spmCounter.SetRotation(Disc.RotationAbsolute); + spmCounter.SetRotation(Disc.BidirectionalRotation); float relativeCircleScale = Spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight; Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 448a2eada7..b9d5674b34 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -82,11 +82,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private float lastAngle; private float currentRotation; - public float RotationAbsolute; + public float BidirectionalRotation; private int completeTick; - private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360)); + private bool updateCompleteTick() => completeTick != (completeTick = (int)(BidirectionalRotation / 360)); private bool rotationTransferred; protected override void Update() @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces lastAngle -= 360; currentRotation += thisAngle - lastAngle; - RotationAbsolute += Math.Abs(thisAngle - lastAngle); + BidirectionalRotation += Math.Abs(thisAngle - lastAngle) * Math.Sign(Time.Current - lastTime); } lastAngle = thisAngle; From f5f2713a17c62037786bb0010b2fd3cd480cd97c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 8 Sep 2019 16:14:14 +0300 Subject: [PATCH 02/11] Account angle change negatively on rewind --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index b9d5674b34..5b2b3bcd42 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -85,8 +85,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public float BidirectionalRotation; private int completeTick; + private double lastTime; private bool updateCompleteTick() => completeTick != (completeTick = (int)(BidirectionalRotation / 360)); + private bool rotationTransferred; protected override void Update() @@ -112,6 +114,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces currentRotation += thisAngle - lastAngle; BidirectionalRotation += Math.Abs(thisAngle - lastAngle) * Math.Sign(Time.Current - lastTime); + lastTime = Time.Current; } lastAngle = thisAngle; From 9defcb0e9945785dc4edf44a444a6015f78517f6 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 8 Sep 2019 21:37:50 +0300 Subject: [PATCH 03/11] Remove redundant using directive --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index c7bcf2526a..a8dc275fb5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From c4aee11fe08c60db192388be63cad4287cb70f65 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 9 Sep 2019 15:35:18 +0300 Subject: [PATCH 04/11] Revert renaming changes --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 4 ++-- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 5d7acb77bb..3ed3f3e981 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && Time.Current > Spinner.StartTime + Spinner.Duration / 2 && Progress < 1) { // force completion only once to not break human interaction - Disc.BidirectionalRotation = Spinner.SpinsRequired * 360; + Disc.RotationAbsolute = Spinner.SpinsRequired * 360; auto = false; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index a8dc275fb5..49aaa2aaea 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.BidirectionalRotation / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { @@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Rotation = Disc.Rotation; Ticks.Rotation = Disc.Rotation; - spmCounter.SetRotation(Disc.BidirectionalRotation); + spmCounter.SetRotation(Disc.RotationAbsolute); float relativeCircleScale = Spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight; Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 5b2b3bcd42..2ae420a5e2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -82,12 +82,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private float lastAngle; private float currentRotation; - public float BidirectionalRotation; + public float RotationAbsolute; private int completeTick; private double lastTime; - private bool updateCompleteTick() => completeTick != (completeTick = (int)(BidirectionalRotation / 360)); + private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360)); private bool rotationTransferred; @@ -113,8 +113,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces lastAngle -= 360; currentRotation += thisAngle - lastAngle; - BidirectionalRotation += Math.Abs(thisAngle - lastAngle) * Math.Sign(Time.Current - lastTime); lastTime = Time.Current; + RotationAbsolute += Math.Abs(thisAngle - lastAngle) * Math.Sign(Clock.ElapsedFrameTime); } lastAngle = thisAngle; From aec04dcf904cc1a8ba2f80b6298f82ef3e419b57 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 9 Sep 2019 15:36:20 +0300 Subject: [PATCH 05/11] Use Clock.ElapsedFrameTime instead --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 2ae420a5e2..c45e98cc76 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -85,8 +85,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public float RotationAbsolute; private int completeTick; - private double lastTime; - private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360)); private bool rotationTransferred; @@ -113,7 +111,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces lastAngle -= 360; currentRotation += thisAngle - lastAngle; - lastTime = Time.Current; RotationAbsolute += Math.Abs(thisAngle - lastAngle) * Math.Sign(Clock.ElapsedFrameTime); } From 143d7ab640b588569e5dc31bd0d87f79b8a78401 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 24 Sep 2019 04:53:26 +0300 Subject: [PATCH 06/11] Add test scene for spinner rotation --- .../TestSceneSpinnerRotation.cs | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs new file mode 100644 index 0000000000..e9fa8e46ed --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -0,0 +1,104 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Logging; +using osu.Framework.MathUtils; +using osu.Framework.Testing; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; +using osuTK; +using System.Collections.Generic; +using System.Linq; +using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneSpinnerRotation : TestSceneOsuPlayer + { + [Resolved] + private AudioManager audioManager { get; set; } + + private TrackVirtualManual track; + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + { + var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + track = (TrackVirtualManual)working.Track; + return working; + } + + private DrawableSpinner drawableSpinner; + + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First()); + + // wait for frame stable clock time to hit 0 (for some reason, executing a seek while current time is below 0 doesn't seek successfully) + addSeekStep(0); + } + + [Test] + public void TestSpinnerRewindingRotation() + { + addSeekStep(5000); + AddAssert("is rotation absolute not almost 0", () => !Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, 0, 100)); + + addSeekStep(0); + AddAssert("is rotation absolute almost 0", () => Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, 0, 100)); + } + + [Test] + public void TestSpinnerMiddleRewindingRotation() + { + double estimatedRotation = 0; + + addSeekStep(5000); + AddStep("retrieve rotation", () => estimatedRotation = drawableSpinner.Disc.RotationAbsolute); + + addSeekStep(2500); + addSeekStep(5000); + AddAssert("is rotation absolute almost same", () => Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, estimatedRotation, 100)); + } + + private void addSeekStep(double time) + { + AddStep($"seek to {time}", () => track.Seek(time)); + + AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, ((TestPlayer)Player).DrawableRuleset.FrameStableClock.CurrentTime, 100)); + } + + protected override Player CreatePlayer(Ruleset ruleset) + { + Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); + return new TestPlayer(); + } + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap + { + HitObjects = new List + { + new Spinner + { + Position = new Vector2(256, 192), + EndTime = 5000, + }, + // placeholder object to avoid hitting the results screen + new HitObject + { + StartTime = 99999, + } + } + }; + } +} From ba679684be0aab707d545b111973253d5926f647 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 24 Sep 2019 04:59:57 +0300 Subject: [PATCH 07/11] Trim whitespaces --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index e9fa8e46ed..4b98e84866 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Osu.Tests Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); return new TestPlayer(); } - + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap { HitObjects = new List From 18fd7aa8055a406ceecd242a359a2ec6072dee10 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 24 Sep 2019 05:10:06 +0300 Subject: [PATCH 08/11] Remove redundant using directive --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 4b98e84866..7e792f0b40 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Logging; using osu.Framework.MathUtils; using osu.Framework.Testing; using osu.Framework.Timing; From 186ea9821708da3260601fc9f6c9ba08ad4e49be Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 26 Sep 2019 02:23:18 +0300 Subject: [PATCH 09/11] Wait for track to start running instead --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 7e792f0b40..cd46bc63a9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -41,10 +41,8 @@ namespace osu.Game.Rulesets.Osu.Tests { base.SetUpSteps(); + AddUntilStep("wait for track to start running", () => track.IsRunning); AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First()); - - // wait for frame stable clock time to hit 0 (for some reason, executing a seek while current time is below 0 doesn't seek successfully) - addSeekStep(0); } [Test] From d773f0cce18b7bad01bebd4f593504ae670658cb Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 26 Sep 2019 04:38:20 +0300 Subject: [PATCH 10/11] Override autoplay bool instead of adding it --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index cd46bc63a9..4eb4c21c90 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Osu.Tests private TrackVirtualManual track; + protected override bool Autoplay => true; + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) { var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); @@ -75,12 +77,6 @@ namespace osu.Game.Rulesets.Osu.Tests AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, ((TestPlayer)Player).DrawableRuleset.FrameStableClock.CurrentTime, 100)); } - protected override Player CreatePlayer(Ruleset ruleset) - { - Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); - return new TestPlayer(); - } - protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap { HitObjects = new List From c57868795e08063241810b497ccc072d78972513 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 26 Sep 2019 04:38:57 +0300 Subject: [PATCH 11/11] Remove redundant using directive --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 4eb4c21c90..cded7f0e95 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -11,7 +11,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Screens.Play; using osu.Game.Tests.Visual; using osuTK; using System.Collections.Generic;