diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs
index b602a67baa..81c41ab628 100644
--- a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs
+++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs
@@ -43,6 +43,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup
private void updateBeatmap()
{
Beatmap.BeatmapInfo.SpecialStyle = specialStyle.Current.Value;
+ Beatmap.SaveState();
}
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs b/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs
index d8471aca1a..2889832ff1 100644
--- a/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs
@@ -49,6 +49,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Setup
private void updateBeatmap()
{
Beatmap.BeatmapInfo.StackLeniency = stackLeniency.Current.Value;
+ Beatmap.SaveState();
}
}
}
diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs
index 05474e3d39..a38089e023 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs
@@ -29,6 +29,7 @@ using osu.Game.Screens.Play;
using osu.Game.Screens.Play.PlayerSettings;
using osu.Game.Utils;
using osuTK.Input;
+using SkipOverlay = osu.Game.Screens.Play.SkipOverlay;
namespace osu.Game.Tests.Visual.Gameplay
{
@@ -56,6 +57,10 @@ namespace osu.Game.Tests.Visual.Gameplay
private readonly ChangelogOverlay changelogOverlay;
+ private double savedTrackVolume;
+ private double savedMasterVolume;
+ private bool savedMutedState;
+
public TestScenePlayerLoader()
{
AddRange(new Drawable[]
@@ -75,11 +80,7 @@ namespace osu.Game.Tests.Visual.Gameplay
}
[SetUp]
- public void Setup() => Schedule(() =>
- {
- player = null;
- audioManager.Volume.SetDefault();
- });
+ public void Setup() => Schedule(() => player = null);
///
/// Sets the input manager child to a new test player loader container instance.
@@ -98,7 +99,13 @@ namespace osu.Game.Tests.Visual.Gameplay
private void prepareBeatmap()
{
var workingBeatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
+
+ // Add intro time to test quick retry skipping (TestQuickRetry).
+ workingBeatmap.BeatmapInfo.AudioLeadIn = 60000;
+
+ // Turn on epilepsy warning to test warning display (TestEpilepsyWarning).
workingBeatmap.BeatmapInfo.EpilepsyWarning = epilepsyWarning;
+
Beatmap.Value = workingBeatmap;
foreach (var mod in SelectedMods.Value.OfType())
@@ -147,6 +154,7 @@ namespace osu.Game.Tests.Visual.Gameplay
moveMouse();
return player?.LoadState == LoadState.Ready;
});
+
AddRepeatStep("move mouse", moveMouse, 20);
AddAssert("loader still active", () => loader.IsCurrentScreen());
@@ -154,6 +162,8 @@ namespace osu.Game.Tests.Visual.Gameplay
void moveMouse()
{
+ notificationOverlay.State.Value = Visibility.Hidden;
+
InputManager.MoveMouseTo(
loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft
+ (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft)
@@ -274,6 +284,8 @@ namespace osu.Game.Tests.Visual.Gameplay
AddStep("load player", () => resetPlayer(false, beforeLoad));
AddUntilStep("wait for player", () => player?.LoadState == LoadState.Ready);
+ saveVolumes();
+
AddAssert("check for notification", () => notificationOverlay.UnreadCount.Value == 1);
AddStep("click notification", () =>
{
@@ -287,6 +299,8 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("check " + volumeName, assert);
+ restoreVolumes();
+
AddUntilStep("wait for player load", () => player.IsLoaded);
}
@@ -294,6 +308,9 @@ namespace osu.Game.Tests.Visual.Gameplay
[TestCase(false)]
public void TestEpilepsyWarning(bool warning)
{
+ saveVolumes();
+ setFullVolume();
+
AddStep("change epilepsy warning", () => epilepsyWarning = warning);
AddStep("load dummy beatmap", () => resetPlayer(false));
@@ -306,6 +323,30 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("sound volume decreased", () => Beatmap.Value.Track.AggregateVolume.Value == 0.25);
AddUntilStep("sound volume restored", () => Beatmap.Value.Track.AggregateVolume.Value == 1);
}
+
+ restoreVolumes();
+ }
+
+ [Test]
+ public void TestEpilepsyWarningEarlyExit()
+ {
+ saveVolumes();
+ setFullVolume();
+
+ AddStep("set epilepsy warning", () => epilepsyWarning = true);
+ AddStep("load dummy beatmap", () => resetPlayer(false));
+
+ AddUntilStep("wait for current", () => loader.IsCurrentScreen());
+
+ AddUntilStep("wait for epilepsy warning", () => getWarning().Alpha > 0);
+ AddUntilStep("warning is shown", () => getWarning().State.Value == Visibility.Visible);
+
+ AddStep("exit early", () => loader.Exit());
+
+ AddUntilStep("warning is hidden", () => getWarning().State.Value == Visibility.Hidden);
+ AddUntilStep("sound volume restored", () => Beatmap.Value.Track.AggregateVolume.Value == 1);
+
+ restoreVolumes();
}
[TestCase(true, 1.0, false)] // on battery, above cutoff --> no warning
@@ -336,21 +377,65 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("wait for player load", () => player.IsLoaded);
}
- [Test]
- public void TestEpilepsyWarningEarlyExit()
+ private void restoreVolumes()
{
- AddStep("set epilepsy warning", () => epilepsyWarning = true);
+ AddStep("restore previous volumes", () =>
+ {
+ audioManager.VolumeTrack.Value = savedTrackVolume;
+ audioManager.Volume.Value = savedMasterVolume;
+ volumeOverlay.IsMuted.Value = savedMutedState;
+ });
+ }
+
+ private void setFullVolume()
+ {
+ AddStep("set volumes to 100%", () =>
+ {
+ audioManager.VolumeTrack.Value = 1;
+ audioManager.Volume.Value = 1;
+ volumeOverlay.IsMuted.Value = false;
+ });
+ }
+
+ private void saveVolumes()
+ {
+ AddStep("save previous volumes", () =>
+ {
+ savedTrackVolume = audioManager.VolumeTrack.Value;
+ savedMasterVolume = audioManager.Volume.Value;
+ savedMutedState = volumeOverlay.IsMuted.Value;
+ });
+ }
+
+ [Test]
+ public void TestQuickRetry()
+ {
+ TestPlayer getCurrentPlayer() => loader.CurrentPlayer as TestPlayer;
+ bool checkSkipButtonVisible() => player.ChildrenOfType().FirstOrDefault()?.IsButtonVisible == true;
+
+ TestPlayer previousPlayer = null;
+
AddStep("load dummy beatmap", () => resetPlayer(false));
- AddUntilStep("wait for current", () => loader.IsCurrentScreen());
+ AddUntilStep("wait for current", () => getCurrentPlayer()?.IsCurrentScreen() == true);
+ AddStep("store previous player", () => previousPlayer = getCurrentPlayer());
- AddUntilStep("wait for epilepsy warning", () => getWarning().Alpha > 0);
- AddUntilStep("warning is shown", () => getWarning().State.Value == Visibility.Visible);
+ AddStep("Restart map normally", () => getCurrentPlayer().Restart());
+ AddUntilStep("wait for load", () => getCurrentPlayer()?.LoadedBeatmapSuccessfully == true);
- AddStep("exit early", () => loader.Exit());
+ AddUntilStep("restart completed", () => getCurrentPlayer() != null && getCurrentPlayer() != previousPlayer);
+ AddStep("store previous player", () => previousPlayer = getCurrentPlayer());
- AddUntilStep("warning is hidden", () => getWarning().State.Value == Visibility.Hidden);
- AddUntilStep("sound volume restored", () => Beatmap.Value.Track.AggregateVolume.Value == 1);
+ AddUntilStep("skip button visible", checkSkipButtonVisible);
+
+ AddStep("press quick retry key", () => InputManager.PressKey(Key.Tilde));
+ AddUntilStep("restart completed", () => getCurrentPlayer() != null && getCurrentPlayer() != previousPlayer);
+ AddStep("release quick retry key", () => InputManager.ReleaseKey(Key.Tilde));
+
+ AddUntilStep("wait for load", () => getCurrentPlayer()?.LoadedBeatmapSuccessfully == true);
+
+ AddUntilStep("time reached zero", () => getCurrentPlayer()?.GameplayClockContainer.CurrentTime > 0);
+ AddUntilStep("skip button not visible", () => !checkSkipButtonVisible());
}
private EpilepsyWarning getWarning() => loader.ChildrenOfType().SingleOrDefault();
diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs
index 91fa09b414..23c1eda7f7 100644
--- a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs
+++ b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs
@@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Mods
protected override TestPlayer CreateModPlayer(Ruleset ruleset)
{
var player = base.CreateModPlayer(ruleset);
- player.RestartRequested = () => restartRequested = true;
+ player.RestartRequested = _ => restartRequested = true;
return player;
}
diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs
index 9196dde73c..32b7f0b29b 100644
--- a/osu.Game/Beatmaps/BeatmapInfo.cs
+++ b/osu.Game/Beatmaps/BeatmapInfo.cs
@@ -102,6 +102,14 @@ namespace osu.Game.Beatmaps
public string OnlineMD5Hash { get; set; } = string.Empty;
+ ///
+ /// The last time of a local modification (via the editor).
+ ///
+ public DateTimeOffset? LastLocalUpdate { get; set; }
+
+ ///
+ /// The last time online metadata was applied to this beatmap.
+ ///
public DateTimeOffset? LastOnlineUpdate { get; set; }
///
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index e148016487..d736765dd9 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -94,6 +94,7 @@ namespace osu.Game.Beatmaps
var beatmapSet = new BeatmapSetInfo
{
+ DateAdded = DateTimeOffset.UtcNow,
Beatmaps =
{
new BeatmapInfo(ruleset, new BeatmapDifficulty(), metadata)
@@ -313,6 +314,7 @@ namespace osu.Game.Beatmaps
beatmapInfo.MD5Hash = stream.ComputeMD5Hash();
beatmapInfo.Hash = stream.ComputeSHA2Hash();
+ beatmapInfo.LastLocalUpdate = DateTimeOffset.Now;
beatmapInfo.Status = BeatmapOnlineStatus.LocallyModified;
AddFile(setInfo, stream, createBeatmapFilenameFromMetadata(beatmapInfo));
diff --git a/osu.Game/Database/LegacyCollectionImporter.cs b/osu.Game/Database/LegacyCollectionImporter.cs
index 4bb28bf731..6d3e3fb76a 100644
--- a/osu.Game/Database/LegacyCollectionImporter.cs
+++ b/osu.Game/Database/LegacyCollectionImporter.cs
@@ -89,7 +89,7 @@ namespace osu.Game.Database
if (existing != null)
{
- foreach (string newBeatmap in existing.BeatmapMD5Hashes)
+ foreach (string newBeatmap in collection.BeatmapMD5Hashes)
{
if (!existing.BeatmapMD5Hashes.Contains(newBeatmap))
existing.BeatmapMD5Hashes.Add(newBeatmap);
diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs
index 8099db44b1..cdaf35a1fb 100644
--- a/osu.Game/Database/RealmAccess.cs
+++ b/osu.Game/Database/RealmAccess.cs
@@ -68,8 +68,9 @@ namespace osu.Game.Database
/// 20 2022-07-21 Added LastAppliedDifficultyVersion to RulesetInfo, changed default value of BeatmapInfo.StarRating to -1.
/// 21 2022-07-27 Migrate collections to realm (BeatmapCollection).
/// 22 2022-07-31 Added ModPreset.
+ /// 23 2022-08-01 Added LastLocalUpdate to BeatmapInfo.
///
- private const int schema_version = 22;
+ private const int schema_version = 23;
///
/// Lock object which is held during sections, blocking realm retrieval during blocking periods.
diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs
index 96425e8bc8..afbb5cc018 100644
--- a/osu.Game/Screens/Edit/EditorBeatmap.cs
+++ b/osu.Game/Screens/Edit/EditorBeatmap.cs
@@ -78,7 +78,10 @@ namespace osu.Game.Screens.Edit
this.beatmapInfo = beatmapInfo ?? playableBeatmap.BeatmapInfo;
if (beatmapSkin is Skin skin)
+ {
BeatmapSkin = new EditorBeatmapSkin(skin);
+ BeatmapSkin.BeatmapSkinChanged += SaveState;
+ }
beatmapProcessor = playableBeatmap.BeatmapInfo.Ruleset.CreateInstance().CreateBeatmapProcessor(PlayableBeatmap);
diff --git a/osu.Game/Screens/Edit/Setup/DesignSection.cs b/osu.Game/Screens/Edit/Setup/DesignSection.cs
index 40bbfeaf7d..5cec730440 100644
--- a/osu.Game/Screens/Edit/Setup/DesignSection.cs
+++ b/osu.Game/Screens/Edit/Setup/DesignSection.cs
@@ -126,6 +126,8 @@ namespace osu.Game.Screens.Edit.Setup
Beatmap.BeatmapInfo.EpilepsyWarning = epilepsyWarning.Current.Value;
Beatmap.BeatmapInfo.LetterboxInBreaks = letterboxDuringBreaks.Current.Value;
Beatmap.BeatmapInfo.SamplesMatchPlaybackRate = samplesMatchPlaybackRate.Current.Value;
+
+ Beatmap.SaveState();
}
}
}
diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs
index 5ce5d05d64..ce44445683 100644
--- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs
+++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs
@@ -96,6 +96,7 @@ namespace osu.Game.Screens.Edit.Setup
Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value;
Beatmap.UpdateAllHitObjects();
+ Beatmap.SaveState();
}
}
}
diff --git a/osu.Game/Screens/Edit/Setup/MetadataSection.cs b/osu.Game/Screens/Edit/Setup/MetadataSection.cs
index 854dec2001..928e5bc3b6 100644
--- a/osu.Game/Screens/Edit/Setup/MetadataSection.cs
+++ b/osu.Game/Screens/Edit/Setup/MetadataSection.cs
@@ -87,7 +87,7 @@ namespace osu.Game.Screens.Edit.Setup
target.Current.Value = value;
updateReadOnlyState();
- updateMetadata();
+ Scheduler.AddOnce(updateMetadata);
}
private void updateReadOnlyState()
@@ -102,7 +102,7 @@ namespace osu.Game.Screens.Edit.Setup
// for now, update on commit rather than making BeatmapMetadata bindables.
// after switching database engines we can reconsider if switching to bindables is a good direction.
- updateMetadata();
+ Scheduler.AddOnce(updateMetadata);
}
private void updateMetadata()
@@ -117,6 +117,8 @@ namespace osu.Game.Screens.Edit.Setup
Beatmap.BeatmapInfo.DifficultyName = difficultyTextBox.Current.Value;
Beatmap.Metadata.Source = sourceTextBox.Current.Value;
Beatmap.Metadata.Tags = tagsTextBox.Current.Value;
+
+ Beatmap.SaveState();
}
}
}
diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs
index faa9a267ce..5f481ed00e 100644
--- a/osu.Game/Screens/Menu/IntroCircles.cs
+++ b/osu.Game/Screens/Menu/IntroCircles.cs
@@ -19,8 +19,11 @@ namespace osu.Game.Screens.Menu
protected override string BeatmapFile => "circles.osz";
+ public const double TRACK_START_DELAY_NON_THEMED = 1000;
+ private const double track_start_delay_themed = 600;
+
+ private const double delay_for_menu = 2900;
private const double delay_step_one = 2300;
- private const double delay_step_two = 600;
private Sample welcome;
@@ -44,14 +47,16 @@ namespace osu.Game.Screens.Menu
{
welcome?.Play();
+ double trackStartDelay = UsingThemedIntro ? track_start_delay_themed : TRACK_START_DELAY_NON_THEMED;
+
Scheduler.AddDelayed(delegate
{
StartTrack();
PrepareMenuLoad();
- Scheduler.AddDelayed(LoadMenu, delay_step_one);
- }, delay_step_two);
+ Scheduler.AddDelayed(LoadMenu, delay_for_menu - trackStartDelay);
+ }, trackStartDelay);
logo.ScaleTo(1);
logo.FadeIn();
diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs
index a2ecd7eacb..bf713997f7 100644
--- a/osu.Game/Screens/Menu/IntroScreen.cs
+++ b/osu.Game/Screens/Menu/IntroScreen.cs
@@ -272,11 +272,17 @@ namespace osu.Game.Screens.Menu
FadeInBackground(200);
}
- protected virtual void StartTrack()
+ protected void StartTrack()
{
- // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu.
- if (UsingThemedIntro)
- Track.Start();
+ var drawableTrack = musicController.CurrentTrack;
+
+ drawableTrack.Start();
+
+ if (!UsingThemedIntro)
+ {
+ drawableTrack.VolumeTo(0).Then()
+ .VolumeTo(1, 2000, Easing.OutQuint);
+ }
}
protected override void LogoArriving(OsuLogo logo, bool resuming)
diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs
index 6ad0350e43..4ec79b852a 100644
--- a/osu.Game/Screens/Menu/IntroTriangles.cs
+++ b/osu.Game/Screens/Menu/IntroTriangles.cs
@@ -84,9 +84,17 @@ namespace osu.Game.Screens.Menu
return;
if (!UsingThemedIntro)
+ {
+ // If the user has requested no theme, fallback to the same intro voice and delay as IntroCircles.
+ // The triangles intro voice and theme are combined which makes it impossible to use.
welcome?.Play();
+ Scheduler.AddDelayed(StartTrack, IntroCircles.TRACK_START_DELAY_NON_THEMED);
+ }
+ else
+ StartTrack();
- StartTrack();
+ // no-op for the case of themed intro, no harm in calling for both scenarios as a safety measure.
+ decoupledClock.Start();
});
}
}
@@ -99,11 +107,6 @@ namespace osu.Game.Screens.Menu
intro.Expire();
}
- protected override void StartTrack()
- {
- decoupledClock.Start();
- }
-
private class TrianglesIntroSequence : CompositeDrawable
{
private readonly OsuLogo logo;
diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs
index 51b2042d1b..6827ff04d3 100644
--- a/osu.Game/Screens/Play/Player.cs
+++ b/osu.Game/Screens/Play/Player.cs
@@ -77,7 +77,7 @@ namespace osu.Game.Screens.Play
///
protected virtual bool PauseOnFocusLost => true;
- public Action RestartRequested;
+ public Action RestartRequested;
private bool isRestarting;
@@ -267,7 +267,7 @@ namespace osu.Game.Screens.Play
FailOverlay = new FailOverlay
{
SaveReplay = prepareAndImportScore,
- OnRetry = Restart,
+ OnRetry = () => Restart(),
OnQuit = () => PerformExit(true),
},
new HotkeyExitOverlay
@@ -294,7 +294,7 @@ namespace osu.Game.Screens.Play
if (!this.IsCurrentScreen()) return;
fadeOut(true);
- Restart();
+ Restart(true);
},
});
}
@@ -371,6 +371,9 @@ namespace osu.Game.Screens.Play
IsBreakTime.BindTo(breakTracker.IsBreakTime);
IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
+
+ if (Configuration.AutomaticallySkipIntro)
+ skipIntroOverlay.SkipWhenReady();
}
protected virtual GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart) => new MasterGameplayClockContainer(beatmap, gameplayStart);
@@ -441,7 +444,7 @@ namespace osu.Game.Screens.Play
{
OnResume = Resume,
Retries = RestartCount,
- OnRetry = Restart,
+ OnRetry = () => Restart(),
OnQuit = () => PerformExit(true),
},
},
@@ -648,7 +651,8 @@ namespace osu.Game.Screens.Play
/// Restart gameplay via a parent .
/// This can be called from a child screen in order to trigger the restart process.
///
- public void Restart()
+ /// Whether a quick restart was requested (skipping intro etc.).
+ public void Restart(bool quickRestart = false)
{
if (!Configuration.AllowRestart)
return;
@@ -660,7 +664,7 @@ namespace osu.Game.Screens.Play
musicController.Stop();
sampleRestart?.Play();
- RestartRequested?.Invoke();
+ RestartRequested?.Invoke(quickRestart);
PerformExit(false);
}
@@ -840,7 +844,7 @@ namespace osu.Game.Screens.Play
failAnimationLayer.Start();
if (GameplayState.Mods.OfType().Any(m => m.RestartOnFail))
- Restart();
+ Restart(true);
return true;
}
diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs
index d11825baee..b1b0e01d80 100644
--- a/osu.Game/Screens/Play/PlayerConfiguration.cs
+++ b/osu.Game/Screens/Play/PlayerConfiguration.cs
@@ -31,5 +31,10 @@ namespace osu.Game.Screens.Play
/// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard.
///
public bool AllowSkipping { get; set; } = true;
+
+ ///
+ /// Whether the intro should be skipped by default.
+ ///
+ public bool AutomaticallySkipIntro { get; set; }
}
}
diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs
index 674490d595..e6bd1367ef 100644
--- a/osu.Game/Screens/Play/PlayerLoader.cs
+++ b/osu.Game/Screens/Play/PlayerLoader.cs
@@ -123,6 +123,8 @@ namespace osu.Game.Screens.Play
private EpilepsyWarning? epilepsyWarning;
+ private bool quickRestart;
+
[Resolved(CanBeNull = true)]
private INotificationOverlay? notificationOverlay { get; set; }
@@ -361,6 +363,7 @@ namespace osu.Game.Screens.Play
return;
CurrentPlayer = createPlayer();
+ CurrentPlayer.Configuration.AutomaticallySkipIntro = quickRestart;
CurrentPlayer.RestartCount = restartCount++;
CurrentPlayer.RestartRequested = restartRequested;
@@ -375,8 +378,9 @@ namespace osu.Game.Screens.Play
{
}
- private void restartRequested()
+ private void restartRequested(bool quickRestartRequested)
{
+ quickRestart = quickRestartRequested;
hideOverlays = true;
ValidForResume = true;
}
diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs
index 687705ff1b..5c9a706549 100644
--- a/osu.Game/Screens/Play/SkipOverlay.cs
+++ b/osu.Game/Screens/Play/SkipOverlay.cs
@@ -39,10 +39,13 @@ namespace osu.Game.Screens.Play
private double displayTime;
private bool isClickable;
+ private bool skipQueued;
[Resolved]
private IGameplayClock gameplayClock { get; set; }
+ internal bool IsButtonVisible => fadeContainer.State == Visibility.Visible && buttonContainer.State.Value == Visibility.Visible;
+
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
///
@@ -123,6 +126,20 @@ namespace osu.Game.Screens.Play
displayTime = gameplayClock.CurrentTime;
fadeContainer.TriggerShow();
+
+ if (skipQueued)
+ {
+ Scheduler.AddDelayed(() => button.TriggerClick(), 200);
+ skipQueued = false;
+ }
+ }
+
+ public void SkipWhenReady()
+ {
+ if (IsLoaded)
+ button.TriggerClick();
+ else
+ skipQueued = true;
}
protected override void Update()
diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs
index c530febcae..226216b0f0 100644
--- a/osu.Game/Screens/Ranking/ResultsScreen.cs
+++ b/osu.Game/Screens/Ranking/ResultsScreen.cs
@@ -177,7 +177,7 @@ namespace osu.Game.Screens.Ranking
{
if (!this.IsCurrentScreen()) return;
- player?.Restart();
+ player?.Restart(true);
},
});
}