diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs
index a98f931e7a3a..495a2211594f 100644
--- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs
+++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs
@@ -7,6 +7,7 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
+using osu.Framework.Utils;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
@@ -66,7 +67,7 @@ public void TestSliderMultiplier(float multiplier)
{
AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = multiplier);
- assertSnapDistance(100 * multiplier);
+ assertSnapDistance(100 * multiplier, null, true);
}
[TestCase(1)]
@@ -79,7 +80,20 @@ public void TestSpeedMultiplierDoesNotChangeDistanceSnap(float multiplier)
{
SliderVelocity = multiplier
}
- });
+ }, false);
+ }
+
+ [TestCase(1)]
+ [TestCase(2)]
+ public void TestSpeedMultiplierDoesChangeDistanceSnap(float multiplier)
+ {
+ assertSnapDistance(100 * multiplier, new HitObject
+ {
+ DifficultyControlPoint = new DifficultyControlPoint
+ {
+ SliderVelocity = multiplier
+ }
+ }, true);
}
[TestCase(1)]
@@ -88,7 +102,32 @@ public void TestBeatDivisor(int divisor)
{
AddStep($"set divisor = {divisor}", () => BeatDivisor.Value = divisor);
- assertSnapDistance(100f / divisor);
+ assertSnapDistance(100f / divisor, null, true);
+ }
+
+ ///
+ /// The basic distance-duration functions should always include slider velocity of the reference object.
+ ///
+ [Test]
+ public void TestConversionsWithSliderVelocity()
+ {
+ const float base_distance = 100;
+ const float slider_velocity = 1.2f;
+
+ var referenceObject = new HitObject
+ {
+ DifficultyControlPoint = new DifficultyControlPoint
+ {
+ SliderVelocity = slider_velocity
+ }
+ };
+
+ assertSnapDistance(base_distance * slider_velocity, referenceObject, true);
+ assertSnappedDistance(base_distance * slider_velocity + 10, base_distance * slider_velocity, referenceObject);
+ assertSnappedDuration(base_distance * slider_velocity + 10, 1000, referenceObject);
+
+ assertDistanceToDuration(base_distance * slider_velocity, 1000, referenceObject);
+ assertDurationToDistance(1000, base_distance * slider_velocity, referenceObject);
}
[Test]
@@ -197,20 +236,20 @@ public void GetSnappedDistanceFromDistance()
assertSnappedDistance(400, 400);
}
- private void assertSnapDistance(float expectedDistance, HitObject? hitObject = null)
- => AddAssert($"distance is {expectedDistance}", () => composer.GetBeatSnapDistanceAt(hitObject ?? new HitObject()), () => Is.EqualTo(expectedDistance));
+ private void assertSnapDistance(float expectedDistance, HitObject? referenceObject, bool includeSliderVelocity)
+ => AddAssert($"distance is {expectedDistance}", () => composer.GetBeatSnapDistanceAt(referenceObject ?? new HitObject(), includeSliderVelocity), () => Is.EqualTo(expectedDistance).Within(Precision.FLOAT_EPSILON));
- private void assertDurationToDistance(double duration, float expectedDistance)
- => AddAssert($"duration = {duration} -> distance = {expectedDistance}", () => composer.DurationToDistance(new HitObject(), duration) == expectedDistance);
+ private void assertDurationToDistance(double duration, float expectedDistance, HitObject? referenceObject = null)
+ => AddAssert($"duration = {duration} -> distance = {expectedDistance}", () => composer.DurationToDistance(referenceObject ?? new HitObject(), duration), () => Is.EqualTo(expectedDistance).Within(Precision.FLOAT_EPSILON));
- private void assertDistanceToDuration(float distance, double expectedDuration)
- => AddAssert($"distance = {distance} -> duration = {expectedDuration}", () => composer.DistanceToDuration(new HitObject(), distance) == expectedDuration);
+ private void assertDistanceToDuration(float distance, double expectedDuration, HitObject? referenceObject = null)
+ => AddAssert($"distance = {distance} -> duration = {expectedDuration}", () => composer.DistanceToDuration(referenceObject ?? new HitObject(), distance), () => Is.EqualTo(expectedDuration).Within(Precision.FLOAT_EPSILON));
- private void assertSnappedDuration(float distance, double expectedDuration)
- => AddAssert($"distance = {distance} -> duration = {expectedDuration} (snapped)", () => composer.FindSnappedDuration(new HitObject(), distance) == expectedDuration);
+ private void assertSnappedDuration(float distance, double expectedDuration, HitObject? referenceObject = null)
+ => AddAssert($"distance = {distance} -> duration = {expectedDuration} (snapped)", () => composer.FindSnappedDuration(referenceObject ?? new HitObject(), distance), () => Is.EqualTo(expectedDuration).Within(Precision.FLOAT_EPSILON));
- private void assertSnappedDistance(float distance, float expectedDistance)
- => AddAssert($"distance = {distance} -> distance = {expectedDistance} (snapped)", () => composer.FindSnappedDistance(new HitObject(), distance) == expectedDistance);
+ private void assertSnappedDistance(float distance, float expectedDistance, HitObject? referenceObject = null)
+ => AddAssert($"distance = {distance} -> distance = {expectedDistance} (snapped)", () => composer.FindSnappedDistance(referenceObject ?? new HitObject(), distance), () => Is.EqualTo(expectedDistance).Within(Precision.FLOAT_EPSILON));
private class TestHitObjectComposer : OsuHitObjectComposer
{
diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs
index 53b6db227774..01a49c7dea79 100644
--- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs
+++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs
@@ -193,7 +193,7 @@ private class SnapProvider : IDistanceSnapProvider
IBindable IDistanceSnapProvider.DistanceSpacingMultiplier => DistanceSpacingMultiplier;
- public float GetBeatSnapDistanceAt(HitObject referenceObject) => beat_snap_distance;
+ public float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true) => beat_snap_distance;
public float DurationToDistance(HitObject referenceObject, double duration) => (float)duration;
diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs
index ca7ca798133f..b0a2694a0a27 100644
--- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs
+++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs
@@ -259,9 +259,9 @@ protected virtual bool AdjustDistanceSpacing(GlobalAction action, float amount)
return true;
}
- public virtual float GetBeatSnapDistanceAt(HitObject referenceObject)
+ public virtual float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true)
{
- return (float)(100 * EditorBeatmap.Difficulty.SliderMultiplier * 1 / BeatSnapProvider.BeatDivisor);
+ return (float)(100 * (useReferenceSliderVelocity ? referenceObject.DifficultyControlPoint.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 / BeatSnapProvider.BeatDivisor);
}
public virtual float DurationToDistance(HitObject referenceObject, double duration)
diff --git a/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs
index 5ad1cc78ff11..6fbd994e23a2 100644
--- a/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs
+++ b/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs
@@ -27,8 +27,9 @@ public interface IDistanceSnapProvider : IPositionSnapProvider
/// Retrieves the distance between two points within a timing point that are one beat length apart.
///
/// An object to be used as a reference point for this operation.
+ /// Whether the 's slider velocity should be factored into the returned distance.
/// The distance between two points residing in the timing point that are one beat length apart.
- float GetBeatSnapDistanceAt(HitObject referenceObject);
+ float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true);
///
/// Converts a duration to a distance without applying any snapping.
diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs
index 69c7fc27750f..c179e7f0c287 100644
--- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs
@@ -97,7 +97,7 @@ protected override void LoadComplete()
private void updateSpacing()
{
float distanceSpacingMultiplier = (float)DistanceSpacingMultiplier.Value;
- float beatSnapDistance = SnapProvider.GetBeatSnapDistanceAt(ReferenceObject);
+ float beatSnapDistance = SnapProvider.GetBeatSnapDistanceAt(ReferenceObject, false);
DistanceBetweenTicks = beatSnapDistance * distanceSpacingMultiplier;