2020-02-14 14:01:45 +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-12-09 00:16:37 +08:00
using System ;
2020-02-14 14:36:47 +08:00
using System.Collections.Generic ;
2021-11-01 14:42:12 +08:00
using System.Diagnostics ;
2020-02-14 14:01:45 +08:00
using System.Linq ;
using NUnit.Framework ;
2020-06-02 13:31:43 +08:00
using osu.Framework.Allocation ;
using osu.Framework.Audio ;
2020-02-14 14:01:45 +08:00
using osu.Framework.Graphics ;
2020-02-14 15:48:30 +08:00
using osu.Framework.Graphics.Containers ;
2020-06-02 13:31:43 +08:00
using osu.Framework.Platform ;
2020-02-14 15:48:30 +08:00
using osu.Framework.Testing ;
2020-06-02 13:31:43 +08:00
using osu.Game.Beatmaps ;
2021-02-02 16:21:46 +08:00
using osu.Game.Beatmaps.Drawables ;
2024-05-27 18:01:02 +08:00
using osu.Game.Beatmaps.Drawables.Cards ;
2021-11-25 22:15:28 +08:00
using osu.Game.Database ;
2020-02-14 15:48:30 +08:00
using osu.Game.Graphics.Containers ;
2022-07-14 07:45:38 +08:00
using osu.Game.Graphics.Cursor ;
2024-01-15 21:58:46 +08:00
using osu.Game.Graphics.UserInterface ;
2021-11-22 14:52:55 +08:00
using osu.Game.Models ;
2022-02-15 15:01:14 +08:00
using osu.Game.Online.API ;
2024-01-15 21:58:46 +08:00
using osu.Game.Online.Chat ;
2020-12-25 12:38:11 +08:00
using osu.Game.Online.Rooms ;
2020-06-02 13:31:43 +08:00
using osu.Game.Rulesets ;
2020-02-14 16:57:25 +08:00
using osu.Game.Rulesets.Osu ;
2020-02-14 14:01:45 +08:00
using osu.Game.Rulesets.Osu.Mods ;
2020-12-25 23:50:00 +08:00
using osu.Game.Screens.OnlinePlay ;
2020-02-14 16:57:25 +08:00
using osu.Game.Tests.Beatmaps ;
2021-11-26 16:40:45 +08:00
using osu.Game.Users.Drawables ;
2020-02-14 14:01:45 +08:00
using osuTK ;
2020-02-14 15:48:30 +08:00
using osuTK.Input ;
2020-02-14 14:01:45 +08:00
namespace osu.Game.Tests.Visual.Multiplayer
{
2022-02-15 20:08:27 +08:00
public partial class TestSceneDrawableRoomPlaylist : MultiplayerTestScene
2020-02-14 14:01:45 +08:00
{
2020-02-20 07:37:23 +08:00
private TestPlaylist playlist ;
2020-02-14 14:01:45 +08:00
2020-06-02 13:31:43 +08:00
private BeatmapManager manager ;
[BackgroundDependencyLoader]
private void load ( GameHost host , AudioManager audio )
{
2022-07-28 15:19:05 +08:00
Dependencies . Cache ( new RealmRulesetStore ( Realm ) ) ;
Dependencies . Cache ( manager = new BeatmapManager ( LocalStorage , Realm , null , audio , Resources , host , Beatmap . Default ) ) ;
2022-01-25 11:58:15 +08:00
Dependencies . Cache ( Realm ) ;
2020-06-02 13:31:43 +08:00
}
2020-02-14 14:01:45 +08:00
[Test]
2020-02-14 14:36:47 +08:00
public void TestNonEditableNonSelectable ( )
2020-02-14 14:01:45 +08:00
{
2021-12-09 00:16:37 +08:00
createPlaylist ( ) ;
2020-02-14 15:48:30 +08:00
moveToItem ( 0 ) ;
assertHandleVisibility ( 0 , false ) ;
assertDeleteButtonVisibility ( 0 , false ) ;
2020-02-14 15:55:05 +08:00
AddStep ( "click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "no item selected" , ( ) = > playlist . SelectedItem . Value = = null ) ;
2022-05-05 10:42:49 +08:00
AddStep ( "press down" , ( ) = > InputManager . Key ( Key . Down ) ) ;
AddAssert ( "no item selected" , ( ) = > playlist . SelectedItem . Value = = null ) ;
2020-02-14 14:01:45 +08:00
}
[Test]
2020-02-14 14:36:47 +08:00
public void TestEditable ( )
2020-02-14 14:01:45 +08:00
{
2021-12-09 16:48:09 +08:00
createPlaylist ( p = >
{
p . AllowReordering = true ;
p . AllowDeletion = true ;
} ) ;
2020-02-14 15:48:30 +08:00
moveToItem ( 0 ) ;
assertHandleVisibility ( 0 , true ) ;
assertDeleteButtonVisibility ( 0 , true ) ;
2020-02-14 15:55:05 +08:00
AddStep ( "click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "no item selected" , ( ) = > playlist . SelectedItem . Value = = null ) ;
2022-05-05 10:42:49 +08:00
AddStep ( "press down" , ( ) = > InputManager . Key ( Key . Down ) ) ;
AddAssert ( "no item selected" , ( ) = > playlist . SelectedItem . Value = = null ) ;
2020-02-14 14:01:45 +08:00
}
2021-11-16 16:08:21 +08:00
[Test]
public void TestMarkInvalid ( )
{
2021-12-09 16:48:09 +08:00
createPlaylist ( p = >
{
p . AllowReordering = true ;
p . AllowDeletion = true ;
p . AllowSelection = true ;
} ) ;
2021-11-16 16:08:21 +08:00
AddStep ( "mark item 0 as invalid" , ( ) = > playlist . Items [ 0 ] . MarkInvalid ( ) ) ;
moveToItem ( 0 ) ;
2020-02-14 15:55:05 +08:00
AddStep ( "click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "no item selected" , ( ) = > playlist . SelectedItem . Value = = null ) ;
2022-05-05 10:42:49 +08:00
AddStep ( "press down" , ( ) = > InputManager . Key ( Key . Down ) ) ;
AddAssert ( "no item selected" , ( ) = > playlist . SelectedItem . Value = = null ) ;
2020-02-14 14:01:45 +08:00
}
[Test]
2020-02-14 14:36:47 +08:00
public void TestSelectable ( )
2020-02-14 14:01:45 +08:00
{
2021-12-09 00:16:37 +08:00
createPlaylist ( p = > p . AllowSelection = true ) ;
2020-02-14 15:48:30 +08:00
moveToItem ( 0 ) ;
assertHandleVisibility ( 0 , false ) ;
assertDeleteButtonVisibility ( 0 , false ) ;
AddStep ( "click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "item 0 is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items [ 0 ] ) ;
2020-02-14 14:01:45 +08:00
}
[Test]
2020-02-14 14:36:47 +08:00
public void TestEditableSelectable ( )
2020-02-14 14:01:45 +08:00
{
2021-12-09 16:48:09 +08:00
createPlaylist ( p = >
{
p . AllowReordering = true ;
p . AllowDeletion = true ;
p . AllowSelection = true ;
} ) ;
2020-02-14 15:48:30 +08:00
moveToItem ( 0 ) ;
assertHandleVisibility ( 0 , true ) ;
assertDeleteButtonVisibility ( 0 , true ) ;
AddStep ( "click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddAssert ( "item 0 is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items [ 0 ] ) ;
}
[Test]
public void TestSelectionNotLostAfterRearrangement ( )
{
2021-12-09 16:48:09 +08:00
createPlaylist ( p = >
{
p . AllowReordering = true ;
p . AllowDeletion = true ;
p . AllowSelection = true ;
} ) ;
2020-02-14 15:48:30 +08:00
moveToItem ( 0 ) ;
AddStep ( "click" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
moveToDragger ( 0 ) ;
AddStep ( "begin drag" , ( ) = > InputManager . PressButton ( MouseButton . Left ) ) ;
moveToDragger ( 1 , new Vector2 ( 0 , 5 ) ) ;
AddStep ( "end drag" , ( ) = > InputManager . ReleaseButton ( MouseButton . Left ) ) ;
AddAssert ( "item 1 is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items [ 1 ] ) ;
}
2022-05-04 19:12:21 +08:00
[Test]
2022-05-05 11:12:24 +08:00
public void TestKeyboardSelection ( )
2022-05-04 19:12:21 +08:00
{
createPlaylist ( p = > p . AllowSelection = true ) ;
AddStep ( "press down" , ( ) = > InputManager . Key ( Key . Down ) ) ;
AddAssert ( "item 0 is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items [ 0 ] ) ;
AddStep ( "press down" , ( ) = > InputManager . Key ( Key . Down ) ) ;
AddAssert ( "item 1 is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items [ 1 ] ) ;
AddStep ( "press up" , ( ) = > InputManager . Key ( Key . Up ) ) ;
AddAssert ( "item 0 is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items [ 0 ] ) ;
AddUntilStep ( "navigate to last item via keyboard" , ( ) = >
{
InputManager . Key ( Key . Down ) ;
return playlist . SelectedItem . Value = = playlist . Items . Last ( ) ;
} ) ;
AddAssert ( "last item is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items . Last ( ) ) ;
AddUntilStep ( "last item is scrolled into view" , ( ) = >
{
var drawableItem = playlist . ItemMap [ playlist . Items . Last ( ) ] ;
return playlist . ScreenSpaceDrawQuad . Contains ( drawableItem . ScreenSpaceDrawQuad . TopLeft )
& & playlist . ScreenSpaceDrawQuad . Contains ( drawableItem . ScreenSpaceDrawQuad . BottomRight ) ;
} ) ;
AddStep ( "press down" , ( ) = > InputManager . Key ( Key . Down ) ) ;
AddAssert ( "last item is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items . Last ( ) ) ;
AddStep ( "press up" , ( ) = > InputManager . Key ( Key . Up ) ) ;
AddAssert ( "second last item is selected" , ( ) = > playlist . SelectedItem . Value = = playlist . Items . Reverse ( ) . ElementAt ( 1 ) ) ;
}
2020-06-02 13:31:43 +08:00
[Test]
2021-01-18 00:17:14 +08:00
public void TestDownloadButtonHiddenWhenBeatmapExists ( )
2020-06-02 13:31:43 +08:00
{
2022-01-26 12:37:33 +08:00
Live < BeatmapSetInfo > imported = null ;
2021-10-28 16:10:04 +08:00
2022-07-14 08:12:48 +08:00
AddStep ( "import beatmap" , ( ) = >
{
var beatmap = new TestBeatmap ( new OsuRuleset ( ) . RulesetInfo ) . BeatmapInfo ;
2021-12-17 17:26:12 +08:00
2022-07-14 08:12:48 +08:00
Debug . Assert ( beatmap . BeatmapSet ! = null ) ;
imported = manager . Import ( beatmap . BeatmapSet ) ;
} ) ;
2021-10-28 16:10:04 +08:00
2022-01-11 14:55:13 +08:00
createPlaylistWithBeatmaps ( ( ) = > imported . PerformRead ( s = > s . Beatmaps . Detach ( ) ) ) ;
2020-06-02 13:31:43 +08:00
2021-01-18 01:08:58 +08:00
assertDownloadButtonVisible ( false ) ;
2021-01-18 00:17:14 +08:00
2022-01-11 14:55:13 +08:00
AddStep ( "delete beatmap set" , ( ) = > imported . PerformWrite ( s = > s . DeletePending = true ) ) ;
2021-01-18 01:08:58 +08:00
assertDownloadButtonVisible ( true ) ;
2021-01-18 00:17:14 +08:00
2022-01-11 14:55:13 +08:00
AddStep ( "undelete beatmap set" , ( ) = > imported . PerformWrite ( s = > s . DeletePending = false ) ) ;
2021-01-18 01:08:58 +08:00
assertDownloadButtonVisible ( false ) ;
void assertDownloadButtonVisible ( bool visible ) = > AddUntilStep ( $"download button {(visible ? " shown " : " hidden ")}" ,
2022-02-15 22:51:44 +08:00
( ) = > playlist . ChildrenOfType < BeatmapDownloadButton > ( ) . SingleOrDefault ( ) ? . Alpha = = ( visible ? 1 : 0 ) ) ;
2020-06-02 13:31:43 +08:00
}
[Test]
public void TestDownloadButtonVisibleInitiallyWhenBeatmapDoesNotExist ( )
{
2021-11-01 14:42:12 +08:00
var byOnlineId = CreateAPIBeatmap ( ) ;
2021-11-01 15:43:39 +08:00
byOnlineId . OnlineID = 1337 ; // Some random ID that does not exist locally.
2020-06-02 13:31:43 +08:00
2021-11-01 14:42:12 +08:00
var byChecksum = CreateAPIBeatmap ( ) ;
byChecksum . Checksum = "1337" ; // Some random checksum that does not exist locally.
2020-06-02 13:31:43 +08:00
2022-01-11 14:55:13 +08:00
createPlaylistWithBeatmaps ( ( ) = > new [ ] { byOnlineId , byChecksum } ) ;
2020-06-02 13:31:43 +08:00
2021-11-27 22:08:03 +08:00
AddAssert ( "download buttons shown" , ( ) = > playlist . ChildrenOfType < BeatmapDownloadButton > ( ) . All ( d = > d . IsPresent ) ) ;
2020-06-02 13:31:43 +08:00
}
2021-01-13 16:57:29 +08:00
[Test]
public void TestExplicitBeatmapItem ( )
{
2021-11-01 14:42:12 +08:00
var beatmap = CreateAPIBeatmap ( ) ;
2021-11-01 15:43:39 +08:00
2021-11-01 14:42:12 +08:00
Debug . Assert ( beatmap . BeatmapSet ! = null ) ;
beatmap . BeatmapSet . HasExplicitContent = true ;
2021-01-13 16:57:29 +08:00
2022-01-11 14:55:13 +08:00
createPlaylistWithBeatmaps ( ( ) = > new [ ] { beatmap } ) ;
2021-01-13 16:57:29 +08:00
}
2021-10-22 20:04:52 +08:00
[Test]
public void TestExpiredItems ( )
{
2022-07-14 07:19:23 +08:00
createPlaylist ( p = >
2021-10-22 20:04:52 +08:00
{
2022-07-14 07:19:23 +08:00
p . Items . Clear ( ) ;
p . Items . AddRange ( new [ ]
2021-10-22 20:04:52 +08:00
{
2022-07-14 07:19:23 +08:00
new PlaylistItem ( new TestBeatmap ( new OsuRuleset ( ) . RulesetInfo ) . BeatmapInfo )
2021-10-22 20:04:52 +08:00
{
2022-07-14 07:19:23 +08:00
ID = 0 ,
RulesetID = new OsuRuleset ( ) . RulesetInfo . OnlineID ,
Expired = true ,
RequiredMods = new [ ]
2021-10-22 20:04:52 +08:00
{
2022-07-14 07:19:23 +08:00
new APIMod ( new OsuModHardRock ( ) ) ,
new APIMod ( new OsuModDoubleTime ( ) ) ,
new APIMod ( new OsuModAutoplay ( ) )
}
} ,
new PlaylistItem ( new TestBeatmap ( new OsuRuleset ( ) . RulesetInfo ) . BeatmapInfo )
{
ID = 1 ,
RulesetID = new OsuRuleset ( ) . RulesetInfo . OnlineID ,
RequiredMods = new [ ]
2021-10-22 20:04:52 +08:00
{
2022-07-14 07:19:23 +08:00
new APIMod ( new OsuModHardRock ( ) ) ,
new APIMod ( new OsuModDoubleTime ( ) ) ,
new APIMod ( new OsuModAutoplay ( ) )
2021-10-22 20:04:52 +08:00
}
}
2022-07-14 07:19:23 +08:00
} ) ;
2021-10-22 20:04:52 +08:00
} ) ;
AddUntilStep ( "wait for items to load" , ( ) = > playlist . ItemMap . Values . All ( i = > i . IsLoaded ) ) ;
}
2021-11-26 16:40:45 +08:00
[TestCase(false)]
[TestCase(true)]
public void TestWithOwner ( bool withOwner )
{
2021-12-09 00:16:37 +08:00
createPlaylist ( p = > p . ShowItemOwners = withOwner ) ;
2021-11-26 16:40:45 +08:00
AddAssert ( "owner visible" , ( ) = > playlist . ChildrenOfType < UpdateableAvatar > ( ) . All ( a = > a . IsPresent = = withOwner ) ) ;
}
2021-12-09 22:46:03 +08:00
[Test]
public void TestWithAllButtonsEnabled ( )
{
createPlaylist ( p = >
{
p . AllowDeletion = true ;
p . AllowShowingResults = true ;
2021-12-10 00:08:54 +08:00
p . AllowEditing = true ;
2021-12-09 22:46:03 +08:00
} ) ;
}
2024-01-15 21:58:46 +08:00
[Test]
public void TestSelectableMouseHandling ( )
{
bool resultsRequested = false ;
AddStep ( "reset flag" , ( ) = > resultsRequested = false ) ;
createPlaylist ( p = >
{
p . AllowSelection = true ;
p . AllowShowingResults = true ;
p . RequestResults = _ = > resultsRequested = true ;
} ) ;
2024-05-27 18:01:02 +08:00
AddUntilStep ( "wait for load" , ( ) = > playlist . ChildrenOfType < DrawableLinkCompiler > ( ) . Any ( ) & & playlist . ChildrenOfType < BeatmapCardThumbnail > ( ) . First ( ) . DrawWidth > 0 ) ;
2024-01-15 21:58:46 +08:00
AddStep ( "move mouse to first item title" , ( ) = >
{
var drawQuad = playlist . ChildrenOfType < LinkFlowContainer > ( ) . First ( ) . ScreenSpaceDrawQuad ;
var location = ( drawQuad . TopLeft + drawQuad . BottomLeft ) / 2 + new Vector2 ( drawQuad . Width * 0.2f , 0 ) ;
InputManager . MoveMouseTo ( location ) ;
} ) ;
AddAssert ( "first item title not hovered" , ( ) = > playlist . ChildrenOfType < DrawableLinkCompiler > ( ) . First ( ) . IsHovered , ( ) = > Is . False ) ;
AddStep ( "click left mouse" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddUntilStep ( "first item selected" , ( ) = > playlist . ChildrenOfType < DrawableRoomPlaylistItem > ( ) . First ( ) . IsSelectedItem , ( ) = > Is . True ) ;
// implies being clickable.
AddUntilStep ( "first item title hovered" , ( ) = > playlist . ChildrenOfType < DrawableLinkCompiler > ( ) . First ( ) . IsHovered , ( ) = > Is . True ) ;
AddStep ( "move mouse to second item results button" , ( ) = > InputManager . MoveMouseTo ( playlist . ChildrenOfType < GrayButton > ( ) . ElementAt ( 5 ) ) ) ;
AddStep ( "click left mouse" , ( ) = > InputManager . Click ( MouseButton . Left ) ) ;
AddUntilStep ( "results requested" , ( ) = > resultsRequested ) ;
}
2020-02-14 15:48:30 +08:00
private void moveToItem ( int index , Vector2 ? offset = null )
2022-02-15 22:51:44 +08:00
= > AddStep ( $"move mouse to item {index}" , ( ) = > InputManager . MoveMouseTo ( playlist . ChildrenOfType < DrawableRoomPlaylistItem > ( ) . ElementAt ( index ) , offset ) ) ;
2020-02-14 15:48:30 +08:00
private void moveToDragger ( int index , Vector2 ? offset = null ) = > AddStep ( $"move mouse to dragger {index}" , ( ) = >
{
var item = playlist . ChildrenOfType < OsuRearrangeableListItem < PlaylistItem > > ( ) . ElementAt ( index ) ;
InputManager . MoveMouseTo ( item . ChildrenOfType < OsuRearrangeableListItem < PlaylistItem > . PlaylistItemHandle > ( ) . Single ( ) , offset ) ;
} ) ;
private void assertHandleVisibility ( int index , bool visible )
= > AddAssert ( $"handle {index} {(visible ? " is " : " is not ")} visible" ,
( ) = > ( playlist . ChildrenOfType < OsuRearrangeableListItem < PlaylistItem > . PlaylistItemHandle > ( ) . ElementAt ( index ) . Alpha > 0 ) = = visible ) ;
private void assertDeleteButtonVisibility ( int index , bool visible )
2021-10-22 20:04:52 +08:00
= > AddAssert ( $"delete button {index} {(visible ? " is " : " is not ")} visible" ,
2021-12-09 23:38:18 +08:00
( ) = > ( playlist . ChildrenOfType < DrawableRoomPlaylistItem . PlaylistRemoveButton > ( ) . ElementAt ( 2 + index * 2 ) . Alpha > 0 ) = = visible ) ;
2020-02-14 15:48:30 +08:00
2022-07-14 07:19:23 +08:00
private void createPlaylistWithBeatmaps ( Func < IEnumerable < IBeatmapInfo > > beatmaps ) = > createPlaylist ( p = >
{
int index = 0 ;
p . Items . Clear ( ) ;
foreach ( var b in beatmaps ( ) )
{
p . Items . Add ( new PlaylistItem ( b )
{
ID = index + + ,
OwnerID = 2 ,
RulesetID = new OsuRuleset ( ) . RulesetInfo . OnlineID ,
RequiredMods = new [ ]
{
new APIMod ( new OsuModHardRock ( ) ) ,
new APIMod ( new OsuModDoubleTime ( ) ) ,
new APIMod ( new OsuModAutoplay ( ) )
}
} ) ;
}
} ) ;
2021-12-09 03:20:23 +08:00
private void createPlaylist ( Action < TestPlaylist > setupPlaylist = null )
2020-02-14 14:01:45 +08:00
{
2020-02-20 07:37:23 +08:00
AddStep ( "create playlist" , ( ) = >
2020-02-14 14:01:45 +08:00
{
2022-07-15 08:19:50 +08:00
Child = new OsuContextMenuContainer
2020-02-20 07:37:23 +08:00
{
2022-07-14 07:45:38 +08:00
RelativeSizeAxes = Axes . Both ,
2022-07-15 08:19:50 +08:00
Child = playlist = new TestPlaylist
2022-07-14 07:45:38 +08:00
{
2022-07-15 08:19:50 +08:00
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
Size = new Vector2 ( 500 , 300 )
}
2020-02-20 07:37:23 +08:00
} ;
2020-02-14 14:01:45 +08:00
2020-02-20 07:37:23 +08:00
for ( int i = 0 ; i < 20 ; i + + )
2020-02-14 14:01:45 +08:00
{
2022-02-15 22:33:26 +08:00
playlist . Items . Add ( new PlaylistItem ( i % 2 = = 1
? new TestBeatmap ( new OsuRuleset ( ) . RulesetInfo ) . BeatmapInfo
: new BeatmapInfo
{
Metadata = new BeatmapMetadata
{
Artist = "Artist" ,
Author = new RealmUser { Username = "Creator name here" } ,
Title = "Long title used to check background colour" ,
} ,
BeatmapSet = new BeatmapSetInfo ( )
} )
2020-02-14 14:01:45 +08:00
{
2020-02-20 07:37:23 +08:00
ID = i ,
2021-11-25 22:15:28 +08:00
OwnerID = 2 ,
2022-02-15 15:01:14 +08:00
RulesetID = new OsuRuleset ( ) . RulesetInfo . OnlineID ,
RequiredMods = new [ ]
2020-02-20 07:37:23 +08:00
{
2022-02-15 15:01:14 +08:00
new APIMod ( new OsuModHardRock ( ) ) ,
new APIMod ( new OsuModDoubleTime ( ) ) ,
new APIMod ( new OsuModAutoplay ( ) )
2020-02-20 07:37:23 +08:00
}
} ) ;
}
2020-06-02 13:31:43 +08:00
2022-07-14 07:19:23 +08:00
setupPlaylist ? . Invoke ( playlist ) ;
2020-06-02 13:31:43 +08:00
} ) ;
AddUntilStep ( "wait for items to load" , ( ) = > playlist . ItemMap . Values . All ( i = > i . IsLoaded ) ) ;
}
2020-02-20 07:37:23 +08:00
private partial class TestPlaylist : DrawableRoomPlaylist
{
public new IReadOnlyDictionary < PlaylistItem , RearrangeableListItem < PlaylistItem > > ItemMap = > base . ItemMap ;
}
2020-02-14 14:01:45 +08:00
}
}