mirror of
https://github.com/ppy/osu.git
synced 2025-01-14 18:32:56 +08:00
Merge pull request #24686 from frenzibyte/hitcircles-fade-fix
This commit is contained in:
commit
38bb0faa58
@ -13,6 +13,7 @@ using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
@ -23,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
private float? alphaAtMiss;
|
||||
|
||||
[Test]
|
||||
public void TestHitCircleClassicMod()
|
||||
public void TestHitCircleClassicModMiss()
|
||||
{
|
||||
AddStep("Create hit circle", () =>
|
||||
{
|
||||
@ -61,8 +62,27 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
AddAssert("Transparent when missed", () => alphaAtMiss == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No early fade is expected to be applied if the hit circle has been hit.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestHitCircleNoMod()
|
||||
public void TestHitCircleClassicModHit()
|
||||
{
|
||||
TestDrawableHitCircle circle = null!;
|
||||
|
||||
AddStep("Create hit circle", () =>
|
||||
{
|
||||
SelectedMods.Value = new Mod[] { new OsuModClassic() };
|
||||
circle = createCircle(true);
|
||||
});
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHitCircleNoModMiss()
|
||||
{
|
||||
AddStep("Create hit circle", () =>
|
||||
{
|
||||
@ -74,6 +94,16 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
AddAssert("Opaque when missed", () => alphaAtMiss == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHitCircleNoModHit()
|
||||
{
|
||||
AddStep("Create hit circle", () =>
|
||||
{
|
||||
SelectedMods.Value = Array.Empty<Mod>();
|
||||
createCircle(true);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSliderClassicMod()
|
||||
{
|
||||
@ -100,27 +130,32 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
AddAssert("Head circle opaque when missed", () => alphaAtMiss == 1);
|
||||
}
|
||||
|
||||
private void createCircle()
|
||||
private TestDrawableHitCircle createCircle(bool shouldHit = false)
|
||||
{
|
||||
alphaAtMiss = null;
|
||||
|
||||
DrawableHitCircle drawableHitCircle = new DrawableHitCircle(new HitCircle
|
||||
TestDrawableHitCircle drawableHitCircle = new TestDrawableHitCircle(new HitCircle
|
||||
{
|
||||
StartTime = Time.Current + 500,
|
||||
Position = new Vector2(250)
|
||||
});
|
||||
Position = new Vector2(250),
|
||||
}, shouldHit);
|
||||
|
||||
drawableHitCircle.Scale = new Vector2(2f);
|
||||
|
||||
foreach (var mod in SelectedMods.Value.OfType<IApplicableToDrawableHitObject>())
|
||||
mod.ApplyToDrawableHitObject(drawableHitCircle);
|
||||
|
||||
drawableHitCircle.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
drawableHitCircle.OnNewResult += (_, _) =>
|
||||
drawableHitCircle.OnNewResult += (_, result) =>
|
||||
{
|
||||
alphaAtMiss = drawableHitCircle.Alpha;
|
||||
if (!result.IsHit)
|
||||
alphaAtMiss = drawableHitCircle.Alpha;
|
||||
};
|
||||
|
||||
Child = drawableHitCircle;
|
||||
|
||||
return drawableHitCircle;
|
||||
}
|
||||
|
||||
private void createSlider()
|
||||
@ -138,6 +173,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
})
|
||||
});
|
||||
|
||||
drawableSlider.Scale = new Vector2(2f);
|
||||
|
||||
drawableSlider.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
drawableSlider.OnLoadComplete += _ =>
|
||||
@ -145,12 +182,36 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
foreach (var mod in SelectedMods.Value.OfType<IApplicableToDrawableHitObject>())
|
||||
mod.ApplyToDrawableHitObject(drawableSlider.HeadCircle);
|
||||
|
||||
drawableSlider.HeadCircle.OnNewResult += (_, _) =>
|
||||
drawableSlider.HeadCircle.OnNewResult += (_, result) =>
|
||||
{
|
||||
alphaAtMiss = drawableSlider.HeadCircle.Alpha;
|
||||
if (!result.IsHit)
|
||||
alphaAtMiss = drawableSlider.HeadCircle.Alpha;
|
||||
};
|
||||
};
|
||||
|
||||
Child = drawableSlider;
|
||||
}
|
||||
|
||||
protected partial class TestDrawableHitCircle : DrawableHitCircle
|
||||
{
|
||||
private readonly bool shouldHit;
|
||||
|
||||
public TestDrawableHitCircle(HitCircle h, bool shouldHit)
|
||||
: base(h)
|
||||
{
|
||||
this.shouldHit = shouldHit;
|
||||
}
|
||||
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (shouldHit && !userTriggered && timeOffset >= 0 && CheckHittable?.Invoke(this, Time.Current) != false)
|
||||
{
|
||||
// force success
|
||||
ApplyResult(r => r.Type = HitResult.Great);
|
||||
}
|
||||
else
|
||||
base.CheckForResult(userTriggered, timeOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,13 +85,16 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
private void applyEarlyFading(DrawableHitCircle circle)
|
||||
{
|
||||
circle.ApplyCustomUpdateState += (o, _) =>
|
||||
circle.ApplyCustomUpdateState += (dho, state) =>
|
||||
{
|
||||
using (o.BeginAbsoluteSequence(o.StateUpdateTime))
|
||||
using (dho.BeginAbsoluteSequence(dho.StateUpdateTime))
|
||||
{
|
||||
double okWindow = o.HitObject.HitWindows.WindowFor(HitResult.Ok);
|
||||
double lateMissFadeTime = o.HitObject.HitWindows.WindowFor(HitResult.Meh) - okWindow;
|
||||
o.Delay(okWindow).FadeOut(lateMissFadeTime);
|
||||
if (state != ArmedState.Hit)
|
||||
{
|
||||
double okWindow = dho.HitObject.HitWindows.WindowFor(HitResult.Ok);
|
||||
double lateMissFadeTime = dho.HitObject.HitWindows.WindowFor(HitResult.Meh) - okWindow;
|
||||
dho.Delay(okWindow).FadeOut(lateMissFadeTime);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user