// 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.Graphics; using osu.Framework.Graphics.Lines; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osuTK; namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneSliderPath : OsuTestScene { private readonly SmoothPath drawablePath; private SliderPath path; public TestSceneSliderPath() { Child = drawablePath = new SmoothPath { Anchor = Anchor.Centre, Origin = Anchor.Centre }; } [SetUp] public void Setup() => Schedule(() => { path = new SliderPath(); }); protected override void Update() { base.Update(); if (path != null) { List<Vector2> vertices = new List<Vector2>(); path.GetPathToProgress(vertices, 0, 1); drawablePath.Vertices = vertices; } } [Test] public void TestEmptyPath() { } [TestCase(PathType.Linear)] [TestCase(PathType.Bezier)] [TestCase(PathType.Catmull)] [TestCase(PathType.PerfectCurve)] public void TestSingleSegment(PathType type) => AddStep("create path", () => path.ControlPoints.AddRange(createSegment(type, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); [TestCase(PathType.Linear)] [TestCase(PathType.Bezier)] [TestCase(PathType.Catmull)] [TestCase(PathType.PerfectCurve)] public void TestMultipleSegment(PathType type) { AddStep("create path", () => { path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero)); path.ControlPoints.AddRange(createSegment(type, new Vector2(0, 100), new Vector2(100), Vector2.Zero)); }); } [Test] public void TestAddControlPoint() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100)))); AddStep("add point", () => path.ControlPoints.Add(new PathControlPoint { Position = { Value = new Vector2(100) } })); } [Test] public void TestInsertControlPoint() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(100)))); AddStep("insert point", () => path.ControlPoints.Insert(1, new PathControlPoint { Position = { Value = new Vector2(0, 100) } })); } [Test] public void TestRemoveControlPoint() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); AddStep("remove second point", () => path.ControlPoints.RemoveAt(1)); } [Test] public void TestChangePathType() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); AddStep("change type to bezier", () => path.ControlPoints[0].Type.Value = PathType.Bezier); } [Test] public void TestAddSegmentByChangingType() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0)))); AddStep("change second point type to bezier", () => path.ControlPoints[1].Type.Value = PathType.Bezier); } [Test] public void TestRemoveSegmentByChangingType() { AddStep("create path", () => { path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0))); path.ControlPoints[1].Type.Value = PathType.Bezier; }); AddStep("change second point type to null", () => path.ControlPoints[1].Type.Value = null); } [Test] public void TestRemoveSegmentByRemovingControlPoint() { AddStep("create path", () => { path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0))); path.ControlPoints[1].Type.Value = PathType.Bezier; }); AddStep("remove second point", () => path.ControlPoints.RemoveAt(1)); } [TestCase(2)] [TestCase(4)] public void TestPerfectCurveFallbackScenarios(int points) { AddStep("create path", () => { switch (points) { case 2: path.ControlPoints.AddRange(createSegment(PathType.PerfectCurve, Vector2.Zero, new Vector2(0, 100))); break; case 4: path.ControlPoints.AddRange(createSegment(PathType.PerfectCurve, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0))); break; } }); } [Test] public void TestLengthenLastSegment() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); AddStep("lengthen last segment", () => path.ExpectedDistance.Value = 300); } [Test] public void TestShortenLastSegment() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); AddStep("shorten last segment", () => path.ExpectedDistance.Value = 150); } [Test] public void TestShortenFirstSegment() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); AddStep("shorten first segment", () => path.ExpectedDistance.Value = 50); } [Test] public void TestShortenToZeroLength() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); AddStep("shorten to 0 length", () => path.ExpectedDistance.Value = 0); } [Test] public void TestShortenToNegativeLength() { AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); AddStep("shorten to -10 length", () => path.ExpectedDistance.Value = -10); } private List<PathControlPoint> createSegment(PathType type, params Vector2[] controlPoints) { var points = controlPoints.Select(p => new PathControlPoint { Position = { Value = p } }).ToList(); points[0].Type.Value = type; return points; } } }