2021-09-26 23:41:20 +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.
2022-06-17 15:37:17 +08:00
#nullable disable
2021-09-26 23:41:20 +08:00
using System ;
2021-09-26 23:45:47 +08:00
using System.Collections.Generic ;
2021-09-26 23:41:20 +08:00
using System.Linq ;
using NUnit.Framework ;
2023-10-30 17:06:09 +08:00
using osu.Framework.Graphics.UserInterface ;
2021-09-26 23:41:20 +08:00
using osu.Framework.Testing ;
using osu.Game.Beatmaps ;
2023-10-30 17:06:09 +08:00
using osu.Game.Graphics.UserInterface ;
2021-09-26 23:41:20 +08:00
using osu.Game.Rulesets ;
using osu.Game.Rulesets.Objects ;
using osu.Game.Rulesets.Osu ;
2024-06-14 15:08:25 +08:00
using osu.Game.Rulesets.Osu.Edit ;
2021-09-26 23:41:20 +08:00
using osu.Game.Rulesets.Osu.Objects ;
using osu.Game.Screens.Edit.Compose.Components.Timeline ;
using osu.Game.Tests.Beatmaps ;
using osuTK ;
using osuTK.Input ;
namespace osu.Game.Tests.Visual.Editing
{
public partial class TestSceneTimelineSelection : EditorTestScene
{
protected override Ruleset CreateEditorRuleset ( ) = > new OsuRuleset ( ) ;
protected override IBeatmap CreateBeatmap ( RulesetInfo ruleset ) = > new TestBeatmap ( ruleset , false ) ;
private TimelineBlueprintContainer blueprintContainer
= > Editor . ChildrenOfType < TimelineBlueprintContainer > ( ) . First ( ) ;
2022-10-05 22:29:45 +08:00
private Vector2 getPosition ( HitObject hitObject ) = >
blueprintContainer . SelectionBlueprints . First ( s = > s . Item = = hitObject ) . ScreenSpaceDrawQuad . Centre ;
private Vector2 getMiddlePosition ( HitObject hitObject1 , HitObject hitObject2 ) = >
( getPosition ( hitObject1 ) + getPosition ( hitObject2 ) ) / 2 ;
2021-09-26 23:41:20 +08:00
private void moveMouseToObject ( Func < HitObject > targetFunc )
{
AddStep ( "move mouse to object" , ( ) = >
{
2022-10-05 22:29:45 +08:00
var hitObject = targetFunc ( ) ;
InputManager . MoveMouseTo ( getPosition ( hitObject ) ) ;
2021-09-26 23:41:20 +08:00
} ) ;
}
2023-10-30 17:06:09 +08:00
[Test]
public void TestContextMenuWithObjectBehind ( )
{
TimelineHitObjectBlueprint blueprint ;
AddStep ( "add object" , ( ) = >
{
EditorBeatmap . Add ( new HitCircle { StartTime = 3000 } ) ;
} ) ;
AddStep ( "enter slider placement" , ( ) = >
{
InputManager . Key ( Key . Number3 ) ;
InputManager . MoveMouseTo ( ScreenSpaceDrawQuad . Centre ) ;
} ) ;
AddStep ( "start conflicting slider" , ( ) = >
{
InputManager . Click ( MouseButton . Left ) ;
blueprint = this . ChildrenOfType < TimelineHitObjectBlueprint > ( ) . First ( ) ;
InputManager . MoveMouseTo ( blueprint . ScreenSpaceDrawQuad . TopLeft - new Vector2 ( 10 , 0 ) ) ;
} ) ;
AddStep ( "end conflicting slider" , ( ) = >
{
InputManager . Click ( MouseButton . Right ) ;
} ) ;
AddStep ( "click object" , ( ) = >
{
InputManager . Key ( Key . Number1 ) ;
blueprint = this . ChildrenOfType < TimelineHitObjectBlueprint > ( ) . First ( ) ;
InputManager . MoveMouseTo ( blueprint ) ;
InputManager . Click ( MouseButton . Left ) ;
} ) ;
AddStep ( "right click" , ( ) = > InputManager . Click ( MouseButton . Right ) ) ;
AddAssert ( "context menu open" , ( ) = > this . ChildrenOfType < OsuContextMenu > ( ) . SingleOrDefault ( ) ? . State = = MenuState . Open ) ;
}
2021-09-26 23:41:20 +08:00
[Test]
public void TestNudgeSelection ( )
{
HitCircle [ ] addedObjects = null ;
AddStep ( "add hitobjects" , ( ) = > EditorBeatmap . AddRange ( addedObjects = new [ ]
{
2022-01-25 22:02:23 +08:00
new HitCircle { StartTime = 500 } ,
new HitCircle { StartTime = 1000 , Position = new Vector2 ( 100 ) } ,
new HitCircle { StartTime = 1500 , Position = new Vector2 ( 200 ) } ,
new HitCircle { StartTime = 2000 , Position = new Vector2 ( 300 ) } ,
2021-09-26 23:41:20 +08:00
} ) ) ;
AddStep ( "select objects" , ( ) = > EditorBeatmap . SelectedHitObjects . AddRange ( addedObjects ) ) ;
AddStep ( "nudge forwards" , ( ) = > InputManager . Key ( Key . K ) ) ;
2022-01-25 22:02:23 +08:00
AddAssert ( "objects moved forwards in time" , ( ) = > addedObjects [ 0 ] . StartTime > 500 ) ;
2021-09-26 23:41:20 +08:00
AddStep ( "nudge backwards" , ( ) = > InputManager . Key ( Key . J ) ) ;
2022-01-25 22:02:23 +08:00
AddAssert ( "objects reverted to original position" , ( ) = > addedObjects [ 0 ] . StartTime = = 500 ) ;
2021-09-26 23:41:20 +08:00
}
[Test]
public void TestBasicSelect ( )
{
2022-01-25 22:02:23 +08:00
var addedObject = new HitCircle { StartTime = 500 } ;
2021-09-26 23:41:20 +08:00
AddStep ( "add hitobject" , ( ) = > EditorBeatmap . Add ( addedObject ) ) ;
moveMouseToObject ( ( ) = > addedObject ) ;
AddStep ( "left click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "hitobject selected" , ( ) = > EditorBeatmap . SelectedHitObjects . Single ( ) = = addedObject ) ;
var addedObject2 = new HitCircle
{
2022-01-25 22:02:23 +08:00
StartTime = 1000 ,
2021-09-26 23:41:20 +08:00
Position = new Vector2 ( 100 ) ,
} ;
AddStep ( "add one more hitobject" , ( ) = > EditorBeatmap . Add ( addedObject2 ) ) ;
AddAssert ( "selection unchanged" , ( ) = > EditorBeatmap . SelectedHitObjects . Single ( ) = = addedObject ) ;
moveMouseToObject ( ( ) = > addedObject2 ) ;
AddStep ( "left click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "hitobject selected" , ( ) = > EditorBeatmap . SelectedHitObjects . Single ( ) = = addedObject2 ) ;
}
[Test]
public void TestMultiSelect ( )
{
var addedObjects = new [ ]
{
2022-01-25 22:02:23 +08:00
new HitCircle { StartTime = 500 } ,
new HitCircle { StartTime = 1000 , Position = new Vector2 ( 100 ) } ,
new HitCircle { StartTime = 1500 , Position = new Vector2 ( 200 ) } ,
new HitCircle { StartTime = 2000 , Position = new Vector2 ( 300 ) } ,
2021-09-26 23:41:20 +08:00
} ;
AddStep ( "add hitobjects" , ( ) = > EditorBeatmap . AddRange ( addedObjects ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 0 ] ) ;
AddStep ( "click first" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "hitobject selected" , ( ) = > EditorBeatmap . SelectedHitObjects . Single ( ) = = addedObjects [ 0 ] ) ;
AddStep ( "hold control" , ( ) = > InputManager . PressKey ( Key . ControlLeft ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 1 ] ) ;
AddStep ( "click second" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "2 hitobjects selected" , ( ) = > EditorBeatmap . SelectedHitObjects . Count = = 2 & & EditorBeatmap . SelectedHitObjects . Contains ( addedObjects [ 1 ] ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 2 ] ) ;
AddStep ( "click third" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "3 hitobjects selected" , ( ) = > EditorBeatmap . SelectedHitObjects . Count = = 3 & & EditorBeatmap . SelectedHitObjects . Contains ( addedObjects [ 2 ] ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 1 ] ) ;
AddStep ( "click second" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "2 hitobjects selected" , ( ) = > EditorBeatmap . SelectedHitObjects . Count = = 2 & & ! EditorBeatmap . SelectedHitObjects . Contains ( addedObjects [ 1 ] ) ) ;
AddStep ( "release control" , ( ) = > InputManager . ReleaseKey ( Key . ControlLeft ) ) ;
}
[Test]
public void TestBasicDeselect ( )
{
2022-01-25 22:02:23 +08:00
var addedObject = new HitCircle { StartTime = 500 } ;
2021-09-26 23:41:20 +08:00
AddStep ( "add hitobject" , ( ) = > EditorBeatmap . Add ( addedObject ) ) ;
moveMouseToObject ( ( ) = > addedObject ) ;
AddStep ( "left click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "hitobject selected" , ( ) = > EditorBeatmap . SelectedHitObjects . Single ( ) = = addedObject ) ;
AddStep ( "click away" , ( ) = >
{
2023-10-30 16:55:21 +08:00
InputManager . MoveMouseTo ( Editor . ChildrenOfType < Timeline > ( ) . First ( ) . ScreenSpaceDrawQuad . TopLeft + new Vector2 ( 5 ) ) ;
2021-09-26 23:41:20 +08:00
InputManager . Click ( MouseButton . Left ) ;
} ) ;
AddAssert ( "selection lost" , ( ) = > EditorBeatmap . SelectedHitObjects . Count = = 0 ) ;
}
[Test]
public void TestQuickDelete ( )
{
var addedObject = new HitCircle
{
StartTime = 0 ,
} ;
AddStep ( "add hitobject" , ( ) = > EditorBeatmap . Add ( addedObject ) ) ;
moveMouseToObject ( ( ) = > addedObject ) ;
AddStep ( "hold shift" , ( ) = > InputManager . PressKey ( Key . ShiftLeft ) ) ;
AddStep ( "right click" , ( ) = > InputManager . Click ( MouseButton . Right ) ) ;
AddStep ( "release shift" , ( ) = > InputManager . ReleaseKey ( Key . ShiftLeft ) ) ;
AddAssert ( "no hitobjects in beatmap" , ( ) = > EditorBeatmap . HitObjects . Count = = 0 ) ;
}
2021-09-26 23:45:47 +08:00
[Test]
public void TestRangeSelect ( )
{
var addedObjects = new [ ]
{
2022-01-25 22:02:23 +08:00
new HitCircle { StartTime = 500 } ,
new HitCircle { StartTime = 1000 , Position = new Vector2 ( 100 ) } ,
new HitCircle { StartTime = 1500 , Position = new Vector2 ( 200 ) } ,
new HitCircle { StartTime = 2000 , Position = new Vector2 ( 300 ) } ,
new HitCircle { StartTime = 2500 , Position = new Vector2 ( 400 ) } ,
2021-09-26 23:45:47 +08:00
} ;
AddStep ( "add hitobjects" , ( ) = > EditorBeatmap . AddRange ( addedObjects ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 1 ] ) ;
AddStep ( "click second" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "hitobject selected" , ( ) = > EditorBeatmap . SelectedHitObjects . Single ( ) = = addedObjects [ 1 ] ) ;
AddStep ( "hold shift" , ( ) = > InputManager . PressKey ( Key . ShiftLeft ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 3 ] ) ;
AddStep ( "click fourth" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Skip ( 1 ) . Take ( 3 ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 0 ] ) ;
AddStep ( "click first" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Take ( 2 ) ) ;
AddStep ( "clear selection" , ( ) = > EditorBeatmap . SelectedHitObjects . Clear ( ) ) ;
AddStep ( "release shift" , ( ) = > InputManager . ReleaseKey ( Key . ShiftLeft ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 0 ] ) ;
AddStep ( "click first" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Take ( 1 ) ) ;
AddStep ( "hold ctrl" , ( ) = > InputManager . PressKey ( Key . ControlLeft ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 2 ] ) ;
AddStep ( "click third" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( new [ ] { addedObjects [ 0 ] , addedObjects [ 2 ] } ) ;
AddStep ( "hold shift" , ( ) = > InputManager . PressKey ( Key . ShiftLeft ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 4 ] ) ;
AddStep ( "click fifth" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Except ( new [ ] { addedObjects [ 1 ] } ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 0 ] ) ;
AddStep ( "click first" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects ) ;
AddStep ( "clear selection" , ( ) = > EditorBeatmap . SelectedHitObjects . Clear ( ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 0 ] ) ;
AddStep ( "click first" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Take ( 1 ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 1 ] ) ;
AddStep ( "click first" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Take ( 2 ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 2 ] ) ;
AddStep ( "click first" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Take ( 3 ) ) ;
2021-09-28 02:43:08 +08:00
AddStep ( "release keys" , ( ) = >
{
InputManager . ReleaseKey ( Key . ControlLeft ) ;
InputManager . ReleaseKey ( Key . ShiftLeft ) ;
} ) ;
}
[Test]
public void TestRangeSelectAfterExternalSelection ( )
{
var addedObjects = new [ ]
{
2022-01-25 22:02:23 +08:00
new HitCircle { StartTime = 500 } ,
new HitCircle { StartTime = 1000 , Position = new Vector2 ( 100 ) } ,
new HitCircle { StartTime = 1500 , Position = new Vector2 ( 200 ) } ,
new HitCircle { StartTime = 2000 , Position = new Vector2 ( 300 ) } ,
2021-09-28 02:43:08 +08:00
} ;
AddStep ( "add hitobjects" , ( ) = > EditorBeatmap . AddRange ( addedObjects ) ) ;
AddStep ( "select all without mouse" , ( ) = > EditorBeatmap . SelectedHitObjects . AddRange ( EditorBeatmap . HitObjects ) ) ;
assertSelectionIs ( addedObjects ) ;
AddStep ( "hold down shift" , ( ) = > InputManager . PressKey ( Key . ShiftLeft ) ) ;
moveMouseToObject ( ( ) = > addedObjects [ 1 ] ) ;
AddStep ( "click second object" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects ) ;
moveMouseToObject ( ( ) = > addedObjects [ 3 ] ) ;
AddStep ( "click fourth object" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Skip ( 1 ) ) ;
AddStep ( "release shift" , ( ) = > InputManager . ReleaseKey ( Key . ShiftLeft ) ) ;
2021-09-26 23:45:47 +08:00
}
2022-10-05 22:29:45 +08:00
[Test]
public void TestBasicDragSelection ( )
{
var addedObjects = new [ ]
{
new HitCircle { StartTime = 0 } ,
new HitCircle { StartTime = 500 , Position = new Vector2 ( 100 ) } ,
new HitCircle { StartTime = 1000 , Position = new Vector2 ( 200 ) } ,
new HitCircle { StartTime = 1500 , Position = new Vector2 ( 300 ) } ,
} ;
AddStep ( "add hitobjects" , ( ) = > EditorBeatmap . AddRange ( addedObjects ) ) ;
AddStep ( "move mouse" , ( ) = > InputManager . MoveMouseTo ( getMiddlePosition ( addedObjects [ 0 ] , addedObjects [ 1 ] ) ) ) ;
AddStep ( "mouse down" , ( ) = > InputManager . PressButton ( MouseButton . Left ) ) ;
AddStep ( "drag to select" , ( ) = > InputManager . MoveMouseTo ( getMiddlePosition ( addedObjects [ 2 ] , addedObjects [ 3 ] ) ) ) ;
assertSelectionIs ( new [ ] { addedObjects [ 1 ] , addedObjects [ 2 ] } ) ;
AddStep ( "drag to deselect" , ( ) = > InputManager . MoveMouseTo ( getMiddlePosition ( addedObjects [ 1 ] , addedObjects [ 2 ] ) ) ) ;
assertSelectionIs ( new [ ] { addedObjects [ 1 ] } ) ;
AddStep ( "mouse up" , ( ) = > InputManager . ReleaseButton ( MouseButton . Left ) ) ;
assertSelectionIs ( new [ ] { addedObjects [ 1 ] } ) ;
}
[Test]
public void TestFastDragSelection ( )
{
var addedObjects = new [ ]
{
new HitCircle { StartTime = 0 } ,
new HitCircle { StartTime = 500 } ,
new HitCircle { StartTime = 20000 , Position = new Vector2 ( 100 ) } ,
new HitCircle { StartTime = 31000 , Position = new Vector2 ( 200 ) } ,
new HitCircle { StartTime = 60000 , Position = new Vector2 ( 300 ) } ,
} ;
AddStep ( "add hitobjects" , ( ) = > EditorBeatmap . AddRange ( addedObjects ) ) ;
AddStep ( "move mouse" , ( ) = > InputManager . MoveMouseTo ( getMiddlePosition ( addedObjects [ 0 ] , addedObjects [ 1 ] ) ) ) ;
AddStep ( "mouse down" , ( ) = > InputManager . PressButton ( MouseButton . Left ) ) ;
AddStep ( "start drag" , ( ) = > InputManager . MoveMouseTo ( getPosition ( addedObjects [ 1 ] ) ) ) ;
AddStep ( "jump editor clock" , ( ) = > EditorClock . Seek ( 30000 ) ) ;
AddStep ( "jump editor clock" , ( ) = > EditorClock . Seek ( 60000 ) ) ;
AddStep ( "end drag" , ( ) = > InputManager . ReleaseButton ( MouseButton . Left ) ) ;
assertSelectionIs ( addedObjects . Skip ( 1 ) ) ;
2022-10-06 13:02:49 +08:00
AddAssert ( "all blueprints are present" , ( ) = > blueprintContainer . SelectionBlueprints . Count = = EditorBeatmap . SelectedHitObjects . Count ) ;
2022-10-05 22:29:45 +08:00
}
2024-06-14 15:08:25 +08:00
[Test]
public void TestDragSelectionDuringPlacement ( )
{
var addedObjects = new [ ]
{
new Slider
{
StartTime = 300 ,
Path = new SliderPath ( [
new PathControlPoint ( ) ,
new PathControlPoint ( new Vector2 ( 200 ) ) ,
] )
} ,
} ;
AddStep ( "add hitobjects" , ( ) = > EditorBeatmap . AddRange ( addedObjects ) ) ;
AddStep ( "seek to 700" , ( ) = > EditorClock . Seek ( 700 ) ) ;
AddStep ( "select spinner placement tool" , ( ) = >
{
InputManager . Key ( Key . Number4 ) ;
InputManager . MoveMouseTo ( this . ChildrenOfType < OsuHitObjectComposer > ( ) . Single ( ) ) ;
} ) ;
AddStep ( "begin spinner placement" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddStep ( "seek to 1500" , ( ) = > EditorClock . Seek ( 1500 ) ) ;
AddStep ( "start dragging" , ( ) = >
{
var blueprintQuad = blueprintContainer . SelectionBlueprints [ 1 ] . ScreenSpaceDrawQuad ;
var dragStartPos = ( blueprintQuad . TopLeft + blueprintQuad . BottomLeft ) / 2 - new Vector2 ( 30 , 0 ) ;
InputManager . MoveMouseTo ( dragStartPos ) ;
InputManager . PressButton ( MouseButton . Left ) ;
} ) ;
AddStep ( "select entire object" , ( ) = >
{
var blueprintQuad = blueprintContainer . SelectionBlueprints [ 1 ] . ScreenSpaceDrawQuad ;
var dragStartPos = ( blueprintQuad . TopRight + blueprintQuad . BottomRight ) / 2 + new Vector2 ( 30 , 0 ) ;
InputManager . MoveMouseTo ( dragStartPos ) ;
} ) ;
AddStep ( "end drag" , ( ) = > InputManager . ReleaseButton ( MouseButton . Left ) ) ;
AddUntilStep ( "hitobject selected" , ( ) = > EditorBeatmap . SelectedHitObjects , ( ) = > NUnit . Framework . Contains . Item ( addedObjects [ 0 ] ) ) ;
AddAssert ( "placement committed" , ( ) = > EditorBeatmap . HitObjects , ( ) = > Has . Count . EqualTo ( 2 ) ) ;
}
2024-07-02 21:02:09 +08:00
[Test]
public void TestBreakRemoval ( )
{
var addedObjects = new [ ]
{
new HitCircle { StartTime = 0 } ,
new HitCircle { StartTime = 5000 } ,
} ;
AddStep ( "add hitobjects" , ( ) = > EditorBeatmap . AddRange ( addedObjects ) ) ;
AddAssert ( "beatmap has one break" , ( ) = > EditorBeatmap . Breaks , ( ) = > Has . Count . EqualTo ( 1 ) ) ;
AddStep ( "move mouse to break" , ( ) = > InputManager . MoveMouseTo ( this . ChildrenOfType < TimelineBreak > ( ) . Single ( ) ) ) ;
AddStep ( "right click" , ( ) = > InputManager . Click ( MouseButton . Right ) ) ;
AddStep ( "move mouse to delete menu item" , ( ) = > InputManager . MoveMouseTo ( this . ChildrenOfType < OsuContextMenu > ( ) . First ( ) . ChildrenOfType < DrawableOsuMenuItem > ( ) . First ( ) ) ) ;
AddStep ( "click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "beatmap has no breaks" , ( ) = > EditorBeatmap . Breaks , ( ) = > Is . Empty ) ;
AddAssert ( "break piece went away" , ( ) = > this . ChildrenOfType < TimelineBreak > ( ) . Count ( ) , ( ) = > Is . Zero ) ;
}
2021-09-26 23:45:47 +08:00
private void assertSelectionIs ( IEnumerable < HitObject > hitObjects )
= > AddAssert ( "correct hitobjects selected" , ( ) = > EditorBeatmap . SelectedHitObjects . OrderBy ( h = > h . StartTime ) . SequenceEqual ( hitObjects ) ) ;
2021-09-26 23:41:20 +08:00
}
}