1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 18:32:55 +08:00

Add comments to SequentialSpeedChangeVisualiser

This commit is contained in:
smoogipoo 2018-04-20 14:16:30 +09:00
parent 1bab601cbc
commit 48b421b4b4
2 changed files with 28 additions and 5 deletions

View File

@ -80,10 +80,12 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers
}
/// <summary>
/// Computes the position of a <see cref="DrawableHitObject"/> at a point in time. <br />
/// Computes the position of a <see cref="DrawableHitObject"/> at a point in time.
/// <para>
/// At t &lt; startTime, position &gt; 0. <br />
/// At t = startTime, position = 0. <br />
/// At t &gt; startTime, position &lt; 0.
/// </para>
/// </summary>
/// <param name="obj">The <see cref="DrawableHitObject"/>.</param>
/// <param name="time">The time to find the position of <paramref name="obj"/> at.</param>

View File

@ -25,23 +25,25 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers
{
foreach (var obj in hitObjects)
{
// To reduce iterations when updating hitobject positions later on, their initial positions are cached
var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime, timeRange);
// Todo: This is approximate and will be incorrect in the case of extreme speed changes
obj.LifetimeStart = obj.HitObject.StartTime - timeRange - 1000;
if (obj.HitObject is IHasEndTime endTime)
{
var diff = positionAt(endTime.EndTime, timeRange) - startPosition;
var hitObjectLength = positionAt(endTime.EndTime, timeRange) - startPosition;
switch (direction)
{
case ScrollingDirection.Up:
case ScrollingDirection.Down:
obj.Height = (float)(diff * length.Y);
obj.Height = (float)(hitObjectLength * length.Y);
break;
case ScrollingDirection.Left:
case ScrollingDirection.Right:
obj.Width = (float)(diff * length.X);
obj.Width = (float)(hitObjectLength * length.X);
break;
}
}
@ -49,6 +51,8 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers
if (obj.HasNestedHitObjects)
{
ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length);
// Nested hitobjects don't need to scroll, but they do need accurate positions
ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length);
}
}
@ -80,21 +84,38 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers
}
}
/// <summary>
/// Finds the position which corresponds to a point in time.
/// This is a non-linear operation that depends on all the control points up to and including the one active at the time value.
/// </summary>
/// <param name="time">The time to find the position at.</param>
/// <param name="timeRange">The amount of time visualised by the scrolling area.</param>
/// <returns>A positive value indicating the position at <paramref name="time"/>.</returns>
private double positionAt(double time, double timeRange)
{
double length = 0;
// We need to consider all timing points until the specified time and not just the currently-active one,
// since each timing point individually affects the positions of _all_ hitobjects after its start time
for (int i = 0; i < controlPoints.Count; i++)
{
var current = controlPoints[i];
var next = i < controlPoints.Count - 1 ? controlPoints[i + 1] : null;
// We don't need to consider any control points beyond the current time, since it will not yet
// affect any hitobjects
if (i > 0 && current.StartTime > time)
continue;
// Duration of the current control point
var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime;
length += Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / timeRange;
// We want to consider the minimal amount of time that this control point has affected,
// which may be either its duration, or the amount of time that has passed within it
var durationInCurrent = Math.Min(currentDuration, time - current.StartTime);
// Figure out how much of the time range the duration represents, and adjust it by the speed multiplier
length += durationInCurrent / timeRange * current.Multiplier;
}
return length;