From 38e5e35743f372de3be1324d3adf0473f29d8bd1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 01:20:05 +0900 Subject: [PATCH 01/68] modify catch hyperdash behavior --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 62 ++++++++++++++--------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 181536a91e..56826d228c 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -248,37 +248,46 @@ namespace osu.Game.Rulesets.Catch.UI if (validCatch && fruit.HyperDash) { - HyperDashModifier = Math.Abs(fruit.HyperDashTarget.X - fruit.X) / Math.Abs(fruit.HyperDashTarget.StartTime - fruit.StartTime) / BASE_SPEED; - HyperDashDirection = fruit.HyperDashTarget.X - fruit.X; + var target = fruit.HyperDashTarget; + double timeDifference = target.StartTime - fruit.StartTime; + double positionDifference = target.X * CatchPlayfield.BASE_WIDTH - catcherPosition; + double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); + + HyperDashing = true; + hyperDashModifier = Math.Abs(velocity); + hyperDashDirection = (int)Math.Sign(velocity); + hyperDashTargetPosition = target.X; } else - HyperDashModifier = 1; + { + HyperDashing = false; + } return validCatch; } + private double hyperDashModifier = 1; + private int hyperDashDirection = 0; + private float hyperDashTargetPosition; + private bool hyperDashing = false; + /// /// Whether we are hypderdashing or not. /// - public bool HyperDashing => hyperDashModifier != 1; - - private double hyperDashModifier = 1; - - /// - /// The direction in which hyperdash is allowed. 0 allows both directions. - /// - public double HyperDashDirection; - - /// - /// The speed modifier resultant from hyperdash. Will trigger hyperdash when not equal to 1. - /// - public double HyperDashModifier + protected bool HyperDashing { - get { return hyperDashModifier; } + get => hyperDashing; set { - if (value == hyperDashModifier) return; - hyperDashModifier = value; + if (hyperDashing == value) return; + + hyperDashing = value; + + if (!HyperDashing) + { + hyperDashModifier = 1; + hyperDashDirection = 0; + } const float transition_length = 180; @@ -290,7 +299,6 @@ namespace osu.Game.Rulesets.Catch.UI } else { - HyperDashDirection = 0; this.FadeColour(Color4.White, transition_length, Easing.OutQuint); this.FadeTo(1, transition_length, Easing.OutQuint); } @@ -347,12 +355,18 @@ namespace osu.Game.Rulesets.Catch.UI var direction = Math.Sign(currentDirection); double dashModifier = Dashing ? 1 : 0.5; - - if (hyperDashModifier != 1 && (HyperDashDirection == 0 || direction == Math.Sign(HyperDashDirection))) - dashModifier = hyperDashModifier; + double speed = BASE_SPEED * dashModifier * hyperDashModifier; Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1); + X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + + // Correct overshooting. + if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || + (hyperDashDirection < 0 && hyperDashTargetPosition > X)) + { + X = hyperDashTargetPosition; + HyperDashing = false; + } } /// From 99c0e19189b95df33b332784e8a13f8a985c2181 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 01:52:15 +0900 Subject: [PATCH 02/68] Fix build error --- osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index f239290ed4..ed6600c55d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -26,7 +26,6 @@ namespace osu.Game.Rulesets.Catch.Tests public TestCaseCatcherArea() { AddSliderStep("CircleSize", 0, 8, 5, createCatcher); - AddToggleStep("Hyperdash", t => catcherArea.ToggleHyperDash(t)); } private void createCatcher(float size) @@ -54,8 +53,6 @@ namespace osu.Game.Rulesets.Catch.Tests : base(beatmapDifficulty) { } - - public void ToggleHyperDash(bool status) => MovableCatcher.HyperDashModifier = status ? 2 : 1; } } } From be323c71477d009bb8bcda38560fa5c370bcd6f1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 02:14:56 +0900 Subject: [PATCH 03/68] Fix InspectCode issues. --- osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs | 3 +-- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index ed6600c55d..511cda6399 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -16,7 +16,6 @@ namespace osu.Game.Rulesets.Catch.Tests public class TestCaseCatcherArea : OsuTestCase { private RulesetInfo catchRuleset; - private TestCatcherArea catcherArea; public override IReadOnlyList RequiredTypes => new[] { @@ -33,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.Tests Child = new CatchInputManager(catchRuleset) { RelativeSizeAxes = Axes.Both, - Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) + Child = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56826d228c..d57d52cf5f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -255,7 +255,7 @@ namespace osu.Game.Rulesets.Catch.UI HyperDashing = true; hyperDashModifier = Math.Abs(velocity); - hyperDashDirection = (int)Math.Sign(velocity); + hyperDashDirection = Math.Sign(velocity); hyperDashTargetPosition = target.X; } else @@ -267,9 +267,9 @@ namespace osu.Game.Rulesets.Catch.UI } private double hyperDashModifier = 1; - private int hyperDashDirection = 0; + private int hyperDashDirection; private float hyperDashTargetPosition; - private bool hyperDashing = false; + private bool hyperDashing; /// /// Whether we are hypderdashing or not. @@ -361,8 +361,8 @@ namespace osu.Game.Rulesets.Catch.UI X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. - if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || - (hyperDashDirection < 0 && hyperDashTargetPosition > X)) + if (hyperDashDirection > 0 && hyperDashTargetPosition < X || + hyperDashDirection < 0 && hyperDashTargetPosition > X) { X = hyperDashTargetPosition; HyperDashing = false; From 9f2e09dae4cba569d6dbd1e36767f5770bfcda93 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 16:21:51 +0900 Subject: [PATCH 04/68] Move PostProcessing to after control points applied and nested hit objects created. --- osu.Game/Beatmaps/WorkingBeatmap.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 66a6206c16..2e6426c056 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -116,9 +116,6 @@ namespace osu.Game.Beatmaps mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty); } - // Post-process - rulesetInstance.CreateBeatmapProcessor(converted)?.PostProcess(); - // Compute default values for hitobjects, including creating nested hitobjects in-case they're needed foreach (var obj in converted.HitObjects) obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty); @@ -127,6 +124,9 @@ namespace osu.Game.Beatmaps foreach (var obj in converted.HitObjects) mod.ApplyToHitObject(obj); + // Post-process + rulesetInstance.CreateBeatmapProcessor(converted)?.PostProcess(); + return converted; } From ca2c2097016521c16a345e6a173d4e62c78cac0a Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 16:26:19 +0900 Subject: [PATCH 05/68] add FastRandom --- .../MathUtils/FastRandom.cs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs diff --git a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs new file mode 100644 index 0000000000..5e8256a504 --- /dev/null +++ b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs @@ -0,0 +1,91 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; + +namespace osu.Game.Rulesets.Catch.MathUtils +{ + /// + /// A PRNG specified in http://heliosphan.org/fastrandom.html. + /// + internal class FastRandom + { + private const double int_to_real = 1.0 / (int.MaxValue + 1.0); + private const uint int_mask = 0x7FFFFFFF; + private const uint y = 842502087; + private const uint z = 3579807591; + private const uint w = 273326509; + private uint _x, _y = y, _z = z, _w = w; + + public FastRandom(int seed) + { + _x = (uint)seed; + } + + public FastRandom() + : this(Environment.TickCount) + { + } + + /// + /// Generates a random unsigned integer within the range [, ). + /// + /// The random value. + public uint NextUInt() + { + uint t = _x ^ _x << 11; + _x = _y; + _y = _z; + _z = _w; + return _w = _w ^ _w >> 19 ^ t ^ t >> 8; + } + + /// + /// Generates a random integer value within the range [0, ). + /// + /// The random value. + public int Next() => (int)(int_mask & NextUInt()); + + /// + /// Generates a random integer value within the range [0, ). + /// + /// The upper bound. + /// The random value. + public int Next(int upperBound) => (int)(NextDouble() * upperBound); + + /// + /// Generates a random integer value within the range [, ). + /// + /// The lower bound of the range. + /// The upper bound of the range. + /// The random value. + public int Next(int lowerBound, int upperBound) => (int)(lowerBound + NextDouble() * (upperBound - lowerBound)); + + /// + /// Generates a random double value within the range [0, 1). + /// + /// The random value. + public double NextDouble() => int_to_real * Next(); + + private uint bitBuffer; + private int bitIndex = 32; + + /// + /// Generates a reandom boolean value. Cached such that a random value is only generated once in every 32 calls. + /// + /// The random value. + public bool NextBool() + { + if (bitIndex == 32) + { + bitBuffer = NextUInt(); + bitIndex = 1; + + return (bitBuffer & 1) == 1; + } + + bitIndex++; + return ((bitBuffer >>= 1) & 1) == 1; + } + } +} From 8c8e87ed7af2423f8d2ab3a7cf77b98d490c17f9 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 16:49:41 +0900 Subject: [PATCH 06/68] Make FastRandom public --- osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs index 5e8256a504..5b3835755a 100644 --- a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs +++ b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Catch.MathUtils /// /// A PRNG specified in http://heliosphan.org/fastrandom.html. /// - internal class FastRandom + public class FastRandom { private const double int_to_real = 1.0 / (int.MaxValue + 1.0); private const uint int_mask = 0x7FFFFFFF; From 26c6313dec3a1286757f157947e93f10a61f2bdc Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 19:11:29 +0900 Subject: [PATCH 07/68] catch: the fruit positions are finalized on the post process --- .../Beatmaps/CatchBeatmapProcessor.cs | 45 +++++++++++++++++++ .../Objects/BananaShower.cs | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index e16f5fcb60..91a69b5c34 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; using OpenTK; +using osu.Game.Rulesets.Catch.MathUtils; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -21,6 +22,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps public override void PostProcess() { + finalizePosition(); + initialiseHyperDash((List)Beatmap.HitObjects); base.PostProcess(); @@ -30,6 +33,48 @@ namespace osu.Game.Rulesets.Catch.Beatmaps obj.IndexInBeatmap = index++; } + public const int RNG_SEED = 1337; + + private void finalizePosition() + { + var rng = new FastRandom(RNG_SEED); + // todo: HardRock displacement should be applied here + + foreach (var obj in Beatmap.HitObjects) + { + switch (obj) + { + case BananaShower bananaShower: + foreach (var nested in bananaShower.NestedHitObjects) + { + ((BananaShower.Banana)nested).X = (float)rng.NextDouble(); + // discarding 3 times + rng.Next(); + rng.Next(); + rng.Next(); + } + break; + case JuiceStream juiceStream: + foreach (var nested in juiceStream.NestedHitObjects) + { + if (nested is TinyDroplet tinyDroplet) + { + tinyDroplet.X += (float)rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH; + } + else if (nested is Droplet) + { + rng.Next(); // Big droplets are not slided + } + } + break; + case Fruit fruit: + break; + } + var catchHitObject = obj as CatchHitObject; + + } + } + private void initialiseHyperDash(List objects) { // todo: add difficulty adjust. diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index a6aba42f03..ed49359c0f 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.Objects { Samples = Samples, StartTime = i, - X = RNG.NextSingle() + X = 0 // The position will be set on the post processing }); } From 456dc81f2fdd67a966a8e837c0c82fb8839a759e Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 19:18:11 +0900 Subject: [PATCH 08/68] Fix InspectCode issues --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 6 +----- osu.Game.Rulesets.Catch/Objects/BananaShower.cs | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 91a69b5c34..869bc560a8 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { if (nested is TinyDroplet tinyDroplet) { - tinyDroplet.X += (float)rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH; + tinyDroplet.X += rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH; } else if (nested is Droplet) { @@ -67,11 +67,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps } } break; - case Fruit fruit: - break; } - var catchHitObject = obj as CatchHitObject; - } } diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index ed49359c0f..4590856d98 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Catch.Objects From 9f27dd848a8503350ab127cc4d87e02412be2018 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Sun, 3 Jun 2018 15:29:56 +0900 Subject: [PATCH 09/68] HyperDashModifier >= 1 --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 38 +++++++++++++++-------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 6c3624aa0a..2ae1f7eb7a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using OpenTK.Graphics; +using System.Diagnostics; namespace osu.Game.Rulesets.Catch.UI { @@ -243,14 +244,21 @@ namespace osu.Game.Rulesets.Catch.UI double positionDifference = target.X * CatchPlayfield.BASE_WIDTH - catcherPosition; double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); - HyperDashing = true; - hyperDashModifier = Math.Abs(velocity); - hyperDashDirection = Math.Sign(velocity); - hyperDashTargetPosition = target.X; + // An edge case + if (Math.Abs(velocity) <= 1) + { + HyperDashModifier = 1; + } + else + { + hyperDashDirection = Math.Sign(velocity); + hyperDashTargetPosition = target.X; + HyperDashModifier = Math.Abs(velocity); + } } else { - HyperDashing = false; + HyperDashModifier = 1; } return validCatch; @@ -259,23 +267,27 @@ namespace osu.Game.Rulesets.Catch.UI private double hyperDashModifier = 1; private int hyperDashDirection; private float hyperDashTargetPosition; - private bool hyperDashing; /// /// Whether we are hypderdashing or not. /// - protected bool HyperDashing + public bool HyperDashing => hyperDashModifier != 1; + + /// + /// The modifier multiplied to the catcher speed. + /// It is always not less than 1 and it is greater than 1 if and only if the catcher is hyper-dashing. + /// + protected double HyperDashModifier { - get => hyperDashing; + get => hyperDashModifier; set { - if (hyperDashing == value) return; - - hyperDashing = value; + Trace.Assert(value >= 1); + if (hyperDashModifier == value) return; + hyperDashModifier = value; if (!HyperDashing) { - hyperDashModifier = 1; hyperDashDirection = 0; } @@ -355,7 +367,7 @@ namespace osu.Game.Rulesets.Catch.UI hyperDashDirection < 0 && hyperDashTargetPosition > X) { X = hyperDashTargetPosition; - HyperDashing = false; + HyperDashModifier = 1; } } From 25d3f0ead18bceec90c477fd11a3ed5ea1908e0b Mon Sep 17 00:00:00 2001 From: ekrctb Date: Sun, 3 Jun 2018 15:31:51 +0900 Subject: [PATCH 10/68] Revert TestCaseCatcherArea --- osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs | 8 ++++++-- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index 9ec39189f8..f239290ed4 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Catch.Tests public class TestCaseCatcherArea : OsuTestCase { private RulesetInfo catchRuleset; + private TestCatcherArea catcherArea; public override IReadOnlyList RequiredTypes => new[] { @@ -25,6 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests public TestCaseCatcherArea() { AddSliderStep("CircleSize", 0, 8, 5, createCatcher); + AddToggleStep("Hyperdash", t => catcherArea.ToggleHyperDash(t)); } private void createCatcher(float size) @@ -32,10 +34,10 @@ namespace osu.Game.Rulesets.Catch.Tests Child = new CatchInputManager(catchRuleset) { RelativeSizeAxes = Axes.Both, - Child = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) + Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) { Anchor = Anchor.CentreLeft, - Origin = Anchor.TopLeft + Origin = Anchor.BottomLeft }, }; } @@ -52,6 +54,8 @@ namespace osu.Game.Rulesets.Catch.Tests : base(beatmapDifficulty) { } + + public void ToggleHyperDash(bool status) => MovableCatcher.HyperDashModifier = status ? 2 : 1; } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 2ae1f7eb7a..d7d4691ad0 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -277,7 +277,7 @@ namespace osu.Game.Rulesets.Catch.UI /// The modifier multiplied to the catcher speed. /// It is always not less than 1 and it is greater than 1 if and only if the catcher is hyper-dashing. /// - protected double HyperDashModifier + public double HyperDashModifier { get => hyperDashModifier; set From a5c5d11da20febe6f6eeb1772a6955818c0247f3 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Sun, 3 Jun 2018 15:42:27 +0900 Subject: [PATCH 11/68] I think I should learn how to use git --- osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index f239290ed4..5119260c53 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Catch.Tests Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) { Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomLeft + Origin = Anchor.TopLeft }, }; } From 9b10cc4e0c7596d55abc44cf092a6f940141e531 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 19:53:47 +0900 Subject: [PATCH 12/68] Remove invertability of ManiaStage --- .../TestCaseManiaPlayfield.cs | 4 ---- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 9 --------- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 15 --------------- 3 files changed, 28 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs index b064d82a23..2ae6bc346a 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs @@ -131,8 +131,6 @@ namespace osu.Game.Rulesets.Mania.Tests Origin = Anchor.Centre, }); - playfield.Inverted.Value = inverted; - return playfield; } @@ -158,8 +156,6 @@ namespace osu.Game.Rulesets.Mania.Tests Clock = new FramedClock(rateAdjustClock) }); - playfield.Inverted.Value = inverted; - for (double t = start_time; t <= start_time + duration; t += 100) { var note1 = new Note { StartTime = t, Column = 0 }; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 4b936fc7f9..153d4698e1 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; @@ -19,11 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI { public class ManiaPlayfield : ScrollingPlayfield { - /// - /// Whether this playfield should be inverted. This flips everything inside the playfield. - /// - public readonly Bindable Inverted = new Bindable(true); - public List Columns => stages.SelectMany(x => x.Columns).ToList(); private readonly List stages = new List(); @@ -36,8 +30,6 @@ namespace osu.Game.Rulesets.Mania.UI if (stageDefinitions.Count <= 0) throw new ArgumentException("Can't have zero or fewer stages."); - Inverted.Value = true; - GridContainer playfieldGrid; InternalChild = playfieldGrid = new GridContainer { @@ -52,7 +44,6 @@ namespace osu.Game.Rulesets.Mania.UI { var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); newStage.VisibleTimeRange.BindTo(VisibleTimeRange); - newStage.Inverted.BindTo(Inverted); playfieldGrid.Content[0][i] = newStage; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index cb93613c7d..41af5fef38 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -5,7 +5,6 @@ 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.Graphics.Shapes; @@ -28,11 +27,6 @@ namespace osu.Game.Rulesets.Mania.UI { public const float HIT_TARGET_POSITION = 50; - /// - /// Whether this playfield should be inverted. This flips everything inside the playfield. - /// - public readonly Bindable Inverted = new Bindable(true); - public IReadOnlyList Columns => columnFlow.Children; private readonly FillFlowContainer columnFlow; @@ -139,15 +133,6 @@ namespace osu.Game.Rulesets.Mania.UI AddColumn(column); } - - Inverted.ValueChanged += invertedChanged; - Inverted.TriggerChange(); - } - - private void invertedChanged(bool newValue) - { - Scale = new Vector2(1, newValue ? -1 : 1); - Judgements.Scale = Scale; } public void AddColumn(Column c) From 2ed978deaa1b32e98ff5616ebd1f2a2988fbbfb5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 19:55:57 +0900 Subject: [PATCH 13/68] Remove TestCaseManiaHitObjects and TestCaseManiaPlayfield --- .../TestCaseManiaHitObjects.cs | 106 ---------- .../TestCaseManiaPlayfield.cs | 181 ------------------ 2 files changed, 287 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs delete mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs deleted file mode 100644 index a4109722d4..0000000000 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Tests.Visual; -using OpenTK; -using OpenTK.Graphics; - -namespace osu.Game.Rulesets.Mania.Tests -{ - [TestFixture] - public class TestCaseManiaHitObjects : OsuTestCase - { - public TestCaseManiaHitObjects() - { - Note note1 = new Note(); - Note note2 = new Note(); - HoldNote holdNote = new HoldNote { StartTime = 1000 }; - - note1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - note2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - - Add(new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - // Imagine that the containers containing the drawable notes are the "columns" - Children = new Drawable[] - { - new Container - { - Name = "Normal note column", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = 50, - Children = new[] - { - new Container - { - Name = "Timing section", - RelativeSizeAxes = Axes.Both, - RelativeChildSize = new Vector2(1, 10000), - Children = new[] - { - new DrawableNote(note1, ManiaAction.Key1) - { - Y = 5000, - LifetimeStart = double.MinValue, - LifetimeEnd = double.MaxValue, - AccentColour = Color4.Red - }, - new DrawableNote(note2, ManiaAction.Key1) - { - Y = 6000, - LifetimeStart = double.MinValue, - LifetimeEnd = double.MaxValue, - AccentColour = Color4.Red - } - } - } - } - }, - new Container - { - Name = "Hold note column", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = 50, - Children = new[] - { - new Container - { - Name = "Timing section", - RelativeSizeAxes = Axes.Both, - RelativeChildSize = new Vector2(1, 10000), - Children = new[] - { - new DrawableHoldNote(holdNote, ManiaAction.Key1) - { - Y = 5000, - Height = 1000, - LifetimeStart = double.MinValue, - LifetimeEnd = double.MaxValue, - AccentColour = Color4.Red, - } - } - } - } - } - } - }); - } - } -} diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs deleted file mode 100644 index 2ae6bc346a..0000000000 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs +++ /dev/null @@ -1,181 +0,0 @@ -// 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.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Configuration; -using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Mania.Configuration; -using osu.Game.Rulesets.Mania.Judgements; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Scoring; -using osu.Game.Tests.Visual; - -namespace osu.Game.Rulesets.Mania.Tests -{ - [TestFixture] - public class TestCaseManiaPlayfield : OsuTestCase - { - private const double start_time = 500; - private const double duration = 500; - - protected override double TimePerAction => 200; - - private RulesetInfo maniaRuleset; - - public TestCaseManiaPlayfield() - { - var rng = new Random(1337); - - AddStep("1 column", () => createPlayfield(1)); - AddStep("4 columns", () => createPlayfield(4)); - AddStep("5 columns", () => createPlayfield(5)); - AddStep("8 columns", () => createPlayfield(8)); - AddStep("4 + 4 columns", () => - { - var stages = new List - { - new StageDefinition { Columns = 4 }, - new StageDefinition { Columns = 4 }, - }; - createPlayfield(stages); - }); - - AddStep("2 + 4 + 2 columns", () => - { - var stages = new List - { - new StageDefinition { Columns = 2 }, - new StageDefinition { Columns = 4 }, - new StageDefinition { Columns = 2 }, - }; - createPlayfield(stages); - }); - - AddStep("1 + 8 + 1 columns", () => - { - var stages = new List - { - new StageDefinition { Columns = 1 }, - new StageDefinition { Columns = 8 }, - new StageDefinition { Columns = 1 }, - }; - createPlayfield(stages); - }); - - AddStep("Reversed", () => createPlayfield(4, true)); - - AddStep("Notes with input", () => createPlayfieldWithNotes()); - AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(true)); - AddStep("Notes with gravity", () => createPlayfieldWithNotes()); - AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true)); - - AddStep("Hit explosion", () => - { - var playfield = createPlayfield(4); - - int col = rng.Next(0, 4); - - var note = new Note { Column = col }; - note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - - var drawableNote = new DrawableNote(note, ManiaAction.Key1) - { - AccentColour = playfield.Columns.ElementAt(col).AccentColour - }; - - playfield.OnJudgement(drawableNote, new ManiaJudgement { Result = HitResult.Perfect }); - playfield.Columns[col].OnJudgement(drawableNote, new ManiaJudgement { Result = HitResult.Perfect }); - }); - } - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets, SettingsStore settings) - { - maniaRuleset = rulesets.GetRuleset(3); - - Dependencies.Cache(new ManiaConfigManager(settings, maniaRuleset, 4)); - } - - private ManiaPlayfield createPlayfield(int cols, bool inverted = false) - { - var stages = new List - { - new StageDefinition { Columns = cols }, - }; - - return createPlayfield(stages, inverted); - } - - private ManiaPlayfield createPlayfield(List stages, bool inverted = false) - { - Clear(); - - var inputManager = new ManiaInputManager(maniaRuleset, stages.Sum(g => g.Columns)) { RelativeSizeAxes = Axes.Both }; - Add(inputManager); - - ManiaPlayfield playfield; - - inputManager.Add(playfield = new ManiaPlayfield(stages) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - - return playfield; - } - - private void createPlayfieldWithNotes(bool inverted = false) - { - Clear(); - - var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; - - var inputManager = new ManiaInputManager(maniaRuleset, 4) { RelativeSizeAxes = Axes.Both }; - Add(inputManager); - - ManiaPlayfield playfield; - var stages = new List - { - new StageDefinition { Columns = 4 }, - }; - - inputManager.Add(playfield = new ManiaPlayfield(stages) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Clock = new FramedClock(rateAdjustClock) - }); - - for (double t = start_time; t <= start_time + duration; t += 100) - { - var note1 = new Note { StartTime = t, Column = 0 }; - var note2 = new Note { StartTime = t, Column = 3 }; - - note1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - note2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - - playfield.Add(new DrawableNote(note1, ManiaAction.Key1)); - playfield.Add(new DrawableNote(note2, ManiaAction.Key4)); - } - - var holdNote1 = new HoldNote { StartTime = start_time, Duration = duration, Column = 1 }; - var holdNote2 = new HoldNote { StartTime = start_time, Duration = duration, Column = 2 }; - - holdNote1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - holdNote2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - - playfield.Add(new DrawableHoldNote(holdNote1, ManiaAction.Key2)); - playfield.Add(new DrawableHoldNote(holdNote2, ManiaAction.Key3)); - } - } -} From 55a5dfa9b6492b1f38aaf6eb608fd48de7a49c8c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 20:24:33 +0900 Subject: [PATCH 14/68] Add column testcase --- .../ManiaInputTestCase.cs | 45 +++++++++++++++++++ .../TestCaseColumn.cs | 39 ++++++++++++++++ osu.Game/Rulesets/UI/RulesetInputManager.cs | 5 ++- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs new file mode 100644 index 0000000000..75c8fc7e79 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public abstract class ManiaInputTestCase : OsuTestCase + { + private readonly Container content; + protected override Container Content => content ?? base.Content; + + protected ManiaInputTestCase(int keys) + { + base.Content.Add(content = new LocalInputManager(keys)); + } + + private class LocalInputManager : ManiaInputManager + { + public LocalInputManager(int variant) + : base(new ManiaRuleset().RulesetInfo, variant) + { + } + + protected override RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + => new LocalKeyBindingContainer(ruleset, variant, unique); + + private class LocalKeyBindingContainer : RulesetKeyBindingContainer + { + public LocalKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + : base(ruleset, variant, unique) + { + } + + protected override void ReloadMappings() + { + KeyBindings = DefaultKeyBindings; + } + } + } + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs new file mode 100644 index 0000000000..8960ecb2fd --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Game.Rulesets.Mania.UI; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestCaseColumn : ManiaInputTestCase + { + public TestCaseColumn() + : base(1) + { + } + + [BackgroundDependencyLoader] + private void load() + { + Child = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 1) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.85f, + Child = new Column + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AccentColour = Color4.OrangeRed, + Action = ManiaAction.Special1 + } + }; + } + } +} diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index b35616985a..21bd61903c 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.UI protected RulesetInputManager(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) { - InternalChild = KeyBindingContainer = new RulesetKeyBindingContainer(ruleset, variant, unique); + InternalChild = KeyBindingContainer = CreateKeyBindingContainer(ruleset, variant, unique); } #region Action mapping (for replays) @@ -247,6 +247,9 @@ namespace osu.Game.Rulesets.UI } #endregion + + protected virtual RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + => new RulesetKeyBindingContainer(ruleset, variant, unique); } /// From 45dca5646181e3fb1c1c027cf41e171405471443 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 20:40:27 +0900 Subject: [PATCH 15/68] Cleanup testcase --- osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index 8960ecb2fd..0f0258d395 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -20,19 +20,13 @@ namespace osu.Game.Rulesets.Mania.Tests [BackgroundDependencyLoader] private void load() { - Child = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 1) + Child = new Column { Anchor = Anchor.Centre, Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, Height = 0.85f, - Child = new Column - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AccentColour = Color4.OrangeRed, - Action = ManiaAction.Special1 - } + AccentColour = Color4.OrangeRed, + Action = ManiaAction.Special1 }; } } From 4af8baefc15beaf8782f24484b063d168949822f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 20:49:06 +0900 Subject: [PATCH 16/68] Make the column background follow the scroll direction --- .../TestCaseColumn.cs | 35 +++++- osu.Game.Rulesets.Mania/UI/Column.cs | 32 ++--- .../UI/Components/ColumnBackground.cs | 109 ++++++++++++++++++ 3 files changed, 147 insertions(+), 29 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index 0f0258d395..b72dd808f4 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -1,10 +1,16 @@ // 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 NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mania.UI.Components; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests @@ -12,22 +18,41 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestCaseColumn : ManiaInputTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Column), + typeof(ColumnBackground) + }; + public TestCaseColumn() - : base(1) + : base(2) { } [BackgroundDependencyLoader] private void load() { - Child = new Column + Child = new FillFlowContainer { + RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Height = 0.85f, - AccentColour = Color4.OrangeRed, - Action = ManiaAction.Special1 + Spacing = new Vector2(20, 0), + Children = new[] + { + createColumn(ScrollingDirection.Up, ManiaAction.Key1), + createColumn(ScrollingDirection.Down, ManiaAction.Key2) + } }; } + + private Column createColumn(ScrollingDirection direction, ManiaAction action) => new Column(direction) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Height = 0.85f, + AccentColour = Color4.OrangeRed, + Action = action + }; } } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index dee113c82f..b00508eb63 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -14,6 +14,7 @@ using System; using System.Linq; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI @@ -32,8 +33,7 @@ namespace osu.Game.Rulesets.Mania.UI public ManiaAction Action; - private readonly Box background; - private readonly Box backgroundOverlay; + private readonly ColumnBackground background; private readonly Container hitTargetBar; private readonly Container keyIcon; @@ -43,8 +43,8 @@ namespace osu.Game.Rulesets.Mania.UI protected override Container Content => content; private readonly Container content; - public Column() - : base(ScrollingDirection.Up) + public Column(ScrollingDirection direction = ScrollingDirection.Up) + : base(direction) { RelativeSizeAxes = Axes.Y; Width = column_width; @@ -54,22 +54,7 @@ namespace osu.Game.Rulesets.Mania.UI InternalChildren = new Drawable[] { - background = new Box - { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Alpha = 0.3f - }, - backgroundOverlay = new Box - { - Name = "Background Gradient Overlay", - RelativeSizeAxes = Axes.Both, - Height = 0.5f, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - Blending = BlendingMode.Additive, - Alpha = 0 - }, + background = new ColumnBackground(direction) { RelativeSizeAxes = Axes.Both }, new Container { Name = "Hit target + hit objects", @@ -192,8 +177,7 @@ namespace osu.Game.Rulesets.Mania.UI return; accentColour = value; - background.Colour = accentColour; - backgroundOverlay.Colour = ColourInfo.GradientVertical(accentColour.Opacity(0.6f), accentColour.Opacity(0)); + background.AccentColour = value; hitTargetBar.EdgeEffect = new EdgeEffectParameters { @@ -235,7 +219,7 @@ namespace osu.Game.Rulesets.Mania.UI { if (action == Action) { - backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); + background.IsLit = true; keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); } @@ -246,7 +230,7 @@ namespace osu.Game.Rulesets.Mania.UI { if (action == Action) { - backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); + background.IsLit = false; keyIcon.ScaleTo(1f, 125, Easing.OutQuint); } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs new file mode 100644 index 0000000000..917d254e3a --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -0,0 +1,109 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.UI.Components +{ + public class ColumnBackground : CompositeDrawable, IHasAccentColour + { + private readonly ScrollingDirection direction; + + public ColumnBackground(ScrollingDirection direction) + { + this.direction = direction; + } + + private Box background; + private Box backgroundOverlay; + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new[] + { + background = new Box + { + Name = "Background", + RelativeSizeAxes = Axes.Both, + Alpha = 0.3f + }, + backgroundOverlay = new Box + { + Name = "Background Gradient Overlay", + RelativeSizeAxes = Axes.Both, + Height = 0.5f, + Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Blending = BlendingMode.Additive, + Alpha = 0 + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateColours(); + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + accentColour = value; + + updateColours(); + } + } + + private void updateColours() + { + if (!IsLoaded) + return; + + background.Colour = AccentColour; + + var brightPoint = AccentColour.Opacity(0.6f); + var dimPoint = AccentColour.Opacity(0); + + backgroundOverlay.Colour = ColourInfo.GradientVertical( + direction == ScrollingDirection.Up ? brightPoint : dimPoint, + direction == ScrollingDirection.Up ? dimPoint : brightPoint); + } + + private bool isLit; + + /// + /// Whether the column lighting should be visible. + /// + public bool IsLit + { + set + { + if (isLit == value) + return; + isLit = value; + + if (isLit) + backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); + else + backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); + } + } + + } +} From d49758d1497a137d486037d4c78d330b2084540e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 20:59:04 +0900 Subject: [PATCH 17/68] Make background handle its own lit state --- osu.Game.Rulesets.Mania/UI/Column.cs | 21 ++++++++---- .../UI/Components/ColumnBackground.cs | 32 ++++++++----------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index b00508eb63..e0ecc9d708 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -31,7 +31,20 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; - public ManiaAction Action; + private ManiaAction action; + + public ManiaAction Action + { + get => action; + set + { + if (action == value) + return; + action = value; + + background.Action = value; + } + } private readonly ColumnBackground background; private readonly Container hitTargetBar; @@ -218,10 +231,7 @@ namespace osu.Game.Rulesets.Mania.UI private bool onPressed(ManiaAction action) { if (action == Action) - { - background.IsLit = true; keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); - } return false; } @@ -229,10 +239,7 @@ namespace osu.Game.Rulesets.Mania.UI private bool onReleased(ManiaAction action) { if (action == Action) - { - background.IsLit = false; keyIcon.ScaleTo(1f, 125, Easing.OutQuint); - } return false; } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 917d254e3a..eeef5afcb0 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -7,14 +7,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Rulesets.UI.Scrolling; using OpenTK.Graphics; namespace osu.Game.Rulesets.Mania.UI.Components { - public class ColumnBackground : CompositeDrawable, IHasAccentColour + public class ColumnBackground : CompositeDrawable, IKeyBindingHandler, IHasAccentColour { + public ManiaAction Action; + private readonly ScrollingDirection direction; public ColumnBackground(ScrollingDirection direction) @@ -85,25 +88,18 @@ namespace osu.Game.Rulesets.Mania.UI.Components direction == ScrollingDirection.Up ? dimPoint : brightPoint); } - private bool isLit; - - /// - /// Whether the column lighting should be visible. - /// - public bool IsLit + public bool OnPressed(ManiaAction action) { - set - { - if (isLit == value) - return; - isLit = value; - - if (isLit) - backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); - else - backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); - } + if (action == Action) + backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); + return false; } + public bool OnReleased(ManiaAction action) + { + if (action == Action) + backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); + return false; + } } } From 11f067d7d6bb3e03fc6666237eddcc76be79c009 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 21:13:29 +0900 Subject: [PATCH 18/68] Fix background input --- osu.Game.Rulesets.Mania/UI/Column.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index e0ecc9d708..e1eb11f5e5 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -65,9 +65,12 @@ namespace osu.Game.Rulesets.Mania.UI Masking = true; CornerRadius = 5; - InternalChildren = new Drawable[] + background = new ColumnBackground(direction) { RelativeSizeAxes = Axes.Both }; + + InternalChildren = new[] { - background = new ColumnBackground(direction) { RelativeSizeAxes = Axes.Both }, + // For input purposes, the background is added at the highest depth, but is then proxied back below all other elements + background.CreateProxy(), new Container { Name = "Hit target + hit objects", @@ -158,6 +161,7 @@ namespace osu.Game.Rulesets.Mania.UI } } }, + background, TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both } }; From 207cdbdefe12d29cdd3d38b4c1d36660542e7833 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 21:13:57 +0900 Subject: [PATCH 19/68] Make the column key area follow the scroll direction --- .../TestCaseColumn.cs | 3 +- osu.Game.Rulesets.Mania/UI/Column.cs | 95 ++------------ .../UI/Components/ColumnKeyArea.cs | 119 ++++++++++++++++++ 3 files changed, 128 insertions(+), 89 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index b72dd808f4..391a30e4c7 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -21,7 +21,8 @@ namespace osu.Game.Rulesets.Mania.Tests public override IReadOnlyList RequiredTypes => new[] { typeof(Column), - typeof(ColumnBackground) + typeof(ColumnBackground), + typeof(ColumnKeyArea) }; public TestCaseColumn() diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index e1eb11f5e5..5568869755 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -1,16 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using System; using System.Linq; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; @@ -21,10 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI { public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { - private const float key_icon_size = 10; - private const float key_icon_corner_radius = 3; - private const float key_icon_border_radius = 2; - private const float hit_target_height = 10; private const float hit_target_bar_height = 2; @@ -43,12 +36,14 @@ namespace osu.Game.Rulesets.Mania.UI action = value; background.Action = value; + keyArea.Action = value; } } private readonly ColumnBackground background; + private readonly ColumnKeyArea keyArea; + private readonly Container hitTargetBar; - private readonly Container keyIcon; internal readonly Container TopLevelContainer; private readonly Container explosionContainer; @@ -112,12 +107,6 @@ namespace osu.Game.Rulesets.Mania.UI Name = "Hit objects", RelativeSizeAxes = Axes.Both, }, - // For column lighting, we need to capture input events before the notes - new InputTarget - { - Pressed = onPressed, - Released = onReleased - }, explosionContainer = new Container { Name = "Hit explosions", @@ -125,41 +114,12 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - new Container + keyArea = new ColumnKeyArea(direction) { - Name = "Key", + Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = ManiaStage.HIT_TARGET_POSITION, - Children = new Drawable[] - { - new Box - { - Name = "Key gradient", - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black, Color4.Black.Opacity(0)), - Alpha = 0.5f - }, - keyIcon = new Container - { - Name = "Key icon", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(key_icon_size), - Masking = true, - CornerRadius = key_icon_corner_radius, - BorderThickness = 2, - BorderColour = Color4.White, // Not true - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - } - } - } }, background, TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both } @@ -195,6 +155,7 @@ namespace osu.Game.Rulesets.Mania.UI accentColour = value; background.AccentColour = value; + keyArea.AccentColour = value; hitTargetBar.EdgeEffect = new EdgeEffectParameters { @@ -202,13 +163,6 @@ namespace osu.Game.Rulesets.Mania.UI Radius = 5, Colour = accentColour.Opacity(0.5f), }; - - keyIcon.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Radius = 5, - Colour = accentColour.Opacity(0.5f), - }; } } @@ -232,41 +186,6 @@ namespace osu.Game.Rulesets.Mania.UI explosionContainer.Add(new HitExplosion(judgedObject)); } - private bool onPressed(ManiaAction action) - { - if (action == Action) - keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); - - return false; - } - - private bool onReleased(ManiaAction action) - { - if (action == Action) - keyIcon.ScaleTo(1f, 125, Easing.OutQuint); - - return false; - } - - /// - /// This is a simple container which delegates various input events that have to be captured before the notes. - /// - private class InputTarget : Container, IKeyBindingHandler - { - public Func Pressed; - public Func Released; - - public InputTarget() - { - RelativeSizeAxes = Axes.Both; - AlwaysPresent = true; - Alpha = 0; - } - - public bool OnPressed(ManiaAction action) => Pressed?.Invoke(action) ?? false; - public bool OnReleased(ManiaAction action) => Released?.Invoke(action) ?? false; - } - public bool OnPressed(ManiaAction action) { if (action != Action) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs new file mode 100644 index 0000000000..f0884f92da --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -0,0 +1,119 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; +using osu.Game.Graphics; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.UI.Components +{ + public class ColumnKeyArea : CompositeDrawable, IKeyBindingHandler, IHasAccentColour + { + private const float key_icon_size = 10; + private const float key_icon_corner_radius = 3; + + public ManiaAction Action; + + private readonly ScrollingDirection direction; + + public ColumnKeyArea(ScrollingDirection direction) + { + this.direction = direction; + } + + private Container keyIcon; + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new Box + { + Name = "Key gradient", + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical( + direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), + direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black), + Alpha = 0.5f + }, + keyIcon = new Container + { + Name = "Key icon", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(key_icon_size), + Masking = true, + CornerRadius = key_icon_corner_radius, + BorderThickness = 2, + BorderColour = Color4.White, // Not true + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateColours(); + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + accentColour = value; + + updateColours(); + } + } + + private void updateColours() + { + if (!IsLoaded) + return; + + keyIcon.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 5, + Colour = accentColour.Opacity(0.5f), + }; + } + + public bool OnPressed(ManiaAction action) + { + if (action == Action) + keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); + return false; + } + + public bool OnReleased(ManiaAction action) + { + if (action == Action) + keyIcon.ScaleTo(1f, 125, Easing.OutQuint); + return false; + } + } +} From 0c359088021e5529067b76e56b84798e8ba7e3e5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 21:19:31 +0900 Subject: [PATCH 20/68] Reorder fields --- osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs | 6 +++--- osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index eeef5afcb0..b71dae035e 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -20,14 +20,14 @@ namespace osu.Game.Rulesets.Mania.UI.Components private readonly ScrollingDirection direction; + private Box background; + private Box backgroundOverlay; + public ColumnBackground(ScrollingDirection direction) { this.direction = direction; } - private Box background; - private Box backgroundOverlay; - [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index f0884f92da..e7fe44171b 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -24,13 +24,13 @@ namespace osu.Game.Rulesets.Mania.UI.Components private readonly ScrollingDirection direction; + private Container keyIcon; + public ColumnKeyArea(ScrollingDirection direction) { this.direction = direction; } - private Container keyIcon; - [BackgroundDependencyLoader] private void load() { From 32037701bfad57592cb39f7b490eda33f9bafce6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 21:40:12 +0900 Subject: [PATCH 21/68] Make the column hitobject area follow the scroll direction --- .../TestCaseColumn.cs | 3 +- osu.Game.Rulesets.Mania/UI/Column.cs | 60 ++---------- .../UI/Components/ColumnHitObjectArea.cs | 96 +++++++++++++++++++ 3 files changed, 107 insertions(+), 52 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index 391a30e4c7..05c7e99a18 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -22,7 +22,8 @@ namespace osu.Game.Rulesets.Mania.Tests { typeof(Column), typeof(ColumnBackground), - typeof(ColumnKeyArea) + typeof(ColumnKeyArea), + typeof(ColumnHitObjectArea) }; public TestCaseColumn() diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 5568869755..81607795fe 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -2,10 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System.Linq; @@ -18,9 +16,6 @@ namespace osu.Game.Rulesets.Mania.UI { public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { - private const float hit_target_height = 10; - private const float hit_target_bar_height = 2; - private const float column_width = 45; private const float special_column_width = 70; @@ -42,14 +37,12 @@ namespace osu.Game.Rulesets.Mania.UI private readonly ColumnBackground background; private readonly ColumnKeyArea keyArea; - - private readonly Container hitTargetBar; + private readonly ColumnHitObjectArea hitObjectArea; internal readonly Container TopLevelContainer; private readonly Container explosionContainer; - protected override Container Content => content; - private readonly Container content; + protected override Container Content => hitObjectArea; public Column(ScrollingDirection direction = ScrollingDirection.Up) : base(direction) @@ -70,43 +63,14 @@ namespace osu.Game.Rulesets.Mania.UI { Name = "Hit target + hit objects", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = ManiaStage.HIT_TARGET_POSITION }, + Padding = new MarginPadding + { + Top = direction == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, + Bottom = direction == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, + }, Children = new Drawable[] { - new Container - { - Name = "Hit target", - RelativeSizeAxes = Axes.X, - Height = hit_target_height, - Children = new Drawable[] - { - new Box - { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black - }, - hitTargetBar = new Container - { - Name = "Bar", - RelativeSizeAxes = Axes.X, - Height = hit_target_bar_height, - Masking = true, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both - } - } - } - } - }, - content = new Container - { - Name = "Hit objects", - RelativeSizeAxes = Axes.Both, - }, + hitObjectArea = new ColumnHitObjectArea(direction) { RelativeSizeAxes = Axes.Both }, explosionContainer = new Container { Name = "Hit explosions", @@ -156,13 +120,7 @@ namespace osu.Game.Rulesets.Mania.UI background.AccentColour = value; keyArea.AccentColour = value; - - hitTargetBar.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Radius = 5, - Colour = accentColour.Opacity(0.5f), - }; + hitObjectArea.AccentColour = value; } } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs new file mode 100644 index 0000000000..31df6d5fa3 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -0,0 +1,96 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.UI.Components +{ + public class ColumnHitObjectArea : Container, IHasAccentColour + { + private const float hit_target_height = 10; + private const float hit_target_bar_height = 2; + + private Container content; + protected override Container Content => content; + + private readonly ScrollingDirection direction; + + private Container hitTargetBar; + + public ColumnHitObjectArea(ScrollingDirection direction) + { + this.direction = direction; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new Box + { + Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = hit_target_height, + Colour = Color4.Black + }, + hitTargetBar = new Container + { + Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = hit_target_bar_height, + Masking = true, + Child = new Box { RelativeSizeAxes = Axes.Both } + }, + content = new Container + { + Name = "Hit objects", + RelativeSizeAxes = Axes.Both, + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateColours(); + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + accentColour = value; + + updateColours(); + } + } + + private void updateColours() + { + if (!IsLoaded) + return; + + hitTargetBar.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 5, + Colour = accentColour.Opacity(0.5f), + }; + } + } +} From ee64760406c6217944475f5f24f3f185fb1affb4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 14:28:27 +0900 Subject: [PATCH 22/68] Add mania stage test case --- .../TestCaseStage.cs | 46 +++++++++++++++++++ osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 6 +-- .../UI/ManiaRulesetContainer.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 6 +-- 5 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs new file mode 100644 index 0000000000..bcdee7b688 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestCaseStage : ManiaInputTestCase + { + public TestCaseStage() + : base(4) + { + } + + [BackgroundDependencyLoader] + private void load() + { + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(20, 0), + Children = new[] + { + createStage(ScrollingDirection.Up, ManiaAction.Key1), + createStage(ScrollingDirection.Down, ManiaAction.Key3) + } + }; + } + + private ManiaStage createStage(ScrollingDirection direction, ManiaAction action) + { + var specialAction = ManiaAction.Special1; + return new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction); + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 81607795fe..e71a95f3dc 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override Container Content => hitObjectArea; - public Column(ScrollingDirection direction = ScrollingDirection.Up) + public Column(ScrollingDirection direction) : base(direction) { RelativeSizeAxes = Axes.Y; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 153d4698e1..73362ab28f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -21,8 +21,8 @@ namespace osu.Game.Rulesets.Mania.UI public List Columns => stages.SelectMany(x => x.Columns).ToList(); private readonly List stages = new List(); - public ManiaPlayfield(List stageDefinitions) - : base(ScrollingDirection.Up) + public ManiaPlayfield(ScrollingDirection direction, List stageDefinitions) + : base(direction) { if (stageDefinitions == null) throw new ArgumentNullException(nameof(stageDefinitions)); @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI int firstColumnIndex = 0; for (int i = 0; i < stageDefinitions.Count; i++) { - var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); + var newStage = new ManiaStage(direction, firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); newStage.VisibleTimeRange.BindTo(VisibleTimeRange); playfieldGrid.Content[0][i] = newStage; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 7123aab901..b7acd1d5ee 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.UI BarLines.ForEach(Playfield.Add); } - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) + protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(ScrollingDirection.Up, Beatmap.Stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 41af5fef38..822042362f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -43,8 +43,8 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int firstColumnIndex; - public ManiaStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) - : base(ScrollingDirection.Up) + public ManiaStage(ScrollingDirection direction, int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) + : base(direction) { this.firstColumnIndex = firstColumnIndex; @@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Mania.UI for (int i = 0; i < definition.Columns; i++) { var isSpecial = definition.IsSpecialColumn(i); - var column = new Column + var column = new Column(direction) { IsSpecial = isSpecial, Action = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ From 2a48e0e44a1b299051a57a63d9d807792b40e04e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 14:49:45 +0900 Subject: [PATCH 23/68] Fix sequential speed change visualiser not working with 0 control points --- .../Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs index e353c07e9f..745352a4d3 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs @@ -93,6 +93,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers /// A positive value indicating the position at . private double positionAt(double time, double timeRange) { + if (controlPoints.Count == 0) + return time / timeRange; + double length = 0; // We need to consider all timing points until the specified time and not just the currently-active one, From d6f230f2b03a753249dbde252d73c37776fb9b8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:16:14 +0900 Subject: [PATCH 24/68] Add notes to TestCaseColumn --- .../TestCaseColumn.cs | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index 05c7e99a18..cd1eb43853 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -7,6 +7,10 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; @@ -26,6 +30,8 @@ namespace osu.Game.Rulesets.Mania.Tests typeof(ColumnHitObjectArea) }; + private readonly List columns = new List(); + public TestCaseColumn() : base(2) { @@ -48,13 +54,38 @@ namespace osu.Game.Rulesets.Mania.Tests }; } - private Column createColumn(ScrollingDirection direction, ManiaAction action) => new Column(direction) + protected override void LoadComplete() { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Height = 0.85f, - AccentColour = Color4.OrangeRed, - Action = action - }; + base.LoadComplete(); + + AddStep("note", createNote); + } + + private void createNote() + { + for (int i = 0; i < columns.Count; i++) + { + var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + columns[i].Add(new DrawableNote(obj, columns[i].Action)); + } + } + + private Column createColumn(ScrollingDirection direction, ManiaAction action) + { + var column = new Column(direction) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Height = 0.85f, + AccentColour = Color4.OrangeRed, + Action = action, + VisibleTimeRange = { Value = 2000 } + }; + + columns.Add(column); + return column; + } } } From 80a577f1823733be9d129d28302810d12205a11c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:16:45 +0900 Subject: [PATCH 25/68] Fix notes not scrolling correctly --- .../Drawables/DrawableManiaHitObject.cs | 23 ++++++++++++++++++- osu.Game.Rulesets.Mania/UI/Column.cs | 7 ++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index fbf1ee8460..61a7f96c91 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -3,10 +3,31 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables { - public abstract class DrawableManiaHitObject : DrawableHitObject + public abstract class DrawableManiaHitObject : DrawableHitObject + { + protected DrawableManiaHitObject(ManiaHitObject hitObject) + : base(hitObject) + { + } + + /// + /// Sets the scrolling direction. + /// + public virtual ScrollingDirection Direction + { + set + { + Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Origin = Anchor; + } + } + } + + public abstract class DrawableManiaHitObject : DrawableManiaHitObject where TObject : ManiaHitObject { /// diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index e71a95f3dc..6f3d82a464 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Objects.Drawables; using System.Linq; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; @@ -35,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI } } + private readonly ScrollingDirection direction; + private readonly ColumnBackground background; private readonly ColumnKeyArea keyArea; private readonly ColumnHitObjectArea hitObjectArea; @@ -47,6 +50,7 @@ namespace osu.Game.Rulesets.Mania.UI public Column(ScrollingDirection direction) : base(direction) { + this.direction = direction; RelativeSizeAxes = Axes.Y; Width = column_width; @@ -130,6 +134,9 @@ namespace osu.Game.Rulesets.Mania.UI /// The DrawableHitObject to add. public override void Add(DrawableHitObject hitObject) { + var maniaObject = (DrawableManiaHitObject)hitObject; + maniaObject.Direction = direction; + hitObject.AccentColour = AccentColour; hitObject.OnJudgement += OnJudgement; From d73c2a1654a481294158be3c4ebc2184963dc317 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:17:22 +0900 Subject: [PATCH 26/68] Fix various note elements not following the scroll direction --- .../Objects/Drawables/DrawableNote.cs | 13 +++++++++++++ .../Objects/Drawables/Pieces/NotePiece.cs | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 3de0a9c5cc..a8666405cc 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -9,6 +9,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -38,6 +39,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }; } + public override ScrollingDirection Direction + { + set + { + base.Direction = value; + + headPiece.Direction = value; + headPiece.Anchor = Anchor; + headPiece.Origin = Origin; + } + } + public override Color4 AccentColour { get { return base.AccentColour; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 9ebeb91e0c..952ddd074e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces { @@ -42,6 +43,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces }; } + public ScrollingDirection Direction + { + set + { + colouredBox.Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + colouredBox.Origin = colouredBox.Anchor; + } + } + private Color4 accentColour; public Color4 AccentColour { From 7deaffdb62b0a2247b49fae5fcdf419ad8749fc4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:23:47 +0900 Subject: [PATCH 27/68] Fix hit explosions not following the scroll direction --- osu.Game.Rulesets.Mania/UI/Column.cs | 5 ++++- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 6f3d82a464..26269ff537 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -148,7 +148,10 @@ namespace osu.Game.Rulesets.Mania.UI if (!judgement.IsHit || !judgedObject.DisplayJudgement) return; - explosionContainer.Add(new HitExplosion(judgedObject)); + explosionContainer.Add(new HitExplosion(judgedObject) + { + Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre + }); } public bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index f19c3a811b..e3f0656000 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -21,7 +21,6 @@ namespace osu.Game.Rulesets.Mania.UI { bool isTick = judgedObject is DrawableHoldNoteTick; - Anchor = Anchor.TopCentre; Origin = Anchor.Centre; RelativeSizeAxes = Axes.X; From c933dd4069aec242bcd1450fd2463099788e9fd3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:28:57 +0900 Subject: [PATCH 28/68] Add hold notes to TestCaseColumn --- osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index cd1eb43853..ced64e21e9 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -59,6 +59,7 @@ namespace osu.Game.Rulesets.Mania.Tests base.LoadComplete(); AddStep("note", createNote); + AddStep("hold note", createHoldNote); } private void createNote() @@ -72,6 +73,17 @@ namespace osu.Game.Rulesets.Mania.Tests } } + private void createHoldNote() + { + for (int i = 0; i < columns.Count; i++) + { + var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + columns[i].Add(new DrawableHoldNote(obj, columns[i].Action)); + } + } + private Column createColumn(ScrollingDirection direction, ManiaAction action) { var column = new Column(direction) From 5c8bea82f8e53cad4d5d15ffc97bd2dd7ef644df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:29:08 +0900 Subject: [PATCH 29/68] Fix scroll direction not applying to nested hitobjects --- .../Objects/Drawables/DrawableManiaHitObject.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 61a7f96c91..89fe0b1945 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.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.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; @@ -23,6 +24,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; Origin = Anchor; + + if (!HasNestedHitObjects) + return; + + foreach (var obj in NestedHitObjects.OfType()) + obj.Direction = value; } } } From c010ea83ca37ed5e8b3b18354cec64cfbe3ca71c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 18:10:07 +0900 Subject: [PATCH 30/68] Add note hitobject testcase --- .../TestCaseNotes.cs | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs new file mode 100644 index 0000000000..bb12bb35db --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -0,0 +1,165 @@ +// 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.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Tests.Visual; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestCaseNotes : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DrawableNote), + typeof(DrawableHoldNote) + }; + + [BackgroundDependencyLoader] + private void load() + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20), + Children = new[] + { + createNoteDisplay(ScrollingDirection.Down), + createNoteDisplay(ScrollingDirection.Up), + createHoldNoteDisplay(ScrollingDirection.Down), + createHoldNoteDisplay(ScrollingDirection.Up), + } + }; + } + + private Drawable createNoteDisplay(ScrollingDirection direction) + { + var note = new Note { StartTime = 999999999 }; + note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + return new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") + { + Child = new DrawableNote(note, ManiaAction.Key1) + { + AccentColour = Color4.OrangeRed, + Direction = direction + } + }; + } + + private Drawable createHoldNoteDisplay(ScrollingDirection direction) + { + var note = new HoldNote { StartTime = 999999999, Duration = 1000 }; + note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + return new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") + { + Child = new DrawableHoldNote(note, ManiaAction.Key1) + { + RelativeSizeAxes = Axes.Both, + AccentColour = Color4.OrangeRed, + Direction = direction + } + }; + } + + private class NoteContainer : Container + { + private readonly Container content; + protected override Container Content => content; + + private readonly ScrollingDirection direction; + + public NoteContainer(ScrollingDirection direction, string description) + { + this.direction = direction; + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(0, 10), + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 45, + Height = 100, + Children = new Drawable[] + { + new Box + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Width = 1.25f, + Colour = Color4.Black.Opacity(0.5f) + }, + content = new Container { RelativeSizeAxes = Axes.Both } + } + }, + new SpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextSize = 14, + Text = description + } + } + }; + } + + protected override void Update() + { + base.Update(); + + foreach (var obj in content.OfType()) + { + if (!(obj.HitObject is IHasEndTime endTime)) + continue; + + if (!obj.HasNestedHitObjects) + continue; + + foreach (var nested in obj.NestedHitObjects) + { + double finalPosition = (nested.HitObject.StartTime - obj.HitObject.StartTime) / endTime.Duration; + switch (direction) + { + case ScrollingDirection.Up: + nested.Y = (float)(finalPosition * content.DrawHeight); + break; + case ScrollingDirection.Down: + nested.Y = (float)(-finalPosition * content.DrawHeight); + break; + } + } + } + } + } + } +} From 0fb4e6b41b5fba0b9bbb75664d8627f3b85c4fc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 18:16:55 +0900 Subject: [PATCH 31/68] Fix hold note body not following the scroll direction --- .../Objects/Drawables/DrawableHoldNote.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index e008fa952e..6ae78ec4d0 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -75,6 +76,19 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(tail); } + private ScrollingDirection direction; + public override ScrollingDirection Direction + { + set + { + base.Direction = value; + direction = value; + + bodyPiece.Anchor = value == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + bodyPiece.Origin = bodyPiece.Anchor; + } + } + public override Color4 AccentColour { get { return base.AccentColour; } @@ -100,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.Update(); // Make the body piece not lie under the head note - bodyPiece.Y = head.Height / 2; + bodyPiece.Y = (direction == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; bodyPiece.Height = DrawHeight - head.Height / 2 + tail.Height / 2; } From ca5103615df1241e7d8aac37678e7d26e4af1fc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 20:13:24 +0900 Subject: [PATCH 32/68] DI the scrolling info rather than pass by ctor --- .../ScrollingTestContainer.cs | 29 +++++++++++++ .../TestCaseColumn.cs | 12 +++++- .../TestCaseNotes.cs | 22 ++++++---- .../TestCaseStage.cs | 12 +++++- .../Objects/Drawables/DrawableHoldNote.cs | 20 ++++----- .../Drawables/DrawableManiaHitObject.cs | 41 +++++-------------- .../Objects/Drawables/DrawableNote.cs | 24 ++++------- .../Objects/Drawables/Pieces/NotePiece.cs | 12 +++--- osu.Game.Rulesets.Mania/UI/Column.cs | 10 ++--- .../UI/Components/ColumnBackground.cs | 19 ++++----- .../UI/Components/ColumnHitObjectArea.cs | 17 +++----- .../UI/Components/ColumnKeyArea.cs | 13 ++---- .../UI/ManiaRulesetContainer.cs | 16 +++++++- osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs | 17 ++++++++ 14 files changed, 146 insertions(+), 118 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs create mode 100644 osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs diff --git a/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs new file mode 100644 index 0000000000..2b86c6187b --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania.Tests +{ + /// + /// A container which provides a to children. + /// + public class ScrollingTestContainer : Container + { + private readonly ScrollingInfo scrollingInfo; + + public ScrollingTestContainer(ScrollingInfo scrollingInfo) + { + this.scrollingInfo = scrollingInfo; + } + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + dependencies.Cache(scrollingInfo); + return dependencies; + } + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index ced64e21e9..d5f43b809e 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Mania.Tests } } - private Column createColumn(ScrollingDirection direction, ManiaAction action) + private Drawable createColumn(ScrollingDirection direction, ManiaAction action) { var column = new Column(direction) { @@ -97,7 +97,15 @@ namespace osu.Game.Rulesets.Mania.Tests }; columns.Add(column); - return column; + + return new ScrollingTestContainer(new ScrollingInfo(direction)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Child = column + }; } } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index bb12bb35db..3342060fe2 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -15,6 +15,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI.Scrolling; @@ -58,12 +59,12 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new Note { StartTime = 999999999 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - return new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") + return new ScrollingTestContainer(new ScrollingInfo(direction)) { - Child = new DrawableNote(note, ManiaAction.Key1) + AutoSizeAxes = Axes.Both, + Child = new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") { - AccentColour = Color4.OrangeRed, - Direction = direction + Child = new DrawableNote(note, ManiaAction.Key1) { AccentColour = Color4.OrangeRed } } }; } @@ -73,13 +74,16 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new HoldNote { StartTime = 999999999, Duration = 1000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - return new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") + return new ScrollingTestContainer(new ScrollingInfo(direction)) { - Child = new DrawableHoldNote(note, ManiaAction.Key1) + AutoSizeAxes = Axes.Both, + Child = new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") { - RelativeSizeAxes = Axes.Both, - AccentColour = Color4.OrangeRed, - Direction = direction + Child = new DrawableHoldNote(note, ManiaAction.Key1) + { + RelativeSizeAxes = Axes.Both, + AccentColour = Color4.OrangeRed, + } } }; } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index bcdee7b688..2f639494bb 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -37,10 +37,18 @@ namespace osu.Game.Rulesets.Mania.Tests }; } - private ManiaStage createStage(ScrollingDirection direction, ManiaAction action) + private Drawable createStage(ScrollingDirection direction, ManiaAction action) { var specialAction = ManiaAction.Special1; - return new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction); + + return new ScrollingTestContainer(new ScrollingInfo(direction)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Child = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) + }; } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 6ae78ec4d0..86bbc2c11d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; @@ -9,6 +10,7 @@ using OpenTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -36,6 +38,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// private bool hasBroken; + private ScrollingInfo scrollingInfo; + private readonly Container tickContainer; public DrawableHoldNote(HoldNote hitObject, ManiaAction action) @@ -76,17 +80,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(tail); } - private ScrollingDirection direction; - public override ScrollingDirection Direction + [BackgroundDependencyLoader] + private void load(ScrollingInfo scrollingInfo) { - set - { - base.Direction = value; - direction = value; + this.scrollingInfo = scrollingInfo; - bodyPiece.Anchor = value == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - bodyPiece.Origin = bodyPiece.Anchor; - } + bodyPiece.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + bodyPiece.Origin = bodyPiece.Anchor; } public override Color4 AccentColour @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.Update(); // Make the body piece not lie under the head note - bodyPiece.Y = (direction == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; + bodyPiece.Y = (scrollingInfo.Direction == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; bodyPiece.Height = DrawHeight - head.Height / 2 + tail.Height / 2; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 89fe0b1945..59f93eb16a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -1,40 +1,15 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables { - public abstract class DrawableManiaHitObject : DrawableHitObject - { - protected DrawableManiaHitObject(ManiaHitObject hitObject) - : base(hitObject) - { - } - - /// - /// Sets the scrolling direction. - /// - public virtual ScrollingDirection Direction - { - set - { - Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - Origin = Anchor; - - if (!HasNestedHitObjects) - return; - - foreach (var obj in NestedHitObjects.OfType()) - obj.Direction = value; - } - } - } - - public abstract class DrawableManiaHitObject : DrawableManiaHitObject + public abstract class DrawableManiaHitObject : DrawableHitObject where TObject : ManiaHitObject { /// @@ -47,15 +22,19 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; - HitObject = hitObject; if (action != null) Action = action.Value; } + [BackgroundDependencyLoader] + private void load(ScrollingInfo scrollingInfo) + { + Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Origin = Anchor; + } + protected override void UpdateState(ArmedState state) { switch (state) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index a8666405cc..7e160befdc 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.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 osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -8,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -29,26 +31,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables CornerRadius = 5; Masking = true; - InternalChildren = new Drawable[] - { - headPiece = new NotePiece - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - } - }; + InternalChild = headPiece = new NotePiece(); } - public override ScrollingDirection Direction + [BackgroundDependencyLoader] + private void load(ScrollingInfo scrollingInfo) { - set - { - base.Direction = value; - - headPiece.Direction = value; - headPiece.Anchor = Anchor; - headPiece.Origin = Origin; - } + headPiece.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + headPiece.Origin = headPiece.Anchor; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 952ddd074e..707d1b5479 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -1,12 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces @@ -43,13 +45,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces }; } - public ScrollingDirection Direction + [BackgroundDependencyLoader] + private void load(ScrollingInfo scrollingInfo) { - set - { - colouredBox.Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - colouredBox.Origin = colouredBox.Anchor; - } + colouredBox.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + colouredBox.Origin = colouredBox.Anchor; } private Color4 accentColour; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 26269ff537..f62d91a52b 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -9,7 +9,6 @@ using osu.Game.Rulesets.Objects.Drawables; using System.Linq; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; @@ -57,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.UI Masking = true; CornerRadius = 5; - background = new ColumnBackground(direction) { RelativeSizeAxes = Axes.Both }; + background = new ColumnBackground { RelativeSizeAxes = Axes.Both }; InternalChildren = new[] { @@ -74,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.UI }, Children = new Drawable[] { - hitObjectArea = new ColumnHitObjectArea(direction) { RelativeSizeAxes = Axes.Both }, + hitObjectArea = new ColumnHitObjectArea { RelativeSizeAxes = Axes.Both }, explosionContainer = new Container { Name = "Hit explosions", @@ -82,7 +81,7 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - keyArea = new ColumnKeyArea(direction) + keyArea = new ColumnKeyArea { Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, @@ -134,9 +133,6 @@ namespace osu.Game.Rulesets.Mania.UI /// The DrawableHitObject to add. public override void Add(DrawableHitObject hitObject) { - var maniaObject = (DrawableManiaHitObject)hitObject; - maniaObject.Direction = direction; - hitObject.AccentColour = AccentColour; hitObject.OnJudgement += OnJudgement; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index b71dae035e..6492380f01 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -18,19 +18,16 @@ namespace osu.Game.Rulesets.Mania.UI.Components { public ManiaAction Action; - private readonly ScrollingDirection direction; - private Box background; private Box backgroundOverlay; - public ColumnBackground(ScrollingDirection direction) - { - this.direction = direction; - } + private ScrollingInfo scrollingInfo; [BackgroundDependencyLoader] - private void load() + private void load(ScrollingInfo scrollingInfo) { + this.scrollingInfo = scrollingInfo; + InternalChildren = new[] { background = new Box @@ -44,8 +41,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components Name = "Background Gradient Overlay", RelativeSizeAxes = Axes.Both, Height = 0.5f, - Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, Blending = BlendingMode.Additive, Alpha = 0 } @@ -84,8 +81,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components var dimPoint = AccentColour.Opacity(0); backgroundOverlay.Colour = ColourInfo.GradientVertical( - direction == ScrollingDirection.Up ? brightPoint : dimPoint, - direction == ScrollingDirection.Up ? dimPoint : brightPoint); + scrollingInfo.Direction == ScrollingDirection.Up ? brightPoint : dimPoint, + scrollingInfo.Direction == ScrollingDirection.Up ? dimPoint : brightPoint); } public bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 31df6d5fa3..cdea3870ab 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -20,32 +20,25 @@ namespace osu.Game.Rulesets.Mania.UI.Components private Container content; protected override Container Content => content; - private readonly ScrollingDirection direction; - private Container hitTargetBar; - public ColumnHitObjectArea(ScrollingDirection direction) - { - this.direction = direction; - } - [BackgroundDependencyLoader] - private void load() + private void load(ScrollingInfo scrollingInfo) { InternalChildren = new Drawable[] { new Box { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = hit_target_height, Colour = Color4.Black }, hitTargetBar = new Container { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = hit_target_bar_height, Masking = true, diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index e7fe44171b..56da7bc9b9 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -22,17 +22,10 @@ namespace osu.Game.Rulesets.Mania.UI.Components public ManiaAction Action; - private readonly ScrollingDirection direction; - private Container keyIcon; - public ColumnKeyArea(ScrollingDirection direction) - { - this.direction = direction; - } - [BackgroundDependencyLoader] - private void load() + private void load(ScrollingInfo scrollingInfo) { InternalChildren = new Drawable[] { @@ -41,8 +34,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components Name = "Key gradient", RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical( - direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), - direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black), + scrollingInfo.Direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), + scrollingInfo.Direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black), Alpha = 0.5f }, keyIcon = new Container diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index b7acd1d5ee..54a1b08ea3 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -36,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; + private ScrollingInfo scrollingInfo; + public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { @@ -73,7 +75,19 @@ namespace osu.Game.Rulesets.Mania.UI BarLines.ForEach(Playfield.Add); } - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(ScrollingDirection.Up, Beatmap.Stages) + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) + { + dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + + scrollingInfo = new ScrollingInfo(ScrollingDirection.Up); + dependencies.Cache(scrollingInfo); + + return dependencies; + } + + protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(scrollingInfo.Direction, Beatmap.Stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs b/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs new file mode 100644 index 0000000000..7772485982 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ScrollingInfo.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 + +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public class ScrollingInfo + { + public readonly ScrollingDirection Direction; + + public ScrollingInfo(ScrollingDirection direction) + { + Direction = direction; + } + } +} From baaf431b9ed11bff42b1487d9d6f5ac134d7e1c2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 21:41:20 +0900 Subject: [PATCH 33/68] Make IScrollingInfo and store direction as bindable --- .../ScrollingTestContainer.cs | 18 +++++++---- .../TestCaseColumn.cs | 2 +- .../TestCaseNotes.cs | 5 ++-- .../TestCaseStage.cs | 2 +- .../Objects/Drawables/DrawableHoldNote.cs | 13 +++----- .../Drawables/DrawableManiaHitObject.cs | 13 ++++++-- .../Objects/Drawables/DrawableNote.cs | 9 +++--- .../Objects/Drawables/Pieces/NotePiece.cs | 15 ++++++---- .../UI/Components/ColumnBackground.cs | 21 ++++++++----- .../UI/Components/ColumnHitObjectArea.cs | 30 ++++++++++++------- .../UI/Components/ColumnKeyArea.cs | 22 ++++++++++---- osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs | 17 +++++++++++ .../UI/ManiaRulesetContainer.cs | 12 ++++++-- osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs | 17 ----------- 14 files changed, 122 insertions(+), 74 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs delete mode 100644 osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs diff --git a/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs index 2b86c6187b..78a98e83e8 100644 --- a/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs @@ -2,28 +2,36 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Tests { /// - /// A container which provides a to children. + /// A container which provides a to children. /// public class ScrollingTestContainer : Container { - private readonly ScrollingInfo scrollingInfo; + private readonly ScrollingDirection direction; - public ScrollingTestContainer(ScrollingInfo scrollingInfo) + public ScrollingTestContainer(ScrollingDirection direction) { - this.scrollingInfo = scrollingInfo; + this.direction = direction; } protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); - dependencies.Cache(scrollingInfo); + dependencies.CacheAs(new ScrollingInfo { Direction = { Value = direction }}); return dependencies; } + + private class ScrollingInfo : IScrollingInfo + { + public readonly Bindable Direction = new Bindable(); + IBindable IScrollingInfo.Direction => Direction; + } } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index d5f43b809e..72f0b046b6 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Mania.Tests columns.Add(column); - return new ScrollingTestContainer(new ScrollingInfo(direction)) + return new ScrollingTestContainer(direction) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index 3342060fe2..4fdfac93b7 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -15,7 +15,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI.Scrolling; @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new Note { StartTime = 999999999 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - return new ScrollingTestContainer(new ScrollingInfo(direction)) + return new ScrollingTestContainer(direction) { AutoSizeAxes = Axes.Both, Child = new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") @@ -74,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new HoldNote { StartTime = 999999999, Duration = 1000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - return new ScrollingTestContainer(new ScrollingInfo(direction)) + return new ScrollingTestContainer(direction) { AutoSizeAxes = Axes.Both, Child = new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index 2f639494bb..d88896d855 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests { var specialAction = ManiaAction.Special1; - return new ScrollingTestContainer(new ScrollingInfo(direction)) + return new ScrollingTestContainer(direction) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 86bbc2c11d..3448d66ce1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; @@ -10,7 +9,6 @@ using OpenTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -38,8 +36,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// private bool hasBroken; - private ScrollingInfo scrollingInfo; - private readonly Container tickContainer; public DrawableHoldNote(HoldNote hitObject, ManiaAction action) @@ -80,12 +76,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(tail); } - [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + protected override void OnDirectionChanged(ScrollingDirection direction) { - this.scrollingInfo = scrollingInfo; + base.OnDirectionChanged(direction); - bodyPiece.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + bodyPiece.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; bodyPiece.Origin = bodyPiece.Anchor; } @@ -114,7 +109,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.Update(); // Make the body piece not lie under the head note - bodyPiece.Y = (scrollingInfo.Direction == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; + bodyPiece.Y = (Direction.Value == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; bodyPiece.Height = DrawHeight - head.Height / 2 + tail.Height / 2; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 59f93eb16a..01df4743c7 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public new TObject HitObject; + protected readonly IBindable Direction = new Bindable(); + protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { @@ -29,9 +32,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Direction.BindTo(scrollingInfo.Direction); + Direction.BindValueChanged(OnDirectionChanged, true); + } + + protected virtual void OnDirectionChanged(ScrollingDirection direction) + { + Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; Origin = Anchor; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 7e160befdc..b9b3fa7824 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -9,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -34,10 +32,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables InternalChild = headPiece = new NotePiece(); } - [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + protected override void OnDirectionChanged(ScrollingDirection direction) { - headPiece.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + base.OnDirectionChanged(direction); + + headPiece.Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; headPiece.Origin = headPiece.Anchor; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 707d1b5479..2c36b96f72 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -21,6 +22,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces public const float NOTE_HEIGHT = 10; private const float head_colour_height = 6; + private readonly IBindable direction = new Bindable(); + private readonly Box colouredBox; public NotePiece() @@ -36,8 +39,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces }, colouredBox = new Box { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, Height = head_colour_height, Alpha = 0.2f @@ -46,10 +47,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - colouredBox.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - colouredBox.Origin = colouredBox.Anchor; + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => + { + colouredBox.Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + colouredBox.Origin = colouredBox.Anchor; + }, true); } private Color4 accentColour; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 6492380f01..50303deda7 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -21,13 +22,11 @@ namespace osu.Game.Rulesets.Mania.UI.Components private Box background; private Box backgroundOverlay; - private ScrollingInfo scrollingInfo; + private readonly IBindable direction = new Bindable(); [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - this.scrollingInfo = scrollingInfo; - InternalChildren = new[] { background = new Box @@ -41,12 +40,18 @@ namespace osu.Game.Rulesets.Mania.UI.Components Name = "Background Gradient Overlay", RelativeSizeAxes = Axes.Both, Height = 0.5f, - Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, Blending = BlendingMode.Additive, Alpha = 0 } }; + + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => + { + backgroundOverlay.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + backgroundOverlay.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + updateColours(); + }, true); } protected override void LoadComplete() @@ -81,8 +86,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components var dimPoint = AccentColour.Opacity(0); backgroundOverlay.Colour = ColourInfo.GradientVertical( - scrollingInfo.Direction == ScrollingDirection.Up ? brightPoint : dimPoint, - scrollingInfo.Direction == ScrollingDirection.Up ? dimPoint : brightPoint); + direction.Value == ScrollingDirection.Up ? brightPoint : dimPoint, + direction.Value == ScrollingDirection.Up ? dimPoint : brightPoint); } public bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index cdea3870ab..4fa8ff4105 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,25 +21,25 @@ namespace osu.Game.Rulesets.Mania.UI.Components private Container content; protected override Container Content => content; - private Container hitTargetBar; + private readonly IBindable direction = new Bindable(); + + private Container hitTargetLine; [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - InternalChildren = new Drawable[] + Drawable hitTargetBar; + + InternalChildren = new[] { - new Box + hitTargetBar = new Box { - Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = hit_target_height, Colour = Color4.Black }, - hitTargetBar = new Container + hitTargetLine = new Container { - Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = hit_target_bar_height, Masking = true, @@ -50,6 +51,15 @@ namespace osu.Game.Rulesets.Mania.UI.Components RelativeSizeAxes = Axes.Both, }, }; + + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => + { + hitTargetBar.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + hitTargetBar.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + hitTargetLine.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + hitTargetLine.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + }, true); } protected override void LoadComplete() @@ -78,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components if (!IsLoaded) return; - hitTargetBar.EdgeEffect = new EdgeEffectParameters + hitTargetLine.EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, Radius = 5, diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index 56da7bc9b9..4ce1614310 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -22,20 +23,21 @@ namespace osu.Game.Rulesets.Mania.UI.Components public ManiaAction Action; + private readonly IBindable direction = new Bindable(); + private Container keyIcon; [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - InternalChildren = new Drawable[] + Drawable gradient; + + InternalChildren = new[] { - new Box + gradient = new Box { Name = "Key gradient", RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical( - scrollingInfo.Direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), - scrollingInfo.Direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black), Alpha = 0.5f }, keyIcon = new Container @@ -59,6 +61,14 @@ namespace osu.Game.Rulesets.Mania.UI.Components } } }; + + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => + { + gradient.Colour = ColourInfo.GradientVertical( + direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), + direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black); + }, true); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs b/osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs new file mode 100644 index 0000000000..ee65e9f1a5 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/IScrollinginfo.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 + +using osu.Framework.Configuration; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public interface IScrollingInfo + { + /// + /// The direction s should scroll in. + /// + IBindable Direction { get; } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 54a1b08ea3..1d32ac75eb 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; @@ -81,8 +82,9 @@ namespace osu.Game.Rulesets.Mania.UI { dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); - scrollingInfo = new ScrollingInfo(ScrollingDirection.Up); - dependencies.Cache(scrollingInfo); + scrollingInfo = new ScrollingInfo { Direction = { Value = ScrollingDirection.Up } }; + + dependencies.CacheAs(scrollingInfo); return dependencies; } @@ -119,5 +121,11 @@ namespace osu.Game.Rulesets.Mania.UI protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay); protected override IRulesetConfigManager CreateConfig(Ruleset ruleset, SettingsStore settings) => new ManiaConfigManager(settings, Ruleset.RulesetInfo, Variant); + + private class ScrollingInfo : IScrollingInfo + { + public readonly Bindable Direction = new Bindable(); + IBindable IScrollingInfo.Direction => Direction; + } } } diff --git a/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs b/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs deleted file mode 100644 index 7772485982..0000000000 --- a/osu.Game.Rulesets.Mania/UI/ScrollingInfo.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 - -using osu.Game.Rulesets.UI.Scrolling; - -namespace osu.Game.Rulesets.Mania.UI -{ - public class ScrollingInfo - { - public readonly ScrollingDirection Direction; - - public ScrollingInfo(ScrollingDirection direction) - { - Direction = direction; - } - } -} From f49b7d6e16407aa5b2d545acbf6bd12ee1ea54cf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 14:36:19 +0900 Subject: [PATCH 34/68] Add mania direction to settings --- .../Configuration/ManiaConfigManager.cs | 5 ++- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 3 ++ .../ManiaSettingsSubsection.cs | 34 +++++++++++++++++++ osu.Game.Rulesets.Mania/UI/Column.cs | 30 +++++++++------- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- .../UI/ManiaRulesetContainer.cs | 13 +++---- .../UI/ManiaScrollingDirection.cs | 13 +++++++ .../UI/ManiaScrollingPlayfield.cs | 26 ++++++++++++++ osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 2 +- osu.Game/Configuration/OsuConfigManager.cs | 2 +- .../Scrolling/ScrollingHitObjectContainer.cs | 13 ++++--- .../UI/Scrolling/ScrollingPlayfield.cs | 11 ++++-- 12 files changed, 121 insertions(+), 33 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs create mode 100644 osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs create mode 100644 osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs index d9e360081d..cb15d55934 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs @@ -4,6 +4,7 @@ using osu.Framework.Configuration.Tracking; using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; +using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Configuration { @@ -19,6 +20,7 @@ namespace osu.Game.Rulesets.Mania.Configuration base.InitialiseDefaults(); Set(ManiaSetting.ScrollTime, 1500.0, 50.0, 10000.0, 50.0); + Set(ManiaSetting.ScrollDirection, ManiaScrollingDirection.Up); } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings @@ -29,6 +31,7 @@ namespace osu.Game.Rulesets.Mania.Configuration public enum ManiaSetting { - ScrollTime + ScrollTime, + ScrollDirection } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index e671a3fb14..ccae0b609b 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -16,6 +16,7 @@ using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; +using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mania.Beatmaps; @@ -155,6 +156,8 @@ namespace osu.Game.Rulesets.Mania public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new ManiaConfigManager(settings, RulesetInfo); + public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this); + public ManiaRuleset(RulesetInfo rulesetInfo = null) : base(rulesetInfo) { diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs new file mode 100644 index 0000000000..54a7bf954d --- /dev/null +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania +{ + public class ManiaSettingsSubsection : RulesetSettingsSubsection + { + protected override string Header => "osu!mania"; + + public ManiaSettingsSubsection(ManiaRuleset ruleset) + : base(ruleset) + { + } + + [BackgroundDependencyLoader] + private void load(ManiaConfigManager config) + { + Children = new Drawable[] + { + new SettingsEnumDropdown + { + LabelText = "Scrolling direction", + Bindable = config.GetBindable(ManiaSetting.ScrollDirection) + } + }; + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index f62d91a52b..6a78143e41 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { - public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour + public class Column : ManiaScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { private const float column_width = 45; private const float special_column_width = 70; @@ -35,8 +35,6 @@ namespace osu.Game.Rulesets.Mania.UI } } - private readonly ScrollingDirection direction; - private readonly ColumnBackground background; private readonly ColumnKeyArea keyArea; private readonly ColumnHitObjectArea hitObjectArea; @@ -49,7 +47,6 @@ namespace osu.Game.Rulesets.Mania.UI public Column(ScrollingDirection direction) : base(direction) { - this.direction = direction; RelativeSizeAxes = Axes.Y; Width = column_width; @@ -58,19 +55,16 @@ namespace osu.Game.Rulesets.Mania.UI background = new ColumnBackground { RelativeSizeAxes = Axes.Both }; + Container hitTargetContainer; + InternalChildren = new[] { // For input purposes, the background is added at the highest depth, but is then proxied back below all other elements background.CreateProxy(), - new Container + hitTargetContainer = new Container { Name = "Hit target + hit objects", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Top = direction == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, - Bottom = direction == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, - }, Children = new Drawable[] { hitObjectArea = new ColumnHitObjectArea { RelativeSizeAxes = Axes.Both }, @@ -83,8 +77,6 @@ namespace osu.Game.Rulesets.Mania.UI }, keyArea = new ColumnKeyArea { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = ManiaStage.HIT_TARGET_POSITION, }, @@ -93,6 +85,18 @@ namespace osu.Game.Rulesets.Mania.UI }; TopLevelContainer.Add(explosionContainer.CreateProxy()); + + Direction.BindValueChanged(d => + { + hitTargetContainer.Padding = new MarginPadding + { + Top = d == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, + Bottom = d == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, + }; + + keyArea.Anchor = d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + keyArea.Origin = d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + }, true); } public override Axes RelativeSizeAxes => Axes.Y; @@ -146,7 +150,7 @@ namespace osu.Game.Rulesets.Mania.UI explosionContainer.Add(new HitExplosion(judgedObject) { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre + Anchor = Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre }); } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 73362ab28f..2f8ad7b17e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -16,7 +16,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaPlayfield : ScrollingPlayfield + public class ManiaPlayfield : ManiaScrollingPlayfield { public List Columns => stages.SelectMany(x => x.Columns).ToList(); private readonly List stages = new List(); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index eaad787999..fa6fba0cd8 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Handlers; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -34,6 +35,7 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; + private readonly Bindable configDirection = new Bindable(); private ScrollingInfo scrollingInfo; public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) @@ -68,9 +70,12 @@ namespace osu.Game.Rulesets.Mania.UI } [BackgroundDependencyLoader] - private void load() + private void load(ManiaConfigManager config) { BarLines.ForEach(Playfield.Add); + + config.BindWith(ManiaSetting.ScrollDirection, configDirection); + configDirection.BindValueChanged(d => scrollingInfo.Direction.Value = (ScrollingDirection)d, true); } private DependencyContainer dependencies; @@ -78,11 +83,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) { dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); - - scrollingInfo = new ScrollingInfo { Direction = { Value = ScrollingDirection.Up } }; - - dependencies.CacheAs(scrollingInfo); - + dependencies.CacheAs(scrollingInfo = new ScrollingInfo()); return dependencies; } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs new file mode 100644 index 0000000000..0fc9c1920a --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public enum ManiaScrollingDirection + { + Up = ScrollingDirection.Up, + Down = ScrollingDirection.Down + } +} diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs new file mode 100644 index 0000000000..f1ff0665cd --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public class ManiaScrollingPlayfield : ScrollingPlayfield + { + private readonly IBindable direction = new Bindable(); + + public ManiaScrollingPlayfield(ScrollingDirection direction) + : base(direction) + { + } + + [BackgroundDependencyLoader] + private void load(IScrollingInfo scrollingInfo) + { + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => Direction.Value = direction, true); + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 822042362f..3ff14ed0c6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.UI /// /// A collection of s. /// - internal class ManiaStage : ScrollingPlayfield + internal class ManiaStage : ManiaScrollingPlayfield { public const float HIT_TARGET_POSITION = 50; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 597960c352..1bb2ac4678 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -147,6 +147,6 @@ namespace osu.Game.Configuration SongSelectRightMouseScroll, BeatmapSkins, BeatmapHitsounds, - IncreaseFirstObjectVisibility + IncreaseFirstObjectVisibility, } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 36c6b07f54..c64fca6eff 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -29,17 +29,16 @@ namespace osu.Game.Rulesets.UI.Scrolling /// protected readonly SortedList ControlPoints = new SortedList(); - private readonly ScrollingDirection direction; + public readonly Bindable Direction = new Bindable(); private Cached initialStateCache = new Cached(); - public ScrollingHitObjectContainer(ScrollingDirection direction) + public ScrollingHitObjectContainer() { - this.direction = direction; - RelativeSizeAxes = Axes.Both; - TimeRange.ValueChanged += v => initialStateCache.Invalidate(); + TimeRange.ValueChanged += _ => initialStateCache.Invalidate(); + Direction.ValueChanged += _ => initialStateCache.Invalidate(); } private ISpeedChangeVisualiser speedChangeVisualiser; @@ -100,7 +99,7 @@ namespace osu.Game.Rulesets.UI.Scrolling if (!initialStateCache.IsValid) { - speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); + speedChangeVisualiser.ComputeInitialStates(Objects, Direction, TimeRange, DrawSize); initialStateCache.Validate(); } } @@ -110,7 +109,7 @@ namespace osu.Game.Rulesets.UI.Scrolling base.UpdateAfterChildrenLife(); // We need to calculate this as soon as possible after lifetimes so that hitobjects get the final say in their positions - speedChangeVisualiser.UpdatePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); + speedChangeVisualiser.UpdatePositions(AliveObjects, Direction, Time.Current, TimeRange, DrawSize); } } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 6f86d20295..b7f6844245 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -54,7 +54,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; - private readonly ScrollingDirection direction; + protected readonly Bindable Direction = new Bindable(); /// /// Creates a new . @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.UI.Scrolling protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null, float? customHeight = null) : base(customWidth, customHeight) { - this.direction = direction; + Direction.Value = direction; } [BackgroundDependencyLoader] @@ -99,6 +99,11 @@ namespace osu.Game.Rulesets.UI.Scrolling return false; } - protected sealed override HitObjectContainer CreateHitObjectContainer() => new ScrollingHitObjectContainer(direction); + protected sealed override HitObjectContainer CreateHitObjectContainer() + { + var container = new ScrollingHitObjectContainer(); + container.Direction.BindTo(Direction); + return container; + } } } From 162237dc46cf28225a2caa1075d97eefcac5af8c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 15:43:15 +0900 Subject: [PATCH 35/68] Fix bar lines being offset --- .../TestCaseStage.cs | 64 ++++++++++++++++++- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 18 ++++-- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index d88896d855..0f90c1f16b 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -1,11 +1,16 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; using OpenTK; @@ -15,8 +20,12 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestCaseStage : ManiaInputTestCase { + private const int columns = 4; + + private readonly List stages = new List(); + public TestCaseStage() - : base(4) + : base(columns) { } @@ -37,17 +46,68 @@ namespace osu.Game.Rulesets.Mania.Tests }; } + protected override void LoadComplete() + { + base.LoadComplete(); + + AddStep("note", createNote); + AddStep("hold note", createHoldNote); + AddStep("bar line", createBarLine); + } + + private void createNote() + { + foreach (var stage in stages) + { + for (int i = 0; i < stage.Columns.Count; i++) + { + var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + stage.Add(new DrawableNote(obj, stage.Columns[i].Action)); + } + } + } + + private void createHoldNote() + { + foreach (var stage in stages) + { + for (int i = 0; i < stage.Columns.Count; i++) + { + var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + stage.Add(new DrawableHoldNote(obj, stage.Columns[i].Action)); + } + } + } + + private void createBarLine() + { + foreach (var stage in stages) + { + var obj = new BarLine { StartTime = Time.Current + 2000, ControlPoint = new TimingControlPoint() }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + stage.Add(obj); + } + } + private Drawable createStage(ScrollingDirection direction, ManiaAction action) { var specialAction = ManiaAction.Special1; + var stage = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction); + stages.Add(stage); + return new ScrollingTestContainer(direction) { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, - Child = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) + Child = stage }; } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 3ff14ed0c6..7b68582944 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Mania.UI public IReadOnlyList Columns => columnFlow.Children; private readonly FillFlowContainer columnFlow; - protected override Container Content => content; - private readonly Container content; + protected override Container Content => barLineContainer; + private readonly Container barLineContainer; public Container Judgements => judgements; private readonly JudgementContainer judgements; @@ -100,13 +100,12 @@ namespace osu.Game.Rulesets.Mania.UI Width = 1366, // Bar lines should only be masked on the vertical axis BypassAutoSizeAxes = Axes.Both, Masking = true, - Child = content = new Container + Child = barLineContainer = new Container { Name = "Bar lines", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding { Top = HIT_TARGET_POSITION } } }, judgements = new JudgementContainer @@ -133,6 +132,15 @@ namespace osu.Game.Rulesets.Mania.UI AddColumn(column); } + + Direction.BindValueChanged(d => + { + barLineContainer.Padding = new MarginPadding + { + Top = d == ScrollingDirection.Up ? HIT_TARGET_POSITION : 0, + Bottom = d == ScrollingDirection.Down ? HIT_TARGET_POSITION : 0, + }; + }, true); } public void AddColumn(Column c) @@ -203,7 +211,7 @@ namespace osu.Game.Rulesets.Mania.UI { // Due to masking differences, it is not possible to get the width of the columns container automatically // While masking on effectively only the Y-axis, so we need to set the width of the bar line container manually - content.Width = columnFlow.Width; + barLineContainer.Width = columnFlow.Width; } } } From b9bf3a1829002036201e96c8359519add545e172 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 15:56:30 +0900 Subject: [PATCH 36/68] Make mania scroll downwards by default --- osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs index cb15d55934..3e9c9feba1 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Configuration base.InitialiseDefaults(); Set(ManiaSetting.ScrollTime, 1500.0, 50.0, 10000.0, 50.0); - Set(ManiaSetting.ScrollDirection, ManiaScrollingDirection.Up); + Set(ManiaSetting.ScrollDirection, ManiaScrollingDirection.Down); } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings From 10d1dfa7cd4ab3a858883f695dfaa921de1c0431 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 16:10:27 +0900 Subject: [PATCH 37/68] A bit of cleanup --- .../Objects/Drawables/DrawableHoldNote.cs | 3 +-- .../Objects/Drawables/DrawableManiaHitObject.cs | 3 +-- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 3 +-- .../Objects/Drawables/Pieces/NotePiece.cs | 3 +-- osu.Game.Rulesets.Mania/UI/Column.cs | 3 +-- osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs | 3 +-- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 5 +---- 7 files changed, 7 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 3448d66ce1..ce0276f759 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -80,8 +80,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { base.OnDirectionChanged(direction); - bodyPiece.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - bodyPiece.Origin = bodyPiece.Anchor; + bodyPiece.Anchor = bodyPiece.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 01df4743c7..1271fae0c1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -40,8 +40,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected virtual void OnDirectionChanged(ScrollingDirection direction) { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - Origin = Anchor; + Anchor = Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } protected override void UpdateState(ArmedState state) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index b9b3fa7824..fb4aa74ad1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -36,8 +36,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { base.OnDirectionChanged(direction); - headPiece.Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - headPiece.Origin = headPiece.Anchor; + headPiece.Anchor = headPiece.Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 2c36b96f72..2c74f5b168 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -52,8 +52,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces direction.BindTo(scrollingInfo.Direction); direction.BindValueChanged(direction => { - colouredBox.Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - colouredBox.Origin = colouredBox.Anchor; + colouredBox.Anchor = colouredBox.Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; }, true); } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 6a78143e41..fafc875706 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -94,8 +94,7 @@ namespace osu.Game.Rulesets.Mania.UI Bottom = d == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, }; - keyArea.Anchor = d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - keyArea.Origin = d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + keyArea.Anchor = keyArea.Origin= d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 50303deda7..9b744bd254 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -48,8 +48,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components direction.BindTo(scrollingInfo.Direction); direction.BindValueChanged(direction => { - backgroundOverlay.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - backgroundOverlay.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + backgroundOverlay.Anchor = backgroundOverlay.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; updateColours(); }, true); } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 4fa8ff4105..6d6edff3f4 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -55,10 +55,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components direction.BindTo(scrollingInfo.Direction); direction.BindValueChanged(direction => { - hitTargetBar.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - hitTargetBar.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - hitTargetLine.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - hitTargetLine.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + hitTargetBar.Anchor = hitTargetBar.Origin = hitTargetLine.Anchor = hitTargetLine.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); } From a36dab638aec66fe4c50eb7b874a1984910334ce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 16:12:52 +0900 Subject: [PATCH 38/68] Improve TestCaseStage --- osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index 0f90c1f16b..9aff853ffd 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -52,7 +52,8 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("note", createNote); AddStep("hold note", createHoldNote); - AddStep("bar line", createBarLine); + AddStep("minor bar line", () => createBarLine(false)); + AddStep("major bar line", () => createBarLine(true)); } private void createNote() @@ -83,11 +84,17 @@ namespace osu.Game.Rulesets.Mania.Tests } } - private void createBarLine() + private void createBarLine(bool major) { foreach (var stage in stages) { - var obj = new BarLine { StartTime = Time.Current + 2000, ControlPoint = new TimingControlPoint() }; + var obj = new BarLine + { + StartTime = Time.Current + 2000, + ControlPoint = new TimingControlPoint(), + BeatIndex = major ? 0 : 1 + }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); stage.Add(obj); @@ -98,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Tests { var specialAction = ManiaAction.Special1; - var stage = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction); + var stage = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) { VisibleTimeRange = { Value = 2000 } }; stages.Add(stage); return new ScrollingTestContainer(direction) From 3bad319dd2995c242ddc74c433a039699928f78e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 16:19:57 +0900 Subject: [PATCH 39/68] Fix filename --- .../UI/{IScrollinginfo.cs => IScrollingInfo.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Mania/UI/{IScrollinginfo.cs => IScrollingInfo.cs} (100%) diff --git a/osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs b/osu.Game.Rulesets.Mania/UI/IScrollingInfo.cs similarity index 100% rename from osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs rename to osu.Game.Rulesets.Mania/UI/IScrollingInfo.cs From 22add2abc5a443ee63fc711a27af2e7dc60c8313 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 16:25:44 +0900 Subject: [PATCH 40/68] Move mania difficulty attributes to ManiaDifficultyCalculator --- .../Difficulty/ManiaDifficultyAttributes.cs | 18 ++++++++++++++++++ .../Difficulty/ManiaDifficultyCalculator.cs | 7 ++++++- .../Difficulty/ManiaPerformanceCalculator.cs | 8 ++++---- 3 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs new file mode 100644 index 0000000000..c7f6890b93 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Difficulty +{ + public class ManiaDifficultyAttributes : DifficultyAttributes + { + public double GreatHitWindow; + + public ManiaDifficultyAttributes(Mod[] mods, double starRating) + : base(mods, starRating) + { + } + } +} diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 9c091ac31a..525426df2d 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -47,9 +47,14 @@ namespace osu.Game.Rulesets.Mania.Difficulty if (!calculateStrainValues(difficultyHitObjects, timeRate)) return new DifficultyAttributes(mods, 0); + double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - return new DifficultyAttributes(mods, starRating); + return new ManiaDifficultyAttributes(mods, starRating) + { + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future + GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate + }; } private bool calculateStrainValues(List objects, double timeRate) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index b6089b830b..1f26bda1b2 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -13,6 +13,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty { public class ManiaPerformanceCalculator : PerformanceCalculator { + protected new ManiaDifficultyAttributes Attributes => (ManiaDifficultyAttributes)base.Attributes; + private Mod[] mods; // Score after being scaled by non-difficulty-increasing mods @@ -105,14 +107,12 @@ namespace osu.Game.Rulesets.Mania.Difficulty private double computeAccuracyValue(double strainValue) { - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; - if (hitWindowGreat <= 0) + if (Attributes.GreatHitWindow <= 0) return 0; // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Max(0.0, 0.2 - (hitWindowGreat - 34) * 0.006667) + double accuracyValue = Math.Max(0.0, 0.2 - (Attributes.GreatHitWindow - 34) * 0.006667) * strainValue * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); From 01dd2d79198202216c439f5827cf436957bbf1a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 16:26:51 +0900 Subject: [PATCH 41/68] Move taiko difficulty attributes to TaikoDifficultyCalculator --- .../Difficulty/TaikoDifficultyAttributes.cs | 19 +++++++++++++++++++ .../Difficulty/TaikoDifficultyCalculator.cs | 8 +++++++- .../Difficulty/TaikoPerformanceCalculator.cs | 14 +++++--------- 3 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs new file mode 100644 index 0000000000..d18d03b1db --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Difficulty +{ + public class TaikoDifficultyAttributes : DifficultyAttributes + { + public double GreatHitWindow; + public int MaxCombo; + + public TaikoDifficultyAttributes(Mod[] mods, double starRating) + : base(mods, starRating) + { + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 473c205293..190717e024 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; @@ -47,7 +48,12 @@ namespace osu.Game.Rulesets.Taiko.Difficulty double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - return new DifficultyAttributes(mods, starRating); + return new TaikoDifficultyAttributes(mods, starRating) + { + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future + GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate, + MaxCombo = beatmap.HitObjects.Count(h => h is Hit) + }; } private bool calculateStrainValues(List objects, double timeRate) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 53cfb4fd0f..f530b6725c 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -8,13 +8,12 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Difficulty { public class TaikoPerformanceCalculator : PerformanceCalculator { - private readonly int beatmapMaxCombo; + protected new TaikoDifficultyAttributes Attributes => (TaikoDifficultyAttributes)base.Attributes; private Mod[] mods; private int countGreat; @@ -25,7 +24,6 @@ namespace osu.Game.Rulesets.Taiko.Difficulty public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) : base(ruleset, beatmap, score) { - beatmapMaxCombo = Beatmap.HitObjects.Count(h => h is Hit); } public override double Calculate(Dictionary categoryDifficulty = null) @@ -78,8 +76,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty strainValue *= Math.Pow(0.985, countMiss); // Combo scaling - if (beatmapMaxCombo > 0) - strainValue *= Math.Min(Math.Pow(Score.MaxCombo, 0.5) / Math.Pow(beatmapMaxCombo, 0.5), 1.0); + if (Attributes.MaxCombo > 0) + strainValue *= Math.Min(Math.Pow(Score.MaxCombo, 0.5) / Math.Pow(Attributes.MaxCombo, 0.5), 1.0); if (mods.Any(m => m is ModHidden)) strainValue *= 1.025; @@ -94,14 +92,12 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private double computeAccuracyValue() { - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; - if (hitWindowGreat <= 0) + if (Attributes.GreatHitWindow <= 0) return 0; // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accValue = Math.Pow(150.0 / hitWindowGreat, 1.1) * Math.Pow(Score.Accuracy, 15) * 22.0; + double accValue = Math.Pow(150.0 / Attributes.GreatHitWindow, 1.1) * Math.Pow(Score.Accuracy, 15) * 22.0; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer return accValue * Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); From 41abd5990cc9adcf6e3865b7149fcf9b7f1747a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 16:27:05 +0900 Subject: [PATCH 42/68] Move osu! difficulty attributes to OsuDifficultyCalculator --- .../Difficulty/OsuDifficultyAttributes.cs | 3 ++ .../Difficulty/OsuDifficultyCalculator.cs | 13 ++++++- .../Difficulty/OsuPerformanceCalculator.cs | 39 ++++++------------- 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs index 50a259ae55..2b42eed0c5 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -10,6 +10,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty { public double AimStrain; public double SpeedStrain; + public double ApproachRate; + public double OverallDifficulty; + public int MaxCombo; public OsuDifficultyAttributes(Mod[] mods, double starRating) : base(mods, starRating) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 400afbc043..4386004e30 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -58,10 +58,21 @@ namespace osu.Game.Rulesets.Osu.Difficulty double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2; + // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future + double hitWindowGreat = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate; + double preEmpt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / timeRate; + + int maxCombo = beatmap.HitObjects.Count(); + // Add the ticks + tail of the slider. 1 is subtracted because the "headcircle" would be counted twice (once for the slider itself in the line above) + maxCombo += beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count - 1); + return new OsuDifficultyAttributes(mods, starRating) { AimStrain = aimRating, - SpeedStrain = speedRating + SpeedStrain = speedRating, + ApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5, + OverallDifficulty = (80 - hitWindowGreat) / 6, + MaxCombo = maxCombo }; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 3ab3cc879a..d4a60dd52f 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -22,16 +22,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty private Mod[] mods; - /// - /// Approach rate adjusted by mods. - /// - private double realApproachRate; - - /// - /// Overall difficulty adjusted by mods. - /// - private double realOverallDifficulty; - private double accuracy; private int scoreMaxCombo; private int countGreat; @@ -63,13 +53,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (mods.Any(m => !m.Ranked)) return 0; - // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; - double preEmpt = (int)BeatmapDifficulty.DifficultyRange(Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / TimeRate; - - realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; - realOverallDifficulty = (80 - hitWindowGreat) / 6; - // Custom multipliers for NoFail and SpunOut. double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things @@ -94,8 +77,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty categoryRatings.Add("Aim", aimValue); categoryRatings.Add("Speed", speedValue); categoryRatings.Add("Accuracy", accuracyValue); - categoryRatings.Add("OD", realOverallDifficulty); - categoryRatings.Add("AR", realApproachRate); + categoryRatings.Add("OD", Attributes.OverallDifficulty); + categoryRatings.Add("AR", Attributes.ApproachRate); categoryRatings.Add("Max Combo", beatmapMaxCombo); } @@ -120,22 +103,22 @@ namespace osu.Game.Rulesets.Osu.Difficulty aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); double approachRateFactor = 1.0f; - if (realApproachRate > 10.33f) - approachRateFactor += 0.45f * (realApproachRate - 10.33f); - else if (realApproachRate < 8.0f) + if (Attributes.ApproachRate > 10.33f) + approachRateFactor += 0.45f * (Attributes.ApproachRate - 10.33f); + else if (Attributes.ApproachRate < 8.0f) { // HD is worth more with lower ar! if (mods.Any(h => h is OsuModHidden)) - approachRateFactor += 0.02f * (8.0f - realApproachRate); + approachRateFactor += 0.02f * (8.0f - Attributes.ApproachRate); else - approachRateFactor += 0.01f * (8.0f - realApproachRate); + approachRateFactor += 0.01f * (8.0f - Attributes.ApproachRate); } aimValue *= approachRateFactor; // We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR. if (mods.Any(h => h is OsuModHidden)) - aimValue *= 1.02 + (11.0f - realApproachRate) / 50.0; // Gives a 1.04 bonus for AR10, a 1.06 bonus for AR9, a 1.02 bonus for AR11. + aimValue *= 1.02 + (11.0f - Attributes.ApproachRate) / 50.0; // Gives a 1.04 bonus for AR10, a 1.06 bonus for AR9, a 1.02 bonus for AR11. if (mods.Any(h => h is OsuModFlashlight)) { @@ -146,7 +129,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Scale the aim value with accuracy _slightly_ aimValue *= 0.5f + accuracy / 2.0f; // It is important to also consider accuracy difficulty when doing that - aimValue *= 0.98f + Math.Pow(realOverallDifficulty, 2) / 2500; + aimValue *= 0.98f + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; return aimValue; } @@ -172,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Scale the speed value with accuracy _slightly_ speedValue *= 0.5f + accuracy / 2.0f; // It is important to also consider accuracy difficulty when doing that - speedValue *= 0.98f + Math.Pow(realOverallDifficulty, 2) / 2500; + speedValue *= 0.98f + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; return speedValue; } @@ -194,7 +177,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Pow(1.52163f, realOverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f; + double accuracyValue = Math.Pow(1.52163f, Attributes.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer accuracyValue *= Math.Min(1.15f, Math.Pow(amountHitObjectsWithAccuracy / 1000.0f, 0.3f)); From cafdbc2d251626dd3dc624c9a7044db3e9828f5a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 18:39:26 +0900 Subject: [PATCH 43/68] Fix discarding too many RNG values, and add test --- .../CatchBeatmapConversionTest.cs | 12 +++ .../Beatmaps/CatchBeatmapProcessor.cs | 6 +- .../Beatmaps/spinner-expected-conversion.json | 74 +++++++++++++++++++ .../Resources/Testing/Beatmaps/spinner.osu | 20 +++++ 4 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-expected-conversion.json create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner.osu diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 5b34e46247..9de0ce3565 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests protected override string ResourceAssembly => "osu.Game.Rulesets.Catch"; [TestCase("basic"), Ignore("See: https://github.com/ppy/osu/issues/2232")] + [TestCase("spinner")] public new void Test(string name) { base.Test(name); @@ -35,6 +36,17 @@ namespace osu.Game.Rulesets.Catch.Tests }; } } + else if (hitObject is BananaShower shower) + { + foreach (var nested in shower.NestedHitObjects) + { + yield return new ConvertValue + { + StartTime = nested.StartTime, + Position = ((CatchHitObject)nested).X * CatchPlayfield.BASE_WIDTH + }; + } + } else { yield return new ConvertValue diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 869bc560a8..a9fbc8bcb2 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -48,10 +48,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps foreach (var nested in bananaShower.NestedHitObjects) { ((BananaShower.Banana)nested).X = (float)rng.NextDouble(); - // discarding 3 times - rng.Next(); - rng.Next(); - rng.Next(); + rng.Next(); // osu!stable retrieved a random banana type + rng.Next(); // osu!stable retrieved a random banana rotation } break; case JuiceStream juiceStream: diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-expected-conversion.json new file mode 100644 index 0000000000..933adb4acc --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-expected-conversion.json @@ -0,0 +1,74 @@ +{ + "Mappings": [{ + "StartTime": 18500, + "Objects": [{ + "StartTime": 18500, + "Position": 65 + }, + { + "StartTime": 18559, + "Position": 459 + }, + { + "StartTime": 18618, + "Position": 255 + }, + { + "StartTime": 18678, + "Position": 113 + }, + { + "StartTime": 18737, + "Position": 315 + }, + { + "StartTime": 18796, + "Position": 17 + }, + { + "StartTime": 18856, + "Position": 482 + }, + { + "StartTime": 18915, + "Position": 44 + }, + { + "StartTime": 18975, + "Position": 310 + }, + { + "StartTime": 19034, + "Position": 244 + }, + { + "StartTime": 19093, + "Position": 18 + }, + { + "StartTime": 19153, + "Position": 482 + }, + { + "StartTime": 19212, + "Position": 243 + }, + { + "StartTime": 19271, + "Position": 332 + }, + { + "StartTime": 19331, + "Position": 477 + }, + { + "StartTime": 19390, + "Position": 376 + }, + { + "StartTime": 19450, + "Position": 104 + } + ] + }] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner.osu b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner.osu new file mode 100644 index 0000000000..0fbd4dbf42 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner.osu @@ -0,0 +1,20 @@ +osu file format v14 + +[General] +Mode: 2 + +[Difficulty] +HPDrainRate:6 +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8.3 +SliderMultiplier:1.6 +SliderTickRate:1 + +[TimingPoints] +500,500,4,2,1,50,1,0 +13426,-100,4,3,1,45,0,0 +14884,-100,4,2,1,50,0,0 + +[HitObjects] +256,192,18500,12,0,19450,0:0:0:0: From a97a7e13bd492a87b3ab7695307ff66bd87f0cf7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 19:52:04 +0900 Subject: [PATCH 44/68] Rework RNG discarding comment --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index a9fbc8bcb2..a146617182 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -56,13 +56,9 @@ namespace osu.Game.Rulesets.Catch.Beatmaps foreach (var nested in juiceStream.NestedHitObjects) { if (nested is TinyDroplet tinyDroplet) - { tinyDroplet.X += rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH; - } else if (nested is Droplet) - { - rng.Next(); // Big droplets are not slided - } + rng.Next(); // osu!stable retrieved a random droplet rotation } break; } From 9b403b0053519266bfb0dfb74313adcf42ff090b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 19:56:00 +0900 Subject: [PATCH 45/68] Fix non-catch beatmaps not getting properly converted Because Osu.ConvertSpinner implements IHasXPosition. --- .../Beatmaps/CatchBeatmapConverter.cs | 46 ++++++++----------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index ad500606ed..46fe8454dc 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -27,22 +27,6 @@ namespace osu.Game.Rulesets.Catch.Beatmaps var comboData = obj as IHasCombo; var endTime = obj as IHasEndTime; - if (positionData == null) - { - if (endTime != null) - { - yield return new BananaShower - { - StartTime = obj.StartTime, - Samples = obj.Samples, - Duration = endTime.Duration, - NewCombo = comboData?.NewCombo ?? false - }; - } - - yield break; - } - if (curveData != null) { yield return new JuiceStream @@ -54,20 +38,30 @@ namespace osu.Game.Rulesets.Catch.Beatmaps Distance = curveData.Distance, RepeatSamples = curveData.RepeatSamples, RepeatCount = curveData.RepeatCount, - X = positionData.X / CatchPlayfield.BASE_WIDTH, + X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH, NewCombo = comboData?.NewCombo ?? false }; - - yield break; } - - yield return new Fruit + else if (endTime != null) { - StartTime = obj.StartTime, - Samples = obj.Samples, - NewCombo = comboData?.NewCombo ?? false, - X = positionData.X / CatchPlayfield.BASE_WIDTH - }; + yield return new BananaShower + { + StartTime = obj.StartTime, + Samples = obj.Samples, + Duration = endTime.Duration, + NewCombo = comboData?.NewCombo ?? false + }; + } + else + { + yield return new Fruit + { + StartTime = obj.StartTime, + Samples = obj.Samples, + NewCombo = comboData?.NewCombo ?? false, + X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH + }; + } } protected override Beatmap CreateBeatmap() => new CatchBeatmap(); From 250e8645e19ecb4f4cdbde14643cfcf25ea7e1ba Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 20:11:27 +0900 Subject: [PATCH 46/68] finalisePosition -> applyPositionOffsets --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index a146617182..1ac1643297 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps public override void PostProcess() { - finalizePosition(); + applyPositionOffsets(); initialiseHyperDash((List)Beatmap.HitObjects); @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps public const int RNG_SEED = 1337; - private void finalizePosition() + private void applyPositionOffsets() { var rng = new FastRandom(RNG_SEED); // todo: HardRock displacement should be applied here From e1f549892475d27b11121dfcb9c96cf3e9c7c414 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 21:10:54 +0900 Subject: [PATCH 47/68] Discarding 3 times is correct --- .../Beatmaps/CatchBeatmapProcessor.cs | 1 + .../Beatmaps/spinner-expected-conversion.json | 62 +++++++++---------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 1ac1643297..2768357034 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -50,6 +50,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps ((BananaShower.Banana)nested).X = (float)rng.NextDouble(); rng.Next(); // osu!stable retrieved a random banana type rng.Next(); // osu!stable retrieved a random banana rotation + rng.Next(); // osu!stable retrieved a random banana colour } break; case JuiceStream juiceStream: diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-expected-conversion.json index 933adb4acc..b69b1ae056 100644 --- a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-expected-conversion.json +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-expected-conversion.json @@ -7,67 +7,67 @@ }, { "StartTime": 18559, - "Position": 459 + "Position": 482 }, { "StartTime": 18618, - "Position": 255 + "Position": 164 }, { "StartTime": 18678, - "Position": 113 - }, - { - "StartTime": 18737, "Position": 315 }, + { + "StartTime": 18737, + "Position": 145 + }, { "StartTime": 18796, - "Position": 17 + "Position": 159 }, { "StartTime": 18856, - "Position": 482 - }, - { - "StartTime": 18915, - "Position": 44 - }, - { - "StartTime": 18975, "Position": 310 }, + { + "StartTime": 18915, + "Position": 441 + }, + { + "StartTime": 18975, + "Position": 428 + }, { "StartTime": 19034, - "Position": 244 - }, - { - "StartTime": 19093, - "Position": 18 - }, - { - "StartTime": 19153, - "Position": 482 - }, - { - "StartTime": 19212, "Position": 243 }, + { + "StartTime": 19093, + "Position": 422 + }, + { + "StartTime": 19153, + "Position": 481 + }, + { + "StartTime": 19212, + "Position": 104 + }, { "StartTime": 19271, - "Position": 332 + "Position": 473 }, { "StartTime": 19331, - "Position": 477 + "Position": 135 }, { "StartTime": 19390, - "Position": 376 + "Position": 360 }, { "StartTime": 19450, - "Position": 104 + "Position": 123 } ] }] From ced4e61b54a320e2307cc60e395035b574747c8b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 21:11:56 +0900 Subject: [PATCH 48/68] Adjust expected output with spinner changes --- .../Beatmaps/basic-expected-conversion.json | 2226 ++++++++++------- 1 file changed, 1272 insertions(+), 954 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/basic-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/basic-expected-conversion.json index 9357d3b75c..8ede7b6719 100644 --- a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/basic-expected-conversion.json +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/basic-expected-conversion.json @@ -1,957 +1,1275 @@ { "Mappings": [{ - "StartTime": 500.0, - "Objects": [{ - "StartTime": 500.0, - "Position": 96.0 - }, { - "StartTime": 562.0, - "Position": 100.84 - }, { - "StartTime": 625.0, - "Position": 125.0 - }, { - "StartTime": 687.0, - "Position": 152.84 - }, { - "StartTime": 750.0, - "Position": 191.0 - }, { - "StartTime": 812.0, - "Position": 212.84 - }, { - "StartTime": 875.0, - "Position": 217.0 - }, { - "StartTime": 937.0, - "Position": 234.84 - }, { - "StartTime": 1000.0, - "Position": 256.0 - }, { - "StartTime": 1062.0, - "Position": 267.84 - }, { - "StartTime": 1125.0, - "Position": 284.0 - }, { - "StartTime": 1187.0, - "Position": 311.84 - }, { - "StartTime": 1250.0, - "Position": 350.0 - }, { - "StartTime": 1312.0, - "Position": 359.84 - }, { - "StartTime": 1375.0, - "Position": 367.0 - }, { - "StartTime": 1437.0, - "Position": 400.84 - }, { - "StartTime": 1500.0, - "Position": 416.0 - }, { - "StartTime": 1562.0, - "Position": 377.159973 - }, { - "StartTime": 1625.0, - "Position": 367.0 - }, { - "StartTime": 1687.0, - "Position": 374.159973 - }, { - "StartTime": 1750.0, - "Position": 353.0 - }, { - "StartTime": 1812.0, - "Position": 329.159973 - }, { - "StartTime": 1875.0, - "Position": 288.0 - }, { - "StartTime": 1937.0, - "Position": 259.159973 - }, { - "StartTime": 2000.0, - "Position": 256.0 - }, { - "StartTime": 2058.0, - "Position": 232.44 - }, { - "StartTime": 2116.0, - "Position": 222.879974 - }, { - "StartTime": 2174.0, - "Position": 185.319992 - }, { - "StartTime": 2232.0, - "Position": 177.76001 - }, { - "StartTime": 2290.0, - "Position": 162.200012 - }, { - "StartTime": 2348.0, - "Position": 158.639984 - }, { - "StartTime": 2406.0, - "Position": 111.079994 - }, { - "StartTime": 2500.0, - "Position": 96.0 - }] - }, { - "StartTime": 3000.0, - "Objects": [{ - "StartTime": 3000.0, - "Position": 18.0 - }, { - "StartTime": 3062.0, - "Position": 482.0 - }, { - "StartTime": 3125.0, - "Position": 243.0 - }, { - "StartTime": 3187.0, - "Position": 332.0 - }, { - "StartTime": 3250.0, - "Position": 477.0 - }, { - "StartTime": 3312.0, - "Position": 376.0 - }, { - "StartTime": 3375.0, - "Position": 104.0 - }, { - "StartTime": 3437.0, - "Position": 156.0 - }, { - "StartTime": 3500.0, - "Position": 135.0 - }, { - "StartTime": 3562.0, - "Position": 256.0 - }, { - "StartTime": 3625.0, - "Position": 360.0 - }, { - "StartTime": 3687.0, - "Position": 199.0 - }, { - "StartTime": 3750.0, - "Position": 239.0 - }, { - "StartTime": 3812.0, - "Position": 326.0 - }, { - "StartTime": 3875.0, - "Position": 393.0 - }, { - "StartTime": 3937.0, - "Position": 470.0 - }, { - "StartTime": 4000.0, - "Position": 136.0 - }] - }, { - "StartTime": 4500.0, - "Objects": [{ - "StartTime": 4500.0, - "Position": 317.0 - }, { - "StartTime": 4562.0, - "Position": 354.0 - }, { - "StartTime": 4625.0, - "Position": 414.0 - }, { - "StartTime": 4687.0, - "Position": 39.0 - }, { - "StartTime": 4750.0, - "Position": 172.0 - }, { - "StartTime": 4812.0, - "Position": 479.0 - }, { - "StartTime": 4875.0, - "Position": 18.0 - }, { - "StartTime": 4937.0, - "Position": 151.0 - }, { - "StartTime": 5000.0, - "Position": 342.0 - }, { - "StartTime": 5062.0, - "Position": 400.0 - }, { - "StartTime": 5125.0, - "Position": 420.0 - }, { - "StartTime": 5187.0, - "Position": 90.0 - }, { - "StartTime": 5250.0, - "Position": 220.0 - }, { - "StartTime": 5312.0, - "Position": 80.0 - }, { - "StartTime": 5375.0, - "Position": 421.0 - }, { - "StartTime": 5437.0, - "Position": 473.0 - }, { - "StartTime": 5500.0, - "Position": 97.0 - }] - }, { - "StartTime": 6000.0, - "Objects": [{ - "StartTime": 6000.0, - "Position": 105.0 - }, { - "StartTime": 6062.0, - "Position": 249.0 - }, { - "StartTime": 6125.0, - "Position": 163.0 - }, { - "StartTime": 6187.0, - "Position": 194.0 - }, { - "StartTime": 6250.0, - "Position": 106.0 - }, { - "StartTime": 6312.0, - "Position": 212.0 - }, { - "StartTime": 6375.0, - "Position": 257.0 - }, { - "StartTime": 6437.0, - "Position": 461.0 - }, { - "StartTime": 6500.0, - "Position": 79.0 - }] - }, { - "StartTime": 7000.0, - "Objects": [{ - "StartTime": 7000.0, - "Position": 256.0 - }, { - "StartTime": 7062.0, - "Position": 294.84 - }, { - "StartTime": 7125.0, - "Position": 279.0 - }, { - "StartTime": 7187.0, - "Position": 309.84 - }, { - "StartTime": 7250.0, - "Position": 336.0 - }, { - "StartTime": 7312.0, - "Position": 322.16 - }, { - "StartTime": 7375.0, - "Position": 308.0 - }, { - "StartTime": 7437.0, - "Position": 263.16 - }, { - "StartTime": 7500.0, - "Position": 256.0 - }, { - "StartTime": 7562.0, - "Position": 261.84 - }, { - "StartTime": 7625.0, - "Position": 277.0 - }, { - "StartTime": 7687.0, - "Position": 318.84 - }, { - "StartTime": 7750.0, - "Position": 336.0 - }, { - "StartTime": 7803.0, - "Position": 305.04 - }, { - "StartTime": 7857.0, - "Position": 307.76 - }, { - "StartTime": 7910.0, - "Position": 297.8 - }, { - "StartTime": 8000.0, - "Position": 256.0 - }] - }, { - "StartTime": 8500.0, - "Objects": [{ - "StartTime": 8500.0, - "Position": 32.0 - }, { - "StartTime": 8562.0, - "Position": 22.8515015 - }, { - "StartTime": 8625.0, - "Position": 28.5659637 - }, { - "StartTime": 8687.0, - "Position": 50.3433228 - }, { - "StartTime": 8750.0, - "Position": 56.58974 - }, { - "StartTime": 8812.0, - "Position": 64.23422 - }, { - "StartTime": 8875.0, - "Position": 67.7117844 - }, { - "StartTime": 8937.0, - "Position": 90.52607 - }, { - "StartTime": 9000.0, - "Position": 101.81015 - }, { - "StartTime": 9062.0, - "Position": 113.478188 - }, { - "StartTime": 9125.0, - "Position": 159.414444 - }, { - "StartTime": 9187.0, - "Position": 155.1861 - }, { - "StartTime": 9250.0, - "Position": 179.600418 - }, { - "StartTime": 9312.0, - "Position": 212.293015 - }, { - "StartTime": 9375.0, - "Position": 197.2076 - }, { - "StartTime": 9437.0, - "Position": 243.438324 - }, { - "StartTime": 9500.0, - "Position": 237.2304 - }, { - "StartTime": 9562.0, - "Position": 241.253983 - }, { - "StartTime": 9625.0, - "Position": 258.950623 - }, { - "StartTime": 9687.0, - "Position": 253.3786 - }, { - "StartTime": 9750.0, - "Position": 270.8865 - }, { - "StartTime": 9812.0, - "Position": 244.38974 - }, { - "StartTime": 9875.0, - "Position": 242.701874 - }, { - "StartTime": 9937.0, - "Position": 256.2331 - }, { - "StartTime": 10000.0, - "Position": 270.339874 - }, { - "StartTime": 10062.0, - "Position": 275.9349 - }, { - "StartTime": 10125.0, - "Position": 297.2969 - }, { - "StartTime": 10187.0, - "Position": 307.834137 - }, { - "StartTime": 10250.0, - "Position": 321.6449 - }, { - "StartTime": 10312.0, - "Position": 357.746338 - }, { - "StartTime": 10375.0, - "Position": 358.21875 - }, { - "StartTime": 10437.0, - "Position": 394.943 - }, { - "StartTime": 10500.0, - "Position": 401.0588 - }, { - "StartTime": 10558.0, - "Position": 418.21347 - }, { - "StartTime": 10616.0, - "Position": 424.6034 - }, { - "StartTime": 10674.0, - "Position": 455.835754 - }, { - "StartTime": 10732.0, - "Position": 477.5042 - }, { - "StartTime": 10790.0, - "Position": 476.290955 - }, { - "StartTime": 10848.0, - "Position": 470.943237 - }, { - "StartTime": 10906.0, - "Position": 503.3372 - }, { - "StartTime": 10999.0, - "Position": 508.166229 - }] - }, { - "StartTime": 11500.0, - "Objects": [{ - "StartTime": 11500.0, - "Position": 321.0 - }, { - "StartTime": 11562.0, - "Position": 17.0 - }, { - "StartTime": 11625.0, - "Position": 173.0 - }, { - "StartTime": 11687.0, - "Position": 170.0 - }, { - "StartTime": 11750.0, - "Position": 447.0 - }, { - "StartTime": 11812.0, - "Position": 218.0 - }, { - "StartTime": 11875.0, - "Position": 394.0 - }, { - "StartTime": 11937.0, - "Position": 46.0 - }, { - "StartTime": 12000.0, - "Position": 480.0 - }] - }, { - "StartTime": 12500.0, - "Objects": [{ - "StartTime": 12500.0, - "Position": 512.0 - }, { - "StartTime": 12562.0, - "Position": 491.3132 - }, { - "StartTime": 12625.0, - "Position": 484.3089 - }, { - "StartTime": 12687.0, - "Position": 454.6221 - }, { - "StartTime": 12750.0, - "Position": 433.617767 - }, { - "StartTime": 12812.0, - "Position": 399.930969 - }, { - "StartTime": 12875.0, - "Position": 395.926666 - }, { - "StartTime": 12937.0, - "Position": 361.239868 - }, { - "StartTime": 13000.0, - "Position": 353.235535 - }, { - "StartTime": 13062.0, - "Position": 314.548767 - }, { - "StartTime": 13125.0, - "Position": 315.544434 - }, { - "StartTime": 13187.0, - "Position": 288.857635 - }, { - "StartTime": 13250.0, - "Position": 254.853333 - }, { - "StartTime": 13312.0, - "Position": 239.166534 - }, { - "StartTime": 13375.0, - "Position": 240.1622 - }, { - "StartTime": 13437.0, - "Position": 212.4754 - }, { - "StartTime": 13500.0, - "Position": 194.471069 - }, { - "StartTime": 13562.0, - "Position": 161.784271 - }, { - "StartTime": 13625.0, - "Position": 145.779968 - }, { - "StartTime": 13687.0, - "Position": 129.09314 - }, { - "StartTime": 13750.0, - "Position": 104.088837 - }, { - "StartTime": 13812.0, - "Position": 95.40204 - }, { - "StartTime": 13875.0, - "Position": 61.3977356 - }, { - "StartTime": 13937.0, - "Position": 56.710907 - }, { - "StartTime": 14000.0, - "Position": 35.7066345 - }, { - "StartTime": 14062.0, - "Position": 5.019806 - }, { - "StartTime": 14125.0, - "Position": 0.0 - }, { - "StartTime": 14187.0, - "Position": 39.7696266 - }, { - "StartTime": 14250.0, - "Position": 23.0119171 - }, { - "StartTime": 14312.0, - "Position": 75.94882 - }, { - "StartTime": 14375.0, - "Position": 98.19112 - }, { - "StartTime": 14437.0, - "Position": 82.12803 - }, { - "StartTime": 14500.0, - "Position": 118.370323 - }, { - "StartTime": 14562.0, - "Position": 149.307236 - }, { - "StartTime": 14625.0, - "Position": 168.549515 - }, { - "StartTime": 14687.0, - "Position": 190.486435 - }, { - "StartTime": 14750.0, - "Position": 186.728714 - }, { - "StartTime": 14812.0, - "Position": 199.665634 - }, { - "StartTime": 14875.0, - "Position": 228.907928 - }, { - "StartTime": 14937.0, - "Position": 264.844849 - }, { - "StartTime": 15000.0, - "Position": 271.087128 - }, { - "StartTime": 15062.0, - "Position": 290.024017 - }, { - "StartTime": 15125.0, - "Position": 302.266327 - }, { - "StartTime": 15187.0, - "Position": 344.203247 - }, { - "StartTime": 15250.0, - "Position": 356.445526 - }, { - "StartTime": 15312.0, - "Position": 359.382446 - }, { - "StartTime": 15375.0, - "Position": 401.624725 - }, { - "StartTime": 15437.0, - "Position": 388.561646 - }, { - "StartTime": 15500.0, - "Position": 423.803925 - }, { - "StartTime": 15562.0, - "Position": 425.740845 - }, { - "StartTime": 15625.0, - "Position": 449.983124 - }, { - "StartTime": 15687.0, - "Position": 468.920044 - }, { - "StartTime": 15750.0, - "Position": 492.162323 - }, { - "StartTime": 15812.0, - "Position": 506.784332 - }, { - "StartTime": 15875.0, - "Position": 474.226227 - }, { - "StartTime": 15937.0, - "Position": 482.978638 - }, { - "StartTime": 16000.0, - "Position": 446.420532 - }, { - "StartTime": 16058.0, - "Position": 418.4146 - }, { - "StartTime": 16116.0, - "Position": 425.408844 - }, { - "StartTime": 16174.0, - "Position": 383.402924 - }, { - "StartTime": 16232.0, - "Position": 363.397156 - }, { - "StartTime": 16290.0, - "Position": 343.391235 - }, { - "StartTime": 16348.0, - "Position": 328.385468 - }, { - "StartTime": 16406.0, - "Position": 322.3797 - }, { - "StartTime": 16500.0, - "Position": 291.1977 - }] - }, { - "StartTime": 17000.0, - "Objects": [{ - "StartTime": 17000.0, - "Position": 256.0 - }, { - "StartTime": 17062.0, - "Position": 228.16 - }, { - "StartTime": 17125.0, - "Position": 234.0 - }, { - "StartTime": 17187.0, - "Position": 202.16 - }, { - "StartTime": 17250.0, - "Position": 176.0 - }, { - "StartTime": 17312.0, - "Position": 210.84 - }, { - "StartTime": 17375.0, - "Position": 221.0 - }, { - "StartTime": 17437.0, - "Position": 219.84 - }, { - "StartTime": 17500.0, - "Position": 256.0 - }, { - "StartTime": 17562.0, - "Position": 219.16 - }, { - "StartTime": 17625.0, - "Position": 228.0 - }, { - "StartTime": 17687.0, - "Position": 203.16 - }, { - "StartTime": 17750.0, - "Position": 176.0 - }, { - "StartTime": 17803.0, - "Position": 174.959991 - }, { - "StartTime": 17857.0, - "Position": 214.23999 - }, { - "StartTime": 17910.0, - "Position": 228.200012 - }, { - "StartTime": 18000.0, - "Position": 256.0 - }] - }, { - "StartTime": 18500.0, - "Objects": [{ - "StartTime": 18500.0, - "Position": 362.0 - }, { - "StartTime": 18559.0, - "Position": 249.0 - }, { - "StartTime": 18618.0, - "Position": 357.0 - }, { - "StartTime": 18678.0, - "Position": 167.0 - }, { - "StartTime": 18737.0, - "Position": 477.0 - }, { - "StartTime": 18796.0, - "Position": 411.0 - }, { - "StartTime": 18856.0, - "Position": 254.0 - }, { - "StartTime": 18915.0, - "Position": 308.0 - }, { - "StartTime": 18975.0, - "Position": 399.0 - }, { - "StartTime": 19034.0, - "Position": 176.0 - }, { - "StartTime": 19093.0, - "Position": 14.0 - }, { - "StartTime": 19153.0, - "Position": 258.0 - }, { - "StartTime": 19212.0, - "Position": 221.0 - }, { - "StartTime": 19271.0, - "Position": 481.0 - }, { - "StartTime": 19331.0, - "Position": 92.0 - }, { - "StartTime": 19390.0, - "Position": 211.0 - }, { - "StartTime": 19450.0, - "Position": 135.0 - }] - }, { - "StartTime": 19875.0, - "Objects": [{ - "StartTime": 19875.0, - "Position": 216.0 - }, { - "StartTime": 19937.0, - "Position": 215.307053 - }, { - "StartTime": 20000.0, - "Position": 236.036865 - }, { - "StartTime": 20062.0, - "Position": 236.312088 - }, { - "StartTime": 20125.0, - "Position": 235.838928 - }, { - "StartTime": 20187.0, - "Position": 269.9743 - }, { - "StartTime": 20250.0, - "Position": 285.999146 - }, { - "StartTime": 20312.0, - "Position": 283.669067 - }, { - "StartTime": 20375.0, - "Position": 317.446747 - }, { - "StartTime": 20437.0, - "Position": 330.750275 - }, { - "StartTime": 20500.0, - "Position": 344.0156 - }, { - "StartTime": 20562.0, - "Position": 318.472168 - }, { - "StartTime": 20625.0, - "Position": 309.165466 - }, { - "StartTime": 20687.0, - "Position": 317.044617 - }, { - "StartTime": 20750.0, - "Position": 280.457367 - }, { - "StartTime": 20812.0, - "Position": 272.220581 - }, { - "StartTime": 20875.0, - "Position": 270.3294 - }, { - "StartTime": 20937.0, - "Position": 262.57605 - }, { - "StartTime": 21000.0, - "Position": 244.803329 - }, { - "StartTime": 21062.0, - "Position": 215.958359 - }, { - "StartTime": 21125.0, - "Position": 177.79332 - }, { - "StartTime": 21187.0, - "Position": 190.948349 - }, { - "StartTime": 21250.0, - "Position": 158.78334 - }, { - "StartTime": 21312.0, - "Position": 136.93837 - }, { - "StartTime": 21375.0, - "Position": 119.121056 - }, { - "StartTime": 21437.0, - "Position": 132.387573 - }, { - "StartTime": 21500.0, - "Position": 124.503014 - }, { - "StartTime": 21562.0, - "Position": 118.749374 - }, { - "StartTime": 21625.0, - "Position": 123.165535 - }, { - "StartTime": 21687.0, - "Position": 96.02999 - }, { - "StartTime": 21750.0, - "Position": 118.547928 - }, { - "StartTime": 21812.0, - "Position": 128.856232 - }, { - "StartTime": 21875.0, - "Position": 124.28746 - }, { - "StartTime": 21937.0, - "Position": 150.754929 - }, { - "StartTime": 22000.0, - "Position": 149.528732 - }, { - "StartTime": 22062.0, - "Position": 145.1691 - }, { - "StartTime": 22125.0, - "Position": 182.802155 - }, { - "StartTime": 22187.0, - "Position": 178.6452 - }, { - "StartTime": 22250.0, - "Position": 213.892181 - }, { - "StartTime": 22312.0, - "Position": 218.713028 - }, { - "StartTime": 22375.0, - "Position": 240.4715 - }, { - "StartTime": 22437.0, - "Position": 239.371887 - }, { - "StartTime": 22500.0, - "Position": 261.907257 - }, { - "StartTime": 22562.0, - "Position": 314.353119 - }, { - "StartTime": 22625.0, - "Position": 299.273376 - }, { - "StartTime": 22687.0, - "Position": 356.98288 - }, { - "StartTime": 22750.0, - "Position": 339.078552 - }, { - "StartTime": 22812.0, - "Position": 377.8958 - }, { - "StartTime": 22875.0, - "Position": 398.054047 - }, { - "StartTime": 22937.0, - "Position": 398.739441 - }, { - "StartTime": 23000.0, - "Position": 407.178467 - }, { - "StartTime": 23062.0, - "Position": 444.8687 - }, { - "StartTime": 23125.0, - "Position": 417.069977 - }, { - "StartTime": 23187.0, - "Position": 454.688477 - }, { - "StartTime": 23250.0, - "Position": 428.9612 - }, { - "StartTime": 23312.0, - "Position": 441.92807 - }, { - "StartTime": 23375.0, - "Position": 439.749878 - }, { - "StartTime": 23433.0, - "Position": 455.644684 - }, { - "StartTime": 23491.0, - "Position": 440.7359 - }, { - "StartTime": 23549.0, - "Position": 430.0944 - }, { - "StartTime": 23607.0, - "Position": 420.796173 - }, { - "StartTime": 23665.0, - "Position": 435.897461 - }, { - "StartTime": 23723.0, - "Position": 418.462555 - }, { - "StartTime": 23781.0, - "Position": 405.53775 - }, { - "StartTime": 23874.0, - "Position": 408.720825 - }] - }] + "StartTime": 500, + "Objects": [{ + "StartTime": 500, + "Position": 96 + }, + { + "StartTime": 562, + "Position": 100.84 + }, + { + "StartTime": 625, + "Position": 125 + }, + { + "StartTime": 687, + "Position": 152.84 + }, + { + "StartTime": 750, + "Position": 191 + }, + { + "StartTime": 812, + "Position": 212.84 + }, + { + "StartTime": 875, + "Position": 217 + }, + { + "StartTime": 937, + "Position": 234.84 + }, + { + "StartTime": 1000, + "Position": 256 + }, + { + "StartTime": 1062, + "Position": 267.84 + }, + { + "StartTime": 1125, + "Position": 284 + }, + { + "StartTime": 1187, + "Position": 311.84 + }, + { + "StartTime": 1250, + "Position": 350 + }, + { + "StartTime": 1312, + "Position": 359.84 + }, + { + "StartTime": 1375, + "Position": 367 + }, + { + "StartTime": 1437, + "Position": 400.84 + }, + { + "StartTime": 1500, + "Position": 416 + }, + { + "StartTime": 1562, + "Position": 377.159973 + }, + { + "StartTime": 1625, + "Position": 367 + }, + { + "StartTime": 1687, + "Position": 374.159973 + }, + { + "StartTime": 1750, + "Position": 353 + }, + { + "StartTime": 1812, + "Position": 329.159973 + }, + { + "StartTime": 1875, + "Position": 288 + }, + { + "StartTime": 1937, + "Position": 259.159973 + }, + { + "StartTime": 2000, + "Position": 256 + }, + { + "StartTime": 2062, + "Position": 231.159988 + }, + { + "StartTime": 2125, + "Position": 220 + }, + { + "StartTime": 2187, + "Position": 181.159988 + }, + { + "StartTime": 2250, + "Position": 172 + }, + { + "StartTime": 2312, + "Position": 155.159988 + }, + { + "StartTime": 2375, + "Position": 150 + }, + { + "StartTime": 2437, + "Position": 101.159988 + }, + { + "StartTime": 2500, + "Position": 96 + } + ] + }, + { + "StartTime": 3000, + "Objects": [{ + "StartTime": 3000, + "Position": 18 + }, + { + "StartTime": 3062, + "Position": 249 + }, + { + "StartTime": 3125, + "Position": 184 + }, + { + "StartTime": 3187, + "Position": 477 + }, + { + "StartTime": 3250, + "Position": 43 + }, + { + "StartTime": 3312, + "Position": 494 + }, + { + "StartTime": 3375, + "Position": 135 + }, + { + "StartTime": 3437, + "Position": 30 + }, + { + "StartTime": 3500, + "Position": 11 + }, + { + "StartTime": 3562, + "Position": 239 + }, + { + "StartTime": 3625, + "Position": 505 + }, + { + "StartTime": 3687, + "Position": 353 + }, + { + "StartTime": 3750, + "Position": 136 + }, + { + "StartTime": 3812, + "Position": 135 + }, + { + "StartTime": 3875, + "Position": 346 + }, + { + "StartTime": 3937, + "Position": 39 + }, + { + "StartTime": 4000, + "Position": 300 + } + ] + }, + { + "StartTime": 4500, + "Objects": [{ + "StartTime": 4500, + "Position": 398 + }, + { + "StartTime": 4562, + "Position": 151 + }, + { + "StartTime": 4625, + "Position": 73 + }, + { + "StartTime": 4687, + "Position": 311 + }, + { + "StartTime": 4750, + "Position": 90 + }, + { + "StartTime": 4812, + "Position": 264 + }, + { + "StartTime": 4875, + "Position": 477 + }, + { + "StartTime": 4937, + "Position": 473 + }, + { + "StartTime": 5000, + "Position": 120 + }, + { + "StartTime": 5062, + "Position": 115 + }, + { + "StartTime": 5125, + "Position": 163 + }, + { + "StartTime": 5187, + "Position": 447 + }, + { + "StartTime": 5250, + "Position": 72 + }, + { + "StartTime": 5312, + "Position": 257 + }, + { + "StartTime": 5375, + "Position": 153 + }, + { + "StartTime": 5437, + "Position": 388 + }, + { + "StartTime": 5500, + "Position": 336 + } + ] + }, + { + "StartTime": 6000, + "Objects": [{ + "StartTime": 6000, + "Position": 13 + }, + { + "StartTime": 6062, + "Position": 429 + }, + { + "StartTime": 6125, + "Position": 381 + }, + { + "StartTime": 6187, + "Position": 186 + }, + { + "StartTime": 6250, + "Position": 267 + }, + { + "StartTime": 6312, + "Position": 305 + }, + { + "StartTime": 6375, + "Position": 456 + }, + { + "StartTime": 6437, + "Position": 26 + }, + { + "StartTime": 6500, + "Position": 238 + } + ] + }, + { + "StartTime": 7000, + "Objects": [{ + "StartTime": 7000, + "Position": 256 + }, + { + "StartTime": 7062, + "Position": 262.84 + }, + { + "StartTime": 7125, + "Position": 295 + }, + { + "StartTime": 7187, + "Position": 303.84 + }, + { + "StartTime": 7250, + "Position": 336 + }, + { + "StartTime": 7312, + "Position": 319.16 + }, + { + "StartTime": 7375, + "Position": 306 + }, + { + "StartTime": 7437, + "Position": 272.16 + }, + { + "StartTime": 7500, + "Position": 256 + }, + { + "StartTime": 7562, + "Position": 255.84 + }, + { + "StartTime": 7625, + "Position": 300 + }, + { + "StartTime": 7687, + "Position": 320.84 + }, + { + "StartTime": 7750, + "Position": 336 + }, + { + "StartTime": 7812, + "Position": 316.16 + }, + { + "StartTime": 7875, + "Position": 278 + }, + { + "StartTime": 7937, + "Position": 257.16 + }, + { + "StartTime": 8000, + "Position": 256 + } + ] + }, + { + "StartTime": 8500, + "Objects": [{ + "StartTime": 8500, + "Position": 32 + }, + { + "StartTime": 8562, + "Position": 21.8515015 + }, + { + "StartTime": 8625, + "Position": 44.5659637 + }, + { + "StartTime": 8687, + "Position": 33.3433228 + }, + { + "StartTime": 8750, + "Position": 63.58974 + }, + { + "StartTime": 8812, + "Position": 71.23422 + }, + { + "StartTime": 8875, + "Position": 62.7117844 + }, + { + "StartTime": 8937, + "Position": 65.52607 + }, + { + "StartTime": 9000, + "Position": 101.81015 + }, + { + "StartTime": 9062, + "Position": 134.47818 + }, + { + "StartTime": 9125, + "Position": 141.414444 + }, + { + "StartTime": 9187, + "Position": 164.1861 + }, + { + "StartTime": 9250, + "Position": 176.600418 + }, + { + "StartTime": 9312, + "Position": 184.293015 + }, + { + "StartTime": 9375, + "Position": 212.2076 + }, + { + "StartTime": 9437, + "Position": 236.438324 + }, + { + "StartTime": 9500, + "Position": 237.2304 + }, + { + "StartTime": 9562, + "Position": 241.253983 + }, + { + "StartTime": 9625, + "Position": 233.950623 + }, + { + "StartTime": 9687, + "Position": 265.3786 + }, + { + "StartTime": 9750, + "Position": 236.8865 + }, + { + "StartTime": 9812, + "Position": 273.38974 + }, + { + "StartTime": 9875, + "Position": 267.701874 + }, + { + "StartTime": 9937, + "Position": 263.2331 + }, + { + "StartTime": 10000, + "Position": 270.339874 + }, + { + "StartTime": 10062, + "Position": 291.9349 + }, + { + "StartTime": 10125, + "Position": 294.2969 + }, + { + "StartTime": 10187, + "Position": 307.834137 + }, + { + "StartTime": 10250, + "Position": 310.6449 + }, + { + "StartTime": 10312, + "Position": 344.746338 + }, + { + "StartTime": 10375, + "Position": 349.21875 + }, + { + "StartTime": 10437, + "Position": 373.943 + }, + { + "StartTime": 10500, + "Position": 401.0588 + }, + { + "StartTime": 10562, + "Position": 422.44046 + }, + { + "StartTime": 10625, + "Position": 434.209717 + }, + { + "StartTime": 10687, + "Position": 437.275177 + }, + { + "StartTime": 10750, + "Position": 456.6923 + }, + { + "StartTime": 10812, + "Position": 490.584229 + }, + { + "StartTime": 10875, + "Position": 493.13208 + }, + { + "StartTime": 10937, + "Position": 496.8966 + }, + { + "StartTime": 10999, + "Position": 508.166229 + } + ] + }, + { + "StartTime": 11500, + "Objects": [{ + "StartTime": 11500, + "Position": 97 + }, + { + "StartTime": 11562, + "Position": 267 + }, + { + "StartTime": 11625, + "Position": 116 + }, + { + "StartTime": 11687, + "Position": 451 + }, + { + "StartTime": 11750, + "Position": 414 + }, + { + "StartTime": 11812, + "Position": 88 + }, + { + "StartTime": 11875, + "Position": 257 + }, + { + "StartTime": 11937, + "Position": 175 + }, + { + "StartTime": 12000, + "Position": 38 + } + ] + }, + { + "StartTime": 12500, + "Objects": [{ + "StartTime": 12500, + "Position": 512 + }, + { + "StartTime": 12562, + "Position": 494.3132 + }, + { + "StartTime": 12625, + "Position": 461.3089 + }, + { + "StartTime": 12687, + "Position": 469.6221 + }, + { + "StartTime": 12750, + "Position": 441.617767 + }, + { + "StartTime": 12812, + "Position": 402.930969 + }, + { + "StartTime": 12875, + "Position": 407.926666 + }, + { + "StartTime": 12937, + "Position": 364.239868 + }, + { + "StartTime": 13000, + "Position": 353.235535 + }, + { + "StartTime": 13062, + "Position": 320.548767 + }, + { + "StartTime": 13125, + "Position": 303.544434 + }, + { + "StartTime": 13187, + "Position": 295.857635 + }, + { + "StartTime": 13250, + "Position": 265.853333 + }, + { + "StartTime": 13312, + "Position": 272.166534 + }, + { + "StartTime": 13375, + "Position": 240.1622 + }, + { + "StartTime": 13437, + "Position": 229.4754 + }, + { + "StartTime": 13500, + "Position": 194.471069 + }, + { + "StartTime": 13562, + "Position": 158.784271 + }, + { + "StartTime": 13625, + "Position": 137.779968 + }, + { + "StartTime": 13687, + "Position": 147.09314 + }, + { + "StartTime": 13750, + "Position": 122.088837 + }, + { + "StartTime": 13812, + "Position": 77.40204 + }, + { + "StartTime": 13875, + "Position": 79.3977356 + }, + { + "StartTime": 13937, + "Position": 56.710907 + }, + { + "StartTime": 14000, + "Position": 35.7066345 + }, + { + "StartTime": 14062, + "Position": 1.01980591 + }, + { + "StartTime": 14125, + "Position": 0 + }, + { + "StartTime": 14187, + "Position": 21.7696266 + }, + { + "StartTime": 14250, + "Position": 49.0119171 + }, + { + "StartTime": 14312, + "Position": 48.9488258 + }, + { + "StartTime": 14375, + "Position": 87.19112 + }, + { + "StartTime": 14437, + "Position": 97.12803 + }, + { + "StartTime": 14500, + "Position": 118.370323 + }, + { + "StartTime": 14562, + "Position": 130.307236 + }, + { + "StartTime": 14625, + "Position": 154.549515 + }, + { + "StartTime": 14687, + "Position": 190.486435 + }, + { + "StartTime": 14750, + "Position": 211.728714 + }, + { + "StartTime": 14812, + "Position": 197.665634 + }, + { + "StartTime": 14875, + "Position": 214.907928 + }, + { + "StartTime": 14937, + "Position": 263.844849 + }, + { + "StartTime": 15000, + "Position": 271.087128 + }, + { + "StartTime": 15062, + "Position": 270.024017 + }, + { + "StartTime": 15125, + "Position": 308.266327 + }, + { + "StartTime": 15187, + "Position": 313.203247 + }, + { + "StartTime": 15250, + "Position": 328.445526 + }, + { + "StartTime": 15312, + "Position": 370.382446 + }, + { + "StartTime": 15375, + "Position": 387.624725 + }, + { + "StartTime": 15437, + "Position": 421.561646 + }, + { + "StartTime": 15500, + "Position": 423.803925 + }, + { + "StartTime": 15562, + "Position": 444.740845 + }, + { + "StartTime": 15625, + "Position": 469.983124 + }, + { + "StartTime": 15687, + "Position": 473.920044 + }, + { + "StartTime": 15750, + "Position": 501.162323 + }, + { + "StartTime": 15812, + "Position": 488.784332 + }, + { + "StartTime": 15875, + "Position": 466.226227 + }, + { + "StartTime": 15937, + "Position": 445.978638 + }, + { + "StartTime": 16000, + "Position": 446.420532 + }, + { + "StartTime": 16062, + "Position": 427.1729 + }, + { + "StartTime": 16125, + "Position": 417.6148 + }, + { + "StartTime": 16187, + "Position": 370.367218 + }, + { + "StartTime": 16250, + "Position": 365.8091 + }, + { + "StartTime": 16312, + "Position": 343.561523 + }, + { + "StartTime": 16375, + "Position": 332.003418 + }, + { + "StartTime": 16437, + "Position": 327.755829 + }, + { + "StartTime": 16500, + "Position": 291.1977 + } + ] + }, + { + "StartTime": 17000, + "Objects": [{ + "StartTime": 17000, + "Position": 256 + }, + { + "StartTime": 17062, + "Position": 247.16 + }, + { + "StartTime": 17125, + "Position": 211 + }, + { + "StartTime": 17187, + "Position": 183.16 + }, + { + "StartTime": 17250, + "Position": 176 + }, + { + "StartTime": 17312, + "Position": 204.84 + }, + { + "StartTime": 17375, + "Position": 218 + }, + { + "StartTime": 17437, + "Position": 231.84 + }, + { + "StartTime": 17500, + "Position": 256 + }, + { + "StartTime": 17562, + "Position": 229.16 + }, + { + "StartTime": 17625, + "Position": 227 + }, + { + "StartTime": 17687, + "Position": 186.16 + }, + { + "StartTime": 17750, + "Position": 176 + }, + { + "StartTime": 17812, + "Position": 214.84 + }, + { + "StartTime": 17875, + "Position": 203 + }, + { + "StartTime": 17937, + "Position": 233.84 + }, + { + "StartTime": 18000, + "Position": 256 + } + ] + }, + { + "StartTime": 18500, + "Objects": [{ + "StartTime": 18500, + "Position": 437 + }, + { + "StartTime": 18559, + "Position": 289 + }, + { + "StartTime": 18618, + "Position": 464 + }, + { + "StartTime": 18678, + "Position": 36 + }, + { + "StartTime": 18737, + "Position": 378 + }, + { + "StartTime": 18796, + "Position": 297 + }, + { + "StartTime": 18856, + "Position": 418 + }, + { + "StartTime": 18915, + "Position": 329 + }, + { + "StartTime": 18975, + "Position": 338 + }, + { + "StartTime": 19034, + "Position": 394 + }, + { + "StartTime": 19093, + "Position": 40 + }, + { + "StartTime": 19153, + "Position": 13 + }, + { + "StartTime": 19212, + "Position": 80 + }, + { + "StartTime": 19271, + "Position": 138 + }, + { + "StartTime": 19331, + "Position": 311 + }, + { + "StartTime": 19390, + "Position": 216 + }, + { + "StartTime": 19450, + "Position": 310 + } + ] + }, + { + "StartTime": 19875, + "Objects": [{ + "StartTime": 19875, + "Position": 216 + }, + { + "StartTime": 19937, + "Position": 228.307053 + }, + { + "StartTime": 20000, + "Position": 214.036865 + }, + { + "StartTime": 20062, + "Position": 224.312088 + }, + { + "StartTime": 20125, + "Position": 253.838928 + }, + { + "StartTime": 20187, + "Position": 259.9743 + }, + { + "StartTime": 20250, + "Position": 299.999146 + }, + { + "StartTime": 20312, + "Position": 289.669067 + }, + { + "StartTime": 20375, + "Position": 317.446747 + }, + { + "StartTime": 20437, + "Position": 344.750275 + }, + { + "StartTime": 20500, + "Position": 328.0156 + }, + { + "StartTime": 20562, + "Position": 331.472168 + }, + { + "StartTime": 20625, + "Position": 302.165466 + }, + { + "StartTime": 20687, + "Position": 303.044617 + }, + { + "StartTime": 20750, + "Position": 306.457367 + }, + { + "StartTime": 20812, + "Position": 265.220581 + }, + { + "StartTime": 20875, + "Position": 270.3294 + }, + { + "StartTime": 20937, + "Position": 257.57605 + }, + { + "StartTime": 21000, + "Position": 247.803329 + }, + { + "StartTime": 21062, + "Position": 225.958359 + }, + { + "StartTime": 21125, + "Position": 201.79332 + }, + { + "StartTime": 21187, + "Position": 170.948349 + }, + { + "StartTime": 21250, + "Position": 146.78334 + }, + { + "StartTime": 21312, + "Position": 149.93837 + }, + { + "StartTime": 21375, + "Position": 119.121056 + }, + { + "StartTime": 21437, + "Position": 133.387573 + }, + { + "StartTime": 21500, + "Position": 117.503014 + }, + { + "StartTime": 21562, + "Position": 103.749374 + }, + { + "StartTime": 21625, + "Position": 127.165535 + }, + { + "StartTime": 21687, + "Position": 113.029991 + }, + { + "StartTime": 21750, + "Position": 101.547928 + }, + { + "StartTime": 21812, + "Position": 133.856232 + }, + { + "StartTime": 21875, + "Position": 124.28746 + }, + { + "StartTime": 21937, + "Position": 121.754929 + }, + { + "StartTime": 22000, + "Position": 155.528732 + }, + { + "StartTime": 22062, + "Position": 142.1691 + }, + { + "StartTime": 22125, + "Position": 186.802155 + }, + { + "StartTime": 22187, + "Position": 198.6452 + }, + { + "StartTime": 22250, + "Position": 191.892181 + }, + { + "StartTime": 22312, + "Position": 232.713028 + }, + { + "StartTime": 22375, + "Position": 240.4715 + }, + { + "StartTime": 22437, + "Position": 278.3719 + }, + { + "StartTime": 22500, + "Position": 288.907257 + }, + { + "StartTime": 22562, + "Position": 297.353119 + }, + { + "StartTime": 22625, + "Position": 301.273376 + }, + { + "StartTime": 22687, + "Position": 339.98288 + }, + { + "StartTime": 22750, + "Position": 353.078552 + }, + { + "StartTime": 22812, + "Position": 363.8958 + }, + { + "StartTime": 22875, + "Position": 398.054047 + }, + { + "StartTime": 22937, + "Position": 419.739441 + }, + { + "StartTime": 23000, + "Position": 435.178467 + }, + { + "StartTime": 23062, + "Position": 420.8687 + }, + { + "StartTime": 23125, + "Position": 448.069977 + }, + { + "StartTime": 23187, + "Position": 425.688477 + }, + { + "StartTime": 23250, + "Position": 426.9612 + }, + { + "StartTime": 23312, + "Position": 454.92807 + }, + { + "StartTime": 23375, + "Position": 439.749878 + }, + { + "StartTime": 23437, + "Position": 440.540833 + }, + { + "StartTime": 23500, + "Position": 445.371735 + }, + { + "StartTime": 23562, + "Position": 431.408173 + }, + { + "StartTime": 23625, + "Position": 414.647522 + }, + { + "StartTime": 23687, + "Position": 406.2767 + }, + { + "StartTime": 23750, + "Position": 407.2297 + }, + { + "StartTime": 23812, + "Position": 403.716827 + }, + { + "StartTime": 23874, + "Position": 408.720825 + } + ] + } + ] } \ No newline at end of file From 6867a398cadb5826dfa8c8e6088dea5ab97a74ab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 21:12:08 +0900 Subject: [PATCH 49/68] Add one more test case --- .../CatchBeatmapConversionTest.cs | 1 + ...inner-and-circles-expected-conversion.json | 65 +++++++++++++++++++ .../Testing/Beatmaps/spinner-and-circles.osu | 24 +++++++ 3 files changed, 90 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-and-circles-expected-conversion.json create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-and-circles.osu diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 9de0ce3565..820929bb4c 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Catch.Tests [TestCase("basic"), Ignore("See: https://github.com/ppy/osu/issues/2232")] [TestCase("spinner")] + [TestCase("spinner-and-circles")] public new void Test(string name) { base.Test(name); diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-and-circles-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-and-circles-expected-conversion.json new file mode 100644 index 0000000000..dd81947f1c --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-and-circles-expected-conversion.json @@ -0,0 +1,65 @@ +{ + "Mappings": [{ + "StartTime": 2589, + "Objects": [{ + "StartTime": 2589, + "Position": 256 + }] + }, + { + "StartTime": 2915, + "Objects": [{ + "StartTime": 2915, + "Position": 65 + }, + { + "StartTime": 2916, + "Position": 482 + } + ] + }, + { + "StartTime": 3078, + "Objects": [{ + "StartTime": 3078, + "Position": 164 + }, + { + "StartTime": 3079, + "Position": 315 + } + ] + }, + { + "StartTime": 3241, + "Objects": [{ + "StartTime": 3241, + "Position": 145 + }, + { + "StartTime": 3242, + "Position": 159 + } + ] + }, + { + "StartTime": 3404, + "Objects": [{ + "StartTime": 3404, + "Position": 310 + }, + { + "StartTime": 3405, + "Position": 441 + } + ] + }, + { + "StartTime": 5197, + "Objects": [{ + "StartTime": 5197, + "Position": 256 + }] + } + ] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-and-circles.osu b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-and-circles.osu new file mode 100644 index 0000000000..9a90768428 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/spinner-and-circles.osu @@ -0,0 +1,24 @@ +osu file format v14 + +[General] +StackLeniency: 0.7 +Mode: 2 + +[Difficulty] +HPDrainRate:5 +CircleSize:2 +OverallDifficulty:5 +ApproachRate:8 +SliderMultiplier:1.4 +SliderTickRate:4 + +[TimingPoints] +2589,326.086956521739,4,2,1,70,1,0 + +[HitObjects] +256,192,2589,5,0,0:0:0:0: +256,192,2915,12,0,2916,0:0:0:0: +256,192,3078,12,0,3079,0:0:0:0: +256,192,3241,12,0,3242,0:0:0:0: +256,192,3404,12,0,3405,0:0:0:0: +256,192,5197,5,0,0:0:0:0: From 31bd59442f9bef317802e2a0f6f605c1c833125b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 21:15:10 +0900 Subject: [PATCH 50/68] Remove banana positioning comment --- osu.Game.Rulesets.Catch/Objects/BananaShower.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 4590856d98..4dd491966c 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -30,8 +30,7 @@ namespace osu.Game.Rulesets.Catch.Objects AddNested(new Banana { Samples = Samples, - StartTime = i, - X = 0 // The position will be set on the post processing + StartTime = i }); } From e840083ab4b6315b2f1c4ff24fc5940dfb81c363 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 22:22:29 +0900 Subject: [PATCH 51/68] Oops fix incorrectly changed file --- .../Beatmaps/basic-expected-conversion.json | 136 +++++++++--------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/basic-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/basic-expected-conversion.json index 8ede7b6719..b65d54a565 100644 --- a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/basic-expected-conversion.json +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/basic-expected-conversion.json @@ -102,32 +102,32 @@ "Position": 256 }, { - "StartTime": 2062, - "Position": 231.159988 + "StartTime": 2058, + "Position": 232.44 }, { - "StartTime": 2125, - "Position": 220 + "StartTime": 2116, + "Position": 222.879974 }, { - "StartTime": 2187, - "Position": 181.159988 + "StartTime": 2174, + "Position": 185.319992 }, { - "StartTime": 2250, - "Position": 172 + "StartTime": 2232, + "Position": 177.76001 }, { - "StartTime": 2312, - "Position": 155.159988 + "StartTime": 2290, + "Position": 162.200012 }, { - "StartTime": 2375, - "Position": 150 + "StartTime": 2348, + "Position": 158.639984 }, { - "StartTime": 2437, - "Position": 101.159988 + "StartTime": 2406, + "Position": 111.079994 }, { "StartTime": 2500, @@ -374,16 +374,16 @@ "Position": 336 }, { - "StartTime": 7812, - "Position": 316.16 + "StartTime": 7803, + "Position": 319.04 }, { - "StartTime": 7875, - "Position": 278 + "StartTime": 7857, + "Position": 283.76 }, { - "StartTime": 7937, - "Position": 257.16 + "StartTime": 7910, + "Position": 265.8 }, { "StartTime": 8000, @@ -526,32 +526,32 @@ "Position": 401.0588 }, { - "StartTime": 10562, - "Position": 422.44046 + "StartTime": 10558, + "Position": 421.21347 }, { - "StartTime": 10625, - "Position": 434.209717 + "StartTime": 10616, + "Position": 431.6034 }, { - "StartTime": 10687, - "Position": 437.275177 + "StartTime": 10674, + "Position": 433.835754 }, { - "StartTime": 10750, - "Position": 456.6923 + "StartTime": 10732, + "Position": 452.5042 }, { - "StartTime": 10812, - "Position": 490.584229 + "StartTime": 10790, + "Position": 486.290955 }, { - "StartTime": 10875, - "Position": 493.13208 + "StartTime": 10848, + "Position": 488.943237 }, { - "StartTime": 10937, - "Position": 496.8966 + "StartTime": 10906, + "Position": 493.3372 }, { "StartTime": 10999, @@ -830,32 +830,32 @@ "Position": 446.420532 }, { - "StartTime": 16062, - "Position": 427.1729 + "StartTime": 16058, + "Position": 428.4146 }, { - "StartTime": 16125, - "Position": 417.6148 + "StartTime": 16116, + "Position": 420.408844 }, { - "StartTime": 16187, - "Position": 370.367218 + "StartTime": 16174, + "Position": 374.402924 }, { - "StartTime": 16250, - "Position": 365.8091 + "StartTime": 16232, + "Position": 371.397156 }, { - "StartTime": 16312, - "Position": 343.561523 + "StartTime": 16290, + "Position": 350.391235 }, { - "StartTime": 16375, - "Position": 332.003418 + "StartTime": 16348, + "Position": 340.385468 }, { - "StartTime": 16437, - "Position": 327.755829 + "StartTime": 16406, + "Position": 337.3797 }, { "StartTime": 16500, @@ -918,16 +918,16 @@ "Position": 176 }, { - "StartTime": 17812, - "Position": 214.84 + "StartTime": 17803, + "Position": 211.959991 }, { - "StartTime": 17875, - "Position": 203 + "StartTime": 17857, + "Position": 197.23999 }, { - "StartTime": 17937, - "Position": 233.84 + "StartTime": 17910, + "Position": 225.200012 }, { "StartTime": 18000, @@ -1238,32 +1238,32 @@ "Position": 439.749878 }, { - "StartTime": 23437, - "Position": 440.540833 + "StartTime": 23433, + "Position": 440.644684 }, { - "StartTime": 23500, - "Position": 445.371735 + "StartTime": 23491, + "Position": 445.7359 }, { - "StartTime": 23562, - "Position": 431.408173 + "StartTime": 23549, + "Position": 432.0944 }, { - "StartTime": 23625, - "Position": 414.647522 + "StartTime": 23607, + "Position": 415.796173 }, { - "StartTime": 23687, - "Position": 406.2767 + "StartTime": 23665, + "Position": 407.897461 }, { - "StartTime": 23750, - "Position": 407.2297 + "StartTime": 23723, + "Position": 409.462555 }, { - "StartTime": 23812, - "Position": 403.716827 + "StartTime": 23781, + "Position": 406.53775 }, { "StartTime": 23874, From b97c415c50a17423c6e10e9255fb47ee0a622c77 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 14:16:58 +0900 Subject: [PATCH 52/68] Fix memory leak due to incorrect binding --- osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs index 240d8dc396..35146dfe29 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs @@ -161,7 +161,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor }; this.beatmap.BindTo(beatmap); - beatmap.ValueChanged += v => calculateScale(); + this.beatmap.ValueChanged += v => calculateScale(); cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); cursorScale.ValueChanged += v => calculateScale(); From caeddc861ab7cdfc65813c185417c8ec4950b43d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 15:12:10 +0900 Subject: [PATCH 53/68] Add test for WorkingBeatmap leakage --- osu.Game/Tests/Visual/TestCasePlayer.cs | 34 ++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 3cdc496ee1..55fb9c483b 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -1,9 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; +using osu.Framework.Lists; +using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -43,6 +46,7 @@ namespace osu.Game.Tests.Visual Player p = null; AddStep(ruleset.RulesetInfo.Name, () => p = loadPlayerFor(ruleset)); AddUntilStep(() => ContinueCondition(p)); + } else { @@ -51,6 +55,20 @@ namespace osu.Game.Tests.Visual Player p = null; AddStep(r.Name, () => p = loadPlayerFor(r)); AddUntilStep(() => ContinueCondition(p)); + AddAssert("no leaked beatmaps", () => + { + p = null; + + GC.Collect(); + GC.WaitForPendingFinalizers(); + int count = 0; + + workingWeakReferences.ForEachAlive(_ => count++); + + Logger.Log($"reference count {count}"); + + return count == 1; + }); } } } @@ -59,21 +77,29 @@ namespace osu.Game.Tests.Visual protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); + private readonly WeakList workingWeakReferences = new WeakList(); + private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance()); private Player loadPlayerFor(Ruleset r) { var beatmap = CreateBeatmap(r); + var working = new TestWorkingBeatmap(beatmap); - Beatmap.Value = new TestWorkingBeatmap(beatmap); + workingWeakReferences.Add(working); + + Beatmap.Value = working; Beatmap.Value.Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; - if (Player != null) - Remove(Player); + Player?.Exit(); var player = CreatePlayer(r); - LoadComponentAsync(player, LoadScreen); + LoadComponentAsync(player, p => + { + Player = p; + LoadScreen(p); + }); return player; } From cb73f215ac126c21553b9f691e134e1bc64f8592 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 15:26:05 +0900 Subject: [PATCH 54/68] Add check for player screens too --- osu.Game/Tests/Visual/TestCasePlayer.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 55fb9c483b..beaa6bb43a 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; using osu.Framework.Lists; -using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -55,6 +54,7 @@ namespace osu.Game.Tests.Visual Player p = null; AddStep(r.Name, () => p = loadPlayerFor(r)); AddUntilStep(() => ContinueCondition(p)); + AddAssert("no leaked beatmaps", () => { p = null; @@ -64,9 +64,16 @@ namespace osu.Game.Tests.Visual int count = 0; workingWeakReferences.ForEachAlive(_ => count++); + return count == 1; + }); - Logger.Log($"reference count {count}"); + AddAssert("no leaked players", () => + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + int count = 0; + playerWeakReferences.ForEachAlive(_ => count++); return count == 1; }); } @@ -78,6 +85,7 @@ namespace osu.Game.Tests.Visual protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); private readonly WeakList workingWeakReferences = new WeakList(); + private readonly WeakList playerWeakReferences = new WeakList(); private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance()); @@ -95,6 +103,8 @@ namespace osu.Game.Tests.Visual var player = CreatePlayer(r); + playerWeakReferences.Add(player); + LoadComponentAsync(player, p => { Player = p; From d259b31893b6deb0c08e49ae643a190cea0068e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 15:43:00 +0900 Subject: [PATCH 55/68] Fix empty line --- osu.Game/Tests/Visual/TestCasePlayer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index beaa6bb43a..20c9646aa3 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -45,7 +45,6 @@ namespace osu.Game.Tests.Visual Player p = null; AddStep(ruleset.RulesetInfo.Name, () => p = loadPlayerFor(ruleset)); AddUntilStep(() => ContinueCondition(p)); - } else { From 9709a40c5455b2191a5b806e788b520484cb149e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 21:46:47 +0900 Subject: [PATCH 56/68] Fix conversion test failing --- .../CatchBeatmapConversionTest.cs | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 820929bb4c..89e8361a72 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Newtonsoft.Json; using NUnit.Framework; using osu.Framework.MathUtils; using osu.Game.Rulesets.Catch.Objects; @@ -29,33 +30,15 @@ namespace osu.Game.Rulesets.Catch.Tests if (hitObject is JuiceStream stream) { foreach (var nested in stream.NestedHitObjects) - { - yield return new ConvertValue - { - StartTime = nested.StartTime, - Position = ((CatchHitObject)nested).X * CatchPlayfield.BASE_WIDTH - }; - } + yield return new ConvertValue((CatchHitObject)nested); } else if (hitObject is BananaShower shower) { foreach (var nested in shower.NestedHitObjects) - { - yield return new ConvertValue - { - StartTime = nested.StartTime, - Position = ((CatchHitObject)nested).X * CatchPlayfield.BASE_WIDTH - }; - } + yield return new ConvertValue((CatchHitObject)nested); } else - { - yield return new ConvertValue - { - StartTime = hitObject.StartTime, - Position = ((CatchHitObject)hitObject).X * CatchPlayfield.BASE_WIDTH - }; - } + yield return new ConvertValue((CatchHitObject)hitObject); } protected override Ruleset CreateRuleset() => new CatchRuleset(); @@ -68,8 +51,31 @@ namespace osu.Game.Rulesets.Catch.Tests /// private const float conversion_lenience = 2; - public double StartTime; - public float Position; + [JsonIgnore] + public readonly CatchHitObject HitObject; + + public ConvertValue(CatchHitObject hitObject) + { + HitObject = hitObject; + startTime = 0; + position = 0; + } + + private double startTime; + + public double StartTime + { + get => HitObject?.StartTime ?? startTime; + set => startTime = value; + } + + private float position; + + public float Position + { + get => HitObject?.X * CatchPlayfield.BASE_WIDTH ?? position; + set => position = value; + } public bool Equals(ConvertValue other) => Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience) From 4eda017fa55824d12e9eac8c52894cea8e9c32ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 17 Jun 2018 17:54:05 +0900 Subject: [PATCH 57/68] Fix CI error --- osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 8f90b6d87e..9b48ec17bd 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -114,7 +114,7 @@ namespace osu.Game.Tests.Visual private class TestPlayfield : ScrollingPlayfield { - public readonly ScrollingDirection Direction; + public new readonly ScrollingDirection Direction; public TestPlayfield(ScrollingDirection direction) : base(direction) From 9d7e5b492009ed883e99655397cb026a96587fcd Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 20 Jun 2018 17:23:55 +0900 Subject: [PATCH 58/68] Clamp juice stream position --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 2768357034..b0344d9a2d 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps foreach (var nested in juiceStream.NestedHitObjects) { if (nested is TinyDroplet tinyDroplet) - tinyDroplet.X += rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH; + tinyDroplet.X = MathHelper.Clamp(tinyDroplet.X + rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, 0, 1); else if (nested is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index b2d8e3f8a5..a4c4faacfa 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Catch.Objects AddNested(new TinyDroplet { StartTime = t, - X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH, + X = MathHelper.Clamp(X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH, 0, 1), Samples = new List(Samples.Select(s => new SampleInfo { Bank = s.Bank, @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Catch.Objects AddNested(new Droplet { StartTime = time, - X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH, + X = MathHelper.Clamp(X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH, 0, 1), Samples = new List(Samples.Select(s => new SampleInfo { Bank = s.Bank, @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Catch.Objects { Samples = Samples, StartTime = spanStartTime + spanDuration, - X = X + Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH + X = MathHelper.Clamp(X + Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH, 0, 1) }); } From 516b1c5495a17e89428989ab20aaa269123042ce Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 20 Jun 2018 18:29:23 +0900 Subject: [PATCH 59/68] Fix droplet position clamping --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 8 +++++--- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index b0344d9a2d..7fa0d256da 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -56,10 +56,12 @@ namespace osu.Game.Rulesets.Catch.Beatmaps case JuiceStream juiceStream: foreach (var nested in juiceStream.NestedHitObjects) { - if (nested is TinyDroplet tinyDroplet) - tinyDroplet.X = MathHelper.Clamp(tinyDroplet.X + rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, 0, 1); - else if (nested is Droplet) + var hitObject = (CatchHitObject)nested; + if (hitObject is TinyDroplet) + hitObject.X += rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH; + else if (hitObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation + hitObject.X = MathHelper.Clamp(hitObject.X, 0, 1); } break; } diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index a4c4faacfa..b2d8e3f8a5 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Catch.Objects AddNested(new TinyDroplet { StartTime = t, - X = MathHelper.Clamp(X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH, 0, 1), + X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH, Samples = new List(Samples.Select(s => new SampleInfo { Bank = s.Bank, @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Catch.Objects AddNested(new Droplet { StartTime = time, - X = MathHelper.Clamp(X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH, 0, 1), + X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH, Samples = new List(Samples.Select(s => new SampleInfo { Bank = s.Bank, @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Catch.Objects { Samples = Samples, StartTime = spanStartTime + spanDuration, - X = MathHelper.Clamp(X + Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH, 0, 1) + X = X + Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH }); } From 9194fd8dfe89e453819662ad4aafbc3ffe945f94 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 20 Jun 2018 20:08:27 +0900 Subject: [PATCH 60/68] don't expose HyperDashModifier directly --- .../TestCaseCatcherArea.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 59 ++++++++----------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index 5119260c53..0ba6398ced 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.Tests { } - public void ToggleHyperDash(bool status) => MovableCatcher.HyperDashModifier = status ? 2 : 1; + public void ToggleHyperDash(bool status) => MovableCatcher.SetHyperdashState(status ? 2 : 1); } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 3c0a6aec30..b74d53eef0 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -18,7 +18,6 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using OpenTK.Graphics; -using System.Diagnostics; namespace osu.Game.Rulesets.Catch.UI { @@ -250,21 +249,11 @@ namespace osu.Game.Rulesets.Catch.UI double positionDifference = target.X * CatchPlayfield.BASE_WIDTH - catcherPosition; double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); - // An edge case - if (Math.Abs(velocity) <= 1) - { - HyperDashModifier = 1; - } - else - { - hyperDashDirection = Math.Sign(velocity); - hyperDashTargetPosition = target.X; - HyperDashModifier = Math.Abs(velocity); - } + SetHyperdashState(Math.Abs(velocity), target.X); } else { - HyperDashModifier = 1; + SetHyperdashState(); } return validCatch; @@ -279,37 +268,39 @@ namespace osu.Game.Rulesets.Catch.UI /// public bool HyperDashing => hyperDashModifier != 1; + private const float hyperdash_transition_length = 180; + /// - /// The modifier multiplied to the catcher speed. - /// It is always not less than 1 and it is greater than 1 if and only if the catcher is hyper-dashing. + /// Set hyperdash state. /// - public double HyperDashModifier + /// The speed multiplier. If this is less or equals to 1, this catcher will be non-hyperdashing state. + /// When this catcher crosses this position, this catcher ends hyperdashing. + public void SetHyperdashState(double modifier = 1, float targetPosition = -1) { - get => hyperDashModifier; - set + bool previouslyHyperDashing = HyperDashing; + if (modifier <= 1 || X == targetPosition) { - Trace.Assert(value >= 1); - if (hyperDashModifier == value) return; - hyperDashModifier = value; + hyperDashModifier = 1; + hyperDashDirection = 0; - if (!HyperDashing) + if (previouslyHyperDashing) { - hyperDashDirection = 0; + this.FadeColour(Color4.White, hyperdash_transition_length, Easing.OutQuint); + this.FadeTo(1, hyperdash_transition_length, Easing.OutQuint); } + } + else + { + hyperDashModifier = modifier; + hyperDashDirection = Math.Sign(targetPosition - X); + hyperDashTargetPosition = targetPosition; - const float transition_length = 180; - - if (HyperDashing) + if (!previouslyHyperDashing) { - this.FadeColour(Color4.OrangeRed, transition_length, Easing.OutQuint); - this.FadeTo(0.2f, transition_length, Easing.OutQuint); + this.FadeColour(Color4.OrangeRed, hyperdash_transition_length, Easing.OutQuint); + this.FadeTo(0.2f, hyperdash_transition_length, Easing.OutQuint); Trail = true; } - else - { - this.FadeColour(Color4.White, transition_length, Easing.OutQuint); - this.FadeTo(1, transition_length, Easing.OutQuint); - } } } @@ -373,7 +364,7 @@ namespace osu.Game.Rulesets.Catch.UI hyperDashDirection < 0 && hyperDashTargetPosition > X) { X = hyperDashTargetPosition; - HyperDashModifier = 1; + SetHyperdashState(); } } From 48989df6ebfa81a4a68cd6034f14b39ecea4b71a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 21 Jun 2018 12:04:14 +0900 Subject: [PATCH 61/68] Make sure that 0 SR is returned when there are no hitobjects --- .../Difficulty/ManiaDifficultyCalculator.cs | 3 +++ osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 3 +++ .../Difficulty/TaikoDifficultyCalculator.cs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 0c899372c0..7b4d4b12ed 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -39,6 +39,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) { + if (!beatmap.HitObjects.Any()) + return new ManiaDifficultyAttributes(mods, 0); + var difficultyHitObjects = new List(); int columnCount = ((ManiaBeatmap)beatmap).TotalColumns; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 4386004e30..62fafd8196 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -25,6 +25,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) { + if (!beatmap.HitObjects.Any()) + return new OsuDifficultyAttributes(mods, 0); + OsuDifficultyBeatmap difficultyBeatmap = new OsuDifficultyBeatmap(beatmap.HitObjects.Cast().ToList(), timeRate); Skill[] skills = { diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 190717e024..8b527c2c82 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -35,6 +35,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) { + if (!beatmap.HitObjects.Any()) + return new TaikoDifficultyAttributes(mods, 0); + var difficultyHitObjects = new List(); foreach (var hitObject in beatmap.HitObjects) From 78ccbcabf36b0f6ee2ecb40dcc3230482dd3b504 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Jun 2018 17:34:29 +0900 Subject: [PATCH 62/68] Fix API getting stuck in an endless loop under a certain unauthorized scenario --- osu.Game/Online/API/APIAccess.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 8c5fc58878..c7ba2d4a11 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -148,7 +148,7 @@ namespace osu.Game.Online.API // The Success callback event is fired on the main thread, so we should wait for that to run before proceeding. // Without this, we will end up circulating this Connecting loop multiple times and queueing up many web requests // before actually going online. - while (State != APIState.Online) + while (State > APIState.Offline) Thread.Sleep(500); break; @@ -158,7 +158,6 @@ namespace osu.Game.Online.API if (authentication.RequestAccessToken() == null) { Logout(false); - State = APIState.Offline; continue; } @@ -208,6 +207,14 @@ namespace osu.Game.Online.API { HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout); + // special cases for un-typed but useful message responses. + switch (we.Message) + { + case "Unauthorized": + statusCode = HttpStatusCode.Unauthorized; + break; + } + switch (statusCode) { case HttpStatusCode.Unauthorized: @@ -292,6 +299,7 @@ namespace osu.Game.Online.API password = null; authentication.Clear(); LocalUser.Value = createGuestUser(); + State = APIState.Offline; } private static User createGuestUser() => new User From a3978278419d595388a0ce1a8df8be112be5a511 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Jun 2018 19:28:38 +0900 Subject: [PATCH 63/68] Reduce line length --- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 6d6edff3f4..b5dfb0949a 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -55,7 +55,10 @@ namespace osu.Game.Rulesets.Mania.UI.Components direction.BindTo(scrollingInfo.Direction); direction.BindValueChanged(direction => { - hitTargetBar.Anchor = hitTargetBar.Origin = hitTargetLine.Anchor = hitTargetLine.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + Anchor anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + + hitTargetBar.Anchor = hitTargetBar.Origin = anchor; + hitTargetLine.Anchor = hitTargetLine.Origin = anchor; }, true); } From 563cb46b4aa38773348e8aed6f8367e578352eb3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jun 2018 12:02:04 +0900 Subject: [PATCH 64/68] Update framework and other nuget dependencies --- osu.Desktop/osu.Desktop.csproj | 2 +- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 2 +- osu.Game/osu.Game.csproj | 10 +++++----- osu.TestProject.props | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 29d3b0e394..0289db20f0 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -29,7 +29,7 @@ - + diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index ffe1560627..6ba36a51d1 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -186,7 +186,7 @@ namespace osu.Game.Overlays.KeyBinding { if (bindTarget.IsHovered) { - bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); + bindTarget.UpdateKeyCombination(new KeyCombination(new[] { state.Mouse.ScrollDelta.Y > 0 ? InputKey.MouseWheelUp : InputKey.MouseWheelDown })); finalise(); return true; } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9cc538f70f..9668d40fd5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,12 +14,12 @@ - - - + + + - - + + diff --git a/osu.TestProject.props b/osu.TestProject.props index 8f7128f8b7..c2e6048a60 100644 --- a/osu.TestProject.props +++ b/osu.TestProject.props @@ -11,7 +11,7 @@ - + From 96191fc3cefcebe4866eafbe78a296353d94efd5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jun 2018 13:02:29 +0900 Subject: [PATCH 65/68] Move transition variable back to being local to function --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index b74d53eef0..24edcbfc98 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -268,8 +268,6 @@ namespace osu.Game.Rulesets.Catch.UI /// public bool HyperDashing => hyperDashModifier != 1; - private const float hyperdash_transition_length = 180; - /// /// Set hyperdash state. /// @@ -277,6 +275,8 @@ namespace osu.Game.Rulesets.Catch.UI /// When this catcher crosses this position, this catcher ends hyperdashing. public void SetHyperdashState(double modifier = 1, float targetPosition = -1) { + const float hyperdash_transition_length = 180; + bool previouslyHyperDashing = HyperDashing; if (modifier <= 1 || X == targetPosition) { From f1dfe04bd9ee23ceb3b763be6b5d08ccb59b0472 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Jun 2018 20:13:44 +0900 Subject: [PATCH 66/68] Fix broken conditional --- osu.Game/Online/API/APIAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index c7ba2d4a11..12935a5ffe 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -148,7 +148,7 @@ namespace osu.Game.Online.API // The Success callback event is fired on the main thread, so we should wait for that to run before proceeding. // Without this, we will end up circulating this Connecting loop multiple times and queueing up many web requests // before actually going online. - while (State > APIState.Offline) + while (State > APIState.Offline && State < APIState.Online) Thread.Sleep(500); break; From 1a8aa6eab10d677a0622b111bbab5d796730b58e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jun 2018 20:13:55 +0900 Subject: [PATCH 67/68] Fix regression causing new combos to once again not be respected --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 4 ++++ osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 7fa0d256da..8473f5a36c 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -30,7 +30,11 @@ namespace osu.Game.Rulesets.Catch.Beatmaps int index = 0; foreach (var obj in Beatmap.HitObjects.OfType()) + { obj.IndexInBeatmap = index++; + if (obj.LastInCombo && obj.NestedHitObjects.LastOrDefault() is IHasComboInformation lastNested) + lastNested.LastInCombo = true; + } } public const int RNG_SEED = 1337; diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index b2d8e3f8a5..6fe9692c26 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -42,7 +42,6 @@ namespace osu.Game.Rulesets.Catch.Objects protected override void CreateNestedHitObjects() { base.CreateNestedHitObjects(); - createTicks(); } @@ -124,9 +123,6 @@ namespace osu.Game.Rulesets.Catch.Objects X = X + Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH }); } - - if (NestedHitObjects.LastOrDefault() is IHasComboInformation lastNested) - lastNested.LastInCombo = LastInCombo; } public double EndTime => StartTime + this.SpanCount() * Curve.Distance / Velocity; From 8a81fba1ea6524adf58eaceb02e6d6aa2404e1ae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Jun 2018 20:34:22 +0900 Subject: [PATCH 68/68] Other input states need to be considered for wheel bindings --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 6ba36a51d1..a12f9dee7e 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -186,7 +186,7 @@ namespace osu.Game.Overlays.KeyBinding { if (bindTarget.IsHovered) { - bindTarget.UpdateKeyCombination(new KeyCombination(new[] { state.Mouse.ScrollDelta.Y > 0 ? InputKey.MouseWheelUp : InputKey.MouseWheelDown })); + bindTarget.UpdateKeyCombination(new KeyCombination(KeyCombination.FromInputState(state).Keys.Append(state.Mouse.ScrollDelta.Y > 0 ? InputKey.MouseWheelUp : InputKey.MouseWheelDown))); finalise(); return true; }