2021-07-22 14:46:23 +08: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 System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using NUnit.Framework;
|
|
|
|
using osu.Framework.Extensions.ObjectExtensions;
|
|
|
|
using osu.Framework.Utils;
|
2021-10-02 11:34:29 +08:00
|
|
|
using osu.Game.Beatmaps;
|
2021-07-22 14:46:23 +08:00
|
|
|
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
|
|
|
using osu.Game.Rulesets.Catch.Objects;
|
|
|
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
|
|
|
using osu.Game.Rulesets.Edit;
|
|
|
|
using osu.Game.Rulesets.Objects;
|
|
|
|
using osu.Game.Rulesets.Objects.Drawables;
|
|
|
|
using osuTK.Input;
|
|
|
|
|
|
|
|
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
|
|
|
{
|
|
|
|
public class TestSceneJuiceStreamPlacementBlueprint : CatchPlacementBlueprintTestScene
|
|
|
|
{
|
|
|
|
private const double velocity = 0.5;
|
|
|
|
|
|
|
|
private JuiceStream lastObject => LastObject?.HitObject as JuiceStream;
|
|
|
|
|
2021-10-02 11:34:29 +08:00
|
|
|
protected override IBeatmap GetPlayableBeatmap()
|
2021-07-22 14:46:23 +08:00
|
|
|
{
|
2021-10-02 11:34:29 +08:00
|
|
|
var playable = base.GetPlayableBeatmap();
|
|
|
|
playable.Difficulty.SliderTickRate = 5;
|
|
|
|
playable.Difficulty.SliderMultiplier = velocity * 10;
|
|
|
|
return playable;
|
2021-07-22 14:46:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestBasicPlacement()
|
|
|
|
{
|
|
|
|
double[] times = { 300, 800 };
|
|
|
|
float[] positions = { 100, 200 };
|
|
|
|
addPlacementSteps(times, positions);
|
|
|
|
|
|
|
|
AddAssert("juice stream is placed", () => lastObject != null);
|
|
|
|
AddAssert("start time is correct", () => Precision.AlmostEquals(lastObject.StartTime, times[0]));
|
|
|
|
AddAssert("end time is correct", () => Precision.AlmostEquals(lastObject.EndTime, times[1]));
|
|
|
|
AddAssert("start position is correct", () => Precision.AlmostEquals(lastObject.OriginalX, positions[0]));
|
|
|
|
AddAssert("end position is correct", () => Precision.AlmostEquals(lastObject.EndX, positions[1]));
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestEmptyNotCommitted()
|
|
|
|
{
|
|
|
|
addMoveAndClickSteps(100, 100);
|
|
|
|
addMoveAndClickSteps(100, 100);
|
|
|
|
addMoveAndClickSteps(100, 100, true);
|
|
|
|
AddAssert("juice stream not placed", () => lastObject == null);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestMultipleSegments()
|
|
|
|
{
|
|
|
|
double[] times = { 100, 300, 500, 700 };
|
|
|
|
float[] positions = { 100, 150, 100, 100 };
|
|
|
|
addPlacementSteps(times, positions);
|
|
|
|
|
|
|
|
AddAssert("has 4 vertices", () => lastObject.Path.ControlPoints.Count == 4);
|
|
|
|
addPathCheckStep(times, positions);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestVelocityLimit()
|
|
|
|
{
|
2021-07-23 09:45:33 +08:00
|
|
|
double[] times = { 100, 300 };
|
|
|
|
float[] positions = { 200, 500 };
|
|
|
|
addPlacementSteps(times, positions);
|
|
|
|
addPathCheckStep(times, new float[] { 200, 300 });
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestPreviousVerticesAreFixed()
|
|
|
|
{
|
|
|
|
double[] times = { 100, 300, 500, 700 };
|
|
|
|
float[] positions = { 200, 400, 100, 500 };
|
2021-07-22 14:46:23 +08:00
|
|
|
addPlacementSteps(times, positions);
|
2021-07-23 09:45:33 +08:00
|
|
|
addPathCheckStep(times, new float[] { 200, 300, 200, 300 });
|
2021-07-22 14:46:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestClampedPositionIsRestored()
|
|
|
|
{
|
|
|
|
double[] times = { 100, 300, 500 };
|
|
|
|
float[] positions = { 200, 200, 0, 250 };
|
|
|
|
|
|
|
|
addMoveAndClickSteps(times[0], positions[0]);
|
|
|
|
addMoveAndClickSteps(times[1], positions[1]);
|
|
|
|
AddMoveStep(times[2], positions[2]);
|
|
|
|
addMoveAndClickSteps(times[2], positions[3], true);
|
|
|
|
|
|
|
|
addPathCheckStep(times, new float[] { 200, 200, 250 });
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestFirstVertexIsFixed()
|
|
|
|
{
|
|
|
|
double[] times = { 100, 200 };
|
|
|
|
float[] positions = { 100, 300 };
|
|
|
|
addPlacementSteps(times, positions);
|
|
|
|
addPathCheckStep(times, new float[] { 100, 150 });
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestOutOfOrder()
|
|
|
|
{
|
|
|
|
double[] times = { 100, 700, 500, 300 };
|
|
|
|
float[] positions = { 100, 200, 150, 50 };
|
|
|
|
addPlacementSteps(times, positions);
|
|
|
|
addPathCheckStep(times, positions);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestMoveBeforeFirstVertex()
|
|
|
|
{
|
|
|
|
double[] times = { 300, 500, 100 };
|
|
|
|
float[] positions = { 100, 100, 100 };
|
|
|
|
addPlacementSteps(times, positions);
|
|
|
|
AddAssert("start time is correct", () => Precision.AlmostEquals(lastObject.StartTime, times[0]));
|
|
|
|
AddAssert("end time is correct", () => Precision.AlmostEquals(lastObject.EndTime, times[1], 1e-3));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableJuiceStream((JuiceStream)hitObject);
|
|
|
|
|
|
|
|
protected override PlacementBlueprint CreateBlueprint() => new JuiceStreamPlacementBlueprint();
|
|
|
|
|
|
|
|
private void addMoveAndClickSteps(double time, float position, bool end = false)
|
|
|
|
{
|
|
|
|
AddMoveStep(time, position);
|
|
|
|
AddClickStep(end ? MouseButton.Right : MouseButton.Left);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void addPlacementSteps(double[] times, float[] positions)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < times.Length; i++)
|
|
|
|
addMoveAndClickSteps(times[i], positions[i], i == times.Length - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void addPathCheckStep(double[] times, float[] positions) => AddStep("assert path is correct", () =>
|
|
|
|
Assert.That(getPositions(times), Is.EqualTo(positions).Within(Precision.FLOAT_EPSILON)));
|
|
|
|
|
|
|
|
private float[] getPositions(IEnumerable<double> times)
|
|
|
|
{
|
|
|
|
JuiceStream hitObject = lastObject.AsNonNull();
|
|
|
|
return times
|
|
|
|
.Select(time => (time - hitObject.StartTime) * hitObject.Velocity)
|
|
|
|
.Select(distance => hitObject.EffectiveX + hitObject.Path.PositionAt(distance / hitObject.Distance).X)
|
|
|
|
.ToArray();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|