diff --git a/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs b/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs
index d7f709dc03..a6e8622b6f 100644
--- a/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs
+++ b/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs
@@ -18,12 +18,21 @@ namespace osu.Game.Tests.ScrollAlgorithms
}
[Test]
- public void TestDisplayStartTime()
+ public void TestPointDisplayStartTime()
{
- Assert.AreEqual(-8000, algorithm.GetDisplayStartTime(2000, 10000));
- Assert.AreEqual(-3000, algorithm.GetDisplayStartTime(2000, 5000));
- Assert.AreEqual(2000, algorithm.GetDisplayStartTime(7000, 5000));
- Assert.AreEqual(7000, algorithm.GetDisplayStartTime(17000, 10000));
+ Assert.AreEqual(-8000, algorithm.GetDisplayStartTime(2000, 0, 10000, 1));
+ Assert.AreEqual(-3000, algorithm.GetDisplayStartTime(2000, 0, 5000, 1));
+ Assert.AreEqual(2000, algorithm.GetDisplayStartTime(7000, 0, 5000, 1));
+ Assert.AreEqual(7000, algorithm.GetDisplayStartTime(17000, 0, 10000, 1));
+ }
+
+ [Test]
+ public void TestObjectDisplayStartTime()
+ {
+ Assert.AreEqual(900, algorithm.GetDisplayStartTime(2000, 50, 1000, 500)); // 2000 - (1 + 50 / 500) * 1000
+ Assert.AreEqual(8900, algorithm.GetDisplayStartTime(10000, 50, 1000, 500)); // 10000 - (1 + 50 / 500) * 1000
+ Assert.AreEqual(13500, algorithm.GetDisplayStartTime(15000, 250, 1000, 500)); // 15000 - (1 + 250 / 500) * 1000
+ Assert.AreEqual(19000, algorithm.GetDisplayStartTime(25000, 100, 5000, 500)); // 25000 - (1 + 100 / 500) * 5000
}
[Test]
diff --git a/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs b/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs
index 106aa88be3..1429d22c1a 100644
--- a/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs
+++ b/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs
@@ -27,11 +27,22 @@ namespace osu.Game.Tests.ScrollAlgorithms
}
[Test]
- public void TestDisplayStartTime()
+ public void TestPointDisplayStartTime()
{
- Assert.AreEqual(1000, algorithm.GetDisplayStartTime(2000, 1000)); // Like constant
- Assert.AreEqual(10000, algorithm.GetDisplayStartTime(10500, 1000)); // 10500 - (1000 * 0.5)
- Assert.AreEqual(20000, algorithm.GetDisplayStartTime(22000, 1000)); // 23000 - (1000 / 0.5)
+ Assert.AreEqual(1000, algorithm.GetDisplayStartTime(2000, 0, 1000, 1)); // Like constant
+ Assert.AreEqual(10000, algorithm.GetDisplayStartTime(10500, 0, 1000, 1)); // 10500 - (1000 * 0.5)
+ Assert.AreEqual(20000, algorithm.GetDisplayStartTime(22000, 0, 1000, 1)); // 23000 - (1000 / 0.5)
+ }
+
+ [Test]
+ public void TestObjectDisplayStartTime()
+ {
+ Assert.AreEqual(900, algorithm.GetDisplayStartTime(2000, 50, 1000, 500)); // 2000 - (1 + 50 / 500) * 1000 / 1
+ Assert.AreEqual(9450, algorithm.GetDisplayStartTime(10000, 50, 1000, 500)); // 10000 - (1 + 50 / 500) * 1000 / 2
+ Assert.AreEqual(14250, algorithm.GetDisplayStartTime(15000, 250, 1000, 500)); // 15000 - (1 + 250 / 500) * 1000 / 2
+ Assert.AreEqual(16500, algorithm.GetDisplayStartTime(18000, 250, 2000, 500)); // 18000 - (1 + 250 / 500) * 2000 / 2
+ Assert.AreEqual(17800, algorithm.GetDisplayStartTime(20000, 50, 1000, 500)); // 20000 - (1 + 50 / 500) * 1000 / 0.5
+ Assert.AreEqual(19800, algorithm.GetDisplayStartTime(22000, 50, 1000, 500)); // 22000 - (1 + 50 / 500) * 1000 / 0.5
}
[Test]
diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs
index 75ea3efdf2..0d4283e319 100644
--- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs
+++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs
@@ -5,7 +5,11 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
{
public class ConstantScrollAlgorithm : IScrollAlgorithm
{
- public double GetDisplayStartTime(double time, double timeRange) => time - timeRange;
+ public double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength)
+ {
+ var adjustedTime = TimeAt(-offset, originTime, timeRange, scrollLength);
+ return adjustedTime - timeRange;
+ }
public float GetLength(double startTime, double endTime, double timeRange, float scrollLength)
{
diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs
index 5f053975c7..c394a05bcc 100644
--- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs
+++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs
@@ -6,15 +6,33 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
public interface IScrollAlgorithm
{
///
- /// Given a point in time, computes the time at which it enters the time range.
+ /// Given a point in time associated with an object's origin
+ /// and the spatial distance between the edge and the origin of the object along the scrolling axis,
+ /// computes the time at which the object initially enters the time range.
///
- ///
- /// E.g. For a constant time range of 5000ms, the time at which t=7000ms enters the time range is 2000ms.
- ///
- /// The point in time.
+ ///
+ /// Let's assume the following parameters:
+ ///
+ /// - = 7000ms,
+ /// - = 100px,
+ /// - = 5000ms,
+ /// - = 1000px
+ ///
+ /// and a constant scrolling rate.
+ /// To arrive at the end of the scrolling container, the object's origin has to cover
+ /// 1000 + 100 = 1100px
+ /// so that the edge starts at the end of the scrolling container.
+ /// One scroll length of 1000px covers 5000ms of time, so the time required to cover 1100px is equal to
+ /// 5000 * (1100 / 1000) = 5500ms,
+ /// and therefore the object should start being visible at
+ /// 7000 - 5500 = 1500ms.
+ ///
+ /// The time point at which the object origin should enter the time range.
+ /// The spatial distance between the object's edge and its origin along the scrolling axis.
/// The amount of visible time.
- /// The time at which enters .
- double GetDisplayStartTime(double time, double timeRange);
+ /// The absolute spatial length through .
+ /// The time at which the object should enter the time range.
+ double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength);
///
/// Computes the spatial length within a start and end time.
diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs
index fe22a86fad..7b827e0c63 100644
--- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs
+++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs
@@ -20,11 +20,12 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
searchPoint = new MultiplierControlPoint();
}
- public double GetDisplayStartTime(double time, double timeRange)
+ public double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength)
{
+ var controlPoint = controlPointAt(originTime);
// The total amount of time that the hitobject will remain visible within the timeRange, which decreases as the speed multiplier increases
- double visibleDuration = timeRange / controlPointAt(time).Multiplier;
- return time - visibleDuration;
+ double visibleDuration = (scrollLength + offset) * timeRange / controlPoint.Multiplier / scrollLength;
+ return originTime - visibleDuration;
}
public float GetLength(double startTime, double endTime, double timeRange, float scrollLength)
diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs
index 3c9a205412..41f9ebdb82 100644
--- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs
+++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs
@@ -20,7 +20,11 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
positionCache = new Dictionary();
}
- public double GetDisplayStartTime(double time, double timeRange) => time - timeRange - 1000;
+ public double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength)
+ {
+ double adjustedTime = TimeAt(-offset, originTime, timeRange, scrollLength);
+ return adjustedTime - timeRange - 1000;
+ }
public float GetLength(double startTime, double endTime, double timeRange, float scrollLength)
{
diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs
index 04b4374fc4..83a7f7289f 100644
--- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs
+++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs
@@ -133,8 +133,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
break;
}
- var adjustedStartTime = scrollingInfo.Algorithm.TimeAt(-originAdjustment, hitObject.HitObject.StartTime, timeRange.Value, scrollLength);
- return scrollingInfo.Algorithm.GetDisplayStartTime(adjustedStartTime, timeRange.Value);
+ return scrollingInfo.Algorithm.GetDisplayStartTime(hitObject.HitObject.StartTime, originAdjustment, timeRange.Value, scrollLength);
}
// Cant use AddOnce() since the delegate is re-constructed every invocation
diff --git a/osu.Game/Tests/Visual/ScrollingTestContainer.cs b/osu.Game/Tests/Visual/ScrollingTestContainer.cs
index 161ebe7030..18326a78ad 100644
--- a/osu.Game/Tests/Visual/ScrollingTestContainer.cs
+++ b/osu.Game/Tests/Visual/ScrollingTestContainer.cs
@@ -86,8 +86,8 @@ namespace osu.Game.Tests.Visual
}
}
- public double GetDisplayStartTime(double time, double timeRange)
- => implementation.GetDisplayStartTime(time, timeRange);
+ public double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength)
+ => implementation.GetDisplayStartTime(originTime, offset, timeRange, scrollLength);
public float GetLength(double startTime, double endTime, double timeRange, float scrollLength)
=> implementation.GetLength(startTime, endTime, timeRange, scrollLength);