From 696e3d53afdc3754c7d8a2565d022520664d1c4c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 9 Oct 2020 20:50:09 +0900 Subject: [PATCH 1/2] Fix slider samples being overwritten by the last node --- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 6 ++++-- osu.Game.Rulesets.Osu/Objects/Slider.cs | 11 ++++++----- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 3 --- osu.Game/Rulesets/Objects/Types/IHasRepeats.cs | 10 ++++++++++ 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 6b8b70ed54..e209d012fa 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -56,6 +57,7 @@ namespace osu.Game.Rulesets.Catch.Objects Volume = s.Volume }).ToList(); + int nodeIndex = 0; SliderEventDescriptor? lastEvent = null; foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset, cancellationToken)) @@ -105,7 +107,7 @@ namespace osu.Game.Rulesets.Catch.Objects case SliderEventType.Repeat: AddNested(new Fruit { - Samples = Samples, + Samples = this.GetNodeSamples(nodeIndex++), StartTime = e.Time, X = X + Path.PositionAt(e.PathProgress).X, }); @@ -119,7 +121,7 @@ namespace osu.Game.Rulesets.Catch.Objects public double Duration { get => this.SpanCount() * Path.Distance / Velocity; - set => throw new System.NotSupportedException($"Adjust via {nameof(RepeatCount)} instead"); // can be implemented if/when needed. + set => throw new NotSupportedException($"Adjust via {nameof(RepeatCount)} instead"); // can be implemented if/when needed. } public double EndTime => StartTime + Duration; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 917382eccf..755ce0866a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -137,6 +137,10 @@ namespace osu.Game.Rulesets.Osu.Objects Velocity = scoringDistance / timingPoint.BeatLength; TickDistance = scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier; + + // The samples should be attached to the slider tail, however this can only be done after LegacyLastTick is removed otherwise they would play earlier than they're intended to. + // For now, the samples are attached to and played by the slider itself at the correct end time. + Samples = this.GetNodeSamples(repeatCount + 1); } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) @@ -230,15 +234,12 @@ namespace osu.Game.Rulesets.Osu.Objects tick.Samples = sampleList; foreach (var repeat in NestedHitObjects.OfType()) - repeat.Samples = getNodeSamples(repeat.RepeatIndex + 1); + repeat.Samples = this.GetNodeSamples(repeat.RepeatIndex + 1); if (HeadCircle != null) - HeadCircle.Samples = getNodeSamples(0); + HeadCircle.Samples = this.GetNodeSamples(0); } - private IList getNodeSamples(int nodeIndex) => - nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; - public override Judgement CreateJudgement() => new OsuIgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 9afc0ecaf4..f6adeced96 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -184,9 +184,6 @@ namespace osu.Game.Rulesets.Objects.Legacy nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); result = CreateSlider(pos, combo, comboOffset, convertControlPoints(points, pathType), length, repeatCount, nodeSamples); - - // The samples are played when the slider ends, which is the last node - result.Samples = nodeSamples[^1]; } else if (type.HasFlag(LegacyHitObjectType.Spinner)) { diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index 7a3fb16196..674e2aee88 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -35,5 +35,15 @@ namespace osu.Game.Rulesets.Objects.Types /// /// The object that has repeats. public static int SpanCount(this IHasRepeats obj) => obj.RepeatCount + 1; + + /// + /// Retrieves the samples at a particular node in a object. + /// + /// The . + /// The node to attempt to retrieve the samples at. + /// The samples at the given node index, or 's default samples if the given node doesn't exist. + public static IList GetNodeSamples(this T obj, int nodeIndex) + where T : HitObject, IHasRepeats + => nodeIndex < obj.NodeSamples.Count ? obj.NodeSamples[nodeIndex] : obj.Samples; } } From 65d8530a11008333c8fc3b75c9fbee2a74c3d96b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 9 Oct 2020 22:47:32 +0900 Subject: [PATCH 2/2] Fix tests --- .../Testing/Beatmaps/convert-samples-expected-conversion.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/convert-samples-expected-conversion.json b/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/convert-samples-expected-conversion.json index fec1360b26..d49ffa01c5 100644 --- a/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/convert-samples-expected-conversion.json +++ b/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/convert-samples-expected-conversion.json @@ -10,7 +10,7 @@ ["soft-hitnormal"], ["drum-hitnormal"] ], - "Samples": ["drum-hitnormal"] + "Samples": ["-hitnormal"] }, { "StartTime": 1875.0, "EndTime": 2750.0, @@ -19,7 +19,7 @@ ["soft-hitnormal"], ["drum-hitnormal"] ], - "Samples": ["drum-hitnormal"] + "Samples": ["-hitnormal"] }] }, { "StartTime": 3750.0,