2019-01-24 16:43:03 +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.
2018-04-13 17:19:50 +08:00
2018-05-11 20:40:48 +08:00
using System ;
2018-04-13 17:19:50 +08:00
using System.Collections.Generic ;
2019-03-25 00:02:36 +08:00
using System.Linq ;
2018-08-07 15:45:18 +08:00
using NUnit.Framework ;
2019-03-25 00:02:36 +08:00
using osu.Framework.Allocation ;
2019-02-21 18:04:31 +08:00
using osu.Framework.Bindables ;
2019-03-25 00:02:36 +08:00
using osu.Framework.Graphics ;
2019-12-13 19:21:35 +08:00
using osu.Framework.Testing ;
2018-04-13 17:19:50 +08:00
using osu.Game.Graphics.Sprites ;
2019-03-25 00:02:36 +08:00
using osu.Game.Graphics.UserInterface ;
using osu.Game.Overlays.Mods ;
using osu.Game.Rulesets ;
2020-07-15 18:45:48 +08:00
using osu.Game.Rulesets.Mania ;
using osu.Game.Rulesets.Mania.Mods ;
2019-03-25 00:02:36 +08:00
using osu.Game.Rulesets.Mods ;
2019-12-13 19:21:35 +08:00
using osu.Game.Rulesets.Osu ;
2019-03-25 00:02:36 +08:00
using osu.Game.Rulesets.Osu.Mods ;
using osu.Game.Screens.Play.HUD ;
using osuTK ;
2018-11-20 15:51:59 +08:00
using osuTK.Graphics ;
2018-04-13 17:19:50 +08:00
2019-03-25 00:02:36 +08:00
namespace osu.Game.Tests.Visual.UserInterface
2018-04-13 17:19:50 +08:00
{
[Description("mod select and icon display")]
2019-06-20 00:40:58 +08:00
public class TestSceneModSelectOverlay : OsuTestScene
2018-04-13 17:19:50 +08:00
{
private RulesetStore rulesets ;
private ModDisplay modDisplay ;
private TestModSelectOverlay modSelect ;
[BackgroundDependencyLoader]
private void load ( RulesetStore rulesets )
{
this . rulesets = rulesets ;
2019-12-13 19:21:35 +08:00
}
2018-04-13 17:19:50 +08:00
2019-12-13 19:21:35 +08:00
[SetUp]
public void SetUp ( ) = > Schedule ( ( ) = >
{
Children = new Drawable [ ]
2018-04-13 17:19:50 +08:00
{
2019-12-13 19:21:35 +08:00
modSelect = new TestModSelectOverlay
{
Origin = Anchor . BottomCentre ,
Anchor = Anchor . BottomCentre ,
2020-01-30 18:55:25 +08:00
SelectedMods = { BindTarget = SelectedMods }
2019-12-13 19:21:35 +08:00
} ,
modDisplay = new ModDisplay
{
Anchor = Anchor . TopRight ,
Origin = Anchor . TopRight ,
AutoSizeAxes = Axes . Both ,
2020-04-04 02:30:02 +08:00
Position = new Vector2 ( - 5 , 25 ) ,
2019-12-13 19:21:35 +08:00
Current = { BindTarget = modSelect . SelectedMods }
}
} ;
} ) ;
[SetUpSteps]
public void SetUpSteps ( )
{
AddStep ( "show" , ( ) = > modSelect . Show ( ) ) ;
2018-04-13 17:19:50 +08:00
}
2018-08-07 15:45:18 +08:00
[Test]
public void TestOsuMods ( )
2018-04-13 17:19:50 +08:00
{
2019-12-13 19:21:35 +08:00
changeRuleset ( 0 ) ;
2018-08-07 15:45:18 +08:00
2019-12-13 19:21:35 +08:00
var osu = new OsuRuleset ( ) ;
2018-08-07 15:45:18 +08:00
2019-12-13 19:21:35 +08:00
var easierMods = osu . GetModsFor ( ModType . DifficultyReduction ) ;
var harderMods = osu . GetModsFor ( ModType . DifficultyIncrease ) ;
2020-02-08 12:08:44 +08:00
var conversionMods = osu . GetModsFor ( ModType . Conversion ) ;
2018-04-13 17:19:50 +08:00
2019-12-13 19:21:35 +08:00
var noFailMod = osu . GetModsFor ( ModType . DifficultyReduction ) . FirstOrDefault ( m = > m is OsuModNoFail ) ;
2018-04-13 17:19:50 +08:00
var hiddenMod = harderMods . FirstOrDefault ( m = > m is OsuModHidden ) ;
var doubleTimeMod = harderMods . OfType < MultiMod > ( ) . FirstOrDefault ( m = > m . Mods . Any ( a = > a is OsuModDoubleTime ) ) ;
2020-02-08 12:08:44 +08:00
var targetMod = conversionMods . FirstOrDefault ( m = > m is OsuModTarget ) ;
2018-04-13 17:19:50 +08:00
var easy = easierMods . FirstOrDefault ( m = > m is OsuModEasy ) ;
var hardRock = harderMods . FirstOrDefault ( m = > m is OsuModHardRock ) ;
testSingleMod ( noFailMod ) ;
testMultiMod ( doubleTimeMod ) ;
testIncompatibleMods ( easy , hardRock ) ;
testDeselectAll ( easierMods . Where ( m = > ! ( m is MultiMod ) ) ) ;
2019-12-13 19:21:35 +08:00
testMultiplierTextColour ( noFailMod , ( ) = > modSelect . LowMultiplierColour ) ;
testMultiplierTextColour ( hiddenMod , ( ) = > modSelect . HighMultiplierColour ) ;
2018-04-13 17:19:50 +08:00
2020-02-08 12:07:21 +08:00
testUnimplementedMod ( targetMod ) ;
2018-04-13 17:19:50 +08:00
}
2018-08-07 15:45:18 +08:00
[Test]
public void TestManiaMods ( )
2018-04-13 17:19:50 +08:00
{
2019-12-13 19:21:35 +08:00
changeRuleset ( 3 ) ;
2020-07-15 18:45:48 +08:00
var mania = new ManiaRuleset ( ) ;
testModsWithSameBaseType (
mania . GetAllMods ( ) . Single ( m = > m . GetType ( ) = = typeof ( ManiaModFadeIn ) ) ,
mania . GetAllMods ( ) . Single ( m = > m . GetType ( ) = = typeof ( ManiaModHidden ) ) ) ;
2018-08-07 15:45:18 +08:00
}
[Test]
public void TestRulesetChanges ( )
{
2019-12-13 19:21:35 +08:00
changeRuleset ( 0 ) ;
2018-08-07 15:45:18 +08:00
2019-12-13 19:21:35 +08:00
var noFailMod = new OsuRuleset ( ) . GetModsFor ( ModType . DifficultyReduction ) . FirstOrDefault ( m = > m is OsuModNoFail ) ;
2018-08-07 15:45:18 +08:00
2019-12-13 20:45:38 +08:00
AddStep ( "set mods externally" , ( ) = > { SelectedMods . Value = new [ ] { noFailMod } ; } ) ;
2018-08-07 15:45:18 +08:00
2019-12-13 19:21:35 +08:00
changeRuleset ( 0 ) ;
2018-08-07 15:45:18 +08:00
AddAssert ( "ensure mods still selected" , ( ) = > modDisplay . Current . Value . Single ( m = > m is OsuModNoFail ) ! = null ) ;
2019-12-13 19:21:35 +08:00
changeRuleset ( 3 ) ;
2018-08-07 15:45:18 +08:00
2019-12-13 19:21:35 +08:00
AddAssert ( "ensure mods not selected" , ( ) = > modDisplay . Current . Value . Count = = 0 ) ;
2018-08-07 15:45:18 +08:00
2019-12-13 19:21:35 +08:00
changeRuleset ( 0 ) ;
2018-08-07 15:45:18 +08:00
2019-12-13 19:21:35 +08:00
AddAssert ( "ensure mods not selected" , ( ) = > modDisplay . Current . Value . Count = = 0 ) ;
2018-04-13 17:19:50 +08:00
}
2021-01-01 08:47:18 +08:00
[Test]
public void TestExternallySetCustomizedMod ( )
{
AddStep ( "set customized mod externally" , ( ) = > SelectedMods . Value = new [ ] { new OsuModDoubleTime { SpeedChange = { Value = 1.01 } } } ) ;
AddAssert ( "ensure button is selected and customized accordingly" , ( ) = >
{
var button = modSelect . GetModButton ( SelectedMods . Value . Single ( ) ) ;
return ( ( OsuModDoubleTime ) button . SelectedMod ) . SpeedChange . Value = = 1.01 ;
} ) ;
}
2018-04-13 17:19:50 +08:00
private void testSingleMod ( Mod mod )
{
selectNext ( mod ) ;
checkSelected ( mod ) ;
selectPrevious ( mod ) ;
checkNotSelected ( mod ) ;
selectNext ( mod ) ;
selectNext ( mod ) ;
checkNotSelected ( mod ) ;
selectPrevious ( mod ) ;
selectPrevious ( mod ) ;
checkNotSelected ( mod ) ;
}
private void testMultiMod ( MultiMod multiMod )
{
foreach ( var mod in multiMod . Mods )
{
selectNext ( mod ) ;
checkSelected ( mod ) ;
}
for ( int index = multiMod . Mods . Length - 1 ; index > = 0 ; index - - )
selectPrevious ( multiMod . Mods [ index ] ) ;
foreach ( var mod in multiMod . Mods )
checkNotSelected ( mod ) ;
}
2018-07-05 10:32:09 +08:00
private void testUnimplementedMod ( Mod mod )
2018-04-13 17:19:50 +08:00
{
selectNext ( mod ) ;
checkNotSelected ( mod ) ;
}
private void testIncompatibleMods ( Mod modA , Mod modB )
{
selectNext ( modA ) ;
checkSelected ( modA ) ;
checkNotSelected ( modB ) ;
selectNext ( modB ) ;
checkSelected ( modB ) ;
checkNotSelected ( modA ) ;
selectPrevious ( modB ) ;
checkNotSelected ( modA ) ;
checkNotSelected ( modB ) ;
}
private void testDeselectAll ( IEnumerable < Mod > mods )
{
foreach ( var mod in mods )
selectNext ( mod ) ;
AddAssert ( "check for any selection" , ( ) = > modSelect . SelectedMods . Value . Any ( ) ) ;
2019-12-13 19:21:35 +08:00
AddStep ( "deselect all" , ( ) = > modSelect . DeselectAllButton . Action . Invoke ( ) ) ;
2018-04-13 17:19:50 +08:00
AddAssert ( "check for no selection" , ( ) = > ! modSelect . SelectedMods . Value . Any ( ) ) ;
}
2019-12-13 19:21:35 +08:00
private void testMultiplierTextColour ( Mod mod , Func < Color4 > getCorrectColour )
2018-04-13 17:19:50 +08:00
{
2019-12-13 19:21:35 +08:00
checkLabelColor ( ( ) = > Color4 . White ) ;
2018-04-13 17:19:50 +08:00
selectNext ( mod ) ;
2019-03-19 16:24:26 +08:00
AddWaitStep ( "wait for changing colour" , 1 ) ;
2019-12-13 19:21:35 +08:00
checkLabelColor ( getCorrectColour ) ;
2018-04-13 17:19:50 +08:00
selectPrevious ( mod ) ;
2019-03-19 16:24:26 +08:00
AddWaitStep ( "wait for changing colour" , 1 ) ;
2019-12-13 19:21:35 +08:00
checkLabelColor ( ( ) = > Color4 . White ) ;
2018-04-13 17:19:50 +08:00
}
2020-07-15 18:45:48 +08:00
private void testModsWithSameBaseType ( Mod modA , Mod modB )
{
selectNext ( modA ) ;
checkSelected ( modA ) ;
selectNext ( modB ) ;
checkSelected ( modB ) ;
// Backwards
selectPrevious ( modA ) ;
checkSelected ( modA ) ;
}
2018-04-13 17:19:50 +08:00
private void selectNext ( Mod mod ) = > AddStep ( $"left click {mod.Name}" , ( ) = > modSelect . GetModButton ( mod ) ? . SelectNext ( 1 ) ) ;
private void selectPrevious ( Mod mod ) = > AddStep ( $"right click {mod.Name}" , ( ) = > modSelect . GetModButton ( mod ) ? . SelectNext ( - 1 ) ) ;
private void checkSelected ( Mod mod )
{
AddAssert ( $"check {mod.Name} is selected" , ( ) = >
{
var button = modSelect . GetModButton ( mod ) ;
return modSelect . SelectedMods . Value . Single ( m = > m . Name = = mod . Name ) ! = null & & button . SelectedMod . GetType ( ) = = mod . GetType ( ) & & button . Selected ;
} ) ;
}
2019-12-13 19:21:35 +08:00
private void changeRuleset ( int? id )
2019-06-20 23:12:39 +08:00
{
2019-12-13 19:35:34 +08:00
AddStep ( $"change ruleset to {(id?.ToString() ?? " none ")}" , ( ) = > { Ruleset . Value = rulesets . AvailableRulesets . FirstOrDefault ( r = > r . ID = = id ) ; } ) ;
2019-06-21 16:51:25 +08:00
waitForLoad ( ) ;
2019-06-20 23:12:39 +08:00
}
2019-06-21 16:51:25 +08:00
private void waitForLoad ( ) = >
AddUntilStep ( "wait for icons to load" , ( ) = > modSelect . AllLoaded ) ;
2018-04-13 17:19:50 +08:00
private void checkNotSelected ( Mod mod )
{
AddAssert ( $"check {mod.Name} is not selected" , ( ) = >
{
var button = modSelect . GetModButton ( mod ) ;
return modSelect . SelectedMods . Value . All ( m = > m . GetType ( ) ! = mod . GetType ( ) ) & & button . SelectedMod ? . GetType ( ) ! = mod . GetType ( ) ;
} ) ;
}
2019-12-13 19:21:35 +08:00
private void checkLabelColor ( Func < Color4 > getColour ) = > AddAssert ( "check label has expected colour" , ( ) = > modSelect . MultiplierLabel . Colour . AverageColour = = getColour ( ) ) ;
2018-04-13 17:19:50 +08:00
private class TestModSelectOverlay : ModSelectOverlay
{
2019-04-10 16:13:12 +08:00
public new Bindable < IReadOnlyList < Mod > > SelectedMods = > base . SelectedMods ;
2018-08-07 13:49:44 +08:00
2019-06-20 23:12:39 +08:00
public bool AllLoaded = > ModSectionsContainer . Children . All ( c = > c . ModIconsLoaded ) ;
2018-04-13 17:19:50 +08:00
public ModButton GetModButton ( Mod mod )
{
var section = ModSectionsContainer . Children . Single ( s = > s . ModType = = mod . Type ) ;
return section . ButtonsContainer . OfType < ModButton > ( ) . Single ( b = > b . Mods . Any ( m = > m . GetType ( ) = = mod . GetType ( ) ) ) ;
}
public new OsuSpriteText MultiplierLabel = > base . MultiplierLabel ;
public new TriangleButton DeselectAllButton = > base . DeselectAllButton ;
public new Color4 LowMultiplierColour = > base . LowMultiplierColour ;
public new Color4 HighMultiplierColour = > base . HighMultiplierColour ;
}
}
}