osu/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

267 lines
10 KiB
C#
Raw Normal View History

2019-10-25 09:19:26 +00:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
2020-01-01 15:41:06 +00:00
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
2019-10-25 09:19:26 +00:00
using osu.Framework.Testing;
using osu.Framework.Utils;
2019-10-25 09:19:26 +00:00
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
2019-10-25 09:19:26 +00:00
using osu.Game.Rulesets.Osu;
2020-01-01 15:41:06 +00:00
using osu.Game.Rulesets.Osu.Beatmaps;
2019-10-25 09:19:26 +00:00
using osu.Game.Rulesets.Osu.Edit;
using osu.Game.Screens.Edit;
using osu.Game.Tests.Visual;
namespace osu.Game.Tests.Editing
2019-10-25 09:19:26 +00:00
{
[HeadlessTest]
public partial class TestSceneHitObjectComposerDistanceSnapping : EditorClockTestScene
{
private TestHitObjectComposer composer = null!;
2019-10-25 09:19:26 +00:00
2020-01-01 15:41:06 +00:00
[Cached(typeof(EditorBeatmap))]
[Cached(typeof(IBeatSnapProvider))]
private readonly EditorBeatmap editorBeatmap;
protected override Container<Drawable> Content { get; } = new Container { RelativeSizeAxes = Axes.Both };
public TestSceneHitObjectComposerDistanceSnapping()
{
base.Content.Add(new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
editorBeatmap = new EditorBeatmap(new OsuBeatmap
{
BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo },
}),
Content
},
});
}
2020-01-01 15:41:06 +00:00
2019-10-25 09:19:26 +00:00
[SetUp]
public void Setup() => Schedule(() =>
{
Children = new Drawable[]
{
composer = new TestHitObjectComposer()
};
2019-10-25 09:19:26 +00:00
BeatDivisor.Value = 1;
composer.EditorBeatmap.Difficulty.SliderMultiplier = 1;
composer.EditorBeatmap.ControlPointInfo.Clear();
composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 });
2019-10-25 09:19:26 +00:00
});
[TestCase(1)]
[TestCase(2)]
public void TestSliderMultiplier(float multiplier)
{
AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = multiplier);
2019-10-25 09:19:26 +00:00
2022-11-01 06:13:05 +00:00
assertSnapDistance(100 * multiplier, null, true);
2019-10-25 09:19:26 +00:00
}
[TestCase(1)]
[TestCase(2)]
public void TestSpeedMultiplierDoesNotChangeDistanceSnap(float multiplier)
2019-10-25 09:19:26 +00:00
{
assertSnapDistance(100, new HitObject
2019-10-25 09:19:26 +00:00
{
2021-09-02 10:42:41 +00:00
DifficultyControlPoint = new DifficultyControlPoint
{
SliderVelocity = multiplier
}
2022-11-01 06:13:05 +00:00
}, false);
}
[TestCase(1)]
[TestCase(2)]
public void TestSpeedMultiplierDoesChangeDistanceSnap(float multiplier)
{
assertSnapDistance(100 * multiplier, new HitObject
{
DifficultyControlPoint = new DifficultyControlPoint
{
SliderVelocity = multiplier
}
}, true);
2019-10-25 09:19:26 +00:00
}
[TestCase(1)]
[TestCase(2)]
public void TestBeatDivisor(int divisor)
{
AddStep($"set divisor = {divisor}", () => BeatDivisor.Value = divisor);
2022-11-01 06:13:05 +00:00
assertSnapDistance(100f / divisor, null, true);
2019-10-25 09:19:26 +00:00
}
/// <summary>
/// The basic distance-duration functions should always include slider velocity of the reference object.
/// </summary>
[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);
}
2019-10-25 09:19:26 +00:00
[Test]
public void TestConvertDurationToDistance()
{
assertDurationToDistance(500, 50);
assertDurationToDistance(1000, 100);
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2);
2019-10-25 09:19:26 +00:00
assertDurationToDistance(500, 100);
assertDurationToDistance(1000, 200);
AddStep("set beat length = 500", () =>
{
composer.EditorBeatmap.ControlPointInfo.Clear();
composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 500 });
2019-10-25 09:19:26 +00:00
});
assertDurationToDistance(500, 200);
assertDurationToDistance(1000, 400);
}
[Test]
public void TestConvertDistanceToDuration()
{
assertDistanceToDuration(50, 500);
assertDistanceToDuration(100, 1000);
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2);
2019-10-25 09:19:26 +00:00
assertDistanceToDuration(100, 500);
assertDistanceToDuration(200, 1000);
AddStep("set beat length = 500", () =>
{
composer.EditorBeatmap.ControlPointInfo.Clear();
composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 500 });
2019-10-25 09:19:26 +00:00
});
assertDistanceToDuration(200, 500);
assertDistanceToDuration(400, 1000);
}
[Test]
public void TestGetSnappedDurationFromDistance()
{
2020-01-28 04:42:22 +00:00
assertSnappedDuration(0, 0);
assertSnappedDuration(50, 1000);
2019-10-25 09:19:26 +00:00
assertSnappedDuration(100, 1000);
2020-01-28 04:42:22 +00:00
assertSnappedDuration(150, 2000);
2019-10-25 09:19:26 +00:00
assertSnappedDuration(200, 2000);
2020-01-28 04:42:22 +00:00
assertSnappedDuration(250, 3000);
2019-10-25 09:19:26 +00:00
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2);
2019-10-25 09:19:26 +00:00
2020-01-28 04:42:22 +00:00
assertSnappedDuration(0, 0);
2019-10-25 09:19:26 +00:00
assertSnappedDuration(50, 0);
2020-01-28 04:42:22 +00:00
assertSnappedDuration(100, 1000);
assertSnappedDuration(150, 1000);
2019-10-25 09:19:26 +00:00
assertSnappedDuration(200, 1000);
assertSnappedDuration(250, 1000);
AddStep("set beat length = 500", () =>
{
composer.EditorBeatmap.ControlPointInfo.Clear();
composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 500 });
2019-10-25 09:19:26 +00:00
});
assertSnappedDuration(50, 0);
2020-01-28 04:42:22 +00:00
assertSnappedDuration(100, 500);
assertSnappedDuration(150, 500);
2019-10-25 09:19:26 +00:00
assertSnappedDuration(200, 500);
assertSnappedDuration(250, 500);
assertSnappedDuration(400, 1000);
}
[Test]
public void GetSnappedDistanceFromDistance()
{
assertSnappedDistance(50, 0);
2019-10-25 09:19:26 +00:00
assertSnappedDistance(100, 100);
assertSnappedDistance(150, 100);
2019-10-25 09:19:26 +00:00
assertSnappedDistance(200, 200);
assertSnappedDistance(250, 200);
2019-10-25 09:19:26 +00:00
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2);
2019-10-25 09:19:26 +00:00
assertSnappedDistance(50, 0);
assertSnappedDistance(100, 0);
assertSnappedDistance(150, 0);
2019-10-25 09:19:26 +00:00
assertSnappedDistance(200, 200);
assertSnappedDistance(250, 200);
AddStep("set beat length = 500", () =>
{
composer.EditorBeatmap.ControlPointInfo.Clear();
composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 500 });
2019-10-25 09:19:26 +00:00
});
assertSnappedDistance(50, 0);
assertSnappedDistance(100, 0);
assertSnappedDistance(150, 0);
2019-10-25 09:19:26 +00:00
assertSnappedDistance(200, 200);
assertSnappedDistance(250, 200);
assertSnappedDistance(400, 400);
}
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));
2019-10-25 09:19:26 +00:00
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));
2019-10-25 09:19:26 +00:00
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));
2019-10-25 09:19:26 +00:00
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));
2019-10-25 09:19:26 +00:00
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));
2019-10-25 09:19:26 +00:00
private partial class TestHitObjectComposer : OsuHitObjectComposer
{
2019-12-27 10:39:30 +00:00
public new EditorBeatmap EditorBeatmap => base.EditorBeatmap;
2019-10-25 09:19:26 +00:00
public new Bindable<double> DistanceSpacingMultiplier => base.DistanceSpacingMultiplier;
2019-10-25 09:19:26 +00:00
public TestHitObjectComposer()
: base(new OsuRuleset())
{
}
}
}
}