diff --git a/osu.Game/Graphics/Carousel/Carousel.cs b/osu.Game/Graphics/Carousel/Carousel.cs index 16e30b7b52..1277dc993f 100644 --- a/osu.Game/Graphics/Carousel/Carousel.cs +++ b/osu.Game/Graphics/Carousel/Carousel.cs @@ -356,11 +356,11 @@ namespace osu.Game.Graphics.Carousel { switch (e.Key) { + // this is a special hard-coded case to allow activating item with modifier keys pressed + // (e.g. press Ctrl+Enter to start beatmap with autoplay mod selected). + // We can't rely on GlobalAction.Select as it only responds to pressing the key without any modifiers. case Key.Enter: case Key.KeypadEnter: - // this is a special hard-coded case to allow activating item with modifier keys pressed - // (e.g. press Ctrl+Enter to start beatmap with autoplay mod selected). - // We can't rely on GlobalAction.Select for that as it only responds to pressing the key without any modifiers. if (currentKeyboardSelection.CarouselItem != null) Activate(currentKeyboardSelection.CarouselItem); return true; diff --git a/osu.Game/Screens/SelectV2/SoloSongSelect.cs b/osu.Game/Screens/SelectV2/SoloSongSelect.cs index 7e26fc1e32..654d5fb78a 100644 --- a/osu.Game/Screens/SelectV2/SoloSongSelect.cs +++ b/osu.Game/Screens/SelectV2/SoloSongSelect.cs @@ -2,11 +2,18 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Beatmaps; +using osu.Game.Localisation; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Edit; using osu.Game.Screens.Play; +using osu.Game.Utils; namespace osu.Game.Screens.SelectV2 { @@ -26,17 +33,92 @@ namespace osu.Game.Screens.SelectV2 this.Push(new EditorLoader()); } + private PlayerLoader? playerLoader; + private IReadOnlyList? modsAtGameplayStart; + + [Resolved] + private INotificationOverlay? notifications { get; set; } + protected override bool OnStart() { - this.Push(new PlayerLoaderV2(() => new SoloPlayer())); + if (playerLoader != null) return false; + + modsAtGameplayStart = Mods.Value; + + // Ctrl+Enter should start map with autoplay enabled. + if (GetContainingInputManager()?.CurrentState?.Keyboard.ControlPressed == true) + { + var autoInstance = getAutoplayMod(); + + if (autoInstance == null) + { + notifications?.Post(new SimpleNotification + { + Text = NotificationsStrings.NoAutoplayMod + }); + return false; + } + + var mods = Mods.Value.Append(autoInstance).ToArray(); + + if (!ModUtils.CheckCompatibleSet(mods, out var invalid)) + mods = mods.Except(invalid).Append(autoInstance).ToArray(); + + Mods.Value = mods; + } + + this.Push(playerLoader = new PlayerLoader(createPlayer)); + return true; + + Player createPlayer() + { + Player player; + + var replayGeneratingMod = Mods.Value.OfType().FirstOrDefault(); + + if (replayGeneratingMod != null) + { + player = new ReplayPlayer((beatmap, mods) => replayGeneratingMod.CreateScoreFromReplayData(beatmap, mods)); + } + else + { + player = new SoloPlayer(); + } + + return player; + } + } + + public override void OnResuming(ScreenTransitionEvent e) + { + base.OnResuming(e); + revertMods(); + } + + public override bool OnExiting(ScreenExitEvent e) + { + if (base.OnExiting(e)) + return true; + + revertMods(); return false; } - private partial class PlayerLoaderV2 : PlayerLoader + private ModAutoplay? getAutoplayMod() => Ruleset.Value.CreateInstance().GetAutoplayMod(); + + private void revertMods() + { + if (playerLoader == null) return; + + Mods.Value = modsAtGameplayStart; + playerLoader = null; + } + + private partial class PlayerLoader : Screens.Play.PlayerLoader { public override bool ShowFooter => true; - public PlayerLoaderV2(Func createPlayer) + public PlayerLoader(Func createPlayer) : base(createPlayer) { }