2023-02-07 09:20:43 +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.
2023-02-10 06:10:11 +08:00
using System ;
using System.Linq ;
2023-02-07 09:20:43 +08:00
using NUnit.Framework ;
using osu.Framework.Extensions.ObjectExtensions ;
using osu.Game.Beatmaps ;
using osu.Game.Beatmaps.ControlPoints ;
2023-02-10 06:10:11 +08:00
using osu.Game.Rulesets.Mods ;
using osu.Game.Rulesets.Objects ;
using osu.Game.Rulesets.Objects.Types ;
using osu.Game.Rulesets.Osu.Mods ;
2023-02-07 09:20:43 +08:00
using osu.Game.Rulesets.Osu.Objects ;
using osu.Game.Rulesets.Osu.Objects.Drawables ;
2023-08-31 02:41:57 +08:00
using osu.Game.Rulesets.Scoring ;
2023-02-07 09:20:43 +08:00
using osu.Game.Tests.Visual ;
using osuTK ;
namespace osu.Game.Rulesets.Osu.Tests
{
public partial class TestSceneHitCircleLateFade : OsuTestScene
{
2023-02-10 06:10:11 +08:00
private float? alphaAtMiss ;
2023-02-07 09:20:43 +08:00
[Test]
2023-08-31 02:41:57 +08:00
public void TestHitCircleClassicModMiss ( )
2023-02-07 09:20:43 +08:00
{
2023-02-10 06:10:11 +08:00
AddStep ( "Create hit circle" , ( ) = >
{
SelectedMods . Value = new Mod [ ] { new OsuModClassic ( ) } ;
createCircle ( ) ;
} ) ;
2023-02-07 09:20:43 +08:00
2023-02-19 23:39:16 +08:00
AddUntilStep ( "Wait until circle is missed" , ( ) = > alphaAtMiss . IsNotNull ( ) ) ;
AddAssert ( "Transparent when missed" , ( ) = > alphaAtMiss = = 0 ) ;
}
[Test]
public void TestHitCircleClassicAndFullHiddenMods ( )
{
AddStep ( "Create hit circle" , ( ) = >
{
SelectedMods . Value = new Mod [ ] { new OsuModHidden ( ) , new OsuModClassic ( ) } ;
createCircle ( ) ;
} ) ;
AddUntilStep ( "Wait until circle is missed" , ( ) = > alphaAtMiss . IsNotNull ( ) ) ;
AddAssert ( "Transparent when missed" , ( ) = > alphaAtMiss = = 0 ) ;
}
[Test]
public void TestHitCircleClassicAndApproachCircleOnlyHiddenMods ( )
{
AddStep ( "Create hit circle" , ( ) = >
{
SelectedMods . Value = new Mod [ ] { new OsuModHidden { OnlyFadeApproachCircles = { Value = true } } , new OsuModClassic ( ) } ;
createCircle ( ) ;
} ) ;
2023-02-10 06:10:11 +08:00
AddUntilStep ( "Wait until circle is missed" , ( ) = > alphaAtMiss . IsNotNull ( ) ) ;
AddAssert ( "Transparent when missed" , ( ) = > alphaAtMiss = = 0 ) ;
}
2023-08-31 02:41:57 +08:00
/// <summary>
/// No early fade is expected to be applied if the hit circle has been hit.
/// </summary>
2023-02-10 06:10:11 +08:00
[Test]
2023-08-31 02:41:57 +08:00
public void TestHitCircleClassicModHit ( )
{
2023-08-31 15:18:18 +08:00
TestDrawableHitCircle circle = null ! ;
2023-08-31 02:41:57 +08:00
AddStep ( "Create hit circle" , ( ) = >
{
SelectedMods . Value = new Mod [ ] { new OsuModClassic ( ) } ;
2023-08-31 15:18:18 +08:00
circle = createCircle ( true ) ;
2023-08-31 02:41:57 +08:00
} ) ;
2023-08-31 15:18:18 +08:00
AddUntilStep ( "Wait until circle is hit" , ( ) = > circle . Result ? . Type = = HitResult . Great ) ;
AddUntilStep ( "Wait for miss window" , ( ) = > Clock . CurrentTime , ( ) = > Is . GreaterThanOrEqualTo ( circle . HitObject . StartTime + circle . HitObject . HitWindows . WindowFor ( HitResult . Miss ) ) ) ;
AddAssert ( "Check circle is still visible" , ( ) = > circle . Alpha , ( ) = > Is . GreaterThan ( 0 ) ) ;
2023-08-31 02:41:57 +08:00
}
[Test]
public void TestHitCircleNoModMiss ( )
2023-02-10 06:10:11 +08:00
{
2023-02-07 09:20:43 +08:00
AddStep ( "Create hit circle" , ( ) = >
{
2023-02-10 06:10:11 +08:00
SelectedMods . Value = Array . Empty < Mod > ( ) ;
createCircle ( ) ;
} ) ;
2023-02-07 09:20:43 +08:00
2023-02-10 06:10:11 +08:00
AddUntilStep ( "Wait until circle is missed" , ( ) = > alphaAtMiss . IsNotNull ( ) ) ;
AddAssert ( "Opaque when missed" , ( ) = > alphaAtMiss = = 1 ) ;
}
2023-02-07 09:20:43 +08:00
2023-08-31 02:41:57 +08:00
[Test]
public void TestHitCircleNoModHit ( )
{
AddStep ( "Create hit circle" , ( ) = >
{
SelectedMods . Value = Array . Empty < Mod > ( ) ;
createCircle ( true ) ;
} ) ;
}
2023-02-10 06:10:11 +08:00
[Test]
public void TestSliderClassicMod ( )
{
AddStep ( "Create slider" , ( ) = >
{
SelectedMods . Value = new Mod [ ] { new OsuModClassic ( ) } ;
createSlider ( ) ;
} ) ;
2023-02-07 09:20:43 +08:00
2023-02-10 06:10:11 +08:00
AddUntilStep ( "Wait until head circle is missed" , ( ) = > alphaAtMiss . IsNotNull ( ) ) ;
AddAssert ( "Head circle transparent when missed" , ( ) = > alphaAtMiss = = 0 ) ;
}
2023-02-07 09:20:43 +08:00
2023-02-10 06:10:11 +08:00
[Test]
public void TestSliderNoMod ( )
{
AddStep ( "Create slider" , ( ) = >
{
SelectedMods . Value = Array . Empty < Mod > ( ) ;
createSlider ( ) ;
2023-02-07 09:20:43 +08:00
} ) ;
2023-02-10 06:10:11 +08:00
AddUntilStep ( "Wait until head circle is missed" , ( ) = > alphaAtMiss . IsNotNull ( ) ) ;
AddAssert ( "Head circle opaque when missed" , ( ) = > alphaAtMiss = = 1 ) ;
}
2023-08-31 15:18:18 +08:00
private TestDrawableHitCircle createCircle ( bool shouldHit = false )
2023-02-10 06:10:11 +08:00
{
alphaAtMiss = null ;
2023-08-31 02:41:57 +08:00
TestDrawableHitCircle drawableHitCircle = new TestDrawableHitCircle ( new HitCircle
2023-02-10 06:10:11 +08:00
{
StartTime = Time . Current + 500 ,
2023-08-31 02:41:57 +08:00
Position = new Vector2 ( 250 ) ,
2023-08-31 15:18:18 +08:00
} , shouldHit ) ;
2023-08-31 02:41:57 +08:00
drawableHitCircle . Scale = new Vector2 ( 2f ) ;
2023-02-10 06:10:11 +08:00
2023-09-06 05:35:03 +08:00
LoadComponent ( drawableHitCircle ) ;
2023-02-10 06:10:11 +08:00
foreach ( var mod in SelectedMods . Value . OfType < IApplicableToDrawableHitObject > ( ) )
mod . ApplyToDrawableHitObject ( drawableHitCircle ) ;
drawableHitCircle . HitObject . ApplyDefaults ( new ControlPointInfo ( ) , new BeatmapDifficulty ( ) ) ;
2023-08-31 02:41:57 +08:00
drawableHitCircle . OnNewResult + = ( _ , result ) = >
2023-02-10 06:10:11 +08:00
{
2023-08-31 02:41:57 +08:00
if ( ! result . IsHit )
alphaAtMiss = drawableHitCircle . Alpha ;
2023-02-10 06:10:11 +08:00
} ;
Child = drawableHitCircle ;
2023-08-31 15:18:18 +08:00
return drawableHitCircle ;
2023-02-10 06:10:11 +08:00
}
private void createSlider ( )
{
alphaAtMiss = null ;
DrawableSlider drawableSlider = new DrawableSlider ( new Slider
{
StartTime = Time . Current + 500 ,
Position = new Vector2 ( 250 ) ,
2023-11-08 18:43:54 +08:00
Path = new SliderPath ( PathType . LINEAR , new [ ]
2023-02-10 06:10:11 +08:00
{
Vector2 . Zero ,
new Vector2 ( 0 , 100 ) ,
} )
} ) ;
2023-08-31 02:41:57 +08:00
drawableSlider . Scale = new Vector2 ( 2f ) ;
2023-02-10 06:10:11 +08:00
drawableSlider . HitObject . ApplyDefaults ( new ControlPointInfo ( ) , new BeatmapDifficulty ( ) ) ;
drawableSlider . OnLoadComplete + = _ = >
{
foreach ( var mod in SelectedMods . Value . OfType < IApplicableToDrawableHitObject > ( ) )
mod . ApplyToDrawableHitObject ( drawableSlider . HeadCircle ) ;
2023-08-31 02:41:57 +08:00
drawableSlider . HeadCircle . OnNewResult + = ( _ , result ) = >
2023-02-10 06:10:11 +08:00
{
2023-08-31 02:41:57 +08:00
if ( ! result . IsHit )
alphaAtMiss = drawableSlider . HeadCircle . Alpha ;
2023-02-10 06:10:11 +08:00
} ;
} ;
2023-08-31 15:18:18 +08:00
2023-02-10 06:10:11 +08:00
Child = drawableSlider ;
2023-02-07 09:20:43 +08:00
}
2023-08-31 02:41:57 +08:00
protected partial class TestDrawableHitCircle : DrawableHitCircle
{
2023-08-31 15:18:18 +08:00
private readonly bool shouldHit ;
2023-08-31 02:41:57 +08:00
2023-08-31 15:18:18 +08:00
public TestDrawableHitCircle ( HitCircle h , bool shouldHit )
2023-08-31 02:41:57 +08:00
: base ( h )
{
2023-08-31 15:18:18 +08:00
this . shouldHit = shouldHit ;
2023-08-31 02:41:57 +08:00
}
protected override void CheckForResult ( bool userTriggered , double timeOffset )
{
2023-09-01 16:19:39 +08:00
if ( shouldHit & & ! userTriggered & & timeOffset > = 0 )
2023-08-31 02:41:57 +08:00
{
// force success
2024-02-05 20:21:01 +08:00
ApplyResult ( HitResult . Great ) ;
2023-08-31 02:41:57 +08:00
}
else
base . CheckForResult ( userTriggered , timeOffset ) ;
}
}
2023-02-07 09:20:43 +08:00
}
}