From 9259aa94f10897d044e590ad61e0aa6e5506bf7a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 24 May 2022 11:47:42 +0900 Subject: [PATCH] Fix Catmull slider parsing with duplicate initial point --- .../Formats/LegacyBeatmapDecoderTest.cs | 19 +++++++++++++++++++ ...catmull-duplicate-initial-controlpoint.osu | 2 ++ .../Objects/Legacy/ConvertHitObjectParser.cs | 6 ++++-- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Resources/catmull-duplicate-initial-controlpoint.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 89baaf228d..e2d9910b82 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -898,5 +898,24 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.That(controlPoints[3].Type, Is.Null); } } + + [Test] + public void TestLegacyDuplicateInitialCatmullPointIsMerged() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("catmull-duplicate-initial-controlpoint.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + var decoded = decoder.Decode(stream); + var controlPoints = ((IHasPath)decoded.HitObjects[0]).Path.ControlPoints; + + Assert.That(controlPoints.Count, Is.EqualTo(4)); + Assert.That(controlPoints[0].Type, Is.EqualTo(PathType.Catmull)); + Assert.That(controlPoints[0].Position, Is.EqualTo(Vector2.Zero)); + Assert.That(controlPoints[1].Type, Is.Null); + Assert.That(controlPoints[1].Position, Is.Not.EqualTo(Vector2.Zero)); + } + } } } diff --git a/osu.Game.Tests/Resources/catmull-duplicate-initial-controlpoint.osu b/osu.Game.Tests/Resources/catmull-duplicate-initial-controlpoint.osu new file mode 100644 index 0000000000..7062229eed --- /dev/null +++ b/osu.Game.Tests/Resources/catmull-duplicate-initial-controlpoint.osu @@ -0,0 +1,2 @@ +[HitObjects] +200,304,23875,6,0,C|200:304|288:304|288:208|352:208,1,260,8|0 \ No newline at end of file diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 7cf68a2df7..d3d1196eae 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -340,8 +340,10 @@ namespace osu.Game.Rulesets.Objects.Legacy if (vertices[endIndex].Position != vertices[endIndex - 1].Position) continue; - // Adjacent legacy Catmull segments should be treated as a single segment. - if (FormatVersion < LegacyBeatmapEncoder.FIRST_LAZER_VERSION && type == PathType.Catmull) + // Legacy Catmull sliders don't support multiple segments, so adjacent Catmull segments should be treated as a single one. + // Importantly, this is not applied to the first control point, which may duplicate the slider path's position + // resulting in a duplicate (0,0) control point in the resultant list. + if (type == PathType.Catmull && endIndex > 1 && FormatVersion < LegacyBeatmapEncoder.FIRST_LAZER_VERSION) continue; // The last control point of each segment is not allowed to start a new implicit segment.