1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 07:32:55 +08:00

Safety for default(SliderPath)

This commit is contained in:
smoogipoo 2018-11-12 16:38:14 +09:00
parent d594ce3530
commit 8ad9b6a02a

View File

@ -10,26 +10,28 @@ using OpenTK;
namespace osu.Game.Rulesets.Objects namespace osu.Game.Rulesets.Objects
{ {
public readonly struct SliderPath public struct SliderPath
{ {
/// <summary> /// <summary>
/// The control points of the path. /// The control points of the path.
/// </summary> /// </summary>
public readonly Vector2[] ControlPoints; public readonly Vector2[] ControlPoints;
/// <summary>
/// The type of path.
/// </summary>
public readonly PathType Type;
/// <summary> /// <summary>
/// The user-set distance of the path. If non-null, <see cref="Distance"/> will match this value, /// The user-set distance of the path. If non-null, <see cref="Distance"/> will match this value,
/// and the path will be shortened/lengthened to match this length. /// and the path will be shortened/lengthened to match this length.
/// </summary> /// </summary>
public readonly double? ExpectedDistance; public readonly double? ExpectedDistance;
private readonly List<Vector2> calculatedPath; /// <summary>
private readonly List<double> cumulativeLength; /// The type of path.
/// </summary>
public readonly PathType Type;
private List<Vector2> calculatedPath;
private List<double> cumulativeLength;
private bool isInitialised;
/// <summary> /// <summary>
/// Creates a new <see cref="SliderPath"/>. /// Creates a new <see cref="SliderPath"/>.
@ -41,21 +43,26 @@ namespace osu.Game.Rulesets.Objects
/// If null, the path will use the true distance between all <paramref name="controlPoints"/>.</param> /// If null, the path will use the true distance between all <paramref name="controlPoints"/>.</param>
public SliderPath(PathType type, Vector2[] controlPoints, double? expectedDistance = null) public SliderPath(PathType type, Vector2[] controlPoints, double? expectedDistance = null)
{ {
this = default;
ControlPoints = controlPoints; ControlPoints = controlPoints;
Type = type; Type = type;
ExpectedDistance = expectedDistance; ExpectedDistance = expectedDistance;
calculatedPath = new List<Vector2>(); ensureInitialised();
cumulativeLength = new List<double>();
calculatePath();
calculateCumulativeLength();
} }
/// <summary> /// <summary>
/// The distance of the path after lengthening/shortening to account for <see cref="ExpectedDistance"/>. /// The distance of the path after lengthening/shortening to account for <see cref="ExpectedDistance"/>.
/// </summary> /// </summary>
public double Distance => cumulativeLength.Count == 0 ? 0 : cumulativeLength[cumulativeLength.Count - 1]; public double Distance
{
get
{
ensureInitialised();
return cumulativeLength.Count == 0 ? 0 : cumulativeLength[cumulativeLength.Count - 1];
}
}
/// <summary> /// <summary>
/// Computes the slider path until a given progress that ranges from 0 (beginning of the slider) /// Computes the slider path until a given progress that ranges from 0 (beginning of the slider)
@ -66,6 +73,8 @@ namespace osu.Game.Rulesets.Objects
/// <param name="p1">End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider).</param> /// <param name="p1">End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider).</param>
public void GetPathToProgress(List<Vector2> path, double p0, double p1) public void GetPathToProgress(List<Vector2> path, double p0, double p1)
{ {
ensureInitialised();
double d0 = progressToDistance(p0); double d0 = progressToDistance(p0);
double d1 = progressToDistance(p1); double d1 = progressToDistance(p1);
@ -92,10 +101,25 @@ namespace osu.Game.Rulesets.Objects
/// <returns></returns> /// <returns></returns>
public Vector2 PositionAt(double progress) public Vector2 PositionAt(double progress)
{ {
ensureInitialised();
double d = progressToDistance(progress); double d = progressToDistance(progress);
return interpolateVertices(indexOfDistance(d), d); return interpolateVertices(indexOfDistance(d), d);
} }
private void ensureInitialised()
{
if (isInitialised)
return;
isInitialised = true;
calculatedPath = new List<Vector2>();
cumulativeLength = new List<double>();
calculatePath();
calculateCumulativeLength();
}
private List<Vector2> calculateSubpath(ReadOnlySpan<Vector2> subControlPoints) private List<Vector2> calculateSubpath(ReadOnlySpan<Vector2> subControlPoints)
{ {
switch (Type) switch (Type)