2021-05-20 02:52:29 +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 System.Linq ;
2021-05-30 02:22:39 +08:00
using NUnit.Framework ;
2021-05-20 02:52:29 +08:00
using osu.Framework.Allocation ;
using osu.Framework.Audio ;
2023-02-15 16:26:05 +08:00
using osu.Framework.Graphics.Containers ;
2021-05-20 02:52:29 +08:00
using osu.Framework.Lists ;
using osu.Framework.Testing ;
using osu.Framework.Timing ;
using osu.Framework.Utils ;
using osu.Game.Beatmaps ;
2021-11-29 16:57:17 +08:00
using osu.Game.Database ;
2021-05-20 02:52:29 +08:00
using osu.Game.Rulesets ;
using osu.Game.Rulesets.Osu ;
using osu.Game.Rulesets.Osu.Skinning.Legacy ;
using osu.Game.Rulesets.Scoring ;
2022-03-15 21:55:47 +08:00
using osu.Game.Screens.Play ;
2023-06-17 01:00:09 +08:00
using osu.Game.Screens.Play.HUD ;
2021-05-20 02:52:29 +08:00
using osu.Game.Skinning ;
using osu.Game.Storyboards ;
namespace osu.Game.Tests.Visual.Gameplay
{
2022-11-24 13:32:20 +08:00
public partial class TestSceneBeatmapSkinFallbacks : OsuPlayerTestScene
2021-05-20 02:52:29 +08:00
{
2023-02-15 16:26:05 +08:00
private ISkin currentBeatmapSkin = null ! ;
2021-05-20 02:52:29 +08:00
[Resolved]
2023-02-15 16:26:05 +08:00
private SkinManager skinManager { get ; set ; } = null ! ;
2021-05-20 02:52:29 +08:00
protected override bool HasCustomSteps = > true ;
2021-05-20 04:01:41 +08:00
[Test]
public void TestEmptyLegacyBeatmapSkinFallsBack ( )
{
2022-09-17 23:14:49 +08:00
CreateSkinTest ( TrianglesSkin . CreateInfo ( ) , ( ) = > new LegacyBeatmapSkin ( new BeatmapInfo ( ) , null ) ) ;
2023-02-15 17:31:55 +08:00
AddUntilStep ( "wait for hud load" , ( ) = > Player . ChildrenOfType < SkinComponentsContainer > ( ) . All ( c = > c . ComponentsLoaded ) ) ;
AddAssert ( "hud from default skin" , ( ) = > AssertComponentsFromExpectedSource ( SkinComponentsContainerLookup . TargetArea . MainHUDComponents , skinManager . CurrentSkin . Value ) ) ;
2021-05-20 04:01:41 +08:00
}
2021-05-20 03:53:21 +08:00
protected void CreateSkinTest ( SkinInfo gameCurrentSkin , Func < ISkin > getBeatmapSkin )
2021-05-20 02:52:29 +08:00
{
CreateTest ( ( ) = >
{
AddStep ( "setup skins" , ( ) = >
{
2021-12-14 13:21:23 +08:00
skinManager . CurrentSkinInfo . Value = gameCurrentSkin . ToLiveUnmanaged ( ) ;
2021-05-20 03:53:21 +08:00
currentBeatmapSkin = getBeatmapSkin ( ) ;
2021-05-20 02:52:29 +08:00
} ) ;
} ) ;
}
2023-02-15 17:31:55 +08:00
protected bool AssertComponentsFromExpectedSource ( SkinComponentsContainerLookup . TargetArea target , ISkin expectedSource )
2021-05-20 02:52:29 +08:00
{
2023-02-15 17:31:55 +08:00
var targetContainer = Player . ChildrenOfType < SkinComponentsContainer > ( ) . First ( s = > s . Lookup . Target = = target ) ;
2023-02-15 16:47:34 +08:00
var actualComponentsContainer = targetContainer . ChildrenOfType < Container > ( ) . SingleOrDefault ( c = > c . Parent = = targetContainer ) ;
2021-05-21 01:47:40 +08:00
if ( actualComponentsContainer = = null )
return false ;
2023-02-15 14:47:41 +08:00
var actualInfo = actualComponentsContainer . CreateSerialisedInfo ( ) ;
2021-05-21 01:47:40 +08:00
2023-02-15 17:31:55 +08:00
var expectedComponentsContainer = expectedSource . GetDrawableComponent ( new SkinComponentsContainerLookup ( target ) ) as Container ;
2021-05-21 01:47:40 +08:00
if ( expectedComponentsContainer = = null )
return false ;
2021-05-20 02:52:29 +08:00
2022-05-28 19:33:09 +08:00
var expectedComponentsAdjustmentContainer = new DependencyProvidingContainer
2021-05-21 01:47:40 +08:00
{
Position = actualComponentsContainer . Parent . ToSpaceOfOtherDrawable ( actualComponentsContainer . DrawPosition , Content ) ,
Size = actualComponentsContainer . DrawSize ,
Child = expectedComponentsContainer ,
2022-05-28 19:33:09 +08:00
// proxy the same required dependencies that `actualComponentsContainer` is using.
CachedDependencies = new ( Type , object ) [ ]
{
( typeof ( ScoreProcessor ) , actualComponentsContainer . Dependencies . Get < ScoreProcessor > ( ) ) ,
( typeof ( HealthProcessor ) , actualComponentsContainer . Dependencies . Get < HealthProcessor > ( ) ) ,
( typeof ( GameplayState ) , actualComponentsContainer . Dependencies . Get < GameplayState > ( ) ) ,
2023-06-17 01:00:09 +08:00
( typeof ( IGameplayClock ) , actualComponentsContainer . Dependencies . Get < IGameplayClock > ( ) ) ,
2023-06-27 01:27:42 +08:00
( typeof ( InputCountController ) , actualComponentsContainer . Dependencies . Get < InputCountController > ( ) )
2022-05-28 19:33:09 +08:00
} ,
2021-05-21 01:47:40 +08:00
} ;
2021-05-20 02:52:29 +08:00
2021-05-21 01:47:40 +08:00
Add ( expectedComponentsAdjustmentContainer ) ;
2021-05-21 02:08:31 +08:00
expectedComponentsAdjustmentContainer . UpdateSubTree ( ) ;
2023-02-15 14:47:41 +08:00
var expectedInfo = expectedComponentsContainer . CreateSerialisedInfo ( ) ;
2022-08-26 14:19:05 +08:00
Remove ( expectedComponentsAdjustmentContainer , true ) ;
2021-05-20 02:52:29 +08:00
2021-05-21 01:47:40 +08:00
return almostEqual ( actualInfo , expectedInfo ) ;
2021-05-20 02:52:29 +08:00
}
2023-02-15 14:47:41 +08:00
private static bool almostEqual ( SerialisedDrawableInfo drawableInfo , SerialisedDrawableInfo ? other ) = >
2021-10-01 21:58:40 +08:00
other ! = null
2023-02-15 14:36:18 +08:00
& & drawableInfo . Type = = other . Type
& & drawableInfo . Anchor = = other . Anchor
& & drawableInfo . Origin = = other . Origin
& & Precision . AlmostEquals ( drawableInfo . Position , other . Position , 1 )
& & Precision . AlmostEquals ( drawableInfo . Scale , other . Scale )
& & Precision . AlmostEquals ( drawableInfo . Rotation , other . Rotation )
2023-02-15 14:47:41 +08:00
& & drawableInfo . Children . SequenceEqual ( other . Children , new FuncEqualityComparer < SerialisedDrawableInfo > ( almostEqual ) ) ;
2021-10-01 21:58:40 +08:00
2023-02-15 16:26:05 +08:00
protected override WorkingBeatmap CreateWorkingBeatmap ( IBeatmap beatmap , Storyboard ? storyboard = null )
2021-05-20 02:52:29 +08:00
= > new CustomSkinWorkingBeatmap ( beatmap , storyboard , Clock , Audio , currentBeatmapSkin ) ;
protected override Ruleset CreatePlayerRuleset ( ) = > new TestOsuRuleset ( ) ;
private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap
{
private readonly ISkin beatmapSkin ;
2023-02-15 16:26:05 +08:00
public CustomSkinWorkingBeatmap ( IBeatmap beatmap , Storyboard ? storyboard , IFrameBasedClock referenceClock , AudioManager audio , ISkin beatmapSkin )
2021-05-20 02:52:29 +08:00
: base ( beatmap , storyboard , referenceClock , audio )
{
this . beatmapSkin = beatmapSkin ;
}
2021-08-16 00:38:01 +08:00
protected internal override ISkin GetSkin ( ) = > beatmapSkin ;
2021-05-20 02:52:29 +08:00
}
private class TestOsuRuleset : OsuRuleset
{
2022-09-15 16:36:14 +08:00
public override ISkin CreateSkinTransformer ( ISkin skin , IBeatmap beatmap ) = > new TestOsuLegacySkinTransformer ( skin ) ;
2021-05-20 02:52:29 +08:00
private class TestOsuLegacySkinTransformer : OsuLegacySkinTransformer
{
2021-06-09 18:34:42 +08:00
public TestOsuLegacySkinTransformer ( ISkin skin )
: base ( skin )
2021-05-20 02:52:29 +08:00
{
}
}
}
}
}