1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-21 23:59:16 +08:00

Allow screens to change the ability to interact with the global track

This commit is contained in:
Dean Herbert 2023-07-25 20:00:18 +09:00
parent 157b1f301b
commit 6146f30541
5 changed files with 53 additions and 21 deletions

View File

@ -30,20 +30,14 @@ namespace osu.Game.Overlays.Music
[Resolved] [Resolved]
private OnScreenDisplay? onScreenDisplay { get; set; } private OnScreenDisplay? onScreenDisplay { get; set; }
[Resolved]
private OsuGame game { get; set; } = null!;
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat) if (e.Repeat || !musicController.AllowTrackControl.Value)
return false; return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.MusicPlay: case GlobalAction.MusicPlay:
if (game.LocalUserPlaying.Value)
return false;
// use previous state as TogglePause may not update the track's state immediately (state update is run on the audio thread see https://github.com/ppy/osu/issues/9880#issuecomment-674668842) // use previous state as TogglePause may not update the track's state immediately (state update is run on the audio thread see https://github.com/ppy/osu/issues/9880#issuecomment-674668842)
bool wasPlaying = musicController.IsPlaying; bool wasPlaying = musicController.IsPlaying;

View File

@ -40,6 +40,11 @@ namespace osu.Game.Overlays
/// </summary> /// </summary>
public bool UserPauseRequested { get; private set; } public bool UserPauseRequested { get; private set; }
/// <summary>
/// Whether control of the global track should be allowed.
/// </summary>
public readonly BindableBool AllowTrackControl = new BindableBool(true);
/// <summary> /// <summary>
/// Fired when the global <see cref="WorkingBeatmap"/> has changed. /// Fired when the global <see cref="WorkingBeatmap"/> has changed.
/// Includes direction information for display purposes. /// Includes direction information for display purposes.
@ -92,8 +97,10 @@ namespace osu.Game.Overlays
seekDelegate?.Cancel(); seekDelegate?.Cancel();
seekDelegate = Schedule(() => seekDelegate = Schedule(() =>
{ {
if (!beatmap.Disabled) if (beatmap.Disabled || !AllowTrackControl.Value)
CurrentTrack.Seek(position); return;
CurrentTrack.Seek(position);
}); });
} }
@ -107,7 +114,7 @@ namespace osu.Game.Overlays
if (CurrentTrack.IsDummyDevice || beatmap.Value.BeatmapSetInfo.DeletePending) if (CurrentTrack.IsDummyDevice || beatmap.Value.BeatmapSetInfo.DeletePending)
{ {
if (beatmap.Disabled) if (beatmap.Disabled || !AllowTrackControl.Value)
return; return;
Logger.Log($"{nameof(MusicController)} skipping next track to {nameof(EnsurePlayingSomething)}"); Logger.Log($"{nameof(MusicController)} skipping next track to {nameof(EnsurePlayingSomething)}");
@ -132,6 +139,9 @@ namespace osu.Game.Overlays
/// <returns>Whether the operation was successful.</returns> /// <returns>Whether the operation was successful.</returns>
public bool Play(bool restart = false, bool requestedByUser = false) public bool Play(bool restart = false, bool requestedByUser = false)
{ {
if (requestedByUser && !AllowTrackControl.Value)
return false;
if (requestedByUser) if (requestedByUser)
UserPauseRequested = false; UserPauseRequested = false;
@ -153,6 +163,9 @@ namespace osu.Game.Overlays
/// </param> /// </param>
public void Stop(bool requestedByUser = false) public void Stop(bool requestedByUser = false)
{ {
if (requestedByUser && !AllowTrackControl.Value)
return;
UserPauseRequested |= requestedByUser; UserPauseRequested |= requestedByUser;
if (CurrentTrack.IsRunning) if (CurrentTrack.IsRunning)
CurrentTrack.StopAsync(); CurrentTrack.StopAsync();
@ -164,6 +177,9 @@ namespace osu.Game.Overlays
/// <returns>Whether the operation was successful.</returns> /// <returns>Whether the operation was successful.</returns>
public bool TogglePause() public bool TogglePause()
{ {
if (!AllowTrackControl.Value)
return false;
if (CurrentTrack.IsRunning) if (CurrentTrack.IsRunning)
Stop(true); Stop(true);
else else
@ -189,7 +205,7 @@ namespace osu.Game.Overlays
/// <returns>The <see cref="PreviousTrackResult"/> that indicate the decided action.</returns> /// <returns>The <see cref="PreviousTrackResult"/> that indicate the decided action.</returns>
private PreviousTrackResult prev() private PreviousTrackResult prev()
{ {
if (beatmap.Disabled) if (beatmap.Disabled || !AllowTrackControl.Value)
return PreviousTrackResult.None; return PreviousTrackResult.None;
double currentTrackPosition = CurrentTrack.CurrentTime; double currentTrackPosition = CurrentTrack.CurrentTime;
@ -229,7 +245,7 @@ namespace osu.Game.Overlays
private bool next() private bool next()
{ {
if (beatmap.Disabled) if (beatmap.Disabled || !AllowTrackControl.Value)
return false; return false;
queuedDirection = TrackChangeDirection.Next; queuedDirection = TrackChangeDirection.Next;
@ -352,7 +368,7 @@ namespace osu.Game.Overlays
private void onTrackCompleted() private void onTrackCompleted()
{ {
if (!CurrentTrack.Looping && !beatmap.Disabled) if (!CurrentTrack.Looping && !beatmap.Disabled && AllowTrackControl.Value)
NextTrack(); NextTrack();
} }

View File

@ -68,6 +68,8 @@ namespace osu.Game.Overlays
[Resolved] [Resolved]
private OsuColour colours { get; set; } private OsuColour colours { get; set; }
private Bindable<bool> allowTrackControl;
public NowPlayingOverlay() public NowPlayingOverlay()
{ {
Width = 400; Width = 400;
@ -220,8 +222,10 @@ namespace osu.Game.Overlays
{ {
base.LoadComplete(); base.LoadComplete();
beatmap.BindDisabledChanged(_ => Scheduler.AddOnce(beatmapDisabledChanged)); beatmap.BindDisabledChanged(_ => Scheduler.AddOnce(updateEnabledStates));
beatmapDisabledChanged();
allowTrackControl = musicController.AllowTrackControl.GetBoundCopy();
allowTrackControl.BindValueChanged(_ => Scheduler.AddOnce(updateEnabledStates), true);
musicController.TrackChanged += trackChanged; musicController.TrackChanged += trackChanged;
trackChanged(beatmap.Value); trackChanged(beatmap.Value);
@ -334,16 +338,18 @@ namespace osu.Game.Overlays
}; };
} }
private void beatmapDisabledChanged() private void updateEnabledStates()
{ {
bool disabled = beatmap.Disabled; bool beatmapDisabled = beatmap.Disabled;
bool trackControlDisabled = !musicController.AllowTrackControl.Value;
if (disabled) if (beatmapDisabled || trackControlDisabled)
playlist?.Hide(); playlist?.Hide();
prevButton.Enabled.Value = !disabled; prevButton.Enabled.Value = !beatmapDisabled && !trackControlDisabled;
nextButton.Enabled.Value = !disabled; nextButton.Enabled.Value = !beatmapDisabled && !trackControlDisabled;
playlistButton.Enabled.Value = !disabled; playlistButton.Enabled.Value = !beatmapDisabled && !trackControlDisabled;
playButton.Enabled.Value = !trackControlDisabled;
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -69,6 +69,12 @@ namespace osu.Game.Screens
/// </summary> /// </summary>
bool? ApplyModTrackAdjustments { get; } bool? ApplyModTrackAdjustments { get; }
/// <summary>
/// Whether control of the global track should be allowed via the music controller / now playing overlay.
/// A <see langword="null"/> value means that the parent screen's value of this setting will be used.
/// </summary>
bool? AllowGlobalTrackControl { get; }
/// <summary> /// <summary>
/// Invoked when the back button has been pressed to close any overlays before exiting this <see cref="IOsuScreen"/>. /// Invoked when the back button has been pressed to close any overlays before exiting this <see cref="IOsuScreen"/>.
/// </summary> /// </summary>

View File

@ -87,6 +87,8 @@ namespace osu.Game.Screens
public virtual bool? ApplyModTrackAdjustments => null; public virtual bool? ApplyModTrackAdjustments => null;
public virtual bool? AllowGlobalTrackControl => null;
public Bindable<WorkingBeatmap> Beatmap { get; private set; } public Bindable<WorkingBeatmap> Beatmap { get; private set; }
public Bindable<RulesetInfo> Ruleset { get; private set; } public Bindable<RulesetInfo> Ruleset { get; private set; }
@ -95,6 +97,8 @@ namespace osu.Game.Screens
private OsuScreenDependencies screenDependencies; private OsuScreenDependencies screenDependencies;
private bool? globalMusicControlStateAtSuspend;
private bool? modTrackAdjustmentStateAtSuspend; private bool? modTrackAdjustmentStateAtSuspend;
internal void CreateLeasedDependencies(IReadOnlyDependencyContainer dependencies) => createDependencies(dependencies); internal void CreateLeasedDependencies(IReadOnlyDependencyContainer dependencies) => createDependencies(dependencies);
@ -180,6 +184,8 @@ namespace osu.Game.Screens
// in such a case there's no need to restore this value. // in such a case there's no need to restore this value.
if (modTrackAdjustmentStateAtSuspend != null) if (modTrackAdjustmentStateAtSuspend != null)
musicController.ApplyModTrackAdjustments = modTrackAdjustmentStateAtSuspend.Value; musicController.ApplyModTrackAdjustments = modTrackAdjustmentStateAtSuspend.Value;
if (globalMusicControlStateAtSuspend != null)
musicController.AllowTrackControl.Value = globalMusicControlStateAtSuspend.Value;
base.OnResuming(e); base.OnResuming(e);
} }
@ -189,6 +195,7 @@ namespace osu.Game.Screens
base.OnSuspending(e); base.OnSuspending(e);
modTrackAdjustmentStateAtSuspend = musicController.ApplyModTrackAdjustments; modTrackAdjustmentStateAtSuspend = musicController.ApplyModTrackAdjustments;
globalMusicControlStateAtSuspend = musicController.AllowTrackControl.Value;
onSuspendingLogo(); onSuspendingLogo();
} }
@ -200,6 +207,9 @@ namespace osu.Game.Screens
if (ApplyModTrackAdjustments != null) if (ApplyModTrackAdjustments != null)
musicController.ApplyModTrackAdjustments = ApplyModTrackAdjustments.Value; musicController.ApplyModTrackAdjustments = ApplyModTrackAdjustments.Value;
if (AllowGlobalTrackControl != null)
musicController.AllowTrackControl.Value = AllowGlobalTrackControl.Value;
if (backgroundStack?.Push(ownedBackground = CreateBackground()) != true) if (backgroundStack?.Push(ownedBackground = CreateBackground()) != true)
{ {
// If the constructed instance was not actually pushed to the background stack, we don't want to track it unnecessarily. // If the constructed instance was not actually pushed to the background stack, we don't want to track it unnecessarily.