From 9b2f25cb93d83899801f73ea2a8c474f16b36f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 May 2025 13:33:13 +0200 Subject: [PATCH] Fix crashes when attempting to adjust length of slider whose maximum path length is less than the current beat snap Closes https://github.com/ppy/osu/issues/32289. There are two possible choices here: either pulling the lower bound of the clamp down to `HitObject.Path.CalculatedDistance`, or pulling the higher bound up to `minDistance`, if it happens to be larger than the path's calculated distance. Both options are a bit weird; pulling down can result in unsnapped sliders when attempting to drag a slider's end when on a lower beat divisor than was used to place the slider, and pulling up can result in weird sliders wherein they get extended beyond their path's definition with a weird linear section at the end without an anchor that is tangent to the slider shape's end. I decided the first one was less weird, but I'm open to discuss further. --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index d6150f85db..363533ae76 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -275,6 +275,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders else { double minDistance = distanceSnapProvider?.GetBeatSnapDistance() * oldVelocityMultiplier ?? 1; + // do not allow the slider to extend beyond the path's calculated distance. + // this can happen in two specific circumstances: + // - floating point issues (`minDistance` is just ever so slightly larger than the calculated distance) + // - the slider was placed with a higher beat snap active than the current one, + // therefore snapping it to the current beat snap distance would mean extrapolating it beyond its actual shape as defined by its control points + minDistance = Math.Min(minDistance, HitObject.Path.CalculatedDistance); + // Add a small amount to the proposed distance to make it easier to snap to the full length of the slider. proposedDistance = distanceSnapProvider?.FindSnappedDistance((float)proposedDistance + 1, HitObject.StartTime, HitObject) ?? proposedDistance; proposedDistance = Math.Clamp(proposedDistance, minDistance, HitObject.Path.CalculatedDistance);