Construct drawable slider paths smoothly using the optimized slider curve instead of by discrete individual re-sampled segments.

This commit is contained in:
Thomas Müller
2016-12-03 11:43:56 +01:00
parent c6e099d725
commit 4dbc6ad4d0
2 changed files with 37 additions and 39 deletions

View File

@ -248,42 +248,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1);
if (progress == drawnProgress) return false;
bool madeChanges = false;
if (progress == 0)
{
//if we have gone backwards, just clear the path for now.
drawnProgress = 0;
path.ClearVertices();
madeChanges = true;
}
drawnProgress = progress;
Vector2 startPosition = slider.Curve.PositionAt(0);
if (drawnProgress == null)
{
drawnProgress = 0;
path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition);
madeChanges = true;
}
double segmentSize = 1 / (slider.Curve.Length / 5);
while (drawnProgress + segmentSize < progress)
{
drawnProgress += segmentSize;
path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition);
madeChanges = true;
}
if (progress == 1 && drawnProgress != progress)
{
drawnProgress = progress;
path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition);
madeChanges = true;
}
return madeChanges;
path.ClearVertices();
slider.Curve.FillCurveUntilProgress(p => path.AddVertex(p - startPosition), progress);
return true;
}
}
}

View File

@ -3,6 +3,7 @@ using OpenTK;
using System.Linq;
using System.Diagnostics;
using osu.Framework.MathUtils;
using System;
namespace osu.Game.Modes.Osu.Objects
{
@ -64,19 +65,28 @@ namespace osu.Game.Modes.Osu.Objects
}
}
public Vector2 PositionAt(double progress)
private int indexOfDistance(double d)
{
progress = MathHelper.Clamp(progress, 0, 1);
double d = progress * Length;
int i = cumulativeLength.BinarySearch(d);
if (i < 0) i = ~i;
if (i >= calculatedPath.Count)
return calculatedPath.Last();
return i;
}
private double progressToDistance(double progress)
{
return MathHelper.Clamp(progress, 0, 1) * Length;
}
private Vector2 interpolateVertices(int i, double d)
{
if (calculatedPath.Count == 0)
return Vector2.Zero;
if (i <= 0)
return calculatedPath.First();
else if (i >= calculatedPath.Count)
return calculatedPath.Last();
Vector2 p0 = calculatedPath[i - 1];
Vector2 p1 = calculatedPath[i];
@ -91,5 +101,22 @@ namespace osu.Game.Modes.Osu.Objects
double w = (d - d0) / (d1 - d0);
return p0 + (p1 - p0) * (float)w;
}
public void FillCurveUntilProgress(Action<Vector2> action, double progress)
{
double d = progressToDistance(progress);
int i = 0;
for (; i < calculatedPath.Count && cumulativeLength[i] <= d; ++i)
action.Invoke(calculatedPath[i]);
action.Invoke(interpolateVertices(i, d));
}
public Vector2 PositionAt(double progress)
{
double d = progressToDistance(progress);
return interpolateVertices(indexOfDistance(d), d);
}
}
}