From 697efba5e2175aef9f275571c7ef9c6a25a08e40 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 15:55:35 +0900 Subject: [PATCH 01/49] Replace .OfType with .Cast --- osu.Game/Rulesets/UI/Playfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index b4a26344d5..5c32aeac73 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.UI public class HitObjectContainer : CompositeDrawable { - public virtual IEnumerable Objects => InternalChildren.OfType(); + public virtual IEnumerable Objects => InternalChildren.Cast(); public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); } From 7beb4c3507b0dc13ace923c909b0325eabd2d4ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:21:15 +0900 Subject: [PATCH 02/49] Initial implementation of a new scrolling hitobject container --- .../Visual/TestCaseScrollingHitObjects.cs | 104 ++++++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + 2 files changed, 105 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs new file mode 100644 index 0000000000..2827f70ebe --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -0,0 +1,104 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseScrollingHitObjects : OsuTestCase + { + public TestCaseScrollingHitObjects() + { + AddStep("Vertically-scrolling", () => createPlayfield(Direction.Vertical)); + AddStep("Horizontally-scrolling", () => createPlayfield(Direction.Horizontal)); + + AddStep("Add hitobject", addHitObject); + } + + private TestPlayfield playfield; + private void createPlayfield(Direction scrollingDirection) + { + if (playfield != null) + Remove(playfield); + Add(playfield = new TestPlayfield(scrollingDirection)); + } + + private void addHitObject() + { + playfield.Add(new TestDrawableHitObject(new HitObject { StartTime = Time.Current + 5000 }) + { + Anchor = playfield.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + }); + } + + private class ScrollingHitObjectContainer : Playfield.HitObjectContainer + { + public double TimeRange = 5000; + + private readonly Direction scrollingDirection; + + public ScrollingHitObjectContainer(Direction scrollingDirection) + { + this.scrollingDirection = scrollingDirection; + + RelativeSizeAxes = Axes.Both; + } + + protected override void Update() + { + base.Update(); + + foreach (var obj in Objects) + { + var relativePosition = (Time.Current - obj.HitObject.StartTime) / TimeRange; + + // Todo: We may need to consider scale here + var finalPosition = (float)relativePosition * DrawSize; + + switch (scrollingDirection) + { + case Direction.Horizontal: + obj.X = finalPosition.X; + break; + case Direction.Vertical: + obj.Y = finalPosition.Y; + break; + } + } + } + } + + private class TestPlayfield : Playfield + { + public readonly Direction ScrollingDirection; + + public TestPlayfield(Direction scrollingDirection) + { + ScrollingDirection = scrollingDirection; + + HitObjects = new ScrollingHitObjectContainer(scrollingDirection); + } + } + + private class TestDrawableHitObject : DrawableHitObject + { + public TestDrawableHitObject(HitObject hitObject) + : base(hitObject) + { + Origin = Anchor.Centre; + AutoSizeAxes = Axes.Both; + + Add(new Box { Size = new Vector2(75) }); + } + + protected override void UpdateState(ArmedState state) + { + } + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 8c04874e75..f47a03990a 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -141,6 +141,7 @@ + From 2b79ad879f7df53567eec7845b89aaeea46ce076 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:37:48 +0900 Subject: [PATCH 03/49] Add a way to access alive hitobjects --- osu.Game/Rulesets/UI/Playfield.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 5c32aeac73..61014b5550 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -97,6 +97,8 @@ namespace osu.Game.Rulesets.UI public class HitObjectContainer : CompositeDrawable { public virtual IEnumerable Objects => InternalChildren.Cast(); + public virtual IEnumerable AliveObjects => AliveInternalChildren.Cast(); + public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); } From b968040963a5c33ced93f7d8cdd28e8a96de77e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:38:07 +0900 Subject: [PATCH 04/49] General improvements to testcase --- .../Visual/TestCaseScrollingHitObjects.cs | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 2827f70ebe..7b462b5cac 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +using System; +using System.Collections.Generic; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -12,27 +14,36 @@ namespace osu.Game.Tests.Visual { public class TestCaseScrollingHitObjects : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; + + private List playfields = new List(); + public TestCaseScrollingHitObjects() { - AddStep("Vertically-scrolling", () => createPlayfield(Direction.Vertical)); - AddStep("Horizontally-scrolling", () => createPlayfield(Direction.Horizontal)); + playfields.Add(new TestPlayfield(Direction.Vertical)); + playfields.Add(new TestPlayfield(Direction.Horizontal)); - AddStep("Add hitobject", addHitObject); + AddRange(playfields); } - private TestPlayfield playfield; - private void createPlayfield(Direction scrollingDirection) + protected override void LoadComplete() { - if (playfield != null) - Remove(playfield); - Add(playfield = new TestPlayfield(scrollingDirection)); + base.LoadComplete(); + + for (int i = 0; i <= 5000; i += 1000) + addHitObject(Time.Current + i); + + Scheduler.AddDelayed(() => addHitObject(Time.Current + 5000), 1000, true); } - private void addHitObject() + private void addHitObject(double time) { - playfield.Add(new TestDrawableHitObject(new HitObject { StartTime = Time.Current + 5000 }) + playfields.ForEach(p => { - Anchor = playfield.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + p.Add(new TestDrawableHitObject(new HitObject { StartTime = time }) + { + Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + }); }); } From 210fd290e53d4b0b869c1482022b8ac02e209453 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:38:20 +0900 Subject: [PATCH 05/49] Use the new AliveObjects --- 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 7b462b5cac..f5b0a964a3 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual { base.Update(); - foreach (var obj in Objects) + foreach (var obj in AliveObjects) { var relativePosition = (Time.Current - obj.HitObject.StartTime) / TimeRange; From c067ee5fbe4b12dbd5d03502a3891f8a0fce5500 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:38:43 +0900 Subject: [PATCH 06/49] Move position calculation to UpdateAfterChildren Because we want this to occur after lifetimes have been evaluated. --- osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index f5b0a964a3..03b95042b2 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -60,9 +60,9 @@ namespace osu.Game.Tests.Visual RelativeSizeAxes = Axes.Both; } - protected override void Update() + protected override void UpdateAfterChildren() { - base.Update(); + base.UpdateAfterChildren(); foreach (var obj in AliveObjects) { From 90839e6d56f3ad6528cfb67745614b00c68e507b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 17:07:16 +0900 Subject: [PATCH 07/49] Test case improvements with TimeRange testing --- .../Visual/TestCaseScrollingHitObjects.cs | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 03b95042b2..346ded046e 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -3,12 +3,15 @@ using System; using System.Collections.Generic; +using osu.Framework.Configuration; using OpenTK; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; +using OpenTK.Graphics; namespace osu.Game.Tests.Visual { @@ -16,14 +19,37 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; - private List playfields = new List(); + private readonly List playfields = new List(); public TestCaseScrollingHitObjects() { playfields.Add(new TestPlayfield(Direction.Vertical)); playfields.Add(new TestPlayfield(Direction.Horizontal)); - AddRange(playfields); + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.85f), + Masking = true, + BorderColour = Color4.White, + BorderThickness = 2, + MaskingSmoothness = 1, + Children = new Drawable[] + { + new Box + { + Name = "Background", + RelativeSizeAxes = Axes.Both, + Alpha = 0.35f, + }, + playfields[0], + playfields[1] + } + }); + + AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.TimeRange.Value = v)); } protected override void LoadComplete() @@ -49,7 +75,11 @@ namespace osu.Game.Tests.Visual private class ScrollingHitObjectContainer : Playfield.HitObjectContainer { - public double TimeRange = 5000; + public readonly BindableDouble TimeRange = new BindableDouble + { + MinValue = 0, + MaxValue = double.MaxValue + }; private readonly Direction scrollingDirection; @@ -86,13 +116,18 @@ namespace osu.Game.Tests.Visual private class TestPlayfield : Playfield { + public readonly BindableDouble TimeRange = new BindableDouble(5000); + public readonly Direction ScrollingDirection; public TestPlayfield(Direction scrollingDirection) { ScrollingDirection = scrollingDirection; - HitObjects = new ScrollingHitObjectContainer(scrollingDirection); + var scrollingHitObjects = new ScrollingHitObjectContainer(scrollingDirection); + scrollingHitObjects.TimeRange.BindTo(TimeRange); + + HitObjects = scrollingHitObjects; } } From 0c5ab98965558a96b80d0efcda631ae0408407dc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 18:35:33 +0900 Subject: [PATCH 08/49] Make MultiplierControlPoint's StartTime variable --- osu.Game/Rulesets/Timing/MultiplierControlPoint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs index 4f1a85cf2d..8b8bbae9d5 100644 --- a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs +++ b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Timing /// /// The time in milliseconds at which this starts. /// - public readonly double StartTime; + public double StartTime; /// /// The multiplier which this provides. From b11f4ab8341c7cbcb3ae28b6cf88c88e98cec0b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 18:35:48 +0900 Subject: [PATCH 09/49] Implement control points --- .../Visual/TestCaseScrollingHitObjects.cs | 94 +++++++++++++++++-- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 346ded046e..d226203b3b 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -8,8 +8,10 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Lists; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; using OpenTK.Graphics; @@ -26,6 +28,8 @@ namespace osu.Game.Tests.Visual playfields.Add(new TestPlayfield(Direction.Vertical)); playfields.Add(new TestPlayfield(Direction.Horizontal)); + playfields.ForEach(p => p.HitObjects.ControlPoints.Add(new MultiplierControlPoint(double.MinValue))); + Add(new Container { Anchor = Anchor.Centre, @@ -50,6 +54,7 @@ namespace osu.Game.Tests.Visual }); AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.TimeRange.Value = v)); + AddStep("Add control point", () => addControlPoint(Time.Current + 5000)); } protected override void LoadComplete() @@ -66,13 +71,35 @@ namespace osu.Game.Tests.Visual { playfields.ForEach(p => { - p.Add(new TestDrawableHitObject(new HitObject { StartTime = time }) + p.Add(new TestDrawableHitObject(time) { Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre }); }); } + private void addControlPoint(double time) + { + playfields.ForEach(p => + { + p.HitObjects.ControlPoints.AddRange(new[] + { + new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } }, + new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }, + new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }, + }); + + TestDrawableControlPoint createDrawablePoint(double t) => new TestDrawableControlPoint(t) + { + Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + }; + + p.Add(createDrawablePoint(time)); + p.Add(createDrawablePoint(time + 2000)); + p.Add(createDrawablePoint(time + 3000)); + }); + } + private class ScrollingHitObjectContainer : Playfield.HitObjectContainer { public readonly BindableDouble TimeRange = new BindableDouble @@ -81,6 +108,8 @@ namespace osu.Game.Tests.Visual MaxValue = double.MaxValue }; + public readonly SortedList ControlPoints = new SortedList(); + private readonly Direction scrollingDirection; public ScrollingHitObjectContainer(Direction scrollingDirection) @@ -94,9 +123,11 @@ namespace osu.Game.Tests.Visual { base.UpdateAfterChildren(); + var currentMultiplier = controlPointAt(Time.Current); + foreach (var obj in AliveObjects) { - var relativePosition = (Time.Current - obj.HitObject.StartTime) / TimeRange; + var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); // Todo: We may need to consider scale here var finalPosition = (float)relativePosition * DrawSize; @@ -112,6 +143,24 @@ namespace osu.Game.Tests.Visual } } } + + private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) + { + if (ControlPoints.Count == 0) + return new MultiplierControlPoint(double.MinValue); + + if (time < ControlPoints[0].StartTime) + return ControlPoints[0]; + + searchingPoint.StartTime = time; + + int index = ControlPoints.BinarySearch(searchingPoint); + if (index < 0) + index = ~index - 1; + + return ControlPoints[index]; + } } private class TestPlayfield : Playfield @@ -120,21 +169,52 @@ namespace osu.Game.Tests.Visual public readonly Direction ScrollingDirection; + public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + public TestPlayfield(Direction scrollingDirection) { ScrollingDirection = scrollingDirection; - var scrollingHitObjects = new ScrollingHitObjectContainer(scrollingDirection); - scrollingHitObjects.TimeRange.BindTo(TimeRange); + base.HitObjects = new ScrollingHitObjectContainer(scrollingDirection); + HitObjects.TimeRange.BindTo(TimeRange); + } + } - HitObjects = scrollingHitObjects; + private class TestDrawableControlPoint : DrawableHitObject + { + private readonly Box box; + + public TestDrawableControlPoint(double time) + : base(new HitObject { StartTime = time }) + { + Origin = Anchor.Centre; + + Add(box = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + + protected override void Update() + { + base.Update(); + + RelativeSizeAxes = (Anchor & Anchor.x2) > 0 ? Axes.Y : Axes.X; + Size = new Vector2(1); + + box.Size = DrawSize; + } + + protected override void UpdateState(ArmedState state) + { } } private class TestDrawableHitObject : DrawableHitObject { - public TestDrawableHitObject(HitObject hitObject) - : base(hitObject) + public TestDrawableHitObject(double time) + : base(new HitObject { StartTime = time }) { Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; From f34131f8f444a99e4088776a5fd107b3fd6d4f51 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 18:50:17 +0900 Subject: [PATCH 10/49] Initial game-wide replacement of scrolling playfields --- .../Drawable/DrawableCatchHitObject.cs | 5 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 4 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 - .../Mods/IGenerateSpeedAdjustments.cs | 23 -- .../Mods/ManiaModGravity.cs | 48 ---- .../Drawables/DrawableManiaHitObject.cs | 4 +- .../Tests/TestCaseManiaPlayfield.cs | 33 +-- .../Timing/GravityScrollingContainer.cs | 60 ----- .../Timing/ManiaSpeedAdjustmentContainer.cs | 29 --- .../Timing/ScrollingAlgorithm.cs | 17 -- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- .../UI/ManiaRulesetContainer.cs | 4 - .../osu.Game.Rulesets.Mania.csproj | 5 - .../Objects/Drawables/DrawableBarLine.cs | 2 +- .../Drawables/DrawableTaikoHitObject.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- .../Visual/TestCaseScrollingHitObjects.cs | 66 +----- .../Visual/TestCaseScrollingPlayfield.cs | 219 ------------------ osu.Game.Tests/osu.Game.Tests.csproj | 1 - .../Drawables/DrawableScrollingHitObject.cs | 67 ------ .../Timing/LinearScrollingContainer.cs | 28 --- .../Rulesets/Timing/ScrollingContainer.cs | 93 -------- .../Timing/SpeedAdjustmentContainer.cs | 114 --------- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 165 ++++--------- .../Rulesets/UI/ScrollingRulesetContainer.cs | 9 +- osu.Game/osu.Game.csproj | 4 - 27 files changed, 61 insertions(+), 948 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs delete mode 100644 osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs delete mode 100644 osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs delete mode 100644 osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs delete mode 100644 osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs delete mode 100644 osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs delete mode 100644 osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs delete mode 100644 osu.Game/Rulesets/Timing/LinearScrollingContainer.cs delete mode 100644 osu.Game/Rulesets/Timing/ScrollingContainer.cs delete mode 100644 osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index a617b65676..8954f9fe9e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -24,14 +24,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable } } - public abstract class DrawableCatchHitObject : DrawableScrollingHitObject + public abstract class DrawableCatchHitObject : DrawableHitObject { protected DrawableCatchHitObject(CatchHitObject hitObject) : base(hitObject) { - RelativePositionAxes = Axes.Both; + RelativePositionAxes = Axes.X; X = hitObject.X; - Y = (float)HitObject.StartTime; } public Func CheckPosition; diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 76dbfa77c6..322d1d91af 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -23,12 +23,10 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; public CatchPlayfield(BeatmapDifficulty difficulty) - : base(Axes.Y) + : base(Direction.Vertical) { Container explodingFruitContainer; - Reversed.Value = true; - Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 070c7b09d1..4765f25808 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -95,7 +95,6 @@ namespace osu.Game.Rulesets.Mania new ModCinema(), }, }, - new ManiaModGravity() }; default: diff --git a/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs b/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs deleted file mode 100644 index 954ee3f481..0000000000 --- a/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Mods -{ - /// - /// A type of mod which generates speed adjustments that scroll the hit objects and bar lines. - /// - internal interface IGenerateSpeedAdjustments - { - /// - /// Applies this mod to a hit renderer. - /// - /// The hit renderer to apply to. - /// The per-column list of speed adjustments for hit objects. - /// The list of speed adjustments for bar lines. - void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List[] hitObjectTimingChanges, ref List barlineTimingChanges); - } -} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs deleted file mode 100644 index 70270af6c9..0000000000 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using System.Linq; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Mods; -using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Timing; -using osu.Game.Rulesets.Timing; -using osu.Game.Rulesets.Mania.Objects.Drawables; - -namespace osu.Game.Rulesets.Mania.Mods -{ - public class ManiaModGravity : Mod, IGenerateSpeedAdjustments - { - public override string Name => "Gravity"; - public override string ShortenedName => "GR"; - - public override double ScoreMultiplier => 0; - - public override FontAwesome Icon => FontAwesome.fa_sort_desc; - - public void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List[] hitObjectTimingChanges, ref List barlineTimingChanges) - { - // We have to generate one speed adjustment per hit object for gravity - foreach (ManiaHitObject obj in rulesetContainer.Objects.OfType()) - { - MultiplierControlPoint controlPoint = rulesetContainer.CreateControlPointAt(obj.StartTime); - // Beat length has too large of an effect for gravity, so we'll force it to a constant value for now - controlPoint.TimingPoint.BeatLength = 1000; - - hitObjectTimingChanges[obj.Column].Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity)); - } - - // Like with hit objects, we need to generate one speed adjustment per bar line - foreach (DrawableBarLine barLine in rulesetContainer.BarLines) - { - var controlPoint = rulesetContainer.CreateControlPointAt(barLine.HitObject.StartTime); - // Beat length has too large of an effect for gravity, so we'll force it to a constant value for now - controlPoint.TimingPoint.BeatLength = 1000; - - barlineTimingChanges.Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity)); - } - } - } -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 6354c6ff77..385f18a4f9 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -1,13 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Graphics; using OpenTK.Graphics; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Objects.Drawables { - public abstract class DrawableManiaHitObject : DrawableScrollingHitObject + public abstract class DrawableManiaHitObject : DrawableHitObject where TObject : ManiaHitObject { /// @@ -20,7 +19,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { - RelativePositionAxes = Axes.Y; HitObject = hitObject; if (action != null) diff --git a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs index b5890b289f..6615b39274 100644 --- a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs @@ -5,16 +5,13 @@ using System; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests @@ -44,10 +41,10 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right)); AddStep("Reversed", () => createPlayfield(4, SpecialColumnPosition.Normal, true)); - AddStep("Notes with input", () => createPlayfieldWithNotes(false)); - AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(false, true)); - AddStep("Notes with gravity", () => createPlayfieldWithNotes(true)); - AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true, 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", () => { @@ -70,11 +67,6 @@ namespace osu.Game.Rulesets.Mania.Tests maniaRuleset = rulesets.GetRuleset(3); } - private SpeedAdjustmentContainer createTimingChange(double time, bool gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time) - { - TimingPoint = { BeatLength = 1000 } - }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); - private ManiaPlayfield createPlayfield(int cols, SpecialColumnPosition specialPos, bool inverted = false) { Clear(); @@ -95,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Tests return playfield; } - private void createPlayfieldWithNotes(bool gravity, bool inverted = false) + private void createPlayfieldWithNotes(bool inverted = false) { Clear(); @@ -114,23 +106,14 @@ namespace osu.Game.Rulesets.Mania.Tests playfield.Inverted.Value = inverted; - if (!gravity) - playfield.Columns.ForEach(c => c.Add(createTimingChange(0, false))); - for (double t = start_time; t <= start_time + duration; t += 100) { - if (gravity) - playfield.Columns.ElementAt(0).Add(createTimingChange(t, true)); - playfield.Add(new DrawableNote(new Note { StartTime = t, Column = 0 }, ManiaAction.Key1)); - if (gravity) - playfield.Columns.ElementAt(3).Add(createTimingChange(t, true)); - playfield.Add(new DrawableNote(new Note { StartTime = t, @@ -138,9 +121,6 @@ namespace osu.Game.Rulesets.Mania.Tests }, ManiaAction.Key4)); } - if (gravity) - playfield.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); - playfield.Add(new DrawableHoldNote(new HoldNote { StartTime = start_time, @@ -148,9 +128,6 @@ namespace osu.Game.Rulesets.Mania.Tests Column = 1 }, ManiaAction.Key2)); - if (gravity) - playfield.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); - playfield.Add(new DrawableHoldNote(new HoldNote { StartTime = start_time, diff --git a/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs b/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs deleted file mode 100644 index 699acc477b..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Timing -{ - /// - /// A that emulates a form of gravity where hit objects speed up over time. - /// - internal class GravityScrollingContainer : ScrollingContainer - { - private readonly MultiplierControlPoint controlPoint; - - public GravityScrollingContainer(MultiplierControlPoint controlPoint) - { - this.controlPoint = controlPoint; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - // The gravity-adjusted start position - float startPos = (float)computeGravityTime(controlPoint.StartTime); - // The gravity-adjusted end position - float endPos = (float)computeGravityTime(controlPoint.StartTime + RelativeChildSize.Y); - - Y = startPos; - Height = endPos - startPos; - } - - /// - /// Applies gravity to a time value based on the current time. - /// - /// The time value gravity should be applied to. - /// The time after gravity is applied to . - private double computeGravityTime(double time) - { - double relativeTime = relativeTimeAt(time); - - // The sign of the relative time, this is used to apply backwards acceleration leading into startTime - double sign = relativeTime < 0 ? -1 : 1; - - return VisibleTimeRange - acceleration * relativeTime * relativeTime * sign; - } - - /// - /// The acceleration due to "gravity" of the content of this container. - /// - private double acceleration => 1 / VisibleTimeRange; - - /// - /// Computes the current time relative to , accounting for . - /// - /// The non-offset time. - /// The current time relative to - . - private double relativeTimeAt(double time) => Time.Current - time + VisibleTimeRange; - } -} diff --git a/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs b/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs deleted file mode 100644 index 321b4ee92b..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Timing -{ - public class ManiaSpeedAdjustmentContainer : SpeedAdjustmentContainer - { - private readonly ScrollingAlgorithm scrollingAlgorithm; - - public ManiaSpeedAdjustmentContainer(MultiplierControlPoint timingSection, ScrollingAlgorithm scrollingAlgorithm) - : base(timingSection) - { - this.scrollingAlgorithm = scrollingAlgorithm; - } - - protected override ScrollingContainer CreateScrollingContainer() - { - switch (scrollingAlgorithm) - { - default: - return base.CreateScrollingContainer(); - case ScrollingAlgorithm.Gravity: - return new GravityScrollingContainer(ControlPoint); - } - } - } -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs b/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs deleted file mode 100644 index 72e096f5aa..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Mania.Timing -{ - public enum ScrollingAlgorithm - { - /// - /// Basic scrolling algorithm based on the timing section time. This is the default algorithm. - /// - Basic, - /// - /// Emulating a form of gravity where hit objects speed up over time. - /// - Gravity - } -} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 2d553f8639..048b3ef9f9 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Mania.UI private const float opacity_pressed = 0.25f; public Column() - : base(Axes.Y) + : base(Direction.Vertical) { Width = column_width; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 6c164a34f0..549b0f2ee6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int columnCount; public ManiaPlayfield(int columnCount) - : base(Axes.Y) + : base(Direction.Vertical) { this.columnCount = columnCount; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 61446a31b6..db9475b31e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -17,12 +17,10 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; -using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.UI @@ -121,8 +119,6 @@ namespace osu.Game.Rulesets.Mania.UI protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(1, 0.8f); - protected override SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Basic); - protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay, this); } } diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 3393774a9c..4445f24cd8 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -62,7 +62,6 @@ - @@ -88,8 +87,6 @@ - - @@ -97,9 +94,7 @@ - - diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index b30b3a1aca..97fa91a94b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : DrawableScrollingHitObject + public class DrawableBarLine : DrawableHitObject { /// /// The width of the line tracker. diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index cc7dd2fa0f..5cda186086 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -12,7 +12,7 @@ using System.Collections.Generic; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : DrawableScrollingHitObject, IKeyBindingHandler + public abstract class DrawableTaikoHitObject : DrawableHitObject, IKeyBindingHandler where TaikoHitType : TaikoHitObject { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 3fdbd056ce..5e1fa7e490 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly Box background; public TaikoPlayfield(ControlPointInfo controlPoints) - : base(Axes.X) + : base(Direction.Horizontal) { AddRangeInternal(new Drawable[] { diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index d226203b3b..01387791a1 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -8,7 +8,6 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Lists; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; @@ -100,68 +99,7 @@ namespace osu.Game.Tests.Visual }); } - private class ScrollingHitObjectContainer : Playfield.HitObjectContainer - { - public readonly BindableDouble TimeRange = new BindableDouble - { - MinValue = 0, - MaxValue = double.MaxValue - }; - public readonly SortedList ControlPoints = new SortedList(); - - private readonly Direction scrollingDirection; - - public ScrollingHitObjectContainer(Direction scrollingDirection) - { - this.scrollingDirection = scrollingDirection; - - RelativeSizeAxes = Axes.Both; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - var currentMultiplier = controlPointAt(Time.Current); - - foreach (var obj in AliveObjects) - { - var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); - - // Todo: We may need to consider scale here - var finalPosition = (float)relativePosition * DrawSize; - - switch (scrollingDirection) - { - case Direction.Horizontal: - obj.X = finalPosition.X; - break; - case Direction.Vertical: - obj.Y = finalPosition.Y; - break; - } - } - } - - private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); - private MultiplierControlPoint controlPointAt(double time) - { - if (ControlPoints.Count == 0) - return new MultiplierControlPoint(double.MinValue); - - if (time < ControlPoints[0].StartTime) - return ControlPoints[0]; - - searchingPoint.StartTime = time; - - int index = ControlPoints.BinarySearch(searchingPoint); - if (index < 0) - index = ~index - 1; - - return ControlPoints[index]; - } - } private class TestPlayfield : Playfield { @@ -169,13 +107,13 @@ namespace osu.Game.Tests.Visual public readonly Direction ScrollingDirection; - public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + public new ScrollingPlayfield.ScrollingHitObjectContainer HitObjects => (ScrollingPlayfield.ScrollingHitObjectContainer)base.HitObjects; public TestPlayfield(Direction scrollingDirection) { ScrollingDirection = scrollingDirection; - base.HitObjects = new ScrollingHitObjectContainer(scrollingDirection); + base.HitObjects = new ScrollingPlayfield.ScrollingHitObjectContainer(scrollingDirection); HitObjects.TimeRange.BindTo(TimeRange); } } diff --git a/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs deleted file mode 100644 index 40fb22af1e..0000000000 --- a/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2007-2017 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.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; -using osu.Game.Rulesets.UI; -using osu.Game.Tests.Beatmaps; -using OpenTK; - -namespace osu.Game.Tests.Visual -{ - /// - /// The most minimal implementation of a playfield with scrolling hit objects. - /// - [TestFixture] - public class TestCaseScrollingPlayfield : OsuTestCase - { - public TestCaseScrollingPlayfield() - { - Clock = new FramedClock(); - - var objects = new List(); - - int time = 1500; - for (int i = 0; i < 50; i++) - { - objects.Add(new TestHitObject { StartTime = time }); - - time += 500; - } - - Beatmap b = new Beatmap - { - HitObjects = objects, - BeatmapInfo = new BeatmapInfo - { - BaseDifficulty = new BeatmapDifficulty(), - Metadata = new BeatmapMetadata() - } - }; - - WorkingBeatmap beatmap = new TestWorkingBeatmap(b); - - TestRulesetContainer horizontalRulesetContainer; - Add(horizontalRulesetContainer = new TestRulesetContainer(Axes.X, beatmap, true)); - - TestRulesetContainer verticalRulesetContainer; - Add(verticalRulesetContainer = new TestRulesetContainer(Axes.Y, beatmap, true)); - - AddStep("Reverse direction", () => - { - horizontalRulesetContainer.Playfield.Reverse(); - verticalRulesetContainer.Playfield.Reverse(); - }); - } - - [Test] - public void TestSpeedAdjustmentOrdering() - { - var hitObjectContainer = new ScrollingPlayfield.ScrollingHitObjectContainer(Axes.X); - - var speedAdjustments = new[] - { - new SpeedAdjustmentContainer(new MultiplierControlPoint()), - new SpeedAdjustmentContainer(new MultiplierControlPoint(1000) - { - TimingPoint = new TimingControlPoint { BeatLength = 500 } - }), - new SpeedAdjustmentContainer(new MultiplierControlPoint(2000) - { - TimingPoint = new TimingControlPoint { BeatLength = 1000 }, - DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 2} - }), - new SpeedAdjustmentContainer(new MultiplierControlPoint(3000) - { - TimingPoint = new TimingControlPoint { BeatLength = 1000 }, - DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 1} - }), - }; - - var hitObjects = new[] - { - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = -1000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject()), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 1000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 2000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 3000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 4000 }), - }; - - hitObjects.ForEach(h => hitObjectContainer.Add(h)); - speedAdjustments.ForEach(hitObjectContainer.AddSpeedAdjustment); - - // The 0th index in hitObjectContainer.SpeedAdjustments is the "default" control point - // Check multiplier of the default speed adjustment - Assert.AreEqual(1, hitObjectContainer.SpeedAdjustments[0].ControlPoint.Multiplier); - Assert.AreEqual(1, speedAdjustments[0].ControlPoint.Multiplier); - Assert.AreEqual(2, speedAdjustments[1].ControlPoint.Multiplier); - Assert.AreEqual(2, speedAdjustments[2].ControlPoint.Multiplier); - Assert.AreEqual(1, speedAdjustments[3].ControlPoint.Multiplier); - - // Check insertion of hit objects - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[4].Contains(hitObjects[0])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[2].Contains(hitObjects[2])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[1].Contains(hitObjects[3])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[4])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[5])); - - hitObjectContainer.RemoveSpeedAdjustment(hitObjectContainer.SpeedAdjustments[3]); - - // The hit object contained in this speed adjustment should be resorted into the one occuring before it - - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1])); - } - - private class TestRulesetContainer : ScrollingRulesetContainer - { - private readonly Axes scrollingAxes; - - public TestRulesetContainer(Axes scrollingAxes, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(null, beatmap, isForCurrentRuleset) - { - this.scrollingAxes = scrollingAxes; - } - - public new TestPlayfield Playfield => base.Playfield; - - public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor(); - - public override PassThroughInputManager CreateInputManager() => new PassThroughInputManager(); - - protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); - - protected override Playfield CreatePlayfield() => new TestPlayfield(scrollingAxes); - - protected override DrawableHitObject GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(scrollingAxes, h); - } - - private class TestScoreProcessor : ScoreProcessor - { - protected override void OnNewJudgement(Judgement judgement) - { - } - } - - private class TestBeatmapConverter : BeatmapConverter - { - protected override IEnumerable ValidConversionTypes => new[] { typeof(HitObject) }; - - protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) - { - yield return original as TestHitObject; - } - } - - private class DrawableTestHitObject : DrawableScrollingHitObject - { - public DrawableTestHitObject(Axes scrollingAxes, TestHitObject hitObject) - : base(hitObject) - { - Anchor = scrollingAxes == Axes.Y ? Anchor.TopCentre : Anchor.CentreLeft; - Origin = Anchor.Centre; - - AutoSizeAxes = Axes.Both; - - Add(new Circle - { - Size = new Vector2(50) - }); - } - - protected override void UpdateState(ArmedState state) - { - } - } - - private class TestPlayfield : ScrollingPlayfield - { - protected override Container Content => content; - private readonly Container content; - - public TestPlayfield(Axes scrollingAxes) - : base(scrollingAxes) - { - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.2f - }, - content = new Container { RelativeSizeAxes = Axes.Both } - }; - } - - public void Reverse() => Reversed.Toggle(); - } - - - private class TestHitObject : HitObject - { - } - } -} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index f47a03990a..2eb79f6b35 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -142,7 +142,6 @@ - diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs deleted file mode 100644 index 538bb826ad..0000000000 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Objects.Drawables -{ - /// - /// A basic class that overrides and implements . - /// This object does not need to have its set to be able to scroll, as this will - /// will be set by the scrolling container that contains it. - /// - public abstract class DrawableScrollingHitObject : DrawableHitObject, IScrollingHitObject - where TObject : HitObject - { - public BindableDouble LifetimeOffset { get; } = new BindableDouble(); - - Axes IScrollingHitObject.ScrollingAxes - { - set - { - RelativePositionAxes |= value; - - if ((value & Axes.X) > 0) - X = (float)HitObject.StartTime; - if ((value & Axes.Y) > 0) - Y = (float)HitObject.StartTime; - } - } - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - protected DrawableScrollingHitObject(TObject hitObject) - : base(hitObject) - { - } - - private double? lifetimeStart; - public override double LifetimeStart - { - get { return lifetimeStart ?? HitObject.StartTime - LifetimeOffset; } - set { lifetimeStart = value; } - } - - private double? lifetimeEnd; - public override double LifetimeEnd - { - get - { - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - return lifetimeEnd ?? endTime + LifetimeOffset; - } - set { lifetimeEnd = value; } - } - - protected override void AddNested(DrawableHitObject h) - { - var scrollingHitObject = h as IScrollingHitObject; - scrollingHitObject?.LifetimeOffset.BindTo(LifetimeOffset); - - base.AddNested(h); - } - } -} \ No newline at end of file diff --git a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs deleted file mode 100644 index b093cf3303..0000000000 --- a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A which scrolls linearly relative to the start time. - /// - public class LinearScrollingContainer : ScrollingContainer - { - private readonly MultiplierControlPoint controlPoint; - - public LinearScrollingContainer(MultiplierControlPoint controlPoint) - { - this.controlPoint = controlPoint; - } - - protected override void Update() - { - base.Update(); - - if ((ScrollingAxes & Axes.X) > 0) X = (float)(controlPoint.StartTime - Time.Current); - if ((ScrollingAxes & Axes.Y) > 0) Y = (float)(controlPoint.StartTime - Time.Current); - } - } -} diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs deleted file mode 100644 index eac596297a..0000000000 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using osu.Framework.Caching; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; -using OpenTK; -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A container that scrolls relative to the current time. Will autosize to the total duration of all contained hit objects along the scrolling axes. - /// - public abstract class ScrollingContainer : Container - { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// - public readonly BindableDouble VisibleTimeRange = new BindableDouble { Default = 1000 }; - - /// - /// The axes through which this scrolls. This is set by the . - /// - internal Axes ScrollingAxes; - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - /// - /// The control point that defines the speed adjustments for this container. This is set by the . - /// - internal MultiplierControlPoint ControlPoint; - - private Cached durationBacking; - - /// - /// Creates a new . - /// - protected ScrollingContainer() - { - RelativeSizeAxes = Axes.Both; - RelativePositionAxes = Axes.Both; - } - - protected override int Compare(Drawable x, Drawable y) - { - var hX = (DrawableHitObject)x; - var hY = (DrawableHitObject)y; - - int result = hY.HitObject.StartTime.CompareTo(hX.HitObject.StartTime); - if (result != 0) - return result; - return base.Compare(y, x); - } - - public override void Add(DrawableHitObject drawable) - { - durationBacking.Invalidate(); - base.Add(drawable); - } - - public override bool Remove(DrawableHitObject drawable) - { - durationBacking.Invalidate(); - return base.Remove(drawable); - } - - // Todo: This may underestimate the size of the hit object in some cases, but won't be too much of a problem for now - private double computeDuration() => Math.Max(0, Children.Select(c => (c.HitObject as IHasEndTime)?.EndTime ?? c.HitObject.StartTime).DefaultIfEmpty().Max() - ControlPoint.StartTime) + 1000; - - /// - /// An approximate total duration of this scrolling container. - /// - public double Duration => durationBacking.IsValid ? durationBacking : (durationBacking.Value = computeDuration()); - - protected override void Update() - { - base.Update(); - - RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)ControlPoint.StartTime : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)ControlPoint.StartTime : 0); - - // We want our size and position-space along the scrolling axes to span our duration to completely enclose all the hit objects - Size = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)Duration : Size.X, (ScrollingAxes & Axes.Y) > 0 ? (float)Duration : Size.Y); - // And we need to make sure the hit object's position-space doesn't change due to our resizing - RelativeChildSize = Size; - } - } -} diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs deleted file mode 100644 index 81e3a5c70e..0000000000 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; -using OpenTK; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A container that provides the speed adjustments defined by s to affect the scroll speed - /// of container s. - /// - public class SpeedAdjustmentContainer : Container - { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// - public readonly Bindable VisibleTimeRange = new Bindable { Default = 1000 }; - - /// - /// Whether to reverse the scrolling direction is reversed. - /// - public readonly BindableBool Reversed = new BindableBool(); - - protected override Container Content => content; - private readonly Container content; - - /// - /// The axes which the content of this container will scroll through. - /// - public Axes ScrollingAxes - { - get { return scrollingContainer.ScrollingAxes; } - set { scrollingContainer.ScrollingAxes = value; } - } - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - /// - /// The that defines the speed adjustments. - /// - public readonly MultiplierControlPoint ControlPoint; - - private readonly ScrollingContainer scrollingContainer; - - /// - /// Creates a new . - /// - /// The that defines the speed adjustments. - public SpeedAdjustmentContainer(MultiplierControlPoint controlPoint) - { - ControlPoint = controlPoint; - RelativeSizeAxes = Axes.Both; - - scrollingContainer = CreateScrollingContainer(); - scrollingContainer.ControlPoint = ControlPoint; - scrollingContainer.VisibleTimeRange.BindTo(VisibleTimeRange); - - AddInternal(content = scrollingContainer); - } - - protected override void Update() - { - float multiplier = (float)ControlPoint.Multiplier; - - // The speed adjustment happens by modifying our size by the multiplier while maintaining the visible time range as the relatve size for our children - Size = new Vector2((ScrollingAxes & Axes.X) > 0 ? multiplier : 1, (ScrollingAxes & Axes.Y) > 0 ? multiplier : 1); - - if (Reversed) - { - RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)-VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)-VisibleTimeRange : 1); - RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 0); - Origin = Anchor = Anchor.BottomRight; - } - else - { - RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1); - RelativeChildOffset = Vector2.Zero; - Origin = Anchor = Anchor.TopLeft; - } - } - - public override double LifetimeStart => ControlPoint.StartTime - VisibleTimeRange; - public override double LifetimeEnd => ControlPoint.StartTime + scrollingContainer.Duration + VisibleTimeRange; - - public override void Add(DrawableHitObject drawable) - { - var scrollingHitObject = drawable as IScrollingHitObject; - - if (scrollingHitObject != null) - { - scrollingHitObject.LifetimeOffset.BindTo(VisibleTimeRange); - scrollingHitObject.ScrollingAxes = ScrollingAxes; - } - - base.Add(drawable); - } - - /// - /// Whether a point in time falls within this s affecting timespan. - /// - public bool CanContain(double startTime) => ControlPoint.StartTime <= startTime; - - /// - /// Creates the which contains the scrolling s of this container. - /// - /// The . - protected virtual ScrollingContainer CreateScrollingContainer() => new LinearScrollingContainer(ControlPoint); - } -} diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 395248b2fd..56959240a8 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -1,15 +1,13 @@ // Copyright (c) 2007-2017 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 OpenTK.Input; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; +using osu.Framework.Lists; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; @@ -50,11 +48,6 @@ namespace osu.Game.Rulesets.UI MaxValue = time_span_max }; - /// - /// Whether to reverse the scrolling direction is reversed. Note that this does _not_ invert the hit objects. - /// - protected readonly BindableBool Reversed = new BindableBool(); - /// /// The container that contains the s and s. /// @@ -65,12 +58,11 @@ namespace osu.Game.Rulesets.UI /// /// The axes on which s in this container should scroll. /// Whether we want our internal coordinate system to be scaled to a specified width - protected ScrollingPlayfield(Axes scrollingAxes, float? customWidth = null) + protected ScrollingPlayfield(Direction scrollingDirection, float? customWidth = null) : base(customWidth) { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) { RelativeSizeAxes = Axes.Both }; - HitObjects.VisibleTimeRange.BindTo(VisibleTimeRange); - HitObjects.Reversed.BindTo(Reversed); + base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingDirection) { RelativeSizeAxes = Axes.Both }; + HitObjects.TimeRange.BindTo(VisibleTimeRange); } private List nestedPlayfields; @@ -131,135 +123,66 @@ namespace osu.Game.Rulesets.UI protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; } - /// - /// A container that provides the foundation for sorting s into s. - /// public class ScrollingHitObjectContainer : HitObjectContainer { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// For example, only hit objects with start time less than or equal to 1000 will be visible with = 1000. - /// - public readonly BindableDouble VisibleTimeRange = new BindableDouble { Default = 1000 }; - - /// - /// Whether to reverse the scrolling direction is reversed. - /// - public readonly BindableBool Reversed = new BindableBool(); - - private readonly SortedContainer speedAdjustments; - public IReadOnlyList SpeedAdjustments => speedAdjustments; - - private readonly SpeedAdjustmentContainer defaultSpeedAdjustment; - - private readonly Axes scrollingAxes; - - /// - /// Creates a new . - /// - /// The axes upon which hit objects should appear to scroll inside this container. - public ScrollingHitObjectContainer(Axes scrollingAxes) + public readonly BindableDouble TimeRange = new BindableDouble { - this.scrollingAxes = scrollingAxes; + MinValue = 0, + MaxValue = double.MaxValue + }; - AddInternal(speedAdjustments = new SortedContainer { RelativeSizeAxes = Axes.Both }); + public readonly SortedList ControlPoints = new SortedList(); - // Default speed adjustment - AddSpeedAdjustment(defaultSpeedAdjustment = new SpeedAdjustmentContainer(new MultiplierControlPoint(0))); + private readonly Direction scrollingDirection; + + public ScrollingHitObjectContainer(Direction scrollingDirection) + { + this.scrollingDirection = scrollingDirection; + + RelativeSizeAxes = Axes.Both; } - /// - /// Adds a to this container, re-sorting all hit objects - /// in the last that occurred (time-wise) before it. - /// - /// The . - public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) + protected override void UpdateAfterChildren() { - speedAdjustment.ScrollingAxes = scrollingAxes; - speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); - speedAdjustment.Reversed.BindTo(Reversed); + base.UpdateAfterChildren(); - if (speedAdjustments.Count > 0) + var currentMultiplier = controlPointAt(Time.Current); + + foreach (var obj in AliveObjects) { - // We need to re-sort all hit objects in the speed adjustment container prior to figure out if they - // should now lie within this one - var existingAdjustment = adjustmentContainerAt(speedAdjustment.ControlPoint.StartTime); - for (int i = 0; i < existingAdjustment.Count; i++) + var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); + + // Todo: We may need to consider scale here + var finalPosition = (float)relativePosition * DrawSize; + + switch (scrollingDirection) { - DrawableHitObject hitObject = existingAdjustment[i]; - - if (!speedAdjustment.CanContain(hitObject.HitObject.StartTime)) - continue; - - existingAdjustment.Remove(hitObject); - speedAdjustment.Add(hitObject); - - i--; + case Direction.Horizontal: + obj.X = finalPosition.X; + break; + case Direction.Vertical: + obj.Y = finalPosition.Y; + break; } } - - speedAdjustments.Add(speedAdjustment); } - /// - /// Removes a from this container, re-sorting all hit objects - /// which it contained into new s. - /// - /// The to remove. - public void RemoveSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) + private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) { - if (speedAdjustment == defaultSpeedAdjustment) - throw new InvalidOperationException($"The default {nameof(SpeedAdjustmentContainer)} must not be removed."); + if (ControlPoints.Count == 0) + return new MultiplierControlPoint(double.MinValue); - if (!speedAdjustments.Remove(speedAdjustment)) - return; + if (time < ControlPoints[0].StartTime) + return ControlPoints[0]; - while (speedAdjustment.Count > 0) - { - DrawableHitObject hitObject = speedAdjustment[0]; + searchingPoint.StartTime = time; - speedAdjustment.Remove(hitObject); - Add(hitObject); - } - } + int index = ControlPoints.BinarySearch(searchingPoint); + if (index < 0) + index = ~index - 1; - public override IEnumerable Objects => speedAdjustments.SelectMany(s => s.Children); - - /// - /// Adds a hit object to this . The hit objects will be queued to be processed - /// new s are added to this . - /// - /// The hit object to add. - public override void Add(DrawableHitObject hitObject) - { - if (!(hitObject is IScrollingHitObject)) - throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}."); - - adjustmentContainerAt(hitObject.HitObject.StartTime).Add(hitObject); - } - - public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)); - - /// - /// Finds the which provides the speed adjustment active at a time. - /// If there is no active at the time, then the first (time-wise) speed adjustment is returned. - /// - /// The time to find the active at. - /// The active at . Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.FirstOrDefault(c => c.CanContain(time)) ?? defaultSpeedAdjustment; - - private class SortedContainer : Container - { - protected override int Compare(Drawable x, Drawable y) - { - var sX = (SpeedAdjustmentContainer)x; - var sY = (SpeedAdjustmentContainer)y; - - int result = sY.ControlPoint.StartTime.CompareTo(sX.ControlPoint.StartTime); - if (result != 0) - return result; - return base.Compare(y, x); - } + return ControlPoints[index]; } } } diff --git a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs index f1b8838fa9..9d98382a8b 100644 --- a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.UI private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield) { - playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint)); + playfield.HitObjects.ControlPoints.Add(controlPoint); playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p)); } @@ -108,12 +108,5 @@ namespace osu.Game.Rulesets.UI return new MultiplierControlPoint(time, DefaultControlPoints[index].DeepClone()); } - - /// - /// Creates a that facilitates the movement of hit objects. - /// - /// The that provides the speed adjustments for the hitobjects. - /// The . - protected virtual SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new SpeedAdjustmentContainer(controlPoint); } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 519e214495..2369724f6b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -614,7 +614,6 @@ - @@ -665,10 +664,7 @@ - - - From 651e24e3cc497c647f782e94fef948dbc75d35a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 19:17:40 +0900 Subject: [PATCH 11/49] Implement proper scrolling directions --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- .../Visual/TestCaseScrollingHitObjects.cs | 16 ++++++------ osu.Game/Rulesets/UI/ScrollingDirection.cs | 25 +++++++++++++++++++ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 24 +++++++++++------- osu.Game/osu.Game.csproj | 1 + 8 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 osu.Game/Rulesets/UI/ScrollingDirection.cs diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 322d1d91af..2f7d7449c8 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; public CatchPlayfield(BeatmapDifficulty difficulty) - : base(Direction.Vertical) + : base(ScrollingDirection.Down) { Container explodingFruitContainer; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 048b3ef9f9..a0768e48a2 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Mania.UI private const float opacity_pressed = 0.25f; public Column() - : base(Direction.Vertical) + : base(ScrollingDirection.Down) { Width = column_width; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 549b0f2ee6..161dd9ec22 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int columnCount; public ManiaPlayfield(int columnCount) - : base(Direction.Vertical) + : base(ScrollingDirection.Down) { this.columnCount = columnCount; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 5e1fa7e490..8c55fe009f 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly Box background; public TaikoPlayfield(ControlPointInfo controlPoints) - : base(Direction.Horizontal) + : base(ScrollingDirection.Left) { AddRangeInternal(new Drawable[] { diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 01387791a1..b05efbde5c 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -24,8 +24,8 @@ namespace osu.Game.Tests.Visual public TestCaseScrollingHitObjects() { - playfields.Add(new TestPlayfield(Direction.Vertical)); - playfields.Add(new TestPlayfield(Direction.Horizontal)); + playfields.Add(new TestPlayfield(ScrollingDirection.Down)); + playfields.Add(new TestPlayfield(ScrollingDirection.Right)); playfields.ForEach(p => p.HitObjects.ControlPoints.Add(new MultiplierControlPoint(double.MinValue))); @@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual { p.Add(new TestDrawableHitObject(time) { - Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + Anchor = p.Direction == ScrollingDirection.Right ? Anchor.CentreRight : Anchor.BottomCentre }); }); } @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual TestDrawableControlPoint createDrawablePoint(double t) => new TestDrawableControlPoint(t) { - Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + Anchor = p.Direction == ScrollingDirection.Right ? Anchor.CentreRight : Anchor.BottomCentre }; p.Add(createDrawablePoint(time)); @@ -105,15 +105,15 @@ namespace osu.Game.Tests.Visual { public readonly BindableDouble TimeRange = new BindableDouble(5000); - public readonly Direction ScrollingDirection; + public readonly ScrollingDirection Direction; public new ScrollingPlayfield.ScrollingHitObjectContainer HitObjects => (ScrollingPlayfield.ScrollingHitObjectContainer)base.HitObjects; - public TestPlayfield(Direction scrollingDirection) + public TestPlayfield(ScrollingDirection direction) { - ScrollingDirection = scrollingDirection; + Direction = direction; - base.HitObjects = new ScrollingPlayfield.ScrollingHitObjectContainer(scrollingDirection); + base.HitObjects = new ScrollingPlayfield.ScrollingHitObjectContainer(direction); HitObjects.TimeRange.BindTo(TimeRange); } } diff --git a/osu.Game/Rulesets/UI/ScrollingDirection.cs b/osu.Game/Rulesets/UI/ScrollingDirection.cs new file mode 100644 index 0000000000..29d63499ee --- /dev/null +++ b/osu.Game/Rulesets/UI/ScrollingDirection.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +namespace osu.Game.Rulesets.UI +{ + public enum ScrollingDirection + { + /// + /// Hitobjects will scroll vertically from the bottom of the hitobject container. + /// + Up, + /// + /// Hitobjects will scroll vertically from the top of the hitobject container. + /// + Down, + /// + /// Hitobjects will scroll horizontally from the right of the hitobject container. + /// + Left, + /// + /// Hitobjects will scroll horizontally from the left of the hitobject container. + /// + Right + } +} diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 56959240a8..f391d01ac9 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -58,10 +58,10 @@ namespace osu.Game.Rulesets.UI /// /// The axes on which s in this container should scroll. /// Whether we want our internal coordinate system to be scaled to a specified width - protected ScrollingPlayfield(Direction scrollingDirection, float? customWidth = null) + protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null) : base(customWidth) { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingDirection) { RelativeSizeAxes = Axes.Both }; + base.HitObjects = HitObjects = new ScrollingHitObjectContainer(direction) { RelativeSizeAxes = Axes.Both }; HitObjects.TimeRange.BindTo(VisibleTimeRange); } @@ -133,11 +133,11 @@ namespace osu.Game.Rulesets.UI public readonly SortedList ControlPoints = new SortedList(); - private readonly Direction scrollingDirection; + private readonly ScrollingDirection direction; - public ScrollingHitObjectContainer(Direction scrollingDirection) + public ScrollingHitObjectContainer(ScrollingDirection direction) { - this.scrollingDirection = scrollingDirection; + this.direction = direction; RelativeSizeAxes = Axes.Both; } @@ -155,14 +155,20 @@ namespace osu.Game.Rulesets.UI // Todo: We may need to consider scale here var finalPosition = (float)relativePosition * DrawSize; - switch (scrollingDirection) + switch (direction) { - case Direction.Horizontal: - obj.X = finalPosition.X; + case ScrollingDirection.Up: + obj.Y = -finalPosition.Y; break; - case Direction.Vertical: + case ScrollingDirection.Down: obj.Y = finalPosition.Y; break; + case ScrollingDirection.Left: + obj.X = -finalPosition.X; + break; + case ScrollingDirection.Right: + obj.X = finalPosition.X; + break; } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2369724f6b..c5c1004663 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -314,6 +314,7 @@ + From e0c921ff5c7426c6115c9f690eb749dcb2405b15 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 19:20:43 +0900 Subject: [PATCH 12/49] Split out ScrollingHitObjectContainer into new file --- .../Visual/TestCaseScrollingHitObjects.cs | 4 +- .../UI/ScrollingHitObjectContainer.cs | 79 +++++++++++++++++++ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 71 ----------------- osu.Game/osu.Game.csproj | 1 + 4 files changed, 82 insertions(+), 73 deletions(-) create mode 100644 osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index b05efbde5c..71c1295ebb 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -107,13 +107,13 @@ namespace osu.Game.Tests.Visual public readonly ScrollingDirection Direction; - public new ScrollingPlayfield.ScrollingHitObjectContainer HitObjects => (ScrollingPlayfield.ScrollingHitObjectContainer)base.HitObjects; + public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; public TestPlayfield(ScrollingDirection direction) { Direction = direction; - base.HitObjects = new ScrollingPlayfield.ScrollingHitObjectContainer(direction); + base.HitObjects = new ScrollingHitObjectContainer(direction); HitObjects.TimeRange.BindTo(TimeRange); } } diff --git a/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs new file mode 100644 index 0000000000..61184ac53f --- /dev/null +++ b/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Lists; +using osu.Game.Rulesets.Timing; + +namespace osu.Game.Rulesets.UI +{ + public class ScrollingHitObjectContainer : Playfield.HitObjectContainer + { + public readonly BindableDouble TimeRange = new BindableDouble + { + MinValue = 0, + MaxValue = double.MaxValue + }; + + public readonly SortedList ControlPoints = new SortedList(); + + private readonly ScrollingDirection direction; + + public ScrollingHitObjectContainer(ScrollingDirection direction) + { + this.direction = direction; + + RelativeSizeAxes = Axes.Both; + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + var currentMultiplier = controlPointAt(Time.Current); + + foreach (var obj in AliveObjects) + { + var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); + + // Todo: We may need to consider scale here + var finalPosition = (float)relativePosition * DrawSize; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = -finalPosition.Y; + break; + case ScrollingDirection.Down: + obj.Y = finalPosition.Y; + break; + case ScrollingDirection.Left: + obj.X = -finalPosition.X; + break; + case ScrollingDirection.Right: + obj.X = finalPosition.X; + break; + } + } + } + + private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) + { + if (ControlPoints.Count == 0) + return new MultiplierControlPoint(double.MinValue); + + if (time < ControlPoints[0].StartTime) + return ControlPoints[0]; + + searchingPoint.StartTime = time; + + int index = ControlPoints.BinarySearch(searchingPoint); + if (index < 0) + index = ~index - 1; + + return ControlPoints[index]; + } + } +} diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index f391d01ac9..5492f9e272 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -7,10 +7,8 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; -using osu.Framework.Lists; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.UI { @@ -122,74 +120,5 @@ namespace osu.Game.Rulesets.UI protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time); protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; } - - public class ScrollingHitObjectContainer : HitObjectContainer - { - public readonly BindableDouble TimeRange = new BindableDouble - { - MinValue = 0, - MaxValue = double.MaxValue - }; - - public readonly SortedList ControlPoints = new SortedList(); - - private readonly ScrollingDirection direction; - - public ScrollingHitObjectContainer(ScrollingDirection direction) - { - this.direction = direction; - - RelativeSizeAxes = Axes.Both; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - var currentMultiplier = controlPointAt(Time.Current); - - foreach (var obj in AliveObjects) - { - var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); - - // Todo: We may need to consider scale here - var finalPosition = (float)relativePosition * DrawSize; - - switch (direction) - { - case ScrollingDirection.Up: - obj.Y = -finalPosition.Y; - break; - case ScrollingDirection.Down: - obj.Y = finalPosition.Y; - break; - case ScrollingDirection.Left: - obj.X = -finalPosition.X; - break; - case ScrollingDirection.Right: - obj.X = finalPosition.X; - break; - } - } - } - - private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); - private MultiplierControlPoint controlPointAt(double time) - { - if (ControlPoints.Count == 0) - return new MultiplierControlPoint(double.MinValue); - - if (time < ControlPoints[0].StartTime) - return ControlPoints[0]; - - searchingPoint.StartTime = time; - - int index = ControlPoints.BinarySearch(searchingPoint); - if (index < 0) - index = ~index - 1; - - return ControlPoints[index]; - } - } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c5c1004663..9cf7d72d1b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -315,6 +315,7 @@ + From a7aab21a29b5d0cc268141933b4146a8f7b7fbf5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 19:22:15 +0900 Subject: [PATCH 13/49] Re-namespace files --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs | 1 + osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs | 1 + osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs | 1 + osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 1 + .../Rulesets/UI/{ => Scrolling}/ScrollingDirection.cs | 2 +- .../UI/{ => Scrolling}/ScrollingHitObjectContainer.cs | 2 +- .../Rulesets/UI/{ => Scrolling}/ScrollingPlayfield.cs | 4 ++-- .../UI/{ => Scrolling}/ScrollingRulesetContainer.cs | 2 +- osu.Game/osu.Game.csproj | 8 ++++---- 13 files changed, 17 insertions(+), 13 deletions(-) rename osu.Game/Rulesets/UI/{ => Scrolling}/ScrollingDirection.cs (92%) rename osu.Game/Rulesets/UI/{ => Scrolling}/ScrollingHitObjectContainer.cs (95%) rename osu.Game/Rulesets/UI/{ => Scrolling}/ScrollingPlayfield.cs (97%) rename osu.Game/Rulesets/UI/{ => Scrolling}/ScrollingRulesetContainer.cs (97%) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 2f7d7449c8..1ea05f8ff6 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Rulesets.UI; using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -10,6 +9,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI { diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 3ed9090098..e9f1a26e69 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI { diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index a0768e48a2..81997d3705 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -12,8 +12,8 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 161dd9ec22..cc028a85ee 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Containers; @@ -17,6 +16,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index db9475b31e..55bae45ab2 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -22,6 +22,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 8c55fe009f..007c637659 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Taiko.Objects; -using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; using osu.Game.Rulesets.Taiko.Judgements; @@ -17,6 +16,7 @@ using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 614b446181..cef51c664f 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Taiko.Replays; using OpenTK; using System.Linq; using osu.Framework.Input; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 71c1295ebb..7e332c7310 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; using OpenTK.Graphics; namespace osu.Game.Tests.Visual diff --git a/osu.Game/Rulesets/UI/ScrollingDirection.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs similarity index 92% rename from osu.Game/Rulesets/UI/ScrollingDirection.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs index 29d63499ee..d89795f4d3 100644 --- a/osu.Game/Rulesets/UI/ScrollingDirection.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { public enum ScrollingDirection { diff --git a/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs similarity index 95% rename from osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 61184ac53f..4c11c53a89 100644 --- a/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { public class ScrollingHitObjectContainer : Playfield.HitObjectContainer { diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs similarity index 97% rename from osu.Game/Rulesets/UI/ScrollingPlayfield.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 5492f9e272..899048531f 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,15 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using OpenTK.Input; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; +using OpenTK.Input; -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { /// /// A type of specialized towards scrolling s. diff --git a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs similarity index 97% rename from osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index 9d98382a8b..73c3848f69 100644 --- a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { /// /// A type of that supports a . diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9cf7d72d1b..a1912487e9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -314,8 +314,10 @@ - - + + + + @@ -671,8 +673,6 @@ - - From 585df22c88f0c8d83587f17f870afa5da8e9ac8f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 20:56:18 +0900 Subject: [PATCH 14/49] Add a way to calculate length of IHasEndTime objects --- .../Scrolling/ScrollingHitObjectContainer.cs | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 4c11c53a89..36b885c84b 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -4,7 +4,9 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; +using OpenTK; namespace osu.Game.Rulesets.UI.Scrolling { @@ -35,9 +37,8 @@ namespace osu.Game.Rulesets.UI.Scrolling foreach (var obj in AliveObjects) { - var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); - // Todo: We may need to consider scale here + var relativePosition = (Time.Current - obj.HitObject.StartTime) * currentMultiplier.Multiplier / TimeRange; var finalPosition = (float)relativePosition * DrawSize; switch (direction) @@ -55,6 +56,27 @@ namespace osu.Game.Rulesets.UI.Scrolling obj.X = finalPosition.X; break; } + + if (!(obj.HitObject is IHasEndTime endTime)) + continue; + + // Todo: We may need to consider scale here + var relativeEndPosition = (Time.Current - endTime.EndTime) * currentMultiplier.Multiplier / TimeRange; + var finalEndPosition = (float)relativeEndPosition * DrawSize; + + float length = Vector2.Distance(finalPosition, finalEndPosition); + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = length; + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = length; + break; + } } } From 4fee76ba0b8b2496f1812cebc5610de88b40ae1d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 20:56:28 +0900 Subject: [PATCH 15/49] Fix drumroll lengths --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index f5bafefd0b..88184d5fcf 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public DrawableDrumRoll(DrumRoll drumRoll) : base(drumRoll) { - Width = (float)HitObject.Duration; + RelativeSizeAxes = Axes.Y; Container tickContainer; MainPiece.Add(tickContainer = new Container From add68ff068577a1f14ac4e9841c56316b8074336 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 21:45:29 +0900 Subject: [PATCH 16/49] Fix swells not stopping at the hit position --- osu-framework | 2 +- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 2 +- .../Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu-framework b/osu-framework index 6134dafccb..067fdb8f5b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 6134dafccb3368dac96d837537325c04b89fb8ee +Subproject commit 067fdb8f5b0594be1cd30e6bbd43f2ea749904ec diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 26e6585fb9..c8e5913fd2 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -192,7 +192,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Size = BaseSize * Parent.RelativeChildSize; // Make the swell stop at the hit target - X = (float)Math.Max(Time.Current, HitObject.StartTime); + X = Math.Max(0, X); double t = Math.Min(HitObject.StartTime, Time.Current); if (t == HitObject.StartTime && !hasStarted) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 36b885c84b..4011e7ffd1 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -29,9 +29,12 @@ namespace osu.Game.Rulesets.UI.Scrolling RelativeSizeAxes = Axes.Both; } - protected override void UpdateAfterChildren() + protected override void UpdateAfterChildrenLife() { - base.UpdateAfterChildren(); + base.UpdateAfterChildrenLife(); + + // We need to calculate this as soon as possible so that hitobjects + // get the final say in their positions var currentMultiplier = controlPointAt(Time.Current); From e0e84ff37011d69a5e0f521bb83f6566c478c7cf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 22:05:20 +0900 Subject: [PATCH 17/49] Fix mania playfield scrolling hitobjects in the wrong direction --- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 81997d3705..0910f9f37d 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Mania.UI private const float opacity_pressed = 0.25f; public Column() - : base(ScrollingDirection.Down) + : base(ScrollingDirection.Up) { Width = column_width; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index cc028a85ee..edb640a537 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int columnCount; public ManiaPlayfield(int columnCount) - : base(ScrollingDirection.Down) + : base(ScrollingDirection.Up) { this.columnCount = columnCount; From ce94c825d18be7f32ab0ba8235bf01d7ad4b2aa2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 22:05:38 +0900 Subject: [PATCH 18/49] Fix length of hold notes --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 41d817a746..48e1332597 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -42,8 +42,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public DrawableHoldNote(HoldNote hitObject, ManiaAction action) : base(hitObject, action) { - RelativeSizeAxes = Axes.Both; - Height = (float)HitObject.Duration; + RelativeSizeAxes = Axes.X; AddRange(new Drawable[] { From d2b135d2a81545202b25a9d7e8a625318c1d9b85 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jan 2018 15:48:19 +0900 Subject: [PATCH 19/49] Give hitobjects lifetimes --- .../UI/Scrolling/ScrollingHitObjectContainer.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 4011e7ffd1..7382d46dec 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -29,11 +29,22 @@ namespace osu.Game.Rulesets.UI.Scrolling RelativeSizeAxes = Axes.Both; } + protected override bool UpdateChildrenLife() + { + foreach (var obj in Objects) + { + obj.LifetimeStart = obj.HitObject.StartTime - TimeRange - 1000; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime + TimeRange) + 1000; + } + + return base.UpdateChildrenLife(); + } + protected override void UpdateAfterChildrenLife() { base.UpdateAfterChildrenLife(); - // We need to calculate this as soon as possible so that hitobjects + // We need to calculate this as soon as possible after lifetimes so that hitobjects // get the final say in their positions var currentMultiplier = controlPointAt(Time.Current); From 5d12682e83335bae9725465c46495bbe17c6457b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jan 2018 20:17:02 +0900 Subject: [PATCH 20/49] Initial implementation of the new (old) mania scrolling calculations --- .../Scrolling/ScrollingHitObjectContainer.cs | 46 +++++++++---------- .../UI/Scrolling/ScrollingRulesetContainer.cs | 10 ++-- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 7382d46dec..8c3e1162e3 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; @@ -33,8 +34,8 @@ namespace osu.Game.Rulesets.UI.Scrolling { foreach (var obj in Objects) { - obj.LifetimeStart = obj.HitObject.StartTime - TimeRange - 1000; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime + TimeRange) + 1000; + obj.LifetimeStart = obj.HitObject.StartTime - TimeRange * 2; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + TimeRange * 2; } return base.UpdateChildrenLife(); @@ -47,27 +48,25 @@ namespace osu.Game.Rulesets.UI.Scrolling // We need to calculate this as soon as possible after lifetimes so that hitobjects // get the final say in their positions - var currentMultiplier = controlPointAt(Time.Current); + var timelinePosition = positionAt(Time.Current); foreach (var obj in AliveObjects) { - // Todo: We may need to consider scale here - var relativePosition = (Time.Current - obj.HitObject.StartTime) * currentMultiplier.Multiplier / TimeRange; - var finalPosition = (float)relativePosition * DrawSize; + var finalPosition = positionAt(obj.HitObject.StartTime); switch (direction) { case ScrollingDirection.Up: - obj.Y = -finalPosition.Y; + obj.Y = finalPosition.Y - timelinePosition.Y; break; case ScrollingDirection.Down: - obj.Y = finalPosition.Y; + obj.Y = -finalPosition.Y + timelinePosition.Y; break; case ScrollingDirection.Left: - obj.X = -finalPosition.X; + obj.X = finalPosition.X - timelinePosition.X; break; case ScrollingDirection.Right: - obj.X = finalPosition.X; + obj.X = -finalPosition.X + timelinePosition.X; break; } @@ -75,8 +74,7 @@ namespace osu.Game.Rulesets.UI.Scrolling continue; // Todo: We may need to consider scale here - var relativeEndPosition = (Time.Current - endTime.EndTime) * currentMultiplier.Multiplier / TimeRange; - var finalEndPosition = (float)relativeEndPosition * DrawSize; + var finalEndPosition = positionAt(endTime.EndTime); float length = Vector2.Distance(finalPosition, finalEndPosition); @@ -94,22 +92,24 @@ namespace osu.Game.Rulesets.UI.Scrolling } } - private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); - private MultiplierControlPoint controlPointAt(double time) + private Vector2 positionAt(double time) { - if (ControlPoints.Count == 0) - return new MultiplierControlPoint(double.MinValue); + float length = 0; + for (int i = 0; i < ControlPoints.Count; i++) + { + var current = ControlPoints[i]; + var next = i < ControlPoints.Count - 1 ? ControlPoints[i + 1] : null; - if (time < ControlPoints[0].StartTime) - return ControlPoints[0]; + if (i > 0 && current.StartTime > time) + continue; - searchingPoint.StartTime = time; + // Duration of the current control point + var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; - int index = ControlPoints.BinarySearch(searchingPoint); - if (index < 0) - index = ~index - 1; + length += (float)(Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / TimeRange); + } - return ControlPoints[index]; + return length * DrawSize; } } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index 73c3848f69..418013bcc1 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -70,12 +70,10 @@ namespace osu.Game.Rulesets.UI.Scrolling // Perform some post processing of the timing changes timingChanges = timingChanges - // Collapse sections after the last hit object - .Where(s => s.StartTime <= lastObjectTime) - // Collapse sections with the same start time - .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime) - // Collapse sections with the same beat length - .GroupBy(s => s.TimingPoint.BeatLength * s.DifficultyPoint.SpeedMultiplier).Select(g => g.First()); + // Collapse sections after the last hit object + .Where(s => s.StartTime <= lastObjectTime) + // Collapse sections with the same start time + .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime); DefaultControlPoints.AddRange(timingChanges); From 7526225282f8aa912e51bb7b1a5fa23af8f07260 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jan 2018 20:56:21 +0900 Subject: [PATCH 21/49] Use DP for most of the code to avoid unnecessary computations --- .../Visual/TestCaseScrollingHitObjects.cs | 11 +- .../Scrolling/ScrollingHitObjectContainer.cs | 105 ++++++++++++------ .../UI/Scrolling/ScrollingRulesetContainer.cs | 2 +- 3 files changed, 79 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 7e332c7310..591bf4fadd 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual playfields.Add(new TestPlayfield(ScrollingDirection.Down)); playfields.Add(new TestPlayfield(ScrollingDirection.Right)); - playfields.ForEach(p => p.HitObjects.ControlPoints.Add(new MultiplierControlPoint(double.MinValue))); + playfields.ForEach(p => p.HitObjects.AddControlPoint(new MultiplierControlPoint(double.MinValue))); Add(new Container { @@ -82,12 +82,9 @@ namespace osu.Game.Tests.Visual { playfields.ForEach(p => { - p.HitObjects.ControlPoints.AddRange(new[] - { - new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } }, - new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }, - new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }, - }); + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } }); + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }); + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }); TestDrawableControlPoint createDrawablePoint(double t) => new TestDrawableControlPoint(t) { diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 8c3e1162e3..7bd5ab8f10 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -2,9 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; +using osu.Framework.Caching; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; using OpenTK; @@ -19,26 +22,86 @@ namespace osu.Game.Rulesets.UI.Scrolling MaxValue = double.MaxValue }; - public readonly SortedList ControlPoints = new SortedList(); - private readonly ScrollingDirection direction; + private Cached positionCache = new Cached(); + public ScrollingHitObjectContainer(ScrollingDirection direction) { this.direction = direction; RelativeSizeAxes = Axes.Both; + + TimeRange.ValueChanged += v => positionCache.Invalidate(); } - protected override bool UpdateChildrenLife() + public override void Add(DrawableHitObject hitObject) { + positionCache.Invalidate(); + base.Add(hitObject); + } + + public override bool Remove(DrawableHitObject hitObject) + { + var result = base.Remove(hitObject); + if (result) + positionCache.Invalidate(); + return result; + } + + private readonly SortedList controlPoints = new SortedList(); + + public void AddControlPoint(MultiplierControlPoint controlPoint) + { + controlPoints.Add(controlPoint); + positionCache.Invalidate(); + } + + public bool RemoveControlPoint(MultiplierControlPoint controlPoint) + { + var result = controlPoints.Remove(controlPoint); + if (result) + positionCache.Invalidate(); + return result; + } + + private readonly Dictionary hitObjectPositions = new Dictionary(); + + protected override void Update() + { + base.Update(); + + if (positionCache.IsValid) + return; + foreach (var obj in Objects) { - obj.LifetimeStart = obj.HitObject.StartTime - TimeRange * 2; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + TimeRange * 2; + var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime); + + obj.LifetimeStart = obj.HitObject.StartTime - TimeRange - 1000; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + TimeRange + 1000; + + if (!(obj.HitObject is IHasEndTime endTime)) + continue; + + var endPosition = positionAt(endTime.EndTime); + + float length = Vector2.Distance(startPosition, endPosition); + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = length; + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = length; + break; + } } - return base.UpdateChildrenLife(); + positionCache.Validate(); } protected override void UpdateAfterChildrenLife() @@ -52,7 +115,7 @@ namespace osu.Game.Rulesets.UI.Scrolling foreach (var obj in AliveObjects) { - var finalPosition = positionAt(obj.HitObject.StartTime); + var finalPosition = hitObjectPositions[obj]; switch (direction) { @@ -69,36 +132,16 @@ namespace osu.Game.Rulesets.UI.Scrolling obj.X = -finalPosition.X + timelinePosition.X; break; } - - if (!(obj.HitObject is IHasEndTime endTime)) - continue; - - // Todo: We may need to consider scale here - var finalEndPosition = positionAt(endTime.EndTime); - - float length = Vector2.Distance(finalPosition, finalEndPosition); - - switch (direction) - { - case ScrollingDirection.Up: - case ScrollingDirection.Down: - obj.Height = length; - break; - case ScrollingDirection.Left: - case ScrollingDirection.Right: - obj.Width = length; - break; - } } } private Vector2 positionAt(double time) { - float length = 0; - for (int i = 0; i < ControlPoints.Count; i++) + double length = 0; + for (int i = 0; i < controlPoints.Count; i++) { - var current = ControlPoints[i]; - var next = i < ControlPoints.Count - 1 ? ControlPoints[i + 1] : null; + var current = controlPoints[i]; + var next = i < controlPoints.Count - 1 ? controlPoints[i + 1] : null; if (i > 0 && current.StartTime > time) continue; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index 418013bcc1..8990710a9d 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.UI.Scrolling private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield) { - playfield.HitObjects.ControlPoints.Add(controlPoint); + playfield.HitObjects.AddControlPoint(controlPoint); playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p)); } From 98fd4f6ff2afae42c569efcb886738e193c06932 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 7 Jan 2018 11:33:59 +0900 Subject: [PATCH 22/49] Fix up precision + sizing issues --- .../Scrolling/ScrollingHitObjectContainer.cs | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 7bd5ab8f10..e0df4321a8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -10,7 +10,6 @@ using osu.Framework.Lists; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; -using OpenTK; namespace osu.Game.Rulesets.UI.Scrolling { @@ -65,7 +64,15 @@ namespace osu.Game.Rulesets.UI.Scrolling return result; } - private readonly Dictionary hitObjectPositions = new Dictionary(); + public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + { + if ((invalidation & (Invalidation.RequiredParentSizeToFit | Invalidation.DrawInfo)) > 0) + positionCache.Invalidate(); + + return base.Invalidate(invalidation, source, shallPropagate); + } + + private readonly Dictionary hitObjectPositions = new Dictionary(); protected override void Update() { @@ -84,19 +91,17 @@ namespace osu.Game.Rulesets.UI.Scrolling if (!(obj.HitObject is IHasEndTime endTime)) continue; - var endPosition = positionAt(endTime.EndTime); - - float length = Vector2.Distance(startPosition, endPosition); + var length = positionAt(endTime.EndTime) - startPosition; switch (direction) { case ScrollingDirection.Up: case ScrollingDirection.Down: - obj.Height = length; + obj.Height = (float)(length * DrawHeight); break; case ScrollingDirection.Left: case ScrollingDirection.Right: - obj.Width = length; + obj.Width = (float)(length * DrawWidth); break; } } @@ -115,27 +120,27 @@ namespace osu.Game.Rulesets.UI.Scrolling foreach (var obj in AliveObjects) { - var finalPosition = hitObjectPositions[obj]; + var finalPosition = hitObjectPositions[obj] - timelinePosition; switch (direction) { case ScrollingDirection.Up: - obj.Y = finalPosition.Y - timelinePosition.Y; + obj.Y = (float)(finalPosition * DrawHeight); break; case ScrollingDirection.Down: - obj.Y = -finalPosition.Y + timelinePosition.Y; + obj.Y = (float)(-finalPosition * DrawHeight); break; case ScrollingDirection.Left: - obj.X = finalPosition.X - timelinePosition.X; + obj.X = (float)(finalPosition * DrawWidth); break; case ScrollingDirection.Right: - obj.X = -finalPosition.X + timelinePosition.X; + obj.X = (float)(-finalPosition * DrawWidth); break; } } } - private Vector2 positionAt(double time) + private double positionAt(double time) { double length = 0; for (int i = 0; i < controlPoints.Count; i++) @@ -149,10 +154,10 @@ namespace osu.Game.Rulesets.UI.Scrolling // Duration of the current control point var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; - length += (float)(Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / TimeRange); + length += Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / TimeRange; } - return length * DrawSize; + return length; } } } From 2d345b2f80e88eebdecb1847fd0ae1203c31a2f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 7 Jan 2018 11:43:31 +0900 Subject: [PATCH 23/49] Fix mania hold note tick positioning --- .../Objects/Drawables/DrawableHoldNoteTick.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 8ed5d2b924..68f6721694 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -32,6 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; + RelativePositionAxes = Axes.Y; Y = (float)HitObject.StartTime; RelativeSizeAxes = Axes.X; From 117ab8a26d32c5277cb1c585c73fdc726d0f1d38 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 7 Jan 2018 12:47:09 +0900 Subject: [PATCH 24/49] Split out scrolling algorithm --- .../Visual/TestCaseScrollingHitObjects.cs | 6 +- osu.Game/Rulesets/UI/HitObjectContainer.cs | 19 +++ osu.Game/Rulesets/UI/Playfield.cs | 22 ++-- .../Algorithms/GlobalScrollingAlgorithm.cs | 98 +++++++++++++++ .../Algorithms/IScrollingAlgorithm.cs | 15 +++ .../GlobalScrollingHitObjectContainer.cs | 17 +++ .../Scrolling/ScrollingHitObjectContainer.cs | 115 +++++------------- .../UI/Scrolling/ScrollingPlayfield.cs | 16 ++- osu.Game/osu.Game.csproj | 4 + 9 files changed, 205 insertions(+), 107 deletions(-) create mode 100644 osu.Game/Rulesets/UI/HitObjectContainer.cs create mode 100644 osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs create mode 100644 osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs create mode 100644 osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 591bf4fadd..4f2e895e9d 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -99,19 +99,17 @@ namespace osu.Game.Tests.Visual - private class TestPlayfield : Playfield + private class TestPlayfield : ScrollingPlayfield { public readonly BindableDouble TimeRange = new BindableDouble(5000); public readonly ScrollingDirection Direction; - public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; - public TestPlayfield(ScrollingDirection direction) + : base(direction) { Direction = direction; - base.HitObjects = new ScrollingHitObjectContainer(direction); HitObjects.TimeRange.BindTo(TimeRange); } } diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs new file mode 100644 index 0000000000..e7843c86ca --- /dev/null +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.UI +{ + public class HitObjectContainer : CompositeDrawable + { + public virtual IEnumerable Objects => InternalChildren.Cast(); + public virtual IEnumerable AliveObjects => AliveInternalChildren.Cast(); + + public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); + public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); + } +} diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 61014b5550..91ea3ade2a 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -8,8 +8,6 @@ using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using osu.Game.Rulesets.Judgements; using osu.Framework.Allocation; -using System.Collections.Generic; -using System.Linq; namespace osu.Game.Rulesets.UI { @@ -18,7 +16,7 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - public HitObjectContainer HitObjects { get; protected set; } + public readonly HitObjectContainer HitObjects; public Container ScaledContent; @@ -52,10 +50,8 @@ namespace osu.Game.Rulesets.UI } }); - HitObjects = new HitObjectContainer - { - RelativeSizeAxes = Axes.Both, - }; + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] @@ -94,14 +90,10 @@ namespace osu.Game.Rulesets.UI /// The that occurred. public virtual void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { } - public class HitObjectContainer : CompositeDrawable - { - public virtual IEnumerable Objects => InternalChildren.Cast(); - public virtual IEnumerable AliveObjects => AliveInternalChildren.Cast(); - - public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); - public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); - } + /// + /// Creates the container that will be used to contain the s. + /// + protected virtual HitObjectContainer CreateHitObjectContainer() => new HitObjectContainer(); private class ScaledContainer : Container { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs new file mode 100644 index 0000000000..0a69d00377 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -0,0 +1,98 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Timing; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +{ + public class GlobalScrollingAlgorithm : IScrollingAlgorithm + { + private readonly Dictionary hitObjectPositions = new Dictionary(); + + private readonly IReadOnlyList controlPoints; + + public GlobalScrollingAlgorithm(IReadOnlyList controlPoints) + { + this.controlPoints = controlPoints; + } + + public void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime, timeRange); + + obj.LifetimeStart = obj.HitObject.StartTime - timeRange - 1000; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange + 1000; + + if (!(obj.HitObject is IHasEndTime endTime)) + continue; + + var diff = positionAt(endTime.EndTime, timeRange) - startPosition; + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = (float)(diff * length.Y); + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = (float)(diff * length.X); + break; + } + } + } + + public void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length) + { + var timelinePosition = positionAt(currentTime, timeRange); + + foreach (var obj in hitObjects) + { + var finalPosition = hitObjectPositions[obj] - timelinePosition; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = (float)(finalPosition * length.Y); + break; + case ScrollingDirection.Down: + obj.Y = (float)(-finalPosition * length.Y); + break; + case ScrollingDirection.Left: + obj.X = (float)(finalPosition * length.X); + break; + case ScrollingDirection.Right: + obj.X = (float)(-finalPosition * length.X); + break; + } + } + } + + private double positionAt(double time, double timeRange) + { + double length = 0; + for (int i = 0; i < controlPoints.Count; i++) + { + var current = controlPoints[i]; + var next = i < controlPoints.Count - 1 ? controlPoints[i + 1] : null; + + if (i > 0 && current.StartTime > time) + continue; + + // Duration of the current control point + var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; + + length += Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / timeRange; + } + + return length; + } + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs new file mode 100644 index 0000000000..2621ae7d6f --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +{ + public interface IScrollingAlgorithm + { + void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length); + void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length); + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs new file mode 100644 index 0000000000..23dff01940 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Game.Rulesets.UI.Scrolling.Algorithms; + +namespace osu.Game.Rulesets.UI.Scrolling +{ + public class GlobalScrollingHitObjectContainer : ScrollingHitObjectContainer + { + public GlobalScrollingHitObjectContainer(ScrollingDirection direction) + : base(direction) + { + } + + protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new GlobalScrollingAlgorithm(ControlPoints); + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e0df4321a8..e1d8fe8d59 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,19 +1,17 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.Collections.Generic; using osu.Framework.Caching; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; +using osu.Game.Rulesets.UI.Scrolling.Algorithms; namespace osu.Game.Rulesets.UI.Scrolling { - public class ScrollingHitObjectContainer : Playfield.HitObjectContainer + public abstract class ScrollingHitObjectContainer : HitObjectContainer { public readonly BindableDouble TimeRange = new BindableDouble { @@ -21,22 +19,32 @@ namespace osu.Game.Rulesets.UI.Scrolling MaxValue = double.MaxValue }; + protected readonly SortedList ControlPoints = new SortedList(); + private readonly ScrollingDirection direction; - private Cached positionCache = new Cached(); + private Cached initialStateCache = new Cached(); - public ScrollingHitObjectContainer(ScrollingDirection direction) + protected ScrollingHitObjectContainer(ScrollingDirection direction) { this.direction = direction; RelativeSizeAxes = Axes.Both; - TimeRange.ValueChanged += v => positionCache.Invalidate(); + TimeRange.ValueChanged += v => initialStateCache.Invalidate(); + } + + private IScrollingAlgorithm scrollingAlgorithm; + protected override void LoadComplete() + { + base.LoadComplete(); + + scrollingAlgorithm = CreateScrollingAlgorithm(); } public override void Add(DrawableHitObject hitObject) { - positionCache.Invalidate(); + initialStateCache.Invalidate(); base.Add(hitObject); } @@ -44,69 +52,42 @@ namespace osu.Game.Rulesets.UI.Scrolling { var result = base.Remove(hitObject); if (result) - positionCache.Invalidate(); + initialStateCache.Invalidate(); return result; } - private readonly SortedList controlPoints = new SortedList(); - public void AddControlPoint(MultiplierControlPoint controlPoint) { - controlPoints.Add(controlPoint); - positionCache.Invalidate(); + ControlPoints.Add(controlPoint); + initialStateCache.Invalidate(); } public bool RemoveControlPoint(MultiplierControlPoint controlPoint) { - var result = controlPoints.Remove(controlPoint); + var result = ControlPoints.Remove(controlPoint); if (result) - positionCache.Invalidate(); + initialStateCache.Invalidate(); return result; } public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { if ((invalidation & (Invalidation.RequiredParentSizeToFit | Invalidation.DrawInfo)) > 0) - positionCache.Invalidate(); + initialStateCache.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); } - private readonly Dictionary hitObjectPositions = new Dictionary(); - protected override void Update() { base.Update(); - if (positionCache.IsValid) + if (initialStateCache.IsValid) return; - foreach (var obj in Objects) - { - var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime); + scrollingAlgorithm.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); - obj.LifetimeStart = obj.HitObject.StartTime - TimeRange - 1000; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + TimeRange + 1000; - - if (!(obj.HitObject is IHasEndTime endTime)) - continue; - - var length = positionAt(endTime.EndTime) - startPosition; - - switch (direction) - { - case ScrollingDirection.Up: - case ScrollingDirection.Down: - obj.Height = (float)(length * DrawHeight); - break; - case ScrollingDirection.Left: - case ScrollingDirection.Right: - obj.Width = (float)(length * DrawWidth); - break; - } - } - - positionCache.Validate(); + initialStateCache.Validate(); } protected override void UpdateAfterChildrenLife() @@ -116,48 +97,12 @@ namespace osu.Game.Rulesets.UI.Scrolling // We need to calculate this as soon as possible after lifetimes so that hitobjects // get the final say in their positions - var timelinePosition = positionAt(Time.Current); - - foreach (var obj in AliveObjects) - { - var finalPosition = hitObjectPositions[obj] - timelinePosition; - - switch (direction) - { - case ScrollingDirection.Up: - obj.Y = (float)(finalPosition * DrawHeight); - break; - case ScrollingDirection.Down: - obj.Y = (float)(-finalPosition * DrawHeight); - break; - case ScrollingDirection.Left: - obj.X = (float)(finalPosition * DrawWidth); - break; - case ScrollingDirection.Right: - obj.X = (float)(-finalPosition * DrawWidth); - break; - } - } + scrollingAlgorithm.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); } - private double positionAt(double time) - { - double length = 0; - for (int i = 0; i < controlPoints.Count; i++) - { - var current = controlPoints[i]; - var next = i < controlPoints.Count - 1 ? controlPoints[i + 1] : null; - - if (i > 0 && current.StartTime > time) - continue; - - // Duration of the current control point - var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; - - length += Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / TimeRange; - } - - return length; - } + /// + /// Creates the algorithm that will process the positions of the s. + /// + protected abstract IScrollingAlgorithm CreateScrollingAlgorithm(); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 899048531f..f560d8eaa6 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// /// A type of specialized towards scrolling s. /// - public class ScrollingPlayfield : Playfield + public abstract class ScrollingPlayfield : Playfield { /// /// The default span of time visible by the length of the scrolling axes. @@ -49,7 +49,9 @@ namespace osu.Game.Rulesets.UI.Scrolling /// /// The container that contains the s and s. /// - public new readonly ScrollingHitObjectContainer HitObjects; + public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + + private readonly ScrollingDirection direction; /// /// Creates a new . @@ -59,7 +61,7 @@ namespace osu.Game.Rulesets.UI.Scrolling protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null) : base(customWidth) { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(direction) { RelativeSizeAxes = Axes.Both }; + this.direction = direction; HitObjects.TimeRange.BindTo(VisibleTimeRange); } @@ -105,6 +107,14 @@ namespace osu.Game.Rulesets.UI.Scrolling this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); } + protected sealed override HitObjectContainer CreateHitObjectContainer() => CreateScrollingHitObjectContainer(); + + /// + /// Creates the that will handle the scrolling of the s. + /// + /// + protected virtual ScrollingHitObjectContainer CreateScrollingHitObjectContainer() => new GlobalScrollingHitObjectContainer(direction); + private class TransformVisibleTimeRange : Transform { private double valueAt(double time) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6d8ce3c1b6..a33cf73934 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -315,6 +315,10 @@ + + + + From 4ab3b0d76be328d8141305930eba63d4f3384bb2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 7 Jan 2018 13:24:09 +0900 Subject: [PATCH 25/49] Implement local scrolling hit object container --- .../Algorithms/LocalScrollingAlgorithm.cs | 79 +++++++++++++++++++ .../LocalScrollingHitObjectContainer.cs | 17 ++++ osu.Game/osu.Game.csproj | 2 + 3 files changed, 98 insertions(+) create mode 100644 osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs create mode 100644 osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs new file mode 100644 index 0000000000..ddd06a3725 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Lists; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Timing; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +{ + public class LocalScrollingAlgorithm : IScrollingAlgorithm + { + private readonly Dictionary hitObjectPositions = new Dictionary(); + + private readonly SortedList controlPoints; + + public LocalScrollingAlgorithm(SortedList controlPoints) + { + this.controlPoints = controlPoints; + } + + public void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var controlPoint = controlPointAt(obj.HitObject.StartTime); + + obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; + obj.LifetimeEnd = ((obj as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; + } + } + + public void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var controlPoint = controlPointAt(obj.HitObject.StartTime); + + var position = (obj.HitObject.StartTime - currentTime) * controlPoint.Multiplier / timeRange; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = (float)(position * length.Y); + break; + case ScrollingDirection.Down: + obj.Y = (float)(-position * length.Y); + break; + case ScrollingDirection.Left: + obj.X = (float)(position * length.X); + break; + case ScrollingDirection.Right: + obj.X = (float)(-position * length.X); + break; + } + } + } + + private readonly MultiplierControlPoint searchPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) + { + if (controlPoints.Count == 0) + return new MultiplierControlPoint(double.NegativeInfinity); + + if (time < controlPoints[0].StartTime) + return controlPoints[0]; + + searchPoint.StartTime = time; + int index = controlPoints.BinarySearch(searchPoint); + + if (index < 0) + index = ~index - 1; + + return controlPoints[index]; + } + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs new file mode 100644 index 0000000000..ceef688cbc --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Game.Rulesets.UI.Scrolling.Algorithms; + +namespace osu.Game.Rulesets.UI.Scrolling +{ + public class LocalScrollingHitObjectContainer : ScrollingHitObjectContainer + { + public LocalScrollingHitObjectContainer(ScrollingDirection direction) + : base(direction) + { + } + + protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new LocalScrollingAlgorithm(ControlPoints); + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a33cf73934..327b87d5de 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -318,7 +318,9 @@ + + From c4d1922c8bbf653a563f8a0854bfff3f7f1e5c78 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 8 Jan 2018 11:34:37 +0900 Subject: [PATCH 26/49] Add scrolling algorithm to global settings --- osu.Game/Configuration/OsuConfigManager.cs | 5 +++- .../Configuration/ScrollingAlgorithmType.cs | 15 +++++++++++ .../Sections/Gameplay/ScrollingSettings.cs | 26 ++++++++++++++++++ .../Settings/Sections/GameplaySection.cs | 3 ++- osu.Game/Rulesets/UI/Playfield.cs | 8 +++--- .../Algorithms/LocalScrollingAlgorithm.cs | 2 +- .../GlobalScrollingHitObjectContainer.cs | 17 ------------ .../LocalScrollingHitObjectContainer.cs | 17 ------------ .../Scrolling/ScrollingHitObjectContainer.cs | 27 +++++++++++-------- .../UI/Scrolling/ScrollingPlayfield.cs | 14 +++++----- osu.Game/osu.Game.csproj | 4 +-- 11 files changed, 77 insertions(+), 61 deletions(-) create mode 100644 osu.Game/Configuration/ScrollingAlgorithmType.cs create mode 100644 osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs delete mode 100644 osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs delete mode 100644 osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index f4c7bdb586..4ff4105b77 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -71,6 +71,8 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); + Set(OsuSetting.ScrollingAlgorithm, ScrollingAlgorithmType.Global); + // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -114,6 +116,7 @@ namespace osu.Game.Configuration ShowFpsDisplay, ChatDisplayHeight, Version, - ShowConvertedBeatmaps + ShowConvertedBeatmaps, + ScrollingAlgorithm } } diff --git a/osu.Game/Configuration/ScrollingAlgorithmType.cs b/osu.Game/Configuration/ScrollingAlgorithmType.cs new file mode 100644 index 0000000000..b4a2b8a4a3 --- /dev/null +++ b/osu.Game/Configuration/ScrollingAlgorithmType.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.ComponentModel; + +namespace osu.Game.Configuration +{ + public enum ScrollingAlgorithmType + { + [Description("Global")] + Global, + [Description("Local")] + Local + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs new file mode 100644 index 0000000000..b2a2a25da7 --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Configuration; + +namespace osu.Game.Overlays.Settings.Sections.Gameplay +{ + public class ScrollingSettings : SettingsSubsection + { + protected override string Header => "Scrolling"; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + Children = new[] + { + new SettingsEnumDropdown + { + LabelText = "Scrolling algorithm", + Bindable = config.GetBindable(OsuSetting.ScrollingAlgorithm), + } + }; + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index 035a3c7a13..8b05bfe8de 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -21,6 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections { new GeneralSettings(), new SongSelectSettings(), + new ScrollingSettings() }; } @@ -35,4 +36,4 @@ namespace osu.Game.Overlays.Settings.Sections } } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 91ea3ade2a..0f8a650718 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - public readonly HitObjectContainer HitObjects; + public HitObjectContainer HitObjects { get; private set; } public Container ScaledContent; @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.UI } } }); - - HitObjects = CreateHitObjectContainer(); - HitObjects.RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load() { + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; + Add(HitObjects); } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index ddd06a3725..be8612ca96 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms var controlPoint = controlPointAt(obj.HitObject.StartTime); obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; - obj.LifetimeEnd = ((obj as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; } } diff --git a/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs deleted file mode 100644 index 23dff01940..0000000000 --- a/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.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-framework/master/LICENCE - -using osu.Game.Rulesets.UI.Scrolling.Algorithms; - -namespace osu.Game.Rulesets.UI.Scrolling -{ - public class GlobalScrollingHitObjectContainer : ScrollingHitObjectContainer - { - public GlobalScrollingHitObjectContainer(ScrollingDirection direction) - : base(direction) - { - } - - protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new GlobalScrollingAlgorithm(ControlPoints); - } -} diff --git a/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs deleted file mode 100644 index ceef688cbc..0000000000 --- a/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.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-framework/master/LICENCE - -using osu.Game.Rulesets.UI.Scrolling.Algorithms; - -namespace osu.Game.Rulesets.UI.Scrolling -{ - public class LocalScrollingHitObjectContainer : ScrollingHitObjectContainer - { - public LocalScrollingHitObjectContainer(ScrollingDirection direction) - : base(direction) - { - } - - protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new LocalScrollingAlgorithm(ControlPoints); - } -} diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e1d8fe8d59..67f2e8aee0 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,17 +1,19 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; +using osu.Game.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI.Scrolling.Algorithms; namespace osu.Game.Rulesets.UI.Scrolling { - public abstract class ScrollingHitObjectContainer : HitObjectContainer + public class ScrollingHitObjectContainer : HitObjectContainer { public readonly BindableDouble TimeRange = new BindableDouble { @@ -25,7 +27,7 @@ namespace osu.Game.Rulesets.UI.Scrolling private Cached initialStateCache = new Cached(); - protected ScrollingHitObjectContainer(ScrollingDirection direction) + public ScrollingHitObjectContainer(ScrollingDirection direction) { this.direction = direction; @@ -35,11 +37,19 @@ namespace osu.Game.Rulesets.UI.Scrolling } private IScrollingAlgorithm scrollingAlgorithm; - protected override void LoadComplete() - { - base.LoadComplete(); - scrollingAlgorithm = CreateScrollingAlgorithm(); + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + switch (config.Get(OsuSetting.ScrollingAlgorithm)) + { + case ScrollingAlgorithmType.Global: + scrollingAlgorithm = new GlobalScrollingAlgorithm(ControlPoints); + break; + case ScrollingAlgorithmType.Local: + scrollingAlgorithm = new LocalScrollingAlgorithm(ControlPoints); + break; + } } public override void Add(DrawableHitObject hitObject) @@ -99,10 +109,5 @@ namespace osu.Game.Rulesets.UI.Scrolling scrollingAlgorithm.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); } - - /// - /// Creates the algorithm that will process the positions of the s. - /// - protected abstract IScrollingAlgorithm CreateScrollingAlgorithm(); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index f560d8eaa6..8669339294 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; @@ -62,6 +63,11 @@ namespace osu.Game.Rulesets.UI.Scrolling : base(customWidth) { this.direction = direction; + } + + [BackgroundDependencyLoader] + private void load() + { HitObjects.TimeRange.BindTo(VisibleTimeRange); } @@ -107,13 +113,7 @@ namespace osu.Game.Rulesets.UI.Scrolling this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); } - protected sealed override HitObjectContainer CreateHitObjectContainer() => CreateScrollingHitObjectContainer(); - - /// - /// Creates the that will handle the scrolling of the s. - /// - /// - protected virtual ScrollingHitObjectContainer CreateScrollingHitObjectContainer() => new GlobalScrollingHitObjectContainer(direction); + protected sealed override HitObjectContainer CreateHitObjectContainer() => new ScrollingHitObjectContainer(direction); private class TransformVisibleTimeRange : Transform { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 327b87d5de..45183de092 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -265,6 +265,7 @@ + @@ -310,6 +311,7 @@ + @@ -319,8 +321,6 @@ - - From 1c412e233ae48e65bf17f1a0fce1b8181dd93db9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 18:04:12 +0900 Subject: [PATCH 27/49] Update submodules --- osu-framework | 2 +- osu-resources | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu-framework b/osu-framework index 067fdb8f5b..80bcb82ef8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 067fdb8f5b0594be1cd30e6bbd43f2ea749904ec +Subproject commit 80bcb82ef8d2e1af1ce077f4a037b6d279ad9e74 diff --git a/osu-resources b/osu-resources index e01f71160f..7724abdf1d 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit e01f71160fb9b3167efcd177c7d7dba9e5d36604 +Subproject commit 7724abdf1d7c9705ba2e3989a9c604e17ccdc871 From f71d086a41e25704ad801fc05c4e04bd6e90a114 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 18:05:19 +0900 Subject: [PATCH 28/49] Fix post-merge issues --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 4 +--- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index dd99229cca..7fdabd46c2 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -2,8 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Rulesets.UI; -using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; @@ -24,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; public CatchPlayfield(BeatmapDifficulty difficulty) - : base(Axes.Y, BASE_WIDTH) + : base(ScrollingDirection.Down, BASE_WIDTH) { Container explodingFruitContainer; diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index eab39ff002..39f8333413 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -64,7 +64,6 @@ - @@ -120,7 +119,7 @@ - + From 9036ea92ebc3146124348af74b3c490e6b6d51ac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 18:29:46 +0900 Subject: [PATCH 29/49] Run child updates for nested hitobjects when parent hitobjects are masked --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 34c34e1d33..e461cb96c5 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -36,6 +36,7 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveCompletedTransforms => false; public override bool RemoveWhenNotAlive => false; + protected override bool RequiresChildrenUpdate => true; protected DrawableHitObject(HitObject hitObject) { From 6255aaab687335b73e941fedb89ea72bbe6725f7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 19:17:43 +0900 Subject: [PATCH 30/49] Per-hitobject lifetime management --- .../Objects/Drawables/DrawableHoldNote.cs | 4 ++++ .../Objects/Drawables/DrawableHoldNoteTick.cs | 4 ---- .../Objects/Drawables/DrawableManiaHitObject.cs | 4 ++++ osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 7 +++++++ .../Objects/Drawables/DrawableDrumRoll.cs | 7 +++++++ .../Objects/Drawables/DrawableDrumRollTick.cs | 2 +- .../UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs | 1 - .../UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs | 3 --- 8 files changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 8e3159d531..1ed7cc594a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -251,6 +251,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } + protected override void UpdateState(ArmedState state) + { + } + public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down public override bool OnReleased(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index cfe82a2b59..0685c7bb2d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -38,10 +38,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables RelativeSizeAxes = Axes.X; Size = new Vector2(1); - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - Children = new[] { glowContainer = new CircularContainer diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 5b98d84e68..0a1624b464 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 osu.Framework.Graphics; using OpenTK.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -19,6 +20,9 @@ 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) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 1696de2880..101db0205c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -78,6 +78,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void UpdateState(ArmedState state) { + switch (state) + { + case ArmedState.Hit: + case ArmedState.Miss: + this.FadeOut(100).Expire(); + break; + } } public virtual bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 564e496af5..0f16f85b63 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -100,6 +100,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void UpdateState(ArmedState state) { + switch (state) + { + case ArmedState.Hit: + case ArmedState.Miss: + this.FadeOut(100).Expire(); + break; + } } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 96485fbc9e..3408a830ed 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { case ArmedState.Hit: - Content.ScaleTo(0, 100, Easing.OutQuint); + Content.ScaleTo(0, 100, Easing.OutQuint).Expire(); break; } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs index 0a69d00377..a8e41a951b 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -28,7 +28,6 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime, timeRange); obj.LifetimeStart = obj.HitObject.StartTime - timeRange - 1000; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange + 1000; if (!(obj.HitObject is IHasEndTime endTime)) continue; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index be8612ca96..c956766474 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using osu.Framework.Lists; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; using OpenTK; @@ -26,9 +25,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms foreach (var obj in hitObjects) { var controlPoint = controlPointAt(obj.HitObject.StartTime); - obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; } } From 6a5a3b01b265878c5fccca36cc80307769c5cfe5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 12:39:06 +0900 Subject: [PATCH 31/49] Fix license headers --- osu.Game/Configuration/ScrollingAlgorithmType.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs | 2 +- osu.Game/Rulesets/UI/HitObjectContainer.cs | 2 +- .../UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs | 2 +- .../Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs | 2 +- .../Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs | 2 +- osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs | 2 +- osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Configuration/ScrollingAlgorithmType.cs b/osu.Game/Configuration/ScrollingAlgorithmType.cs index b4a2b8a4a3..8b9d292634 100644 --- a/osu.Game/Configuration/ScrollingAlgorithmType.cs +++ b/osu.Game/Configuration/ScrollingAlgorithmType.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs index b2a2a25da7..3243f4c23a 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; using osu.Game.Configuration; diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index e7843c86ca..c26a6cdff0 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs index a8e41a951b..55a0a7c2f3 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs index 2621ae7d6f..f9863bd299 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index c956766474..b2d4289a9a 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; using osu.Framework.Lists; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs index d89795f4d3..372bdb1030 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.UI.Scrolling { diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 67f2e8aee0..dfa6a40db4 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; From 3a869edf36312657761727a26917a3bafb5e7029 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 12:44:17 +0900 Subject: [PATCH 32/49] Add a flag to disable user scroll speed adjustments --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 1 + osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index b8e4ede120..3c5093d82f 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -37,6 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// private const float left_area_size = 240; + protected override bool UserScrollSpeedAdjustment => false; private readonly Container hitExplosionContainer; private readonly Container kiaiExplosionContainer; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 5be1c8bed7..11185015b8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -47,6 +47,11 @@ namespace osu.Game.Rulesets.UI.Scrolling MaxValue = time_span_max }; + /// + /// Whether the player can change . + /// + protected virtual bool UserScrollSpeedAdjustment => true; + /// /// The container that contains the s and s. /// @@ -92,6 +97,9 @@ namespace osu.Game.Rulesets.UI.Scrolling protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { + if (!UserScrollSpeedAdjustment) + return false; + if (state.Keyboard.ControlPressed) { switch (args.Key) From a6d8b28221910993005d6adbbcc5b0447b5a1511 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 13:40:46 +0900 Subject: [PATCH 33/49] Add OSD + config value for scroll speed --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 5 ++++- osu.Game/Configuration/OsuConfigManager.cs | 4 +++- osu.Game/Overlays/OnScreenDisplay.cs | 6 +++++- osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 7 +++++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 919518dbe8..532be2759f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -15,6 +15,7 @@ using osu.Framework.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Framework.Graphics.Shapes; +using osu.Game.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.UI.Scrolling; @@ -161,8 +162,10 @@ namespace osu.Game.Rulesets.Mania.UI } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, OsuConfigManager config) { + config.BindWith(OsuSetting.UserScrollSpeed, VisibleTimeRange); + normalColumnColours = new List { colours.RedDark, diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 13213a54a1..26879782fc 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -73,6 +73,7 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); Set(OsuSetting.ScrollingAlgorithm, ScrollingAlgorithmType.Global); + Set(OsuSetting.UserScrollSpeed, 1500.0, 50.0, 10000.0); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -119,6 +120,7 @@ namespace osu.Game.Configuration ChatDisplayHeight, Version, ShowConvertedBeatmaps, - ScrollingAlgorithm + ScrollingAlgorithm, + UserScrollSpeed } } diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 6a1bd8e182..4f3f03c749 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Configuration; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays @@ -115,7 +116,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig) + private void load(FrameworkConfigManager frameworkConfig, OsuConfigManager osuConfig) { trackSetting(frameworkConfig.GetBindable(FrameworkSetting.FrameSync), v => display(v, "Frame Limiter", v.GetDescription(), "Ctrl+F7")); trackSetting(frameworkConfig.GetBindable(FrameworkSetting.AudioDevice), v => display(v, "Audio Device", string.IsNullOrEmpty(v) ? "Default" : v, v)); @@ -135,6 +136,9 @@ namespace osu.Game.Overlays }); trackSetting(frameworkConfig.GetBindable(FrameworkSetting.WindowMode), v => display(v, "Screen Mode", v.ToString(), "Alt+Enter")); + + // Todo: This should be part of the ruleset-specific OSD + trackSetting(osuConfig.GetBindable(OsuSetting.UserScrollSpeed), v => display(v, "Scroll Speed", $"{v:N0}ms", "Ctrl+(+/-) to change")); } private readonly List references = new List(); diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 11185015b8..fa04b7f137 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -102,13 +103,15 @@ namespace osu.Game.Rulesets.UI.Scrolling if (state.Keyboard.ControlPressed) { + var lastValue = Transforms.OfType().LastOrDefault()?.EndValue ?? VisibleTimeRange.Value; + switch (args.Key) { case Key.Minus: - transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); + transformVisibleTimeRangeTo(lastValue + time_span_step, 200, Easing.OutQuint); break; case Key.Plus: - transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); + transformVisibleTimeRangeTo(lastValue - time_span_step, 200, Easing.OutQuint); break; } } From 9d00e5bb7dfc103003f11a73bda6d435b345686c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 15:08:30 +0900 Subject: [PATCH 34/49] Make ScrollingHitObjectContainer handle nested hitobjects --- .../Objects/Drawable/DrawableJuiceStream.cs | 2 +- .../Objects/Drawables/DrawableHoldNote.cs | 24 +---------- .../Objects/Drawables/DrawableHoldNoteTick.cs | 3 -- .../Objects/Drawables/DrawableDrumRoll.cs | 7 +--- .../Objects/Drawables/DrawableDrumRollTick.cs | 12 ------ .../Objects/Drawables/DrawableHitObject.cs | 41 +++++++++++++------ .../Algorithms/GlobalScrollingAlgorithm.cs | 34 ++++++++------- .../Algorithms/LocalScrollingAlgorithm.cs | 6 +++ 8 files changed, 59 insertions(+), 70 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 031b70924d..dcb7fdb823 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable } } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject h) { ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; dropletContainer.Add(h); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 1ed7cc594a..6748bc22e6 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -7,7 +7,6 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using OpenTK.Graphics; -using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Extensions.IEnumerableExtensions; @@ -59,12 +58,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, }, - tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), - RelativeChildSize = new Vector2(1, (float)HitObject.Duration) - }, + tickContainer = new Container { RelativeSizeAxes = Axes.Both }, head = new DrawableHeadNote(this, action) { Anchor = Anchor.TopCentre, @@ -72,7 +66,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }, tail = new DrawableTailNote(this, action) { - Anchor = Anchor.BottomCentre, + Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre } }); @@ -174,13 +168,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { this.holdNote = holdNote; - RelativePositionAxes = Axes.None; - Y = 0; - - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - GlowPiece.Alpha = 0; } @@ -213,13 +200,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { this.holdNote = holdNote; - RelativePositionAxes = Axes.None; - Y = 0; - - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - GlowPiece.Alpha = 0; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 0685c7bb2d..f9c0b96d37 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -32,9 +32,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; - RelativePositionAxes = Axes.Y; - Y = (float)HitObject.StartTime; - RelativeSizeAxes = Axes.X; Size = new Vector2(1); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 0f16f85b63..2fa6c8ed95 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -37,12 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables RelativeSizeAxes = Axes.Y; Container tickContainer; - MainPiece.Add(tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2((float)HitObject.StartTime, 0), - RelativeChildSize = new Vector2((float)HitObject.Duration, 1) - }); + MainPiece.Add(tickContainer = new Container { RelativeSizeAxes = Axes.Both }); foreach (var tick in drumRoll.NestedHitObjects.OfType()) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 3408a830ed..bc5abce245 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -15,23 +15,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public DrawableDrumRollTick(DrumRollTick tick) : base(tick) { - // Because ticks aren't added by the ScrollingPlayfield, we need to set the following properties ourselves - RelativePositionAxes = Axes.X; - X = (float)tick.StartTime; - FillMode = FillMode.Fit; } public override bool DisplayJudgement => false; - protected override void LoadComplete() - { - base.LoadComplete(); - - // We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize - Width *= Parent.RelativeChildSize.X; - } - protected override TaikoPiece CreateMainPiece() => new TickPiece { Filled = HitObject.FirstTick diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e461cb96c5..13329a1470 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -38,11 +38,30 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveWhenNotAlive => false; protected override bool RequiresChildrenUpdate => true; + public virtual bool AllJudged => false; + protected DrawableHitObject(HitObject hitObject) { HitObject = hitObject; } + /// + /// Processes this , checking if any judgements have occurred. + /// + /// Whether the user triggered this process. + /// Whether a judgement has occurred from this or any nested s. + protected internal virtual bool UpdateJudgement(bool userTriggered) => false; + + private List nestedHitObjects; + public IReadOnlyList NestedHitObjects => nestedHitObjects; + + protected virtual void AddNested(DrawableHitObject h) + { + if (nestedHitObjects == null) + nestedHitObjects = new List(); + nestedHitObjects.Add(h); + } + /// /// The screen-space point that causes this to be selected in the Editor. /// @@ -145,7 +164,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether this and all of its nested s have been judged. /// - public bool AllJudged => (!ProvidesJudgement || judgementFinalized) && (NestedHitObjects?.All(h => h.AllJudged) ?? true); + public sealed override bool AllJudged => (!ProvidesJudgement || judgementFinalized) && (NestedHitObjects?.All(h => h.AllJudged) ?? true); /// /// Notifies that a new judgement has occurred for this . @@ -181,7 +200,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether the user triggered this process. /// Whether a judgement has occurred from this or any nested s. - protected bool UpdateJudgement(bool userTriggered) + protected internal sealed override bool UpdateJudgement(bool userTriggered) { judgementOccurred = false; @@ -238,18 +257,16 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateJudgement(false); } - private List> nestedHitObjects; - protected IEnumerable> NestedHitObjects => nestedHitObjects; - - protected virtual void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject h) { - if (nestedHitObjects == null) - nestedHitObjects = new List>(); + base.AddNested(h); - h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); - h.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); - h.ApplyCustomUpdateState += (d, s) => ApplyCustomUpdateState?.Invoke(d, s); - nestedHitObjects.Add(h); + if (!(h is DrawableHitObject hWithJudgement)) + return; + + hWithJudgement.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); + hWithJudgement.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); + hWithJudgement.ApplyCustomUpdateState += (d, s) => ApplyCustomUpdateState?.Invoke(d, s); } /// diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs index 55a0a7c2f3..c1347ad122 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -29,22 +29,25 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.LifetimeStart = obj.HitObject.StartTime - timeRange - 1000; - if (!(obj.HitObject is IHasEndTime endTime)) - continue; - - var diff = positionAt(endTime.EndTime, timeRange) - startPosition; - - switch (direction) + if (obj.HitObject is IHasEndTime endTime) { - case ScrollingDirection.Up: - case ScrollingDirection.Down: - obj.Height = (float)(diff * length.Y); - break; - case ScrollingDirection.Left: - case ScrollingDirection.Right: - obj.Width = (float)(diff * length.X); - break; + var diff = positionAt(endTime.EndTime, timeRange) - startPosition; + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = (float)(diff * length.Y); + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = (float)(diff * length.X); + break; + } } + + if (obj.NestedHitObjects != null) + ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); } } @@ -71,6 +74,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.X = (float)(-finalPosition * length.X); break; } + + if (obj.NestedHitObjects != null) + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index b2d4289a9a..ecb7aaff95 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -26,6 +26,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { var controlPoint = controlPointAt(obj.HitObject.StartTime); obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; + + if (obj.NestedHitObjects != null) + ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); } } @@ -52,6 +55,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.X = (float)(-position * length.X); break; } + + if (obj.NestedHitObjects != null) + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); } } From 428f8b6670b2a7b55861de4dc63d53389514a320 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 15:08:46 +0900 Subject: [PATCH 35/49] Fix up license header --- 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 4f2e895e9d..b8e0934928 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; From 9ae67b519b6bb8f81dab49efa465c6004e5a5981 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 15:25:15 +0900 Subject: [PATCH 36/49] Optimise nested hitobject position computations --- .../UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs | 6 +++--- .../UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs index c1347ad122..ed156ecfd5 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -47,7 +47,10 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms } if (obj.NestedHitObjects != null) + { ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); + } } } @@ -74,9 +77,6 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.X = (float)(-finalPosition * length.X); break; } - - if (obj.NestedHitObjects != null) - ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index ecb7aaff95..96a85c5f9f 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -28,7 +28,10 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; if (obj.NestedHitObjects != null) + { ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); + } } } @@ -55,9 +58,6 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.X = (float)(-position * length.X); break; } - - if (obj.NestedHitObjects != null) - ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); } } From d998936e9eaa57a276c3d371496c6dc3e95f0338 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 15:50:44 +0900 Subject: [PATCH 37/49] Fix testcase errors --- osu.Game/Rulesets/UI/Playfield.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 25a7adb5a7..a1d07d9a03 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.UI } } }); + + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load() { - HitObjects = CreateHitObjectContainer(); - HitObjects.RelativeSizeAxes = Axes.Both; - Add(HitObjects); } From ab762045d608655c6495298544ed62c5545f6b36 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 16:51:46 +0900 Subject: [PATCH 38/49] Move back to using load(), fix testcase --- .../Visual/TestCaseEditorSelectionLayer.cs | 39 +++--- .../Visual/TestCaseScrollingHitObjects.cs | 114 ++++++++++-------- osu.Game/Rulesets/UI/Playfield.cs | 6 +- 3 files changed, 90 insertions(+), 69 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index b318d4afd3..f236182939 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using osu.Framework.Allocation; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,26 +19,10 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(SelectionLayer) }; - public TestCaseEditorSelectionLayer() + [BackgroundDependencyLoader] + private void load() { - var playfield = new OsuEditPlayfield - { - new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f }), - new DrawableHitCircle(new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f }), - new DrawableSlider(new Slider - { - ControlPoints = new List - { - new Vector2(128, 256), - new Vector2(344, 256), - }, - Distance = 400, - Position = new Vector2(128, 256), - Velocity = 1, - TickDistance = 100, - Scale = 0.5f - }) - }; + var playfield = new OsuEditPlayfield(); Children = new Drawable[] { @@ -49,6 +34,22 @@ namespace osu.Game.Tests.Visual }, new SelectionLayer(playfield) }; + + playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f })); + playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f })); + playfield.Add(new DrawableSlider(new Slider + { + ControlPoints = new List + { + new Vector2(128, 256), + new Vector2(344, 256), + }, + Distance = 400, + Position = new Vector2(128, 256), + Velocity = 1, + TickDistance = 100, + Scale = 0.5f + })); } } } diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index b8e0934928..21d967c3e3 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +13,6 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; -using OpenTK.Graphics; namespace osu.Game.Tests.Visual { @@ -21,39 +20,29 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; - private readonly List playfields = new List(); + private readonly TestPlayfield[] playfields = new TestPlayfield[4]; public TestCaseScrollingHitObjects() { - playfields.Add(new TestPlayfield(ScrollingDirection.Down)); - playfields.Add(new TestPlayfield(ScrollingDirection.Right)); - - playfields.ForEach(p => p.HitObjects.AddControlPoint(new MultiplierControlPoint(double.MinValue))); - - Add(new Container + Add(new GridContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.85f), - Masking = true, - BorderColour = Color4.White, - BorderThickness = 2, - MaskingSmoothness = 1, - Children = new Drawable[] + Content = new[] { - new Box + new Drawable[] { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Alpha = 0.35f, + playfields[0] = new TestPlayfield(ScrollingDirection.Up), + playfields[1] = new TestPlayfield(ScrollingDirection.Down) }, - playfields[0], - playfields[1] + new Drawable[] + { + playfields[2] = new TestPlayfield(ScrollingDirection.Left), + playfields[3] = new TestPlayfield(ScrollingDirection.Right) + } } }); - AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.TimeRange.Value = v)); + AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.VisibleTimeRange.Value = v)); AddStep("Add control point", () => addControlPoint(Time.Current + 5000)); } @@ -61,6 +50,8 @@ namespace osu.Game.Tests.Visual { base.LoadComplete(); + playfields.ForEach(p => p.HitObjects.AddControlPoint(new MultiplierControlPoint(0))); + for (int i = 0; i <= 5000; i += 1000) addHitObject(Time.Current + i); @@ -71,10 +62,10 @@ namespace osu.Game.Tests.Visual { playfields.ForEach(p => { - p.Add(new TestDrawableHitObject(time) - { - Anchor = p.Direction == ScrollingDirection.Right ? Anchor.CentreRight : Anchor.BottomCentre - }); + var hitObject = new TestDrawableHitObject(time); + setAnchor(hitObject, p); + + p.Add(hitObject); }); } @@ -86,10 +77,12 @@ namespace osu.Game.Tests.Visual p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }); p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }); - TestDrawableControlPoint createDrawablePoint(double t) => new TestDrawableControlPoint(t) + TestDrawableControlPoint createDrawablePoint(double t) { - Anchor = p.Direction == ScrollingDirection.Right ? Anchor.CentreRight : Anchor.BottomCentre - }; + var obj = new TestDrawableControlPoint(p.Direction, t); + setAnchor(obj, p); + return obj; + } p.Add(createDrawablePoint(time)); p.Add(createDrawablePoint(time + 2000)); @@ -97,12 +90,28 @@ namespace osu.Game.Tests.Visual }); } + private void setAnchor(DrawableHitObject obj, TestPlayfield playfield) + { + switch (playfield.Direction) + { + case ScrollingDirection.Up: + obj.Anchor = Anchor.TopCentre; + break; + case ScrollingDirection.Down: + obj.Anchor = Anchor.BottomCentre; + break; + case ScrollingDirection.Left: + obj.Anchor = Anchor.CentreLeft; + break; + case ScrollingDirection.Right: + obj.Anchor = Anchor.CentreRight; + break; + } + } private class TestPlayfield : ScrollingPlayfield { - public readonly BindableDouble TimeRange = new BindableDouble(5000); - public readonly ScrollingDirection Direction; public TestPlayfield(ScrollingDirection direction) @@ -110,34 +119,45 @@ namespace osu.Game.Tests.Visual { Direction = direction; - HitObjects.TimeRange.BindTo(TimeRange); + Padding = new MarginPadding(2); + ScaledContent.Masking = true; + + AddInternal(new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + Depth = float.MaxValue + }); } } private class TestDrawableControlPoint : DrawableHitObject { - private readonly Box box; - - public TestDrawableControlPoint(double time) + public TestDrawableControlPoint(ScrollingDirection direction, double time) : base(new HitObject { StartTime = time }) { Origin = Anchor.Centre; - Add(box = new Box + Add(new Box { Anchor = Anchor.Centre, Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both }); - } - protected override void Update() - { - base.Update(); - - RelativeSizeAxes = (Anchor & Anchor.x2) > 0 ? Axes.Y : Axes.X; - Size = new Vector2(1); - - box.Size = DrawSize; + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + RelativeSizeAxes = Axes.X; + Height = 2; + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + RelativeSizeAxes = Axes.Y; + Width = 2; + break; + } } protected override void UpdateState(ArmedState state) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index a1d07d9a03..25a7adb5a7 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.UI } } }); - - HitObjects = CreateHitObjectContainer(); - HitObjects.RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load() { + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; + Add(HitObjects); } From 5b190d3cd2e311cf28d1fcdf93ebf08c521ab288 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 12:47:04 +0900 Subject: [PATCH 39/49] Use correct container type when removing fruit (cherry picked from commit a2be7f7) --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index e02849d0f5..c70cb15b40 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; @@ -48,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.UI var screenSpacePosition = fruit.ScreenSpaceDrawQuad.Centre; // todo: make this less ugly, somehow. - (fruit.Parent as Container)?.Remove(fruit); + (fruit.Parent as HitObjectContainer)?.Remove(fruit); (fruit.Parent as Container)?.Remove(fruit); fruit.RelativePositionAxes = Axes.None; From 66ebe2ee6679866d46b497a6b1318d8bc5cab5e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 20:55:43 +0900 Subject: [PATCH 40/49] Change anchors in line with new ScrollingPlayfield implementation (cherry picked from commit 079827d) --- .../Objects/Drawable/DrawableCatchHitObject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 41313b9197..d9a16ad248 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable HitObject = hitObject; Scale = new Vector2(HitObject.Scale); + + Anchor = Anchor.BottomLeft; } } From 0609fc40de1ba8ba08e5126bc22c1351b027d268 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 20:56:09 +0900 Subject: [PATCH 41/49] Fix up DrawableJuiceStream/BananaShower (cherry picked from commit 0bfb3b6) --- .../Objects/Drawable/DrawableJuiceStream.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index dcb7fdb823..036c5bd879 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -16,15 +16,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public DrawableJuiceStream(JuiceStream s) : base(s) { RelativeSizeAxes = Axes.Both; - Height = (float)HitObject.Duration; + Origin = Anchor.BottomLeft; X = 0; - Child = dropletContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), - RelativeChildSize = new Vector2(1, (float)HitObject.Duration) - }; + Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; foreach (CatchHitObject tick in s.NestedHitObjects.OfType()) { From 61062164cb3944efb45066132015a3a67b4d9bd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 21:12:27 +0900 Subject: [PATCH 42/49] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 80bcb82ef8..6594729122 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 80bcb82ef8d2e1af1ce077f4a037b6d279ad9e74 +Subproject commit 65947291229541de3eb1aff0e703f6968b07f976 From e5f17e3ddbd6ec793f5e618fb57f2067b376f1ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 21:49:20 +0900 Subject: [PATCH 43/49] Remove scale from all but palpable fruit --- .../Objects/Drawable/DrawableCatchHitObject.cs | 14 +++++++++++--- .../Objects/Drawable/DrawableDroplet.cs | 2 +- .../Objects/Drawable/DrawableFruit.cs | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index d9a16ad248..554fb1323e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -10,6 +10,17 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Objects.Drawable { + public abstract class PalpableCatchHitObject : DrawableCatchHitObject + where TObject : CatchHitObject + { + protected PalpableCatchHitObject(TObject hitObject) + : base(hitObject) + { + Scale = new Vector2(HitObject.Scale); + } + } + + public abstract class DrawableCatchHitObject : DrawableCatchHitObject where TObject : CatchHitObject { @@ -19,9 +30,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable : base(hitObject) { HitObject = hitObject; - - Scale = new Vector2(HitObject.Scale); - Anchor = Anchor.BottomLeft; } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index 289323c1b5..c2b0552ab3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -8,7 +8,7 @@ using OpenTK; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - public class DrawableDroplet : DrawableCatchHitObject + public class DrawableDroplet : PalpableCatchHitObject { public DrawableDroplet(Droplet h) : base(h) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index c2c59468e9..ae20abf0d9 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -14,7 +14,7 @@ using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - public class DrawableFruit : DrawableCatchHitObject + public class DrawableFruit : PalpableCatchHitObject { private Circle border; From 712d586d4159e1271d7b57129c4a6564637cb965 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 13:40:46 +0900 Subject: [PATCH 44/49] Revert "Add OSD + config value for scroll speed" This reverts commit a6d8b28221910993005d6adbbcc5b0447b5a1511. --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 5 +---- osu.Game/Configuration/OsuConfigManager.cs | 4 +--- osu.Game/Overlays/OnScreenDisplay.cs | 6 +----- osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 7 ++----- 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 532be2759f..919518dbe8 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -15,7 +15,6 @@ using osu.Framework.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Framework.Graphics.Shapes; -using osu.Game.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.UI.Scrolling; @@ -162,10 +161,8 @@ namespace osu.Game.Rulesets.Mania.UI } [BackgroundDependencyLoader] - private void load(OsuColour colours, OsuConfigManager config) + private void load(OsuColour colours) { - config.BindWith(OsuSetting.UserScrollSpeed, VisibleTimeRange); - normalColumnColours = new List { colours.RedDark, diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 26879782fc..13213a54a1 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -73,7 +73,6 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); Set(OsuSetting.ScrollingAlgorithm, ScrollingAlgorithmType.Global); - Set(OsuSetting.UserScrollSpeed, 1500.0, 50.0, 10000.0); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -120,7 +119,6 @@ namespace osu.Game.Configuration ChatDisplayHeight, Version, ShowConvertedBeatmaps, - ScrollingAlgorithm, - UserScrollSpeed + ScrollingAlgorithm } } diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 4f3f03c749..6a1bd8e182 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -14,7 +14,6 @@ using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; -using osu.Game.Configuration; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays @@ -116,7 +115,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig, OsuConfigManager osuConfig) + private void load(FrameworkConfigManager frameworkConfig) { trackSetting(frameworkConfig.GetBindable(FrameworkSetting.FrameSync), v => display(v, "Frame Limiter", v.GetDescription(), "Ctrl+F7")); trackSetting(frameworkConfig.GetBindable(FrameworkSetting.AudioDevice), v => display(v, "Audio Device", string.IsNullOrEmpty(v) ? "Default" : v, v)); @@ -136,9 +135,6 @@ namespace osu.Game.Overlays }); trackSetting(frameworkConfig.GetBindable(FrameworkSetting.WindowMode), v => display(v, "Screen Mode", v.ToString(), "Alt+Enter")); - - // Todo: This should be part of the ruleset-specific OSD - trackSetting(osuConfig.GetBindable(OsuSetting.UserScrollSpeed), v => display(v, "Scroll Speed", $"{v:N0}ms", "Ctrl+(+/-) to change")); } private readonly List references = new List(); diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index fa04b7f137..11185015b8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -103,15 +102,13 @@ namespace osu.Game.Rulesets.UI.Scrolling if (state.Keyboard.ControlPressed) { - var lastValue = Transforms.OfType().LastOrDefault()?.EndValue ?? VisibleTimeRange.Value; - switch (args.Key) { case Key.Minus: - transformVisibleTimeRangeTo(lastValue + time_span_step, 200, Easing.OutQuint); + transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); break; case Key.Plus: - transformVisibleTimeRangeTo(lastValue - time_span_step, 200, Easing.OutQuint); + transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); break; } } From 4b2d971b005bf6e82d84d4969b248bbf55ef32b8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 13:03:47 +0900 Subject: [PATCH 45/49] Add some comments --- .../Algorithms/IScrollingAlgorithm.cs | 18 ++++++++++++++++++ .../Scrolling/ScrollingHitObjectContainer.cs | 10 +++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs index f9863bd299..d9e4ab228f 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs @@ -9,7 +9,25 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { public interface IScrollingAlgorithm { + /// + /// Computes the states of s that are constant, such as lifetime and spatial length. + /// This is invoked once whenever or changes. + /// + /// The s whose states should be computed. + /// The scrolling direction. + /// The duration required to scroll through one length of the screen before any control point adjustments. + /// The length of the screen that is scrolled through. void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length); + + /// + /// Computes the states of s that change depending on , such as position. + /// This is invoked once per frame. + /// + /// The s whose states should be computed. + /// The scrolling direction. + /// The current time. + /// The duration required to scroll through one length of the screen before any control point adjustments. + /// The length of the screen that is scrolled through. void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index dfa6a40db4..960fd94762 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -15,12 +15,18 @@ namespace osu.Game.Rulesets.UI.Scrolling { public class ScrollingHitObjectContainer : HitObjectContainer { + /// + /// The duration required to scroll through one length of the before any control point adjustments. + /// public readonly BindableDouble TimeRange = new BindableDouble { MinValue = 0, MaxValue = double.MaxValue }; + /// + /// The control points that adjust the scrolling speed. + /// protected readonly SortedList ControlPoints = new SortedList(); private readonly ScrollingDirection direction; @@ -104,9 +110,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 - + // We need to calculate this as soon as possible after lifetimes so that hitobjects get the final say in their positions scrollingAlgorithm.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); } } From 03824eccc8f658a50551e1f592520a45aa77447c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 17:09:21 +0900 Subject: [PATCH 46/49] Block fadeout on holdnote heads --- .../Objects/Drawables/DrawableHoldNote.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 6748bc22e6..76fc0dcf77 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -186,6 +186,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return true; } + + protected override void UpdateState(ArmedState state) + { + // The holdnote keeps scrolling through for now, so having the head disappear looks weird + } } /// From cae93a1d1f7a6d31ebc181c97766e341d3023322 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 17:09:34 +0900 Subject: [PATCH 47/49] Add comment to fade override of holdnote tail --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 76fc0dcf77..58f024870d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -238,6 +238,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void UpdateState(ArmedState state) { + // The holdnote keeps scrolling through, so having the tail disappear looks weird } public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down From 441e8aced51376ac99d153423a20de42b1a6e55e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 17:18:34 +0900 Subject: [PATCH 48/49] Better namings for the speed change "algorithms" --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- ...pe.cs => SpeedChangeVisualisationMethod.cs} | 10 +++++----- .../Sections/Gameplay/ScrollingSettings.cs | 6 +++--- .../Scrolling/ScrollingHitObjectContainer.cs | 18 +++++++++--------- .../ISpeedChangeVisualiser.cs} | 4 ++-- .../OverlappingSpeedChangeVisualiser.cs} | 6 +++--- .../SequentialSpeedChangeVisualiser.cs} | 6 +++--- osu.Game/osu.Game.csproj | 8 ++++---- 8 files changed, 31 insertions(+), 31 deletions(-) rename osu.Game/Configuration/{ScrollingAlgorithmType.cs => SpeedChangeVisualisationMethod.cs} (57%) rename osu.Game/Rulesets/UI/Scrolling/{Algorithms/IScrollingAlgorithm.cs => Visualisers/ISpeedChangeVisualiser.cs} (93%) rename osu.Game/Rulesets/UI/Scrolling/{Algorithms/LocalScrollingAlgorithm.cs => Visualisers/OverlappingSpeedChangeVisualiser.cs} (90%) rename osu.Game/Rulesets/UI/Scrolling/{Algorithms/GlobalScrollingAlgorithm.cs => Visualisers/SequentialSpeedChangeVisualiser.cs} (92%) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 13213a54a1..23f7fd6ac1 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -72,7 +72,7 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); - Set(OsuSetting.ScrollingAlgorithm, ScrollingAlgorithmType.Global); + Set(OsuSetting.SpeedChangeVisualisation, SpeedChangeVisualisationMethod.Sequential); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -119,6 +119,6 @@ namespace osu.Game.Configuration ChatDisplayHeight, Version, ShowConvertedBeatmaps, - ScrollingAlgorithm + SpeedChangeVisualisation } } diff --git a/osu.Game/Configuration/ScrollingAlgorithmType.cs b/osu.Game/Configuration/SpeedChangeVisualisationMethod.cs similarity index 57% rename from osu.Game/Configuration/ScrollingAlgorithmType.cs rename to osu.Game/Configuration/SpeedChangeVisualisationMethod.cs index 8b9d292634..644ae0a727 100644 --- a/osu.Game/Configuration/ScrollingAlgorithmType.cs +++ b/osu.Game/Configuration/SpeedChangeVisualisationMethod.cs @@ -5,11 +5,11 @@ using System.ComponentModel; namespace osu.Game.Configuration { - public enum ScrollingAlgorithmType + public enum SpeedChangeVisualisationMethod { - [Description("Global")] - Global, - [Description("Local")] - Local + [Description("Sequential")] + Sequential, + [Description("Overlapping")] + Overlapping } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs index 3243f4c23a..4e8706137c 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs @@ -15,10 +15,10 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Children = new[] { - new SettingsEnumDropdown + new SettingsEnumDropdown { - LabelText = "Scrolling algorithm", - Bindable = config.GetBindable(OsuSetting.ScrollingAlgorithm), + LabelText = "Visualise speed changes as", + Bindable = config.GetBindable(OsuSetting.SpeedChangeVisualisation), } }; } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 960fd94762..e69abec45e 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -9,7 +9,7 @@ using osu.Framework.Lists; using osu.Game.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; -using osu.Game.Rulesets.UI.Scrolling.Algorithms; +using osu.Game.Rulesets.UI.Scrolling.Visualisers; namespace osu.Game.Rulesets.UI.Scrolling { @@ -42,18 +42,18 @@ namespace osu.Game.Rulesets.UI.Scrolling TimeRange.ValueChanged += v => initialStateCache.Invalidate(); } - private IScrollingAlgorithm scrollingAlgorithm; + private ISpeedChangeVisualiser speedChangeVisualiser; [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - switch (config.Get(OsuSetting.ScrollingAlgorithm)) + switch (config.Get(OsuSetting.SpeedChangeVisualisation)) { - case ScrollingAlgorithmType.Global: - scrollingAlgorithm = new GlobalScrollingAlgorithm(ControlPoints); + case SpeedChangeVisualisationMethod.Sequential: + speedChangeVisualiser = new SequentialSpeedChangeVisualiser(ControlPoints); break; - case ScrollingAlgorithmType.Local: - scrollingAlgorithm = new LocalScrollingAlgorithm(ControlPoints); + case SpeedChangeVisualisationMethod.Overlapping: + speedChangeVisualiser = new OverlappingSpeedChangeVisualiser(ControlPoints); break; } } @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.UI.Scrolling if (initialStateCache.IsValid) return; - scrollingAlgorithm.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); + speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); initialStateCache.Validate(); } @@ -111,7 +111,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 - scrollingAlgorithm.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); + speedChangeVisualiser.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); } } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs similarity index 93% rename from osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs rename to osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs index d9e4ab228f..46d71e1602 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; -namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers { - public interface IScrollingAlgorithm + public interface ISpeedChangeVisualiser { /// /// Computes the states of s that are constant, such as lifetime and spatial length. diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs similarity index 90% rename from osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs rename to osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs index 96a85c5f9f..24f69c627d 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs @@ -7,15 +7,15 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using OpenTK; -namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers { - public class LocalScrollingAlgorithm : IScrollingAlgorithm + public class OverlappingSpeedChangeVisualiser : ISpeedChangeVisualiser { private readonly Dictionary hitObjectPositions = new Dictionary(); private readonly SortedList controlPoints; - public LocalScrollingAlgorithm(SortedList controlPoints) + public OverlappingSpeedChangeVisualiser(SortedList controlPoints) { this.controlPoints = controlPoints; } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs similarity index 92% rename from osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs rename to osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs index ed156ecfd5..94705426f8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs @@ -8,15 +8,15 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; using OpenTK; -namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers { - public class GlobalScrollingAlgorithm : IScrollingAlgorithm + public class SequentialSpeedChangeVisualiser : ISpeedChangeVisualiser { private readonly Dictionary hitObjectPositions = new Dictionary(); private readonly IReadOnlyList controlPoints; - public GlobalScrollingAlgorithm(IReadOnlyList controlPoints) + public SequentialSpeedChangeVisualiser(IReadOnlyList controlPoints) { this.controlPoints = controlPoints; } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 45183de092..01052a7898 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -265,7 +265,7 @@ - + @@ -318,9 +318,9 @@ - - - + + + From 8a04c954a90198a6c2e4b3369160a9fcd84c8dea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 17:19:59 +0900 Subject: [PATCH 49/49] Cleanup --- .../UI/Scrolling/ScrollingHitObjectContainer.cs | 11 +++++------ .../Visualisers/OverlappingSpeedChangeVisualiser.cs | 2 -- osu.Game/osu.Game.csproj | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e69abec45e..530ed653aa 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -98,12 +98,11 @@ namespace osu.Game.Rulesets.UI.Scrolling { base.Update(); - if (initialStateCache.IsValid) - return; - - speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); - - initialStateCache.Validate(); + if (!initialStateCache.IsValid) + { + speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); + initialStateCache.Validate(); + } } protected override void UpdateAfterChildrenLife() diff --git a/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs index 24f69c627d..4cce90ee94 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs @@ -11,8 +11,6 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers { public class OverlappingSpeedChangeVisualiser : ISpeedChangeVisualiser { - private readonly Dictionary hitObjectPositions = new Dictionary(); - private readonly SortedList controlPoints; public OverlappingSpeedChangeVisualiser(SortedList controlPoints) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 01052a7898..967f3fc1d7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -318,9 +318,9 @@ - - - + + +