2021-04-27 13:26:12 +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
2023-07-05 17:20:25 +08:00
using System ;
2021-04-27 13:26:12 +08:00
using NUnit.Framework ;
2021-08-06 18:59:02 +08:00
using osu.Framework.Graphics ;
2021-04-27 13:26:12 +08:00
using osu.Framework.Testing ;
2021-05-28 20:27:10 +08:00
using osu.Game.Beatmaps ;
using osu.Game.Beatmaps.ControlPoints ;
2022-12-01 05:53:56 +08:00
using osu.Game.Rulesets.Judgements ;
2021-04-27 13:26:12 +08:00
using osu.Game.Rulesets.Objects ;
using osu.Game.Rulesets.Objects.Drawables ;
2021-08-06 18:59:02 +08:00
using osu.Game.Rulesets.Scoring ;
2021-04-27 13:26:12 +08:00
using osu.Game.Tests.Visual ;
namespace osu.Game.Tests.Gameplay
{
[HeadlessTest]
public partial class TestSceneDrawableHitObject : OsuTestScene
{
[Test]
public void TestEntryLifetime ( )
{
TestDrawableHitObject dho = null ;
var initialHitObject = new HitObject
{
StartTime = 1000
} ;
var entry = new TestLifetimeEntry ( new HitObject
{
StartTime = 2000
} ) ;
AddStep ( "Create DHO" , ( ) = > Child = dho = new TestDrawableHitObject ( initialHitObject ) ) ;
AddAssert ( "Correct initial lifetime" , ( ) = > dho . LifetimeStart = = initialHitObject . StartTime - TestDrawableHitObject . INITIAL_LIFETIME_OFFSET ) ;
AddStep ( "Apply entry" , ( ) = > dho . Apply ( entry ) ) ;
AddAssert ( "Correct initial lifetime" , ( ) = > dho . LifetimeStart = = entry . HitObject . StartTime - TestLifetimeEntry . INITIAL_LIFETIME_OFFSET ) ;
AddStep ( "Set lifetime" , ( ) = > dho . LifetimeEnd = 3000 ) ;
AddAssert ( "Entry lifetime is updated" , ( ) = > entry . LifetimeEnd = = 3000 ) ;
}
2021-04-27 17:10:44 +08:00
[Test]
public void TestKeepAlive ( )
{
TestDrawableHitObject dho = null ;
TestLifetimeEntry entry = null ;
2021-06-16 15:01:29 +08:00
AddStep ( "Create DHO" , ( ) = > Child = dho = new TestDrawableHitObject
2021-04-27 17:10:44 +08:00
{
2021-06-16 15:01:29 +08:00
Entry = entry = new TestLifetimeEntry ( new HitObject ( ) )
2021-04-27 17:10:44 +08:00
} ) ;
2021-04-28 19:23:52 +08:00
AddStep ( "KeepAlive = true" , ( ) = >
{
entry . LifetimeStart = 0 ;
entry . LifetimeEnd = 1000 ;
entry . KeepAlive = true ;
} ) ;
2021-04-27 17:10:44 +08:00
AddAssert ( "Lifetime is overriden" , ( ) = > entry . LifetimeStart = = double . MinValue & & entry . LifetimeEnd = = double . MaxValue ) ;
AddStep ( "Set LifetimeStart" , ( ) = > dho . LifetimeStart = 500 ) ;
AddStep ( "KeepAlive = false" , ( ) = > entry . KeepAlive = false ) ;
AddAssert ( "Lifetime is correct" , ( ) = > entry . LifetimeStart = = 500 & & entry . LifetimeEnd = = 1000 ) ;
AddStep ( "Set LifetimeStart while KeepAlive" , ( ) = >
{
entry . KeepAlive = true ;
dho . LifetimeStart = double . MinValue ;
entry . KeepAlive = false ;
} ) ;
AddAssert ( "Lifetime is changed" , ( ) = > entry . LifetimeStart = = double . MinValue & & entry . LifetimeEnd = = 1000 ) ;
}
2021-05-28 20:27:10 +08:00
[Test]
public void TestLifetimeUpdatedOnDefaultApplied ( )
{
TestLifetimeEntry entry = null ;
AddStep ( "Create entry" , ( ) = > entry = new TestLifetimeEntry ( new HitObject ( ) ) { LifetimeStart = 1 } ) ;
2023-07-05 17:20:25 +08:00
assertJudged ( ( ) = > entry , false ) ;
2021-05-28 20:27:10 +08:00
AddStep ( "ApplyDefaults" , ( ) = > entry . HitObject . ApplyDefaults ( new ControlPointInfo ( ) , new BeatmapDifficulty ( ) ) ) ;
2023-07-05 17:20:25 +08:00
assertJudged ( ( ) = > entry , false ) ;
2021-05-28 20:27:10 +08:00
AddAssert ( "Lifetime is updated" , ( ) = > entry . LifetimeStart = = - TestLifetimeEntry . INITIAL_LIFETIME_OFFSET ) ;
2021-05-28 20:51:48 +08:00
TestDrawableHitObject dho = null ;
2021-06-16 15:01:29 +08:00
AddStep ( "Create DHO" , ( ) = > Child = dho = new TestDrawableHitObject
2021-05-28 20:51:48 +08:00
{
2021-06-16 15:01:29 +08:00
Entry = entry ,
SetLifetimeStartOnApply = true
2021-05-28 20:51:48 +08:00
} ) ;
AddStep ( "ApplyDefaults" , ( ) = > entry . HitObject . ApplyDefaults ( new ControlPointInfo ( ) , new BeatmapDifficulty ( ) ) ) ;
AddAssert ( "Lifetime is correct" , ( ) = > dho . LifetimeStart = = TestDrawableHitObject . LIFETIME_ON_APPLY & & entry . LifetimeStart = = TestDrawableHitObject . LIFETIME_ON_APPLY ) ;
2023-07-05 17:20:25 +08:00
assertJudged ( ( ) = > entry , false ) ;
2021-05-28 20:27:10 +08:00
}
2021-05-31 13:37:51 +08:00
[Test]
public void TestDrawableLifetimeUpdateOnEntryLifetimeChange ( )
{
TestDrawableHitObject dho = null ;
TestLifetimeEntry entry = null ;
2021-06-16 15:01:29 +08:00
AddStep ( "Create DHO" , ( ) = > Child = dho = new TestDrawableHitObject
2021-05-31 13:37:51 +08:00
{
2021-06-16 15:01:29 +08:00
Entry = entry = new TestLifetimeEntry ( new HitObject ( ) )
2021-05-31 13:37:51 +08:00
} ) ;
AddStep ( "Set entry lifetime" , ( ) = >
{
entry . LifetimeStart = 777 ;
entry . LifetimeEnd = 888 ;
} ) ;
AddAssert ( "Drawable lifetime is updated" , ( ) = > dho . LifetimeStart = = 777 & & dho . LifetimeEnd = = 888 ) ;
AddStep ( "KeepAlive = true" , ( ) = > entry . KeepAlive = true ) ;
AddAssert ( "Drawable lifetime is updated" , ( ) = > dho . LifetimeStart = = double . MinValue & & dho . LifetimeEnd = = double . MaxValue ) ;
AddStep ( "Modify start time" , ( ) = > entry . HitObject . StartTime = 100 ) ;
AddAssert ( "Drawable lifetime is correct" , ( ) = > dho . LifetimeStart = = double . MinValue ) ;
2021-06-01 13:38:02 +08:00
AddStep ( "Set LifetimeStart" , ( ) = > dho . LifetimeStart = 666 ) ;
AddAssert ( "Lifetime change is blocked" , ( ) = > dho . LifetimeStart = = double . MinValue ) ;
2021-06-01 13:25:32 +08:00
AddStep ( "Set LifetimeEnd" , ( ) = > dho . LifetimeEnd = 999 ) ;
AddAssert ( "Lifetime change is blocked" , ( ) = > dho . LifetimeEnd = = double . MaxValue ) ;
2021-05-31 13:37:51 +08:00
AddStep ( "KeepAlive = false" , ( ) = > entry . KeepAlive = false ) ;
2021-06-01 13:38:02 +08:00
AddAssert ( "Drawable lifetime is restored" , ( ) = > dho . LifetimeStart = = 666 & & dho . LifetimeEnd = = 999 ) ;
2021-05-31 13:37:51 +08:00
}
2021-08-06 18:59:02 +08:00
[Test]
public void TestStateChangeBeforeLoadComplete ( )
{
TestDrawableHitObject dho = null ;
AddStep ( "Add DHO and apply result" , ( ) = >
{
Child = dho = new TestDrawableHitObject ( new HitObject { StartTime = Time . Current } ) ;
dho . MissForcefully ( ) ;
} ) ;
AddAssert ( "DHO state is correct" , ( ) = > dho . State . Value = = ArmedState . Miss ) ;
}
2023-07-05 17:20:25 +08:00
[Test]
public void TestJudgedStateThroughLifetime ( )
{
TestDrawableHitObject dho = null ;
HitObjectLifetimeEntry lifetimeEntry = null ;
AddStep ( "Create lifetime entry" , ( ) = > lifetimeEntry = new HitObjectLifetimeEntry ( new HitObject { StartTime = Time . Current } ) ) ;
assertJudged ( ( ) = > lifetimeEntry , false ) ;
AddStep ( "Create DHO and apply entry" , ( ) = >
{
Child = dho = new TestDrawableHitObject ( ) ;
dho . Apply ( lifetimeEntry ) ;
} ) ;
assertJudged ( ( ) = > lifetimeEntry , false ) ;
AddStep ( "Apply result" , ( ) = > dho . MissForcefully ( ) ) ;
assertJudged ( ( ) = > lifetimeEntry , true ) ;
}
2022-12-01 05:53:56 +08:00
[Test]
public void TestResultSetBeforeLoadComplete ( )
{
TestDrawableHitObject dho = null ;
HitObjectLifetimeEntry lifetimeEntry = null ;
AddStep ( "Create lifetime entry" , ( ) = >
{
var hitObject = new HitObject { StartTime = Time . Current } ;
lifetimeEntry = new HitObjectLifetimeEntry ( hitObject )
{
2024-02-10 19:16:45 +08:00
Result = new JudgementResult ( hitObject , hitObject . Judgement )
2022-12-01 05:53:56 +08:00
{
Type = HitResult . Great
}
} ;
} ) ;
2023-07-05 17:20:25 +08:00
assertJudged ( ( ) = > lifetimeEntry , true ) ;
2022-12-01 05:53:56 +08:00
AddStep ( "Create DHO and apply entry" , ( ) = >
{
dho = new TestDrawableHitObject ( ) ;
dho . Apply ( lifetimeEntry ) ;
Child = dho ;
} ) ;
2023-07-05 17:20:25 +08:00
assertJudged ( ( ) = > lifetimeEntry , true ) ;
2022-12-01 05:53:56 +08:00
AddAssert ( "DHO state is correct" , ( ) = > dho . State . Value , ( ) = > Is . EqualTo ( ArmedState . Hit ) ) ;
}
2023-07-05 17:20:25 +08:00
private void assertJudged ( Func < HitObjectLifetimeEntry > entry , bool val ) = >
AddAssert ( val ? "Is judged" : "Not judged" , ( ) = > entry ( ) . Judged , ( ) = > Is . EqualTo ( val ) ) ;
2021-04-27 13:26:12 +08:00
private partial class TestDrawableHitObject : DrawableHitObject
{
public const double INITIAL_LIFETIME_OFFSET = 100 ;
2021-05-28 20:51:48 +08:00
public const double LIFETIME_ON_APPLY = 222 ;
2021-04-27 13:26:12 +08:00
protected override double InitialLifetimeOffset = > INITIAL_LIFETIME_OFFSET ;
2021-05-28 20:51:48 +08:00
public bool SetLifetimeStartOnApply ;
2021-06-16 15:01:29 +08:00
public TestDrawableHitObject ( HitObject hitObject = null )
2021-04-27 13:26:12 +08:00
: base ( hitObject )
{
}
2021-05-28 20:51:48 +08:00
protected override void OnApply ( )
{
base . OnApply ( ) ;
if ( SetLifetimeStartOnApply )
LifetimeStart = LIFETIME_ON_APPLY ;
}
2021-08-06 18:59:02 +08:00
2024-02-05 20:21:01 +08:00
public void MissForcefully ( ) = > ApplyResult ( HitResult . Miss ) ;
2021-08-06 18:59:02 +08:00
protected override void UpdateHitStateTransforms ( ArmedState state )
{
if ( state ! = ArmedState . Miss )
{
base . UpdateHitStateTransforms ( state ) ;
return ;
}
this . FadeOut ( 1000 ) ;
}
2021-04-27 13:26:12 +08:00
}
private class TestLifetimeEntry : HitObjectLifetimeEntry
{
public const double INITIAL_LIFETIME_OFFSET = 200 ;
protected override double InitialLifetimeOffset = > INITIAL_LIFETIME_OFFSET ;
public TestLifetimeEntry ( HitObject hitObject )
: base ( hitObject )
{
}
}
}
}