diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs
index 4010218f6e..a90d60cd1b 100644
--- a/osu.Game.Rulesets.Osu/Objects/Slider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs
@@ -163,14 +163,6 @@ namespace osu.Game.Rulesets.Osu.Objects
TickDistance = generateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity;
}
- protected override void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
- {
- base.ApplyLegacyInfoToSelf(controlPointInfo, difficulty);
-
- DifficultyControlPoint difficultyControlPoint = controlPointInfo is LegacyControlPointInfo legacyInfo ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT;
- SliderVelocity = difficultyControlPoint.SliderVelocity;
- }
-
protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
{
base.CreateNestedHitObjects(cancellationToken);
diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
index 6f948e4d23..dad23df282 100644
--- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
@@ -17,6 +17,7 @@ using osu.Game.IO;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Legacy;
+using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Beatmaps.Formats
{
@@ -27,6 +28,11 @@ namespace osu.Game.Beatmaps.Formats
///
public const int EARLY_VERSION_TIMING_OFFSET = 24;
+ ///
+ /// A small adjustment to the start time of control points to account for rounding/precision errors.
+ ///
+ private const double control_point_leniency = 1;
+
internal static RulesetStore RulesetStore;
private Beatmap beatmap;
@@ -87,12 +93,11 @@ namespace osu.Game.Beatmaps.Formats
foreach (var hitObject in this.beatmap.HitObjects)
{
- applyLegacyInfoToHitObject(hitObject);
- hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.Difficulty);
+ applyLegacyInfoAndDefaults(hitObject);
}
}
- private void applyLegacyInfoToHitObject(HitObject hitObject)
+ private void applyLegacyInfoAndDefaults(HitObject hitObject)
{
var legacyInfo = beatmap.ControlPointInfo as LegacyControlPointInfo;
@@ -102,7 +107,30 @@ namespace osu.Game.Beatmaps.Formats
#pragma warning restore 618
hitObject.SetContext(new LegacyContext(legacyDifficultyControlPoint.BpmMultiplier, legacyDifficultyControlPoint.GenerateTicks));
- hitObject.ApplyLegacyInfo(beatmap.ControlPointInfo, beatmap.Difficulty);
+ if (hitObject is IHasSliderVelocity hasSliderVelocity)
+ hasSliderVelocity.SliderVelocity = difficultyControlPoint.SliderVelocity;
+
+ hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty);
+
+ SampleControlPoint sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(hitObject.GetEndTime() + control_point_leniency) : SampleControlPoint.DEFAULT;
+
+ foreach (var hitSampleInfo in hitObject.Samples)
+ {
+ sampleControlPoint.ApplyTo(hitSampleInfo);
+ }
+
+ if (hitObject is not IHasRepeats hasRepeats) return;
+
+ for (int i = 0; i < hasRepeats.NodeSamples.Count; i++)
+ {
+ double time = hitObject.StartTime + i * hasRepeats.Duration / hasRepeats.SpanCount() + control_point_leniency;
+ sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(time) : SampleControlPoint.DEFAULT;
+
+ foreach (var hitSampleInfo in hasRepeats.NodeSamples[i])
+ {
+ sampleControlPoint.ApplyTo(hitSampleInfo);
+ }
+ }
}
///
diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs
index fb7a5739b4..2298a7ef12 100644
--- a/osu.Game/Rulesets/Objects/HitObject.cs
+++ b/osu.Game/Rulesets/Objects/HitObject.cs
@@ -158,32 +158,6 @@ namespace osu.Game.Rulesets.Objects
HitWindows?.SetDifficulty(difficulty.OverallDifficulty);
}
- ///
- /// Applies legacy information to this HitObject.
- /// This method gets called at the end of before applying defaults.
- ///
- /// The control points.
- /// The difficulty settings to use.
- /// The cancellation token.
- public void ApplyLegacyInfo(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty, CancellationToken cancellationToken = default)
- {
- var legacyInfo = controlPointInfo as LegacyControlPointInfo;
-
- ApplyLegacyInfoToSelf(controlPointInfo, difficulty);
-
- // This is done here after ApplyLegacyInfoToSelf as we may require custom defaults to be applied to have an accurate end time.
- SampleControlPoint sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(this.GetEndTime() + control_point_leniency) : SampleControlPoint.DEFAULT;
-
- foreach (var hitSampleInfo in Samples)
- {
- sampleControlPoint.ApplyTo(hitSampleInfo);
- }
- }
-
- protected virtual void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
- {
- }
-
protected virtual void CreateNestedHitObjects(CancellationToken cancellationToken)
{
}
diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
index 11e1f0beae..47aabf1599 100644
--- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
@@ -54,14 +54,6 @@ namespace osu.Game.Rulesets.Objects.Legacy
Velocity = scoringDistance / timingPoint.BeatLength;
}
- protected override void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
- {
- base.ApplyLegacyInfoToSelf(controlPointInfo, difficulty);
-
- DifficultyControlPoint difficultyControlPoint = controlPointInfo is LegacyControlPointInfo legacyInfo ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT;
- SliderVelocity = difficultyControlPoint.SliderVelocity;
- }
-
public double LegacyLastTickOffset => 36;
}
}