diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index 39b3c23ddd..367f612dc8 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -51,7 +51,12 @@ namespace osu.Game.Beatmaps [JsonProperty(@"tags")] public string Tags { get; set; } + /// + /// The time in milliseconds to begin playing the track for preview purposes. + /// If -1, the track should begin playing at 40% of its length. + /// public int PreviewTime { get; set; } + public string AudioFile { get; set; } public string BackgroundFile { get; set; } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 30382c444f..aab8ff6bd6 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -266,6 +266,26 @@ namespace osu.Game.Beatmaps [NotNull] public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000); + /// + /// Reads the correct track restart point from beatmap metadata and sets looping to enabled. + /// + public void PrepareTrackForPreviewLooping() + { + Track.Looping = true; + Track.RestartPoint = Metadata.PreviewTime; + + if (Track.RestartPoint == -1) + { + if (!Track.IsLoaded) + { + // force length to be populated (https://github.com/ppy/osu-framework/issues/4202) + Track.Seek(Track.CurrentTime); + } + + Track.RestartPoint = 0.4f * Track.Length; + } + } + /// /// Transfer a valid audio track into this working beatmap. Used as an optimisation to avoid reload / track swap /// across difficulties in the same beatmap set. diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 71b83d4aab..71f3b60026 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -168,7 +168,7 @@ namespace osu.Game.Screens.Menu { // 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.Restart(); + Track.Start(); } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 97fd58318b..424e6d2cd5 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -179,14 +179,15 @@ namespace osu.Game.Screens.Menu base.OnEntering(last); buttons.FadeInFromZero(500); - var metadata = Beatmap.Value.Metadata; - if (last is IntroScreen && musicController.TrackLoaded) { - if (!musicController.CurrentTrack.IsRunning) + var track = musicController.CurrentTrack; + + // presume the track is the current beatmap's track. not sure how correct this assumption is but it has worked until now. + if (!track.IsRunning) { - musicController.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.CurrentTrack.Length); - musicController.CurrentTrack.Start(); + Beatmap.Value.PrepareTrackForPreviewLooping(); + track.Restart(); } } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index e755f8c405..86422085a1 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -173,9 +173,7 @@ namespace osu.Game.Screens.OnlinePlay.Match if (track != null) { - track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - track.Looping = true; - + Beatmap.Value.PrepareTrackForPreviewLooping(); music?.EnsurePlayingSomething(); } } @@ -185,10 +183,7 @@ namespace osu.Game.Screens.OnlinePlay.Match var track = Beatmap?.Value?.Track; if (track != null) - { track.Looping = false; - track.RestartPoint = 0; - } } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index edbab083cd..b7f7c40539 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -648,8 +648,9 @@ namespace osu.Game.Screens.Select { Debug.Assert(!isHandlingLooping); - music.CurrentTrack.Looping = isHandlingLooping = true; + isHandlingLooping = true; + ensureTrackLooping(Beatmap.Value, TrackChangeDirection.None); music.TrackChanged += ensureTrackLooping; } @@ -665,7 +666,7 @@ namespace osu.Game.Screens.Select } private void ensureTrackLooping(WorkingBeatmap beatmap, TrackChangeDirection changeDirection) - => music.CurrentTrack.Looping = true; + => beatmap.PrepareTrackForPreviewLooping(); public override bool OnBackButton() { @@ -719,8 +720,6 @@ namespace osu.Game.Screens.Select bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; - track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - if (!track.IsRunning && (music.UserPauseRequested != true || isNewTrack)) music.Play(true);