mirror of
https://github.com/ppy/osu.git
synced 2026-05-29 06:09:59 +08:00
Move implicit slider path segment handling logic to Bezier converter
The logic in `LegacyBeatmapEncoder` that was supposed to handle the lazer-exclusive feature of supporting multiple slider segment types in a single slider was interfering rather badly with the Bezier converter. Generally it was a bit difficult to follow, too. The nice thing about `BezierConverter` is that it is *guaranteed* to only output Bezier control points. In light of this, the same double-up- -the-control-point logic that was supposed to make multiple slider segment types backwards-compatible with stable can be placed in the Bezier conversion logic, and be *much* more understandable, too.
This commit is contained in:
@@ -447,60 +447,31 @@ namespace osu.Game.Beatmaps.Formats
|
||||
|
||||
private void addPathData(TextWriter writer, IHasPath pathData, Vector2 position)
|
||||
{
|
||||
PathType? lastType = null;
|
||||
|
||||
for (int i = 0; i < pathData.Path.ControlPoints.Count; i++)
|
||||
{
|
||||
PathControlPoint point = pathData.Path.ControlPoints[i];
|
||||
|
||||
// Note that lazer's encoding format supports specifying multiple curve types for a slider path, which is not supported by stable.
|
||||
// Backwards compatibility with stable is handled by `LegacyBeatmapExporter` and `BezierConverter.ConvertToModernBezier()`.
|
||||
if (point.Type != null)
|
||||
{
|
||||
// We've reached a new (explicit) segment!
|
||||
|
||||
// Explicit segments have a new format in which the type is injected into the middle of the control point string.
|
||||
// To preserve compatibility with osu-stable as much as possible, explicit segments with the same type are converted to use implicit segments by duplicating the control point.
|
||||
// One exception are consecutive perfect curves, which aren't supported in osu!stable and can lead to decoding issues if encoded as implicit segments
|
||||
bool needsExplicitSegment = point.Type != lastType || point.Type == PathType.PERFECT_CURVE || i == pathData.Path.ControlPoints.Count - 1;
|
||||
|
||||
// Another exception to this is when the last two control points of the last segment were duplicated. This is not a scenario supported by osu!stable.
|
||||
// Lazer does not add implicit segments for the last two control points of _any_ explicit segment, so an explicit segment is forced in order to maintain consistency with the decoder.
|
||||
if (i > 1)
|
||||
switch (point.Type?.Type)
|
||||
{
|
||||
// We need to use the absolute control point position to determine equality, otherwise floating point issues may arise.
|
||||
Vector2 p1 = position + pathData.Path.ControlPoints[i - 1].Position;
|
||||
Vector2 p2 = position + pathData.Path.ControlPoints[i - 2].Position;
|
||||
case SplineType.BSpline:
|
||||
writer.Write(point.Type.Value.Degree > 0 ? $"B{point.Type.Value.Degree}|" : "B|");
|
||||
break;
|
||||
|
||||
if ((int)p1.X == (int)p2.X && (int)p1.Y == (int)p2.Y)
|
||||
needsExplicitSegment = true;
|
||||
}
|
||||
case SplineType.Catmull:
|
||||
writer.Write("C|");
|
||||
break;
|
||||
|
||||
if (needsExplicitSegment)
|
||||
{
|
||||
switch (point.Type?.Type)
|
||||
{
|
||||
case SplineType.BSpline:
|
||||
writer.Write(point.Type.Value.Degree > 0 ? $"B{point.Type.Value.Degree}|" : "B|");
|
||||
break;
|
||||
case SplineType.PerfectCurve:
|
||||
writer.Write("P|");
|
||||
break;
|
||||
|
||||
case SplineType.Catmull:
|
||||
writer.Write("C|");
|
||||
break;
|
||||
|
||||
case SplineType.PerfectCurve:
|
||||
writer.Write("P|");
|
||||
break;
|
||||
|
||||
case SplineType.Linear:
|
||||
writer.Write("L|");
|
||||
break;
|
||||
}
|
||||
|
||||
lastType = point.Type;
|
||||
}
|
||||
else
|
||||
{
|
||||
// New segment with the same type - duplicate the control point
|
||||
writer.Write(FormattableString.Invariant($"{position.X + point.Position.X}:{position.Y + point.Position.Y}|"));
|
||||
case SplineType.Linear:
|
||||
writer.Write("L|");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ namespace osu.Game.Rulesets.Objects
|
||||
{
|
||||
for (int j = 0; j < segment.Length - 1; j++)
|
||||
{
|
||||
if (result.Count > 0 && j == 0) result.Add(new PathControlPoint(segment[j]));
|
||||
result.Add(new PathControlPoint(segment[j], j == 0 ? PathType.BEZIER : null));
|
||||
}
|
||||
}
|
||||
@@ -147,6 +148,7 @@ namespace osu.Game.Rulesets.Objects
|
||||
{
|
||||
for (int j = 0; j < segment.Length - 1; j++)
|
||||
{
|
||||
if (result.Count > 0 && j == 0) result.Add(new PathControlPoint(segment[j]));
|
||||
result.Add(new PathControlPoint(segment[j], j == 0 ? PathType.BEZIER : null));
|
||||
}
|
||||
}
|
||||
@@ -158,6 +160,7 @@ namespace osu.Game.Rulesets.Objects
|
||||
|
||||
for (int j = 0; j < circleResult.Length - 1; j++)
|
||||
{
|
||||
if (result.Count > 0 && j == 0) result.Add(new PathControlPoint(circleResult[j]));
|
||||
result.Add(new PathControlPoint(circleResult[j], j == 0 ? PathType.BEZIER : null));
|
||||
}
|
||||
|
||||
@@ -170,6 +173,7 @@ namespace osu.Game.Rulesets.Objects
|
||||
|
||||
for (int j = 0; j < bSplineResult.Length - 1; j++)
|
||||
{
|
||||
if (result.Count > 0 && j == 0) result.Add(new PathControlPoint(bSplineResult[j]));
|
||||
result.Add(new PathControlPoint(bSplineResult[j], j == 0 ? PathType.BEZIER : null));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user