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