1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-30 16:20:25 +08:00

Merge pull request #16710 from peppy/add-intro-playback-safety

Add failsafe to `IntroScreen` to stop users with incorrect audio configuration getting stuck
This commit is contained in:
Dan Balasescu
2022-01-31 13:40:40 +09:00
committed by GitHub
Unverified
6 changed files with 92 additions and 0 deletions
@@ -5,6 +5,8 @@ using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Threading;
using osu.Game.Overlays;
using osu.Game.Screens;
using osu.Game.Screens.Menu;
using osuTK;
@@ -18,10 +20,17 @@ namespace osu.Game.Tests.Visual.Menus
[Cached]
private OsuLogo logo;
protected abstract bool IntroReliesOnTrack { get; }
protected OsuScreenStack IntroStack;
private IntroScreen intro;
[Cached]
private NotificationOverlay notifications;
private ScheduledDelegate trackResetDelegate;
protected IntroTestScene()
{
Children = new Drawable[]
@@ -38,6 +47,11 @@ namespace osu.Game.Tests.Visual.Menus
RelativePositionAxes = Axes.Both,
Depth = float.MinValue,
Position = new Vector2(0.5f),
},
notifications = new NotificationOverlay
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
}
};
}
@@ -63,6 +77,41 @@ namespace osu.Game.Tests.Visual.Menus
AddUntilStep("wait for menu", () => intro.DidLoadMenu);
}
[Test]
public virtual void TestPlayIntroWithFailingAudioDevice()
{
AddStep("hide notifications", () => notifications.Hide());
AddStep("restart sequence", () =>
{
logo.FinishTransforms();
logo.IsTracking = false;
IntroStack?.Expire();
Add(IntroStack = new OsuScreenStack
{
RelativeSizeAxes = Axes.Both,
});
IntroStack.Push(intro = CreateScreen());
});
AddStep("trigger failure", () =>
{
trackResetDelegate = Scheduler.AddDelayed(() =>
{
intro.Beatmap.Value.Track.Seek(0);
}, 0, true);
});
AddUntilStep("wait for menu", () => intro.DidLoadMenu);
if (IntroReliesOnTrack)
AddUntilStep("wait for notification", () => notifications.UnreadCount.Value == 1);
AddStep("uninstall delegate", () => trackResetDelegate?.Cancel());
}
protected abstract IntroScreen CreateScreen();
}
}
@@ -9,6 +9,7 @@ namespace osu.Game.Tests.Visual.Menus
[TestFixture]
public class TestSceneIntroCircles : IntroTestScene
{
protected override bool IntroReliesOnTrack => false;
protected override IntroScreen CreateScreen() => new IntroCircles();
}
}
@@ -9,6 +9,7 @@ namespace osu.Game.Tests.Visual.Menus
[TestFixture]
public class TestSceneIntroTriangles : IntroTestScene
{
protected override bool IntroReliesOnTrack => true;
protected override IntroScreen CreateScreen() => new IntroTriangles();
}
}
@@ -10,6 +10,7 @@ namespace osu.Game.Tests.Visual.Menus
[TestFixture]
public class TestSceneIntroWelcome : IntroTestScene
{
protected override bool IntroReliesOnTrack => false;
protected override IntroScreen CreateScreen() => new IntroWelcome();
public override void TestPlayIntro()
+37
View File
@@ -18,6 +18,7 @@ using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.IO.Archives;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Screens.Backgrounds;
using osuTK;
using osuTK.Graphics;
@@ -147,6 +148,36 @@ namespace osu.Game.Screens.Menu
}
}
public override void OnEntering(IScreen last)
{
base.OnEntering(last);
ensureEventuallyArrivingAtMenu();
}
[Resolved]
private NotificationOverlay notifications { get; set; }
private void ensureEventuallyArrivingAtMenu()
{
// This intends to handle the case where an intro may get stuck.
// Historically, this could happen if the host system's audio device is in a state it can't
// play audio, causing a clock to never elapse time and the intro to never end.
//
// This safety measure gives the user a chance to fix the problem from the settings menu.
Scheduler.AddDelayed(() =>
{
if (DidLoadMenu)
return;
PrepareMenuLoad();
LoadMenu();
notifications.Post(new SimpleErrorNotification
{
Text = "osu! doesn't seem to be able to play audio correctly.\n\nPlease try changing your audio device to a working setting."
});
}, 5000);
}
public override void OnResuming(IScreen last)
{
this.FadeIn(300);
@@ -241,6 +272,9 @@ namespace osu.Game.Screens.Menu
protected void PrepareMenuLoad()
{
if (nextScreen != null)
return;
nextScreen = createNextScreen?.Invoke();
if (nextScreen != null)
@@ -249,6 +283,9 @@ namespace osu.Game.Screens.Menu
protected void LoadMenu()
{
if (DidLoadMenu)
return;
beatmap.Return();
DidLoadMenu = true;
+3
View File
@@ -93,6 +93,9 @@ namespace osu.Game.Screens.Menu
{
base.OnSuspending(next);
// ensure the background is shown, even if the TriangleIntroSequence failed to do so.
background.ApplyToBackground(b => b.Show());
// important as there is a clock attached to a track which will likely be disposed before returning to this screen.
intro.Expire();
}