From 2dbfdc3d2c0276e431b4b45bc4dabbb4f480b5b0 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 20 Oct 2025 17:02:35 +0900 Subject: [PATCH] Preview next song in quick play --- .../Matchmaking/Match/ScreenMatchmaking.cs | 60 ++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/Match/ScreenMatchmaking.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/Match/ScreenMatchmaking.cs index 590d84f310..a40510aab5 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/Match/ScreenMatchmaking.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/Match/ScreenMatchmaking.cs @@ -16,6 +16,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Graphics.Cursor; @@ -37,7 +38,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match /// /// The main matchmaking screen which houses a custom through the life cycle of a single session. /// - public partial class ScreenMatchmaking : OsuScreen + public partial class ScreenMatchmaking : OsuScreen, IPreviewTrackOwner { /// /// Padding between rows of the content. @@ -74,6 +75,12 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match [Resolved] private AudioManager audio { get; set; } = null!; + [Resolved] + private PreviewTrackManager previewTrackManager { get; set; } = null!; + + [Resolved] + private MusicController music { get; set; } = null!; + private readonly MultiplayerRoom room; private Sample? sampleStart; @@ -308,6 +315,18 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match return false; } + public override void OnEntering(ScreenTransitionEvent e) + { + base.OnEntering(e); + beginHandlingTrack(); + } + + public override void OnSuspending(ScreenTransitionEvent e) + { + onLeaving(); + base.OnSuspending(e); + } + private bool exitConfirmed; public override bool OnExiting(ScreenExitEvent e) @@ -320,6 +339,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match return true; } + onLeaving(); client.LeaveRoom().FireAndForget(); return false; } @@ -342,6 +362,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match public override void OnResuming(ScreenTransitionEvent e) { base.OnResuming(e); + beginHandlingTrack(); if (e.Last is not MultiplayerPlayerLoader playerLoader) return; @@ -355,6 +376,43 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match client.ChangeState(MultiplayerUserState.Idle); } + private void onLeaving() + { + endHandlingTrack(); + } + + /// + /// Handles changes in the track to keep it looping while active. + /// + private void beginHandlingTrack() + { + Beatmap.BindValueChanged(applyLoopingToTrack, true); + } + + /// + /// Stops looping the current track and stops handling further changes to the track. + /// + private void endHandlingTrack() + { + Beatmap.ValueChanged -= applyLoopingToTrack; + Beatmap.Value.Track.Looping = false; + + previewTrackManager.StopAnyPlaying(this); + } + + /// + /// Invoked on changes to the beatmap to loop the track. See: . + /// + /// The beatmap change event. + private void applyLoopingToTrack(ValueChangedEvent beatmap) + { + if (!this.IsCurrentScreen()) + return; + + beatmap.NewValue.PrepareTrackForPreview(true); + music.EnsurePlayingSomething(); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing);