From 0f901c99a01bcd75b6bb7904d6fd529ea6c29d0e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 4 Aug 2017 14:44:43 +0930 Subject: [PATCH 01/67] Implement SpeedAdjustedPlayfield and a new HitRenderer derivation. --- .../UI/ManiaHitRenderer.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- osu.Game/Rulesets/UI/HitRenderer.cs | 28 ++++++++++++++++++- .../Rulesets/UI/SpeedAdjustedHitRenderer.cs | 6 ++-- .../Rulesets/UI/SpeedAdjustedPlayfield.cs | 15 ++++++++++ osu.Game/osu.Game.csproj | 1 + 6 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Rulesets/UI/SpeedAdjustedPlayfield.cs diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index b92c0916b1..2805c129f3 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -30,7 +30,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaHitRenderer : SpeedAdjustedHitRenderer + public class ManiaHitRenderer : SpeedAdjustedHitRenderer { /// /// Preferred column count. This will only have an effect during the initialization of the play field. diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 03b6e18856..b81b9c44fe 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -23,7 +23,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaPlayfield : Playfield + public class ManiaPlayfield : SpeedAdjustedPlayfield { public const float HIT_TARGET_POSITION = 50; diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index 8fe1dd3e0a..fd43078c2b 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.UI /// /// The playfield. /// - protected Playfield Playfield; + protected Playfield Playfield { get; private set; } protected override Container Content => content; private readonly Container content; @@ -319,6 +319,32 @@ namespace osu.Game.Rulesets.UI protected abstract Playfield CreatePlayfield(); } + /// + /// A derivable HitRenderer that manages the Playfield and HitObjects. + /// + /// The type of HitObject contained by this HitRenderer. + /// The type of Judgement of DrawableHitObjects contained by this HitRenderer. + public abstract class HitRenderer : HitRenderer + where TObject : HitObject + where TJudgement : Judgement + where TPlayfield : Playfield + { + /// + /// The playfield. + /// + protected new TPlayfield Playfield => (TPlayfield)base.Playfield; + + /// + /// Creates a hit renderer for a beatmap. + /// + /// The beatmap to create the hit renderer for. + /// Whether to assume the beatmap is for the current ruleset. + protected HitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(beatmap, isForCurrentRuleset) + { + } + } + public class BeatmapInvalidForRulesetException : ArgumentException { public BeatmapInvalidForRulesetException(string text) diff --git a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs b/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs index 42dadb047d..2dadbb04d0 100644 --- a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs +++ b/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs @@ -16,11 +16,13 @@ using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.UI { /// - /// A type of that supports speed adjustments in some capacity. + /// A type of that exposes s to be used + /// in s. /// - public abstract class SpeedAdjustedHitRenderer : HitRenderer + public abstract class SpeedAdjustedHitRenderer : HitRenderer where TObject : HitObject where TJudgement : Judgement + where TPlayfield : SpeedAdjustedPlayfield { protected readonly SortedList DefaultControlPoints = new SortedList(Comparer.Default); diff --git a/osu.Game/Rulesets/UI/SpeedAdjustedPlayfield.cs b/osu.Game/Rulesets/UI/SpeedAdjustedPlayfield.cs new file mode 100644 index 0000000000..1d1f890a6e --- /dev/null +++ b/osu.Game/Rulesets/UI/SpeedAdjustedPlayfield.cs @@ -0,0 +1,15 @@ +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.UI +{ + public class SpeedAdjustedPlayfield : Playfield + where TObject : HitObject + where TJudgement : Judgement + { + protected SpeedAdjustedPlayfield(float? customWidth = null) + : base(customWidth) + { + } + } +} \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3f475a34c8..5ec7f365f5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -340,6 +340,7 @@ + From d42faa02df7e090362da87b4d09fb15cfc1687c6 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 4 Aug 2017 20:11:51 +0930 Subject: [PATCH 02/67] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 9ae8979ef7..c687b8b102 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 9ae8979ef7ef0968c90cdbce40a04969d43633c7 +Subproject commit c687b8b102dac1f8b7ffad7efc12939484e256c0 From 54503eef71d409ebc842fd0df028833f93e67d5b Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 4 Aug 2017 20:52:53 +0930 Subject: [PATCH 03/67] Rename *ScrollingDrawableTimingSection -> *ScrollingContainer, move LinearScrollingContainer to osu.Game, make SpeedAdjustmentContainer non-abstract. --- .../Visual/TestCaseScrollingHitObjects.cs | 8 ++--- .../BasicScrollingDrawableTimingSection.cs | 27 ---------------- ...ection.cs => GravityScrollingContainer.cs} | 11 ++++--- .../Timing/ManiaSpeedAdjustmentContainer.cs | 7 ++-- .../osu.Game.Rulesets.Mania.csproj | 3 +- .../Timing/LinearScrollingContainer.cs | 32 +++++++++++++++++++ ...TimingSection.cs => ScrollingContainer.cs} | 10 +++--- .../Timing/SpeedAdjustmentContainer.cs | 26 +++++++-------- osu.Game/osu.Game.csproj | 3 +- 9 files changed, 66 insertions(+), 61 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Timing/BasicScrollingDrawableTimingSection.cs rename osu.Game.Rulesets.Mania/Timing/{GravityScrollingDrawableTimingSection.cs => GravityScrollingContainer.cs} (80%) create mode 100644 osu.Game/Rulesets/Timing/LinearScrollingContainer.cs rename osu.Game/Rulesets/Timing/{DrawableTimingSection.cs => ScrollingContainer.cs} (93%) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs index efc129a678..056e063120 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -18,7 +18,7 @@ namespace osu.Desktop.Tests.Visual { public class TestCaseScrollingHitObjects : OsuTestCase { - public override string Description => "SpeedAdjustmentContainer/DrawableTimingSection"; + public override string Description => "SpeedAdjustmentContainer/ScrollingContainer"; private readonly BindableDouble timeRangeBindable; private readonly OsuSpriteText bottomLabel; @@ -131,13 +131,13 @@ namespace osu.Desktop.Tests.Visual { } - protected override DrawableTimingSection CreateTimingSection() => new TestDrawableTimingSection(ControlPoint); + protected override ScrollingContainer CreateScrollingContainer() => new TestScrollingContainer(ControlPoint); - private class TestDrawableTimingSection : DrawableTimingSection + private class TestScrollingContainer : ScrollingContainer { private readonly MultiplierControlPoint controlPoint; - public TestDrawableTimingSection(MultiplierControlPoint controlPoint) + public TestScrollingContainer(MultiplierControlPoint controlPoint) { this.controlPoint = controlPoint; } diff --git a/osu.Game.Rulesets.Mania/Timing/BasicScrollingDrawableTimingSection.cs b/osu.Game.Rulesets.Mania/Timing/BasicScrollingDrawableTimingSection.cs deleted file mode 100644 index e485581d9f..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/BasicScrollingDrawableTimingSection.cs +++ /dev/null @@ -1,27 +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 which scrolls relative to the control point start time. - /// - internal class BasicScrollingDrawableTimingSection : DrawableTimingSection - { - private readonly MultiplierControlPoint controlPoint; - - public BasicScrollingDrawableTimingSection(MultiplierControlPoint controlPoint) - { - this.controlPoint = controlPoint; - } - - protected override void Update() - { - base.Update(); - - Y = (float)(controlPoint.StartTime - Time.Current); - } - } -} diff --git a/osu.Game.Rulesets.Mania/Timing/GravityScrollingDrawableTimingSection.cs b/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs similarity index 80% rename from osu.Game.Rulesets.Mania/Timing/GravityScrollingDrawableTimingSection.cs rename to osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs index 730daa9ffd..2cb14f224e 100644 --- a/osu.Game.Rulesets.Mania/Timing/GravityScrollingDrawableTimingSection.cs +++ b/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs @@ -1,18 +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.Graphics; 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. + /// A that emulates a form of gravity where hit objects speed up over time. /// - internal class GravityScrollingDrawableTimingSection : DrawableTimingSection + internal class GravityScrollingContainer : ScrollingContainer { private readonly MultiplierControlPoint controlPoint; - public GravityScrollingDrawableTimingSection(MultiplierControlPoint controlPoint) + public GravityScrollingContainer(MultiplierControlPoint controlPoint) { this.controlPoint = controlPoint; } @@ -51,10 +52,10 @@ namespace osu.Game.Rulesets.Mania.Timing private double acceleration => 1 / VisibleTimeRange; /// - /// Computes the current time relative to , accounting for . + /// Computes the current time relative to , accounting for . /// /// The non-offset time. - /// The current time relative to - . + /// 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 index ed22264d74..321b4ee92b 100644 --- a/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs @@ -15,15 +15,14 @@ namespace osu.Game.Rulesets.Mania.Timing this.scrollingAlgorithm = scrollingAlgorithm; } - protected override DrawableTimingSection CreateTimingSection() + protected override ScrollingContainer CreateScrollingContainer() { switch (scrollingAlgorithm) { default: - case ScrollingAlgorithm.Basic: - return new BasicScrollingDrawableTimingSection(ControlPoint); + return base.CreateScrollingContainer(); case ScrollingAlgorithm.Gravity: - return new GravityScrollingDrawableTimingSection(ControlPoint); + return new GravityScrollingContainer(ControlPoint); } } } diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 88d1ad7ad8..3832f9ace5 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -79,8 +79,7 @@ - - + diff --git a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs new file mode 100644 index 0000000000..b86165997b --- /dev/null +++ b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Rulesets.Timing; + +namespace osu.Game.Rulesets.Timing +{ + /// + /// A which scrolls relative to the control point start time. + /// This is the default returned by the base . + /// + internal class LinearScrollingContainer : ScrollingContainer + { + private readonly Axes scrollingAxes; + private readonly MultiplierControlPoint controlPoint; + + public LinearScrollingContainer(Axes scrollingAxes, MultiplierControlPoint controlPoint) + { + this.scrollingAxes = scrollingAxes; + 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/DrawableTimingSection.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs similarity index 93% rename from osu.Game/Rulesets/Timing/DrawableTimingSection.cs rename to osu.Game/Rulesets/Timing/ScrollingContainer.cs index 6345a566c2..c412530b15 100644 --- a/osu.Game/Rulesets/Timing/DrawableTimingSection.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Timing /// and to apply further time offsets to this collection of hit objects. /// /// - public abstract class DrawableTimingSection : Container + public abstract class ScrollingContainer : Container { private readonly BindableDouble visibleTimeRange = new BindableDouble(); /// @@ -71,9 +71,9 @@ namespace osu.Game.Rulesets.Timing } /// - /// Creates a new . + /// Creates a new . /// - protected DrawableTimingSection() + protected ScrollingContainer() { RelativeSizeAxes = Axes.Both; RelativePositionAxes = Axes.Both; @@ -128,8 +128,8 @@ namespace osu.Game.Rulesets.Timing } /// - /// The maximum duration of any one hit object inside this . This is calculated as the maximum - /// end time between all hit objects relative to this 's . + /// The maximum duration of any one hit object inside this . This is calculated as the maximum + /// end time between all hit objects relative to this 's . /// public double Duration => durationBacking.IsValid ? durationBacking : (durationBacking.Value = computeDuration()); diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index f41ef21c1e..3c0ba86db3 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -12,14 +12,14 @@ namespace osu.Game.Rulesets.Timing { /// /// A container for hit objects which applies applies the speed adjustments defined by the properties of a - /// to affect the scroll speed of the contained . + /// to affect the scroll speed of the contained . /// /// /// This container must always be relatively-sized to its parent to provide the speed adjustments. This container will provide the speed adjustments /// by modifying its size while maintaining a constant for its children /// /// - public abstract class SpeedAdjustmentContainer : Container + public class SpeedAdjustmentContainer : Container { private readonly Bindable visibleTimeRange = new Bindable(); /// @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Timing public readonly MultiplierControlPoint ControlPoint; - private DrawableTimingSection timingSection; + private ScrollingContainer scrollingContainer; /// /// Creates a new . @@ -58,14 +58,14 @@ namespace osu.Game.Rulesets.Timing [BackgroundDependencyLoader] private void load() { - timingSection = CreateTimingSection(); + scrollingContainer = CreateScrollingContainer(); - timingSection.ScrollingAxes = ScrollingAxes; - timingSection.ControlPoint = ControlPoint; - timingSection.VisibleTimeRange.BindTo(VisibleTimeRange); - timingSection.RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)ControlPoint.StartTime : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)ControlPoint.StartTime : 0); + scrollingContainer.ScrollingAxes = ScrollingAxes; + scrollingContainer.ControlPoint = ControlPoint; + scrollingContainer.VisibleTimeRange.BindTo(VisibleTimeRange); + scrollingContainer.RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)ControlPoint.StartTime : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)ControlPoint.StartTime : 0); - AddInternal(content = timingSection); + AddInternal(content = scrollingContainer); } protected override void Update() @@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Timing } public override double LifetimeStart => ControlPoint.StartTime - VisibleTimeRange; - public override double LifetimeEnd => ControlPoint.StartTime + timingSection.Duration + VisibleTimeRange; + public override double LifetimeEnd => ControlPoint.StartTime + scrollingContainer.Duration + VisibleTimeRange; public override void Add(DrawableHitObject drawable) { @@ -99,9 +99,9 @@ namespace osu.Game.Rulesets.Timing public bool CanContain(double startTime) => ControlPoint.StartTime <= startTime; /// - /// Creates the container which handles the movement of a collection of hit objects. + /// Creates the container which contains a collection of hit objects and scrolls through this SpeedAdjustmentContainer. /// - /// The . - protected abstract DrawableTimingSection CreateTimingSection(); + /// The . + protected virtual ScrollingContainer CreateScrollingContainer() => new LinearScrollingContainer(ScrollingAxes, ControlPoint); } } \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5ec7f365f5..075f0732f7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -227,7 +227,8 @@ - + + From b1d25ed38815296ca64280eb08e7475a0a6d5ca8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 4 Aug 2017 23:07:08 +0900 Subject: [PATCH 04/67] Implement ScrollingPlayfield, now containing ScrollingHitObjectContainer (prev. SpeedAdjustmentCollection). Also removing a lot of mania code relating to gravity mod for now. --- .../Visual/TestCaseScrollingHitObjects.cs | 25 ++- osu.Game.Rulesets.Mania/UI/Column.cs | 37 ++-- .../UI/ManiaHitRenderer.cs | 65 +----- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 48 +---- .../Rulesets/Timing/ScrollingContainer.cs | 2 +- .../Timing/SpeedAdjustmentCollection.cs | 133 ------------ .../Timing/SpeedAdjustmentContainer.cs | 2 +- osu.Game/Rulesets/UI/Playfield.cs | 5 +- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 190 ++++++++++++++++++ .../Rulesets/UI/SpeedAdjustedHitRenderer.cs | 15 +- .../Rulesets/UI/SpeedAdjustedPlayfield.cs | 15 -- osu.Game/osu.Game.csproj | 3 +- 12 files changed, 263 insertions(+), 277 deletions(-) delete mode 100644 osu.Game/Rulesets/Timing/SpeedAdjustmentCollection.cs create mode 100644 osu.Game/Rulesets/UI/ScrollingPlayfield.cs delete mode 100644 osu.Game/Rulesets/UI/SpeedAdjustedPlayfield.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs index 056e063120..6b30cc4f32 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -13,6 +13,9 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using OpenTK; using OpenTK.Graphics; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.Judgements; +using System; namespace osu.Desktop.Tests.Visual { @@ -28,7 +31,7 @@ namespace osu.Desktop.Tests.Visual public TestCaseScrollingHitObjects() { OsuSpriteText timeRangeText; - SpeedAdjustmentCollection adjustmentCollection; + ScrollingPlayfield.ScrollingHitObjectContainer scrollingHitObjectContainer; timeRangeBindable = new BindableDouble(2000) { @@ -68,7 +71,7 @@ namespace osu.Desktop.Tests.Visual RelativeSizeAxes = Axes.Both, Alpha = 0.25f }, - adjustmentCollection = new SpeedAdjustmentCollection(Axes.Y) + scrollingHitObjectContainer = new ScrollingPlayfield.ScrollingHitObjectContainer(Axes.Y) { RelativeSizeAxes = Axes.Both, VisibleTimeRange = timeRangeBindable, @@ -109,9 +112,9 @@ namespace osu.Desktop.Tests.Visual timeRangeBindable.TriggerChange(); - adjustmentCollection.Add(new TestSpeedAdjustmentContainer(new MultiplierControlPoint())); + scrollingHitObjectContainer.AddSpeedAdjustment(new TestSpeedAdjustmentContainer(new MultiplierControlPoint())); - AddStep("Add hit object", () => adjustmentCollection.Add(new TestDrawableHitObject(new HitObject { StartTime = Time.Current + 2000 }))); + AddStep("Add hit object", () => scrollingHitObjectContainer.Add(new TestDrawableHitObject(new HitObject { StartTime = Time.Current + 2000 }))); } protected override void Update() @@ -151,7 +154,7 @@ namespace osu.Desktop.Tests.Visual } } - private class TestDrawableHitObject : DrawableHitObject, IScrollingHitObject + private class TestDrawableHitObject : DrawableHitObject, IScrollingHitObject { private readonly Box background; private const float height = 14; @@ -204,6 +207,18 @@ namespace osu.Desktop.Tests.Visual if (Time.Current >= HitObject.StartTime) background.Colour = Color4.Red; } + + protected override Judgement CreateJudgement() => new TestJudgement(); + + protected override void UpdateState(ArmedState state) + { + } + + private class TestJudgement : Judgement + { + public override string ResultString { get { throw new NotImplementedException(); } } + public override string MaxResultString { get { throw new NotImplementedException(); } } + } } } } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 94cf6a4337..424ed77783 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -15,10 +15,15 @@ using osu.Game.Rulesets.Objects.Drawables; using System; using osu.Framework.Configuration; using osu.Game.Rulesets.Timing; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Judgements; +using osu.Framework.Allocation; namespace osu.Game.Rulesets.Mania.UI { - public class Column : Container, IHasAccentColour + public class Column : ScrollingPlayfield, IHasAccentColour { private const float key_icon_size = 10; private const float key_icon_corner_radius = 3; @@ -30,13 +35,6 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; - private readonly BindableDouble visibleTimeRange = new BindableDouble(); - public BindableDouble VisibleTimeRange - { - get { return visibleTimeRange; } - set { visibleTimeRange.BindTo(value); } - } - /// /// The key that will trigger input actions for this column and hit objects contained inside it. /// @@ -46,14 +44,15 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Container hitTargetBar; private readonly Container keyIcon; - private readonly SpeedAdjustmentCollection speedAdjustments; + protected override Container Content => content; + private readonly Container content; public Column() + : base(Axes.Y) { - RelativeSizeAxes = Axes.Y; Width = column_width; - Children = new Drawable[] + InternalChildren = new Drawable[] { background = new Box { @@ -97,11 +96,10 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - speedAdjustments = new SpeedAdjustmentCollection(Axes.Y) + content = new Container { Name = "Hit objects", RelativeSizeAxes = Axes.Both, - VisibleTimeRange = VisibleTimeRange }, // For column lighting, we need to capture input events before the notes new InputTarget @@ -150,6 +148,8 @@ namespace osu.Game.Rulesets.Mania.UI }; } + public override Axes RelativeSizeAxes => Axes.Y; + private bool isSpecial; public bool IsSpecial { @@ -192,11 +192,16 @@ namespace osu.Game.Rulesets.Mania.UI } } - public void Add(SpeedAdjustmentContainer speedAdjustment) => speedAdjustments.Add(speedAdjustment); - public void Add(DrawableHitObject hitObject) + public void Add(SpeedAdjustmentContainer speedAdjustment) => HitObjects.AddSpeedAdjustment(speedAdjustment); + + /// + /// Adds a DrawableHitObject to this Playfield. + /// + /// The DrawableHitObject to add. + public override void Add(DrawableHitObject hitObject) { hitObject.AccentColour = AccentColour; - speedAdjustments.Add(hitObject); + HitObjects.Add(hitObject); } private bool onKeyDown(InputState state, KeyDownEventArgs args) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 2805c129f3..04185f0872 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -39,24 +39,9 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; - /// - /// Per-column timing changes. - /// - private readonly List[] hitObjectSpeedAdjustments; - - /// - /// Bar line timing changes. - /// - private readonly List barLineSpeedAdjustments = new List(); - public ManiaHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(beatmap, isForCurrentRuleset) { - // Generate the speed adjustment container lists - hitObjectSpeedAdjustments = new List[PreferredColumns]; - for (int i = 0; i < PreferredColumns; i++) - hitObjectSpeedAdjustments[i] = new List(); - // Generate the bar lines double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; @@ -83,30 +68,12 @@ namespace osu.Game.Rulesets.Mania.UI } BarLines = barLines; - - // Generate speed adjustments from mods first - bool useDefaultSpeedAdjustments = true; - - if (Mods != null) - { - foreach (var speedAdjustmentMod in Mods.OfType()) - { - useDefaultSpeedAdjustments = false; - speedAdjustmentMod.ApplyToHitRenderer(this, ref hitObjectSpeedAdjustments, ref barLineSpeedAdjustments); - } - } - - // Generate the default speed adjustments - if (useDefaultSpeedAdjustments) - generateDefaultSpeedAdjustments(); } [BackgroundDependencyLoader] private void load() { - var maniaPlayfield = (ManiaPlayfield)Playfield; - - BarLines.ForEach(maniaPlayfield.Add); + BarLines.ForEach(Playfield.Add); } protected override void ApplyBeatmap() @@ -116,28 +83,6 @@ namespace osu.Game.Rulesets.Mania.UI PreferredColumns = (int)Math.Max(1, Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize)); } - protected override void ApplySpeedAdjustments() - { - var maniaPlayfield = (ManiaPlayfield)Playfield; - - for (int i = 0; i < PreferredColumns; i++) - foreach (var change in hitObjectSpeedAdjustments[i]) - maniaPlayfield.Columns.ElementAt(i).Add(change); - - foreach (var change in barLineSpeedAdjustments) - maniaPlayfield.Add(change); - } - - private void generateDefaultSpeedAdjustments() - { - DefaultControlPoints.ForEach(c => - { - foreach (List t in hitObjectSpeedAdjustments) - t.Add(new ManiaSpeedAdjustmentContainer(c, ScrollingAlgorithm.Basic)); - barLineSpeedAdjustments.Add(new ManiaSpeedAdjustmentContainer(c, ScrollingAlgorithm.Basic)); - }); - } - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(PreferredColumns) { Anchor = Anchor.Centre, @@ -168,5 +113,13 @@ namespace osu.Game.Rulesets.Mania.UI } protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(1, 0.8f); + + protected override void ApplySpeedAdjustment(MultiplierControlPoint controlPoint) + { + base.ApplySpeedAdjustment(controlPoint); + Playfield.Columns.ForEach(c => c.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint))); + } + + protected override SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Basic); } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index b81b9c44fe..3b1dc58e4f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -20,18 +20,14 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Framework.Configuration; using osu.Framework.Graphics.Shapes; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaPlayfield : SpeedAdjustedPlayfield + public class ManiaPlayfield : ScrollingPlayfield { public const float HIT_TARGET_POSITION = 50; - private const double time_span_default = 1500; - private const double time_span_min = 50; - private const double time_span_max = 10000; - private const double time_span_step = 50; - /// /// Default column keys, expanding outwards from the middle as more column are added. /// E.g. 2 columns use FJ, 4 columns use DFJK, 6 use SDFJKL, etc... @@ -56,13 +52,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly FlowContainer columns; public IEnumerable Columns => columns.Children; - private readonly BindableDouble visibleTimeRange = new BindableDouble(time_span_default) - { - MinValue = time_span_min, - MaxValue = time_span_max - }; - - private readonly SpeedAdjustmentCollection barLineContainer; + private readonly ScrollingHitObjectContainer barLineContainer; private List normalColumnColours = new List(); private Color4 specialColumnColour; @@ -70,6 +60,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int columnCount; public ManiaPlayfield(int columnCount) + : base(Axes.Y) { this.columnCount = columnCount; @@ -120,13 +111,13 @@ namespace osu.Game.Rulesets.Mania.UI Padding = new MarginPadding { Top = HIT_TARGET_POSITION }, Children = new[] { - barLineContainer = new SpeedAdjustmentCollection(Axes.Y) + barLineContainer = new ScrollingHitObjectContainer(Axes.Y) { Name = "Bar lines", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Y, - VisibleTimeRange = visibleTimeRange + VisibleTimeRange = VisibleTimeRange // Width is set in the Update method } } @@ -136,7 +127,7 @@ namespace osu.Game.Rulesets.Mania.UI }; for (int i = 0; i < columnCount; i++) - columns.Add(new Column { VisibleTimeRange = visibleTimeRange }); + columns.Add(new Column { VisibleTimeRange = VisibleTimeRange }); } [BackgroundDependencyLoader] @@ -211,30 +202,7 @@ namespace osu.Game.Rulesets.Mania.UI public override void Add(DrawableHitObject h) => Columns.ElementAt(h.HitObject.Column).Add(h); public void Add(DrawableBarLine barline) => barLineContainer.Add(barline); - public void Add(SpeedAdjustmentContainer speedAdjustment) => barLineContainer.Add(speedAdjustment); - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - if (state.Keyboard.ControlPressed) - { - switch (args.Key) - { - case Key.Minus: - transformVisibleTimeRangeTo(visibleTimeRange + time_span_step, 200, Easing.OutQuint); - break; - case Key.Plus: - transformVisibleTimeRangeTo(visibleTimeRange - time_span_step, 200, Easing.OutQuint); - break; - } - } - - return false; - } - - private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) - { - this.TransformTo(nameof(visibleTimeRange), newTimeRange, duration, easing); - } + public void Add(SpeedAdjustmentContainer speedAdjustment) => barLineContainer.AddSpeedAdjustment(speedAdjustment); protected override void Update() { diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index c412530b15..daeca5a910 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Timing /// public abstract class ScrollingContainer : Container { - private readonly BindableDouble visibleTimeRange = new BindableDouble(); + private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; /// /// Gets or sets the range of time that is visible by the length of this container. /// diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentCollection.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentCollection.cs deleted file mode 100644 index 22213be740..0000000000 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentCollection.cs +++ /dev/null @@ -1,133 +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 System.Linq; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A collection of s. - /// - /// - /// This container redirects any 's added to it to the - /// which provides the speed adjustment active at the start time of the hit object. Furthermore, this container provides the - /// necessary for the contained s. - /// - /// - public class SpeedAdjustmentCollection : Container - { - private readonly BindableDouble visibleTimeRange = new BindableDouble(); - /// - /// Gets or sets the range of time that is visible by the length of this container. - /// For example, only hit objects with start time less than or equal to 1000 will be visible with = 1000. - /// - public Bindable VisibleTimeRange - { - get { return visibleTimeRange; } - set { visibleTimeRange.BindTo(value); } - } - - protected override int Compare(Drawable x, Drawable y) - { - var xSpeedAdjust = x as SpeedAdjustmentContainer; - var ySpeedAdjust = y as SpeedAdjustmentContainer; - - // If either of the two drawables are not hit objects, fall back to the base comparer - if (xSpeedAdjust?.ControlPoint == null || ySpeedAdjust?.ControlPoint == null) - return CompareReverseChildID(x, y); - - // Compare by start time - int i = ySpeedAdjust.ControlPoint.StartTime.CompareTo(xSpeedAdjust.ControlPoint.StartTime); - - return i != 0 ? i : CompareReverseChildID(x, y); - } - - /// - /// Hit objects that are to be re-processed on the next update. - /// - private readonly Queue queuedHitObjects = new Queue(); - - private readonly Axes scrollingAxes; - - /// - /// Creates a new . - /// - /// The axes upon which hit objects should appear to scroll inside this container. - public SpeedAdjustmentCollection(Axes scrollingAxes) - { - this.scrollingAxes = scrollingAxes; - } - - public override void Add(SpeedAdjustmentContainer speedAdjustment) - { - speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); - speedAdjustment.ScrollingAxes = scrollingAxes; - base.Add(speedAdjustment); - } - - /// - /// Adds a hit object to this . The hit objects will be kept in a queue - /// and will be processed when new s are added to this . - /// - /// The hit object to add. - public void Add(DrawableHitObject hitObject) - { - if (!(hitObject is IScrollingHitObject)) - throw new InvalidOperationException($"Hit objects added to a {nameof(SpeedAdjustmentCollection)} must implement {nameof(IScrollingHitObject)}."); - - queuedHitObjects.Enqueue(hitObject); - } - - protected override void Update() - { - base.Update(); - - // Todo: At the moment this is going to re-process every single Update, however this will only be a null-op - // when there are no SpeedAdjustmentContainers available. This should probably error or something, but it's okay for now. - - // An external count is kept because hit objects that can't be added are re-queued - int count = queuedHitObjects.Count; - while (count-- > 0) - { - var hitObject = queuedHitObjects.Dequeue(); - - var target = adjustmentContainerFor(hitObject); - if (target == null) - { - // We can't add this hit object to a speed adjustment container yet, so re-queue it - // for re-processing when the layout next invalidated - queuedHitObjects.Enqueue(hitObject); - continue; - } - - if (hitObject.RelativePositionAxes != target.ScrollingAxes) - throw new InvalidOperationException($"Make sure to set all {nameof(DrawableHitObject)}'s {nameof(RelativePositionAxes)} are equal to the correct axes of scrolling ({target.ScrollingAxes})."); - - target.Add(hitObject); - } - } - - /// - /// Finds the which provides the speed adjustment active at the start time - /// of a hit object. If there is no active at the start time of the hit object, - /// then the first (time-wise) speed adjustment is returned. - /// - /// The hit object to find the active for. - /// The active at 's start time. Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => Children.FirstOrDefault(c => c.CanContain(hitObject)) ?? Children.LastOrDefault(); - - /// - /// 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) => Children.FirstOrDefault(c => c.CanContain(time)) ?? Children.LastOrDefault(); - } -} diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index 3c0ba86db3..6be721f6e7 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Timing /// public class SpeedAdjustmentContainer : Container { - private readonly Bindable visibleTimeRange = new Bindable(); + private readonly Bindable visibleTimeRange = new Bindable { Default = 1000 }; /// /// Gets or sets the range of time that is visible by the length of this container. /// diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index ff321a18a5..5f07df5088 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - protected HitObjectContainer> HitObjects; + public HitObjectContainer> HitObjects { get; protected set; } internal Container ScaledContent; @@ -99,7 +99,8 @@ namespace osu.Game.Rulesets.UI protected override Vector2 DrawScale => CustomWidth.HasValue ? new Vector2(DrawSize.X / CustomWidth.Value) : base.DrawScale; } - public class HitObjectContainer : Container where U : Drawable + public class HitObjectContainer : Container + where U : Drawable { } } diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs new file mode 100644 index 0000000000..b765b533a0 --- /dev/null +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -0,0 +1,190 @@ +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.Input; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Timing; + +namespace osu.Game.Rulesets.UI +{ + public class ScrollingPlayfield : Playfield + where TObject : HitObject + where TJudgement : Judgement + { + private const double time_span_default = 1500; + private const double time_span_min = 50; + private const double time_span_max = 10000; + private const double time_span_step = 50; + + /// + /// Gets or sets the range of time that is visible by the length of this playfield the scrolling axis direction. + /// For example, only hit objects with start time less than or equal to 1000 will be visible with = 1000. + /// + private readonly BindableDouble visibleTimeRange = new BindableDouble(time_span_default) + { + Default = time_span_default, + MinValue = time_span_min, + MaxValue = time_span_max + }; + + public BindableDouble VisibleTimeRange + { + get { return visibleTimeRange; } + set { visibleTimeRange.BindTo(value); } + } + + public new readonly ScrollingHitObjectContainer HitObjects; + + protected ScrollingPlayfield(Axes scrollingAxes, float? customWidth = null) + : base(customWidth) + { + base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) + { + RelativeSizeAxes = Axes.Both, + VisibleTimeRange = VisibleTimeRange + }; + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (state.Keyboard.ControlPressed) + { + switch (args.Key) + { + case Key.Minus: + transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); + break; + case Key.Plus: + transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); + break; + } + } + + return false; + } + + private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) + { + this.TransformTo(nameof(VisibleTimeRange), newTimeRange, duration, easing); + } + + /// + /// A collection of s. + /// + /// + /// This container redirects any 's added to it to the + /// which provides the speed adjustment active at the start time of the hit object. Furthermore, this container provides the + /// necessary for the contained s. + /// + /// + public class ScrollingHitObjectContainer : HitObjectContainer> + { + private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; + /// + /// Gets or sets the range of time that is visible by the length of this container. + /// For example, only hit objects with start time less than or equal to 1000 will be visible with = 1000. + /// + public Bindable VisibleTimeRange + { + get { return visibleTimeRange; } + set { visibleTimeRange.BindTo(value); } + } + + protected override Container> Content => content; + /// + /// The following is never used - it only exists for the purpose of being able to use AddInternal below. + /// + private Container> content; + + /// + /// Hit objects that are to be re-processed on the next update. + /// + private readonly Queue> queuedHitObjects = new Queue>(); + + private readonly Axes scrollingAxes; + + /// + /// Creates a new . + /// + /// The axes upon which hit objects should appear to scroll inside this container. + public ScrollingHitObjectContainer(Axes scrollingAxes) + { + this.scrollingAxes = scrollingAxes; + + content = new Container>(); + } + + public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) + { + speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); + speedAdjustment.ScrollingAxes = scrollingAxes; + AddInternal(speedAdjustment); + } + + /// + /// Adds a hit object to this . The hit objects will be kept in a queue + /// and will be processed when 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)}."); + + queuedHitObjects.Enqueue(hitObject); + } + + protected override void Update() + { + base.Update(); + + // Todo: At the moment this is going to re-process every single Update, however this will only be a null-op + // when there are no SpeedAdjustmentContainers available. This should probably error or something, but it's okay for now. + + // An external count is kept because hit objects that can't be added are re-queued + int count = queuedHitObjects.Count; + while (count-- > 0) + { + var hitObject = queuedHitObjects.Dequeue(); + + var target = adjustmentContainerFor(hitObject); + if (target == null) + { + // We can't add this hit object to a speed adjustment container yet, so re-queue it + // for re-processing when the layout next invalidated + queuedHitObjects.Enqueue(hitObject); + continue; + } + + if (hitObject.RelativePositionAxes != target.ScrollingAxes) + throw new InvalidOperationException($"Make sure to set all {nameof(DrawableHitObject)}'s {nameof(RelativePositionAxes)} are equal to the correct axes of scrolling ({target.ScrollingAxes})."); + + target.Add(hitObject); + } + } + + /// + /// Finds the which provides the speed adjustment active at the start time + /// of a hit object. If there is no active at the start time of the hit object, + /// then the first (time-wise) speed adjustment is returned. + /// + /// The hit object to find the active for. + /// The active at 's start time. Null if there are no speed adjustments. + private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => InternalChildren.OfType().FirstOrDefault(c => c.CanContain(hitObject)) ?? InternalChildren.OfType().LastOrDefault(); + + /// + /// 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) => InternalChildren.OfType().FirstOrDefault(c => c.CanContain(time)) ?? InternalChildren.OfType().LastOrDefault(); + } + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs b/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs index 2dadbb04d0..5d6293c802 100644 --- a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs +++ b/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Lists; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.UI public abstract class SpeedAdjustedHitRenderer : HitRenderer where TObject : HitObject where TJudgement : Judgement - where TPlayfield : SpeedAdjustedPlayfield + where TPlayfield : ScrollingPlayfield { protected readonly SortedList DefaultControlPoints = new SortedList(Comparer.Default); @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.UI [BackgroundDependencyLoader] private void load() { - ApplySpeedAdjustments(); + DefaultControlPoints.ForEach(c => ApplySpeedAdjustment(c)); } protected override void ApplyBeatmap() @@ -98,9 +99,11 @@ namespace osu.Game.Rulesets.UI return new MultiplierControlPoint(time, DefaultControlPoints[index].DeepClone()); } - /// - /// Applies speed changes to the playfield. - /// - protected abstract void ApplySpeedAdjustments(); + protected virtual void ApplySpeedAdjustment(MultiplierControlPoint controlPoint) + { + Playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint)); + } + + protected abstract SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint); } } diff --git a/osu.Game/Rulesets/UI/SpeedAdjustedPlayfield.cs b/osu.Game/Rulesets/UI/SpeedAdjustedPlayfield.cs deleted file mode 100644 index 1d1f890a6e..0000000000 --- a/osu.Game/Rulesets/UI/SpeedAdjustedPlayfield.cs +++ /dev/null @@ -1,15 +0,0 @@ -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; - -namespace osu.Game.Rulesets.UI -{ - public class SpeedAdjustedPlayfield : Playfield - where TObject : HitObject - where TJudgement : Judgement - { - protected SpeedAdjustedPlayfield(float? customWidth = null) - : base(customWidth) - { - } - } -} \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 075f0732f7..342a02ba60 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -230,7 +230,6 @@ - @@ -341,7 +340,7 @@ - + From 554d0d6fb8fa7b7dbd8c3f8454575ed1bfeda2b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Aug 2017 19:37:20 +0900 Subject: [PATCH 05/67] Update basic structure of Catch project --- .../Beatmaps/CatchBeatmapConverter.cs | 9 +- .../Objects/Drawable/DrawableFruit.cs | 83 +++++++++++++++---- .../UI/CatchHitRenderer.cs | 9 +- 3 files changed, 85 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index f9859cd244..40180ac3a0 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -8,6 +8,7 @@ using System; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -17,7 +18,13 @@ namespace osu.Game.Rulesets.Catch.Beatmaps protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) { - yield return null; + var catchHit = original as CatchBaseHit; + + yield return catchHit ?? new Fruit + { + StartTime = original.StartTime, + Position = ((IHasXPosition)original).X / OsuPlayfield.BASE_SIZE.X + }; } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 3e7d9bd6d7..01f9a78c8e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -3,33 +3,88 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Shapes; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Objects.Drawables; using OpenTK; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - internal class DrawableFruit : Sprite + internal class DrawableFruit : DrawableHitObject { - //private readonly CatchBaseHit h; - - public DrawableFruit(CatchBaseHit h) + public DrawableFruit(CatchBaseHit h) : base(h) { - //this.h = h; - Origin = Anchor.Centre; - Scale = new Vector2(0.1f); - RelativePositionAxes = Axes.Y; + Size = new Vector2(50); + RelativePositionAxes = Axes.Both; Position = new Vector2(h.Position, -0.1f); + Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; + + Alpha = 0; } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load() { - Texture = textures.Get(@"Menu/logo"); + Children = new Framework.Graphics.Drawable[] + { + new Circle + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Scale = new Vector2(0.12f), + Y = 0.08f, + }, + new Circle + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Scale = new Vector2(0.32f), + Position = new Vector2(-0.16f, 0.3f), + }, + new Circle + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Scale = new Vector2(0.32f), + Position = new Vector2(0.16f, 0.3f), + }, + new Circle + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Scale = new Vector2(0.32f), + Position = new Vector2(0, 0.6f), + }, + }; + + Alpha = 0; + } + + protected override CatchJudgement CreateJudgement() => new CatchJudgement(); + + private const float preempt = 1000; + + protected override void UpdateState(ArmedState state) + { + using (BeginAbsoluteSequence(HitObject.StartTime - preempt)) + { + // default state + this.MoveToY(-0.1f).FadeOut(); + + // animation + this.FadeIn(200).MoveToY(0.9f, preempt); + } - //Transforms.Add(new TransformPosition { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position, -0.1f), EndValue = new Vector2(h.Position, 0.9f) }); - //Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 }); Expire(true); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs index 179440adb3..cd6adfeea9 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -26,6 +27,12 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(); - protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) => null; + protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) + { + if (h is Fruit) + return new DrawableFruit(h); + + return null; + } } } From 81b738f68c8d1245c0b34f557538e1fcc01c9c72 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Aug 2017 20:28:24 +0900 Subject: [PATCH 06/67] Add basic Catcher --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 18 ++++- osu.Game.Rulesets.Catch/UI/Catcher.cs | 73 +++++++++++++++++++ .../osu.Game.Rulesets.Catch.csproj | 1 + 3 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Catch/UI/Catcher.cs diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 8be52150fc..3aa5b3f1e3 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -18,7 +18,23 @@ namespace osu.Game.Rulesets.Catch.UI Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; - Add(new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.5f }); + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f + }, + new Catcher + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.2f), + FillMode = FillMode.Fit, + Origin = Anchor.TopCentre, + Position = new Vector2(0.5f, 0.9f), + } + }; } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs new file mode 100644 index 0000000000..42e4f03da1 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -0,0 +1,73 @@ +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Input; +using OpenTK; +using OpenTK.Input; + +namespace osu.Game.Rulesets.Catch.UI +{ + public class Catcher : Sprite + { + public override bool HandleInput => true; + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); + } + + private bool leftPressed; + private bool rightPressed; + + private int currentDirection; + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) return true; + + switch (args.Key) + { + case Key.Left: + currentDirection = -1; + leftPressed = true; + return true; + case Key.Right: + currentDirection = 1; + rightPressed = true; + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + { + switch (args.Key) + { + case Key.Left: + currentDirection = rightPressed ? 1 : 0; + leftPressed = false; + + return true; + case Key.Right: + currentDirection = leftPressed ? -1 : 0; + rightPressed = false; + return true; + } + + return base.OnKeyUp(state, args); + } + + protected override void Update() + { + base.Update(); + + if (currentDirection == 0) return; + + Scale = new Vector2(Scale.X * (Math.Sign(currentDirection) != Math.Sign(Scale.X) ? -1 : 1), Scale.Y); + X = (float)MathHelper.Clamp(X + currentDirection * Clock.ElapsedFrameTime / 1000, 0, 1); + } + } +} diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 83996df41a..f84f9302bb 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -57,6 +57,7 @@ + From 51d2b9c35ce255e161cdd5c00a874a2b1587a7f9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Aug 2017 20:41:38 +0900 Subject: [PATCH 07/67] Tidy up visually --- .../Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 01f9a78c8e..9b4a9bd957 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -82,7 +82,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable this.MoveToY(-0.1f).FadeOut(); // animation - this.FadeIn(200).MoveToY(0.9f, preempt); + this.FadeIn(200).MoveToY(1, preempt); } Expire(true); diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 3aa5b3f1e3..ba766fa61b 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.Framework.Graphics.Shapes; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.UI; using OpenTK; @@ -14,17 +13,13 @@ namespace osu.Game.Rulesets.Catch.UI { public CatchPlayfield() { - Size = new Vector2(1, 0.9f); - Anchor = Anchor.BottomCentre; - Origin = Anchor.BottomCentre; + Size = new Vector2(1); + + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.5f - }, new Catcher { RelativePositionAxes = Axes.Both, @@ -32,7 +27,7 @@ namespace osu.Game.Rulesets.Catch.UI Scale = new Vector2(0.2f), FillMode = FillMode.Fit, Origin = Anchor.TopCentre, - Position = new Vector2(0.5f, 0.9f), + Position = new Vector2(0.5f, 1), } }; } From c9300852139dbe6c5d0ddd843c785721f2acd33c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Aug 2017 08:32:38 +0900 Subject: [PATCH 08/67] Add glow --- .../Objects/Drawable/DrawableFruit.cs | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 9b4a9bd957..be51f60c46 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -2,17 +2,37 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; +using osu.Game.Graphics; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { internal class DrawableFruit : DrawableHitObject { + private class Pulp : Circle, IHasAccentColour + { + public Pulp() + { + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 5, + Colour = AccentColour.Opacity(0.5f), + }; + } + + public Color4 AccentColour { get; set; } = Color4.White; + } + + public DrawableFruit(CatchBaseHit h) : base(h) { Origin = Anchor.Centre; @@ -29,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { Children = new Framework.Graphics.Drawable[] { - new Circle + new Pulp { RelativePositionAxes = Axes.Both, RelativeSizeAxes = Axes.Both, @@ -38,7 +58,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Scale = new Vector2(0.12f), Y = 0.08f, }, - new Circle + new Pulp { RelativePositionAxes = Axes.Both, RelativeSizeAxes = Axes.Both, @@ -47,7 +67,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Scale = new Vector2(0.32f), Position = new Vector2(-0.16f, 0.3f), }, - new Circle + new Pulp { RelativePositionAxes = Axes.Both, RelativeSizeAxes = Axes.Both, @@ -56,7 +76,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Scale = new Vector2(0.32f), Position = new Vector2(0.16f, 0.3f), }, - new Circle + new Pulp { RelativePositionAxes = Axes.Both, RelativeSizeAxes = Axes.Both, From e1dfe364b22690d5eada9900119b3efca2879a5e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 14:07:49 +0900 Subject: [PATCH 09/67] Fix lifetime performance regression. --- .../Objects/Drawables/DrawableScrollingHitObject.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs index 8dc17b9542..52b8d3e12d 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs @@ -22,20 +22,22 @@ namespace osu.Game.Rulesets.Objects.Drawables { } + private double? lifetimeStart; public override double LifetimeStart { - get { return Math.Min(HitObject.StartTime - LifetimeOffset, base.LifetimeStart); } - set { base.LifetimeStart = value; } + 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 Math.Max(endTime + LifetimeOffset, base.LifetimeEnd); + return lifetimeEnd ?? endTime + LifetimeOffset; } - set { base.LifetimeEnd = value; } + set { lifetimeEnd = value; } } protected override void AddNested(DrawableHitObject h) From 376f99c1e3f05ac2eaa773d74ba4db25b0fd7bb8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 14:32:55 +0900 Subject: [PATCH 10/67] Make VisibleTimeRange transform work again. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index b765b533a0..d21b07490a 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -5,7 +5,9 @@ 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.MathUtils; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -71,7 +73,23 @@ namespace osu.Game.Rulesets.UI private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) { - this.TransformTo(nameof(VisibleTimeRange), newTimeRange, duration, easing); + this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); + } + + private class TransformVisibleTimeRange : Transform> + { + private double valueAt(double time) + { + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + + public override string TargetMember => "VisibleTimeRange.Value"; + + protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time); + protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; } /// From c6447e40f92368fef7ca796e200a80ada951e949 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 14:56:26 +0900 Subject: [PATCH 11/67] Reduce implementation overhead for nested playfields (e.g. playfield + columns). --- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 6 ------ osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 15 +++++++++------ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 11 +++++++++++ osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs | 13 +++++++------ 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 04185f0872..a34765448c 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -114,12 +114,6 @@ namespace osu.Game.Rulesets.Mania.UI protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(1, 0.8f); - protected override void ApplySpeedAdjustment(MultiplierControlPoint controlPoint) - { - base.ApplySpeedAdjustment(controlPoint); - Playfield.Columns.ForEach(c => c.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint))); - } - protected override SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Basic); } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 3b1dc58e4f..4b240e4659 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -52,7 +52,8 @@ namespace osu.Game.Rulesets.Mania.UI private readonly FlowContainer columns; public IEnumerable Columns => columns.Children; - private readonly ScrollingHitObjectContainer barLineContainer; + protected override Container Content => barLineContainer; + private readonly Container barLineContainer; private List normalColumnColours = new List(); private Color4 specialColumnColour; @@ -67,7 +68,7 @@ namespace osu.Game.Rulesets.Mania.UI if (columnCount <= 0) throw new ArgumentException("Can't have zero or fewer columns."); - Children = new Drawable[] + InternalChildren = new Drawable[] { new Container { @@ -111,13 +112,12 @@ namespace osu.Game.Rulesets.Mania.UI Padding = new MarginPadding { Top = HIT_TARGET_POSITION }, Children = new[] { - barLineContainer = new ScrollingHitObjectContainer(Axes.Y) + barLineContainer = new Container { Name = "Bar lines", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Y, - VisibleTimeRange = VisibleTimeRange // Width is set in the Update method } } @@ -127,7 +127,11 @@ namespace osu.Game.Rulesets.Mania.UI }; for (int i = 0; i < columnCount; i++) - columns.Add(new Column { VisibleTimeRange = VisibleTimeRange }); + { + var c = new Column { VisibleTimeRange = VisibleTimeRange }; + columns.Add(c); + AddNested(c); + } } [BackgroundDependencyLoader] @@ -202,7 +206,6 @@ namespace osu.Game.Rulesets.Mania.UI public override void Add(DrawableHitObject h) => Columns.ElementAt(h.HitObject.Column).Add(h); public void Add(DrawableBarLine barline) => barLineContainer.Add(barline); - public void Add(SpeedAdjustmentContainer speedAdjustment) => barLineContainer.AddSpeedAdjustment(speedAdjustment); protected override void Update() { diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index d21b07490a..8850bd6b96 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -53,6 +53,17 @@ namespace osu.Game.Rulesets.UI }; } + private List> nestedPlayfields; + public IEnumerable> NestedPlayfields => nestedPlayfields; + + protected void AddNested(ScrollingPlayfield otherPlayfield) + { + if (nestedPlayfields == null) + nestedPlayfields = new List>(); + + nestedPlayfields.Add(otherPlayfield); + } + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { if (state.Keyboard.ControlPressed) diff --git a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs b/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs index 5d6293c802..4a560748c1 100644 --- a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs +++ b/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs @@ -35,7 +35,13 @@ namespace osu.Game.Rulesets.UI [BackgroundDependencyLoader] private void load() { - DefaultControlPoints.ForEach(c => ApplySpeedAdjustment(c)); + DefaultControlPoints.ForEach(c => applySpeedAdjustment(c, Playfield)); + } + + private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield) + { + playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint)); + playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p)); } protected override void ApplyBeatmap() @@ -99,11 +105,6 @@ namespace osu.Game.Rulesets.UI return new MultiplierControlPoint(time, DefaultControlPoints[index].DeepClone()); } - protected virtual void ApplySpeedAdjustment(MultiplierControlPoint controlPoint) - { - Playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint)); - } - protected abstract SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint); } } From b71caca131c42c6b34cc0717483f754e111b2ec0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Aug 2017 15:09:31 +0900 Subject: [PATCH 12/67] Expand abilities of catcher --- osu.Desktop.Tests/Visual/TestCaseCatcher.cs | 26 ++++ osu.Desktop.Tests/osu.Desktop.Tests.csproj | 1 + osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 10 +- osu.Game.Rulesets.Catch/UI/Catcher.cs | 73 --------- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 143 ++++++++++++++++++ .../osu.Game.Rulesets.Catch.csproj | 2 +- 6 files changed, 175 insertions(+), 80 deletions(-) create mode 100644 osu.Desktop.Tests/Visual/TestCaseCatcher.cs delete mode 100644 osu.Game.Rulesets.Catch/UI/Catcher.cs create mode 100644 osu.Game.Rulesets.Catch/UI/CatcherArea.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseCatcher.cs b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs new file mode 100644 index 0000000000..eb714c9994 --- /dev/null +++ b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs @@ -0,0 +1,26 @@ +using osu.Framework.Graphics; +using osu.Game.Rulesets.Catch.UI; +using OpenTK; + +namespace osu.Desktop.Tests.Visual +{ + internal class TestCaseCatcher : OsuTestCase + { + protected override void LoadComplete() + { + base.LoadComplete(); + + Children = new Drawable[] + { + new CatcherArea + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Size = new Vector2(1, 0.2f), + } + }; + } + } +} diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index aa862498d1..ba8ae06863 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -71,6 +71,7 @@ + diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index ba766fa61b..03aabc5632 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -20,14 +20,12 @@ namespace osu.Game.Rulesets.Catch.UI Children = new Drawable[] { - new Catcher + new CatcherArea { - RelativePositionAxes = Axes.Both, RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.2f), - FillMode = FillMode.Fit, - Origin = Anchor.TopCentre, - Position = new Vector2(0.5f, 1), + Anchor = Anchor.BottomLeft, + Origin = Anchor.TopLeft, + Height = 0.3f } }; } diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs deleted file mode 100644 index 42e4f03da1..0000000000 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using osu.Framework.Allocation; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Framework.Input; -using OpenTK; -using OpenTK.Input; - -namespace osu.Game.Rulesets.Catch.UI -{ - public class Catcher : Sprite - { - public override bool HandleInput => true; - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); - } - - private bool leftPressed; - private bool rightPressed; - - private int currentDirection; - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - if (args.Repeat) return true; - - switch (args.Key) - { - case Key.Left: - currentDirection = -1; - leftPressed = true; - return true; - case Key.Right: - currentDirection = 1; - rightPressed = true; - return true; - } - - return base.OnKeyDown(state, args); - } - - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) - { - switch (args.Key) - { - case Key.Left: - currentDirection = rightPressed ? 1 : 0; - leftPressed = false; - - return true; - case Key.Right: - currentDirection = leftPressed ? -1 : 0; - rightPressed = false; - return true; - } - - return base.OnKeyUp(state, args); - } - - protected override void Update() - { - base.Update(); - - if (currentDirection == 0) return; - - Scale = new Vector2(Scale.X * (Math.Sign(currentDirection) != Math.Sign(Scale.X) ? -1 : 1), Scale.Y); - X = (float)MathHelper.Clamp(X + currentDirection * Clock.ElapsedFrameTime / 1000, 0, 1); - } - } -} diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs new file mode 100644 index 0000000000..cb979ffc55 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -0,0 +1,143 @@ +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Input; +using OpenTK; +using OpenTK.Input; + +namespace osu.Game.Rulesets.Catch.UI +{ + public class CatcherArea : Container + { + public override bool HandleInput => true; + + private Sprite catcher; + + private Drawable createAdditiveFrame() => new Sprite + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + + Texture = catcher.Texture, + BlendingMode = BlendingMode.Additive, + Position = catcher.Position, + Scale = catcher.Scale, + }; + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Children = new Drawable[] + { + catcher = new Sprite + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + + X = 0.5f, + Texture = textures.Get(@"Play/Catch/fruit-catcher-idle"), + }, + }; + } + + private bool leftPressed; + private bool rightPressed; + + private int currentDirection; + + private bool dashing; + + protected bool Dashing + { + get + { + return dashing; + } + set + { + if (value == dashing) return; + + dashing = value; + + if (dashing) + Schedule(addAdditiveSprite); + } + } + + private void addAdditiveSprite() + { + if (!dashing) return; + + var additive = createAdditiveFrame(); + + Add(additive); + + additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); + + Scheduler.AddDelayed(addAdditiveSprite, 50); + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) return true; + + switch (args.Key) + { + case Key.Left: + currentDirection = -1; + leftPressed = true; + return true; + case Key.Right: + currentDirection = 1; + rightPressed = true; + return true; + case Key.ShiftLeft: + Dashing = true; + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + { + switch (args.Key) + { + case Key.Left: + currentDirection = rightPressed ? 1 : 0; + leftPressed = false; + return true; + case Key.Right: + currentDirection = leftPressed ? -1 : 0; + rightPressed = false; + return true; + case Key.ShiftLeft: + Dashing = false; + return true; + } + + return base.OnKeyUp(state, args); + } + + protected override void Update() + { + base.Update(); + + if (currentDirection == 0) return; + + float speed = Dashing ? 1.5f : 1; + + catcher.Scale = new Vector2(Math.Sign(currentDirection), 1); + catcher.X = (float)MathHelper.Clamp(catcher.X + currentDirection * Clock.ElapsedFrameTime / 1800 * speed, 0, 1); + } + } +} diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index f84f9302bb..003fe2763e 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -57,7 +57,7 @@ - + From 068dfcb19aeeaf1ce1a3bbb29b9451625771f2f5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 15:22:31 +0900 Subject: [PATCH 13/67] Default CreateSpeedAdjustmentContainer implementation. --- osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs | 2 +- osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index 6be721f6e7..c7249d5b84 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Timing /// Creates a new . /// /// The which provides the speed adjustments for this container. - protected SpeedAdjustmentContainer(MultiplierControlPoint controlPoint) + public SpeedAdjustmentContainer(MultiplierControlPoint controlPoint) { ControlPoint = controlPoint; diff --git a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs b/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs index 4a560748c1..5f8bebc213 100644 --- a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs +++ b/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs @@ -86,6 +86,9 @@ namespace osu.Game.Rulesets.UI .GroupBy(s => s.TimingPoint.BeatLength * s.DifficultyPoint.SpeedMultiplier).Select(g => g.First()); DefaultControlPoints.AddRange(timingChanges); + + if (DefaultControlPoints.Count == 0) + DefaultControlPoints.Add(new MultiplierControlPoint()); } /// @@ -105,6 +108,6 @@ namespace osu.Game.Rulesets.UI return new MultiplierControlPoint(time, DefaultControlPoints[index].DeepClone()); } - protected abstract SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint); + protected virtual SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new SpeedAdjustmentContainer(controlPoint); } } From 725a69d9736a214e46855954ca6a82f86508ff17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Aug 2017 16:02:14 +0900 Subject: [PATCH 14/67] Begin conversion --- .../Beatmaps/CatchBeatmapConverter.cs | 13 ++++++++----- .../Objects/Drawable/DrawableFruit.cs | 5 +++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 40180ac3a0..6a20fa525e 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -16,14 +16,17 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; - protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) + protected override IEnumerable ConvertHitObject(HitObject obj, Beatmap beatmap) { - var catchHit = original as CatchBaseHit; + var distanceData = obj as IHasDistance; + var repeatsData = obj as IHasRepeats; + var endTimeData = obj as IHasEndTime; + var curveData = obj as IHasCurve; - yield return catchHit ?? new Fruit + yield return new Fruit { - StartTime = original.StartTime, - Position = ((IHasXPosition)original).X / OsuPlayfield.BASE_SIZE.X + StartTime = obj.StartTime, + Position = ((IHasXPosition)obj).X / OsuPlayfield.BASE_SIZE.X }; } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index be51f60c46..aa92f36d23 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -49,6 +49,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { Children = new Framework.Graphics.Drawable[] { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Red, + }, new Pulp { RelativePositionAxes = Axes.Both, From a3efca9c357874b3d15cd0a75a43b5b64cb92a06 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 16:02:38 +0900 Subject: [PATCH 15/67] Reduce implementation overhead in actually positioning hitobjects and making them scroll. --- .../Visual/TestCaseScrollingHitObjects.cs | 16 +--------------- .../Objects/Drawables/DrawableManiaHitObject.cs | 3 --- osu.Game.Rulesets.Mania/UI/Column.cs | 2 -- .../Drawables/DrawableScrollingHitObject.cs | 14 ++++++++++++++ .../Objects/Drawables/IScrollingHitObject.cs | 8 +++++++- osu.Game/Rulesets/Timing/ScrollingContainer.cs | 4 ++-- .../Rulesets/Timing/SpeedAdjustmentContainer.cs | 8 ++++++-- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 4 ++-- 8 files changed, 32 insertions(+), 27 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs index 6b30cc4f32..30ad5871f2 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -31,7 +31,6 @@ namespace osu.Desktop.Tests.Visual public TestCaseScrollingHitObjects() { OsuSpriteText timeRangeText; - ScrollingPlayfield.ScrollingHitObjectContainer scrollingHitObjectContainer; timeRangeBindable = new BindableDouble(2000) { @@ -71,12 +70,6 @@ namespace osu.Desktop.Tests.Visual RelativeSizeAxes = Axes.Both, Alpha = 0.25f }, - scrollingHitObjectContainer = new ScrollingPlayfield.ScrollingHitObjectContainer(Axes.Y) - { - RelativeSizeAxes = Axes.Both, - VisibleTimeRange = timeRangeBindable, - Masking = true, - }, new OsuSpriteText { Text = "t minus 0", @@ -111,17 +104,12 @@ namespace osu.Desktop.Tests.Visual }); timeRangeBindable.TriggerChange(); - - scrollingHitObjectContainer.AddSpeedAdjustment(new TestSpeedAdjustmentContainer(new MultiplierControlPoint())); - - AddStep("Add hit object", () => scrollingHitObjectContainer.Add(new TestDrawableHitObject(new HitObject { StartTime = Time.Current + 2000 }))); } protected override void Update() { base.Update(); - topTime.Text = Time.Current.ToString("#,#"); bottomTime.Text = (Time.Current + timeRangeBindable.Value).ToString("#,#"); } @@ -154,13 +142,11 @@ namespace osu.Desktop.Tests.Visual } } - private class TestDrawableHitObject : DrawableHitObject, IScrollingHitObject + private class TestDrawableHitObject : DrawableScrollingHitObject { private readonly Box background; private const float height = 14; - public BindableDouble LifetimeOffset { get; } = new BindableDouble(); - public TestDrawableHitObject(HitObject hitObject) : base(hitObject) { diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index cb1352fc4a..c1b2df8898 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -27,9 +27,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (key != null) Key.BindTo(key); - - RelativePositionAxes = Axes.Y; - Y = (float)HitObject.StartTime; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 424ed77783..694e8c8126 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -192,8 +192,6 @@ namespace osu.Game.Rulesets.Mania.UI } } - public void Add(SpeedAdjustmentContainer speedAdjustment) => HitObjects.AddSpeedAdjustment(speedAdjustment); - /// /// Adds a DrawableHitObject to this Playfield. /// diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs index 52b8d3e12d..ec206928b2 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Configuration; +using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; @@ -17,6 +18,19 @@ namespace osu.Game.Rulesets.Objects.Drawables { 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; + } + } + protected DrawableScrollingHitObject(TObject hitObject) : base(hitObject) { diff --git a/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs index 560f15f133..30b65237a4 100644 --- a/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// An interface that exposes properties required for scrolling hit objects to be properly displayed. /// - public interface IScrollingHitObject : IDrawable + internal interface IScrollingHitObject : IDrawable { /// /// Time offset before the hit object start time at which this becomes visible and the time offset @@ -21,5 +21,11 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// BindableDouble LifetimeOffset { get; } + + /// + /// Axes which this will scroll through. + /// This is set by the container which this scrolls through. + /// + Axes ScrollingAxes { set; } } } \ No newline at end of file diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index daeca5a910..dcedf102aa 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -53,6 +53,8 @@ namespace osu.Game.Rulesets.Timing /// internal MultiplierControlPoint ControlPoint; + private Cached durationBacking; + protected override int Compare(Drawable x, Drawable y) { var xHitObject = x as DrawableHitObject; @@ -93,8 +95,6 @@ namespace osu.Game.Rulesets.Timing base.InvalidateFromChild(invalidation); } - private Cached durationBacking; - private double computeDuration() { if (!Children.Any()) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index c7249d5b84..f3475621c7 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -37,7 +37,6 @@ namespace osu.Game.Rulesets.Timing /// /// Axes which the content of this container will scroll through. /// - /// public Axes ScrollingAxes { get; internal set; } public readonly MultiplierControlPoint ControlPoint; @@ -83,7 +82,12 @@ namespace osu.Game.Rulesets.Timing public override void Add(DrawableHitObject drawable) { var scrollingHitObject = drawable as IScrollingHitObject; - scrollingHitObject?.LifetimeOffset.BindTo(VisibleTimeRange); + + if (scrollingHitObject != null) + { + scrollingHitObject.LifetimeOffset.BindTo(VisibleTimeRange); + scrollingHitObject.ScrollingAxes = ScrollingAxes; + } base.Add(drawable); } diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 8850bd6b96..1dd4ac508b 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.UI set { visibleTimeRange.BindTo(value); } } - public new readonly ScrollingHitObjectContainer HitObjects; + internal new readonly ScrollingHitObjectContainer HitObjects; protected ScrollingPlayfield(Axes scrollingAxes, float? customWidth = null) : base(customWidth) @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.UI /// necessary for the contained s. /// /// - public class ScrollingHitObjectContainer : HitObjectContainer> + internal class ScrollingHitObjectContainer : HitObjectContainer> { private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; /// From fc252f88889a20985557d38bd4ab9451cfd4c824 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 16:24:51 +0900 Subject: [PATCH 16/67] Remove exception (this is set in SpeedAdjustmentContainer). --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 1dd4ac508b..27267f8a79 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -191,9 +191,6 @@ namespace osu.Game.Rulesets.UI continue; } - if (hitObject.RelativePositionAxes != target.ScrollingAxes) - throw new InvalidOperationException($"Make sure to set all {nameof(DrawableHitObject)}'s {nameof(RelativePositionAxes)} are equal to the correct axes of scrolling ({target.ScrollingAxes})."); - target.Add(hitObject); } } From 0d3797b497921362e9839e522d0212e93635364c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 16:25:06 +0900 Subject: [PATCH 17/67] Remove TestCaseScrollingHitObjects, replace with TestCaseScrollingPlayfield. --- .../Visual/TestCaseScrollingHitObjects.cs | 210 ------------------ .../Visual/TestCaseScrollingPlayfield.cs | 150 +++++++++++++ osu.Desktop.Tests/osu.Desktop.Tests.csproj | 2 +- 3 files changed, 151 insertions(+), 211 deletions(-) delete mode 100644 osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs create mode 100644 osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs deleted file mode 100644 index 30ad5871f2..0000000000 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingHitObjects.cs +++ /dev/null @@ -1,210 +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.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Timing; -using OpenTK; -using OpenTK.Graphics; -using osu.Game.Rulesets.UI; -using osu.Game.Rulesets.Judgements; -using System; - -namespace osu.Desktop.Tests.Visual -{ - public class TestCaseScrollingHitObjects : OsuTestCase - { - public override string Description => "SpeedAdjustmentContainer/ScrollingContainer"; - - private readonly BindableDouble timeRangeBindable; - private readonly OsuSpriteText bottomLabel; - private readonly SpriteText topTime; - private readonly SpriteText bottomTime; - - public TestCaseScrollingHitObjects() - { - OsuSpriteText timeRangeText; - - timeRangeBindable = new BindableDouble(2000) - { - MinValue = 200, - MaxValue = 4000, - }; - - SliderBar timeRange; - Add(timeRange = new BasicSliderBar - { - Size = new Vector2(200, 20), - SelectionColor = Color4.Pink, - KeyboardStep = 100 - }); - - Add(timeRangeText = new OsuSpriteText - { - X = 210, - TextSize = 16, - }); - - timeRange.Current.BindTo(timeRangeBindable); - timeRangeBindable.ValueChanged += v => timeRangeText.Text = $"Visible Range: {v:#,#.#}"; - timeRangeBindable.ValueChanged += v => bottomLabel.Text = $"t minus {v:#,#}"; - - AddRange(new Drawable[] - { - new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(100, 500), - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.25f - }, - new OsuSpriteText - { - Text = "t minus 0", - Margin = new MarginPadding(2), - TextSize = 14, - Anchor = Anchor.TopRight, - }, - bottomLabel = new OsuSpriteText - { - Text = "t minus x", - Margin = new MarginPadding(2), - TextSize = 14, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomLeft, - }, - topTime = new OsuSpriteText - { - Margin = new MarginPadding(2), - TextSize = 14, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopRight, - }, - bottomTime = new OsuSpriteText - { - Margin = new MarginPadding(2), - TextSize = 14, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomRight, - }, - } - } - }); - - timeRangeBindable.TriggerChange(); - } - - protected override void Update() - { - base.Update(); - - bottomTime.Text = (Time.Current + timeRangeBindable.Value).ToString("#,#"); - } - - private class TestSpeedAdjustmentContainer : SpeedAdjustmentContainer - { - public override bool RemoveWhenNotAlive => false; - - public TestSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) - : base(controlPoint) - { - } - - protected override ScrollingContainer CreateScrollingContainer() => new TestScrollingContainer(ControlPoint); - - private class TestScrollingContainer : ScrollingContainer - { - private readonly MultiplierControlPoint controlPoint; - - public TestScrollingContainer(MultiplierControlPoint controlPoint) - { - this.controlPoint = controlPoint; - } - - protected override void Update() - { - base.Update(); - - Y = (float)(controlPoint.StartTime - Time.Current); - } - } - } - - private class TestDrawableHitObject : DrawableScrollingHitObject - { - private readonly Box background; - private const float height = 14; - - public TestDrawableHitObject(HitObject hitObject) - : base(hitObject) - { - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; - RelativePositionAxes = Axes.Y; - - Y = (float)hitObject.StartTime; - - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.X, - Height = height, - }, - new Box - { - RelativeSizeAxes = Axes.X, - Colour = Color4.Cyan, - Height = 1, - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Colour = Color4.Black, - TextSize = height, - Font = @"Exo2.0-BoldItalic", - Text = $"{hitObject.StartTime:#,#}" - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - this.FadeInFromZero(250, Easing.OutQuint); - } - - protected override void Update() - { - base.Update(); - if (Time.Current >= HitObject.StartTime) - background.Colour = Color4.Red; - } - - protected override Judgement CreateJudgement() => new TestJudgement(); - - protected override void UpdateState(ArmedState state) - { - } - - private class TestJudgement : Judgement - { - public override string ResultString { get { throw new NotImplementedException(); } } - public override string MaxResultString { get { throw new NotImplementedException(); } } - } - } - } -} diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs new file mode 100644 index 0000000000..07f59fe876 --- /dev/null +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using OpenTK; +using osu.Desktop.Tests.Beatmaps; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Timing; +using osu.Game.Rulesets.UI; + +namespace osu.Desktop.Tests.Visual +{ + /// + /// The most minimal implementation of a playfield with scrolling hit objects. + /// + public class TestCaseScrollingPlayfield : TestCase + { + 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 + { + Difficulty = new BeatmapDifficulty(), + Metadata = new BeatmapMetadata + { + Artist = @"Unknown", + Title = @"Sample Beatmap", + Author = @"peppy", + } + } + }; + + WorkingBeatmap beatmap = new TestWorkingBeatmap(b); + + Add(new TestHitRenderer(beatmap, true)); + } + + private class TestHitRenderer : SpeedAdjustedHitRenderer + { + public TestHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(beatmap, isForCurrentRuleset) + { + } + + public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor(); + + protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); + + protected override Playfield CreatePlayfield() => new TestPlayfield(); + + protected override DrawableHitObject GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(h); + } + + private class TestScoreProcessor : ScoreProcessor + { + protected override void OnNewJudgement(TestJudgement 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(TestHitObject hitObject) + : base(hitObject) + { + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + + AutoSizeAxes = Axes.Both; + + Add(new Circle + { + Size = new Vector2(50) + }); + } + + protected override TestJudgement CreateJudgement() => new TestJudgement(); + + protected override void UpdateState(ArmedState state) + { + } + } + + private class TestPlayfield : ScrollingPlayfield + { + protected override Container Content => content; + private readonly Container content; + + public TestPlayfield() + : base(Axes.X) + { + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f + }, + content = new Container { RelativeSizeAxes = Axes.Both } + }; + } + } + + + private class TestHitObject : HitObject + { + } + + private class TestJudgement : Judgement + { + public override string ResultString { get { throw new NotImplementedException(); } } + public override string MaxResultString { get { throw new NotImplementedException(); } } + } + } +} \ No newline at end of file diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index 5058d2eed5..87ec805288 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -98,7 +98,7 @@ - + From 933740664c1925dcdc64745c9b045e31916911a4 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 16:43:54 +0900 Subject: [PATCH 18/67] SpeedAdjustedHitRenderer -> ScrollingHitRenderer for consistent naming. --- osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs | 9 ++------- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 2 +- .../Objects/Drawables/DrawableScrollingHitObject.cs | 2 ++ ...eedAdjustedHitRenderer.cs => ScrollingHitRenderer.cs} | 4 ++-- osu.Game/osu.Game.csproj | 2 +- 5 files changed, 8 insertions(+), 11 deletions(-) rename osu.Game/Rulesets/UI/{SpeedAdjustedHitRenderer.cs => ScrollingHitRenderer.cs} (93%) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 07f59fe876..cc12c3ca61 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -46,12 +46,7 @@ namespace osu.Desktop.Tests.Visual BeatmapInfo = new BeatmapInfo { Difficulty = new BeatmapDifficulty(), - Metadata = new BeatmapMetadata - { - Artist = @"Unknown", - Title = @"Sample Beatmap", - Author = @"peppy", - } + Metadata = new BeatmapMetadata() } }; @@ -60,7 +55,7 @@ namespace osu.Desktop.Tests.Visual Add(new TestHitRenderer(beatmap, true)); } - private class TestHitRenderer : SpeedAdjustedHitRenderer + private class TestHitRenderer : ScrollingHitRenderer { public TestHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(beatmap, isForCurrentRuleset) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index a34765448c..65be8a4e88 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -30,7 +30,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaHitRenderer : SpeedAdjustedHitRenderer + public class ManiaHitRenderer : ScrollingHitRenderer { /// /// Preferred column count. This will only have an effect during the initialization of the play field. diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs index ec206928b2..6861f15c40 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs @@ -11,6 +11,8 @@ 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 diff --git a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs b/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs similarity index 93% rename from osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs rename to osu.Game/Rulesets/UI/ScrollingHitRenderer.cs index 5f8bebc213..ee549f5223 100644 --- a/osu.Game/Rulesets/UI/SpeedAdjustedHitRenderer.cs +++ b/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs @@ -20,14 +20,14 @@ namespace osu.Game.Rulesets.UI /// A type of that exposes s to be used /// in s. /// - public abstract class SpeedAdjustedHitRenderer : HitRenderer + public abstract class ScrollingHitRenderer : HitRenderer where TObject : HitObject where TJudgement : Judgement where TPlayfield : ScrollingPlayfield { protected readonly SortedList DefaultControlPoints = new SortedList(Comparer.Default); - protected SpeedAdjustedHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) + protected ScrollingHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(beatmap, isForCurrentRuleset) { } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 342a02ba60..b200d55ade 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -339,7 +339,7 @@ - + From 9c0a0b1e2c3c0cbfd3a34958bd4cb07cc3f0ca1b Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 17:25:40 +0900 Subject: [PATCH 19/67] Rewrite/add comments. --- .../Timing/LinearScrollingContainer.cs | 3 +- .../Rulesets/Timing/ScrollingContainer.cs | 54 +++-------------- .../Timing/SpeedAdjustmentContainer.cs | 25 ++++---- osu.Game/Rulesets/UI/ScrollingHitRenderer.cs | 19 ++++-- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 60 ++++++++++++++----- 5 files changed, 81 insertions(+), 80 deletions(-) diff --git a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs index b86165997b..8c2b863d5e 100644 --- a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs @@ -7,8 +7,7 @@ using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.Timing { /// - /// A which scrolls relative to the control point start time. - /// This is the default returned by the base . + /// A which scrolls linearly relative to the start time. /// internal class LinearScrollingContainer : ScrollingContainer { diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index dcedf102aa..1cb5e42251 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -13,29 +13,13 @@ using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Timing { /// - /// A collection of hit objects which scrolls within a . - /// - /// - /// This container handles the conversion between time and position through and - /// such that hit objects added to this container should have time values set as their - /// positions/sizes to make proper use of this container. - /// - /// - /// - /// This container will auto-size to the total duration of the contained hit objects along the desired auto-sizing axes such that the resulting size - /// of this container will be a value representing the total duration of all contained hit objects. - /// - /// - /// - /// This container is and must always be relatively-sized and positioned to its such that the parent can utilise - /// and to apply further time offsets to this collection of hit objects. - /// + /// 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 { private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; /// - /// Gets or sets the range of time that is visible by the length of this container. + /// Gets or sets the range of time that is visible by the length of the scrolling axes. /// public BindableDouble VisibleTimeRange { @@ -44,34 +28,17 @@ namespace osu.Game.Rulesets.Timing } /// - /// Axes through which this timing section scrolls. This is set by the . + /// The axes through which this scrolls. This is set by the . /// internal Axes ScrollingAxes; /// - /// The control point that provides the speed adjustments for this container. This is set by the . + /// The control point that defines the speed adjustments for this container. This is set by the . /// internal MultiplierControlPoint ControlPoint; private Cached durationBacking; - protected override int Compare(Drawable x, Drawable y) - { - var xHitObject = x as DrawableHitObject; - var yHitObject = y as DrawableHitObject; - - // If either of the two drawables are not hit objects, fall back to the base comparer - if (xHitObject?.HitObject == null || yHitObject?.HitObject == null) - return base.Compare(x, y); - - // Compare by start time - int i = yHitObject.HitObject.StartTime.CompareTo(xHitObject.HitObject.StartTime); - if (i != 0) - return i; - - return base.Compare(x, y); - } - /// /// Creates a new . /// @@ -106,13 +73,8 @@ namespace osu.Game.Rulesets.Timing if (baseDuration == 0) baseDuration = 1; - // Scrolling ruleset hit objects typically have anchors+origins set to the hit object's start time, but if the hit object doesn't implement IHasEndTime and lies on the control point - // then the baseDuration above will be 0. This will cause problems with masking when it is further set as the value for Size in Update(). We _want_ the timing section bounds to - // completely enclose the hit object to avoid the masking optimisations. - // - // To do this we need to find a duration that corresponds to the absolute size of the element that extrudes beyond the timing section's bounds and add that to baseDuration. - // We can utilize the fact that the Size and RelativeChildSpace are 1:1, meaning that an change in duration for the timing section has no change to the hit object's positioning - // and simply find the largest absolutely-sized element in this timing section. This introduces a little bit of error, but will never under-estimate the duration. + // This container needs to resize such that it completely encloses the hit objects to avoid masking optimisations. This is done by converting the largest + // absolutely-sized element along the scrolling axes and adding a corresponding duration value. This introduces a bit of error, but will never under-estimate.ion. // Find the largest element that is absolutely-sized along ScrollingAxes float maxAbsoluteSize = Children.Where(c => (c.RelativeSizeAxes & ScrollingAxes) == 0) @@ -129,7 +91,7 @@ namespace osu.Game.Rulesets.Timing /// /// The maximum duration of any one hit object inside this . This is calculated as the maximum - /// end time between all hit objects relative to this 's . + /// duration of all hit objects relative to this 's . /// public double Duration => durationBacking.IsValid ? durationBacking : (durationBacking.Value = computeDuration()); @@ -137,7 +99,7 @@ namespace osu.Game.Rulesets.Timing { base.Update(); - // We want our size and position-space along ScrollingAxes to span our duration to completely enclose all the hit objects + // 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 index f3475621c7..4d5db9f720 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -11,19 +11,14 @@ using OpenTK; namespace osu.Game.Rulesets.Timing { /// - /// A container for hit objects which applies applies the speed adjustments defined by the properties of a - /// to affect the scroll speed of the contained . - /// - /// - /// This container must always be relatively-sized to its parent to provide the speed adjustments. This container will provide the speed adjustments - /// by modifying its size while maintaining a constant for its children - /// + /// A container that provides the speed adjustments defined by s to affect the scroll speed + /// of container s. /// public class SpeedAdjustmentContainer : Container { private readonly Bindable visibleTimeRange = new Bindable { Default = 1000 }; /// - /// Gets or sets the range of time that is visible by the length of this container. + /// Gets or sets the range of time that is visible by the length of the scrolling axes. /// public Bindable VisibleTimeRange { @@ -35,10 +30,13 @@ namespace osu.Game.Rulesets.Timing private Container content; /// - /// Axes which the content of this container will scroll through. + /// The axes which the content of this container will scroll through. /// public Axes ScrollingAxes { get; internal set; } + /// + /// The that defines the speed adjustments. + /// public readonly MultiplierControlPoint ControlPoint; private ScrollingContainer scrollingContainer; @@ -46,11 +44,10 @@ namespace osu.Game.Rulesets.Timing /// /// Creates a new . /// - /// The which provides the speed adjustments for this container. + /// The that defines the speed adjustments. public SpeedAdjustmentContainer(MultiplierControlPoint controlPoint) { ControlPoint = controlPoint; - RelativeSizeAxes = Axes.Both; } @@ -93,17 +90,17 @@ namespace osu.Game.Rulesets.Timing } /// - /// Whether this speed adjustment can contain a hit object. This is true if the hit object occurs after this speed adjustment with respect to time. + /// Whether a falls within this s affecting timespan. /// public bool CanContain(DrawableHitObject hitObject) => CanContain(hitObject.HitObject.StartTime); /// - /// Whether this speed adjustment can contain an object placed at a time value. This is true if the time occurs after this speed adjustment. + /// Whether a point in time falls within this s affecting timespan. /// public bool CanContain(double startTime) => ControlPoint.StartTime <= startTime; /// - /// Creates the container which contains a collection of hit objects and scrolls through this SpeedAdjustmentContainer. + /// Creates the which contains the scrolling s of this container. /// /// The . protected virtual ScrollingContainer CreateScrollingContainer() => new LinearScrollingContainer(ScrollingAxes, ControlPoint); diff --git a/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs b/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs index ee549f5223..da4340ac7a 100644 --- a/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs +++ b/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs @@ -17,14 +17,19 @@ using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.UI { /// - /// A type of that exposes s to be used - /// in s. + /// A type of that supports a . + /// s inside this will scroll within the playfield. /// public abstract class ScrollingHitRenderer : HitRenderer where TObject : HitObject where TJudgement : Judgement where TPlayfield : ScrollingPlayfield { + /// + /// Provides the default s that adjust the scrolling rate of s + /// inside this . + /// + /// protected readonly SortedList DefaultControlPoints = new SortedList(Comparer.Default); protected ScrollingHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) @@ -87,15 +92,16 @@ namespace osu.Game.Rulesets.UI DefaultControlPoints.AddRange(timingChanges); + // If we have no control points, add a default one if (DefaultControlPoints.Count == 0) DefaultControlPoints.Add(new MultiplierControlPoint()); } /// - /// Generates a control point with the default timing change/difficulty change from the beatmap at a time. + /// Generates a with the default timing change/difficulty change from the beatmap at a time. /// /// The time to create the control point at. - /// The at . + /// The default at . public MultiplierControlPoint CreateControlPointAt(double time) { if (DefaultControlPoints.Count == 0) @@ -108,6 +114,11 @@ 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/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 27267f8a79..9d3a474b71 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -15,17 +15,33 @@ using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.UI { + /// + /// A type of specialized towards scrolling . + /// public class ScrollingPlayfield : Playfield where TObject : HitObject where TJudgement : Judgement { + /// + /// The default span of time visible by the length of the scrolling axes. + /// This is clamped between and . + /// private const double time_span_default = 1500; + /// + /// The minimum span of time that may be visible by the length of the scrolling axes. + /// private const double time_span_min = 50; + /// + /// The maximum span of time that may be visible by the length of the scrolling axes. + /// private const double time_span_max = 10000; + /// + /// The step increase/decrease of the span of time visible by the length of the scrolling axes. + /// private const double time_span_step = 50; /// - /// Gets or sets the range of time that is visible by the length of this playfield the scrolling axis direction. + /// 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. /// private readonly BindableDouble visibleTimeRange = new BindableDouble(time_span_default) @@ -35,14 +51,26 @@ namespace osu.Game.Rulesets.UI MaxValue = time_span_max }; + /// + /// The span of time visible by the length of the scrolling axes. + /// + /// public BindableDouble VisibleTimeRange { get { return visibleTimeRange; } set { visibleTimeRange.BindTo(value); } } + /// + /// The container that contains the s and s. + /// internal new readonly ScrollingHitObjectContainer HitObjects; + /// + /// Creates a new . + /// + /// 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) : base(customWidth) { @@ -54,8 +82,16 @@ namespace osu.Game.Rulesets.UI } private List> nestedPlayfields; + /// + /// All the s nested inside this playfield. + /// public IEnumerable> NestedPlayfields => nestedPlayfields; + /// + /// Adds a to this playfield. The nested + /// will be given all of the same speed adjustments as this playfield. + /// + /// The to add. protected void AddNested(ScrollingPlayfield otherPlayfield) { if (nestedPlayfields == null) @@ -104,19 +140,13 @@ namespace osu.Game.Rulesets.UI } /// - /// A collection of s. - /// - /// - /// This container redirects any 's added to it to the - /// which provides the speed adjustment active at the start time of the hit object. Furthermore, this container provides the - /// necessary for the contained s. - /// + /// A container that provides the foundation for sorting s into s. /// internal class ScrollingHitObjectContainer : HitObjectContainer> { private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; /// - /// Gets or sets the range of time that is visible by the length of this container. + /// 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 Bindable VisibleTimeRange @@ -126,9 +156,6 @@ namespace osu.Game.Rulesets.UI } protected override Container> Content => content; - /// - /// The following is never used - it only exists for the purpose of being able to use AddInternal below. - /// private Container> content; /// @@ -146,9 +173,14 @@ namespace osu.Game.Rulesets.UI { this.scrollingAxes = scrollingAxes; + // The following is never used - it only exists for the purpose of being able to use AddInternal below. content = new Container>(); } + /// + /// Adds a to this container. + /// + /// The . public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) { speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); @@ -157,8 +189,8 @@ namespace osu.Game.Rulesets.UI } /// - /// Adds a hit object to this . The hit objects will be kept in a queue - /// and will be processed when new s are added to this . + /// 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) From f3c05fe232275aee82656d60d927e2becfed9200 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 17:34:57 +0900 Subject: [PATCH 20/67] CI fixes. --- osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs | 4 ---- .../Objects/Drawables/DrawableManiaHitObject.cs | 1 - osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs | 1 - osu.Game.Rulesets.Mania/UI/Column.cs | 5 +---- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 5 +---- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 4 ---- .../Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs | 1 - osu.Game/Rulesets/Timing/LinearScrollingContainer.cs | 1 - osu.Game/Rulesets/UI/HitRenderer.cs | 1 + osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 4 ++-- 10 files changed, 5 insertions(+), 22 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index cc12c3ca61..b5dabc3a97 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -2,21 +2,17 @@ using System; using System.Collections.Generic; using OpenTK; using osu.Desktop.Tests.Beatmaps; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; -using osu.Game.Rulesets; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; namespace osu.Desktop.Tests.Visual diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index c1b2df8898..10dc607ec3 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -4,7 +4,6 @@ using OpenTK.Graphics; using OpenTK.Input; using osu.Framework.Configuration; -using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs b/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs index 2cb14f224e..699acc477b 100644 --- a/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Graphics; using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.Mania.Timing diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 694e8c8126..9fbc9ba5e7 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -14,12 +14,9 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System; using osu.Framework.Configuration; -using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; -using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Judgements; -using osu.Framework.Allocation; namespace osu.Game.Rulesets.Mania.UI { @@ -195,7 +192,7 @@ namespace osu.Game.Rulesets.Mania.UI /// /// Adds a DrawableHitObject to this Playfield. /// - /// The DrawableHitObject to add. + /// The DrawableHitObject to add. public override void Add(DrawableHitObject hitObject) { hitObject.AccentColour = AccentColour; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 65be8a4e88..0b8ad10b16 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -17,7 +17,6 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Judgements; -using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Scoring; @@ -97,9 +96,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) { - var maniaPlayfield = (ManiaPlayfield)Playfield; - - Bindable key = maniaPlayfield.Columns.ElementAt(h.Column).Key; + Bindable key = Playfield.Columns.ElementAt(h.Column).Key; var holdNote = h as HoldNote; if (holdNote != null) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 4b240e4659..ba6d947729 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -15,12 +15,8 @@ using OpenTK.Input; using System.Linq; using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; -using osu.Framework.Input; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Timing; -using osu.Framework.Configuration; using osu.Framework.Graphics.Shapes; -using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Mania.UI { diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs index 6861f15c40..243fd79b6f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs index 8c2b863d5e..db497b7664 100644 --- a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/LinearScrollingContainer.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.Timing; namespace osu.Game.Rulesets.Timing { diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index fd43078c2b..286d3a40f4 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -322,6 +322,7 @@ namespace osu.Game.Rulesets.UI /// /// A derivable HitRenderer that manages the Playfield and HitObjects. /// + /// The type of Playfield contained by this HitRenderer. /// The type of HitObject contained by this HitRenderer. /// The type of Judgement of DrawableHitObjects contained by this HitRenderer. public abstract class HitRenderer : HitRenderer diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 9d3a474b71..ffd7a993f0 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -16,7 +16,7 @@ using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.UI { /// - /// A type of specialized towards scrolling . + /// A type of specialized towards scrolling s. /// public class ScrollingPlayfield : Playfield where TObject : HitObject @@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.UI } protected override Container> Content => content; - private Container> content; + private readonly Container> content; /// /// Hit objects that are to be re-processed on the next update. From 12f9793fecd7bcc8c8aa284a7b34c3dbd1a17fc1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 17:45:45 +0900 Subject: [PATCH 21/67] Fix mania bar lines not working. --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index ba6d947729..72b82ab60b 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -48,8 +48,8 @@ namespace osu.Game.Rulesets.Mania.UI private readonly FlowContainer columns; public IEnumerable Columns => columns.Children; - protected override Container Content => barLineContainer; - private readonly Container barLineContainer; + protected override Container Content => content; + private readonly Container content; private List normalColumnColours = new List(); private Color4 specialColumnColour; @@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Mania.UI Padding = new MarginPadding { Top = HIT_TARGET_POSITION }, Children = new[] { - barLineContainer = new Container + content = new Container { Name = "Bar lines", Anchor = Anchor.TopCentre, @@ -201,13 +201,13 @@ namespace osu.Game.Rulesets.Mania.UI } public override void Add(DrawableHitObject h) => Columns.ElementAt(h.HitObject.Column).Add(h); - public void Add(DrawableBarLine barline) => barLineContainer.Add(barline); + public void Add(DrawableBarLine barline) => HitObjects.Add(barline); protected override void Update() { // Due to masking differences, it is not possible to get the width of the columns container automatically // While masking on effectively only the Y-axis, so we need to set the width of the bar line container manually - barLineContainer.Width = columns.Width; + content.Width = columns.Width; } } } From bd2ef4dc6b23f902e8d631cde551a92c75b5b5de Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 18:03:44 +0900 Subject: [PATCH 22/67] Line endings + license headers. --- .../Visual/TestCaseScrollingPlayfield.cs | 283 +++++----- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 497 +++++++++--------- 2 files changed, 393 insertions(+), 387 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index b5dabc3a97..6f93d50ff1 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -1,141 +1,144 @@ -using System; -using System.Collections.Generic; -using OpenTK; -using osu.Desktop.Tests.Beatmaps; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Testing; -using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Beatmaps; -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.UI; - -namespace osu.Desktop.Tests.Visual -{ - /// - /// The most minimal implementation of a playfield with scrolling hit objects. - /// - public class TestCaseScrollingPlayfield : TestCase - { - 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 - { - Difficulty = new BeatmapDifficulty(), - Metadata = new BeatmapMetadata() - } - }; - - WorkingBeatmap beatmap = new TestWorkingBeatmap(b); - - Add(new TestHitRenderer(beatmap, true)); - } - - private class TestHitRenderer : ScrollingHitRenderer - { - public TestHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) - { - } - - public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor(); - - protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); - - protected override Playfield CreatePlayfield() => new TestPlayfield(); - - protected override DrawableHitObject GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(h); - } - - private class TestScoreProcessor : ScoreProcessor - { - protected override void OnNewJudgement(TestJudgement 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(TestHitObject hitObject) - : base(hitObject) - { - Anchor = Anchor.CentreLeft; - Origin = Anchor.Centre; - - AutoSizeAxes = Axes.Both; - - Add(new Circle - { - Size = new Vector2(50) - }); - } - - protected override TestJudgement CreateJudgement() => new TestJudgement(); - - protected override void UpdateState(ArmedState state) - { - } - } - - private class TestPlayfield : ScrollingPlayfield - { - protected override Container Content => content; - private readonly Container content; - - public TestPlayfield() - : base(Axes.X) - { - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.2f - }, - content = new Container { RelativeSizeAxes = Axes.Both } - }; - } - } - - - private class TestHitObject : HitObject - { - } - - private class TestJudgement : Judgement - { - public override string ResultString { get { throw new NotImplementedException(); } } - public override string MaxResultString { get { throw new NotImplementedException(); } } - } - } +// 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 OpenTK; +using osu.Desktop.Tests.Beatmaps; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Beatmaps; +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.UI; + +namespace osu.Desktop.Tests.Visual +{ + /// + /// The most minimal implementation of a playfield with scrolling hit objects. + /// + public class TestCaseScrollingPlayfield : TestCase + { + 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 + { + Difficulty = new BeatmapDifficulty(), + Metadata = new BeatmapMetadata() + } + }; + + WorkingBeatmap beatmap = new TestWorkingBeatmap(b); + + Add(new TestHitRenderer(beatmap, true)); + } + + private class TestHitRenderer : ScrollingHitRenderer + { + public TestHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(beatmap, isForCurrentRuleset) + { + } + + public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor(); + + protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); + + protected override Playfield CreatePlayfield() => new TestPlayfield(); + + protected override DrawableHitObject GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(h); + } + + private class TestScoreProcessor : ScoreProcessor + { + protected override void OnNewJudgement(TestJudgement 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(TestHitObject hitObject) + : base(hitObject) + { + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + + AutoSizeAxes = Axes.Both; + + Add(new Circle + { + Size = new Vector2(50) + }); + } + + protected override TestJudgement CreateJudgement() => new TestJudgement(); + + protected override void UpdateState(ArmedState state) + { + } + } + + private class TestPlayfield : ScrollingPlayfield + { + protected override Container Content => content; + private readonly Container content; + + public TestPlayfield() + : base(Axes.X) + { + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f + }, + content = new Container { RelativeSizeAxes = Axes.Both } + }; + } + } + + + private class TestHitObject : HitObject + { + } + + private class TestJudgement : Judgement + { + public override string ResultString { get { throw new NotImplementedException(); } } + public override string MaxResultString { get { throw new NotImplementedException(); } } + } + } } \ No newline at end of file diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index ffd7a993f0..1a88c74ebc 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -1,248 +1,251 @@ -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.MathUtils; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.UI -{ - /// - /// A type of specialized towards scrolling s. - /// - public class ScrollingPlayfield : Playfield - where TObject : HitObject - where TJudgement : Judgement - { - /// - /// The default span of time visible by the length of the scrolling axes. - /// This is clamped between and . - /// - private const double time_span_default = 1500; - /// - /// The minimum span of time that may be visible by the length of the scrolling axes. - /// - private const double time_span_min = 50; - /// - /// The maximum span of time that may be visible by the length of the scrolling axes. - /// - private const double time_span_max = 10000; - /// - /// The step increase/decrease of the span of time visible by the length of the scrolling axes. - /// - private const double time_span_step = 50; - - /// - /// 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. - /// - private readonly BindableDouble visibleTimeRange = new BindableDouble(time_span_default) - { - Default = time_span_default, - MinValue = time_span_min, - MaxValue = time_span_max - }; - - /// - /// The span of time visible by the length of the scrolling axes. - /// - /// - public BindableDouble VisibleTimeRange - { - get { return visibleTimeRange; } - set { visibleTimeRange.BindTo(value); } - } - - /// - /// The container that contains the s and s. - /// - internal new readonly ScrollingHitObjectContainer HitObjects; - - /// - /// Creates a new . - /// - /// 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) - : base(customWidth) - { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) - { - RelativeSizeAxes = Axes.Both, - VisibleTimeRange = VisibleTimeRange - }; - } - - private List> nestedPlayfields; - /// - /// All the s nested inside this playfield. - /// - public IEnumerable> NestedPlayfields => nestedPlayfields; - - /// - /// Adds a to this playfield. The nested - /// will be given all of the same speed adjustments as this playfield. - /// - /// The to add. - protected void AddNested(ScrollingPlayfield otherPlayfield) - { - if (nestedPlayfields == null) - nestedPlayfields = new List>(); - - nestedPlayfields.Add(otherPlayfield); - } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - if (state.Keyboard.ControlPressed) - { - switch (args.Key) - { - case Key.Minus: - transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); - break; - case Key.Plus: - transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); - break; - } - } - - return false; - } - - private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) - { - this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); - } - - private class TransformVisibleTimeRange : Transform> - { - private double valueAt(double time) - { - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - - public override string TargetMember => "VisibleTimeRange.Value"; - - protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time); - protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; - } - - /// - /// A container that provides the foundation for sorting s into s. - /// - internal class ScrollingHitObjectContainer : HitObjectContainer> - { - private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; - /// - /// 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 Bindable VisibleTimeRange - { - get { return visibleTimeRange; } - set { visibleTimeRange.BindTo(value); } - } - - protected override Container> Content => content; - private readonly Container> content; - - /// - /// Hit objects that are to be re-processed on the next update. - /// - private readonly Queue> queuedHitObjects = new Queue>(); - - private readonly Axes scrollingAxes; - - /// - /// Creates a new . - /// - /// The axes upon which hit objects should appear to scroll inside this container. - public ScrollingHitObjectContainer(Axes scrollingAxes) - { - this.scrollingAxes = scrollingAxes; - - // The following is never used - it only exists for the purpose of being able to use AddInternal below. - content = new Container>(); - } - - /// - /// Adds a to this container. - /// - /// The . - public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) - { - speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); - speedAdjustment.ScrollingAxes = scrollingAxes; - AddInternal(speedAdjustment); - } - - /// - /// 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)}."); - - queuedHitObjects.Enqueue(hitObject); - } - - protected override void Update() - { - base.Update(); - - // Todo: At the moment this is going to re-process every single Update, however this will only be a null-op - // when there are no SpeedAdjustmentContainers available. This should probably error or something, but it's okay for now. - - // An external count is kept because hit objects that can't be added are re-queued - int count = queuedHitObjects.Count; - while (count-- > 0) - { - var hitObject = queuedHitObjects.Dequeue(); - - var target = adjustmentContainerFor(hitObject); - if (target == null) - { - // We can't add this hit object to a speed adjustment container yet, so re-queue it - // for re-processing when the layout next invalidated - queuedHitObjects.Enqueue(hitObject); - continue; - } - - target.Add(hitObject); - } - } - - /// - /// Finds the which provides the speed adjustment active at the start time - /// of a hit object. If there is no active at the start time of the hit object, - /// then the first (time-wise) speed adjustment is returned. - /// - /// The hit object to find the active for. - /// The active at 's start time. Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => InternalChildren.OfType().FirstOrDefault(c => c.CanContain(hitObject)) ?? InternalChildren.OfType().LastOrDefault(); - - /// - /// 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) => InternalChildren.OfType().FirstOrDefault(c => c.CanContain(time)) ?? InternalChildren.OfType().LastOrDefault(); - } - } +// 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.MathUtils; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Timing; + +namespace osu.Game.Rulesets.UI +{ + /// + /// A type of specialized towards scrolling s. + /// + public class ScrollingPlayfield : Playfield + where TObject : HitObject + where TJudgement : Judgement + { + /// + /// The default span of time visible by the length of the scrolling axes. + /// This is clamped between and . + /// + private const double time_span_default = 1500; + /// + /// The minimum span of time that may be visible by the length of the scrolling axes. + /// + private const double time_span_min = 50; + /// + /// The maximum span of time that may be visible by the length of the scrolling axes. + /// + private const double time_span_max = 10000; + /// + /// The step increase/decrease of the span of time visible by the length of the scrolling axes. + /// + private const double time_span_step = 50; + + /// + /// 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. + /// + private readonly BindableDouble visibleTimeRange = new BindableDouble(time_span_default) + { + Default = time_span_default, + MinValue = time_span_min, + MaxValue = time_span_max + }; + + /// + /// The span of time visible by the length of the scrolling axes. + /// + /// + public BindableDouble VisibleTimeRange + { + get { return visibleTimeRange; } + set { visibleTimeRange.BindTo(value); } + } + + /// + /// The container that contains the s and s. + /// + internal new readonly ScrollingHitObjectContainer HitObjects; + + /// + /// Creates a new . + /// + /// 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) + : base(customWidth) + { + base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) + { + RelativeSizeAxes = Axes.Both, + VisibleTimeRange = VisibleTimeRange + }; + } + + private List> nestedPlayfields; + /// + /// All the s nested inside this playfield. + /// + public IEnumerable> NestedPlayfields => nestedPlayfields; + + /// + /// Adds a to this playfield. The nested + /// will be given all of the same speed adjustments as this playfield. + /// + /// The to add. + protected void AddNested(ScrollingPlayfield otherPlayfield) + { + if (nestedPlayfields == null) + nestedPlayfields = new List>(); + + nestedPlayfields.Add(otherPlayfield); + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (state.Keyboard.ControlPressed) + { + switch (args.Key) + { + case Key.Minus: + transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); + break; + case Key.Plus: + transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); + break; + } + } + + return false; + } + + private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) + { + this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); + } + + private class TransformVisibleTimeRange : Transform> + { + private double valueAt(double time) + { + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + + public override string TargetMember => "VisibleTimeRange.Value"; + + protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time); + protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; + } + + /// + /// A container that provides the foundation for sorting s into s. + /// + internal class ScrollingHitObjectContainer : HitObjectContainer> + { + private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; + /// + /// 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 Bindable VisibleTimeRange + { + get { return visibleTimeRange; } + set { visibleTimeRange.BindTo(value); } + } + + protected override Container> Content => content; + private readonly Container> content; + + /// + /// Hit objects that are to be re-processed on the next update. + /// + private readonly Queue> queuedHitObjects = new Queue>(); + + private readonly Axes scrollingAxes; + + /// + /// Creates a new . + /// + /// The axes upon which hit objects should appear to scroll inside this container. + public ScrollingHitObjectContainer(Axes scrollingAxes) + { + this.scrollingAxes = scrollingAxes; + + // The following is never used - it only exists for the purpose of being able to use AddInternal below. + content = new Container>(); + } + + /// + /// Adds a to this container. + /// + /// The . + public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) + { + speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); + speedAdjustment.ScrollingAxes = scrollingAxes; + AddInternal(speedAdjustment); + } + + /// + /// 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)}."); + + queuedHitObjects.Enqueue(hitObject); + } + + protected override void Update() + { + base.Update(); + + // Todo: At the moment this is going to re-process every single Update, however this will only be a null-op + // when there are no SpeedAdjustmentContainers available. This should probably error or something, but it's okay for now. + + // An external count is kept because hit objects that can't be added are re-queued + int count = queuedHitObjects.Count; + while (count-- > 0) + { + var hitObject = queuedHitObjects.Dequeue(); + + var target = adjustmentContainerFor(hitObject); + if (target == null) + { + // We can't add this hit object to a speed adjustment container yet, so re-queue it + // for re-processing when the layout next invalidated + queuedHitObjects.Enqueue(hitObject); + continue; + } + + target.Add(hitObject); + } + } + + /// + /// Finds the which provides the speed adjustment active at the start time + /// of a hit object. If there is no active at the start time of the hit object, + /// then the first (time-wise) speed adjustment is returned. + /// + /// The hit object to find the active for. + /// The active at 's start time. Null if there are no speed adjustments. + private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => InternalChildren.OfType().FirstOrDefault(c => c.CanContain(hitObject)) ?? InternalChildren.OfType().LastOrDefault(); + + /// + /// 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) => InternalChildren.OfType().FirstOrDefault(c => c.CanContain(time)) ?? InternalChildren.OfType().LastOrDefault(); + } + } } \ No newline at end of file From bcd1b61529fe105b4ae1a63e0a22338d7e767cd6 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 7 Aug 2017 18:11:45 +0900 Subject: [PATCH 23/67] Use OsuTestCase. --- osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 6f93d50ff1..21f1aa603a 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -8,7 +8,6 @@ using osu.Desktop.Tests.Beatmaps; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Beatmaps; @@ -23,7 +22,7 @@ namespace osu.Desktop.Tests.Visual /// /// The most minimal implementation of a playfield with scrolling hit objects. /// - public class TestCaseScrollingPlayfield : TestCase + public class TestCaseScrollingPlayfield : OsuTestCase { public TestCaseScrollingPlayfield() { From fc30c471ed3156a15c429d720e4f0beb0b825dd3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 07:18:31 +0900 Subject: [PATCH 24/67] Update resources --- osu-resources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-resources b/osu-resources index 76656c51f2..f6042e1cb3 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 76656c51f281e7934159e9ed4414378fef24d130 +Subproject commit f6042e1cb37cfad6c879d0e1245f7880c7fcd5f5 From fe625f711ab7660c9bb0e853769763cff30d8ba2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 07:22:03 +0900 Subject: [PATCH 25/67] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 107c551767..8413a36fd2 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 107c5517670ca88dbe8c83a97e37e99ac5742ee6 +Subproject commit 8413a36fd26f3bae2a789208a9317b4511c35e99 From 4d1dd70cfbe23f9faf8f59c0cecfe13ead267db2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 07:32:23 +0900 Subject: [PATCH 26/67] Licence headers --- osu.Desktop.Tests/Visual/TestCaseCatcher.cs | 5 ++++- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseCatcher.cs b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs index eb714c9994..0e92b5114b 100644 --- a/osu.Desktop.Tests/Visual/TestCaseCatcher.cs +++ b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs @@ -1,4 +1,7 @@ -using osu.Framework.Graphics; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.UI; using OpenTK; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index cb979ffc55..153302c1d1 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From 70585a279dc3be236f617ebb70b20407a76cdeaa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 07:48:03 +0900 Subject: [PATCH 27/67] Comment out unused variables for now --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 6a20fa525e..4e741b3a55 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -18,10 +18,10 @@ namespace osu.Game.Rulesets.Catch.Beatmaps protected override IEnumerable ConvertHitObject(HitObject obj, Beatmap beatmap) { - var distanceData = obj as IHasDistance; + /*var distanceData = obj as IHasDistance; var repeatsData = obj as IHasRepeats; var endTimeData = obj as IHasEndTime; - var curveData = obj as IHasCurve; + var curveData = obj as IHasCurve;*/ yield return new Fruit { From debe13629f07da44eb14489aa959eb772127c11e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 09:20:54 +0900 Subject: [PATCH 28/67] Don't set RelativePositionAxes when setting ScrollingAxes --- .../Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs index 243fd79b6f..f67dd4dfea 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { set { - RelativePositionAxes = value; + RelativePositionAxes |= value; if ((value & Axes.X) > 0) X = (float)HitObject.StartTime; From e67379b6de2619d16caf236b0ab4929264e5b001 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 10:35:56 +0900 Subject: [PATCH 29/67] Use ScrollingHitRenderer --- .../Objects/Drawable/DrawableFruit.cs | 19 ++++++------------- .../UI/CatchHitRenderer.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 17 ++++++++++++++--- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index aa92f36d23..a2cf0ec279 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -15,7 +15,7 @@ using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - internal class DrawableFruit : DrawableHitObject + internal class DrawableFruit : DrawableScrollingHitObject { private class Pulp : Circle, IHasAccentColour { @@ -37,11 +37,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { Origin = Anchor.Centre; Size = new Vector2(50); - RelativePositionAxes = Axes.Both; - Position = new Vector2(h.Position, -0.1f); - Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; - Alpha = 0; + RelativePositionAxes = Axes.Both; + X = h.Position; + + Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; } [BackgroundDependencyLoader] @@ -91,8 +91,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Position = new Vector2(0, 0.6f), }, }; - - Alpha = 0; } protected override CatchJudgement CreateJudgement() => new CatchJudgement(); @@ -103,14 +101,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { using (BeginAbsoluteSequence(HitObject.StartTime - preempt)) { - // default state - this.MoveToY(-0.1f).FadeOut(); - // animation - this.FadeIn(200).MoveToY(1, preempt); + this.FadeIn(200); } - - Expire(true); } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs index cd6adfeea9..8f614cc4c3 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.UI { - public class CatchHitRenderer : HitRenderer + public class CatchHitRenderer : ScrollingHitRenderer { public CatchHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(beatmap, isForCurrentRuleset) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 03aabc5632..3aed94daad 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -6,20 +6,31 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.UI; using OpenTK; using osu.Game.Rulesets.Catch.Judgements; +using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Catch.UI { - public class CatchPlayfield : Playfield + public class CatchPlayfield : ScrollingPlayfield { + protected override Container Content => content; + private readonly Container content; + public CatchPlayfield() + : base(Axes.Y) { Size = new Vector2(1); Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; - Children = new Drawable[] + InternalChildren = new Drawable[] { + content = new Container + { + Scale = new Vector2(1, -1), + RelativeSizeAxes = Axes.Both, + Origin = Anchor.BottomLeft + }, new CatcherArea { RelativeSizeAxes = Axes.Both, @@ -30,4 +41,4 @@ namespace osu.Game.Rulesets.Catch.UI }; } } -} \ No newline at end of file +} From 4bdaa8ae680213f6b4e2c18e514f7bd51c0a9068 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 10:36:05 +0900 Subject: [PATCH 30/67] Add basic miss support --- .../Objects/Drawable/DrawableFruit.cs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index a2cf0ec279..8531428acf 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { internal class DrawableFruit : DrawableScrollingHitObject { + private Box box; + private class Pulp : Circle, IHasAccentColour { public Pulp() @@ -49,10 +51,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { Children = new Framework.Graphics.Drawable[] { - new Box + box = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Red, + Colour = Color4.Blue, }, new Pulp { @@ -97,6 +99,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable private const float preempt = 1000; + protected override void CheckJudgement(bool userTriggered) + { + if (Judgement.TimeOffset > 0) + Judgement.Result = HitResult.Miss; + } + protected override void UpdateState(ArmedState state) { using (BeginAbsoluteSequence(HitObject.StartTime - preempt)) @@ -104,6 +112,17 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable // animation this.FadeIn(200); } + + switch (state) + { + case ArmedState.Miss: + using (BeginAbsoluteSequence(HitObject.StartTime, true)) + { + this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out); + box.FadeColour(Color4.OrangeRed); + } + break; + } } } } From 3926238be992dfb4cb1e2b34f0e4f742b06157e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 10:53:59 +0900 Subject: [PATCH 31/67] Allow DrawableHitObjects to be removed from a Playfield --- osu.Game/Rulesets/UI/Playfield.cs | 6 ++++++ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 5f07df5088..ade2c2d070 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -82,6 +82,12 @@ namespace osu.Game.Rulesets.UI /// The DrawableHitObject to add. public virtual void Add(DrawableHitObject h) => HitObjects.Add(h); + /// + /// Remove a DrawableHitObject from this Playfield. + /// + /// The DrawableHitObject to remove. + public virtual void Remove(DrawableHitObject h) => HitObjects.Remove(h); + /// /// Triggered when an object's Judgement is updated. /// diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 1a88c74ebc..f1eef6ea31 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -204,6 +204,13 @@ namespace osu.Game.Rulesets.UI queuedHitObjects.Enqueue(hitObject); } + public override bool Remove(DrawableHitObject hitObject) + { + foreach (var c in InternalChildren.OfType()) + c.Remove(hitObject); + return true; + } + protected override void Update() { base.Update(); From 99a00ed3190b68063357adee55e07899d192c061 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 12:46:01 +0900 Subject: [PATCH 32/67] Make fruit look a bit better (and buffer them to a texture) --- .../Objects/Drawable/DrawableFruit.cs | 84 +++++++++---------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 8531428acf..f8b0830089 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -17,12 +17,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { internal class DrawableFruit : DrawableScrollingHitObject { - private Box box; + const float pulp_size = 30; private class Pulp : Circle, IHasAccentColour { public Pulp() { + Size = new Vector2(pulp_size); + EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, @@ -38,11 +40,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public DrawableFruit(CatchBaseHit h) : base(h) { Origin = Anchor.Centre; - Size = new Vector2(50); + Size = new Vector2(pulp_size * 2, pulp_size * 2.6f); RelativePositionAxes = Axes.Both; X = h.Position; + Colour = new Color4(RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), 1); + Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; } @@ -51,47 +55,42 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { Children = new Framework.Graphics.Drawable[] { - box = new Box + //todo: share this more + new BufferedContainer { RelativeSizeAxes = Axes.Both, - Colour = Color4.Blue, - }, - new Pulp - { - RelativePositionAxes = Axes.Both, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre, - Scale = new Vector2(0.12f), - Y = 0.08f, - }, - new Pulp - { - RelativePositionAxes = Axes.Both, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre, - Scale = new Vector2(0.32f), - Position = new Vector2(-0.16f, 0.3f), - }, - new Pulp - { - RelativePositionAxes = Axes.Both, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre, - Scale = new Vector2(0.32f), - Position = new Vector2(0.16f, 0.3f), - }, - new Pulp - { - RelativePositionAxes = Axes.Both, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre, - Scale = new Vector2(0.32f), - Position = new Vector2(0, 0.6f), - }, + CacheDrawnFrameBuffer = true, + Children = new Framework.Graphics.Drawable[] + { + new Pulp + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Scale = new Vector2(0.6f), + }, + new Pulp + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Y = -0.08f + }, + new Pulp + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Y = -0.08f + }, + new Pulp + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }, + } + } }; } @@ -117,10 +116,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { case ArmedState.Miss: using (BeginAbsoluteSequence(HitObject.StartTime, true)) - { this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out); - box.FadeColour(Color4.OrangeRed); - } break; } } From ff490cf44ce155542fe9faee5041eae13223e653 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 12:46:37 +0900 Subject: [PATCH 33/67] Add catching support --- .../Objects/Drawable/DrawableFruit.cs | 10 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 24 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 254 ++++++++++-------- 3 files changed, 179 insertions(+), 109 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index f8b0830089..0aba83696c 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.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.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -15,7 +16,7 @@ using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - internal class DrawableFruit : DrawableScrollingHitObject + public class DrawableFruit : DrawableScrollingHitObject { const float pulp_size = 30; @@ -37,7 +38,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable } - public DrawableFruit(CatchBaseHit h) : base(h) + public DrawableFruit(CatchBaseHit h) + : base(h) { Origin = Anchor.Centre; Size = new Vector2(pulp_size * 2, pulp_size * 2.6f); @@ -50,6 +52,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; } + public Func CheckPosition; + [BackgroundDependencyLoader] private void load() { @@ -101,7 +105,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable protected override void CheckJudgement(bool userTriggered) { if (Judgement.TimeOffset > 0) - Judgement.Result = HitResult.Miss; + Judgement.Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Hit : HitResult.Miss; } protected override void UpdateState(ArmedState state) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 3aed94daad..388444d49d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -7,6 +7,8 @@ using osu.Game.Rulesets.UI; using OpenTK; using osu.Game.Rulesets.Catch.Judgements; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.UI { @@ -14,6 +16,7 @@ namespace osu.Game.Rulesets.Catch.UI { protected override Container Content => content; private readonly Container content; + private readonly CatcherArea catcherArea; public CatchPlayfield() : base(Axes.Y) @@ -31,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.UI RelativeSizeAxes = Axes.Both, Origin = Anchor.BottomLeft }, - new CatcherArea + catcherArea = new CatcherArea { RelativeSizeAxes = Axes.Both, Anchor = Anchor.BottomLeft, @@ -40,5 +43,24 @@ namespace osu.Game.Rulesets.Catch.UI } }; } + + public override void Add(DrawableHitObject h) + { + base.Add(h); + + var fruit = (DrawableFruit)h; + fruit.CheckPosition = catcherArea.CheckIfWeCanCatch; + fruit.OnJudgement += Fruit_OnJudgement; + } + + private void Fruit_OnJudgement(DrawableHitObject obj) + { + if (obj.Judgement.Result == HitResult.Hit) + { + Vector2 screenPosition = obj.ScreenSpaceDrawQuad.Centre; + Remove(obj); + catcherArea.Add(obj, screenPosition); + } + } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 153302c1d1..6ed8030941 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -2,12 +2,18 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using OpenTK.Input; @@ -15,132 +21,170 @@ namespace osu.Game.Rulesets.Catch.UI { public class CatcherArea : Container { - public override bool HandleInput => true; + private Catcher catcher; - private Sprite catcher; + public void Add(DrawableHitObject fruit, Vector2 screenPosition) => catcher.AddToStack(fruit, screenPosition); - private Drawable createAdditiveFrame() => new Sprite - { - RelativePositionAxes = Axes.Both, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - - Texture = catcher.Texture, - BlendingMode = BlendingMode.Additive, - Position = catcher.Position, - Scale = catcher.Scale, - }; + public bool CheckIfWeCanCatch(CatchBaseHit obj) => Math.Abs(catcher.Position.X - obj.Position) < catcher.DrawSize.X / DrawSize.X / 2; [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load() { Children = new Drawable[] { - catcher = new Sprite + catcher = new Catcher { RelativePositionAxes = Axes.Both, Anchor = Anchor.TopLeft, Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - X = 0.5f, - Texture = textures.Get(@"Play/Catch/fruit-catcher-idle"), - }, + } }; } - private bool leftPressed; - private bool rightPressed; - - private int currentDirection; - - private bool dashing; - - protected bool Dashing - { - get - { - return dashing; - } - set - { - if (value == dashing) return; - - dashing = value; - - if (dashing) - Schedule(addAdditiveSprite); - } - } - - private void addAdditiveSprite() - { - if (!dashing) return; - - var additive = createAdditiveFrame(); - - Add(additive); - - additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); - - Scheduler.AddDelayed(addAdditiveSprite, 50); - } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - if (args.Repeat) return true; - - switch (args.Key) - { - case Key.Left: - currentDirection = -1; - leftPressed = true; - return true; - case Key.Right: - currentDirection = 1; - rightPressed = true; - return true; - case Key.ShiftLeft: - Dashing = true; - return true; - } - - return base.OnKeyDown(state, args); - } - - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) - { - switch (args.Key) - { - case Key.Left: - currentDirection = rightPressed ? 1 : 0; - leftPressed = false; - return true; - case Key.Right: - currentDirection = leftPressed ? -1 : 0; - rightPressed = false; - return true; - case Key.ShiftLeft: - Dashing = false; - return true; - } - - return base.OnKeyUp(state, args); - } - protected override void Update() { base.Update(); - if (currentDirection == 0) return; + catcher.Size = new Vector2(DrawSize.Y); + } - float speed = Dashing ? 1.5f : 1; + private class Catcher : Container + { + public override bool HandleInput => true; - catcher.Scale = new Vector2(Math.Sign(currentDirection), 1); - catcher.X = (float)MathHelper.Clamp(catcher.X + currentDirection * Clock.ElapsedFrameTime / 1800 * speed, 0, 1); + private Texture texture; + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); + + Child = createCatcherSprite(); + } + + private bool leftPressed; + private bool rightPressed; + + private int currentDirection; + + private bool dashing; + + protected bool Dashing + { + get { return dashing; } + set + { + if (value == dashing) return; + + dashing = value; + + if (dashing) + Schedule(addAdditiveSprite); + } + } + + private void addAdditiveSprite() + { + if (!dashing) return; + + var additive = createCatcherSprite(); + + additive.RelativePositionAxes = Axes.Both; + additive.BlendingMode = BlendingMode.Additive; + additive.Position = Position; + additive.Scale = Scale; + + ((CatcherArea)Parent).Add(additive); + + additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); + + Scheduler.AddDelayed(addAdditiveSprite, 50); + } + + private Sprite createCatcherSprite() => new Sprite + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Texture = texture, + OriginPosition = new Vector2(DrawWidth / 2, 10) //temporary until the sprite is aligned correctly. + }; + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) return true; + + switch (args.Key) + { + case Key.Left: + currentDirection = -1; + leftPressed = true; + return true; + case Key.Right: + currentDirection = 1; + rightPressed = true; + return true; + case Key.ShiftLeft: + Dashing = true; + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + { + switch (args.Key) + { + case Key.Left: + currentDirection = rightPressed ? 1 : 0; + leftPressed = false; + return true; + case Key.Right: + currentDirection = leftPressed ? -1 : 0; + rightPressed = false; + return true; + case Key.ShiftLeft: + Dashing = false; + return true; + } + + return base.OnKeyUp(state, args); + } + + protected override void Update() + { + base.Update(); + + if (currentDirection == 0) return; + + float speed = Dashing ? 1.5f : 1; + + Scale = new Vector2(Math.Sign(currentDirection), 1); + X = (float)MathHelper.Clamp(X + currentDirection * Clock.ElapsedFrameTime / 1800 * speed, 0, 1); + } + + public void AddToStack(DrawableHitObject fruit, Vector2 absolutePosition) + { + fruit.RelativePositionAxes = Axes.None; + fruit.Position = new Vector2(ToLocalSpace(absolutePosition).X - DrawSize.X / 2, 0); + + fruit.Anchor = Anchor.TopCentre; + fruit.Origin = Anchor.BottomCentre; + fruit.Scale *= 0.7f; + fruit.LifetimeEnd = double.MaxValue; + fruit.Depth = (float)Time.Current; + + float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; + + while (Children.OfType().Any(f => Vector2.DistanceSquared(f.Position, fruit.Position) < distance * distance)) + { + fruit.X += RNG.Next(-5, 5); + fruit.Y -= RNG.Next(0, 5); + } + + Add(fruit); + } } } } From 5704e9ee6553de4324dffa802cdf7bbada5108ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 12:56:22 +0900 Subject: [PATCH 34/67] Fix failing at beginning of map --- osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 3f29547e46..1c866320c9 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -19,6 +19,14 @@ namespace osu.Game.Rulesets.Catch.Scoring { } + protected override void Reset() + { + base.Reset(); + + Health.Value = 1; + Accuracy.Value = 1; + } + protected override void OnNewJudgement(CatchJudgement judgement) { } From c5ce86b9f3a1252f012391216c180c6c7cfa2568 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 8 Aug 2017 12:59:50 +0900 Subject: [PATCH 35/67] Add reversing capability to ScrollingPlayfield. --- .../Visual/TestCaseScrollingPlayfield.cs | 8 +++++- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 4 ++- .../Timing/SpeedAdjustmentContainer.cs | 19 ++++++++++++- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 27 ++++++++++++------- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 21f1aa603a..8334992d5a 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -24,6 +24,8 @@ namespace osu.Desktop.Tests.Visual /// public class TestCaseScrollingPlayfield : OsuTestCase { + private readonly TestHitRenderer hitRenderer; + public TestCaseScrollingPlayfield() { Clock = new FramedClock(); @@ -50,7 +52,9 @@ namespace osu.Desktop.Tests.Visual WorkingBeatmap beatmap = new TestWorkingBeatmap(b); - Add(new TestHitRenderer(beatmap, true)); + Add(hitRenderer = new TestHitRenderer(beatmap, true)); + + AddStep("Reverse direction", () => hitRenderer.Playfield.Reversed.Value = !hitRenderer.Playfield.Reversed); } private class TestHitRenderer : ScrollingHitRenderer @@ -60,6 +64,8 @@ namespace osu.Desktop.Tests.Visual { } + public new TestPlayfield Playfield => base.Playfield; + public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor(); protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 72b82ab60b..b836b54fa8 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -124,7 +124,9 @@ namespace osu.Game.Rulesets.Mania.UI for (int i = 0; i < columnCount; i++) { - var c = new Column { VisibleTimeRange = VisibleTimeRange }; + var c = new Column(); + c.VisibleTimeRange.BindTo(VisibleTimeRange); + columns.Add(c); AddNested(c); } diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index 4d5db9f720..de4bc8a22b 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -26,6 +26,16 @@ namespace osu.Game.Rulesets.Timing set { visibleTimeRange.BindTo(value); } } + private readonly BindableBool reversed = new BindableBool(); + /// + /// Whether to reverse the scrolling direction is reversed. + /// + public BindableBool Reversed + { + get { return reversed; } + set { reversed.BindTo(value); } + } + protected override Container Content => content; private Container content; @@ -70,7 +80,14 @@ namespace osu.Game.Rulesets.Timing // 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); - RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 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); + } + else + RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1); } public override double LifetimeStart => ControlPoint.StartTime - VisibleTimeRange; diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 1a88c74ebc..685eaa8e65 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -44,10 +44,10 @@ namespace osu.Game.Rulesets.UI private const double time_span_step = 50; /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. + /// The span 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. /// - private readonly BindableDouble visibleTimeRange = new BindableDouble(time_span_default) + public readonly BindableDouble VisibleTimeRange = new BindableDouble(time_span_default) { Default = time_span_default, MinValue = time_span_min, @@ -55,14 +55,9 @@ namespace osu.Game.Rulesets.UI }; /// - /// The span of time visible by the length of the scrolling axes. + /// Whether to reverse the scrolling direction is reversed. /// - /// - public BindableDouble VisibleTimeRange - { - get { return visibleTimeRange; } - set { visibleTimeRange.BindTo(value); } - } + public readonly BindableBool Reversed = new BindableBool(); /// /// The container that contains the s and s. @@ -80,7 +75,8 @@ namespace osu.Game.Rulesets.UI base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) { RelativeSizeAxes = Axes.Both, - VisibleTimeRange = VisibleTimeRange + VisibleTimeRange = VisibleTimeRange, + Reversed = Reversed }; } @@ -158,6 +154,16 @@ namespace osu.Game.Rulesets.UI set { visibleTimeRange.BindTo(value); } } + private readonly BindableBool reversed = new BindableBool(); + /// + /// Whether to reverse the scrolling direction is reversed. + /// + public BindableBool Reversed + { + get { return reversed; } + set { reversed.BindTo(value); } + } + protected override Container> Content => content; private readonly Container> content; @@ -188,6 +194,7 @@ namespace osu.Game.Rulesets.UI { speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); speedAdjustment.ScrollingAxes = scrollingAxes; + speedAdjustment.Reversed = Reversed; AddInternal(speedAdjustment); } From ee7bb1b4f5a787fea871d07adc029ab22f5348ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 09:20:54 +0900 Subject: [PATCH 36/67] Don't set RelativePositionAxes when setting ScrollingAxes (cherry picked from commit debe13629f07da44eb14489aa959eb772127c11e) --- .../Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs index 243fd79b6f..f67dd4dfea 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { set { - RelativePositionAxes = value; + RelativePositionAxes |= value; if ((value & Axes.X) > 0) X = (float)HitObject.StartTime; From a95aa90adc101f545ec7813baba14cb22b76ff46 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 10:53:59 +0900 Subject: [PATCH 37/67] Allow DrawableHitObjects to be removed from a Playfield (cherry picked from commit 3926238be992dfb4cb1e2b34f0e4f742b06157e1) --- osu.Game/Rulesets/UI/Playfield.cs | 6 ++++++ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 5f07df5088..ade2c2d070 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -82,6 +82,12 @@ namespace osu.Game.Rulesets.UI /// The DrawableHitObject to add. public virtual void Add(DrawableHitObject h) => HitObjects.Add(h); + /// + /// Remove a DrawableHitObject from this Playfield. + /// + /// The DrawableHitObject to remove. + public virtual void Remove(DrawableHitObject h) => HitObjects.Remove(h); + /// /// Triggered when an object's Judgement is updated. /// diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 685eaa8e65..96d3765eb5 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -211,6 +211,13 @@ namespace osu.Game.Rulesets.UI queuedHitObjects.Enqueue(hitObject); } + public override bool Remove(DrawableHitObject hitObject) + { + foreach (var c in InternalChildren.OfType()) + c.Remove(hitObject); + return true; + } + protected override void Update() { base.Update(); From ca2da5ac9bae231d16e6827064a2a2c200a6393d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 12:57:38 +0900 Subject: [PATCH 38/67] Don't crash on spinners --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 4e741b3a55..d6efe45adf 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -18,10 +18,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps protected override IEnumerable ConvertHitObject(HitObject obj, Beatmap beatmap) { - /*var distanceData = obj as IHasDistance; - var repeatsData = obj as IHasRepeats; - var endTimeData = obj as IHasEndTime; - var curveData = obj as IHasCurve;*/ + if (!(obj is IHasXPosition)) + yield break; yield return new Fruit { From e54abe8d0af71d30b21997b9709554e4e7966cd7 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 8 Aug 2017 13:23:46 +0900 Subject: [PATCH 39/67] Fix not removing queued hit objects. --- .../Timing/SpeedAdjustmentContainer.cs | 3 +++ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 27 ++++++++----------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index de4bc8a22b..f521fa18c4 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -87,7 +87,10 @@ namespace osu.Game.Rulesets.Timing RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 0); } else + { RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1); + RelativeChildOffset = Vector2.Zero; + } } public override double LifetimeStart => ControlPoint.StartTime - VisibleTimeRange; diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 96d3765eb5..adfcb6c971 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.UI /// /// Hit objects that are to be re-processed on the next update. /// - private readonly Queue> queuedHitObjects = new Queue>(); + private readonly List> queuedHitObjects = new List>(); private readonly Axes scrollingAxes; @@ -208,14 +208,15 @@ namespace osu.Game.Rulesets.UI if (!(hitObject is IScrollingHitObject)) throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}."); - queuedHitObjects.Enqueue(hitObject); + queuedHitObjects.Add(hitObject); } public override bool Remove(DrawableHitObject hitObject) { - foreach (var c in InternalChildren.OfType()) - c.Remove(hitObject); - return true; + bool removed = InternalChildren.OfType().Any(c => c.Remove(hitObject)); + removed = removed || queuedHitObjects.Remove(hitObject); + + return removed; } protected override void Update() @@ -225,22 +226,16 @@ namespace osu.Game.Rulesets.UI // Todo: At the moment this is going to re-process every single Update, however this will only be a null-op // when there are no SpeedAdjustmentContainers available. This should probably error or something, but it's okay for now. - // An external count is kept because hit objects that can't be added are re-queued - int count = queuedHitObjects.Count; - while (count-- > 0) + for (int i = queuedHitObjects.Count - 1; i >= 0; i--) { - var hitObject = queuedHitObjects.Dequeue(); + var hitObject = queuedHitObjects[i]; var target = adjustmentContainerFor(hitObject); - if (target == null) + if (target != null) { - // We can't add this hit object to a speed adjustment container yet, so re-queue it - // for re-processing when the layout next invalidated - queuedHitObjects.Enqueue(hitObject); - continue; + target.Add(hitObject); + queuedHitObjects.RemoveAt(i); } - - target.Add(hitObject); } } From 80c95d5b26e46a8729a05ebd215b68402d425e22 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 8 Aug 2017 13:24:15 +0900 Subject: [PATCH 40/67] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 107c551767..dd0daafcfc 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 107c5517670ca88dbe8c83a97e37e99ac5742ee6 +Subproject commit dd0daafcfc0d625bb588c8e12d7db58bc00c255e From 2203d55d647fd60072f96eed7ac35e564a704210 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 13:31:55 +0900 Subject: [PATCH 41/67] fixes --- osu-framework | 2 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 4 ++-- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 7 ------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/osu-framework b/osu-framework index 8413a36fd2..dd0daafcfc 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 8413a36fd26f3bae2a789208a9317b4511c35e99 +Subproject commit dd0daafcfc0d625bb588c8e12d7db58bc00c255e diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 388444d49d..4ea6d180f3 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Catch.UI public CatchPlayfield() : base(Axes.Y) { + Reversed.Value = true; + Size = new Vector2(1); Anchor = Anchor.TopCentre; @@ -30,9 +32,7 @@ namespace osu.Game.Rulesets.Catch.UI { content = new Container { - Scale = new Vector2(1, -1), RelativeSizeAxes = Axes.Both, - Origin = Anchor.BottomLeft }, catcherArea = new CatcherArea { diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 6929967a96..adfcb6c971 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -219,13 +219,6 @@ namespace osu.Game.Rulesets.UI return removed; } - public override bool Remove(DrawableHitObject hitObject) - { - foreach (var c in InternalChildren.OfType()) - c.Remove(hitObject); - return true; - } - protected override void Update() { base.Update(); From 25202b522df20b2765e6e2ba79c07984387b23d9 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 8 Aug 2017 14:10:26 +0900 Subject: [PATCH 42/67] Fix not setting Origin + Anchors properly when reversing. --- osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index f521fa18c4..d582f19660 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -85,11 +85,13 @@ namespace osu.Game.Rulesets.Timing { 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.BottomLeft; } else { RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1); RelativeChildOffset = Vector2.Zero; + Anchor = Anchor = Anchor.TopLeft; } } From 9e01b47a093629c61062821b776f1c5560ac8e24 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 8 Aug 2017 14:15:08 +0900 Subject: [PATCH 43/67] Convert to local object. --- osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 8334992d5a..7f067efa78 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -24,8 +24,6 @@ namespace osu.Desktop.Tests.Visual /// public class TestCaseScrollingPlayfield : OsuTestCase { - private readonly TestHitRenderer hitRenderer; - public TestCaseScrollingPlayfield() { Clock = new FramedClock(); @@ -52,6 +50,7 @@ namespace osu.Desktop.Tests.Visual WorkingBeatmap beatmap = new TestWorkingBeatmap(b); + TestHitRenderer hitRenderer; Add(hitRenderer = new TestHitRenderer(beatmap, true)); AddStep("Reverse direction", () => hitRenderer.Playfield.Reversed.Value = !hitRenderer.Playfield.Reversed); From cae21869d0ed470ca6d420638a84672b67ddc70b Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 8 Aug 2017 17:37:11 +0900 Subject: [PATCH 44/67] Use CompositeDrawable for HitObjectContainer. Removes a looooooot of generics :+1:. --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 4 +-- osu.Game/Rulesets/UI/Playfield.cs | 18 ++++++++------ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 29 ++++++++-------------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index e80ac933c8..2604b1ee8a 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -80,9 +80,9 @@ namespace osu.Game.Rulesets.Osu.UI public override void PostProcess() { - connectionLayer.HitObjects = HitObjects.Children + connectionLayer.HitObjects = HitObjects.Objects .Select(d => d.HitObject) - .OrderBy(h => h.StartTime); + .OrderBy(h => h.StartTime).OfType(); } public override void OnJudgement(DrawableHitObject judgedObject) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index ade2c2d070..cc16eff6d6 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -9,6 +9,8 @@ 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 { @@ -19,7 +21,7 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - public HitObjectContainer> HitObjects { get; protected set; } + public HitObjectContainer HitObjects { get; protected set; } internal Container ScaledContent; @@ -53,7 +55,7 @@ namespace osu.Game.Rulesets.UI } }); - HitObjects = new HitObjectContainer> + HitObjects = new HitObjectContainer { RelativeSizeAxes = Axes.Both, }; @@ -94,6 +96,13 @@ namespace osu.Game.Rulesets.UI /// The object that Judgement has been updated for. public virtual void OnJudgement(DrawableHitObject judgedObject) { } + public class HitObjectContainer : CompositeDrawable + { + public virtual IEnumerable Objects => InternalChildren.OfType(); + public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); + public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); + } + private class ScaledContainer : Container { /// @@ -104,10 +113,5 @@ namespace osu.Game.Rulesets.UI //dividing by the customwidth will effectively scale our content to the required container size. protected override Vector2 DrawScale => CustomWidth.HasValue ? new Vector2(DrawSize.X / CustomWidth.Value) : base.DrawScale; } - - public class HitObjectContainer : Container - where U : Drawable - { - } } } diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index adfcb6c971..a54ece4c05 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -141,7 +141,7 @@ namespace osu.Game.Rulesets.UI /// /// A container that provides the foundation for sorting s into s. /// - internal class ScrollingHitObjectContainer : HitObjectContainer> + internal class ScrollingHitObjectContainer : HitObjectContainer { private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; /// @@ -164,13 +164,11 @@ namespace osu.Game.Rulesets.UI set { reversed.BindTo(value); } } - protected override Container> Content => content; - private readonly Container> content; - /// /// Hit objects that are to be re-processed on the next update. /// - private readonly List> queuedHitObjects = new List>(); + private readonly List queuedHitObjects = new List(); + private readonly Container speedAdjustments; private readonly Axes scrollingAxes; @@ -182,8 +180,7 @@ namespace osu.Game.Rulesets.UI { this.scrollingAxes = scrollingAxes; - // The following is never used - it only exists for the purpose of being able to use AddInternal below. - content = new Container>(); + AddInternal(speedAdjustments = new Container { RelativeSizeAxes = Axes.Both }); } /// @@ -195,15 +192,17 @@ namespace osu.Game.Rulesets.UI speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); speedAdjustment.ScrollingAxes = scrollingAxes; speedAdjustment.Reversed = Reversed; - AddInternal(speedAdjustment); + speedAdjustments.Add(speedAdjustment); } + 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) + public override void Add(DrawableHitObject hitObject) { if (!(hitObject is IScrollingHitObject)) throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}."); @@ -211,13 +210,7 @@ namespace osu.Game.Rulesets.UI queuedHitObjects.Add(hitObject); } - public override bool Remove(DrawableHitObject hitObject) - { - bool removed = InternalChildren.OfType().Any(c => c.Remove(hitObject)); - removed = removed || queuedHitObjects.Remove(hitObject); - - return removed; - } + public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)) || queuedHitObjects.Remove(hitObject); protected override void Update() { @@ -246,7 +239,7 @@ namespace osu.Game.Rulesets.UI /// /// The hit object to find the active for. /// The active at 's start time. Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => InternalChildren.OfType().FirstOrDefault(c => c.CanContain(hitObject)) ?? InternalChildren.OfType().LastOrDefault(); + private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => speedAdjustments.FirstOrDefault(c => c.CanContain(hitObject)) ?? speedAdjustments.LastOrDefault(); /// /// Finds the which provides the speed adjustment active at a time. @@ -254,7 +247,7 @@ namespace osu.Game.Rulesets.UI /// /// The time to find the active at. /// The active at . Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerAt(double time) => InternalChildren.OfType().FirstOrDefault(c => c.CanContain(time)) ?? InternalChildren.OfType().LastOrDefault(); + private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.FirstOrDefault(c => c.CanContain(time)) ?? speedAdjustments.LastOrDefault(); } } } \ No newline at end of file From 9e17549d7f778678e67925bc7234ffc3b23f985b Mon Sep 17 00:00:00 2001 From: John Neijzen Date: Tue, 8 Aug 2017 22:56:27 +0800 Subject: [PATCH 45/67] Update HitObjectPatternGenerator.cs --- .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index b1ba99d98b..b65f92e1dc 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy // More than 111 BPM stream convertType |= PatternType.Cycle | PatternType.KeepSingle; } - else if (timeSeparation <= 150 & positionSeparation < 20) + else if (timeSeparation <= 150 && positionSeparation < 20) { // More than 100 BPM stream convertType |= PatternType.ForceStack | PatternType.LowProbability; @@ -401,4 +401,4 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy }); } } -} \ No newline at end of file +} From 21d44b1e99e0916981a17ec91b66b8320d6ccf40 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 9 Aug 2017 06:24:08 +0900 Subject: [PATCH 46/67] Remove correct duplicate code. Already present on line 51. --- .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index b65f92e1dc..99f55cb98b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -33,12 +33,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy float positionSeparation = ((positionData?.Position ?? Vector2.Zero) - previousPosition).Length; double timeSeparation = hitObject.StartTime - previousTime; - if (timeSeparation <= 125) - { - // More than 120 BPM - convertType |= PatternType.ForceNotStack; - } - if (timeSeparation <= 80) { // More than 187 BPM From 56caa6ef10482f9834bf67dcb712157be90b2727 Mon Sep 17 00:00:00 2001 From: Jorolf Date: Wed, 9 Aug 2017 01:48:30 +0200 Subject: [PATCH 47/67] fix tests argument --- osu.Desktop/osu.Desktop.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 8ffa6b62f7..bbca4145c6 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -103,6 +103,7 @@ 6 prompt AllRules.ruleset + --tests From 482626adc27d94acbdc909d21a93633f33b242cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Aug 2017 12:57:38 +0900 Subject: [PATCH 48/67] Don't crash on spinners --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 4e741b3a55..d6efe45adf 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -18,10 +18,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps protected override IEnumerable ConvertHitObject(HitObject obj, Beatmap beatmap) { - /*var distanceData = obj as IHasDistance; - var repeatsData = obj as IHasRepeats; - var endTimeData = obj as IHasEndTime; - var curveData = obj as IHasCurve;*/ + if (!(obj is IHasXPosition)) + yield break; yield return new Fruit { From 1c7fe02d1b73838d2ca286a86b98225e3a519b84 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 08:56:45 +0900 Subject: [PATCH 49/67] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 8413a36fd2..d29abdf0d0 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 8413a36fd26f3bae2a789208a9317b4511c35e99 +Subproject commit d29abdf0d042d832f0849c013d14762db04730e7 From 06e5f7de096ad87088003705cd863585016d4d53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 10:16:31 +0900 Subject: [PATCH 50/67] Make pulp size private --- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 0aba83696c..62e5c094be 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableFruit : DrawableScrollingHitObject { - const float pulp_size = 30; + private const float pulp_size = 30; private class Pulp : Circle, IHasAccentColour { From b88f37de455f78511b13e50e06cd4f66483c79cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 11:50:34 +0900 Subject: [PATCH 51/67] Add custom actions for Catch Reworks input management for rulesets --- osu.Desktop.Tests/Visual/TestCaseCatcher.cs | 17 ++++-- .../RulesetInputManager.cs | 32 +++++++++++ .../UI/CatchHitRenderer.cs | 3 + osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 56 +++++++++---------- .../osu.Game.Rulesets.Catch.csproj | 2 + .../OsuKeyConversionInputManager.cs | 3 +- osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs | 4 +- osu.Game/Input/ActionMappingInputManager.cs | 34 +++++++++++ osu.Game/Rulesets/UI/HitRenderer.cs | 5 +- .../Screens/Play/KeyConversionInputManager.cs | 16 ------ osu.Game/osu.Game.csproj | 2 +- 11 files changed, 116 insertions(+), 58 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/RulesetInputManager.cs create mode 100644 osu.Game/Input/ActionMappingInputManager.cs delete mode 100644 osu.Game/Screens/Play/KeyConversionInputManager.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseCatcher.cs b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs index 0e92b5114b..de32608a6c 100644 --- a/osu.Desktop.Tests/Visual/TestCaseCatcher.cs +++ b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; +using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Catch.UI; using OpenTK; @@ -15,14 +16,18 @@ namespace osu.Desktop.Tests.Visual Children = new Drawable[] { - new CatcherArea + new CatchInputManager { - RelativePositionAxes = Axes.Both, RelativeSizeAxes = Axes.Both, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Size = new Vector2(1, 0.2f), - } + Child = new CatcherArea + { + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Size = new Vector2(1, 0.2f), + } + }, }; } } diff --git a/osu.Game.Rulesets.Catch/RulesetInputManager.cs b/osu.Game.Rulesets.Catch/RulesetInputManager.cs new file mode 100644 index 0000000000..78bd18baa3 --- /dev/null +++ b/osu.Game.Rulesets.Catch/RulesetInputManager.cs @@ -0,0 +1,32 @@ +// 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.Input; +using OpenTK.Input; + +namespace osu.Game.Rulesets.Catch +{ + public class CatchInputManager : ActionMappingInputManager + { + public CatchInputManager() + { + Mappings = new Dictionary + { + { Key.Z, CatchAction.MoveLeft }, + { Key.Left, CatchAction.MoveLeft }, + { Key.X, CatchAction.MoveRight }, + { Key.Right, CatchAction.MoveRight }, + { Key.LShift, CatchAction.Dash }, + { Key.RShift, CatchAction.Dash }, + }; + } + } + + public enum CatchAction + { + MoveLeft, + MoveRight, + Dash + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs index 8f614cc4c3..04e3036db6 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.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 osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps; @@ -27,6 +28,8 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(); + protected override PassThroughInputManager CreateKeyConversionInputManager() => new CatchInputManager(); + protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) { if (h is Fruit) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 6ed8030941..f0a6b89d7e 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -15,7 +15,6 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; -using OpenTK.Input; namespace osu.Game.Rulesets.Catch.UI { @@ -63,9 +62,6 @@ namespace osu.Game.Rulesets.Catch.UI Child = createCatcherSprite(); } - private bool leftPressed; - private bool rightPressed; - private int currentDirection; private bool dashing; @@ -114,19 +110,20 @@ namespace osu.Game.Rulesets.Catch.UI { if (args.Repeat) return true; - switch (args.Key) + if (state.Data is CatchAction) { - case Key.Left: - currentDirection = -1; - leftPressed = true; - return true; - case Key.Right: - currentDirection = 1; - rightPressed = true; - return true; - case Key.ShiftLeft: - Dashing = true; - return true; + switch ((CatchAction)state.Data) + { + case CatchAction.MoveLeft: + currentDirection--; + return true; + case CatchAction.MoveRight: + currentDirection++; + return true; + case CatchAction.Dash: + Dashing = true; + return true; + } } return base.OnKeyDown(state, args); @@ -134,19 +131,20 @@ namespace osu.Game.Rulesets.Catch.UI protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) { - switch (args.Key) + if (state.Data is CatchAction) { - case Key.Left: - currentDirection = rightPressed ? 1 : 0; - leftPressed = false; - return true; - case Key.Right: - currentDirection = leftPressed ? -1 : 0; - rightPressed = false; - return true; - case Key.ShiftLeft: - Dashing = false; - return true; + switch ((CatchAction)state.Data) + { + case CatchAction.MoveLeft: + currentDirection++; + return true; + case CatchAction.MoveRight: + currentDirection--; + return true; + case CatchAction.Dash: + Dashing = false; + return true; + } } return base.OnKeyUp(state, args); @@ -161,7 +159,7 @@ namespace osu.Game.Rulesets.Catch.UI float speed = Dashing ? 1.5f : 1; Scale = new Vector2(Math.Sign(currentDirection), 1); - X = (float)MathHelper.Clamp(X + currentDirection * Clock.ElapsedFrameTime / 1800 * speed, 0, 1); + X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime / 1800 * speed, 0, 1); } public void AddToStack(DrawableHitObject fruit, Vector2 absolutePosition) diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 003fe2763e..fcffcb8060 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -38,6 +38,7 @@ True + @@ -50,6 +51,7 @@ + diff --git a/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs b/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs index d60aab90fb..10adca4e43 100644 --- a/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs @@ -3,14 +3,13 @@ using System.Linq; using osu.Framework.Input; -using osu.Game.Screens.Play; using OpenTK.Input; using KeyboardState = osu.Framework.Input.KeyboardState; using MouseState = osu.Framework.Input.MouseState; namespace osu.Game.Rulesets.Osu { - public class OsuKeyConversionInputManager : KeyConversionInputManager + public class OsuKeyConversionInputManager : PassThroughInputManager { private bool leftViaKeyboard; private bool rightViaKeyboard; diff --git a/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs b/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs index e582d2fcd3..e59af40db4 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.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 osu.Framework.Input; using OpenTK; using osu.Game.Beatmaps; using osu.Game.Rulesets.Beatmaps; @@ -12,7 +13,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; namespace osu.Game.Rulesets.Osu.UI { @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override Playfield CreatePlayfield() => new OsuPlayfield(); - protected override KeyConversionInputManager CreateKeyConversionInputManager() => new OsuKeyConversionInputManager(); + protected override PassThroughInputManager CreateKeyConversionInputManager() => new OsuKeyConversionInputManager(); protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { diff --git a/osu.Game/Input/ActionMappingInputManager.cs b/osu.Game/Input/ActionMappingInputManager.cs new file mode 100644 index 0000000000..5e2facdc93 --- /dev/null +++ b/osu.Game/Input/ActionMappingInputManager.cs @@ -0,0 +1,34 @@ +// 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.Framework.Input; +using OpenTK.Input; + +namespace osu.Game.Input +{ + public class ActionMappingInputManager : PassThroughInputManager + where T : struct + { + protected IDictionary Mappings { get; set; } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + mapKey(state, args.Key); + return base.OnKeyDown(state, args); + } + + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + { + mapKey(state, args.Key); + return base.OnKeyUp(state, args); + } + + private void mapKey(InputState state, Key key) + { + T mappedData; + if (Mappings.TryGetValue(key, out mappedData)) + state.Data = mappedData; + } + } +} diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index 47339fb6e6..244c3312c4 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -14,6 +14,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using osu.Framework.Input; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using OpenTK; @@ -47,7 +48,7 @@ namespace osu.Game.Rulesets.UI /// /// The key conversion input manager for this HitRenderer. /// - protected readonly KeyConversionInputManager KeyConversionInputManager; + protected readonly PassThroughInputManager KeyConversionInputManager; /// /// Whether we are currently providing the local user a gameplay cursor. @@ -87,7 +88,7 @@ namespace osu.Game.Rulesets.UI /// Creates a key conversion input manager. /// /// The input manager. - protected virtual KeyConversionInputManager CreateKeyConversionInputManager() => new KeyConversionInputManager(); + protected virtual PassThroughInputManager CreateKeyConversionInputManager() => new PassThroughInputManager(); protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay); diff --git a/osu.Game/Screens/Play/KeyConversionInputManager.cs b/osu.Game/Screens/Play/KeyConversionInputManager.cs deleted file mode 100644 index f3ca764bd7..0000000000 --- a/osu.Game/Screens/Play/KeyConversionInputManager.cs +++ /dev/null @@ -1,16 +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.Input; - -namespace osu.Game.Screens.Play -{ - /// - /// An InputManager primarily used to map keys to new functions. - /// By default this does nothing; override TransformState to make alterations. - /// - public class KeyConversionInputManager : PassThroughInputManager - { - - } -} \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 17596f0f49..0a73754e14 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -118,6 +118,7 @@ + @@ -309,7 +310,6 @@ - From dfb47b571a6ae22e5e6a13c3d76523e0d09156b3 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 12:24:38 +0900 Subject: [PATCH 52/67] Make HitRenderer's Playfield public so it can be used in testing. --- osu.Game/Rulesets/UI/HitRenderer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index 47339fb6e6..13ea83dc48 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -225,7 +225,7 @@ namespace osu.Game.Rulesets.UI /// /// The playfield. /// - protected Playfield Playfield { get; private set; } + public Playfield Playfield { get; private set; } protected override Container Content => content; private readonly Container content; From eee64049866a6aa60a57ae9985d6d29722361c98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 12:37:47 +0900 Subject: [PATCH 53/67] Store bindings to database --- osu.Game/Input/ActionMappingInputManager.cs | 53 +++++++++++++++++++++ osu.Game/OsuGameBase.cs | 4 ++ 2 files changed, 57 insertions(+) diff --git a/osu.Game/Input/ActionMappingInputManager.cs b/osu.Game/Input/ActionMappingInputManager.cs index 5e2facdc93..89e8686a2c 100644 --- a/osu.Game/Input/ActionMappingInputManager.cs +++ b/osu.Game/Input/ActionMappingInputManager.cs @@ -1,9 +1,16 @@ // 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.Allocation; using osu.Framework.Input; +using osu.Framework.Platform; +using osu.Game.Database; +using osu.Game.Rulesets; using OpenTK.Input; +using SQLite.Net; +using SQLiteNetExtensions.Attributes; namespace osu.Game.Input { @@ -12,6 +19,13 @@ namespace osu.Game.Input { protected IDictionary Mappings { get; set; } + [BackgroundDependencyLoader] + private void load(BindingStore bindings) + { + foreach (var b in bindings.Query()) + Mappings[b.Key] = (T)(object)b.Action; + } + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { mapKey(state, args.Key); @@ -30,5 +44,44 @@ namespace osu.Game.Input if (Mappings.TryGetValue(key, out mappedData)) state.Data = mappedData; } + + private T parseStringRepresentation(string str) + { + T res; + + if (Enum.TryParse(str, out res)) + return res; + + return default(T); + } + } + + public class Binding + { + [ForeignKey(typeof(RulesetInfo))] + public int? RulesetID { get; set; } + + public Key Key { get; set; } + + public int Action { get; set; } + } + + public class BindingStore : DatabaseBackedStore + { + public BindingStore(SQLiteConnection connection, Storage storage = null) + : base(connection, storage) + { + } + + protected override void Prepare(bool reset = false) + { + Connection.CreateTable(); + } + + protected override Type[] ValidTypes => new[] + { + typeof(Binding) + }; + } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 0dec4228de..b76235f3f4 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -19,6 +19,7 @@ using osu.Game.Online.API; using SQLite.Net; using osu.Framework.Graphics.Performance; using osu.Game.Database; +using osu.Game.Input; using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; @@ -37,6 +38,8 @@ namespace osu.Game protected ScoreStore ScoreStore; + protected BindingStore BindingStore; + protected override string MainResourceFile => @"osu.Game.Resources.dll"; public APIAccess API; @@ -104,6 +107,7 @@ namespace osu.Game dependencies.Cache(FileStore = new FileStore(connection, Host.Storage)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, FileStore, connection, RulesetStore, Host)); dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, connection, Host, BeatmapManager)); + dependencies.Cache(BindingStore = new BindingStore(connection)); dependencies.Cache(new OsuColour()); //this completely overrides the framework default. will need to change once we make a proper FontStore. From 1c5584f06879191abbd2458da1299ee14031cbc2 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 12:45:50 +0900 Subject: [PATCH 54/67] Make ScrollingPlayfield store a list of SpeedAdjustments instead of a Container. Because they're removed from the container when they're not alive, and any further adding methods fail. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index a54ece4c05..204742eec9 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -168,7 +168,7 @@ namespace osu.Game.Rulesets.UI /// Hit objects that are to be re-processed on the next update. /// private readonly List queuedHitObjects = new List(); - private readonly Container speedAdjustments; + private readonly List speedAdjustments = new List(); private readonly Axes scrollingAxes; @@ -179,8 +179,6 @@ namespace osu.Game.Rulesets.UI public ScrollingHitObjectContainer(Axes scrollingAxes) { this.scrollingAxes = scrollingAxes; - - AddInternal(speedAdjustments = new Container { RelativeSizeAxes = Axes.Both }); } /// @@ -193,6 +191,8 @@ namespace osu.Game.Rulesets.UI speedAdjustment.ScrollingAxes = scrollingAxes; speedAdjustment.Reversed = Reversed; speedAdjustments.Add(speedAdjustment); + + AddInternal(speedAdjustment); } public override IEnumerable Objects => speedAdjustments.SelectMany(s => s.Children); From 7c0e7ebcd0e734ba69cf4da5140b9a583aba3204 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 13:04:11 +0900 Subject: [PATCH 55/67] Give HitRenderer a reference to Ruleset Used to get correct bindings for a mode (ActionMappingInputManager). --- osu.Desktop.Tests/Visual/TestCaseCatcher.cs | 9 ++++--- osu.Desktop.Tests/Visual/TestCaseGamefield.cs | 12 ++++++--- .../Visual/TestCaseScrollingPlayfield.cs | 2 +- osu.Game.Rulesets.Catch/CatchRuleset.cs | 7 ++++- .../RulesetInputManager.cs | 2 +- .../UI/CatchHitRenderer.cs | 6 ++--- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 7 ++++- .../UI/ManiaHitRenderer.cs | 4 +-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 7 ++++- osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs | 6 ++--- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 7 ++++- .../UI/TaikoHitRenderer.cs | 5 ++-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 7 ++++- osu.Game/Input/ActionMappingInputManager.cs | 10 ++++++- osu.Game/Rulesets/Ruleset.cs | 7 +++++ osu.Game/Rulesets/RulesetInfo.cs | 2 +- osu.Game/Rulesets/RulesetStore.cs | 2 +- osu.Game/Rulesets/UI/HitRenderer.cs | 26 +++++++++++++------ osu.Game/Rulesets/UI/ScrollingHitRenderer.cs | 4 +-- 19 files changed, 93 insertions(+), 39 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseCatcher.cs b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs index de32608a6c..3f57b5eeb9 100644 --- a/osu.Desktop.Tests/Visual/TestCaseCatcher.cs +++ b/osu.Desktop.Tests/Visual/TestCaseCatcher.cs @@ -1,7 +1,9 @@ // 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.Graphics; +using osu.Game.Rulesets; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Catch.UI; using OpenTK; @@ -10,13 +12,12 @@ namespace osu.Desktop.Tests.Visual { internal class TestCaseCatcher : OsuTestCase { - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) { - base.LoadComplete(); - Children = new Drawable[] { - new CatchInputManager + new CatchInputManager(rulesets.GetRuleset(2)) { RelativeSizeAxes = Axes.Both, Child = new CatcherArea diff --git a/osu.Desktop.Tests/Visual/TestCaseGamefield.cs b/osu.Desktop.Tests/Visual/TestCaseGamefield.cs index 9d61c9ab0c..98dda56d41 100644 --- a/osu.Desktop.Tests/Visual/TestCaseGamefield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseGamefield.cs @@ -11,11 +11,15 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets; +using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Taiko; using osu.Game.Rulesets.Taiko.UI; using OpenTK; @@ -84,25 +88,25 @@ namespace osu.Desktop.Tests.Visual Clock = new FramedClock(), Children = new Drawable[] { - new OsuHitRenderer(beatmap, false) + new OsuHitRenderer(new OsuRuleset(new RulesetInfo()), beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft }, - new TaikoHitRenderer(beatmap, false) + new TaikoHitRenderer(new TaikoRuleset(new RulesetInfo()),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.TopRight, Origin = Anchor.TopRight }, - new CatchHitRenderer(beatmap, false) + new CatchHitRenderer(new CatchRuleset(new RulesetInfo()),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, - new ManiaHitRenderer(beatmap, false) + new ManiaHitRenderer(new ManiaRuleset(new RulesetInfo()),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.BottomRight, diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 7f067efa78..aaa2f7d49d 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -59,7 +59,7 @@ namespace osu.Desktop.Tests.Visual private class TestHitRenderer : ScrollingHitRenderer { public TestHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) + : base(null, beatmap, isForCurrentRuleset) { } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index dc13329bde..66e2fd30bb 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchHitRenderer(beatmap, isForCurrentRuleset); + public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchHitRenderer(this, beatmap, isForCurrentRuleset); public override IEnumerable GetModsFor(ModType type) { @@ -102,5 +102,10 @@ namespace osu.Game.Rulesets.Catch public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); public override int LegacyID => 2; + + public CatchRuleset(RulesetInfo rulesetInfo) + : base(rulesetInfo) + { + } } } diff --git a/osu.Game.Rulesets.Catch/RulesetInputManager.cs b/osu.Game.Rulesets.Catch/RulesetInputManager.cs index 78bd18baa3..eada5cf532 100644 --- a/osu.Game.Rulesets.Catch/RulesetInputManager.cs +++ b/osu.Game.Rulesets.Catch/RulesetInputManager.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchInputManager : ActionMappingInputManager { - public CatchInputManager() + public CatchInputManager(RulesetInfo ruleset) : base(ruleset) { Mappings = new Dictionary { diff --git a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs index 04e3036db6..d08b349459 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs @@ -17,8 +17,8 @@ namespace osu.Game.Rulesets.Catch.UI { public class CatchHitRenderer : ScrollingHitRenderer { - public CatchHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) + public CatchHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(ruleset, beatmap, isForCurrentRuleset) { } @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(); - protected override PassThroughInputManager CreateKeyConversionInputManager() => new CatchInputManager(); + protected override PassThroughInputManager CreateActionMappingInputManager() => new CatchInputManager(Ruleset.RulesetInfo); protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) { diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index a8a89a57e0..b61230d347 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaHitRenderer(beatmap, isForCurrentRuleset); + public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaHitRenderer(this, beatmap, isForCurrentRuleset); public override IEnumerable GetModsFor(ModType type) { @@ -118,5 +118,10 @@ namespace osu.Game.Rulesets.Mania public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); public override int LegacyID => 3; + + public ManiaRuleset(RulesetInfo rulesetInfo) + : base(rulesetInfo) + { + } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 0b8ad10b16..ffb3ad4a45 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -38,8 +38,8 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; - public ManiaHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) + public ManiaHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(ruleset, beatmap, isForCurrentRuleset) { // Generate the bar lines double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 9a1971d791..d80beaf0a3 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuHitRenderer(beatmap, isForCurrentRuleset); + public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuHitRenderer(this, beatmap, isForCurrentRuleset); public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new[] { @@ -126,5 +126,10 @@ namespace osu.Game.Rulesets.Osu public override SettingsSubsection CreateSettings() => new OsuSettings(); public override int LegacyID => 0; + + public OsuRuleset(RulesetInfo rulesetInfo) + : base(rulesetInfo) + { + } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs b/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs index e59af40db4..1356e97907 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs @@ -18,8 +18,8 @@ namespace osu.Game.Rulesets.Osu.UI { public class OsuHitRenderer : HitRenderer { - public OsuHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) + public OsuHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(ruleset, beatmap, isForCurrentRuleset) { } @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override Playfield CreatePlayfield() => new OsuPlayfield(); - protected override PassThroughInputManager CreateKeyConversionInputManager() => new OsuKeyConversionInputManager(); + protected override PassThroughInputManager CreateActionMappingInputManager() => new OsuKeyConversionInputManager(); protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 83db9b35af..9b2536a7ec 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoHitRenderer(beatmap, isForCurrentRuleset); + public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoHitRenderer(this, beatmap, isForCurrentRuleset); public override IEnumerable GetModsFor(ModType type) { @@ -103,5 +103,10 @@ namespace osu.Game.Rulesets.Taiko public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); public override int LegacyID => 1; + + public TaikoRuleset(RulesetInfo rulesetInfo) + : base(rulesetInfo) + { + } } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs index 570b4be488..cb89cfed72 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs @@ -23,8 +23,8 @@ namespace osu.Game.Rulesets.Taiko.UI { public class TaikoHitRenderer : HitRenderer { - public TaikoHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) + public TaikoHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(ruleset, beatmap, isForCurrentRuleset) { } @@ -93,7 +93,6 @@ namespace osu.Game.Rulesets.Taiko.UI return new Vector2(1, default_relative_height * aspectAdjust); } - public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index bd53a80555..7538893cb7 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps private class DummyRulesetInfo : RulesetInfo { - public override Ruleset CreateInstance() => new DummyRuleset(); + public override Ruleset CreateInstance() => new DummyRuleset(this); private class DummyRuleset : Ruleset { @@ -77,6 +77,11 @@ namespace osu.Game.Beatmaps public override string Description => "dummy"; public override IEnumerable CreateGameplayKeys() => new List(); + + public DummyRuleset(RulesetInfo rulesetInfo) + : base(rulesetInfo) + { + } } } } diff --git a/osu.Game/Input/ActionMappingInputManager.cs b/osu.Game/Input/ActionMappingInputManager.cs index 89e8686a2c..2e78b49b75 100644 --- a/osu.Game/Input/ActionMappingInputManager.cs +++ b/osu.Game/Input/ActionMappingInputManager.cs @@ -17,12 +17,20 @@ namespace osu.Game.Input public class ActionMappingInputManager : PassThroughInputManager where T : struct { + private readonly RulesetInfo ruleset; + + protected ActionMappingInputManager(RulesetInfo ruleset = null) + { + this.ruleset = ruleset; + } + protected IDictionary Mappings { get; set; } [BackgroundDependencyLoader] private void load(BindingStore bindings) { - foreach (var b in bindings.Query()) + var rulesetId = ruleset?.ID; + foreach (var b in bindings.Query(b => b.RulesetID == rulesetId)) Mappings[b.Key] = (T)(object)b.Action; } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index b3be36a983..4a492b84fb 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -15,12 +15,19 @@ namespace osu.Game.Rulesets { public abstract class Ruleset { + public readonly RulesetInfo RulesetInfo; + public virtual IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { }; public abstract IEnumerable GetModsFor(ModType type); public abstract Mod GetAutoplayMod(); + protected Ruleset(RulesetInfo rulesetInfo) + { + RulesetInfo = rulesetInfo; + } + /// /// Attempt to create a hit renderer for a beatmap /// diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 84ecb7718e..bc23649ede 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -20,6 +20,6 @@ namespace osu.Game.Rulesets [Indexed] public bool Available { get; set; } - public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo)); + public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this); } } \ No newline at end of file diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 1564df1366..2956c11d7f 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets continue; foreach (Type rulesetType in rulesets) - instances.Add((Ruleset)Activator.CreateInstance(rulesetType)); + instances.Add((Ruleset)Activator.CreateInstance(rulesetType, new RulesetInfo())); } catch (Exception) { } } diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index 244c3312c4..00f8e8a469 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -67,9 +67,16 @@ namespace osu.Game.Rulesets.UI /// protected abstract bool AllObjectsJudged { get; } - internal HitRenderer() + protected readonly Ruleset Ruleset; + + /// + /// A visual representation of a . + /// + /// The ruleset being repesented. + internal HitRenderer(Ruleset ruleset) { - KeyConversionInputManager = CreateKeyConversionInputManager(); + Ruleset = ruleset; + KeyConversionInputManager = CreateActionMappingInputManager(); KeyConversionInputManager.RelativeSizeAxes = Axes.Both; } @@ -88,7 +95,7 @@ namespace osu.Game.Rulesets.UI /// Creates a key conversion input manager. /// /// The input manager. - protected virtual PassThroughInputManager CreateKeyConversionInputManager() => new PassThroughInputManager(); + protected virtual PassThroughInputManager CreateActionMappingInputManager() => new PassThroughInputManager(); protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay); @@ -134,9 +141,10 @@ namespace osu.Game.Rulesets.UI /// /// Creates a hit renderer for a beatmap. /// + /// The ruleset being repesented. /// The beatmap to create the hit renderer for. /// Whether to assume the beatmap is for the current ruleset. - internal HitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) + internal HitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset) { Debug.Assert(beatmap != null, "HitRenderer initialized with a null beatmap."); @@ -236,10 +244,11 @@ namespace osu.Game.Rulesets.UI /// /// Creates a hit renderer for a beatmap. /// + /// The ruleset being repesented. /// The beatmap to create the hit renderer for. /// Whether to assume the beatmap is for the current ruleset. - protected HitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) + protected HitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(ruleset, beatmap, isForCurrentRuleset) { InputManager.Add(content = new Container { @@ -343,10 +352,11 @@ namespace osu.Game.Rulesets.UI /// /// Creates a hit renderer for a beatmap. /// + /// The ruleset being repesented. /// The beatmap to create the hit renderer for. /// Whether to assume the beatmap is for the current ruleset. - protected HitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) + protected HitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(ruleset, beatmap, isForCurrentRuleset) { } } diff --git a/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs b/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs index da4340ac7a..37df08ba21 100644 --- a/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs +++ b/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs @@ -32,8 +32,8 @@ namespace osu.Game.Rulesets.UI /// protected readonly SortedList DefaultControlPoints = new SortedList(Comparer.Default); - protected ScrollingHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(beatmap, isForCurrentRuleset) + protected ScrollingHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(ruleset, beatmap, isForCurrentRuleset) { } From f21b370f4e2098a61ef9e1de431ab5b11d48bda9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 13:23:23 +0900 Subject: [PATCH 56/67] Add variant for rulesets with more than one possible key layout --- osu.Game/Input/ActionMappingInputManager.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Input/ActionMappingInputManager.cs b/osu.Game/Input/ActionMappingInputManager.cs index 2e78b49b75..d926b888c5 100644 --- a/osu.Game/Input/ActionMappingInputManager.cs +++ b/osu.Game/Input/ActionMappingInputManager.cs @@ -10,6 +10,7 @@ using osu.Game.Database; using osu.Game.Rulesets; using OpenTK.Input; using SQLite.Net; +using SQLite.Net.Attributes; using SQLiteNetExtensions.Attributes; namespace osu.Game.Input @@ -19,9 +20,12 @@ namespace osu.Game.Input { private readonly RulesetInfo ruleset; - protected ActionMappingInputManager(RulesetInfo ruleset = null) + private readonly int? variant; + + protected ActionMappingInputManager(RulesetInfo ruleset = null, int? variant = null) { this.ruleset = ruleset; + this.variant = variant; } protected IDictionary Mappings { get; set; } @@ -30,7 +34,7 @@ namespace osu.Game.Input private void load(BindingStore bindings) { var rulesetId = ruleset?.ID; - foreach (var b in bindings.Query(b => b.RulesetID == rulesetId)) + foreach (var b in bindings.Query(b => b.RulesetID == rulesetId && b.Variant == variant)) Mappings[b.Key] = (T)(object)b.Action; } @@ -69,6 +73,9 @@ namespace osu.Game.Input [ForeignKey(typeof(RulesetInfo))] public int? RulesetID { get; set; } + [Indexed] + public int? Variant { get; set; } + public Key Key { get; set; } public int Action { get; set; } From 723e27353c0a25792f7361729ccb33aef8c48b9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 13:28:29 +0900 Subject: [PATCH 57/67] HitRenderer -> RulesetContainer --- osu.Desktop.Tests/Visual/TestCaseGamefield.cs | 8 +-- .../Visual/TestCaseScrollingPlayfield.cs | 10 ++-- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../Scoring/CatchScoreProcessor.cs | 4 +- ...itRenderer.cs => CatchRulesetContainer.cs} | 4 +- .../osu.Game.Rulesets.Catch.csproj | 2 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Mods/IGenerateSpeedAdjustments.cs | 4 +- .../Mods/ManiaModGravity.cs | 10 ++-- .../Scoring/ManiaScoreProcessor.cs | 4 +- ...itRenderer.cs => ManiaRulesetContainer.cs} | 4 +- .../osu.Game.Rulesets.Mania.csproj | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Scoring/OsuScoreProcessor.cs | 4 +- ...uHitRenderer.cs => OsuRulesetContainer.cs} | 4 +- .../osu.Game.Rulesets.Osu.csproj | 2 +- .../Scoring/TaikoScoreProcessor.cs | 4 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- ...itRenderer.cs => TaikoRulesetContainer.cs} | 4 +- .../osu.Game.Rulesets.Taiko.csproj | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Rulesets/Mods/IApplicableMod.cs | 10 ++-- osu.Game/Rulesets/Mods/ModAutoplay.cs | 4 +- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 8 +-- .../{HitRenderer.cs => RulesetContainer.cs} | 50 +++++++++---------- ...nderer.cs => ScrollingRulesetContainer.cs} | 10 ++-- osu.Game/Screens/Play/HUDOverlay.cs | 6 +-- osu.Game/Screens/Play/Player.cs | 40 +++++++-------- osu.Game/Screens/Play/ReplayPlayer.cs | 2 +- osu.Game/osu.Game.csproj | 4 +- 32 files changed, 110 insertions(+), 110 deletions(-) rename osu.Game.Rulesets.Catch/UI/{CatchHitRenderer.cs => CatchRulesetContainer.cs} (84%) rename osu.Game.Rulesets.Mania/UI/{ManiaHitRenderer.cs => ManiaRulesetContainer.cs} (92%) rename osu.Game.Rulesets.Osu/UI/{OsuHitRenderer.cs => OsuRulesetContainer.cs} (88%) rename osu.Game.Rulesets.Taiko/UI/{TaikoHitRenderer.cs => TaikoRulesetContainer.cs} (93%) rename osu.Game/Rulesets/UI/{HitRenderer.cs => RulesetContainer.cs} (84%) rename osu.Game/Rulesets/UI/{ScrollingHitRenderer.cs => ScrollingRulesetContainer.cs} (87%) diff --git a/osu.Desktop.Tests/Visual/TestCaseGamefield.cs b/osu.Desktop.Tests/Visual/TestCaseGamefield.cs index 98dda56d41..73c61f5669 100644 --- a/osu.Desktop.Tests/Visual/TestCaseGamefield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseGamefield.cs @@ -88,25 +88,25 @@ namespace osu.Desktop.Tests.Visual Clock = new FramedClock(), Children = new Drawable[] { - new OsuHitRenderer(new OsuRuleset(new RulesetInfo()), beatmap, false) + new OsuRulesetContainer(new OsuRuleset(new RulesetInfo()), beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft }, - new TaikoHitRenderer(new TaikoRuleset(new RulesetInfo()),beatmap, false) + new TaikoRulesetContainer(new TaikoRuleset(new RulesetInfo()),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.TopRight, Origin = Anchor.TopRight }, - new CatchHitRenderer(new CatchRuleset(new RulesetInfo()),beatmap, false) + new CatchRulesetContainer(new CatchRuleset(new RulesetInfo()),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, - new ManiaHitRenderer(new ManiaRuleset(new RulesetInfo()),beatmap, false) + new ManiaRulesetContainer(new ManiaRuleset(new RulesetInfo()),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.BottomRight, diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index aaa2f7d49d..861e79b0b1 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -50,15 +50,15 @@ namespace osu.Desktop.Tests.Visual WorkingBeatmap beatmap = new TestWorkingBeatmap(b); - TestHitRenderer hitRenderer; - Add(hitRenderer = new TestHitRenderer(beatmap, true)); + TestRulesetContainer rulesetContainer; + Add(rulesetContainer = new TestRulesetContainer(beatmap, true)); - AddStep("Reverse direction", () => hitRenderer.Playfield.Reversed.Value = !hitRenderer.Playfield.Reversed); + AddStep("Reverse direction", () => rulesetContainer.Playfield.Reversed.Value = !rulesetContainer.Playfield.Reversed); } - private class TestHitRenderer : ScrollingHitRenderer + private class TestRulesetContainer : ScrollingRulesetContainer { - public TestHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) + public TestRulesetContainer(WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(null, beatmap, isForCurrentRuleset) { } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 66e2fd30bb..8d45ea8fa2 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchHitRenderer(this, beatmap, isForCurrentRuleset); + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchRulesetContainer(this, beatmap, isForCurrentRuleset); public override IEnumerable GetModsFor(ModType type) { diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 1c866320c9..33c1355823 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -14,8 +14,8 @@ namespace osu.Game.Rulesets.Catch.Scoring { } - public CatchScoreProcessor(HitRenderer hitRenderer) - : base(hitRenderer) + public CatchScoreProcessor(RulesetContainer rulesetContainer) + : base(rulesetContainer) { } diff --git a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs similarity index 84% rename from osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs rename to osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index d08b349459..27cc05c47a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -15,9 +15,9 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.UI { - public class CatchHitRenderer : ScrollingHitRenderer + public class CatchRulesetContainer : ScrollingRulesetContainer { - public CatchHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) { } diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index fcffcb8060..8fefdc7b3c 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -60,7 +60,7 @@ - + diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index b61230d347..50ad6960ae 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaHitRenderer(this, beatmap, isForCurrentRuleset); + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaRulesetContainer(this, beatmap, isForCurrentRuleset); public override IEnumerable GetModsFor(ModType type) { diff --git a/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs b/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs index f179aa2ff8..954ee3f481 100644 --- a/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs +++ b/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs @@ -15,9 +15,9 @@ namespace osu.Game.Rulesets.Mania.Mods /// /// Applies this mod to a hit renderer. /// - /// The hit renderer to apply to. + /// 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 ApplyToHitRenderer(ManiaHitRenderer hitRenderer, ref List[] hitObjectTimingChanges, ref List barlineTimingChanges); + 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 index 1ba8ac4710..a054e0db56 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs @@ -20,12 +20,12 @@ namespace osu.Game.Rulesets.Mania.Mods public override FontAwesome Icon => FontAwesome.fa_sort_desc; - public void ApplyToHitRenderer(ManiaHitRenderer hitRenderer, ref List[] hitObjectTimingChanges, ref List barlineTimingChanges) + 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 hitRenderer.Objects) + foreach (ManiaHitObject obj in rulesetContainer.Objects) { - MultiplierControlPoint controlPoint = hitRenderer.CreateControlPointAt(obj.StartTime); + 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; @@ -33,9 +33,9 @@ namespace osu.Game.Rulesets.Mania.Mods } // Like with hit objects, we need to generate one speed adjustment per bar line - foreach (DrawableBarLine barLine in hitRenderer.BarLines) + foreach (DrawableBarLine barLine in rulesetContainer.BarLines) { - var controlPoint = hitRenderer.CreateControlPointAt(barLine.HitObject.StartTime); + 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; diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index f575342486..63b443319f 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -155,8 +155,8 @@ namespace osu.Game.Rulesets.Mania.Scoring { } - public ManiaScoreProcessor(HitRenderer hitRenderer) - : base(hitRenderer) + public ManiaScoreProcessor(RulesetContainer rulesetContainer) + : base(rulesetContainer) { } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs similarity index 92% rename from osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs rename to osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index ffb3ad4a45..7f6b19f3bd 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -29,7 +29,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaHitRenderer : ScrollingHitRenderer + public class ManiaRulesetContainer : ScrollingRulesetContainer { /// /// Preferred column count. This will only have an effect during the initialization of the play field. @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; - public ManiaHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) { // Generate the bar lines diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 3832f9ace5..fb0b2d907f 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -82,7 +82,7 @@ - + diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index d80beaf0a3..212c634aaf 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuHitRenderer(this, beatmap, isForCurrentRuleset); + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuRulesetContainer(this, beatmap, isForCurrentRuleset); public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new[] { diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 079ee928af..856ca0c98d 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -18,8 +18,8 @@ namespace osu.Game.Rulesets.Osu.Scoring { } - public OsuScoreProcessor(HitRenderer hitRenderer) - : base(hitRenderer) + public OsuScoreProcessor(RulesetContainer rulesetContainer) + : base(rulesetContainer) { } diff --git a/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs similarity index 88% rename from osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs rename to osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index 1356e97907..d029524a32 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -16,9 +16,9 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.UI { - public class OsuHitRenderer : HitRenderer + public class OsuRulesetContainer : RulesetContainer { - public OsuHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) { } diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 684060c981..b24d5b3a4a 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -80,7 +80,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 70df3d8317..647a1381c6 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -113,8 +113,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring { } - public TaikoScoreProcessor(HitRenderer hitRenderer) - : base(hitRenderer) + public TaikoScoreProcessor(RulesetContainer rulesetContainer) + : base(rulesetContainer) { } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 9b2536a7ec..4d4bbb7bc5 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoHitRenderer(this, beatmap, isForCurrentRuleset); + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoRulesetContainer(this, beatmap, isForCurrentRuleset); public override IEnumerable GetModsFor(ModType type) { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index dca339f734..119cd64fef 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Taiko.UI public class TaikoPlayfield : Playfield { /// - /// Default height of a when inside a . + /// Default height of a when inside a . /// public const float DEFAULT_HEIGHT = 178; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs similarity index 93% rename from osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs rename to osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index cb89cfed72..29f563b735 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -21,9 +21,9 @@ using System.Linq; namespace osu.Game.Rulesets.Taiko.UI { - public class TaikoHitRenderer : HitRenderer + public class TaikoRulesetContainer : RulesetContainer { - public TaikoHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) { } diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index f719f2002b..59c6f4db0a 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -91,7 +91,7 @@ - + diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 7538893cb7..2fb9a568f8 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -62,7 +62,7 @@ namespace osu.Game.Beatmaps public override Mod GetAutoplayMod() => new ModAutoplay(); - public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) + public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) { throw new NotImplementedException(); } diff --git a/osu.Game/Rulesets/Mods/IApplicableMod.cs b/osu.Game/Rulesets/Mods/IApplicableMod.cs index 18e1ae4b3d..1957952720 100644 --- a/osu.Game/Rulesets/Mods/IApplicableMod.cs +++ b/osu.Game/Rulesets/Mods/IApplicableMod.cs @@ -7,16 +7,16 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mods { /// - /// An interface for mods that are applied to a HitRenderer. + /// An interface for mods that are applied to a RulesetContainer. /// - /// The type of HitObject the HitRenderer contains. + /// The type of HitObject the RulesetContainer contains. public interface IApplicableMod where TObject : HitObject { /// - /// Applies the mod to a HitRenderer. + /// Applies the mod to a RulesetContainer. /// - /// The HitRenderer to apply the mod to. - void ApplyToHitRenderer(HitRenderer hitRenderer); + /// The RulesetContainer to apply the mod to. + void ApplyToRulesetContainer(RulesetContainer rulesetContainer); } } diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 1217bf835f..ca120e446e 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -15,9 +15,9 @@ namespace osu.Game.Rulesets.Mods { protected abstract Score CreateReplayScore(Beatmap beatmap); - public void ApplyToHitRenderer(HitRenderer hitRenderer) + public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { - hitRenderer.SetReplay(CreateReplayScore(hitRenderer.Beatmap)?.Replay); + rulesetContainer.SetReplay(CreateReplayScore(rulesetContainer.Beatmap)?.Replay); } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 4a492b84fb..ba040403ba 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets /// Whether the hit renderer should assume the beatmap is for the current ruleset. /// Unable to successfully load the beatmap to be usable with this ruleset. /// - public abstract HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset); + public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset); public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap); diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index cd9089c859..5ccac2db32 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -150,13 +150,13 @@ namespace osu.Game.Rulesets.Scoring { } - protected ScoreProcessor(HitRenderer hitRenderer) + protected ScoreProcessor(RulesetContainer rulesetContainer) { - Judgements.Capacity = hitRenderer.Beatmap.HitObjects.Count; + Judgements.Capacity = rulesetContainer.Beatmap.HitObjects.Count; - hitRenderer.OnJudgement += AddJudgement; + rulesetContainer.OnJudgement += AddJudgement; - ComputeTargets(hitRenderer.Beatmap); + ComputeTargets(rulesetContainer.Beatmap); Reset(); } diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs similarity index 84% rename from osu.Game/Rulesets/UI/HitRenderer.cs rename to osu.Game/Rulesets/UI/RulesetContainer.cs index 00f8e8a469..16ea895fac 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -23,12 +23,12 @@ using osu.Game.Rulesets.Beatmaps; namespace osu.Game.Rulesets.UI { /// - /// Base HitRenderer. Doesn't hold objects. + /// Base RulesetContainer. Doesn't hold objects. /// - /// Should not be derived - derive instead. + /// Should not be derived - derive instead. /// /// - public abstract class HitRenderer : Container + public abstract class RulesetContainer : Container { /// /// Invoked when all the judgeable HitObjects have been judged. @@ -41,12 +41,12 @@ namespace osu.Game.Rulesets.UI public bool AspectAdjust = true; /// - /// The input manager for this HitRenderer. + /// The input manager for this RulesetContainer. /// internal readonly PlayerInputManager InputManager = new PlayerInputManager(); /// - /// The key conversion input manager for this HitRenderer. + /// The key conversion input manager for this RulesetContainer. /// protected readonly PassThroughInputManager KeyConversionInputManager; @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.UI /// A visual representation of a . /// /// The ruleset being repesented. - internal HitRenderer(Ruleset ruleset) + internal RulesetContainer(Ruleset ruleset) { Ruleset = ruleset; KeyConversionInputManager = CreateActionMappingInputManager(); @@ -113,14 +113,14 @@ namespace osu.Game.Rulesets.UI } /// - /// HitRenderer that applies conversion to Beatmaps. Does not contain a Playfield + /// RulesetContainer that applies conversion to Beatmaps. Does not contain a Playfield /// and does not load drawable hit objects. /// - /// Should not be derived - derive instead. + /// Should not be derived - derive instead. /// /// - /// The type of HitObject contained by this HitRenderer. - public abstract class HitRenderer : HitRenderer + /// The type of HitObject contained by this RulesetContainer. + public abstract class RulesetContainer : RulesetContainer where TObject : HitObject { /// @@ -144,9 +144,9 @@ namespace osu.Game.Rulesets.UI /// The ruleset being repesented. /// The beatmap to create the hit renderer for. /// Whether to assume the beatmap is for the current ruleset. - internal HitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset) + internal RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset) { - Debug.Assert(beatmap != null, "HitRenderer initialized with a null beatmap."); + Debug.Assert(beatmap != null, "RulesetContainer initialized with a null beatmap."); Mods = beatmap.Mods.Value; @@ -180,7 +180,7 @@ namespace osu.Game.Rulesets.UI } /// - /// Applies the active mods to this HitRenderer. + /// Applies the active mods to this RulesetContainer. /// /// private void applyMods(IEnumerable mods) @@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.UI return; foreach (var mod in mods.OfType>()) - mod.ApplyToHitRenderer(this); + mod.ApplyToRulesetContainer(this); } /// @@ -212,11 +212,11 @@ namespace osu.Game.Rulesets.UI } /// - /// A derivable HitRenderer that manages the Playfield and HitObjects. + /// A derivable RulesetContainer that manages the Playfield and HitObjects. /// - /// The type of HitObject contained by this HitRenderer. - /// The type of Judgement of DrawableHitObjects contained by this HitRenderer. - public abstract class HitRenderer : HitRenderer + /// The type of HitObject contained by this RulesetContainer. + /// The type of Judgement of DrawableHitObjects contained by this RulesetContainer. + public abstract class RulesetContainer : RulesetContainer where TObject : HitObject where TJudgement : Judgement { @@ -247,7 +247,7 @@ namespace osu.Game.Rulesets.UI /// The ruleset being repesented. /// The beatmap to create the hit renderer for. /// Whether to assume the beatmap is for the current ruleset. - protected HitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) { InputManager.Add(content = new Container @@ -334,12 +334,12 @@ namespace osu.Game.Rulesets.UI } /// - /// A derivable HitRenderer that manages the Playfield and HitObjects. + /// A derivable RulesetContainer that manages the Playfield and HitObjects. /// - /// The type of Playfield contained by this HitRenderer. - /// The type of HitObject contained by this HitRenderer. - /// The type of Judgement of DrawableHitObjects contained by this HitRenderer. - public abstract class HitRenderer : HitRenderer + /// The type of Playfield contained by this RulesetContainer. + /// The type of HitObject contained by this RulesetContainer. + /// The type of Judgement of DrawableHitObjects contained by this RulesetContainer. + public abstract class RulesetContainer : RulesetContainer where TObject : HitObject where TJudgement : Judgement where TPlayfield : Playfield @@ -355,7 +355,7 @@ namespace osu.Game.Rulesets.UI /// The ruleset being repesented. /// The beatmap to create the hit renderer for. /// Whether to assume the beatmap is for the current ruleset. - protected HitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) { } diff --git a/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs b/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs similarity index 87% rename from osu.Game/Rulesets/UI/ScrollingHitRenderer.cs rename to osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs index 37df08ba21..64e865473d 100644 --- a/osu.Game/Rulesets/UI/ScrollingHitRenderer.cs +++ b/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs @@ -17,22 +17,22 @@ using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.UI { /// - /// A type of that supports a . - /// s inside this will scroll within the playfield. + /// A type of that supports a . + /// s inside this will scroll within the playfield. /// - public abstract class ScrollingHitRenderer : HitRenderer + public abstract class ScrollingRulesetContainer : RulesetContainer where TObject : HitObject where TJudgement : Judgement where TPlayfield : ScrollingPlayfield { /// /// Provides the default s that adjust the scrolling rate of s - /// inside this . + /// inside this . /// /// protected readonly SortedList DefaultControlPoints = new SortedList(Comparer.Default); - protected ScrollingHitRenderer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + protected ScrollingRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) { } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index ea75c140db..cf6bc03c60 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -90,11 +90,11 @@ namespace osu.Game.Screens.Play } } - public virtual void BindHitRenderer(HitRenderer hitRenderer) + public virtual void BindRulesetContainer(RulesetContainer rulesetContainer) { - hitRenderer.InputManager.Add(KeyCounter.GetReceptor()); + rulesetContainer.InputManager.Add(KeyCounter.GetReceptor()); - replayLoaded = hitRenderer.HasReplayLoaded; + replayLoaded = rulesetContainer.HasReplayLoaded; // in the case a replay isn't loaded, we want some elements to only appear briefly. if (!replayLoaded) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a13e9ed369..00f1bd1b6b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Play internal override bool ShowOverlays => false; - internal override bool HasLocalCursorDisplayed => !pauseContainer.IsPaused && !HasFailed && HitRenderer.ProvidingUserCursor; + internal override bool HasLocalCursorDisplayed => !pauseContainer.IsPaused && !HasFailed && RulesetContainer.ProvidingUserCursor; public Action RestartRequested; @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Play private RulesetInfo ruleset; private ScoreProcessor scoreProcessor; - protected HitRenderer HitRenderer; + protected RulesetContainer RulesetContainer; #region User Settings @@ -66,7 +66,7 @@ namespace osu.Game.Screens.Play private HUDOverlay hudOverlay; private FailOverlay failOverlay; - private bool loadedSuccessfully => HitRenderer?.Objects.Any() == true; + private bool loadedSuccessfully => RulesetContainer?.Objects.Any() == true; [BackgroundDependencyLoader(permitNulls: true)] private void load(AudioManager audio, OsuConfigManager config, OsuGame osu) @@ -93,18 +93,18 @@ namespace osu.Game.Screens.Play try { - HitRenderer = rulesetInstance.CreateHitRendererWith(working, ruleset.ID == beatmap.BeatmapInfo.Ruleset.ID); + RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working, ruleset.ID == beatmap.BeatmapInfo.Ruleset.ID); } catch (BeatmapInvalidForRulesetException) { - // we may fail to create a HitRenderer if the beatmap cannot be loaded with the user's preferred ruleset + // we may fail to create a RulesetContainer if the beatmap cannot be loaded with the user's preferred ruleset // let's try again forcing the beatmap's ruleset. ruleset = beatmap.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); - HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap, true); + RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap, true); } - if (!HitRenderer.Objects.Any()) + if (!RulesetContainer.Objects.Any()) throw new InvalidOperationException("Beatmap contains no hit objects!"); } catch (Exception e) @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Play adjustableSourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock(); decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; - var firstObjectTime = HitRenderer.Objects.First().StartTime; + var firstObjectTime = RulesetContainer.Objects.First().StartTime; decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, beatmap.BeatmapInfo.AudioLeadIn))); decoupledClock.ProcessFrame(); @@ -147,7 +147,7 @@ namespace osu.Game.Screens.Play FramedClock = offsetClock, OnRetry = Restart, OnQuit = Exit, - CheckCanPause = () => ValidForResume && !HasFailed && !HitRenderer.HasReplayLoaded, + CheckCanPause = () => ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, Retries = RestartCount, OnPause = () => { hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused; @@ -164,7 +164,7 @@ namespace osu.Game.Screens.Play Clock = offsetClock, Children = new Drawable[] { - HitRenderer, + RulesetContainer, } }, hudOverlay = new HUDOverlay @@ -184,27 +184,27 @@ namespace osu.Game.Screens.Play Action = () => { //we want to hide the hitrenderer immediately (looks better). //we may be able to remove this once the mouse cursor trail is improved. - HitRenderer?.Hide(); + RulesetContainer?.Hide(); Restart(); }, } }; - scoreProcessor = HitRenderer.CreateScoreProcessor(); + scoreProcessor = RulesetContainer.CreateScoreProcessor(); hudOverlay.KeyCounter.AddRange(rulesetInstance.CreateGameplayKeys()); hudOverlay.BindProcessor(scoreProcessor); - hudOverlay.BindHitRenderer(HitRenderer); + hudOverlay.BindRulesetContainer(RulesetContainer); - hudOverlay.Progress.Objects = HitRenderer.Objects; + hudOverlay.Progress.Objects = RulesetContainer.Objects; hudOverlay.Progress.AudioClock = decoupledClock; - hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded; + hudOverlay.Progress.AllowSeeking = RulesetContainer.HasReplayLoaded; hudOverlay.Progress.OnSeek = pos => decoupledClock.Seek(pos); hudOverlay.ModDisplay.Current.BindTo(working.Mods); - //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) - HitRenderer.OnAllJudged += onCompletion; + //bind RulesetContainer to ScoreProcessor and ourselves (for a pass situation) + RulesetContainer.OnAllJudged += onCompletion; //bind ScoreProcessor to ourselves (for a fail situation) scoreProcessor.Failed += onFail; @@ -238,7 +238,7 @@ namespace osu.Game.Screens.Play Ruleset = ruleset }; scoreProcessor.PopulateScore(score); - score.User = HitRenderer.Replay?.User ?? (Game as OsuGame)?.API?.LocalUser?.Value; + score.User = RulesetContainer.Replay?.User ?? (Game as OsuGame)?.API?.LocalUser?.Value; Push(new Results(score)); }); } @@ -295,7 +295,7 @@ namespace osu.Game.Screens.Play protected override bool OnExiting(Screen next) { - if (HasFailed || !ValidForResume || pauseContainer?.AllowExit != false || HitRenderer?.HasReplayLoaded != false) + if (HasFailed || !ValidForResume || pauseContainer?.AllowExit != false || RulesetContainer?.HasReplayLoaded != false) { fadeOut(); return base.OnExiting(next); @@ -313,7 +313,7 @@ namespace osu.Game.Screens.Play { const float fade_out_duration = 250; - HitRenderer?.FadeOut(fade_out_duration); + RulesetContainer?.FadeOut(fade_out_duration); Content.FadeOut(fade_out_duration); hudOverlay?.ScaleTo(0.7f, fade_out_duration * 3, Easing.In); diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 860675b62a..4748ddfd71 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { base.LoadComplete(); - HitRenderer.SetReplay(Replay); + RulesetContainer.SetReplay(Replay); } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0a73754e14..482422cfd9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -338,9 +338,9 @@ - + - + From 431a9649a4b569f624254715171f654ac45904a1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 13:38:12 +0900 Subject: [PATCH 58/67] Remove unused using. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 204742eec9..3a66d1c929 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -7,7 +7,6 @@ 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.MathUtils; From a20753abc69c3963c35e0345aa135732112ce308 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 14:10:10 +0900 Subject: [PATCH 59/67] Applied suggested changes. --- .../Visual/TestCaseScrollingPlayfield.cs | 2 +- .../Timing/SpeedAdjustmentContainer.cs | 14 ++------- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 29 +++++-------------- 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 7f067efa78..82fa93797d 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -53,7 +53,7 @@ namespace osu.Desktop.Tests.Visual TestHitRenderer hitRenderer; Add(hitRenderer = new TestHitRenderer(beatmap, true)); - AddStep("Reverse direction", () => hitRenderer.Playfield.Reversed.Value = !hitRenderer.Playfield.Reversed); + AddStep("Reverse direction", () => hitRenderer.Playfield.Reversed.Toggle()); } private class TestHitRenderer : ScrollingHitRenderer diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index d582f19660..f9ca43d0fc 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -16,25 +16,15 @@ namespace osu.Game.Rulesets.Timing /// public class SpeedAdjustmentContainer : Container { - private readonly Bindable visibleTimeRange = new Bindable { Default = 1000 }; /// /// Gets or sets the range of time that is visible by the length of the scrolling axes. /// - public Bindable VisibleTimeRange - { - get { return visibleTimeRange; } - set { visibleTimeRange.BindTo(value); } - } + public readonly Bindable VisibleTimeRange = new Bindable { Default = 1000 }; - private readonly BindableBool reversed = new BindableBool(); /// /// Whether to reverse the scrolling direction is reversed. /// - public BindableBool Reversed - { - get { return reversed; } - set { reversed.BindTo(value); } - } + public readonly BindableBool Reversed = new BindableBool(); protected override Container Content => content; private Container content; diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 3a66d1c929..66ca2dd7c4 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -71,12 +71,9 @@ namespace osu.Game.Rulesets.UI protected ScrollingPlayfield(Axes scrollingAxes, float? customWidth = null) : base(customWidth) { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) - { - RelativeSizeAxes = Axes.Both, - VisibleTimeRange = VisibleTimeRange, - Reversed = Reversed - }; + base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) { RelativeSizeAxes = Axes.Both }; + HitObjects.VisibleTimeRange.BindTo(VisibleTimeRange); + HitObjects.Reversed.BindTo(Reversed); } private List> nestedPlayfields; @@ -142,26 +139,16 @@ namespace osu.Game.Rulesets.UI /// internal class ScrollingHitObjectContainer : HitObjectContainer { - private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; /// /// 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 Bindable VisibleTimeRange - { - get { return visibleTimeRange; } - set { visibleTimeRange.BindTo(value); } - } + public readonly BindableDouble VisibleTimeRange = new BindableDouble { Default = 1000 }; - private readonly BindableBool reversed = new BindableBool(); /// /// Whether to reverse the scrolling direction is reversed. /// - public BindableBool Reversed - { - get { return reversed; } - set { reversed.BindTo(value); } - } + public readonly BindableBool Reversed = new BindableBool(); /// /// Hit objects that are to be re-processed on the next update. @@ -186,11 +173,11 @@ namespace osu.Game.Rulesets.UI /// The . public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) { - speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); speedAdjustment.ScrollingAxes = scrollingAxes; - speedAdjustment.Reversed = Reversed; - speedAdjustments.Add(speedAdjustment); + speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); + speedAdjustment.Reversed.BindTo(Reversed); + speedAdjustments.Add(speedAdjustment); AddInternal(speedAdjustment); } From 346aebebc0a135490eb085d54fab1c809e73d456 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 14:24:07 +0900 Subject: [PATCH 60/67] Fix origins not being set correctly when reverting from reversed playfield. --- osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index f9ca43d0fc..e9640dba24 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Timing { RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1); RelativeChildOffset = Vector2.Zero; - Anchor = Anchor = Anchor.TopLeft; + Origin = Anchor = Anchor.TopLeft; } } From ea073c02b37e2c6fa74239f3851e807b7d3bee8b Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 14:24:29 +0900 Subject: [PATCH 61/67] Showcase both horizontal and vertical styles in TestCaseScrollingPlayfield. --- .../Visual/TestCaseScrollingPlayfield.cs | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 82fa93797d..1dd55974e8 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -50,17 +50,27 @@ namespace osu.Desktop.Tests.Visual WorkingBeatmap beatmap = new TestWorkingBeatmap(b); - TestHitRenderer hitRenderer; - Add(hitRenderer = new TestHitRenderer(beatmap, true)); + TestHitRenderer horizontalHitRenderer; + Add(horizontalHitRenderer = new TestHitRenderer(Axes.X, beatmap, true)); - AddStep("Reverse direction", () => hitRenderer.Playfield.Reversed.Toggle()); + TestHitRenderer verticalHitRenderer; + Add(verticalHitRenderer = new TestHitRenderer(Axes.Y, beatmap, true)); + + AddStep("Reverse direction", () => + { + horizontalHitRenderer.Playfield.Reversed.Toggle(); + verticalHitRenderer.Playfield.Reversed.Toggle(); + }); } private class TestHitRenderer : ScrollingHitRenderer { - public TestHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) + private readonly Axes scrollingAxes; + + public TestHitRenderer(Axes scrollingAxes, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(beatmap, isForCurrentRuleset) { + this.scrollingAxes = scrollingAxes; } public new TestPlayfield Playfield => base.Playfield; @@ -69,9 +79,9 @@ namespace osu.Desktop.Tests.Visual protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); - protected override Playfield CreatePlayfield() => new TestPlayfield(); + protected override Playfield CreatePlayfield() => new TestPlayfield(scrollingAxes); - protected override DrawableHitObject GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(h); + protected override DrawableHitObject GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(scrollingAxes, h); } private class TestScoreProcessor : ScoreProcessor @@ -93,10 +103,14 @@ namespace osu.Desktop.Tests.Visual private class DrawableTestHitObject : DrawableScrollingHitObject { - public DrawableTestHitObject(TestHitObject hitObject) + public DrawableTestHitObject(Axes scrollingAxes, TestHitObject hitObject) : base(hitObject) { - Anchor = Anchor.CentreLeft; + if (scrollingAxes == Axes.Y) + Anchor = Anchor.TopCentre; + else + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; @@ -119,8 +133,8 @@ namespace osu.Desktop.Tests.Visual protected override Container Content => content; private readonly Container content; - public TestPlayfield() - : base(Axes.X) + public TestPlayfield(Axes scrollingAxes) + : base(scrollingAxes) { InternalChildren = new Drawable[] { From f70c00423a83fb89d5659c3fe3912bd074e34820 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 14:25:49 +0900 Subject: [PATCH 62/67] Missed one. --- osu.Game/Rulesets/Timing/ScrollingContainer.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index 1cb5e42251..843f307d0d 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -17,15 +17,10 @@ namespace osu.Game.Rulesets.Timing /// public abstract class ScrollingContainer : Container { - private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 }; /// /// Gets or sets the range of time that is visible by the length of the scrolling axes. /// - public BindableDouble VisibleTimeRange - { - get { return visibleTimeRange; } - set { visibleTimeRange.BindTo(value); } - } + public readonly BindableDouble VisibleTimeRange = new BindableDouble { Default = 1000 }; /// /// The axes through which this scrolls. This is set by the . From c70f96a9cd8df37cc048f5e1ab0c3598be6306ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 14:50:10 +0900 Subject: [PATCH 63/67] Add basic documentation and split out classes. --- osu.Game/Input/ActionMappingInputManager.cs | 41 +++++---------------- osu.Game/Input/Binding.cs | 20 ++++++++++ osu.Game/Input/BindingStore.cs | 26 +++++++++++++ osu.Game/osu.Game.csproj | 2 + 4 files changed, 57 insertions(+), 32 deletions(-) create mode 100644 osu.Game/Input/Binding.cs create mode 100644 osu.Game/Input/BindingStore.cs diff --git a/osu.Game/Input/ActionMappingInputManager.cs b/osu.Game/Input/ActionMappingInputManager.cs index d926b888c5..836f0734fd 100644 --- a/osu.Game/Input/ActionMappingInputManager.cs +++ b/osu.Game/Input/ActionMappingInputManager.cs @@ -15,6 +15,10 @@ using SQLiteNetExtensions.Attributes; namespace osu.Game.Input { + /// + /// Maps custom action data of type and stores to . + /// + /// The type of the custom action. public class ActionMappingInputManager : PassThroughInputManager where T : struct { @@ -22,6 +26,11 @@ namespace osu.Game.Input private readonly int? variant; + /// + /// Create a new instance. + /// + /// A reference to identify the current . Used to lookup mappings. Null for global mappings. + /// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts. protected ActionMappingInputManager(RulesetInfo ruleset = null, int? variant = null) { this.ruleset = ruleset; @@ -67,36 +76,4 @@ namespace osu.Game.Input return default(T); } } - - public class Binding - { - [ForeignKey(typeof(RulesetInfo))] - public int? RulesetID { get; set; } - - [Indexed] - public int? Variant { get; set; } - - public Key Key { get; set; } - - public int Action { get; set; } - } - - public class BindingStore : DatabaseBackedStore - { - public BindingStore(SQLiteConnection connection, Storage storage = null) - : base(connection, storage) - { - } - - protected override void Prepare(bool reset = false) - { - Connection.CreateTable(); - } - - protected override Type[] ValidTypes => new[] - { - typeof(Binding) - }; - - } } diff --git a/osu.Game/Input/Binding.cs b/osu.Game/Input/Binding.cs new file mode 100644 index 0000000000..6f7a1594b2 --- /dev/null +++ b/osu.Game/Input/Binding.cs @@ -0,0 +1,20 @@ +using osu.Game.Rulesets; +using OpenTK.Input; +using SQLite.Net.Attributes; +using SQLiteNetExtensions.Attributes; + +namespace osu.Game.Input +{ + public class Binding + { + [ForeignKey(typeof(RulesetInfo))] + public int? RulesetID { get; set; } + + [Indexed] + public int? Variant { get; set; } + + public Key Key { get; set; } + + public int Action { get; set; } + } +} \ No newline at end of file diff --git a/osu.Game/Input/BindingStore.cs b/osu.Game/Input/BindingStore.cs new file mode 100644 index 0000000000..e20ea2e68b --- /dev/null +++ b/osu.Game/Input/BindingStore.cs @@ -0,0 +1,26 @@ +using System; +using osu.Framework.Platform; +using osu.Game.Database; +using SQLite.Net; + +namespace osu.Game.Input +{ + public class BindingStore : DatabaseBackedStore + { + public BindingStore(SQLiteConnection connection, Storage storage = null) + : base(connection, storage) + { + } + + protected override void Prepare(bool reset = false) + { + Connection.CreateTable(); + } + + protected override Type[] ValidTypes => new[] + { + typeof(Binding) + }; + + } +} \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 482422cfd9..aba4384b59 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -92,6 +92,8 @@ + + From 2715324a766e0cab8124b7326977b99992240014 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 14:50:52 +0900 Subject: [PATCH 64/67] Fix possible incorrect reversing behavior for horizontal playfields. --- osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index e9640dba24..9d5f49e155 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Timing { 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.BottomLeft; + Origin = Anchor = Anchor.BottomRight; } else { From e6c100da27a8cc51d08a8da026ccf5533a24efed Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 14:51:00 +0900 Subject: [PATCH 65/67] Fix CI. --- osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 1dd55974e8..79a9fab91c 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -106,11 +106,7 @@ namespace osu.Desktop.Tests.Visual public DrawableTestHitObject(Axes scrollingAxes, TestHitObject hitObject) : base(hitObject) { - if (scrollingAxes == Axes.Y) - Anchor = Anchor.TopCentre; - else - Anchor = Anchor.CentreLeft; - + Anchor = scrollingAxes == Axes.Y ? Anchor.TopCentre : Anchor.CentreLeft; Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; From 3b48a6c66885de27ba913ab15e1a911c5b595157 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 15:15:41 +0900 Subject: [PATCH 66/67] Fix CI issues --- .../{RulesetInputManager.cs => CatchInputManager.cs} | 0 osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 2 +- osu.Game/Input/Binding.cs | 3 +++ osu.Game/Input/BindingStore.cs | 5 ++++- 4 files changed, 8 insertions(+), 2 deletions(-) rename osu.Game.Rulesets.Catch/{RulesetInputManager.cs => CatchInputManager.cs} (100%) diff --git a/osu.Game.Rulesets.Catch/RulesetInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs similarity index 100% rename from osu.Game.Rulesets.Catch/RulesetInputManager.cs rename to osu.Game.Rulesets.Catch/CatchInputManager.cs diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 8fefdc7b3c..79ef5f4ba8 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/Input/Binding.cs b/osu.Game/Input/Binding.cs index 6f7a1594b2..e887d15a65 100644 --- a/osu.Game/Input/Binding.cs +++ b/osu.Game/Input/Binding.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Game.Rulesets; using OpenTK.Input; using SQLite.Net.Attributes; diff --git a/osu.Game/Input/BindingStore.cs b/osu.Game/Input/BindingStore.cs index e20ea2e68b..aa47bee068 100644 --- a/osu.Game/Input/BindingStore.cs +++ b/osu.Game/Input/BindingStore.cs @@ -1,4 +1,7 @@ -using System; +// 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.Platform; using osu.Game.Database; using SQLite.Net; From 459a4cafb13085d0806c95becc5120bbba76c048 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2017 15:17:05 +0900 Subject: [PATCH 67/67] Remove unnecessary HandleInput --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index f0a6b89d7e..776f2119ab 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -50,8 +50,6 @@ namespace osu.Game.Rulesets.Catch.UI private class Catcher : Container { - public override bool HandleInput => true; - private Texture texture; [BackgroundDependencyLoader]