mirror of
https://github.com/ppy/osu.git
synced 2024-11-14 15:57:24 +08:00
Update parsing.
This commit is contained in:
parent
4bff54d35d
commit
fe34577ee2
@ -278,6 +278,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
// The start of a new segment(indicated by having an alpha character at position 0).
|
// The start of a new segment(indicated by having an alpha character at position 0).
|
||||||
var pathType = convertPathType(s);
|
var pathType = convertPathType(s);
|
||||||
segments[segmentsCount++] = (pathType, pointsCount);
|
segments[segmentsCount++] = (pathType, pointsCount);
|
||||||
|
|
||||||
|
// First segment is prepended by an extra zero point
|
||||||
|
if (pointsCount == 0)
|
||||||
|
points[pointsCount++] = Vector2.Zero;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -306,47 +310,30 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<PathControlPoint> convertPoints(PathType type, ReadOnlySpan<Vector2> points, Vector2? endPoint)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a given point list into a set of path segments.
|
/// Converts a given point list into a set of path segments.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="type">The path type of the point list.</param>
|
||||||
/// <param name="points">The point list.</param>
|
/// <param name="points">The point list.</param>
|
||||||
/// <param name="endPoint">Any extra endpoint to consider as part of the points. This will NOT be returned.</param>
|
/// <param name="endPoint">Any extra endpoint to consider as part of the points. This will NOT be returned.</param>
|
||||||
/// <param name="first">Whether this is the first segment in the set. If <c>true</c> the first of the returned segments will contain a zero point.</param>
|
/// <returns>The set of points contained by <paramref name="points"/> as one or more segments of the path.</returns>
|
||||||
/// <param name="offset">The positional offset to apply to the control points.</param>
|
private IEnumerable<PathControlPoint> convertPoints(PathType type, ReadOnlySpan<Vector2> points, Vector2? endPoint)
|
||||||
/// <returns>The set of points contained by <paramref name="points"/> as one or more segments of the path, prepended by an extra zero point if <paramref name="first"/> is <c>true</c>.</returns>
|
|
||||||
private IEnumerable<Memory<PathControlPoint>> convertPoints(ReadOnlyMemory<string> points, string endPoint, bool first, Vector2 offset)
|
|
||||||
{
|
{
|
||||||
PathType type = convertPathType(points.Span[0]);
|
var vertices = new PathControlPoint[points.Length];
|
||||||
|
var result = new List<PathControlPoint>();
|
||||||
int readOffset = first ? 1 : 0; // First control point is zero for the first segment.
|
|
||||||
int readablePoints = points.Length - 1; // Total points readable from the base point span.
|
|
||||||
int endPointLength = endPoint != null ? 1 : 0; // Extra length if an endpoint is given that lies outside the base point span.
|
|
||||||
|
|
||||||
var vertices = new PathControlPoint[readOffset + readablePoints + endPointLength];
|
|
||||||
|
|
||||||
// Fill any non-read points.
|
|
||||||
for (int i = 0; i < readOffset; i++)
|
|
||||||
vertices[i] = new PathControlPoint();
|
|
||||||
|
|
||||||
// Parse into control points.
|
// Parse into control points.
|
||||||
for (int i = 1; i < points.Length; i++)
|
for (int i = 0; i < points.Length; i++)
|
||||||
readPoint(points.Span[i], offset, out vertices[readOffset + i - 1]);
|
vertices[i] = new PathControlPoint { Position = points[i] };
|
||||||
|
|
||||||
// If an endpoint is given, add it to the end.
|
|
||||||
if (endPoint != null)
|
|
||||||
readPoint(endPoint, offset, out vertices[^1]);
|
|
||||||
|
|
||||||
// Edge-case rules (to match stable).
|
// Edge-case rules (to match stable).
|
||||||
if (type == PathType.PERFECT_CURVE)
|
if (type == PathType.PERFECT_CURVE)
|
||||||
{
|
{
|
||||||
if (vertices.Length != 3)
|
int endPointLength = endPoint is null ? 0 : 1;
|
||||||
|
|
||||||
|
if (vertices.Length + endPointLength != 3)
|
||||||
type = PathType.BEZIER;
|
type = PathType.BEZIER;
|
||||||
else if (isLinear(vertices))
|
else if (isLinear(stackalloc[] { points[0], points[1], endPoint ?? points[2] }))
|
||||||
{
|
{
|
||||||
// osu-stable special-cased colinear perfect curves to a linear path
|
// osu-stable special-cased colinear perfect curves to a linear path
|
||||||
type = PathType.LINEAR;
|
type = PathType.LINEAR;
|
||||||
@ -365,7 +352,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
int startIndex = 0;
|
int startIndex = 0;
|
||||||
int endIndex = 0;
|
int endIndex = 0;
|
||||||
|
|
||||||
while (++endIndex < vertices.Length - endPointLength)
|
while (++endIndex < vertices.Length)
|
||||||
{
|
{
|
||||||
// Keep incrementing while an implicit segment doesn't need to be started.
|
// Keep incrementing while an implicit segment doesn't need to be started.
|
||||||
if (vertices[endIndex].Position != vertices[endIndex - 1].Position)
|
if (vertices[endIndex].Position != vertices[endIndex - 1].Position)
|
||||||
@ -378,50 +365,25 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// The last control point of each segment is not allowed to start a new implicit segment.
|
// The last control point of each segment is not allowed to start a new implicit segment.
|
||||||
if (endIndex == vertices.Length - endPointLength - 1)
|
if (endIndex == vertices.Length - 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Force a type on the last point, and return the current control point set as a segment.
|
// Force a type on the last point, and return the current control point set as a segment.
|
||||||
vertices[endIndex - 1].Type = type;
|
vertices[endIndex - 1].Type = type;
|
||||||
yield return vertices.AsMemory().Slice(startIndex, endIndex - startIndex);
|
for (int i = startIndex; i < endIndex; i++)
|
||||||
|
result.Add(vertices[i]);
|
||||||
|
|
||||||
// Skip the current control point - as it's the same as the one that's just been returned.
|
// Skip the current control point - as it's the same as the one that's just been returned.
|
||||||
startIndex = endIndex + 1;
|
startIndex = endIndex + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endIndex > startIndex)
|
for (int i = startIndex; i < endIndex; i++)
|
||||||
yield return vertices.AsMemory().Slice(startIndex, endIndex - startIndex);
|
result.Add(vertices[i]);
|
||||||
|
|
||||||
static void readPoint(string value, Vector2 startPos, out PathControlPoint point)
|
return result;
|
||||||
{
|
|
||||||
string[] vertexSplit = value.Split(':');
|
|
||||||
|
|
||||||
Vector2 pos = new Vector2((int)Parsing.ParseDouble(vertexSplit[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseDouble(vertexSplit[1], Parsing.MAX_COORDINATE_VALUE)) - startPos;
|
static bool isLinear(ReadOnlySpan<Vector2> p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X)
|
||||||
point = new PathControlPoint { Position = pos };
|
- (p[1].X - p[0].X) * (p[2].Y - p[0].Y));
|
||||||
}
|
|
||||||
|
|
||||||
static bool isLinear(PathControlPoint[] p) => Precision.AlmostEquals(0, (p[1].Position.Y - p[0].Position.Y) * (p[2].Position.X - p[0].Position.X)
|
|
||||||
- (p[1].Position.X - p[0].Position.X) * (p[2].Position.Y - p[0].Position.Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
private PathControlPoint[] mergePointsLists(List<Memory<PathControlPoint>> controlPointList)
|
|
||||||
{
|
|
||||||
int totalCount = 0;
|
|
||||||
|
|
||||||
foreach (var arr in controlPointList)
|
|
||||||
totalCount += arr.Length;
|
|
||||||
|
|
||||||
var mergedArray = new PathControlPoint[totalCount];
|
|
||||||
var mergedArrayMemory = mergedArray.AsMemory();
|
|
||||||
int copyIndex = 0;
|
|
||||||
|
|
||||||
foreach (var arr in controlPointList)
|
|
||||||
{
|
|
||||||
arr.CopyTo(mergedArrayMemory.Slice(copyIndex));
|
|
||||||
copyIndex += arr.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mergedArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user