Skip to content

Commit

Permalink
Merge pull request ppy#12310 from FamousPig/perfect-curve-undo
Browse files Browse the repository at this point in the history
Fix consecutive perfect curve segments not being loaded properly
  • Loading branch information
smoogipoo authored Apr 6, 2021
2 parents d4c5507 + dd90244 commit 1c7aa71
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
30 changes: 30 additions & 0 deletions osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,36 @@ public void TestMultiSegmentSliders()
Assert.That(fifth.ControlPoints[5].Type.Value, Is.EqualTo(PathType.Bezier));
Assert.That(fifth.ControlPoints[6].Position.Value, Is.EqualTo(new Vector2(5, 5)));
Assert.That(fifth.ControlPoints[6].Type.Value, Is.EqualTo(null));

// Implicit perfect-curve multi-segment(Should convert to bezier to match stable)
var sixth = ((IHasPath)decoded.HitObjects[5]).Path;

Assert.That(sixth.ControlPoints[0].Position.Value, Is.EqualTo(Vector2.Zero));
Assert.That(sixth.ControlPoints[0].Type.Value == PathType.Bezier);
Assert.That(sixth.ControlPoints[1].Position.Value, Is.EqualTo(new Vector2(75, 145)));
Assert.That(sixth.ControlPoints[1].Type.Value == null);
Assert.That(sixth.ControlPoints[2].Position.Value, Is.EqualTo(new Vector2(170, 75)));

Assert.That(sixth.ControlPoints[2].Type.Value == PathType.Bezier);
Assert.That(sixth.ControlPoints[3].Position.Value, Is.EqualTo(new Vector2(300, 145)));
Assert.That(sixth.ControlPoints[3].Type.Value == null);
Assert.That(sixth.ControlPoints[4].Position.Value, Is.EqualTo(new Vector2(410, 20)));
Assert.That(sixth.ControlPoints[4].Type.Value == null);

// Explicit perfect-curve multi-segment(Should not convert to bezier)
var seventh = ((IHasPath)decoded.HitObjects[6]).Path;

Assert.That(seventh.ControlPoints[0].Position.Value, Is.EqualTo(Vector2.Zero));
Assert.That(seventh.ControlPoints[0].Type.Value == PathType.PerfectCurve);
Assert.That(seventh.ControlPoints[1].Position.Value, Is.EqualTo(new Vector2(75, 145)));
Assert.That(seventh.ControlPoints[1].Type.Value == null);
Assert.That(seventh.ControlPoints[2].Position.Value, Is.EqualTo(new Vector2(170, 75)));

Assert.That(seventh.ControlPoints[2].Type.Value == PathType.PerfectCurve);
Assert.That(seventh.ControlPoints[3].Position.Value, Is.EqualTo(new Vector2(300, 145)));
Assert.That(seventh.ControlPoints[3].Type.Value == null);
Assert.That(seventh.ControlPoints[4].Position.Value, Is.EqualTo(new Vector2(410, 20)));
Assert.That(seventh.ControlPoints[4].Type.Value == null);
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions osu.Game.Tests/Resources/multi-segment-slider.osu
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ osu file format v128

// Last control point in segment duplicated
0,0,5000,2,0,B|1:1|2:2|3:3|3:3|B|4:4|5:5,2,200

// Implicit perfect-curve multi-segment (Should convert to bezier to match stable)
0,0,6000,2,0,P|75:145|170:75|170:75|300:145|410:20,1,475,0:0:0:0:

// Explicit perfect-curve multi-segment (Should not convert to bezier)
0,0,7000,2,0,P|75:145|P|170:75|300:145|410:20,1,650,0:0:0:0:

5 changes: 3 additions & 2 deletions osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,10 @@ private void addPathData(TextWriter writer, IHasPath pathData, Vector2 position)

// 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.
bool needsExplicitSegment = point.Type.Value != lastType;
// 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.Value != lastType || point.Type.Value == PathType.PerfectCurve;

// One 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.
// 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)
{
Expand Down

0 comments on commit 1c7aa71

Please sign in to comment.