2019-10-11 14:27: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 ;
using NUnit.Framework ;
using osu.Framework.Allocation ;
using osu.Framework.Graphics ;
2019-10-11 16:11:37 +08:00
using osu.Framework.Graphics.Containers ;
2019-10-11 14:27:23 +08:00
using osu.Framework.Graphics.Shapes ;
using osu.Framework.Input.Events ;
2020-01-09 12:43:44 +08:00
using osu.Framework.Utils ;
2019-10-11 14:27:23 +08:00
using osu.Game.Beatmaps.ControlPoints ;
2019-10-25 16:25:46 +08:00
using osu.Game.Rulesets.Edit ;
2021-09-01 17:05:10 +08:00
using osu.Game.Rulesets.Objects ;
2019-10-11 14:27:23 +08:00
using osu.Game.Rulesets.Osu.Beatmaps ;
2019-10-11 16:13:28 +08:00
using osu.Game.Rulesets.Osu.Edit ;
2019-10-11 14:27:23 +08:00
using osu.Game.Rulesets.Osu.Objects ;
using osu.Game.Screens.Edit ;
using osu.Game.Tests.Visual ;
using osuTK ;
using osuTK.Graphics ;
2020-09-25 17:48:04 +08:00
namespace osu.Game.Rulesets.Osu.Tests.Editor
2019-10-11 14:27:23 +08:00
{
2020-03-23 09:01:33 +08:00
public class TestSceneOsuDistanceSnapGrid : OsuManualInputManagerTestScene
2019-10-11 14:27:23 +08:00
{
private const double beat_length = 100 ;
private static readonly Vector2 grid_position = new Vector2 ( 512 , 384 ) ;
2019-12-27 18:46:33 +08:00
[Cached(typeof(EditorBeatmap))]
2019-12-27 18:39:30 +08:00
private readonly EditorBeatmap editorBeatmap ;
2019-10-11 14:27:23 +08:00
[Cached]
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor ( ) ;
2020-05-20 16:48:43 +08:00
[Cached(typeof(IPositionSnapProvider))]
2019-10-25 16:25:46 +08:00
private readonly SnapProvider snapProvider = new SnapProvider ( ) ;
2019-11-06 15:20:13 +08:00
private TestOsuDistanceSnapGrid grid ;
2019-10-11 14:27:23 +08:00
2019-10-17 14:32:02 +08:00
public TestSceneOsuDistanceSnapGrid ( )
2019-10-11 14:27:23 +08:00
{
2022-01-12 22:17:35 +08:00
editorBeatmap = new EditorBeatmap ( new OsuBeatmap
{
BeatmapInfo =
{
Ruleset = new OsuRuleset ( ) . RulesetInfo
}
} ) ;
2019-11-06 15:20:13 +08:00
}
[SetUp]
public void Setup ( ) = > Schedule ( ( ) = >
{
2021-10-02 11:34:29 +08:00
editorBeatmap . Difficulty . SliderMultiplier = 1 ;
2019-11-06 15:20:13 +08:00
editorBeatmap . ControlPointInfo . Clear ( ) ;
editorBeatmap . ControlPointInfo . Add ( 0 , new TimingControlPoint { BeatLength = beat_length } ) ;
2019-10-11 16:11:37 +08:00
2019-10-25 16:25:46 +08:00
Children = new Drawable [ ]
{
new Box
{
RelativeSizeAxes = Axes . Both ,
Colour = Color4 . SlateGray
} ,
grid = new TestOsuDistanceSnapGrid ( new HitCircle { Position = grid_position } ) ,
new SnappingCursorContainer { GetSnapPosition = v = > grid . GetSnappedPosition ( grid . ToLocalSpace ( v ) ) . position }
} ;
2019-10-11 14:27:23 +08:00
} ) ;
[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
[TestCase(4)]
[TestCase(6)]
[TestCase(8)]
[TestCase(12)]
[TestCase(16)]
public void TestBeatDivisor ( int divisor )
{
AddStep ( $"set beat divisor = {divisor}" , ( ) = > beatDivisor . Value = divisor ) ;
2019-10-11 16:11:37 +08:00
}
[Test]
public void TestCursorInCentre ( )
{
AddStep ( "move mouse to centre" , ( ) = > InputManager . MoveMouseTo ( grid . ToScreenSpace ( grid_position ) ) ) ;
assertSnappedDistance ( ( float ) beat_length ) ;
}
[Test]
public void TestCursorBeforeMovementPoint ( )
{
AddStep ( "move mouse to just before movement point" , ( ) = > InputManager . MoveMouseTo ( grid . ToScreenSpace ( grid_position + new Vector2 ( ( float ) beat_length , 0 ) * 1.49f ) ) ) ;
assertSnappedDistance ( ( float ) beat_length ) ;
}
[Test]
public void TestCursorAfterMovementPoint ( )
{
AddStep ( "move mouse to just after movement point" , ( ) = > InputManager . MoveMouseTo ( grid . ToScreenSpace ( grid_position + new Vector2 ( ( float ) beat_length , 0 ) * 1.51f ) ) ) ;
assertSnappedDistance ( ( float ) beat_length * 2 ) ;
}
2019-11-06 15:20:13 +08:00
[Test]
public void TestLimitedDistance ( )
{
AddStep ( "create limited grid" , ( ) = >
{
Children = new Drawable [ ]
{
new Box
{
RelativeSizeAxes = Axes . Both ,
Colour = Color4 . SlateGray
} ,
grid = new TestOsuDistanceSnapGrid ( new HitCircle { Position = grid_position } , new HitCircle { StartTime = 200 } ) ,
new SnappingCursorContainer { GetSnapPosition = v = > grid . GetSnappedPosition ( grid . ToLocalSpace ( v ) ) . position }
} ;
} ) ;
AddStep ( "move mouse outside grid" , ( ) = > InputManager . MoveMouseTo ( grid . ToScreenSpace ( grid_position + new Vector2 ( ( float ) beat_length , 0 ) * 3f ) ) ) ;
assertSnappedDistance ( ( float ) beat_length * 2 ) ;
}
2019-10-11 16:11:37 +08:00
private void assertSnappedDistance ( float expectedDistance ) = > AddAssert ( $"snap distance = {expectedDistance}" , ( ) = >
{
2019-10-25 11:34:49 +08:00
Vector2 snappedPosition = grid . GetSnappedPosition ( grid . ToLocalSpace ( InputManager . CurrentState . Mouse . Position ) ) . position ;
2019-10-11 16:11:37 +08:00
2019-10-25 11:34:49 +08:00
return Precision . AlmostEquals ( expectedDistance , Vector2 . Distance ( snappedPosition , grid_position ) ) ;
2019-10-11 16:11:37 +08:00
} ) ;
private class SnappingCursorContainer : CompositeDrawable
{
public Func < Vector2 , Vector2 > GetSnapPosition ;
private readonly Drawable cursor ;
public SnappingCursorContainer ( )
{
RelativeSizeAxes = Axes . Both ;
InternalChild = cursor = new Circle
{
Origin = Anchor . Centre ,
Size = new Vector2 ( 50 ) ,
Colour = Color4 . Red
} ;
}
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
updatePosition ( GetContainingInputManager ( ) . CurrentState . Mouse . Position ) ;
}
protected override bool OnMouseMove ( MouseMoveEvent e )
{
base . OnMouseMove ( e ) ;
updatePosition ( e . ScreenSpaceMousePosition ) ;
return true ;
}
private void updatePosition ( Vector2 screenSpacePosition )
{
cursor . Position = GetSnapPosition . Invoke ( screenSpacePosition ) ;
}
}
2019-10-17 14:32:02 +08:00
private class TestOsuDistanceSnapGrid : OsuDistanceSnapGrid
2019-10-11 16:11:37 +08:00
{
public new float DistanceSpacing = > base . DistanceSpacing ;
2019-11-06 15:20:13 +08:00
public TestOsuDistanceSnapGrid ( OsuHitObject hitObject , OsuHitObject nextHitObject = null )
: base ( hitObject , nextHitObject )
2019-10-11 16:11:37 +08:00
{
}
}
2019-10-25 16:25:46 +08:00
2020-05-20 16:48:43 +08:00
private class SnapProvider : IPositionSnapProvider
2019-10-25 16:25:46 +08:00
{
2020-11-24 16:14:39 +08:00
public SnapResult SnapScreenSpacePositionToValidPosition ( Vector2 screenSpacePosition ) = >
new SnapResult ( screenSpacePosition , null ) ;
2020-05-20 17:19:21 +08:00
public SnapResult SnapScreenSpacePositionToValidTime ( Vector2 screenSpacePosition ) = > new SnapResult ( screenSpacePosition , 0 ) ;
2019-10-25 16:25:46 +08:00
2021-09-01 17:05:10 +08:00
public float GetBeatSnapDistanceAt ( HitObject referenceObject ) = > ( float ) beat_length ;
2019-10-25 16:25:46 +08:00
2021-09-01 17:05:10 +08:00
public float DurationToDistance ( HitObject referenceObject , double duration ) = > ( float ) duration ;
2019-10-25 16:25:46 +08:00
2021-09-01 17:05:10 +08:00
public double DistanceToDuration ( HitObject referenceObject , float distance ) = > distance ;
2019-10-25 16:25:46 +08:00
2021-09-01 17:05:10 +08:00
public double GetSnappedDurationFromDistance ( HitObject referenceObject , float distance ) = > 0 ;
2019-10-25 16:25:46 +08:00
2021-09-01 17:05:10 +08:00
public float GetSnappedDistanceFromDistance ( HitObject referenceObject , float distance ) = > 0 ;
2019-10-25 16:25:46 +08:00
}
2019-10-11 14:27:23 +08:00
}
}