diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs new file mode 100644 index 0000000000..ddd06a3725 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Lists; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Timing; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +{ + public class LocalScrollingAlgorithm : IScrollingAlgorithm + { + private readonly Dictionary hitObjectPositions = new Dictionary(); + + private readonly SortedList controlPoints; + + public LocalScrollingAlgorithm(SortedList controlPoints) + { + this.controlPoints = controlPoints; + } + + public void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var controlPoint = controlPointAt(obj.HitObject.StartTime); + + obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; + obj.LifetimeEnd = ((obj as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; + } + } + + public void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var controlPoint = controlPointAt(obj.HitObject.StartTime); + + var position = (obj.HitObject.StartTime - currentTime) * controlPoint.Multiplier / timeRange; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = (float)(position * length.Y); + break; + case ScrollingDirection.Down: + obj.Y = (float)(-position * length.Y); + break; + case ScrollingDirection.Left: + obj.X = (float)(position * length.X); + break; + case ScrollingDirection.Right: + obj.X = (float)(-position * length.X); + break; + } + } + } + + private readonly MultiplierControlPoint searchPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) + { + if (controlPoints.Count == 0) + return new MultiplierControlPoint(double.NegativeInfinity); + + if (time < controlPoints[0].StartTime) + return controlPoints[0]; + + searchPoint.StartTime = time; + int index = controlPoints.BinarySearch(searchPoint); + + if (index < 0) + index = ~index - 1; + + return controlPoints[index]; + } + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs new file mode 100644 index 0000000000..ceef688cbc --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Game.Rulesets.UI.Scrolling.Algorithms; + +namespace osu.Game.Rulesets.UI.Scrolling +{ + public class LocalScrollingHitObjectContainer : ScrollingHitObjectContainer + { + public LocalScrollingHitObjectContainer(ScrollingDirection direction) + : base(direction) + { + } + + protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new LocalScrollingAlgorithm(ControlPoints); + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a33cf73934..327b87d5de 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -318,7 +318,9 @@ + +