From 6e42b8219c4510b856923aa08712c50dbf37fa87 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Aug 2020 21:53:00 +0900 Subject: [PATCH 01/86] Move track to MusicController, compiles --- .../TestSceneHoldNoteInput.cs | 2 +- .../TestSceneOutOfOrderHits.cs | 2 +- .../TestSceneSliderInput.cs | 2 +- .../TestSceneSliderSnaking.cs | 15 +- .../TestSceneSpinnerRotation.cs | 13 +- .../Skinning/TestSceneDrawableTaikoMascot.cs | 4 +- .../Skinning/TestSceneTaikoPlayfield.cs | 2 +- .../Skins/TestSceneBeatmapSkinResources.cs | 3 +- .../Visual/Editing/TimelineTestScene.cs | 11 +- .../TestSceneCompletionCancellation.cs | 15 +- .../Gameplay/TestSceneGameplayRewinding.cs | 15 +- .../TestSceneNightcoreBeatContainer.cs | 4 +- .../Visual/Gameplay/TestScenePause.cs | 2 +- .../Visual/Gameplay/TestScenePlayerLoader.cs | 6 +- .../Visual/Gameplay/TestSceneStoryboard.cs | 10 +- .../Visual/Menus/TestSceneIntroWelcome.cs | 7 +- .../Navigation/TestSceneScreenNavigation.cs | 23 +- .../TestSceneBeatSyncedContainer.cs | 5 +- .../TestSceneNowPlayingOverlay.cs | 4 +- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 16 -- osu.Game/Beatmaps/IWorkingBeatmap.cs | 5 - osu.Game/Beatmaps/WorkingBeatmap.cs | 22 +- .../Containers/BeatSyncedContainer.cs | 16 +- osu.Game/OsuGame.cs | 23 +- osu.Game/OsuGameBase.cs | 10 - osu.Game/Overlays/Music/PlaylistOverlay.cs | 10 +- osu.Game/Overlays/MusicController.cs | 221 ++++++++++++++++-- osu.Game/Overlays/NowPlayingOverlay.cs | 10 +- osu.Game/Rulesets/Mods/IApplicableToTrack.cs | 2 +- osu.Game/Rulesets/Mods/ModDaycore.cs | 6 +- osu.Game/Rulesets/Mods/ModNightcore.cs | 6 +- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 4 +- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 4 +- .../Edit/Components/BottomBarContainer.cs | 2 - .../Edit/Components/PlaybackControl.cs | 8 +- .../Timelines/Summary/Parts/MarkerPart.cs | 5 +- .../Timelines/Summary/Parts/TimelinePart.cs | 8 +- .../Compose/Components/Timeline/Timeline.cs | 34 +-- .../Timeline/TimelineTickDisplay.cs | 7 +- osu.Game/Screens/Edit/Editor.cs | 8 +- osu.Game/Screens/Edit/EditorClock.cs | 22 +- osu.Game/Screens/Menu/IntroScreen.cs | 8 +- osu.Game/Screens/Menu/IntroTriangles.cs | 2 +- osu.Game/Screens/Menu/IntroWelcome.cs | 6 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 12 +- osu.Game/Screens/Menu/MainMenu.cs | 16 +- osu.Game/Screens/Menu/OsuLogo.cs | 9 +- .../Multi/Match/Components/ReadyButton.cs | 6 +- osu.Game/Screens/Multi/Multiplayer.cs | 23 +- osu.Game/Screens/Play/FailAnimation.cs | 12 +- .../Screens/Play/GameplayClockContainer.cs | 46 +--- osu.Game/Screens/Select/SongSelect.cs | 34 ++- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 - osu.Game/Tests/Visual/EditorClockTestScene.cs | 2 +- osu.Game/Tests/Visual/OsuTestScene.cs | 8 +- .../Visual/RateAdjustedBeatmapTestScene.cs | 2 +- 57 files changed, 438 insertions(+), 346 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 95072cf4f8..c3e0c277a0 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -343,7 +343,7 @@ namespace osu.Game.Rulesets.Mania.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs index 854626d362..dc7e59b40d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs @@ -385,7 +385,7 @@ namespace osu.Game.Rulesets.Osu.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index b543b6fa94..2dffcfeabb 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -366,7 +366,7 @@ namespace osu.Game.Rulesets.Osu.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs index a69646507a..cd46e8c545 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs @@ -22,7 +22,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Storyboards; using osuTK; -using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; namespace osu.Game.Rulesets.Osu.Tests { @@ -32,8 +31,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Resolved] private AudioManager audioManager { get; set; } - private TrackVirtualManual track; - protected override bool Autoplay => autoplay; private bool autoplay; @@ -44,11 +41,7 @@ namespace osu.Game.Rulesets.Osu.Tests private const double fade_in_modifier = -1200; protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) - { - var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); - track = (TrackVirtualManual)working.Track; - return working; - } + => new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); [BackgroundDependencyLoader] private void load(RulesetConfigCache configCache) @@ -72,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep("enable autoplay", () => autoplay = true); base.SetUpSteps(); - AddUntilStep("wait for track to start running", () => track.IsRunning); + AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); double startTime = hitObjects[sliderIndex].StartTime; retrieveDrawableSlider(sliderIndex); @@ -97,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep("have autoplay", () => autoplay = true); base.SetUpSteps(); - AddUntilStep("wait for track to start running", () => track.IsRunning); + AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); double startTime = hitObjects[sliderIndex].StartTime; retrieveDrawableSlider(sliderIndex); @@ -201,7 +194,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void addSeekStep(double time) { - AddStep($"seek to {time}", () => track.Seek(time)); + AddStep($"seek to {time}", () => MusicController.SeekTo(time)); AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index b46964e8b7..105e19a73c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -24,7 +24,6 @@ using osu.Game.Scoring; using osu.Game.Storyboards; using osu.Game.Tests.Visual; using osuTK; -using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; namespace osu.Game.Rulesets.Osu.Tests { @@ -33,18 +32,12 @@ namespace osu.Game.Rulesets.Osu.Tests [Resolved] private AudioManager audioManager { get; set; } - private TrackVirtualManual track; - protected override bool Autoplay => true; protected override TestPlayer CreatePlayer(Ruleset ruleset) => new ScoreExposedPlayer(); protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) - { - var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); - track = (TrackVirtualManual)working.Track; - return working; - } + => new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); private DrawableSpinner drawableSpinner; private SpriteIcon spinnerSymbol => drawableSpinner.ChildrenOfType().Single(); @@ -54,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Tests { base.SetUpSteps(); - AddUntilStep("wait for track to start running", () => track.IsRunning); + AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)Player.DrawableRuleset.Playfield.AllHitObjects.First()); } @@ -198,7 +191,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void addSeekStep(double time) { - AddStep($"seek to {time}", () => track.Seek(time)); + AddStep($"seek to {time}", () => MusicController.SeekTo(time)); AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); } diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs index 47d8a5c012..ba5aef5968 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs @@ -175,11 +175,11 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning private void createDrawableRuleset() { - AddUntilStep("wait for beatmap to be loaded", () => Beatmap.Value.Track.IsLoaded); + AddUntilStep("wait for beatmap to be loaded", () => MusicController.TrackLoaded); AddStep("create drawable ruleset", () => { - Beatmap.Value.Track.Start(); + MusicController.Play(true); SetContents(() => { diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs index 7b7e2c43d1..5c54393fb8 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }); - Beatmap.Value.Track.Start(); + MusicController.Play(true); }); AddStep("Load playfield", () => SetContents(() => new TaikoPlayfield(new ControlPointInfo()) diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index 4d3b73fb32..1a19326ac4 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -3,7 +3,6 @@ using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -32,6 +31,6 @@ namespace osu.Game.Tests.Skins public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => beatmap.Skin.GetSample(new SampleInfo("sample")) != null); [Test] - public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => !(beatmap.Track is TrackVirtual)); + public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => !MusicController.IsDummyDevice); } } diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index fdb8781563..5d6136d9fb 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -3,12 +3,11 @@ using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; @@ -65,10 +64,10 @@ namespace osu.Game.Tests.Visual.Editing private readonly Drawable marker; [Resolved] - private IBindable beatmap { get; set; } + private EditorClock editorClock { get; set; } [Resolved] - private EditorClock editorClock { get; set; } + private MusicController musicController { get; set; } public AudioVisualiser() { @@ -94,8 +93,8 @@ namespace osu.Game.Tests.Visual.Editing { base.Update(); - if (beatmap.Value.Track.IsLoaded) - marker.X = (float)(editorClock.CurrentTime / beatmap.Value.Track.Length); + if (musicController.TrackLoaded) + marker.X = (float)(editorClock.CurrentTime / musicController.TrackLength); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs index 79275d70a7..b39cfc3699 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Framework.Timing; @@ -18,8 +17,6 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneCompletionCancellation : OsuPlayerTestScene { - private Track track; - [Resolved] private AudioManager audio { get; set; } @@ -34,7 +31,7 @@ namespace osu.Game.Tests.Visual.Gameplay base.SetUpSteps(); // Ensure track has actually running before attempting to seek - AddUntilStep("wait for track to start running", () => track.IsRunning); + AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); } [Test] @@ -73,13 +70,13 @@ namespace osu.Game.Tests.Visual.Gameplay private void complete() { - AddStep("seek to completion", () => track.Seek(5000)); + AddStep("seek to completion", () => MusicController.SeekTo(5000)); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); } private void cancel() { - AddStep("rewind to cancel", () => track.Seek(4000)); + AddStep("rewind to cancel", () => MusicController.SeekTo(4000)); AddUntilStep("completion cleared by processor", () => !Player.ScoreProcessor.HasCompleted.Value); } @@ -91,11 +88,7 @@ namespace osu.Game.Tests.Visual.Gameplay } protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) - { - var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audio); - track = working.Track; - return working; - } + => new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audio); protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 2a119f5199..6bdc65078a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -5,10 +5,10 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Storyboards; @@ -21,19 +21,16 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private AudioManager audioManager { get; set; } - private Track track; + [Resolved] + private MusicController musicController { get; set; } protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) - { - var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); - track = working.Track; - return working; - } + => new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); [Test] public void TestNoJudgementsOnRewind() { - AddUntilStep("wait for track to start running", () => track.IsRunning); + AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); addSeekStep(3000); AddAssert("all judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7)); @@ -46,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void addSeekStep(double time) { - AddStep($"seek to {time}", () => track.Seek(time)); + AddStep($"seek to {time}", () => MusicController.SeekTo(time)); // Allow a few frames of lenience AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs index 951ee1489d..ce99d85e92 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs @@ -19,8 +19,8 @@ namespace osu.Game.Tests.Visual.Gameplay Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - Beatmap.Value.Track.Start(); - Beatmap.Value.Track.Seek(Beatmap.Value.Beatmap.HitObjects.First().StartTime - 1000); + MusicController.Play(true); + MusicController.SeekTo(Beatmap.Value.Beatmap.HitObjects.First().StartTime - 1000); Add(new ModNightcore.NightcoreBeatContainer()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 420bf29429..8f14de1578 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -288,7 +288,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void confirmNoTrackAdjustments() { - AddAssert("track has no adjustments", () => Beatmap.Value.Track.AggregateFrequency.Value == 1); + AddAssert("track has no adjustments", () => MusicController.AggregateFrequency.Value == 1); } private void restart() => AddStep("restart", () => Player.Restart()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 4c73065087..2f86db1b25 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); foreach (var mod in SelectedMods.Value.OfType()) - mod.ApplyToTrack(Beatmap.Value.Track); + mod.ApplyToTrack(MusicController); InputManager.Child = container = new TestPlayerLoaderContainer( loader = new TestPlayerLoader(() => @@ -77,12 +77,12 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("load dummy beatmap", () => ResetPlayer(false, () => SelectedMods.Value = new[] { new OsuModNightcore() })); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddAssert("mod rate applied", () => Beatmap.Value.Track.Rate != 1); + AddAssert("mod rate applied", () => MusicController.Rate != 1); AddStep("exit loader", () => loader.Exit()); AddUntilStep("wait for not current", () => !loader.IsCurrentScreen()); AddAssert("player did not load", () => !player.IsLoaded); AddUntilStep("player disposed", () => loader.DisposalTask?.IsCompleted == true); - AddAssert("mod rate still applied", () => Beatmap.Value.Track.Rate != 1); + AddAssert("mod rate still applied", () => MusicController.Rate != 1); } [Test] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index 9f1492a25f..a4b558fce2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -87,11 +87,9 @@ namespace osu.Game.Tests.Visual.Gameplay private void restart() { - var track = Beatmap.Value.Track; - - track.Reset(); + MusicController.Reset(); loadStoryboard(Beatmap.Value); - track.Start(); + MusicController.Play(true); } private void loadStoryboard(WorkingBeatmap working) @@ -106,7 +104,7 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard.Passing = false; storyboardContainer.Add(storyboard); - decoupledClock.ChangeSource(working.Track); + decoupledClock.ChangeSource(musicController.GetTrackClock()); } private void loadStoryboardNoVideo() @@ -129,7 +127,7 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard = sb.CreateDrawable(Beatmap.Value); storyboardContainer.Add(storyboard); - decoupledClock.ChangeSource(Beatmap.Value.Track); + decoupledClock.ChangeSource(musicController.GetTrackClock()); } } } diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs index 8f20e38494..36f98b7a0c 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; -using osu.Framework.Audio.Track; using osu.Framework.Screens; using osu.Game.Screens.Menu; @@ -15,11 +14,9 @@ namespace osu.Game.Tests.Visual.Menus public TestSceneIntroWelcome() { - AddUntilStep("wait for load", () => getTrack() != null); + AddUntilStep("wait for load", () => MusicController.TrackLoaded); - AddAssert("check if menu music loops", () => getTrack().Looping); + AddAssert("check if menu music loops", () => MusicController.Looping); } - - private Track getTrack() => (IntroStack?.CurrentScreen as MainMenu)?.Track; } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 8ccaca8630..455b7e56e6 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -4,7 +4,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -46,7 +45,6 @@ namespace osu.Game.Tests.Visual.Navigation Player player = null; WorkingBeatmap beatmap() => Game.Beatmap.Value; - Track track() => beatmap().Track; PushAndConfirm(() => new TestSongSelect()); @@ -62,30 +60,27 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null); AddUntilStep("wait for fail", () => player.HasFailed); - AddUntilStep("wait for track stop", () => !track().IsRunning); - AddAssert("Ensure time before preview point", () => track().CurrentTime < beatmap().Metadata.PreviewTime); + AddUntilStep("wait for track stop", () => !MusicController.IsPlaying); + AddAssert("Ensure time before preview point", () => MusicController.CurrentTrackTime < beatmap().Metadata.PreviewTime); pushEscape(); - AddUntilStep("wait for track playing", () => track().IsRunning); - AddAssert("Ensure time wasn't reset to preview point", () => track().CurrentTime < beatmap().Metadata.PreviewTime); + AddUntilStep("wait for track playing", () => MusicController.IsPlaying); + AddAssert("Ensure time wasn't reset to preview point", () => MusicController.CurrentTrackTime < beatmap().Metadata.PreviewTime); } [Test] public void TestMenuMakesMusic() { - WorkingBeatmap beatmap() => Game.Beatmap.Value; - Track track() => beatmap().Track; - TestSongSelect songSelect = null; PushAndConfirm(() => songSelect = new TestSongSelect()); - AddUntilStep("wait for no track", () => track() is TrackVirtual); + AddUntilStep("wait for no track", () => MusicController.IsDummyDevice); AddStep("return to menu", () => songSelect.Exit()); - AddUntilStep("wait for track", () => !(track() is TrackVirtual) && track().IsRunning); + AddUntilStep("wait for track", () => !MusicController.IsDummyDevice && MusicController.IsPlaying); } [Test] @@ -140,12 +135,12 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded); AddStep("Seek close to end", () => { - Game.MusicController.SeekTo(Game.Beatmap.Value.Track.Length - 1000); - Game.Beatmap.Value.Track.Completed += () => trackCompleted = true; + Game.MusicController.SeekTo(MusicController.TrackLength - 1000); + // MusicController.Completed += () => trackCompleted = true; }); AddUntilStep("Track was completed", () => trackCompleted); - AddUntilStep("Track was restarted", () => Game.Beatmap.Value.Track.IsRunning); + AddUntilStep("Track was restarted", () => MusicController.IsPlaying); } private void pushEscape() => diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index dd5ceec739..f3fef8c355 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -71,6 +71,9 @@ namespace osu.Game.Tests.Visual.UserInterface private readonly Box flashLayer; + [Resolved] + private MusicController musicController { get; set; } + public BeatContainer() { RelativeSizeAxes = Axes.X; @@ -165,7 +168,7 @@ namespace osu.Game.Tests.Visual.UserInterface if (timingPoints.Count == 0) return 0; if (timingPoints[^1] == current) - return (int)Math.Ceiling((Beatmap.Value.Track.Length - current.Time) / current.BeatLength); + return (int)Math.Ceiling((musicController.TrackLength - current.Time) / current.BeatLength); return (int)Math.Ceiling((getNextTimingPoint(current).Time - current.Time) / current.BeatLength); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 532744a0fc..3ecd8ab550 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -80,12 +80,12 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Store track", () => currentBeatmap = Beatmap.Value); AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000)); - AddUntilStep(@"Wait for current time to update", () => currentBeatmap.Track.CurrentTime > 5000); + AddUntilStep(@"Wait for current time to update", () => musicController.CurrentTrackTime > 5000); AddStep(@"Set previous", () => musicController.PreviousTrack()); AddAssert(@"Check beatmap didn't change", () => currentBeatmap == Beatmap.Value); - AddUntilStep("Wait for current time to update", () => currentBeatmap.Track.CurrentTime < 5000); + AddUntilStep("Wait for current time to update", () => musicController.CurrentTrackTime < 5000); AddStep(@"Set previous", () => musicController.PreviousTrack()); AddAssert(@"Check beatmap did change", () => currentBeatmap != Beatmap.Value); diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b4b341634c..b2329f58ad 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -255,7 +255,7 @@ namespace osu.Game.Beatmaps new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager)); } - previous?.TransferTo(working); + // previous?.TransferTo(working); return working; } } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 39c5ccab27..33945a9eb1 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -79,22 +79,6 @@ namespace osu.Game.Beatmaps } } - public override void RecycleTrack() - { - base.RecycleTrack(); - - trackStore?.Dispose(); - trackStore = null; - } - - public override void TransferTo(WorkingBeatmap other) - { - base.TransferTo(other); - - if (other is BeatmapManagerWorkingBeatmap owb && textureStore != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo)) - owb.textureStore = textureStore; - } - protected override Waveform GetWaveform() { try diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 31975157a0..086b7502a2 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -26,11 +26,6 @@ namespace osu.Game.Beatmaps /// Texture Background { get; } - /// - /// Retrieves the audio track for this . - /// - Track Track { get; } - /// /// Retrieves the for the of this . /// diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index ac399e37c4..171201ca68 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -40,7 +40,6 @@ namespace osu.Game.Beatmaps BeatmapSetInfo = beatmapInfo.BeatmapSet; Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); - track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack(1000)); background = new RecyclableLazy(GetBackground, BackgroundStillValid); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); @@ -250,10 +249,9 @@ namespace osu.Game.Beatmaps protected abstract Texture GetBackground(); private readonly RecyclableLazy background; - public virtual bool TrackLoaded => track.IsResultAvailable; - public Track Track => track.Value; + public Track GetRealTrack() => GetTrack() ?? GetVirtualTrack(1000); + protected abstract Track GetTrack(); - private RecyclableLazy track; public bool WaveformLoaded => waveform.IsResultAvailable; public Waveform Waveform => waveform.Value; @@ -271,22 +269,6 @@ namespace osu.Game.Beatmaps protected virtual ISkin GetSkin() => new DefaultSkin(); private readonly RecyclableLazy skin; - /// - /// Transfer pieces of a beatmap to a new one, where possible, to save on loading. - /// - /// The new beatmap which is being switched to. - public virtual void TransferTo(WorkingBeatmap other) - { - if (track.IsResultAvailable && Track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo)) - other.track = track; - } - - /// - /// Eagerly dispose of the audio track associated with this (if any). - /// Accessing track again will load a fresh instance. - /// - public virtual void RecycleTrack() => track.Recycle(); - ~WorkingBeatmap() { total_count.Value--; diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index df063f57d5..2dd28a01dc 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Overlays; namespace osu.Game.Graphics.Containers { @@ -14,6 +15,9 @@ namespace osu.Game.Graphics.Containers { protected readonly IBindable Beatmap = new Bindable(); + [Resolved] + private MusicController musicController { get; set; } + private int lastBeat; private TimingControlPoint lastTimingPoint; @@ -47,22 +51,18 @@ namespace osu.Game.Graphics.Containers protected override void Update() { - Track track = null; IBeatmap beatmap = null; double currentTrackTime = 0; TimingControlPoint timingPoint = null; EffectControlPoint effectPoint = null; - if (Beatmap.Value.TrackLoaded && Beatmap.Value.BeatmapLoaded) - { - track = Beatmap.Value.Track; + if (musicController.TrackLoaded && Beatmap.Value.BeatmapLoaded) beatmap = Beatmap.Value.Beatmap; - } - if (track != null && beatmap != null && track.IsRunning && track.Length > 0) + if (beatmap != null && musicController.IsPlaying && musicController.TrackLength > 0) { - currentTrackTime = track.CurrentTime + EarlyActivationMilliseconds; + currentTrackTime = musicController.CurrentTrackTime + EarlyActivationMilliseconds; timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime); effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime); @@ -98,7 +98,7 @@ namespace osu.Game.Graphics.Containers return; using (BeginDelayedSequence(-TimeSinceLastBeat, true)) - OnNewBeat(beatIndex, timingPoint, effectPoint, track?.CurrentAmplitudes ?? ChannelAmplitudes.Empty); + OnNewBeat(beatIndex, timingPoint, effectPoint, musicController.CurrentAmplitudes); lastBeat = beatIndex; lastTimingPoint = timingPoint; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 26f7c3b93b..929254e8ad 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -431,19 +431,19 @@ namespace osu.Game if (newBeatmap != null) { - newBeatmap.Track.Completed += () => Scheduler.AddOnce(() => trackCompleted(newBeatmap)); + // MusicController.Completed += () => Scheduler.AddOnce(() => trackCompleted(newBeatmap)); newBeatmap.BeginAsyncLoad(); } - void trackCompleted(WorkingBeatmap b) - { - // the source of track completion is the audio thread, so the beatmap may have changed before firing. - if (Beatmap.Value != b) - return; - - if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled) - MusicController.NextTrack(); - } + // void trackCompleted(WorkingBeatmap b) + // { + // // the source of track completion is the audio thread, so the beatmap may have changed before firing. + // if (Beatmap.Value != b) + // return; + // + // if (!MusicController.Looping && !Beatmap.Disabled) + // MusicController.NextTrack(); + // } } private void modsChanged(ValueChangedEvent> mods) @@ -555,6 +555,7 @@ namespace osu.Game BackButton.Receptor receptor; dependencies.CacheAs(idleTracker = new GameIdleTracker(6000)); + dependencies.CacheAs(MusicController = new MusicController()); AddRange(new Drawable[] { @@ -617,7 +618,7 @@ namespace osu.Game loadComponentSingleFile(new OnScreenDisplay(), Add, true); - loadComponentSingleFile(MusicController = new MusicController(), Add, true); + loadComponentSingleFile(MusicController, Add); loadComponentSingleFile(notifications.With(d => { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 98f60d52d3..24c1f7849c 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -238,16 +238,6 @@ namespace osu.Game Beatmap = new NonNullableBindable(defaultBeatmap); - // ScheduleAfterChildren is safety against something in the current frame accessing the previous beatmap's track - // and potentially causing a reload of it after just unloading. - // Note that the reason for this being added *has* been resolved, so it may be feasible to removed this if required. - Beatmap.BindValueChanged(b => ScheduleAfterChildren(() => - { - // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) - if (b.OldValue?.TrackLoaded == true && b.OldValue?.Track != b.NewValue?.Track) - b.OldValue.RecycleTrack(); - })); - dependencies.CacheAs>(Beatmap); dependencies.CacheAs(Beatmap); diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index b878aba489..c089158c01 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -30,6 +30,9 @@ namespace osu.Game.Overlays.Music [Resolved] private BeatmapManager beatmaps { get; set; } + [Resolved] + private MusicController musicController { get; set; } + private FilterControl filter; private Playlist list; @@ -80,10 +83,7 @@ namespace osu.Game.Overlays.Music BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); if (toSelect != null) - { beatmap.Value = beatmaps.GetWorkingBeatmap(toSelect); - beatmap.Value.Track.Restart(); - } }; } @@ -116,12 +116,12 @@ namespace osu.Game.Overlays.Music { if (set.ID == (beatmap.Value?.BeatmapSetInfo?.ID ?? -1)) { - beatmap.Value?.Track?.Seek(0); + musicController.SeekTo(0); return; } beatmap.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First()); - beatmap.Value.Track.Restart(); + musicController.Play(true); } } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index a990f9a6ab..f5ca5a3a49 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -4,13 +4,18 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Audio; +using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Framework.Utils; using osu.Framework.Threading; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Input.Bindings; using osu.Game.Overlays.OSD; @@ -21,7 +26,7 @@ namespace osu.Game.Overlays /// /// Handles playback of the global music track. /// - public class MusicController : Component, IKeyBindingHandler + public class MusicController : CompositeDrawable, IKeyBindingHandler, ITrack { [Resolved] private BeatmapManager beatmaps { get; set; } @@ -61,9 +66,23 @@ namespace osu.Game.Overlays [Resolved(canBeNull: true)] private OnScreenDisplay onScreenDisplay { get; set; } + [NotNull] + private readonly TrackContainer trackContainer; + + [CanBeNull] + private DrawableTrack drawableTrack; + + [CanBeNull] + private Track track; + private IBindable> managerUpdated; private IBindable> managerRemoved; + public MusicController() + { + InternalChild = trackContainer = new TrackContainer { RelativeSizeAxes = Axes.Both }; + } + [BackgroundDependencyLoader] private void load() { @@ -95,9 +114,35 @@ namespace osu.Game.Overlays } /// - /// Returns whether the current beatmap track is playing. + /// Returns whether the beatmap track is playing. /// - public bool IsPlaying => current?.Track.IsRunning ?? false; + public bool IsPlaying => drawableTrack?.IsRunning ?? false; + + /// + /// Returns whether the beatmap track is loaded. + /// + public bool TrackLoaded => drawableTrack?.IsLoaded == true; + + /// + /// Returns the current time of the beatmap track. + /// + public double CurrentTrackTime => drawableTrack?.CurrentTime ?? 0; + + /// + /// Returns the length of the beatmap track. + /// + public double TrackLength => drawableTrack?.Length ?? 0; + + public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) + => trackContainer.AddAdjustment(type, adjustBindable); + + public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) + => trackContainer.RemoveAdjustment(type, adjustBindable); + + public void Reset() => drawableTrack?.Reset(); + + [CanBeNull] + public IAdjustableClock GetTrackClock() => track; private void beatmapUpdated(ValueChangedEvent> weakSet) { @@ -130,7 +175,7 @@ namespace osu.Game.Overlays seekDelegate = Schedule(() => { if (!beatmap.Disabled) - current?.Track.Seek(position); + drawableTrack?.Seek(position); }); } @@ -142,9 +187,7 @@ namespace osu.Game.Overlays { if (IsUserPaused) return; - var track = current?.Track; - - if (track == null || track is TrackVirtual) + if (drawableTrack == null || drawableTrack.IsDummyDevice) { if (beatmap.Disabled) return; @@ -163,17 +206,15 @@ namespace osu.Game.Overlays /// Whether the operation was successful. public bool Play(bool restart = false) { - var track = current?.Track; - IsUserPaused = false; - if (track == null) + if (drawableTrack == null) return false; if (restart) - track.Restart(); + drawableTrack.Restart(); else if (!IsPlaying) - track.Start(); + drawableTrack.Start(); return true; } @@ -183,11 +224,9 @@ namespace osu.Game.Overlays /// public void Stop() { - var track = current?.Track; - IsUserPaused = true; - if (track?.IsRunning == true) - track.Stop(); + if (drawableTrack?.IsRunning == true) + drawableTrack.Stop(); } /// @@ -196,9 +235,7 @@ namespace osu.Game.Overlays /// Whether the operation was successful. public bool TogglePause() { - var track = current?.Track; - - if (track?.IsRunning == true) + if (drawableTrack?.IsRunning == true) Stop(); else Play(); @@ -220,7 +257,7 @@ namespace osu.Game.Overlays if (beatmap.Disabled) return PreviousTrackResult.None; - var currentTrackPosition = current?.Track.CurrentTime; + var currentTrackPosition = drawableTrack?.CurrentTime; if (currentTrackPosition >= restart_cutoff_point) { @@ -274,7 +311,7 @@ namespace osu.Game.Overlays { // if not scheduled, the previously track will be stopped one frame later (see ScheduleAfterChildren logic in GameBase). // we probably want to move this to a central method for switching to a new working beatmap in the future. - Schedule(() => beatmap.Value.Track.Restart()); + Schedule(() => drawableTrack?.Restart()); } private WorkingBeatmap current; @@ -307,6 +344,14 @@ namespace osu.Game.Overlays } current = beatmap.NewValue; + + drawableTrack?.Expire(); + drawableTrack = null; + track = null; + + if (current != null) + trackContainer.Add(drawableTrack = new DrawableTrack(track = current.GetRealTrack())); + TrackChanged?.Invoke(current, direction); ResetTrackAdjustments(); @@ -334,16 +379,15 @@ namespace osu.Game.Overlays public void ResetTrackAdjustments() { - var track = current?.Track; - if (track == null) + if (drawableTrack == null) return; - track.ResetSpeedAdjustments(); + drawableTrack.ResetSpeedAdjustments(); if (allowRateAdjustments) { foreach (var mod in mods.Value.OfType()) - mod.ApplyToTrack(track); + mod.ApplyToTrack(drawableTrack); } } @@ -394,6 +438,133 @@ namespace osu.Game.Overlays { } } + + private class TrackContainer : AudioContainer + { + } + + #region ITrack + + /// + /// The volume of this component. + /// + public BindableNumber Volume => drawableTrack?.Volume; // Todo: Bad + + /// + /// The playback balance of this sample (-1 .. 1 where 0 is centered) + /// + public BindableNumber Balance => drawableTrack?.Balance; // Todo: Bad + + /// + /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency. + /// + public BindableNumber Frequency => drawableTrack?.Frequency; // Todo: Bad + + /// + /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed. + /// + public BindableNumber Tempo => drawableTrack?.Tempo; // Todo: Bad + + public IBindable AggregateVolume => drawableTrack?.AggregateVolume; // Todo: Bad + + public IBindable AggregateBalance => drawableTrack?.AggregateBalance; // Todo: Bad + + public IBindable AggregateFrequency => drawableTrack?.AggregateFrequency; // Todo: Bad + + public IBindable AggregateTempo => drawableTrack?.AggregateTempo; // Todo: Bad + + /// + /// Overall playback rate (1 is 100%, -1 is reversed at 100%). + /// + public double Rate => AggregateFrequency.Value * AggregateTempo.Value; + + event Action ITrack.Completed + { + add + { + if (drawableTrack != null) + drawableTrack.Completed += value; + } + remove + { + if (drawableTrack != null) + drawableTrack.Completed -= value; + } + } + + event Action ITrack.Failed + { + add + { + if (drawableTrack != null) + drawableTrack.Failed += value; + } + remove + { + if (drawableTrack != null) + drawableTrack.Failed -= value; + } + } + + public bool Looping + { + get => drawableTrack?.Looping ?? false; + set + { + if (drawableTrack != null) + drawableTrack.Looping = value; + } + } + + public bool IsDummyDevice => drawableTrack?.IsDummyDevice ?? true; + + public double RestartPoint + { + get => drawableTrack?.RestartPoint ?? 0; + set + { + if (drawableTrack != null) + drawableTrack.RestartPoint = value; + } + } + + double ITrack.CurrentTime => CurrentTrackTime; + + double ITrack.Length + { + get => TrackLength; + set + { + if (drawableTrack != null) + drawableTrack.Length = value; + } + } + + public int? Bitrate => drawableTrack?.Bitrate; + + bool ITrack.IsRunning => IsPlaying; + + public bool IsReversed => drawableTrack?.IsReversed ?? false; + + public bool HasCompleted => drawableTrack?.HasCompleted ?? false; + + void ITrack.Reset() => drawableTrack?.Reset(); + + void ITrack.Restart() => Play(true); + + void ITrack.ResetSpeedAdjustments() => ResetTrackAdjustments(); + + bool ITrack.Seek(double seek) + { + SeekTo(seek); + return true; + } + + void ITrack.Start() => Play(); + + public ChannelAmplitudes CurrentAmplitudes => drawableTrack?.CurrentAmplitudes ?? ChannelAmplitudes.Empty; + + #endregion } public enum TrackChangeDirection diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index ebb4a96d14..fde6a52fee 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -234,14 +234,12 @@ namespace osu.Game.Overlays pendingBeatmapSwitch = null; } - var track = beatmap.Value?.TrackLoaded ?? false ? beatmap.Value.Track : null; - - if (track?.IsDummyDevice == false) + if (musicController.IsDummyDevice == false) { - progressBar.EndTime = track.Length; - progressBar.CurrentTime = track.CurrentTime; + progressBar.EndTime = musicController.TrackLength; + progressBar.CurrentTime = musicController.CurrentTrackTime; - playButton.Icon = track.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; + playButton.Icon = musicController.IsPlaying ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; } else { diff --git a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs index 4d6d958e82..9b840cea08 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Mods /// public interface IApplicableToTrack : IApplicableMod { - void ApplyToTrack(Track track); + void ApplyToTrack(ITrack track); } } diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index bd98e735e5..9cefeb3340 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -27,11 +27,11 @@ namespace osu.Game.Rulesets.Mods }, true); } - public override void ApplyToTrack(Track track) + public override void ApplyToTrack(ITrack track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) - track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + (track as Track)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + (track as Track)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } } } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index ed8eb2fb66..b34affa77f 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -38,11 +38,11 @@ namespace osu.Game.Rulesets.Mods }, true); } - public override void ApplyToTrack(Track track) + public override void ApplyToTrack(ITrack track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) - track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + (track as Track)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + (track as Track)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index 874384686f..ee1280da39 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -12,9 +12,9 @@ namespace osu.Game.Rulesets.Mods { public abstract BindableNumber SpeedChange { get; } - public virtual void ApplyToTrack(Track track) + public virtual void ApplyToTrack(ITrack track) { - track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); + (track as Track)?.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); } public virtual void ApplyToSample(SampleChannel sample) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 839d97f04e..0257e241b8 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -51,9 +51,9 @@ namespace osu.Game.Rulesets.Mods AdjustPitch.BindValueChanged(applyPitchAdjustment); } - public void ApplyToTrack(Track track) + public void ApplyToTrack(ITrack track) { - this.track = track; + this.track = track as Track; FinalRate.TriggerChange(); AdjustPitch.TriggerChange(); diff --git a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs index cb5078a479..8d8c59b2ee 100644 --- a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs +++ b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,7 +17,6 @@ namespace osu.Game.Screens.Edit.Components private const float contents_padding = 15; protected readonly IBindable Beatmap = new Bindable(); - protected Track Track => Beatmap.Value.Track; private readonly Drawable background; private readonly Container content; diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 59b3d1c565..0a9b4f06a7 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -16,6 +16,7 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osuTK.Input; namespace osu.Game.Screens.Edit.Components @@ -27,6 +28,9 @@ namespace osu.Game.Screens.Edit.Components [Resolved] private EditorClock editorClock { get; set; } + [Resolved] + private MusicController musicController { get; set; } + private readonly BindableNumber tempo = new BindableDouble(1); [BackgroundDependencyLoader] @@ -62,12 +66,12 @@ namespace osu.Game.Screens.Edit.Components } }; - Track?.AddAdjustment(AdjustableProperty.Tempo, tempo); + musicController.AddAdjustment(AdjustableProperty.Tempo, tempo); } protected override void Dispose(bool isDisposing) { - Track?.RemoveAdjustment(AdjustableProperty.Tempo, tempo); + musicController?.RemoveAdjustment(AdjustableProperty.Tempo, tempo); base.Dispose(isDisposing); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 9e9ac93d23..a353f79ef4 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -58,7 +59,9 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts return; float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); - editorClock.SeekTo(markerPos / DrawWidth * editorClock.TrackLength); + + Debug.Assert(editorClock.TrackLength != null); + editorClock.SeekTo(markerPos / DrawWidth * editorClock.TrackLength.Value); }); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index 4a7c3f26bc..446f7fdf88 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -8,6 +8,7 @@ using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Overlays; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { @@ -26,6 +27,9 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected override Container Content => content; + [Resolved] + private MusicController musicController { get; set; } + public TimelinePart(Container content = null) { AddInternal(this.content = content ?? new Container { RelativeSizeAxes = Axes.Both }); @@ -46,14 +50,14 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts private void updateRelativeChildSize() { // the track may not be loaded completely (only has a length once it is). - if (!Beatmap.Value.Track.IsLoaded) + if (!musicController.TrackLoaded) { content.RelativeChildSize = Vector2.One; Schedule(updateRelativeChildSize); return; } - content.RelativeChildSize = new Vector2((float)Math.Max(1, Beatmap.Value.Track.Length), 1); + content.RelativeChildSize = new Vector2((float)Math.Max(1, musicController.TrackLength), 1); } protected virtual void LoadBeatmap(WorkingBeatmap beatmap) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 717d60b4f3..f35e5defd8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -11,6 +10,7 @@ using osu.Framework.Graphics.Audio; using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osuTK; @@ -26,6 +26,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [Resolved] private EditorClock editorClock { get; set; } + [Resolved] + private MusicController musicController { get; set; } + public Timeline() { ZoomDuration = 200; @@ -57,18 +60,21 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Beatmap.BindValueChanged(b => { waveform.Waveform = b.NewValue.Waveform; - track = b.NewValue.Track; - if (track.Length > 0) + // Todo: Wrong. + Schedule(() => { - MaxZoom = getZoomLevelForVisibleMilliseconds(500); - MinZoom = getZoomLevelForVisibleMilliseconds(10000); - Zoom = getZoomLevelForVisibleMilliseconds(2000); - } + if (musicController.TrackLength > 0) + { + MaxZoom = getZoomLevelForVisibleMilliseconds(500); + MinZoom = getZoomLevelForVisibleMilliseconds(10000); + Zoom = getZoomLevelForVisibleMilliseconds(2000); + } + }); }, true); } - private float getZoomLevelForVisibleMilliseconds(double milliseconds) => (float)(track.Length / milliseconds); + private float getZoomLevelForVisibleMilliseconds(double milliseconds) => (float)(musicController.TrackLength / milliseconds); /// /// The timeline's scroll position in the last frame. @@ -90,8 +96,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline /// private bool trackWasPlaying; - private Track track; - protected override void Update() { base.Update(); @@ -129,18 +133,18 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void seekTrackToCurrent() { - if (!track.IsLoaded) + if (!musicController.TrackLoaded) return; - editorClock.Seek(Current / Content.DrawWidth * track.Length); + editorClock.Seek(Current / Content.DrawWidth * musicController.TrackLength); } private void scrollToTrackTime() { - if (!track.IsLoaded || track.Length == 0) + if (!musicController.TrackLoaded || musicController.TrackLength == 0) return; - ScrollTo((float)(editorClock.CurrentTime / track.Length) * Content.DrawWidth, false); + ScrollTo((float)(editorClock.CurrentTime / musicController.TrackLength) * Content.DrawWidth, false); } protected override bool OnMouseDown(MouseDownEvent e) @@ -184,7 +188,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline new SnapResult(screenSpacePosition, beatSnapProvider.SnapTime(getTimeFromPosition(Content.ToLocalSpace(screenSpacePosition)))); private double getTimeFromPosition(Vector2 localPosition) => - (localPosition.X / Content.DrawWidth) * track.Length; + (localPosition.X / Content.DrawWidth) * musicController.TrackLength; public float GetBeatSnapDistanceAt(double referenceTime) => throw new NotImplementedException(); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 36ee976bf7..a833b354ed 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -3,10 +3,9 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Overlays; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; @@ -18,7 +17,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private EditorBeatmap beatmap { get; set; } [Resolved] - private Bindable working { get; set; } + private MusicController musicController { get; set; } [Resolved] private BindableBeatDivisor beatDivisor { get; set; } @@ -44,7 +43,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) { var point = beatmap.ControlPointInfo.TimingPoints[i]; - var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; + var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : musicController.TrackLength; int beat = 0; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index d92f3922c3..756b03d049 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -28,6 +28,7 @@ using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; +using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Setup; @@ -53,6 +54,9 @@ namespace osu.Game.Screens.Edit [Resolved] private BeatmapManager beatmapManager { get; set; } + [Resolved] + private MusicController musicController { get; set; } + private Box bottomBackground; private Container screenContainer; @@ -79,7 +83,7 @@ namespace osu.Game.Screens.Edit beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); // Todo: should probably be done at a DrawableRuleset level to share logic with Player. - var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); + var sourceClock = musicController.GetTrackClock() ?? new StopwatchClock(); clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); @@ -346,7 +350,7 @@ namespace osu.Game.Screens.Edit private void resetTrack(bool seekToStart = false) { - Beatmap.Value.Track?.Stop(); + musicController.Stop(); if (seekToStart) { diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index d4d0feb813..4cb24f90a6 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -2,13 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Overlays; namespace osu.Game.Screens.Edit { @@ -17,7 +20,7 @@ namespace osu.Game.Screens.Edit /// public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock { - public readonly double TrackLength; + public double? TrackLength { get; private set; } public ControlPointInfo ControlPointInfo; @@ -25,12 +28,15 @@ namespace osu.Game.Screens.Edit private readonly DecoupleableInterpolatingFramedClock underlyingClock; + [Resolved] + private MusicController musicController { get; set; } + public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) - : this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor) + : this(beatmap.Beatmap.ControlPointInfo, null, beatDivisor) { } - public EditorClock(ControlPointInfo controlPointInfo, double trackLength, BindableBeatDivisor beatDivisor) + public EditorClock(ControlPointInfo controlPointInfo, double? trackLength, BindableBeatDivisor beatDivisor) { this.beatDivisor = beatDivisor; @@ -45,6 +51,13 @@ namespace osu.Game.Screens.Edit { } + [BackgroundDependencyLoader] + private void load() + { + // Todo: What. + TrackLength ??= musicController.TrackLength; + } + /// /// Seek to the closest snappable beat from a time. /// @@ -135,7 +148,8 @@ namespace osu.Game.Screens.Edit seekTime = timingPoint.Time; // Ensure the sought point is within the boundaries - seekTime = Math.Clamp(seekTime, 0, TrackLength); + Debug.Assert(TrackLength != null); + seekTime = Math.Clamp(seekTime, 0, TrackLength.Value); SeekTo(seekTime); } diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 5f91aaad15..7da5df2723 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -12,6 +12,7 @@ using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.IO.Archives; +using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osu.Game.Skinning; using osuTK; @@ -43,7 +44,8 @@ namespace osu.Game.Screens.Menu private WorkingBeatmap initialBeatmap; - protected Track Track => initialBeatmap?.Track; + [Resolved] + protected MusicController MusicController { get; private set; } private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); @@ -111,7 +113,7 @@ namespace osu.Game.Screens.Menu if (setInfo != null) { initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - UsingThemedIntro = !(Track is TrackVirtual); + UsingThemedIntro = !MusicController.IsDummyDevice; } return UsingThemedIntro; @@ -150,7 +152,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(); + MusicController.Play(true); } 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 a9ef20436f..86a6fa3802 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Menu LoadComponentAsync(new TrianglesIntroSequence(logo, background) { RelativeSizeAxes = Axes.Both, - Clock = new FramedClock(UsingThemedIntro ? Track : null), + Clock = new FramedClock(UsingThemedIntro ? MusicController.GetTrackClock() : null), LoadMenu = LoadMenu }, t => { diff --git a/osu.Game/Screens/Menu/IntroWelcome.cs b/osu.Game/Screens/Menu/IntroWelcome.cs index bf42e36e8c..62cada577d 100644 --- a/osu.Game/Screens/Menu/IntroWelcome.cs +++ b/osu.Game/Screens/Menu/IntroWelcome.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osuTK.Graphics; @@ -30,6 +31,9 @@ namespace osu.Game.Screens.Menu Alpha = 0, }; + [Resolved] + private MusicController musicController { get; set; } + private BackgroundScreenDefault background; [BackgroundDependencyLoader] @@ -40,7 +44,7 @@ namespace osu.Game.Screens.Menu pianoReverb = audio.Samples.Get(@"Intro/Welcome/welcome_piano"); - Track.Looping = true; + musicController.Looping = true; } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index ebbb19636c..349654165f 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -20,6 +20,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Utils; +using osu.Game.Overlays; namespace osu.Game.Screens.Menu { @@ -74,6 +75,9 @@ namespace osu.Game.Screens.Menu /// public float Magnitude { get; set; } = 1; + [Resolved] + private MusicController musicController { get; set; } + private readonly float[] frequencyAmplitudes = new float[256]; private IShader shader; @@ -103,15 +107,15 @@ namespace osu.Game.Screens.Menu private void updateAmplitudes() { - var effect = beatmap.Value.BeatmapLoaded && beatmap.Value.TrackLoaded - ? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(beatmap.Value.Track.CurrentTime) + var effect = beatmap.Value.BeatmapLoaded && musicController.TrackLoaded + ? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(musicController.CurrentTrackTime) : null; for (int i = 0; i < temporalAmplitudes.Length; i++) temporalAmplitudes[i] = 0; - if (beatmap.Value.TrackLoaded) - addAmplitudesFromSource(beatmap.Value.Track); + if (musicController.TrackLoaded) + addAmplitudesFromSource(musicController); foreach (var source in amplitudeSources) addAmplitudesFromSource(source); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 57252d557e..c422f57332 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -5,7 +5,6 @@ using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Platform; @@ -62,8 +61,6 @@ namespace osu.Game.Screens.Menu protected override BackgroundScreen CreateBackground() => background; - internal Track Track { get; private set; } - private Bindable holdDelay; private Bindable loginDisplayed; @@ -172,20 +169,23 @@ namespace osu.Game.Screens.Menu [Resolved] private Storage storage { get; set; } + [Resolved] + private MusicController musicController { get; set; } + public override void OnEntering(IScreen last) { base.OnEntering(last); buttons.FadeInFromZero(500); - Track = Beatmap.Value.Track; var metadata = Beatmap.Value.Metadata; - if (last is IntroScreen && Track != null) + if (last is IntroScreen && musicController.TrackLoaded) { - if (!Track.IsRunning) + // Todo: Wrong. + if (!musicController.IsPlaying) { - Track.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * Track.Length); - Track.Start(); + musicController.SeekTo(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.TrackLength); + musicController.Play(); } } diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index f5e4b078da..1feb2481c3 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -17,6 +17,7 @@ using osu.Framework.Utils; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; +using osu.Game.Overlays; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -46,7 +47,6 @@ namespace osu.Game.Screens.Menu private SampleChannel sampleBeat; private readonly Container colourAndTriangles; - private readonly Triangles triangles; /// @@ -319,6 +319,9 @@ namespace osu.Game.Screens.Menu intro.Delay(length + fade).FadeOut(); } + [Resolved] + private MusicController musicController { get; set; } + protected override void Update() { base.Update(); @@ -327,9 +330,9 @@ namespace osu.Game.Screens.Menu const float velocity_adjust_cutoff = 0.98f; const float paused_velocity = 0.5f; - if (Beatmap.Value.Track.IsRunning) + if (musicController.IsPlaying) { - var maxAmplitude = lastBeatIndex >= 0 ? Beatmap.Value.Track.CurrentAmplitudes.Maximum : 0; + var maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentAmplitudes.Maximum : 0; logoAmplitudeContainer.Scale = new Vector2((float)Interpolation.Damp(logoAmplitudeContainer.Scale.X, 1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 0.9f, Time.Elapsed)); if (maxAmplitude > velocity_adjust_cutoff) diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index a64f24dd7e..032c8d5ca9 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -10,6 +10,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; +using osu.Game.Overlays; namespace osu.Game.Screens.Multi.Match.Components { @@ -26,6 +27,9 @@ namespace osu.Game.Screens.Multi.Match.Components [Resolved] private BeatmapManager beatmaps { get; set; } + [Resolved] + private MusicController musicController { get; set; } + private bool hasBeatmap; public ReadyButton() @@ -100,7 +104,7 @@ namespace osu.Game.Screens.Multi.Match.Components return; } - bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value; + bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(musicController.TrackLength) < endDate.Value; Enabled.Value = hasBeatmap && hasEnoughTime; } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 4912df17b1..2d74434c76 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Multi private readonly Bindable currentFilter = new Bindable(new FilterCriteria()); [Resolved] - private MusicController music { get; set; } + private MusicController musicController { get; set; } [Cached(Type = typeof(IRoomManager))] private RoomManager roomManager; @@ -343,15 +343,9 @@ namespace osu.Game.Screens.Multi { if (screenStack.CurrentScreen is MatchSubScreen) { - var track = Beatmap.Value?.Track; - - if (track != null) - { - track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - track.Looping = true; - - music.EnsurePlayingSomething(); - } + musicController.RestartPoint = Beatmap.Value.Metadata.PreviewTime; + musicController.Looping = true; + musicController.EnsurePlayingSomething(); } else { @@ -361,13 +355,8 @@ namespace osu.Game.Screens.Multi private void cancelLooping() { - var track = Beatmap?.Value?.Track; - - if (track != null) - { - track.Looping = false; - track.RestartPoint = 0; - } + musicController.Looping = false; + musicController.RestartPoint = 0; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index 54c644c999..0e0ef8c675 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -8,10 +8,10 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; -using osu.Framework.Audio.Track; using osu.Framework.Graphics; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Overlays; using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Graphics; @@ -30,12 +30,13 @@ namespace osu.Game.Screens.Play private readonly BindableDouble trackFreq = new BindableDouble(1); - private Track track; - private const float duration = 2500; private SampleChannel failSample; + [Resolved] + private MusicController musicController { get; set; } + public FailAnimation(DrawableRuleset drawableRuleset) { this.drawableRuleset = drawableRuleset; @@ -44,7 +45,6 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(AudioManager audio, IBindable beatmap) { - track = beatmap.Value.Track; failSample = audio.Samples.Get(@"Gameplay/failsound"); } @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Play Expire(); }); - track.AddAdjustment(AdjustableProperty.Frequency, trackFreq); + musicController.AddAdjustment(AdjustableProperty.Frequency, trackFreq); applyToPlayfield(drawableRuleset.Playfield); drawableRuleset.Playfield.HitObjectContainer.FlashColour(Color4.Red, 500); @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Play protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - track?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); + musicController?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); } } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 0653373c91..cf4678ab29 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -8,13 +8,13 @@ using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Overlays; using osu.Game.Rulesets.Mods; namespace osu.Game.Screens.Play @@ -27,10 +27,8 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private readonly IReadOnlyList mods; - /// - /// The 's track. - /// - private Track track; + [Resolved] + private MusicController musicController { get; set; } public readonly BindableBool IsPaused = new BindableBool(); @@ -72,8 +70,6 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both; - track = beatmap.Track; - adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited. @@ -125,15 +121,15 @@ namespace osu.Game.Screens.Play { // The Reset() call below causes speed adjustments to be reset in an async context, leading to deadlocks. // The deadlock can be prevented by resetting the track synchronously before entering the async context. - track.ResetSpeedAdjustments(); + musicController.Reset(); Task.Run(() => { - track.Reset(); + musicController.Reset(); Schedule(() => { - adjustableClock.ChangeSource(track); + adjustableClock.ChangeSource(musicController.GetTrackClock()); updateRate(); if (!IsPaused.Value) @@ -194,20 +190,6 @@ namespace osu.Game.Screens.Play IsPaused.Value = true; } - /// - /// Changes the backing clock to avoid using the originally provided beatmap's track. - /// - public void StopUsingBeatmapClock() - { - if (track != beatmap.Track) - return; - - removeSourceClockAdjustments(); - - track = new TrackVirtual(beatmap.Track.Length); - adjustableClock.ChangeSource(track); - } - protected override void Update() { if (!IsPaused.Value) @@ -220,31 +202,23 @@ namespace osu.Game.Screens.Play private void updateRate() { - if (track == null) return; - speedAdjustmentsApplied = true; - track.ResetSpeedAdjustments(); - - track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); - track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); - - foreach (var mod in mods.OfType()) - mod.ApplyToTrack(track); + musicController.ResetTrackAdjustments(); + musicController.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + musicController.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); } protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - removeSourceClockAdjustments(); - track = null; } private void removeSourceClockAdjustments() { if (speedAdjustmentsApplied) { - track.ResetSpeedAdjustments(); + musicController.ResetTrackAdjustments(); speedAdjustmentsApplied = false; } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 74a5ee8309..9ba2732920 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -561,8 +560,11 @@ namespace osu.Game.Screens.Select BeatmapDetails.Refresh(); - Beatmap.Value.Track.Looping = true; - music?.ResetTrackAdjustments(); + if (music != null) + { + music.Looping = true; + music.ResetTrackAdjustments(); + } if (Beatmap != null && !Beatmap.Value.BeatmapSetInfo.DeletePending) { @@ -586,8 +588,8 @@ namespace osu.Game.Screens.Select BeatmapOptions.Hide(); - if (Beatmap.Value.Track != null) - Beatmap.Value.Track.Looping = false; + if (music != null) + music.Looping = false; this.ScaleTo(1.1f, 250, Easing.InSine); @@ -608,8 +610,8 @@ namespace osu.Game.Screens.Select FilterControl.Deactivate(); - if (Beatmap.Value.Track != null) - Beatmap.Value.Track.Looping = false; + if (music != null) + music.Looping = false; return false; } @@ -650,28 +652,18 @@ namespace osu.Game.Screens.Select BeatmapDetails.Beatmap = beatmap; - if (beatmap.Track != null) - beatmap.Track.Looping = true; + if (music != null) + music.Looping = false; } - private readonly WeakReference lastTrack = new WeakReference(null); - /// /// Ensures some music is playing for the current track. /// Will resume playback from a manual user pause if the track has changed. /// private void ensurePlayingSelected() { - Track track = Beatmap.Value.Track; - - bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; - - track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - - if (!track.IsRunning && (music?.IsUserPaused != true || isNewTrack)) - music?.Play(true); - - lastTrack.SetTarget(track); + music.RestartPoint = Beatmap.Value.Metadata.PreviewTime; + music.EnsurePlayingSomething(); } private void carouselBeatmapsLoaded() diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index cdf9170701..ee04142035 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -27,8 +27,6 @@ namespace osu.Game.Tests.Beatmaps this.storyboard = storyboard; } - public override bool TrackLoaded => true; - public override bool BeatmapLoaded => true; protected override IBeatmap GetBeatmap() => beatmap; diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index f0ec638fc9..5226a49def 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(ValueChangedEvent e) { Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; - Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock()); + Clock.ChangeSource(MusicController.GetTrackClock() ?? new StopwatchClock()); Clock.ProcessFrame(); } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 866fc215d6..e968f7e675 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -20,6 +20,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Online.API; +using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; @@ -135,6 +136,9 @@ namespace osu.Game.Tests.Visual [Resolved] protected AudioManager Audio { get; private set; } + [Resolved] + protected MusicController MusicController { get; private set; } + /// /// Creates the ruleset to be used for this test scene. /// @@ -164,8 +168,8 @@ namespace osu.Game.Tests.Visual rulesetDependencies?.Dispose(); - if (Beatmap?.Value.TrackLoaded == true) - Beatmap.Value.Track.Stop(); + if (MusicController?.TrackLoaded == true) + MusicController.Stop(); if (contextFactory.IsValueCreated) contextFactory.Value.ResetDatabase(); diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index ad24ffc7b8..e7cb461d7b 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual base.Update(); // note that this will override any mod rate application - Beatmap.Value.Track.Tempo.Value = Clock.Rate; + MusicController.Tempo.Value = Clock.Rate; } } } From 5c05fe3988ad5ba9c92e908628f2d11def1c9376 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Aug 2020 21:10:38 +0900 Subject: [PATCH 02/86] Expose track from MusicController --- .../TestSceneHoldNoteInput.cs | 2 +- .../TestSceneOutOfOrderHits.cs | 2 +- .../TestSceneSliderInput.cs | 2 +- .../Skins/TestSceneBeatmapSkinResources.cs | 2 +- .../Visual/Editing/TimelineTestScene.cs | 6 +- .../Visual/Gameplay/TestScenePause.cs | 2 +- .../Visual/Gameplay/TestScenePlayerLoader.cs | 6 +- .../Visual/Gameplay/TestSceneStoryboard.cs | 8 +- .../Visual/Menus/TestSceneIntroWelcome.cs | 2 +- .../Navigation/TestSceneScreenNavigation.cs | 13 +- .../TestSceneBeatSyncedContainer.cs | 3 +- .../TestSceneNowPlayingOverlay.cs | 4 +- .../Containers/BeatSyncedContainer.cs | 14 +- osu.Game/Overlays/MusicController.cs | 190 ++---------------- osu.Game/Overlays/NowPlayingOverlay.cs | 12 +- osu.Game/Rulesets/Mods/IApplicableToTrack.cs | 3 +- osu.Game/Rulesets/Mods/ModDaycore.cs | 7 +- osu.Game/Rulesets/Mods/ModNightcore.cs | 6 +- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 4 +- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 10 +- .../Edit/Components/PlaybackControl.cs | 4 +- .../Timelines/Summary/Parts/TimelinePart.cs | 4 +- .../Compose/Components/Timeline/Timeline.cs | 31 +-- .../Timeline/TimelineTickDisplay.cs | 3 +- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 2 +- osu.Game/Screens/Menu/IntroScreen.cs | 4 +- osu.Game/Screens/Menu/IntroTriangles.cs | 2 +- osu.Game/Screens/Menu/IntroWelcome.cs | 3 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 5 +- osu.Game/Screens/Menu/MainMenu.cs | 10 +- osu.Game/Screens/Menu/OsuLogo.cs | 4 +- .../Multi/Match/Components/ReadyButton.cs | 2 +- osu.Game/Screens/Multi/Multiplayer.cs | 17 +- osu.Game/Screens/Play/FailAnimation.cs | 13 +- .../Screens/Play/GameplayClockContainer.cs | 44 +++- osu.Game/Screens/Select/SongSelect.cs | 33 ++- osu.Game/Tests/Visual/EditorClockTestScene.cs | 2 +- .../Visual/RateAdjustedBeatmapTestScene.cs | 4 +- 39 files changed, 204 insertions(+), 283 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index c3e0c277a0..98669efb10 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -343,7 +343,7 @@ namespace osu.Game.Rulesets.Mania.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs index dc7e59b40d..e5be778527 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs @@ -385,7 +385,7 @@ namespace osu.Game.Rulesets.Osu.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 2dffcfeabb..c9d13d3976 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -366,7 +366,7 @@ namespace osu.Game.Rulesets.Osu.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index 1a19326ac4..08a4e27ff7 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -31,6 +31,6 @@ namespace osu.Game.Tests.Skins public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => beatmap.Skin.GetSample(new SampleInfo("sample")) != null); [Test] - public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => !MusicController.IsDummyDevice); + public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => MusicController.CurrentTrack?.IsDummyDevice == false); } } diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index 5d6136d9fb..4113bdddf8 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; @@ -94,7 +95,10 @@ namespace osu.Game.Tests.Visual.Editing base.Update(); if (musicController.TrackLoaded) - marker.X = (float)(editorClock.CurrentTime / musicController.TrackLength); + { + Debug.Assert(musicController.CurrentTrack != null); + marker.X = (float)(editorClock.CurrentTime / musicController.CurrentTrack.Length); + } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 8f14de1578..e500b451f0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -288,7 +288,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void confirmNoTrackAdjustments() { - AddAssert("track has no adjustments", () => MusicController.AggregateFrequency.Value == 1); + AddAssert("track has no adjustments", () => MusicController.CurrentTrack?.AggregateFrequency.Value == 1); } private void restart() => AddStep("restart", () => Player.Restart()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 2f86db1b25..c72ab7d3d1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); foreach (var mod in SelectedMods.Value.OfType()) - mod.ApplyToTrack(MusicController); + mod.ApplyToTrack(MusicController.CurrentTrack); InputManager.Child = container = new TestPlayerLoaderContainer( loader = new TestPlayerLoader(() => @@ -77,12 +77,12 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("load dummy beatmap", () => ResetPlayer(false, () => SelectedMods.Value = new[] { new OsuModNightcore() })); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddAssert("mod rate applied", () => MusicController.Rate != 1); + AddAssert("mod rate applied", () => MusicController.CurrentTrack?.Rate != 1); AddStep("exit loader", () => loader.Exit()); AddUntilStep("wait for not current", () => !loader.IsCurrentScreen()); AddAssert("player did not load", () => !player.IsLoaded); AddUntilStep("player disposed", () => loader.DisposalTask?.IsCompleted == true); - AddAssert("mod rate still applied", () => MusicController.Rate != 1); + AddAssert("mod rate still applied", () => MusicController.CurrentTrack?.Rate != 1); } [Test] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index a4b558fce2..c7a012a03f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -87,9 +87,9 @@ namespace osu.Game.Tests.Visual.Gameplay private void restart() { - MusicController.Reset(); + MusicController.CurrentTrack?.Reset(); loadStoryboard(Beatmap.Value); - MusicController.Play(true); + MusicController.CurrentTrack?.Start(); } private void loadStoryboard(WorkingBeatmap working) @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard.Passing = false; storyboardContainer.Add(storyboard); - decoupledClock.ChangeSource(musicController.GetTrackClock()); + decoupledClock.ChangeSource(musicController.CurrentTrack); } private void loadStoryboardNoVideo() @@ -127,7 +127,7 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard = sb.CreateDrawable(Beatmap.Value); storyboardContainer.Add(storyboard); - decoupledClock.ChangeSource(musicController.GetTrackClock()); + decoupledClock.ChangeSource(musicController.CurrentTrack); } } } diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs index 36f98b7a0c..a88704c831 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Menus { AddUntilStep("wait for load", () => MusicController.TrackLoaded); - AddAssert("check if menu music loops", () => MusicController.Looping); + AddAssert("check if menu music loops", () => MusicController.CurrentTrack?.Looping == true); } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 455b7e56e6..946bc2a175 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -4,6 +4,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -61,12 +62,12 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for fail", () => player.HasFailed); AddUntilStep("wait for track stop", () => !MusicController.IsPlaying); - AddAssert("Ensure time before preview point", () => MusicController.CurrentTrackTime < beatmap().Metadata.PreviewTime); + AddAssert("Ensure time before preview point", () => MusicController.CurrentTrack?.CurrentTime < beatmap().Metadata.PreviewTime); pushEscape(); AddUntilStep("wait for track playing", () => MusicController.IsPlaying); - AddAssert("Ensure time wasn't reset to preview point", () => MusicController.CurrentTrackTime < beatmap().Metadata.PreviewTime); + AddAssert("Ensure time wasn't reset to preview point", () => MusicController.CurrentTrack?.CurrentTime < beatmap().Metadata.PreviewTime); } [Test] @@ -76,11 +77,11 @@ namespace osu.Game.Tests.Visual.Navigation PushAndConfirm(() => songSelect = new TestSongSelect()); - AddUntilStep("wait for no track", () => MusicController.IsDummyDevice); + AddUntilStep("wait for no track", () => MusicController.CurrentTrack?.IsDummyDevice == true); AddStep("return to menu", () => songSelect.Exit()); - AddUntilStep("wait for track", () => !MusicController.IsDummyDevice && MusicController.IsPlaying); + AddUntilStep("wait for track", () => MusicController.CurrentTrack?.IsDummyDevice == false && MusicController.IsPlaying); } [Test] @@ -135,8 +136,8 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded); AddStep("Seek close to end", () => { - Game.MusicController.SeekTo(MusicController.TrackLength - 1000); - // MusicController.Completed += () => trackCompleted = true; + Game.MusicController.SeekTo(MusicController.CurrentTrack.AsNonNull().Length - 1000); + MusicController.CurrentTrack.AsNonNull().Completed += () => trackCompleted = true; }); AddUntilStep("Track was completed", () => trackCompleted); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index f3fef8c355..ac743d76df 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -168,7 +169,7 @@ namespace osu.Game.Tests.Visual.UserInterface if (timingPoints.Count == 0) return 0; if (timingPoints[^1] == current) - return (int)Math.Ceiling((musicController.TrackLength - current.Time) / current.BeatLength); + return (int)Math.Ceiling((musicController.CurrentTrack.AsNonNull().Length - current.Time) / current.BeatLength); return (int)Math.Ceiling((getNextTimingPoint(current).Time - current.Time) / current.BeatLength); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 3ecd8ab550..0161ec0c56 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -80,12 +80,12 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Store track", () => currentBeatmap = Beatmap.Value); AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000)); - AddUntilStep(@"Wait for current time to update", () => musicController.CurrentTrackTime > 5000); + AddUntilStep(@"Wait for current time to update", () => musicController.CurrentTrack?.CurrentTime > 5000); AddStep(@"Set previous", () => musicController.PreviousTrack()); AddAssert(@"Check beatmap didn't change", () => currentBeatmap == Beatmap.Value); - AddUntilStep("Wait for current time to update", () => musicController.CurrentTrackTime < 5000); + AddUntilStep("Wait for current time to update", () => musicController.CurrentTrack?.CurrentTime < 5000); AddStep(@"Set previous", () => musicController.PreviousTrack()); AddAssert(@"Check beatmap did change", () => currentBeatmap != Beatmap.Value); diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 2dd28a01dc..92a9ed0566 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -51,6 +51,7 @@ namespace osu.Game.Graphics.Containers protected override void Update() { + ITrack track = null; IBeatmap beatmap = null; double currentTrackTime = 0; @@ -58,11 +59,14 @@ namespace osu.Game.Graphics.Containers EffectControlPoint effectPoint = null; if (musicController.TrackLoaded && Beatmap.Value.BeatmapLoaded) - beatmap = Beatmap.Value.Beatmap; - - if (beatmap != null && musicController.IsPlaying && musicController.TrackLength > 0) { - currentTrackTime = musicController.CurrentTrackTime + EarlyActivationMilliseconds; + track = musicController.CurrentTrack; + beatmap = Beatmap.Value.Beatmap; + } + + if (track != null && beatmap != null && musicController.IsPlaying && track.Length > 0) + { + currentTrackTime = track.CurrentTime + EarlyActivationMilliseconds; timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime); effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime); @@ -98,7 +102,7 @@ namespace osu.Game.Graphics.Containers return; using (BeginDelayedSequence(-TimeSinceLastBeat, true)) - OnNewBeat(beatIndex, timingPoint, effectPoint, musicController.CurrentAmplitudes); + OnNewBeat(beatIndex, timingPoint, effectPoint, track?.CurrentAmplitudes ?? ChannelAmplitudes.Empty); lastBeat = beatIndex; lastTimingPoint = timingPoint; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index f5ca5a3a49..c22849b7d6 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; -using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -15,7 +14,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Framework.Utils; using osu.Framework.Threading; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Input.Bindings; using osu.Game.Overlays.OSD; @@ -26,7 +24,7 @@ namespace osu.Game.Overlays /// /// Handles playback of the global music track. /// - public class MusicController : CompositeDrawable, IKeyBindingHandler, ITrack + public class MusicController : CompositeDrawable, IKeyBindingHandler { [Resolved] private BeatmapManager beatmaps { get; set; } @@ -70,10 +68,7 @@ namespace osu.Game.Overlays private readonly TrackContainer trackContainer; [CanBeNull] - private DrawableTrack drawableTrack; - - [CanBeNull] - private Track track; + public DrawableTrack CurrentTrack { get; private set; } private IBindable> managerUpdated; private IBindable> managerRemoved; @@ -116,33 +111,12 @@ namespace osu.Game.Overlays /// /// Returns whether the beatmap track is playing. /// - public bool IsPlaying => drawableTrack?.IsRunning ?? false; + public bool IsPlaying => CurrentTrack?.IsRunning ?? false; /// /// Returns whether the beatmap track is loaded. /// - public bool TrackLoaded => drawableTrack?.IsLoaded == true; - - /// - /// Returns the current time of the beatmap track. - /// - public double CurrentTrackTime => drawableTrack?.CurrentTime ?? 0; - - /// - /// Returns the length of the beatmap track. - /// - public double TrackLength => drawableTrack?.Length ?? 0; - - public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) - => trackContainer.AddAdjustment(type, adjustBindable); - - public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) - => trackContainer.RemoveAdjustment(type, adjustBindable); - - public void Reset() => drawableTrack?.Reset(); - - [CanBeNull] - public IAdjustableClock GetTrackClock() => track; + public bool TrackLoaded => CurrentTrack?.IsLoaded == true; private void beatmapUpdated(ValueChangedEvent> weakSet) { @@ -175,7 +149,7 @@ namespace osu.Game.Overlays seekDelegate = Schedule(() => { if (!beatmap.Disabled) - drawableTrack?.Seek(position); + CurrentTrack?.Seek(position); }); } @@ -187,7 +161,7 @@ namespace osu.Game.Overlays { if (IsUserPaused) return; - if (drawableTrack == null || drawableTrack.IsDummyDevice) + if (CurrentTrack == null || CurrentTrack.IsDummyDevice) { if (beatmap.Disabled) return; @@ -208,13 +182,13 @@ namespace osu.Game.Overlays { IsUserPaused = false; - if (drawableTrack == null) + if (CurrentTrack == null) return false; if (restart) - drawableTrack.Restart(); + CurrentTrack.Restart(); else if (!IsPlaying) - drawableTrack.Start(); + CurrentTrack.Start(); return true; } @@ -225,8 +199,8 @@ namespace osu.Game.Overlays public void Stop() { IsUserPaused = true; - if (drawableTrack?.IsRunning == true) - drawableTrack.Stop(); + if (CurrentTrack?.IsRunning == true) + CurrentTrack.Stop(); } /// @@ -235,7 +209,7 @@ namespace osu.Game.Overlays /// Whether the operation was successful. public bool TogglePause() { - if (drawableTrack?.IsRunning == true) + if (CurrentTrack?.IsRunning == true) Stop(); else Play(); @@ -257,7 +231,7 @@ namespace osu.Game.Overlays if (beatmap.Disabled) return PreviousTrackResult.None; - var currentTrackPosition = drawableTrack?.CurrentTime; + var currentTrackPosition = CurrentTrack?.CurrentTime; if (currentTrackPosition >= restart_cutoff_point) { @@ -311,7 +285,7 @@ namespace osu.Game.Overlays { // if not scheduled, the previously track will be stopped one frame later (see ScheduleAfterChildren logic in GameBase). // we probably want to move this to a central method for switching to a new working beatmap in the future. - Schedule(() => drawableTrack?.Restart()); + Schedule(() => CurrentTrack?.Restart()); } private WorkingBeatmap current; @@ -345,12 +319,11 @@ namespace osu.Game.Overlays current = beatmap.NewValue; - drawableTrack?.Expire(); - drawableTrack = null; - track = null; + CurrentTrack?.Expire(); + CurrentTrack = null; if (current != null) - trackContainer.Add(drawableTrack = new DrawableTrack(track = current.GetRealTrack())); + trackContainer.Add(CurrentTrack = new DrawableTrack(current.GetRealTrack())); TrackChanged?.Invoke(current, direction); @@ -379,15 +352,15 @@ namespace osu.Game.Overlays public void ResetTrackAdjustments() { - if (drawableTrack == null) + if (CurrentTrack == null) return; - drawableTrack.ResetSpeedAdjustments(); + CurrentTrack.ResetSpeedAdjustments(); if (allowRateAdjustments) { foreach (var mod in mods.Value.OfType()) - mod.ApplyToTrack(drawableTrack); + mod.ApplyToTrack(CurrentTrack); } } @@ -442,129 +415,6 @@ namespace osu.Game.Overlays private class TrackContainer : AudioContainer { } - - #region ITrack - - /// - /// The volume of this component. - /// - public BindableNumber Volume => drawableTrack?.Volume; // Todo: Bad - - /// - /// The playback balance of this sample (-1 .. 1 where 0 is centered) - /// - public BindableNumber Balance => drawableTrack?.Balance; // Todo: Bad - - /// - /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency. - /// - public BindableNumber Frequency => drawableTrack?.Frequency; // Todo: Bad - - /// - /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed. - /// - public BindableNumber Tempo => drawableTrack?.Tempo; // Todo: Bad - - public IBindable AggregateVolume => drawableTrack?.AggregateVolume; // Todo: Bad - - public IBindable AggregateBalance => drawableTrack?.AggregateBalance; // Todo: Bad - - public IBindable AggregateFrequency => drawableTrack?.AggregateFrequency; // Todo: Bad - - public IBindable AggregateTempo => drawableTrack?.AggregateTempo; // Todo: Bad - - /// - /// Overall playback rate (1 is 100%, -1 is reversed at 100%). - /// - public double Rate => AggregateFrequency.Value * AggregateTempo.Value; - - event Action ITrack.Completed - { - add - { - if (drawableTrack != null) - drawableTrack.Completed += value; - } - remove - { - if (drawableTrack != null) - drawableTrack.Completed -= value; - } - } - - event Action ITrack.Failed - { - add - { - if (drawableTrack != null) - drawableTrack.Failed += value; - } - remove - { - if (drawableTrack != null) - drawableTrack.Failed -= value; - } - } - - public bool Looping - { - get => drawableTrack?.Looping ?? false; - set - { - if (drawableTrack != null) - drawableTrack.Looping = value; - } - } - - public bool IsDummyDevice => drawableTrack?.IsDummyDevice ?? true; - - public double RestartPoint - { - get => drawableTrack?.RestartPoint ?? 0; - set - { - if (drawableTrack != null) - drawableTrack.RestartPoint = value; - } - } - - double ITrack.CurrentTime => CurrentTrackTime; - - double ITrack.Length - { - get => TrackLength; - set - { - if (drawableTrack != null) - drawableTrack.Length = value; - } - } - - public int? Bitrate => drawableTrack?.Bitrate; - - bool ITrack.IsRunning => IsPlaying; - - public bool IsReversed => drawableTrack?.IsReversed ?? false; - - public bool HasCompleted => drawableTrack?.HasCompleted ?? false; - - void ITrack.Reset() => drawableTrack?.Reset(); - - void ITrack.Restart() => Play(true); - - void ITrack.ResetSpeedAdjustments() => ResetTrackAdjustments(); - - bool ITrack.Seek(double seek) - { - SeekTo(seek); - return true; - } - - void ITrack.Start() => Play(); - - public ChannelAmplitudes CurrentAmplitudes => drawableTrack?.CurrentAmplitudes ?? ChannelAmplitudes.Empty; - - #endregion } public enum TrackChangeDirection diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index fde6a52fee..15b189ead6 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -234,12 +234,14 @@ namespace osu.Game.Overlays pendingBeatmapSwitch = null; } - if (musicController.IsDummyDevice == false) - { - progressBar.EndTime = musicController.TrackLength; - progressBar.CurrentTime = musicController.CurrentTrackTime; + var track = musicController.TrackLoaded ? musicController.CurrentTrack : null; - playButton.Icon = musicController.IsPlaying ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; + if (track?.IsDummyDevice == false) + { + progressBar.EndTime = track.Length; + progressBar.CurrentTime = track.CurrentTime; + + playButton.Icon = track.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; } else { diff --git a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs index 9b840cea08..5ae41fe09c 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Audio; using osu.Framework.Audio.Track; namespace osu.Game.Rulesets.Mods @@ -10,6 +11,6 @@ namespace osu.Game.Rulesets.Mods /// public interface IApplicableToTrack : IApplicableMod { - void ApplyToTrack(ITrack track); + void ApplyToTrack(T track) where T : ITrack, IAdjustableAudioComponent; } } diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 9cefeb3340..989978eb35 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; @@ -27,11 +26,11 @@ namespace osu.Game.Rulesets.Mods }, true); } - public override void ApplyToTrack(ITrack track) + public override void ApplyToTrack(T track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) - (track as Track)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - (track as Track)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } } } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index b34affa77f..70cdaa6345 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -38,11 +38,11 @@ namespace osu.Game.Rulesets.Mods }, true); } - public override void ApplyToTrack(ITrack track) + public override void ApplyToTrack(T track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) - (track as Track)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - (track as Track)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index ee1280da39..e2c8ac64d9 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -12,9 +12,9 @@ namespace osu.Game.Rulesets.Mods { public abstract BindableNumber SpeedChange { get; } - public virtual void ApplyToTrack(ITrack track) + public virtual void ApplyToTrack(T track) where T : ITrack, IAdjustableAudioComponent { - (track as Track)?.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); + track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); } public virtual void ApplyToSample(SampleChannel sample) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 0257e241b8..b6cbe72971 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mods Precision = 0.01, }; - private Track track; + private ITrack track; protected ModTimeRamp() { @@ -51,9 +51,9 @@ namespace osu.Game.Rulesets.Mods AdjustPitch.BindValueChanged(applyPitchAdjustment); } - public void ApplyToTrack(ITrack track) + public void ApplyToTrack(T track) where T : ITrack, IAdjustableAudioComponent { - this.track = track as Track; + this.track = track; FinalRate.TriggerChange(); AdjustPitch.TriggerChange(); @@ -89,9 +89,9 @@ namespace osu.Game.Rulesets.Mods private void applyPitchAdjustment(ValueChangedEvent adjustPitchSetting) { // remove existing old adjustment - track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); + (track as IAdjustableAudioComponent)?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); + (track as IAdjustableAudioComponent)?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); } private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue) diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 0a9b4f06a7..412efe266c 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -66,12 +66,12 @@ namespace osu.Game.Screens.Edit.Components } }; - musicController.AddAdjustment(AdjustableProperty.Tempo, tempo); + musicController.CurrentTrack?.AddAdjustment(AdjustableProperty.Tempo, tempo); } protected override void Dispose(bool isDisposing) { - musicController?.RemoveAdjustment(AdjustableProperty.Tempo, tempo); + musicController?.CurrentTrack?.RemoveAdjustment(AdjustableProperty.Tempo, tempo); base.Dispose(isDisposing); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index 446f7fdf88..24fb855009 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osuTK; @@ -57,7 +58,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts return; } - content.RelativeChildSize = new Vector2((float)Math.Max(1, musicController.TrackLength), 1); + Debug.Assert(musicController.CurrentTrack != null); + content.RelativeChildSize = new Vector2((float)Math.Max(1, musicController.CurrentTrack.Length), 1); } protected virtual void LoadBeatmap(WorkingBeatmap beatmap) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index f35e5defd8..d556d948f6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -60,21 +62,20 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Beatmap.BindValueChanged(b => { waveform.Waveform = b.NewValue.Waveform; + track = musicController.CurrentTrack; - // Todo: Wrong. - Schedule(() => + Debug.Assert(track != null); + + if (track.Length > 0) { - if (musicController.TrackLength > 0) - { - MaxZoom = getZoomLevelForVisibleMilliseconds(500); - MinZoom = getZoomLevelForVisibleMilliseconds(10000); - Zoom = getZoomLevelForVisibleMilliseconds(2000); - } - }); + MaxZoom = getZoomLevelForVisibleMilliseconds(500); + MinZoom = getZoomLevelForVisibleMilliseconds(10000); + Zoom = getZoomLevelForVisibleMilliseconds(2000); + } }, true); } - private float getZoomLevelForVisibleMilliseconds(double milliseconds) => (float)(musicController.TrackLength / milliseconds); + private float getZoomLevelForVisibleMilliseconds(double milliseconds) => (float)(track.Length / milliseconds); /// /// The timeline's scroll position in the last frame. @@ -96,6 +97,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline /// private bool trackWasPlaying; + private ITrack track; + protected override void Update() { base.Update(); @@ -136,15 +139,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (!musicController.TrackLoaded) return; - editorClock.Seek(Current / Content.DrawWidth * musicController.TrackLength); + editorClock.Seek(Current / Content.DrawWidth * track.Length); } private void scrollToTrackTime() { - if (!musicController.TrackLoaded || musicController.TrackLength == 0) + if (!musicController.TrackLoaded || track.Length == 0) return; - ScrollTo((float)(editorClock.CurrentTime / musicController.TrackLength) * Content.DrawWidth, false); + ScrollTo((float)(editorClock.CurrentTime / track.Length) * Content.DrawWidth, false); } protected override bool OnMouseDown(MouseDownEvent e) @@ -188,7 +191,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline new SnapResult(screenSpacePosition, beatSnapProvider.SnapTime(getTimeFromPosition(Content.ToLocalSpace(screenSpacePosition)))); private double getTimeFromPosition(Vector2 localPosition) => - (localPosition.X / Content.DrawWidth) * musicController.TrackLength; + (localPosition.X / Content.DrawWidth) * track.Length; public float GetBeatSnapDistanceAt(double referenceTime) => throw new NotImplementedException(); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index a833b354ed..ceb0275a13 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Overlays; @@ -43,7 +44,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) { var point = beatmap.ControlPointInfo.TimingPoints[i]; - var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : musicController.TrackLength; + var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : musicController.CurrentTrack.AsNonNull().Length; int beat = 0; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 756b03d049..b02aabc24d 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -83,7 +83,7 @@ namespace osu.Game.Screens.Edit beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); // Todo: should probably be done at a DrawableRuleset level to share logic with Player. - var sourceClock = musicController.GetTrackClock() ?? new StopwatchClock(); + var sourceClock = (IAdjustableClock)musicController.CurrentTrack ?? new StopwatchClock(); clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 4cb24f90a6..4e589aeeef 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit private void load() { // Todo: What. - TrackLength ??= musicController.TrackLength; + TrackLength ??= musicController.CurrentTrack?.Length ?? 0; } /// diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 7da5df2723..030923c228 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -113,7 +113,9 @@ namespace osu.Game.Screens.Menu if (setInfo != null) { initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - UsingThemedIntro = !MusicController.IsDummyDevice; + + // Todo: Wrong. + UsingThemedIntro = MusicController.CurrentTrack?.IsDummyDevice == false; } return UsingThemedIntro; diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 86a6fa3802..e29ea6e743 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Menu LoadComponentAsync(new TrianglesIntroSequence(logo, background) { RelativeSizeAxes = Axes.Both, - Clock = new FramedClock(UsingThemedIntro ? MusicController.GetTrackClock() : null), + Clock = new FramedClock(UsingThemedIntro ? MusicController.CurrentTrack : null), LoadMenu = LoadMenu }, t => { diff --git a/osu.Game/Screens/Menu/IntroWelcome.cs b/osu.Game/Screens/Menu/IntroWelcome.cs index 62cada577d..85f11eb244 100644 --- a/osu.Game/Screens/Menu/IntroWelcome.cs +++ b/osu.Game/Screens/Menu/IntroWelcome.cs @@ -44,7 +44,8 @@ namespace osu.Game.Screens.Menu pianoReverb = audio.Samples.Get(@"Intro/Welcome/welcome_piano"); - musicController.Looping = true; + if (musicController.CurrentTrack != null) + musicController.CurrentTrack.Looping = true; } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 349654165f..7a1ff4fa06 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -19,6 +19,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Utils; using osu.Game.Overlays; @@ -108,14 +109,14 @@ namespace osu.Game.Screens.Menu private void updateAmplitudes() { var effect = beatmap.Value.BeatmapLoaded && musicController.TrackLoaded - ? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(musicController.CurrentTrackTime) + ? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(musicController.CurrentTrack.AsNonNull().CurrentTime) : null; for (int i = 0; i < temporalAmplitudes.Length; i++) temporalAmplitudes[i] = 0; if (musicController.TrackLoaded) - addAmplitudesFromSource(musicController); + addAmplitudesFromSource(musicController.CurrentTrack.AsNonNull()); foreach (var source in amplitudeSources) addAmplitudesFromSource(source); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c422f57332..ce48777ce1 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; using System.Linq; using osuTK; using osuTK.Graphics; @@ -181,11 +182,12 @@ namespace osu.Game.Screens.Menu if (last is IntroScreen && musicController.TrackLoaded) { - // Todo: Wrong. - if (!musicController.IsPlaying) + Debug.Assert(musicController.CurrentTrack != null); + + if (!musicController.CurrentTrack.IsRunning) { - musicController.SeekTo(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.TrackLength); - musicController.Play(); + musicController.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.CurrentTrack.Length); + musicController.CurrentTrack.Start(); } } diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 1feb2481c3..f028f9b229 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -330,9 +330,9 @@ namespace osu.Game.Screens.Menu const float velocity_adjust_cutoff = 0.98f; const float paused_velocity = 0.5f; - if (musicController.IsPlaying) + if (musicController.CurrentTrack?.IsRunning == true) { - var maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentAmplitudes.Maximum : 0; + var maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0; logoAmplitudeContainer.Scale = new Vector2((float)Interpolation.Damp(logoAmplitudeContainer.Scale.X, 1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 0.9f, Time.Elapsed)); if (maxAmplitude > velocity_adjust_cutoff) diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index 032c8d5ca9..c7dc20ff23 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Multi.Match.Components return; } - bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(musicController.TrackLength) < endDate.Value; + bool hasEnoughTime = musicController.CurrentTrack != null && DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(musicController.CurrentTrack.Length) < endDate.Value; Enabled.Value = hasBeatmap && hasEnoughTime; } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 2d74434c76..e068899c7b 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -343,9 +343,13 @@ namespace osu.Game.Screens.Multi { if (screenStack.CurrentScreen is MatchSubScreen) { - musicController.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - musicController.Looping = true; - musicController.EnsurePlayingSomething(); + if (musicController.CurrentTrack != null) + { + musicController.CurrentTrack.RestartPoint = Beatmap.Value.Metadata.PreviewTime; + musicController.CurrentTrack.Looping = true; + + musicController.EnsurePlayingSomething(); + } } else { @@ -355,8 +359,11 @@ namespace osu.Game.Screens.Multi private void cancelLooping() { - musicController.Looping = false; - musicController.RestartPoint = 0; + if (musicController.CurrentTrack != null) + { + musicController.CurrentTrack.Looping = false; + musicController.CurrentTrack.RestartPoint = 0; + } } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index 0e0ef8c675..1171d8c3b0 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; +using osu.Framework.Graphics.Audio; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Overlays; @@ -30,21 +31,21 @@ namespace osu.Game.Screens.Play private readonly BindableDouble trackFreq = new BindableDouble(1); + private DrawableTrack track; + private const float duration = 2500; private SampleChannel failSample; - [Resolved] - private MusicController musicController { get; set; } - public FailAnimation(DrawableRuleset drawableRuleset) { this.drawableRuleset = drawableRuleset; } [BackgroundDependencyLoader] - private void load(AudioManager audio, IBindable beatmap) + private void load(AudioManager audio, IBindable beatmap, MusicController musicController) { + track = musicController.CurrentTrack; failSample = audio.Samples.Get(@"Gameplay/failsound"); } @@ -68,7 +69,7 @@ namespace osu.Game.Screens.Play Expire(); }); - musicController.AddAdjustment(AdjustableProperty.Frequency, trackFreq); + track.AddAdjustment(AdjustableProperty.Frequency, trackFreq); applyToPlayfield(drawableRuleset.Playfield); drawableRuleset.Playfield.HitObjectContainer.FlashColour(Color4.Red, 500); @@ -107,7 +108,7 @@ namespace osu.Game.Screens.Play protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - musicController?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); + track?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); } } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index cf4678ab29..61272f56ad 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -8,8 +8,10 @@ using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -27,8 +29,7 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private readonly IReadOnlyList mods; - [Resolved] - private MusicController musicController { get; set; } + private DrawableTrack track; public readonly BindableBool IsPaused = new BindableBool(); @@ -95,8 +96,10 @@ namespace osu.Game.Screens.Play private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load(OsuConfigManager config, MusicController musicController) { + track = musicController.CurrentTrack; + userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); @@ -121,15 +124,15 @@ namespace osu.Game.Screens.Play { // The Reset() call below causes speed adjustments to be reset in an async context, leading to deadlocks. // The deadlock can be prevented by resetting the track synchronously before entering the async context. - musicController.Reset(); + track.ResetSpeedAdjustments(); Task.Run(() => { - musicController.Reset(); + track.Reset(); Schedule(() => { - adjustableClock.ChangeSource(musicController.GetTrackClock()); + adjustableClock.ChangeSource(track); updateRate(); if (!IsPaused.Value) @@ -190,6 +193,20 @@ namespace osu.Game.Screens.Play IsPaused.Value = true; } + /// + /// Changes the backing clock to avoid using the originally provided track. + /// + public void StopUsingBeatmapClock() + { + if (track == null) + return; + + removeSourceClockAdjustments(); + + track = new DrawableTrack(new TrackVirtual(track.Length)); + adjustableClock.ChangeSource(track); + } + protected override void Update() { if (!IsPaused.Value) @@ -202,23 +219,30 @@ namespace osu.Game.Screens.Play private void updateRate() { + if (track == null) return; + speedAdjustmentsApplied = true; - musicController.ResetTrackAdjustments(); - musicController.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); - musicController.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); + track.ResetSpeedAdjustments(); + + track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); + + foreach (var mod in mods.OfType()) + mod.ApplyToTrack(track); } protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); removeSourceClockAdjustments(); + track = null; } private void removeSourceClockAdjustments() { if (speedAdjustmentsApplied) { - musicController.ResetTrackAdjustments(); + track.ResetSpeedAdjustments(); speedAdjustmentsApplied = false; } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 9ba2732920..ea04d82e67 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using osu.Framework.Audio.Track; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Game.Graphics.UserInterface; @@ -560,9 +561,9 @@ namespace osu.Game.Screens.Select BeatmapDetails.Refresh(); - if (music != null) + if (music?.CurrentTrack != null) { - music.Looping = true; + music.CurrentTrack.Looping = true; music.ResetTrackAdjustments(); } @@ -588,8 +589,8 @@ namespace osu.Game.Screens.Select BeatmapOptions.Hide(); - if (music != null) - music.Looping = false; + if (music?.CurrentTrack != null) + music.CurrentTrack.Looping = false; this.ScaleTo(1.1f, 250, Easing.InSine); @@ -610,8 +611,8 @@ namespace osu.Game.Screens.Select FilterControl.Deactivate(); - if (music != null) - music.Looping = false; + if (music?.CurrentTrack != null) + music.CurrentTrack.Looping = false; return false; } @@ -652,18 +653,30 @@ namespace osu.Game.Screens.Select BeatmapDetails.Beatmap = beatmap; - if (music != null) - music.Looping = false; + if (music?.CurrentTrack != null) + music.CurrentTrack.Looping = false; } + private readonly WeakReference lastTrack = new WeakReference(null); + /// /// Ensures some music is playing for the current track. /// Will resume playback from a manual user pause if the track has changed. /// private void ensurePlayingSelected() { - music.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - music.EnsurePlayingSomething(); + ITrack track = music?.CurrentTrack; + if (track == null) + return; + + bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; + + track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; + + if (!track.IsRunning && (music?.IsUserPaused != true || isNewTrack)) + music?.Play(true); + + lastTrack.SetTarget(track); } private void carouselBeatmapsLoaded() diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 5226a49def..780b4f1b3a 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(ValueChangedEvent e) { Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; - Clock.ChangeSource(MusicController.GetTrackClock() ?? new StopwatchClock()); + Clock.ChangeSource((IAdjustableClock)MusicController.CurrentTrack ?? new StopwatchClock()); Clock.ProcessFrame(); } diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index e7cb461d7b..ae4b0ef84a 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Extensions.ObjectExtensions; + namespace osu.Game.Tests.Visual { /// @@ -13,7 +15,7 @@ namespace osu.Game.Tests.Visual base.Update(); // note that this will override any mod rate application - MusicController.Tempo.Value = Clock.Rate; + MusicController.CurrentTrack.AsNonNull().Tempo.Value = Clock.Rate; } } } From 58660c70a3c9cad61e78ef854d238e8f569ee08e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Aug 2020 21:20:41 +0900 Subject: [PATCH 03/86] Cache before idle tracker --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 929254e8ad..3e41be2028 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -554,8 +554,8 @@ namespace osu.Game Container logoContainer; BackButton.Receptor receptor; - dependencies.CacheAs(idleTracker = new GameIdleTracker(6000)); dependencies.CacheAs(MusicController = new MusicController()); + dependencies.CacheAs(idleTracker = new GameIdleTracker(6000)); AddRange(new Drawable[] { From e9fc783b1d75f31ec8291fa8a11f254f28cb1860 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Aug 2020 21:21:08 +0900 Subject: [PATCH 04/86] Add back loop-on-completion --- osu.Game/OsuGame.cs | 18 +----------------- osu.Game/Overlays/MusicController.cs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3e41be2028..a41c7b28a5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -427,23 +427,7 @@ namespace osu.Game updateModDefaults(); - var newBeatmap = beatmap.NewValue; - - if (newBeatmap != null) - { - // MusicController.Completed += () => Scheduler.AddOnce(() => trackCompleted(newBeatmap)); - newBeatmap.BeginAsyncLoad(); - } - - // void trackCompleted(WorkingBeatmap b) - // { - // // the source of track completion is the audio thread, so the beatmap may have changed before firing. - // if (Beatmap.Value != b) - // return; - // - // if (!MusicController.Looping && !Beatmap.Disabled) - // MusicController.NextTrack(); - // } + beatmap.NewValue?.BeginAsyncLoad(); } private void modsChanged(ValueChangedEvent> mods) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index c22849b7d6..50ad97be7c 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -323,7 +324,10 @@ namespace osu.Game.Overlays CurrentTrack = null; if (current != null) + { trackContainer.Add(CurrentTrack = new DrawableTrack(current.GetRealTrack())); + CurrentTrack.Completed += () => onTrackCompleted(current); + } TrackChanged?.Invoke(current, direction); @@ -332,6 +336,18 @@ namespace osu.Game.Overlays queuedDirection = null; } + private void onTrackCompleted(WorkingBeatmap workingBeatmap) + { + // the source of track completion is the audio thread, so the beatmap may have changed before firing. + if (current != workingBeatmap) + return; + + Debug.Assert(CurrentTrack != null); + + if (!CurrentTrack.Looping && !beatmap.Disabled) + NextTrack(); + } + private bool allowRateAdjustments; /// From 11a6c9bdccc65e89575a0e138512ccc379b1a15f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Aug 2020 21:21:14 +0900 Subject: [PATCH 05/86] Revert unnecessary change --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 92a9ed0566..69021e1634 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -64,7 +64,7 @@ namespace osu.Game.Graphics.Containers beatmap = Beatmap.Value.Beatmap; } - if (track != null && beatmap != null && musicController.IsPlaying && track.Length > 0) + if (track != null && beatmap != null && track.IsRunning && track.Length > 0) { currentTrackTime = track.CurrentTime + EarlyActivationMilliseconds; From f058f5e977bbfb532b2711e0101c76868022b808 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Aug 2020 21:29:53 +0900 Subject: [PATCH 06/86] Fix incorrect value being set --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index ea04d82e67..80ed894233 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -654,7 +654,7 @@ namespace osu.Game.Screens.Select BeatmapDetails.Beatmap = beatmap; if (music?.CurrentTrack != null) - music.CurrentTrack.Looping = false; + music.CurrentTrack.Looping = true; } private readonly WeakReference lastTrack = new WeakReference(null); From 0edd50939783f86909c3e024d47100259417c42e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Aug 2020 21:30:11 +0900 Subject: [PATCH 07/86] Only change track when audio doesn't equal --- osu.Game/Overlays/MusicController.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 50ad97be7c..47d1bef177 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -320,6 +320,18 @@ namespace osu.Game.Overlays current = beatmap.NewValue; + if (!beatmap.OldValue.BeatmapInfo.AudioEquals(current?.BeatmapInfo)) + changeTrack(); + + TrackChanged?.Invoke(current, direction); + + ResetTrackAdjustments(); + + queuedDirection = null; + } + + private void changeTrack() + { CurrentTrack?.Expire(); CurrentTrack = null; @@ -328,12 +340,6 @@ namespace osu.Game.Overlays trackContainer.Add(CurrentTrack = new DrawableTrack(current.GetRealTrack())); CurrentTrack.Completed += () => onTrackCompleted(current); } - - TrackChanged?.Invoke(current, direction); - - ResetTrackAdjustments(); - - queuedDirection = null; } private void onTrackCompleted(WorkingBeatmap workingBeatmap) From 86ae61c6b79aec0febbe8220781cc7ad3aefb9de Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Aug 2020 22:09:47 +0900 Subject: [PATCH 08/86] Re-implement store transferral in BeatmapManager --- osu.Game/Beatmaps/BeatmapManager.cs | 19 +++++++++++-------- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 17 +++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b2329f58ad..6a7d0b053f 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -218,7 +218,7 @@ namespace osu.Game.Beatmaps removeWorkingCache(info); } - private readonly WeakList workingCache = new WeakList(); + private readonly WeakList workingCache = new WeakList(); /// /// Retrieve a instance for the provided @@ -246,16 +246,19 @@ namespace osu.Game.Beatmaps lock (workingCache) { var working = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID); + if (working != null) + return working; - if (working == null) - { - beatmapInfo.Metadata ??= beatmapInfo.BeatmapSet.Metadata; + beatmapInfo.Metadata ??= beatmapInfo.BeatmapSet.Metadata; - workingCache.Add(working = new BeatmapManagerWorkingBeatmap(Files.Store, - new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager)); - } + ITrackStore trackStore = workingCache.FirstOrDefault(b => b.BeatmapInfo.AudioEquals(beatmapInfo))?.TrackStore; + TextureStore textureStore = workingCache.FirstOrDefault(b => b.BeatmapInfo.BackgroundEquals(beatmapInfo))?.TextureStore; + + textureStore ??= new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)); + trackStore ??= audioManager.GetTrackStore(Files.Store); + + workingCache.Add(working = new BeatmapManagerWorkingBeatmap(Files.Store, textureStore, trackStore, beatmapInfo, audioManager)); - // previous?.TransferTo(working); return working; } } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 33945a9eb1..ceefef5d7e 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -19,13 +19,18 @@ namespace osu.Game.Beatmaps { protected class BeatmapManagerWorkingBeatmap : WorkingBeatmap { + public readonly TextureStore TextureStore; + public readonly ITrackStore TrackStore; + private readonly IResourceStore store; - public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, BeatmapInfo beatmapInfo, AudioManager audioManager) + public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, ITrackStore trackStore, BeatmapInfo beatmapInfo, AudioManager audioManager) : base(beatmapInfo, audioManager) { this.store = store; - this.textureStore = textureStore; + + TextureStore = textureStore; + TrackStore = trackStore; } protected override IBeatmap GetBeatmap() @@ -44,10 +49,6 @@ namespace osu.Game.Beatmaps private string getPathForFile(string filename) => BeatmapSetInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; - private TextureStore textureStore; - - private ITrackStore trackStore; - protected override bool BackgroundStillValid(Texture b) => false; // bypass lazy logic. we want to return a new background each time for refcounting purposes. protected override Texture GetBackground() @@ -57,7 +58,7 @@ namespace osu.Game.Beatmaps try { - return textureStore.Get(getPathForFile(Metadata.BackgroundFile)); + return TextureStore.Get(getPathForFile(Metadata.BackgroundFile)); } catch (Exception e) { @@ -70,7 +71,7 @@ namespace osu.Game.Beatmaps { try { - return (trackStore ??= AudioManager.GetTrackStore(store)).Get(getPathForFile(Metadata.AudioFile)); + return TrackStore.Get(getPathForFile(Metadata.AudioFile)); } catch (Exception e) { From 0f7fde5d2cd5db7eb8e621bfe221ea28cc252da8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Aug 2020 22:32:44 +0900 Subject: [PATCH 09/86] Revert unnecessary change --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index c089158c01..b9a58c37cb 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -83,7 +83,10 @@ namespace osu.Game.Overlays.Music BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); if (toSelect != null) + { beatmap.Value = beatmaps.GetWorkingBeatmap(toSelect); + musicController.CurrentTrack?.Restart(); + } }; } @@ -116,12 +119,12 @@ namespace osu.Game.Overlays.Music { if (set.ID == (beatmap.Value?.BeatmapSetInfo?.ID ?? -1)) { - musicController.SeekTo(0); + musicController.CurrentTrack?.Seek(0); return; } beatmap.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First()); - musicController.Play(true); + musicController.CurrentTrack?.Restart(); } } From fe8c462498ad18a842544202bc4e6a14d3e217ed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 17:00:17 +0900 Subject: [PATCH 10/86] Remove intermediate container --- osu.Game/Overlays/MusicController.cs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 47d1bef177..6adfa1817e 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -65,20 +65,12 @@ namespace osu.Game.Overlays [Resolved(canBeNull: true)] private OnScreenDisplay onScreenDisplay { get; set; } - [NotNull] - private readonly TrackContainer trackContainer; - [CanBeNull] public DrawableTrack CurrentTrack { get; private set; } private IBindable> managerUpdated; private IBindable> managerRemoved; - public MusicController() - { - InternalChild = trackContainer = new TrackContainer { RelativeSizeAxes = Axes.Both }; - } - [BackgroundDependencyLoader] private void load() { @@ -337,8 +329,10 @@ namespace osu.Game.Overlays if (current != null) { - trackContainer.Add(CurrentTrack = new DrawableTrack(current.GetRealTrack())); + CurrentTrack = new DrawableTrack(current.GetRealTrack()); CurrentTrack.Completed += () => onTrackCompleted(current); + + AddInternal(CurrentTrack); } } @@ -433,10 +427,6 @@ namespace osu.Game.Overlays { } } - - private class TrackContainer : AudioContainer - { - } } public enum TrackChangeDirection From e8ab3cff3c38c5dad046b0c69f0f34b7478a08ce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 17:02:42 +0900 Subject: [PATCH 11/86] Add class constraint --- osu.Game/Rulesets/Mods/IApplicableToTrack.cs | 2 +- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 3 ++- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs index 5ae41fe09c..b29ba55942 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Mods /// public interface IApplicableToTrack : IApplicableMod { - void ApplyToTrack(T track) where T : ITrack, IAdjustableAudioComponent; + void ApplyToTrack(T track) where T : class, ITrack, IAdjustableAudioComponent; } } diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index e2c8ac64d9..4aee5affe9 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -12,7 +12,8 @@ namespace osu.Game.Rulesets.Mods { public abstract BindableNumber SpeedChange { get; } - public virtual void ApplyToTrack(T track) where T : ITrack, IAdjustableAudioComponent + public virtual void ApplyToTrack(T track) + where T : class, ITrack, IAdjustableAudioComponent { track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index b6cbe72971..4b5241488f 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -51,7 +51,8 @@ namespace osu.Game.Rulesets.Mods AdjustPitch.BindValueChanged(applyPitchAdjustment); } - public void ApplyToTrack(T track) where T : ITrack, IAdjustableAudioComponent + public void ApplyToTrack(T track) + where T : class, ITrack, IAdjustableAudioComponent { this.track = track; From c72ab9047e3ea00dbc6eb176a797d20dfd5c95d3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 17:15:33 +0900 Subject: [PATCH 12/86] Cleanup test scene disposal --- osu.Game/Tests/Visual/OsuTestScene.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index e968f7e675..f2b9388fdc 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -169,7 +170,10 @@ namespace osu.Game.Tests.Visual rulesetDependencies?.Dispose(); if (MusicController?.TrackLoaded == true) - MusicController.Stop(); + { + Debug.Assert(MusicController.CurrentTrack != null); + MusicController.CurrentTrack.Stop(); + } if (contextFactory.IsValueCreated) contextFactory.Value.ResetDatabase(); From f53672193eb6ccd1d14c7900603aa5269e7468c9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 17:48:07 +0900 Subject: [PATCH 13/86] Fix track stores being kept alive --- osu.Game/Beatmaps/BeatmapManager.cs | 16 +++++++++++++++- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 10 +++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6a7d0b053f..f22f41531a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -219,6 +219,7 @@ namespace osu.Game.Beatmaps } private readonly WeakList workingCache = new WeakList(); + private readonly Dictionary referencedTrackStores = new Dictionary(); /// /// Retrieve a instance for the provided @@ -257,12 +258,25 @@ namespace osu.Game.Beatmaps textureStore ??= new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)); trackStore ??= audioManager.GetTrackStore(Files.Store); - workingCache.Add(working = new BeatmapManagerWorkingBeatmap(Files.Store, textureStore, trackStore, beatmapInfo, audioManager)); + workingCache.Add(working = new BeatmapManagerWorkingBeatmap(Files.Store, textureStore, trackStore, beatmapInfo, audioManager, dereferenceTrackStore)); + referencedTrackStores[trackStore] = referencedTrackStores.GetOrDefault(trackStore) + 1; return working; } } + private void dereferenceTrackStore(ITrackStore trackStore) + { + lock (workingCache) + { + if (--referencedTrackStores[trackStore] == 0) + { + referencedTrackStores.Remove(trackStore); + trackStore.Dispose(); + } + } + } + /// /// Perform a lookup query on available s. /// diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index ceefef5d7e..a54d46c1b1 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -23,11 +23,14 @@ namespace osu.Game.Beatmaps public readonly ITrackStore TrackStore; private readonly IResourceStore store; + private readonly Action dereferenceAction; - public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, ITrackStore trackStore, BeatmapInfo beatmapInfo, AudioManager audioManager) + public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, ITrackStore trackStore, BeatmapInfo beatmapInfo, AudioManager audioManager, + Action dereferenceAction) : base(beatmapInfo, audioManager) { this.store = store; + this.dereferenceAction = dereferenceAction; TextureStore = textureStore; TrackStore = trackStore; @@ -137,6 +140,11 @@ namespace osu.Game.Beatmaps return null; } } + + ~BeatmapManagerWorkingBeatmap() + { + dereferenceAction?.Invoke(TrackStore); + } } } } From c8ebbc8594b79423825614268feb88f2f20a32e6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 18:19:55 +0900 Subject: [PATCH 14/86] Remove MusicController from EditorClock --- .../Timelines/Summary/Parts/MarkerPart.cs | 5 +-- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 36 ++++++------------- 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index a353f79ef4..9e9ac93d23 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics; using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -59,9 +58,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts return; float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); - - Debug.Assert(editorClock.TrackLength != null); - editorClock.SeekTo(markerPos / DrawWidth * editorClock.TrackLength.Value); + editorClock.SeekTo(markerPos / DrawWidth * editorClock.TrackLength); }); } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index b02aabc24d..79b13a7eac 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit // Todo: should probably be done at a DrawableRuleset level to share logic with Player. var sourceClock = (IAdjustableClock)musicController.CurrentTrack ?? new StopwatchClock(); - clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; + clock = new EditorClock(Beatmap.Value, musicController.CurrentTrack?.Length ?? 0, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); dependencies.CacheAs(clock); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 4e589aeeef..fbfa397795 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -2,16 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Overlays; namespace osu.Game.Screens.Edit { @@ -20,7 +17,7 @@ namespace osu.Game.Screens.Edit /// public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock { - public double? TrackLength { get; private set; } + public readonly double TrackLength; public ControlPointInfo ControlPointInfo; @@ -28,34 +25,24 @@ namespace osu.Game.Screens.Edit private readonly DecoupleableInterpolatingFramedClock underlyingClock; - [Resolved] - private MusicController musicController { get; set; } - - public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) - : this(beatmap.Beatmap.ControlPointInfo, null, beatDivisor) + public EditorClock(WorkingBeatmap beatmap, double trackLength, BindableBeatDivisor beatDivisor) + : this(beatmap.Beatmap.ControlPointInfo, trackLength, beatDivisor) { } - public EditorClock(ControlPointInfo controlPointInfo, double? trackLength, BindableBeatDivisor beatDivisor) - { - this.beatDivisor = beatDivisor; - - ControlPointInfo = controlPointInfo; - TrackLength = trackLength; - - underlyingClock = new DecoupleableInterpolatingFramedClock(); - } - public EditorClock() : this(new ControlPointInfo(), 1000, new BindableBeatDivisor()) { } - [BackgroundDependencyLoader] - private void load() + public EditorClock(ControlPointInfo controlPointInfo, double trackLength, BindableBeatDivisor beatDivisor) { - // Todo: What. - TrackLength ??= musicController.CurrentTrack?.Length ?? 0; + this.beatDivisor = beatDivisor; + + ControlPointInfo = controlPointInfo; + TrackLength = trackLength; + + underlyingClock = new DecoupleableInterpolatingFramedClock(); } /// @@ -148,8 +135,7 @@ namespace osu.Game.Screens.Edit seekTime = timingPoint.Time; // Ensure the sought point is within the boundaries - Debug.Assert(TrackLength != null); - seekTime = Math.Clamp(seekTime, 0, TrackLength.Value); + seekTime = Math.Clamp(seekTime, 0, TrackLength); SeekTo(seekTime); } From 7c3ae4ed4291eeb86f704344956dedfef75e8735 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 18:25:34 +0900 Subject: [PATCH 15/86] Remove generics from IApplicableToTrack --- osu.Game/Rulesets/Mods/IApplicableToTrack.cs | 3 +-- osu.Game/Rulesets/Mods/ModDaycore.cs | 7 ++++--- osu.Game/Rulesets/Mods/ModNightcore.cs | 6 +++--- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 5 ++--- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +-- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs index b29ba55942..9b840cea08 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Audio; using osu.Framework.Audio.Track; namespace osu.Game.Rulesets.Mods @@ -11,6 +10,6 @@ namespace osu.Game.Rulesets.Mods /// public interface IApplicableToTrack : IApplicableMod { - void ApplyToTrack(T track) where T : class, ITrack, IAdjustableAudioComponent; + void ApplyToTrack(ITrack track); } } diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 989978eb35..800312d047 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; @@ -26,11 +27,11 @@ namespace osu.Game.Rulesets.Mods }, true); } - public override void ApplyToTrack(T track) + public override void ApplyToTrack(ITrack track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) - track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } } } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 70cdaa6345..4932df08f1 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -38,11 +38,11 @@ namespace osu.Game.Rulesets.Mods }, true); } - public override void ApplyToTrack(T track) + public override void ApplyToTrack(ITrack track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) - track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index 4aee5affe9..ae7077c67b 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -12,10 +12,9 @@ namespace osu.Game.Rulesets.Mods { public abstract BindableNumber SpeedChange { get; } - public virtual void ApplyToTrack(T track) - where T : class, ITrack, IAdjustableAudioComponent + public virtual void ApplyToTrack(ITrack track) { - track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); + (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); } public virtual void ApplyToSample(SampleChannel sample) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 4b5241488f..b904cf007b 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -51,8 +51,7 @@ namespace osu.Game.Rulesets.Mods AdjustPitch.BindValueChanged(applyPitchAdjustment); } - public void ApplyToTrack(T track) - where T : class, ITrack, IAdjustableAudioComponent + public void ApplyToTrack(ITrack track) { this.track = track; From 2e3ecf71c70c035db37621df04cc289a4b7d7489 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 18:31:08 +0900 Subject: [PATCH 16/86] Pass track from Player to components --- .../TestSceneGameplayClockContainer.cs | 7 +++++- .../Gameplay/TestSceneStoryboardSamples.cs | 6 +++-- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 4 +++- osu.Game/Screens/Play/FailAnimation.cs | 16 ++++++-------- .../Screens/Play/GameplayClockContainer.cs | 22 +++++++++---------- osu.Game/Screens/Play/Player.cs | 11 +++++----- 6 files changed, 36 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs index cd3669f160..40f6cecd9a 100644 --- a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs @@ -19,7 +19,12 @@ namespace osu.Game.Tests.Gameplay { GameplayClockContainer gcc = null; - AddStep("create container", () => Add(gcc = new GameplayClockContainer(CreateWorkingBeatmap(new OsuRuleset().RulesetInfo), Array.Empty(), 0))); + AddStep("create container", () => + { + var working = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + Add(gcc = new GameplayClockContainer(working.GetRealTrack(), working, Array.Empty(), 0)); + }); + AddStep("start track", () => gcc.Start()); AddUntilStep("elapsed greater than zero", () => gcc.GameplayClock.ElapsedFrameTime > 0); } diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index b30870d057..720436fae4 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -59,7 +59,9 @@ namespace osu.Game.Tests.Gameplay AddStep("create container", () => { - Add(gameplayContainer = new GameplayClockContainer(CreateWorkingBeatmap(new OsuRuleset().RulesetInfo), Array.Empty(), 0)); + var working = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + + Add(gameplayContainer = new GameplayClockContainer(working.GetRealTrack(), working, Array.Empty(), 0)); gameplayContainer.Add(sample = new DrawableStoryboardSample(new StoryboardSampleInfo(string.Empty, 0, 1)) { @@ -103,7 +105,7 @@ namespace osu.Game.Tests.Gameplay Beatmap.Value = new TestCustomSkinWorkingBeatmap(new OsuRuleset().RulesetInfo, Audio); SelectedMods.Value = new[] { testedMod }; - Add(gameplayContainer = new GameplayClockContainer(Beatmap.Value, SelectedMods.Value, 0)); + Add(gameplayContainer = new GameplayClockContainer(MusicController.CurrentTrack, Beatmap.Value, SelectedMods.Value, 0)); gameplayContainer.Add(sample = new TestDrawableStoryboardSample(new StoryboardSampleInfo("test-sample", 1, 1)) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 7ed7a116b4..68110d759c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -32,7 +32,9 @@ namespace osu.Game.Tests.Visual.Gameplay requestCount = 0; increment = skip_time; - Child = gameplayClockContainer = new GameplayClockContainer(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), Array.Empty(), 0) + var working = CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); + + Child = gameplayClockContainer = new GameplayClockContainer(working.GetRealTrack(), working, Array.Empty(), 0) { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index 1171d8c3b0..a7bfca612e 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -8,11 +8,10 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; +using osu.Framework.Audio.Track; using osu.Framework.Graphics; -using osu.Framework.Graphics.Audio; using osu.Framework.Utils; using osu.Game.Beatmaps; -using osu.Game.Overlays; using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Graphics; @@ -28,24 +27,23 @@ namespace osu.Game.Screens.Play public Action OnComplete; private readonly DrawableRuleset drawableRuleset; + private readonly ITrack track; private readonly BindableDouble trackFreq = new BindableDouble(1); - private DrawableTrack track; - private const float duration = 2500; private SampleChannel failSample; - public FailAnimation(DrawableRuleset drawableRuleset) + public FailAnimation(DrawableRuleset drawableRuleset, ITrack track) { this.drawableRuleset = drawableRuleset; + this.track = track; } [BackgroundDependencyLoader] - private void load(AudioManager audio, IBindable beatmap, MusicController musicController) + private void load(AudioManager audio, IBindable beatmap) { - track = musicController.CurrentTrack; failSample = audio.Samples.Get(@"Gameplay/failsound"); } @@ -69,7 +67,7 @@ namespace osu.Game.Screens.Play Expire(); }); - track.AddAdjustment(AdjustableProperty.Frequency, trackFreq); + (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, trackFreq); applyToPlayfield(drawableRuleset.Playfield); drawableRuleset.Playfield.HitObjectContainer.FlashColour(Color4.Red, 500); @@ -108,7 +106,7 @@ namespace osu.Game.Screens.Play protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - track?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); + (track as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); } } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 61272f56ad..c4f368e1f5 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -11,12 +11,10 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Overlays; using osu.Game.Rulesets.Mods; namespace osu.Game.Screens.Play @@ -29,7 +27,7 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private readonly IReadOnlyList mods; - private DrawableTrack track; + private ITrack track; public readonly BindableBool IsPaused = new BindableBool(); @@ -62,11 +60,13 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; - public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) + public GameplayClockContainer(ITrack track, WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) { this.beatmap = beatmap; this.mods = mods; this.gameplayStartTime = gameplayStartTime; + this.track = track; + firstHitObjectTime = beatmap.Beatmap.HitObjects.First().StartTime; RelativeSizeAxes = Axes.Both; @@ -96,10 +96,8 @@ namespace osu.Game.Screens.Play private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); [BackgroundDependencyLoader] - private void load(OsuConfigManager config, MusicController musicController) + private void load(OsuConfigManager config) { - track = musicController.CurrentTrack; - userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); @@ -132,7 +130,7 @@ namespace osu.Game.Screens.Play Schedule(() => { - adjustableClock.ChangeSource(track); + adjustableClock.ChangeSource((IAdjustableClock)track); updateRate(); if (!IsPaused.Value) @@ -203,8 +201,8 @@ namespace osu.Game.Screens.Play removeSourceClockAdjustments(); - track = new DrawableTrack(new TrackVirtual(track.Length)); - adjustableClock.ChangeSource(track); + track = new TrackVirtual(track.Length); + adjustableClock.ChangeSource((IAdjustableClock)track); } protected override void Update() @@ -224,8 +222,8 @@ namespace osu.Game.Screens.Play speedAdjustmentsApplied = true; track.ResetSpeedAdjustments(); - track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); - track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); + (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); foreach (var mod in mods.OfType()) mod.ApplyToTrack(track); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 541275cf55..e92164de7c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -8,6 +8,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -150,7 +151,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuConfigManager config) + private void load(AudioManager audio, OsuConfigManager config, MusicController musicController) { Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); @@ -178,7 +179,7 @@ namespace osu.Game.Screens.Play if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); + InternalChild = GameplayClockContainer = new GameplayClockContainer(musicController.CurrentTrack, Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); @@ -187,7 +188,7 @@ namespace osu.Game.Screens.Play addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, Beatmap.Value, playableBeatmap); - addOverlayComponents(GameplayClockContainer, Beatmap.Value); + addOverlayComponents(GameplayClockContainer, Beatmap.Value, musicController.CurrentTrack); if (!DrawableRuleset.AllowGameplayOverlays) { @@ -264,7 +265,7 @@ namespace osu.Game.Screens.Play }); } - private void addOverlayComponents(Container target, WorkingBeatmap working) + private void addOverlayComponents(Container target, WorkingBeatmap working, ITrack track) { target.AddRange(new[] { @@ -331,7 +332,7 @@ namespace osu.Game.Screens.Play performImmediateExit(); }, }, - failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, }, + failAnimation = new FailAnimation(DrawableRuleset, track) { OnComplete = onFailComplete, }, }); } From ef689d943aafc413dac909da50d96532816abd6c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 18:54:08 +0900 Subject: [PATCH 17/86] Fix intros playing incorrectly --- osu.Game/OsuGame.cs | 4 ++-- osu.Game/Screens/Menu/IntroScreen.cs | 13 +++++++------ osu.Game/Screens/Menu/IntroTriangles.cs | 2 +- osu.Game/Screens/Menu/IntroWelcome.cs | 9 ++------- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a41c7b28a5..0049e5a520 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -581,6 +581,8 @@ namespace osu.Game ScreenStack.ScreenPushed += screenPushed; ScreenStack.ScreenExited += screenExited; + loadComponentSingleFile(MusicController, Add); + loadComponentSingleFile(osuLogo, logo => { logoContainer.Add(logo); @@ -602,8 +604,6 @@ namespace osu.Game loadComponentSingleFile(new OnScreenDisplay(), Add, true); - loadComponentSingleFile(MusicController, Add); - loadComponentSingleFile(notifications.With(d => { d.GetToolbarHeight = () => ToolbarOffset; diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 030923c228..7e327261ab 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -44,8 +44,7 @@ namespace osu.Game.Screens.Menu private WorkingBeatmap initialBeatmap; - [Resolved] - protected MusicController MusicController { get; private set; } + protected ITrack Track { get; private set; } private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); @@ -62,6 +61,9 @@ namespace osu.Game.Screens.Menu [Resolved] private AudioManager audio { get; set; } + [Resolved] + private MusicController musicController { get; set; } + /// /// Whether the is provided by osu! resources, rather than a user beatmap. /// @@ -113,9 +115,7 @@ namespace osu.Game.Screens.Menu if (setInfo != null) { initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - - // Todo: Wrong. - UsingThemedIntro = MusicController.CurrentTrack?.IsDummyDevice == false; + UsingThemedIntro = initialBeatmap.GetRealTrack().IsDummyDevice == false; } return UsingThemedIntro; @@ -154,7 +154,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) - MusicController.Play(true); + Track.Restart(); } protected override void LogoArriving(OsuLogo logo, bool resuming) @@ -168,6 +168,7 @@ namespace osu.Game.Screens.Menu if (!resuming) { beatmap.Value = initialBeatmap; + Track = musicController.CurrentTrack; logo.MoveTo(new Vector2(0.5f)); logo.ScaleTo(Vector2.One); diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index e29ea6e743..86f7dbdd6f 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Menu LoadComponentAsync(new TrianglesIntroSequence(logo, background) { RelativeSizeAxes = Axes.Both, - Clock = new FramedClock(UsingThemedIntro ? MusicController.CurrentTrack : null), + Clock = new FramedClock(UsingThemedIntro ? (IAdjustableClock)Track : null), LoadMenu = LoadMenu }, t => { diff --git a/osu.Game/Screens/Menu/IntroWelcome.cs b/osu.Game/Screens/Menu/IntroWelcome.cs index 85f11eb244..e81646456f 100644 --- a/osu.Game/Screens/Menu/IntroWelcome.cs +++ b/osu.Game/Screens/Menu/IntroWelcome.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osuTK.Graphics; @@ -31,9 +30,6 @@ namespace osu.Game.Screens.Menu Alpha = 0, }; - [Resolved] - private MusicController musicController { get; set; } - private BackgroundScreenDefault background; [BackgroundDependencyLoader] @@ -43,9 +39,6 @@ namespace osu.Game.Screens.Menu welcome = audio.Samples.Get(@"Intro/Welcome/welcome"); pianoReverb = audio.Samples.Get(@"Intro/Welcome/welcome_piano"); - - if (musicController.CurrentTrack != null) - musicController.CurrentTrack.Looping = true; } protected override void LogoArriving(OsuLogo logo, bool resuming) @@ -54,6 +47,8 @@ namespace osu.Game.Screens.Menu if (!resuming) { + Track.Looping = true; + LoadComponentAsync(new WelcomeIntroSequence { RelativeSizeAxes = Axes.Both From f8279dab328d758f2a590924de44a8a8921ca595 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 18:54:14 +0900 Subject: [PATCH 18/86] Refactor MainMenu --- osu.Game/Screens/Menu/MainMenu.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index ce48777ce1..ea4347a285 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -170,9 +170,6 @@ namespace osu.Game.Screens.Menu [Resolved] private Storage storage { get; set; } - [Resolved] - private MusicController musicController { get; set; } - public override void OnEntering(IScreen last) { base.OnEntering(last); @@ -180,14 +177,14 @@ namespace osu.Game.Screens.Menu var metadata = Beatmap.Value.Metadata; - if (last is IntroScreen && musicController.TrackLoaded) + if (last is IntroScreen && music.TrackLoaded) { - Debug.Assert(musicController.CurrentTrack != null); + Debug.Assert(music.CurrentTrack != null); - if (!musicController.CurrentTrack.IsRunning) + if (!music.CurrentTrack.IsRunning) { - musicController.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.CurrentTrack.Length); - musicController.CurrentTrack.Start(); + music.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * music.CurrentTrack.Length); + music.CurrentTrack.Start(); } } From adf4f56dce1871816e29bde01e51fe78a77397ab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 19:01:23 +0900 Subject: [PATCH 19/86] Move MusicController to OsuGameBase --- osu.Game/OsuGame.cs | 5 ----- osu.Game/OsuGameBase.cs | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 0049e5a520..cf4610793c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -538,7 +538,6 @@ namespace osu.Game Container logoContainer; BackButton.Receptor receptor; - dependencies.CacheAs(MusicController = new MusicController()); dependencies.CacheAs(idleTracker = new GameIdleTracker(6000)); AddRange(new Drawable[] @@ -581,8 +580,6 @@ namespace osu.Game ScreenStack.ScreenPushed += screenPushed; ScreenStack.ScreenExited += screenExited; - loadComponentSingleFile(MusicController, Add); - loadComponentSingleFile(osuLogo, logo => { logoContainer.Add(logo); @@ -925,8 +922,6 @@ namespace osu.Game private ScalingContainer screenContainer; - protected MusicController MusicController { get; private set; } - protected override bool OnExiting() { if (ScreenStack.CurrentScreen is Loader) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 24c1f7849c..51b9b7278d 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -30,6 +30,7 @@ using osu.Game.Database; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; +using osu.Game.Overlays; using osu.Game.Resources; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -73,6 +74,8 @@ namespace osu.Game protected MenuCursorContainer MenuCursorContainer; + protected MusicController MusicController; + private Container content; protected override Container Content => content; @@ -265,6 +268,9 @@ namespace osu.Game dependencies.Cache(previewTrackManager = new PreviewTrackManager()); Add(previewTrackManager); + AddInternal(MusicController = new MusicController()); + dependencies.CacheAs(MusicController); + Ruleset.BindValueChanged(onRulesetChanged); } From 4cfca71d080822734e7f29de27b5273f3304460a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 19:05:15 +0900 Subject: [PATCH 20/86] Fix a few test scenes --- osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index ae4b0ef84a..a6266d210c 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; using osu.Framework.Extensions.ObjectExtensions; namespace osu.Game.Tests.Visual @@ -15,7 +16,11 @@ namespace osu.Game.Tests.Visual base.Update(); // note that this will override any mod rate application - MusicController.CurrentTrack.AsNonNull().Tempo.Value = Clock.Rate; + if (MusicController.TrackLoaded) + { + Debug.Assert(MusicController.CurrentTrack != null); + MusicController.CurrentTrack.Tempo.Value = Clock.Rate; + } } } } From d1af1429b3dd8d79ba36bc5d41ac02a75ad86bac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Aug 2020 19:08:45 +0900 Subject: [PATCH 21/86] Fix inspection --- osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index a6266d210c..54458716b1 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; -using osu.Framework.Extensions.ObjectExtensions; namespace osu.Game.Tests.Visual { From 61b632516eb73c43918697a9e408b5d75d04ab4d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 19:43:16 +0900 Subject: [PATCH 22/86] Ensure CurrentTrack is never null --- osu.Game.Tests/Visual/Editing/TimelineTestScene.cs | 3 --- .../Visual/Navigation/TestSceneScreenNavigation.cs | 4 ++-- .../Visual/UserInterface/TestSceneBeatSyncedContainer.cs | 2 +- osu.Game/Overlays/MusicController.cs | 6 ++---- .../Edit/Components/Timelines/Summary/Parts/TimelinePart.cs | 1 - .../Edit/Compose/Components/Timeline/TimelineTickDisplay.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 4 ++-- osu.Game/Screens/Menu/MainMenu.cs | 2 -- osu.Game/Tests/Visual/OsuTestScene.cs | 3 --- osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs | 3 --- 10 files changed, 8 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index 4113bdddf8..347b5757c8 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -95,10 +95,7 @@ namespace osu.Game.Tests.Visual.Editing base.Update(); if (musicController.TrackLoaded) - { - Debug.Assert(musicController.CurrentTrack != null); marker.X = (float)(editorClock.CurrentTime / musicController.CurrentTrack.Length); - } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 946bc2a175..e5d862cfc7 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -136,8 +136,8 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded); AddStep("Seek close to end", () => { - Game.MusicController.SeekTo(MusicController.CurrentTrack.AsNonNull().Length - 1000); - MusicController.CurrentTrack.AsNonNull().Completed += () => trackCompleted = true; + Game.MusicController.SeekTo(MusicController.CurrentTrack.Length - 1000); + MusicController.CurrentTrack.Completed += () => trackCompleted = true; }); AddUntilStep("Track was completed", () => trackCompleted); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index ac743d76df..3cccfa992e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -169,7 +169,7 @@ namespace osu.Game.Tests.Visual.UserInterface if (timingPoints.Count == 0) return 0; if (timingPoints[^1] == current) - return (int)Math.Ceiling((musicController.CurrentTrack.AsNonNull().Length - current.Time) / current.BeatLength); + return (int)Math.Ceiling((musicController.CurrentTrack.Length - current.Time) / current.BeatLength); return (int)Math.Ceiling((getNextTimingPoint(current).Time - current.Time) / current.BeatLength); } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 6adfa1817e..7e3bb1ce89 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; @@ -65,8 +64,7 @@ namespace osu.Game.Overlays [Resolved(canBeNull: true)] private OnScreenDisplay onScreenDisplay { get; set; } - [CanBeNull] - public DrawableTrack CurrentTrack { get; private set; } + public DrawableTrack CurrentTrack { get; private set; } = new DrawableTrack(new TrackVirtual(1000)); private IBindable> managerUpdated; private IBindable> managerRemoved; @@ -312,7 +310,7 @@ namespace osu.Game.Overlays current = beatmap.NewValue; - if (!beatmap.OldValue.BeatmapInfo.AudioEquals(current?.BeatmapInfo)) + if (CurrentTrack == null || !beatmap.OldValue.BeatmapInfo.AudioEquals(current?.BeatmapInfo)) changeTrack(); TrackChanged?.Invoke(current, direction); diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index 24fb855009..7085c8b020 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -58,7 +58,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts return; } - Debug.Assert(musicController.CurrentTrack != null); content.RelativeChildSize = new Vector2((float)Math.Max(1, musicController.CurrentTrack.Length), 1); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index ceb0275a13..1ce33f221a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) { var point = beatmap.ControlPointInfo.TimingPoints[i]; - var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : musicController.CurrentTrack.AsNonNull().Length; + var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : musicController.CurrentTrack.Length; int beat = 0; diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 7a1ff4fa06..974b704200 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -109,14 +109,14 @@ namespace osu.Game.Screens.Menu private void updateAmplitudes() { var effect = beatmap.Value.BeatmapLoaded && musicController.TrackLoaded - ? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(musicController.CurrentTrack.AsNonNull().CurrentTime) + ? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(musicController.CurrentTrack.CurrentTime) : null; for (int i = 0; i < temporalAmplitudes.Length; i++) temporalAmplitudes[i] = 0; if (musicController.TrackLoaded) - addAmplitudesFromSource(musicController.CurrentTrack.AsNonNull()); + addAmplitudesFromSource(musicController.CurrentTrack); foreach (var source in amplitudeSources) addAmplitudesFromSource(source); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index ea4347a285..518277bce3 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -179,8 +179,6 @@ namespace osu.Game.Screens.Menu if (last is IntroScreen && music.TrackLoaded) { - Debug.Assert(music.CurrentTrack != null); - if (!music.CurrentTrack.IsRunning) { music.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * music.CurrentTrack.Length); diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index f2b9388fdc..af7579aafb 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -170,10 +170,7 @@ namespace osu.Game.Tests.Visual rulesetDependencies?.Dispose(); if (MusicController?.TrackLoaded == true) - { - Debug.Assert(MusicController.CurrentTrack != null); MusicController.CurrentTrack.Stop(); - } if (contextFactory.IsValueCreated) contextFactory.Value.ResetDatabase(); diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index 54458716b1..027259d4f0 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -16,10 +16,7 @@ namespace osu.Game.Tests.Visual // note that this will override any mod rate application if (MusicController.TrackLoaded) - { - Debug.Assert(MusicController.CurrentTrack != null); MusicController.CurrentTrack.Tempo.Value = Clock.Rate; - } } } } From 5002d69f6973ab9753997dd28255c90a90de270a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 20:51:56 +0900 Subject: [PATCH 23/86] Update inspections --- .../TestSceneHoldNoteInput.cs | 2 +- .../TestSceneOutOfOrderHits.cs | 2 +- .../TestSceneSliderInput.cs | 2 +- .../Skins/TestSceneBeatmapSkinResources.cs | 2 +- .../Visual/Editing/TimelineTestScene.cs | 1 - .../Visual/Gameplay/TestScenePause.cs | 2 +- .../Visual/Gameplay/TestScenePlayerLoader.cs | 4 +-- .../Visual/Gameplay/TestSceneStoryboard.cs | 4 +-- .../Visual/Menus/TestSceneIntroWelcome.cs | 2 +- .../Navigation/TestSceneScreenNavigation.cs | 9 +++--- .../TestSceneBeatSyncedContainer.cs | 1 - .../TestSceneNowPlayingOverlay.cs | 4 +-- osu.Game/Audio/PreviewTrackManager.cs | 2 +- osu.Game/Overlays/Music/PlaylistOverlay.cs | 6 ++-- osu.Game/Overlays/MusicController.cs | 31 +++++++------------ .../Edit/Components/PlaybackControl.cs | 4 +-- .../Timelines/Summary/Parts/TimelinePart.cs | 1 - .../Timeline/TimelineTickDisplay.cs | 1 - osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 1 - osu.Game/Screens/Menu/MainMenu.cs | 1 - osu.Game/Screens/Menu/OsuLogo.cs | 2 +- .../Multi/Match/Components/ReadyButton.cs | 2 +- osu.Game/Screens/Multi/Multiplayer.cs | 16 +++------- osu.Game/Tests/Visual/OsuTestScene.cs | 1 - .../Visual/RateAdjustedBeatmapTestScene.cs | 2 -- 26 files changed, 42 insertions(+), 65 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 98669efb10..19b69bac6d 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -343,7 +343,7 @@ namespace osu.Game.Rulesets.Mania.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs index e5be778527..744ad46c28 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs @@ -385,7 +385,7 @@ namespace osu.Game.Rulesets.Osu.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index c9d13d3976..1690f648f9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -366,7 +366,7 @@ namespace osu.Game.Rulesets.Osu.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index 08a4e27ff7..2866692be4 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -31,6 +31,6 @@ namespace osu.Game.Tests.Skins public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => beatmap.Skin.GetSample(new SampleInfo("sample")) != null); [Test] - public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => MusicController.CurrentTrack?.IsDummyDevice == false); + public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => MusicController.CurrentTrack.IsDummyDevice == false); } } diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index 347b5757c8..4988a09650 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index e500b451f0..e7dd586f4e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -288,7 +288,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void confirmNoTrackAdjustments() { - AddAssert("track has no adjustments", () => MusicController.CurrentTrack?.AggregateFrequency.Value == 1); + AddAssert("track has no adjustments", () => MusicController.CurrentTrack.AggregateFrequency.Value == 1); } private void restart() => AddStep("restart", () => Player.Restart()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index c72ab7d3d1..c4882046de 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -77,12 +77,12 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("load dummy beatmap", () => ResetPlayer(false, () => SelectedMods.Value = new[] { new OsuModNightcore() })); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddAssert("mod rate applied", () => MusicController.CurrentTrack?.Rate != 1); + AddAssert("mod rate applied", () => MusicController.CurrentTrack.Rate != 1); AddStep("exit loader", () => loader.Exit()); AddUntilStep("wait for not current", () => !loader.IsCurrentScreen()); AddAssert("player did not load", () => !player.IsLoaded); AddUntilStep("player disposed", () => loader.DisposalTask?.IsCompleted == true); - AddAssert("mod rate still applied", () => MusicController.CurrentTrack?.Rate != 1); + AddAssert("mod rate still applied", () => MusicController.CurrentTrack.Rate != 1); } [Test] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index c7a012a03f..3d2dd8a0c5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -87,9 +87,9 @@ namespace osu.Game.Tests.Visual.Gameplay private void restart() { - MusicController.CurrentTrack?.Reset(); + MusicController.CurrentTrack.Reset(); loadStoryboard(Beatmap.Value); - MusicController.CurrentTrack?.Start(); + MusicController.CurrentTrack.Start(); } private void loadStoryboard(WorkingBeatmap working) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs index a88704c831..29be250b12 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Menus { AddUntilStep("wait for load", () => MusicController.TrackLoaded); - AddAssert("check if menu music loops", () => MusicController.CurrentTrack?.Looping == true); + AddAssert("check if menu music loops", () => MusicController.CurrentTrack.Looping); } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index e5d862cfc7..d2c71c1d17 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -4,7 +4,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -62,12 +61,12 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for fail", () => player.HasFailed); AddUntilStep("wait for track stop", () => !MusicController.IsPlaying); - AddAssert("Ensure time before preview point", () => MusicController.CurrentTrack?.CurrentTime < beatmap().Metadata.PreviewTime); + AddAssert("Ensure time before preview point", () => MusicController.CurrentTrack.CurrentTime < beatmap().Metadata.PreviewTime); pushEscape(); AddUntilStep("wait for track playing", () => MusicController.IsPlaying); - AddAssert("Ensure time wasn't reset to preview point", () => MusicController.CurrentTrack?.CurrentTime < beatmap().Metadata.PreviewTime); + AddAssert("Ensure time wasn't reset to preview point", () => MusicController.CurrentTrack.CurrentTime < beatmap().Metadata.PreviewTime); } [Test] @@ -77,11 +76,11 @@ namespace osu.Game.Tests.Visual.Navigation PushAndConfirm(() => songSelect = new TestSongSelect()); - AddUntilStep("wait for no track", () => MusicController.CurrentTrack?.IsDummyDevice == true); + AddUntilStep("wait for no track", () => MusicController.CurrentTrack.IsDummyDevice); AddStep("return to menu", () => songSelect.Exit()); - AddUntilStep("wait for track", () => MusicController.CurrentTrack?.IsDummyDevice == false && MusicController.IsPlaying); + AddUntilStep("wait for track", () => MusicController.CurrentTrack.IsDummyDevice == false && MusicController.IsPlaying); } [Test] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index 3cccfa992e..127915c6c6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -8,7 +8,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 0161ec0c56..cadecbbef0 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -80,12 +80,12 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Store track", () => currentBeatmap = Beatmap.Value); AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000)); - AddUntilStep(@"Wait for current time to update", () => musicController.CurrentTrack?.CurrentTime > 5000); + AddUntilStep(@"Wait for current time to update", () => musicController.CurrentTrack.CurrentTime > 5000); AddStep(@"Set previous", () => musicController.PreviousTrack()); AddAssert(@"Check beatmap didn't change", () => currentBeatmap == Beatmap.Value); - AddUntilStep("Wait for current time to update", () => musicController.CurrentTrack?.CurrentTime < 5000); + AddUntilStep("Wait for current time to update", () => musicController.CurrentTrack.CurrentTime < 5000); AddStep(@"Set previous", () => musicController.PreviousTrack()); AddAssert(@"Check beatmap did change", () => currentBeatmap != Beatmap.Value); diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 862be41c1a..1c68ce71d4 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -48,7 +48,7 @@ namespace osu.Game.Audio track.Started += () => Schedule(() => { - CurrentTrack?.Stop(); + CurrentTrack.Stop(); CurrentTrack = track; audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); }); diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index b9a58c37cb..7471e31923 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -85,7 +85,7 @@ namespace osu.Game.Overlays.Music if (toSelect != null) { beatmap.Value = beatmaps.GetWorkingBeatmap(toSelect); - musicController.CurrentTrack?.Restart(); + musicController.CurrentTrack.Restart(); } }; } @@ -119,12 +119,12 @@ namespace osu.Game.Overlays.Music { if (set.ID == (beatmap.Value?.BeatmapSetInfo?.ID ?? -1)) { - musicController.CurrentTrack?.Seek(0); + musicController.CurrentTrack.Seek(0); return; } beatmap.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First()); - musicController.CurrentTrack?.Restart(); + musicController.CurrentTrack.Restart(); } } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 7e3bb1ce89..3e93ae2ccd 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -3,8 +3,8 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; @@ -64,6 +64,7 @@ namespace osu.Game.Overlays [Resolved(canBeNull: true)] private OnScreenDisplay onScreenDisplay { get; set; } + [NotNull] public DrawableTrack CurrentTrack { get; private set; } = new DrawableTrack(new TrackVirtual(1000)); private IBindable> managerUpdated; @@ -102,12 +103,12 @@ namespace osu.Game.Overlays /// /// Returns whether the beatmap track is playing. /// - public bool IsPlaying => CurrentTrack?.IsRunning ?? false; + public bool IsPlaying => CurrentTrack.IsRunning; /// /// Returns whether the beatmap track is loaded. /// - public bool TrackLoaded => CurrentTrack?.IsLoaded == true; + public bool TrackLoaded => CurrentTrack.IsLoaded; private void beatmapUpdated(ValueChangedEvent> weakSet) { @@ -140,7 +141,7 @@ namespace osu.Game.Overlays seekDelegate = Schedule(() => { if (!beatmap.Disabled) - CurrentTrack?.Seek(position); + CurrentTrack.Seek(position); }); } @@ -152,7 +153,7 @@ namespace osu.Game.Overlays { if (IsUserPaused) return; - if (CurrentTrack == null || CurrentTrack.IsDummyDevice) + if (CurrentTrack.IsDummyDevice) { if (beatmap.Disabled) return; @@ -173,9 +174,6 @@ namespace osu.Game.Overlays { IsUserPaused = false; - if (CurrentTrack == null) - return false; - if (restart) CurrentTrack.Restart(); else if (!IsPlaying) @@ -190,7 +188,7 @@ namespace osu.Game.Overlays public void Stop() { IsUserPaused = true; - if (CurrentTrack?.IsRunning == true) + if (CurrentTrack.IsRunning) CurrentTrack.Stop(); } @@ -200,7 +198,7 @@ namespace osu.Game.Overlays /// Whether the operation was successful. public bool TogglePause() { - if (CurrentTrack?.IsRunning == true) + if (CurrentTrack.IsRunning) Stop(); else Play(); @@ -222,7 +220,7 @@ namespace osu.Game.Overlays if (beatmap.Disabled) return PreviousTrackResult.None; - var currentTrackPosition = CurrentTrack?.CurrentTime; + var currentTrackPosition = CurrentTrack.CurrentTime; if (currentTrackPosition >= restart_cutoff_point) { @@ -276,7 +274,7 @@ namespace osu.Game.Overlays { // if not scheduled, the previously track will be stopped one frame later (see ScheduleAfterChildren logic in GameBase). // we probably want to move this to a central method for switching to a new working beatmap in the future. - Schedule(() => CurrentTrack?.Restart()); + Schedule(() => CurrentTrack.Restart()); } private WorkingBeatmap current; @@ -310,7 +308,7 @@ namespace osu.Game.Overlays current = beatmap.NewValue; - if (CurrentTrack == null || !beatmap.OldValue.BeatmapInfo.AudioEquals(current?.BeatmapInfo)) + if (CurrentTrack.IsDummyDevice || !beatmap.OldValue.BeatmapInfo.AudioEquals(current?.BeatmapInfo)) changeTrack(); TrackChanged?.Invoke(current, direction); @@ -322,7 +320,7 @@ namespace osu.Game.Overlays private void changeTrack() { - CurrentTrack?.Expire(); + CurrentTrack.Expire(); CurrentTrack = null; if (current != null) @@ -340,8 +338,6 @@ namespace osu.Game.Overlays if (current != workingBeatmap) return; - Debug.Assert(CurrentTrack != null); - if (!CurrentTrack.Looping && !beatmap.Disabled) NextTrack(); } @@ -366,9 +362,6 @@ namespace osu.Game.Overlays public void ResetTrackAdjustments() { - if (CurrentTrack == null) - return; - CurrentTrack.ResetSpeedAdjustments(); if (allowRateAdjustments) diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 412efe266c..5bafc120af 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -66,12 +66,12 @@ namespace osu.Game.Screens.Edit.Components } }; - musicController.CurrentTrack?.AddAdjustment(AdjustableProperty.Tempo, tempo); + musicController.CurrentTrack.AddAdjustment(AdjustableProperty.Tempo, tempo); } protected override void Dispose(bool isDisposing) { - musicController?.CurrentTrack?.RemoveAdjustment(AdjustableProperty.Tempo, tempo); + musicController?.CurrentTrack.RemoveAdjustment(AdjustableProperty.Tempo, tempo); base.Dispose(isDisposing); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index 7085c8b020..c8a470c58a 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osuTK; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 1ce33f221a..cb122c590e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Overlays; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 79b13a7eac..9f2009b415 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit // Todo: should probably be done at a DrawableRuleset level to share logic with Player. var sourceClock = (IAdjustableClock)musicController.CurrentTrack ?? new StopwatchClock(); - clock = new EditorClock(Beatmap.Value, musicController.CurrentTrack?.Length ?? 0, beatDivisor) { IsCoupled = false }; + clock = new EditorClock(Beatmap.Value, musicController.CurrentTrack.Length, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); dependencies.CacheAs(clock); diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 974b704200..4d95ee9b7b 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -19,7 +19,6 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Utils; using osu.Game.Overlays; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 518277bce3..8837a49772 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Diagnostics; using System.Linq; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index f028f9b229..4515ee8ed0 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -330,7 +330,7 @@ namespace osu.Game.Screens.Menu const float velocity_adjust_cutoff = 0.98f; const float paused_velocity = 0.5f; - if (musicController.CurrentTrack?.IsRunning == true) + if (musicController.CurrentTrack.IsRunning) { var maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0; logoAmplitudeContainer.Scale = new Vector2((float)Interpolation.Damp(logoAmplitudeContainer.Scale.X, 1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 0.9f, Time.Elapsed)); diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index c7dc20ff23..384d3bd5a5 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Multi.Match.Components return; } - bool hasEnoughTime = musicController.CurrentTrack != null && DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(musicController.CurrentTrack.Length) < endDate.Value; + bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(musicController.CurrentTrack.Length) < endDate.Value; Enabled.Value = hasBeatmap && hasEnoughTime; } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index e068899c7b..1a39d80f8d 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -343,13 +343,10 @@ namespace osu.Game.Screens.Multi { if (screenStack.CurrentScreen is MatchSubScreen) { - if (musicController.CurrentTrack != null) - { - musicController.CurrentTrack.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - musicController.CurrentTrack.Looping = true; + musicController.CurrentTrack.RestartPoint = Beatmap.Value.Metadata.PreviewTime; + musicController.CurrentTrack.Looping = true; - musicController.EnsurePlayingSomething(); - } + musicController.EnsurePlayingSomething(); } else { @@ -359,11 +356,8 @@ namespace osu.Game.Screens.Multi private void cancelLooping() { - if (musicController.CurrentTrack != null) - { - musicController.CurrentTrack.Looping = false; - musicController.CurrentTrack.RestartPoint = 0; - } + musicController.CurrentTrack.Looping = false; + musicController.CurrentTrack.RestartPoint = 0; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index af7579aafb..b0d15bf442 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index 027259d4f0..7651285970 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Diagnostics; - namespace osu.Game.Tests.Visual { /// From 028040344a9c2bfcc1cd25d3efad2e8dcf651207 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 21:07:59 +0900 Subject: [PATCH 24/86] Fix test scene using local beatmap --- osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index 2866692be4..03faee9ad2 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -18,17 +18,15 @@ namespace osu.Game.Tests.Skins [Resolved] private BeatmapManager beatmaps { get; set; } - private WorkingBeatmap beatmap; - [BackgroundDependencyLoader] private void load() { var imported = beatmaps.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-beatmap.osz"))).Result; - beatmap = beatmaps.GetWorkingBeatmap(imported.Beatmaps[0]); + Beatmap.Value = beatmaps.GetWorkingBeatmap(imported.Beatmaps[0]); } [Test] - public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => beatmap.Skin.GetSample(new SampleInfo("sample")) != null); + public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => Beatmap.Value.Skin.GetSample(new SampleInfo("sample")) != null); [Test] public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => MusicController.CurrentTrack.IsDummyDevice == false); From 961c6dab541c379e30cd4afe837f5bbfb265096b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 21:08:03 +0900 Subject: [PATCH 25/86] Fix more inspections --- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Tests/Visual/EditorClockTestScene.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 9f2009b415..1a7d76ba8f 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -83,7 +83,7 @@ namespace osu.Game.Screens.Edit beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); // Todo: should probably be done at a DrawableRuleset level to share logic with Player. - var sourceClock = (IAdjustableClock)musicController.CurrentTrack ?? new StopwatchClock(); + var sourceClock = (IAdjustableClock)musicController.CurrentTrack; clock = new EditorClock(Beatmap.Value, musicController.CurrentTrack.Length, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 780b4f1b3a..1009151ac4 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(ValueChangedEvent e) { Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; - Clock.ChangeSource((IAdjustableClock)MusicController.CurrentTrack ?? new StopwatchClock()); + Clock.ChangeSource((IAdjustableClock)MusicController.CurrentTrack); Clock.ProcessFrame(); } From b08ebe6f81f9d596920ba602e04a1df9cb90798a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 21:14:45 +0900 Subject: [PATCH 26/86] More inspections (rider is broken) --- osu.Game/Screens/Edit/Editor.cs | 4 +--- osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 1a7d76ba8f..78fa6c74b0 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -14,7 +14,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Platform; -using osu.Framework.Timing; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; @@ -83,9 +82,8 @@ namespace osu.Game.Screens.Edit beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); // Todo: should probably be done at a DrawableRuleset level to share logic with Player. - var sourceClock = (IAdjustableClock)musicController.CurrentTrack; clock = new EditorClock(Beatmap.Value, musicController.CurrentTrack.Length, beatDivisor) { IsCoupled = false }; - clock.ChangeSource(sourceClock); + clock.ChangeSource(musicController.CurrentTrack); dependencies.CacheAs(clock); AddInternal(clock); diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 1009151ac4..59c9329d37 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit; @@ -44,7 +43,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(ValueChangedEvent e) { Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; - Clock.ChangeSource((IAdjustableClock)MusicController.CurrentTrack); + Clock.ChangeSource(MusicController.CurrentTrack); Clock.ProcessFrame(); } From 08820c62ec6ab6121b60c59ad8e89f3dfbcef3f5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 21:36:02 +0900 Subject: [PATCH 27/86] Add back removed nullcheck --- osu.Game/Audio/PreviewTrackManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 1c68ce71d4..862be41c1a 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -48,7 +48,7 @@ namespace osu.Game.Audio track.Started += () => Schedule(() => { - CurrentTrack.Stop(); + CurrentTrack?.Stop(); CurrentTrack = track; audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); }); From b6fb7a0d39e6a5667be3fa45d90a3f2a5072d5ed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 22:05:58 +0900 Subject: [PATCH 28/86] Fix possibly setting null track --- .../Visual/Online/TestSceneNowPlayingCommand.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 3 ++- osu.Game/Overlays/MusicController.cs | 8 +++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs index 103308d34d..9662bd65b4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Set activity", () => API.Activity.Value = new UserActivity.InLobby()); - AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(null, null) + AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(Audio, null) { BeatmapInfo = { OnlineBeatmapID = hasOnlineId ? 1234 : (int?)null } }); diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 8080e94075..ca801cf745 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using JetBrains.Annotations; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions.IEnumerableExtensions; @@ -19,7 +20,7 @@ namespace osu.Game.Beatmaps { private readonly TextureStore textures; - public DummyWorkingBeatmap(AudioManager audio, TextureStore textures) + public DummyWorkingBeatmap([NotNull] AudioManager audio, TextureStore textures) : base(new BeatmapInfo { Metadata = new BeatmapMetadata diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 3e93ae2ccd..2aed46a1d0 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -321,15 +321,13 @@ namespace osu.Game.Overlays private void changeTrack() { CurrentTrack.Expire(); - CurrentTrack = null; + CurrentTrack = new DrawableTrack(new TrackVirtual(1000)); if (current != null) - { CurrentTrack = new DrawableTrack(current.GetRealTrack()); - CurrentTrack.Completed += () => onTrackCompleted(current); - AddInternal(CurrentTrack); - } + CurrentTrack.Completed += () => onTrackCompleted(current); + AddInternal(CurrentTrack); } private void onTrackCompleted(WorkingBeatmap workingBeatmap) From d1765c8a45e3940974c35ec2c75366c14a96a4e1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 22:06:04 +0900 Subject: [PATCH 29/86] Fix using the wrong music controller instance --- .../Navigation/TestSceneScreenNavigation.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index d2c71c1d17..0f06010a6a 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -60,13 +60,13 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null); AddUntilStep("wait for fail", () => player.HasFailed); - AddUntilStep("wait for track stop", () => !MusicController.IsPlaying); - AddAssert("Ensure time before preview point", () => MusicController.CurrentTrack.CurrentTime < beatmap().Metadata.PreviewTime); + AddUntilStep("wait for track stop", () => !Game.MusicController.IsPlaying); + AddAssert("Ensure time before preview point", () => Game.MusicController.CurrentTrack.CurrentTime < beatmap().Metadata.PreviewTime); pushEscape(); - AddUntilStep("wait for track playing", () => MusicController.IsPlaying); - AddAssert("Ensure time wasn't reset to preview point", () => MusicController.CurrentTrack.CurrentTime < beatmap().Metadata.PreviewTime); + AddUntilStep("wait for track playing", () => Game.MusicController.IsPlaying); + AddAssert("Ensure time wasn't reset to preview point", () => Game.MusicController.CurrentTrack.CurrentTime < beatmap().Metadata.PreviewTime); } [Test] @@ -76,11 +76,11 @@ namespace osu.Game.Tests.Visual.Navigation PushAndConfirm(() => songSelect = new TestSongSelect()); - AddUntilStep("wait for no track", () => MusicController.CurrentTrack.IsDummyDevice); + AddUntilStep("wait for no track", () => Game.MusicController.CurrentTrack.IsDummyDevice); AddStep("return to menu", () => songSelect.Exit()); - AddUntilStep("wait for track", () => MusicController.CurrentTrack.IsDummyDevice == false && MusicController.IsPlaying); + AddUntilStep("wait for track", () => Game.MusicController.CurrentTrack.IsDummyDevice == false && Game.MusicController.IsPlaying); } [Test] @@ -135,12 +135,12 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded); AddStep("Seek close to end", () => { - Game.MusicController.SeekTo(MusicController.CurrentTrack.Length - 1000); - MusicController.CurrentTrack.Completed += () => trackCompleted = true; + Game.MusicController.SeekTo(Game.MusicController.CurrentTrack.Length - 1000); + Game.MusicController.CurrentTrack.Completed += () => trackCompleted = true; }); AddUntilStep("Track was completed", () => trackCompleted); - AddUntilStep("Track was restarted", () => MusicController.IsPlaying); + AddUntilStep("Track was restarted", () => Game.MusicController.IsPlaying); } private void pushEscape() => From e87f50f74f28ca8d5b5c6a0189b3ec2be21a1360 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 22:31:41 +0900 Subject: [PATCH 30/86] Rename method --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs | 2 +- osu.Game.Tests/WaveformTestBeatmap.cs | 2 +- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/IWorkingBeatmap.cs | 5 +++++ osu.Game/Beatmaps/WorkingBeatmap.cs | 4 ++-- osu.Game/Overlays/MusicController.cs | 2 +- osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs | 2 +- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 +- osu.Game/Tests/Visual/OsuTestScene.cs | 2 +- 16 files changed, 21 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index 30331e98d2..4a11e1785b 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -106,7 +106,7 @@ namespace osu.Game.Tests.Beatmaps.Formats protected override Texture GetBackground() => throw new NotImplementedException(); - protected override Track GetTrack() => throw new NotImplementedException(); + protected override Track GetBeatmapTrack() => throw new NotImplementedException(); } } } diff --git a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs index 40f6cecd9a..bb60ae73db 100644 --- a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Gameplay AddStep("create container", () => { var working = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - Add(gcc = new GameplayClockContainer(working.GetRealTrack(), working, Array.Empty(), 0)); + Add(gcc = new GameplayClockContainer(working.GetTrack(), working, Array.Empty(), 0)); }); AddStep("start track", () => gcc.Start()); diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index 720436fae4..360e7eccdc 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tests.Gameplay { var working = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - Add(gameplayContainer = new GameplayClockContainer(working.GetRealTrack(), working, Array.Empty(), 0)); + Add(gameplayContainer = new GameplayClockContainer(working.GetTrack(), working, Array.Empty(), 0)); gameplayContainer.Add(sample = new DrawableStoryboardSample(new StoryboardSampleInfo(string.Empty, 0, 1)) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 68110d759c..58fd760fc3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -34,7 +34,7 @@ namespace osu.Game.Tests.Visual.Gameplay var working = CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); - Child = gameplayClockContainer = new GameplayClockContainer(working.GetRealTrack(), working, Array.Empty(), 0) + Child = gameplayClockContainer = new GameplayClockContainer(working.GetTrack(), working, Array.Empty(), 0) { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 90c91eb007..7dc5ce1d7f 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile)); - protected override Track GetTrack() => trackStore.Get(firstAudioFile); + protected override Track GetBeatmapTrack() => trackStore.Get(firstAudioFile); private string firstAudioFile { diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index f22f41531a..e001185da9 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -476,7 +476,7 @@ namespace osu.Game.Beatmaps protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; - protected override Track GetTrack() => null; + protected override Track GetBeatmapTrack() => null; } } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index a54d46c1b1..f1289cd3aa 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -70,7 +70,7 @@ namespace osu.Game.Beatmaps } } - protected override Track GetTrack() + protected override Track GetBeatmapTrack() { try { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index ca801cf745..af2a2ac250 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -45,7 +45,7 @@ namespace osu.Game.Beatmaps protected override Texture GetBackground() => textures?.Get(@"Backgrounds/bg4"); - protected override Track GetTrack() => GetVirtualTrack(); + protected override Track GetBeatmapTrack() => GetVirtualTrack(); private class DummyRulesetInfo : RulesetInfo { diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 086b7502a2..e020625b99 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -54,5 +54,10 @@ namespace osu.Game.Beatmaps /// The converted . /// If could not be converted to . IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods = null, TimeSpan? timeout = null); + + /// + /// Retrieves the which this provides. + /// + Track GetTrack(); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 171201ca68..af6a67ad3f 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -249,9 +249,9 @@ namespace osu.Game.Beatmaps protected abstract Texture GetBackground(); private readonly RecyclableLazy background; - public Track GetRealTrack() => GetTrack() ?? GetVirtualTrack(1000); + public Track GetTrack() => GetBeatmapTrack() ?? GetVirtualTrack(1000); - protected abstract Track GetTrack(); + protected abstract Track GetBeatmapTrack(); public bool WaveformLoaded => waveform.IsResultAvailable; public Waveform Waveform => waveform.Value; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 2aed46a1d0..cf420c3b91 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -324,7 +324,7 @@ namespace osu.Game.Overlays CurrentTrack = new DrawableTrack(new TrackVirtual(1000)); if (current != null) - CurrentTrack = new DrawableTrack(current.GetRealTrack()); + CurrentTrack = new DrawableTrack(current.GetTrack()); CurrentTrack.Completed += () => onTrackCompleted(current); AddInternal(CurrentTrack); diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index fc3dd4c105..57b7ce6940 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Edit protected override Texture GetBackground() => throw new NotImplementedException(); - protected override Track GetTrack() => throw new NotImplementedException(); + protected override Track GetBeatmapTrack() => throw new NotImplementedException(); } } } diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 7e327261ab..6e85abf7dc 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Menu if (setInfo != null) { initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - UsingThemedIntro = initialBeatmap.GetRealTrack().IsDummyDevice == false; + UsingThemedIntro = initialBeatmap.GetTrack().IsDummyDevice == false; } return UsingThemedIntro; diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 6ada632850..e492069c5e 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -208,7 +208,7 @@ namespace osu.Game.Tests.Beatmaps protected override Texture GetBackground() => throw new NotImplementedException(); - protected override Track GetTrack() => throw new NotImplementedException(); + protected override Track GetBeatmapTrack() => throw new NotImplementedException(); protected override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) { diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index ee04142035..d091da3206 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -35,6 +35,6 @@ namespace osu.Game.Tests.Beatmaps protected override Texture GetBackground() => null; - protected override Track GetTrack() => null; + protected override Track GetBeatmapTrack() => null; } } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index b0d15bf442..756074c0b3 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -223,7 +223,7 @@ namespace osu.Game.Tests.Visual store?.Dispose(); } - protected override Track GetTrack() => track; + protected override Track GetBeatmapTrack() => track; public class TrackVirtualStore : AudioCollectionManager, ITrackStore { From b8373e89b7e30e0370170f10bf16c1d7bb36b835 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 23:05:59 +0900 Subject: [PATCH 31/86] Move beatmap bind to BDL load() --- osu.Game/Overlays/MusicController.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index cf420c3b91..26df48171e 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -79,12 +79,9 @@ namespace osu.Game.Overlays managerRemoved.BindValueChanged(beatmapRemoved); beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets(IncludedDetails.Minimal, true).OrderBy(_ => RNG.Next())); - } - - protected override void LoadComplete() - { - base.LoadComplete(); + // Todo: These binds really shouldn't be here, but are unlikely to cause any issues for now. + // They are placed here for now since some tests rely on setting the beatmap _and_ their hierarchies inside their load(), which runs before the MusicController's load(). beatmap.BindValueChanged(beatmapChanged, true); mods.BindValueChanged(_ => ResetTrackAdjustments(), true); } From 2351701ade19e518b2d07f308af5237df2e7eedd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Aug 2020 23:08:51 +0900 Subject: [PATCH 32/86] Fix test not having a long enough track --- .../UserInterface/TestSceneNowPlayingOverlay.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index cadecbbef0..c14a1ddbf2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -11,6 +12,7 @@ using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.UserInterface { @@ -20,8 +22,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private MusicController musicController = new MusicController(); - private WorkingBeatmap currentBeatmap; - private NowPlayingOverlay nowPlayingOverlay; private RulesetStore rulesets; @@ -76,8 +76,13 @@ namespace osu.Game.Tests.Visual.UserInterface } }).Wait(), 5); - AddStep(@"Next track", () => musicController.NextTrack()); - AddStep("Store track", () => currentBeatmap = Beatmap.Value); + WorkingBeatmap currentBeatmap = null; + + AddStep("import beatmap with track", () => + { + var setWithTrack = manager.Import(TestResources.GetTestBeatmapForImport()).Result; + Beatmap.Value = currentBeatmap = manager.GetWorkingBeatmap(setWithTrack.Beatmaps.First()); + }); AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000)); AddUntilStep(@"Wait for current time to update", () => musicController.CurrentTrack.CurrentTime > 5000); From 87ce1e3558d598388c38cd078840d7148c95f0fd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 8 Aug 2020 00:58:04 +0900 Subject: [PATCH 33/86] Remove impossible null case (DummyWorkingBeatmap) --- osu.Game/Overlays/MusicController.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 26df48171e..c5ba82288c 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -318,12 +318,9 @@ namespace osu.Game.Overlays private void changeTrack() { CurrentTrack.Expire(); - CurrentTrack = new DrawableTrack(new TrackVirtual(1000)); - - if (current != null) - CurrentTrack = new DrawableTrack(current.GetTrack()); - + CurrentTrack = new DrawableTrack(current.GetTrack()); CurrentTrack.Completed += () => onTrackCompleted(current); + AddInternal(CurrentTrack); } From 20197e276861128b96dec6fcf7f9fd148a763e8d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 12:27:32 +0900 Subject: [PATCH 34/86] Remove locally-cached music controller --- osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index 3d2dd8a0c5..c11a47d62b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -25,16 +25,12 @@ namespace osu.Game.Tests.Visual.Gameplay private readonly Container storyboardContainer; private DrawableStoryboard storyboard; - [Cached] - private MusicController musicController = new MusicController(); - public TestSceneStoryboard() { Clock = new FramedClock(); AddRange(new Drawable[] { - musicController, new Container { RelativeSizeAxes = Axes.Both, @@ -104,7 +100,7 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard.Passing = false; storyboardContainer.Add(storyboard); - decoupledClock.ChangeSource(musicController.CurrentTrack); + decoupledClock.ChangeSource(MusicController.CurrentTrack); } private void loadStoryboardNoVideo() @@ -127,7 +123,7 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard = sb.CreateDrawable(Beatmap.Value); storyboardContainer.Add(storyboard); - decoupledClock.ChangeSource(musicController.CurrentTrack); + decoupledClock.ChangeSource(MusicController.CurrentTrack); } } } From b64142dff9d04deb9295eeb9c5b3e52623c63cdf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 12:37:00 +0900 Subject: [PATCH 35/86] Fix incorrect load state being used --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index c5ba82288c..813ad26ae4 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -105,7 +105,7 @@ namespace osu.Game.Overlays /// /// Returns whether the beatmap track is loaded. /// - public bool TrackLoaded => CurrentTrack.IsLoaded; + public bool TrackLoaded => CurrentTrack.TrackLoaded; private void beatmapUpdated(ValueChangedEvent> weakSet) { From c66a14e9c5d160def0fdcdabcf39772e72cdd0dc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 12:37:48 +0900 Subject: [PATCH 36/86] Remove beatmap from FailAnimation --- osu.Game/Screens/Play/FailAnimation.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index a7bfca612e..122ae505ca 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -11,7 +11,6 @@ using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Graphics; using osu.Framework.Utils; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Graphics; @@ -42,7 +41,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(AudioManager audio, IBindable beatmap) + private void load(AudioManager audio) { failSample = audio.Samples.Get(@"Gameplay/failsound"); } From 7d35893ecd2bf8b277c2e6ac9632592dbf313f6f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 12:40:58 +0900 Subject: [PATCH 37/86] Make MusicController non-nullable --- osu.Game/Screens/Menu/MainMenu.cs | 2 +- .../Screens/Multi/Lounge/LoungeSubScreen.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 28 +++++++------------ 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 8837a49772..470e8ca9a6 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Menu [Resolved] private GameHost host { get; set; } - [Resolved(canBeNull: true)] + [Resolved] private MusicController music { get; set; } [Resolved(canBeNull: true)] diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index ff7d56a95b..f9c5fd13a4 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Multi.Lounge [Resolved] private Bindable selectedRoom { get; set; } - [Resolved(canBeNull: true)] + [Resolved] private MusicController music { get; set; } private bool joiningRoom; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 80ed894233..ddbb021054 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -99,7 +99,7 @@ namespace osu.Game.Screens.Select private readonly Bindable decoupledRuleset = new Bindable(); - [Resolved(canBeNull: true)] + [Resolved] private MusicController music { get; set; } [BackgroundDependencyLoader(true)] @@ -561,18 +561,15 @@ namespace osu.Game.Screens.Select BeatmapDetails.Refresh(); - if (music?.CurrentTrack != null) - { - music.CurrentTrack.Looping = true; - music.ResetTrackAdjustments(); - } + music.CurrentTrack.Looping = true; + music.ResetTrackAdjustments(); if (Beatmap != null && !Beatmap.Value.BeatmapSetInfo.DeletePending) { updateComponentFromBeatmap(Beatmap.Value); // restart playback on returning to song select, regardless. - music?.Play(); + music.Play(); } this.FadeIn(250); @@ -589,8 +586,7 @@ namespace osu.Game.Screens.Select BeatmapOptions.Hide(); - if (music?.CurrentTrack != null) - music.CurrentTrack.Looping = false; + music.CurrentTrack.Looping = false; this.ScaleTo(1.1f, 250, Easing.InSine); @@ -611,8 +607,7 @@ namespace osu.Game.Screens.Select FilterControl.Deactivate(); - if (music?.CurrentTrack != null) - music.CurrentTrack.Looping = false; + music.CurrentTrack.Looping = false; return false; } @@ -653,8 +648,7 @@ namespace osu.Game.Screens.Select BeatmapDetails.Beatmap = beatmap; - if (music?.CurrentTrack != null) - music.CurrentTrack.Looping = true; + music.CurrentTrack.Looping = true; } private readonly WeakReference lastTrack = new WeakReference(null); @@ -665,16 +659,14 @@ namespace osu.Game.Screens.Select /// private void ensurePlayingSelected() { - ITrack track = music?.CurrentTrack; - if (track == null) - return; + ITrack track = music.CurrentTrack; bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - if (!track.IsRunning && (music?.IsUserPaused != true || isNewTrack)) - music?.Play(true); + if (!track.IsRunning && (music.IsUserPaused != true || isNewTrack)) + music.Play(true); lastTrack.SetTarget(track); } From 322d08af1bfe25f45f90fcd8bc395219ce85c108 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 13:11:59 +0900 Subject: [PATCH 38/86] Remove more local music controller caches --- osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs | 5 ----- .../Visual/UserInterface/TestSceneBeatSyncedContainer.cs | 4 ---- 2 files changed, 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs b/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs index d7f23f5cc0..4b22af38c5 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays; @@ -11,14 +10,10 @@ namespace osu.Game.Tests.Visual.Menus { public class TestSceneSongTicker : OsuTestScene { - [Cached] - private MusicController musicController = new MusicController(); - public TestSceneSongTicker() { AddRange(new Drawable[] { - musicController, new SongTicker { Anchor = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index 127915c6c6..82b7e65c4f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -26,9 +26,6 @@ namespace osu.Game.Tests.Visual.UserInterface { private readonly NowPlayingOverlay np; - [Cached] - private MusicController musicController = new MusicController(); - public TestSceneBeatSyncedContainer() { Clock = new FramedClock(); @@ -36,7 +33,6 @@ namespace osu.Game.Tests.Visual.UserInterface AddRange(new Drawable[] { - musicController, new BeatContainer { Anchor = Anchor.BottomCentre, From 6aafb3d2710174fe4bf302300ecf2cd1edd52988 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 13:14:20 +0900 Subject: [PATCH 39/86] Cleanup TestSceneScreenNavigation --- osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 0f06010a6a..73a833c15d 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -80,7 +80,7 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("return to menu", () => songSelect.Exit()); - AddUntilStep("wait for track", () => Game.MusicController.CurrentTrack.IsDummyDevice == false && Game.MusicController.IsPlaying); + AddUntilStep("wait for track", () => !Game.MusicController.CurrentTrack.IsDummyDevice && Game.MusicController.IsPlaying); } [Test] From 338c01fa43657beb3f1476aab90db227605deed2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 13:16:06 +0900 Subject: [PATCH 40/86] Remove track store reference counting, use single instance stores --- osu.Game/Beatmaps/BeatmapManager.cs | 29 ++++--------------- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 24 +++++---------- 2 files changed, 13 insertions(+), 40 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e001185da9..6f01580998 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -63,8 +63,9 @@ namespace osu.Game.Beatmaps private readonly RulesetStore rulesets; private readonly BeatmapStore beatmaps; private readonly AudioManager audioManager; - private readonly GameHost host; private readonly BeatmapOnlineLookupQueue onlineLookupQueue; + private readonly TextureStore textureStore; + private readonly ITrackStore trackStore; public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null, WorkingBeatmap defaultBeatmap = null) @@ -72,7 +73,6 @@ namespace osu.Game.Beatmaps { this.rulesets = rulesets; this.audioManager = audioManager; - this.host = host; DefaultBeatmap = defaultBeatmap; @@ -83,6 +83,9 @@ namespace osu.Game.Beatmaps beatmaps.ItemUpdated += removeWorkingCache; onlineLookupQueue = new BeatmapOnlineLookupQueue(api, storage); + + textureStore = new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)); + trackStore = audioManager.GetTrackStore(Files.Store); } protected override ArchiveDownloadRequest CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize) => @@ -219,7 +222,6 @@ namespace osu.Game.Beatmaps } private readonly WeakList workingCache = new WeakList(); - private readonly Dictionary referencedTrackStores = new Dictionary(); /// /// Retrieve a instance for the provided @@ -252,31 +254,12 @@ namespace osu.Game.Beatmaps beatmapInfo.Metadata ??= beatmapInfo.BeatmapSet.Metadata; - ITrackStore trackStore = workingCache.FirstOrDefault(b => b.BeatmapInfo.AudioEquals(beatmapInfo))?.TrackStore; - TextureStore textureStore = workingCache.FirstOrDefault(b => b.BeatmapInfo.BackgroundEquals(beatmapInfo))?.TextureStore; - - textureStore ??= new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)); - trackStore ??= audioManager.GetTrackStore(Files.Store); - - workingCache.Add(working = new BeatmapManagerWorkingBeatmap(Files.Store, textureStore, trackStore, beatmapInfo, audioManager, dereferenceTrackStore)); - referencedTrackStores[trackStore] = referencedTrackStores.GetOrDefault(trackStore) + 1; + workingCache.Add(working = new BeatmapManagerWorkingBeatmap(Files.Store, textureStore, trackStore, beatmapInfo, audioManager)); return working; } } - private void dereferenceTrackStore(ITrackStore trackStore) - { - lock (workingCache) - { - if (--referencedTrackStores[trackStore] == 0) - { - referencedTrackStores.Remove(trackStore); - trackStore.Dispose(); - } - } - } - /// /// Perform a lookup query on available s. /// diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index f1289cd3aa..aa93833f33 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -19,21 +19,16 @@ namespace osu.Game.Beatmaps { protected class BeatmapManagerWorkingBeatmap : WorkingBeatmap { - public readonly TextureStore TextureStore; - public readonly ITrackStore TrackStore; - private readonly IResourceStore store; - private readonly Action dereferenceAction; + private readonly TextureStore textureStore; + private readonly ITrackStore trackStore; - public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, ITrackStore trackStore, BeatmapInfo beatmapInfo, AudioManager audioManager, - Action dereferenceAction) + public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, ITrackStore trackStore, BeatmapInfo beatmapInfo, AudioManager audioManager) : base(beatmapInfo, audioManager) { this.store = store; - this.dereferenceAction = dereferenceAction; - - TextureStore = textureStore; - TrackStore = trackStore; + this.textureStore = textureStore; + this.trackStore = trackStore; } protected override IBeatmap GetBeatmap() @@ -61,7 +56,7 @@ namespace osu.Game.Beatmaps try { - return TextureStore.Get(getPathForFile(Metadata.BackgroundFile)); + return textureStore.Get(getPathForFile(Metadata.BackgroundFile)); } catch (Exception e) { @@ -74,7 +69,7 @@ namespace osu.Game.Beatmaps { try { - return TrackStore.Get(getPathForFile(Metadata.AudioFile)); + return trackStore.Get(getPathForFile(Metadata.AudioFile)); } catch (Exception e) { @@ -140,11 +135,6 @@ namespace osu.Game.Beatmaps return null; } } - - ~BeatmapManagerWorkingBeatmap() - { - dereferenceAction?.Invoke(TrackStore); - } } } } From faff0a70c49734841f6c1dd36c8df2775d1b867e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 13:48:57 +0900 Subject: [PATCH 41/86] Privatise BMWB --- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index aa93833f33..92199789ec 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -17,7 +17,7 @@ namespace osu.Game.Beatmaps { public partial class BeatmapManager { - protected class BeatmapManagerWorkingBeatmap : WorkingBeatmap + private class BeatmapManagerWorkingBeatmap : WorkingBeatmap { private readonly IResourceStore store; private readonly TextureStore textureStore; From 031d29ac34bd6684340f51aab051b84db42c4644 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Aug 2020 13:53:23 +0900 Subject: [PATCH 42/86] Inspect current track directly --- osu.Game/Overlays/NowPlayingOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 15b189ead6..dc52300cdb 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -234,9 +234,9 @@ namespace osu.Game.Overlays pendingBeatmapSwitch = null; } - var track = musicController.TrackLoaded ? musicController.CurrentTrack : null; + var track = musicController.CurrentTrack; - if (track?.IsDummyDevice == false) + if (track.IsDummyDevice == false) { progressBar.EndTime = track.Length; progressBar.CurrentTime = track.CurrentTime; From 070d71ec27fa74eec6d27fa551dd5162ab628d4e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Aug 2020 00:48:38 +0900 Subject: [PATCH 43/86] More cleanups --- .../Skinning/TestSceneDrawableTaikoMascot.cs | 4 ++-- .../Skinning/TestSceneTaikoPlayfield.cs | 2 +- osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs | 2 +- .../Visual/Gameplay/TestSceneNightcoreBeatContainer.cs | 4 ++-- osu.Game/Overlays/NowPlayingOverlay.cs | 2 +- osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs | 3 --- osu.Game/Screens/Edit/Editor.cs | 4 ++-- osu.Game/Screens/Edit/EditorClock.cs | 4 ++-- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- 9 files changed, 12 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs index ba5aef5968..6141bf062e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs @@ -175,11 +175,11 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning private void createDrawableRuleset() { - AddUntilStep("wait for beatmap to be loaded", () => MusicController.TrackLoaded); + AddUntilStep("wait for beatmap to be loaded", () => MusicController.CurrentTrack.TrackLoaded); AddStep("create drawable ruleset", () => { - MusicController.Play(true); + MusicController.CurrentTrack.Start(); SetContents(() => { diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs index 5c54393fb8..a3d3bc81c4 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }); - MusicController.Play(true); + MusicController.CurrentTrack.Start(); }); AddStep("Load playfield", () => SetContents(() => new TaikoPlayfield(new ControlPointInfo()) diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index 03faee9ad2..49b40daf99 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -29,6 +29,6 @@ namespace osu.Game.Tests.Skins public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => Beatmap.Value.Skin.GetSample(new SampleInfo("sample")) != null); [Test] - public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => MusicController.CurrentTrack.IsDummyDevice == false); + public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => !MusicController.CurrentTrack.IsDummyDevice); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs index ce99d85e92..53e06a632e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs @@ -19,8 +19,8 @@ namespace osu.Game.Tests.Visual.Gameplay Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - MusicController.Play(true); - MusicController.SeekTo(Beatmap.Value.Beatmap.HitObjects.First().StartTime - 1000); + MusicController.CurrentTrack.Start(); + MusicController.CurrentTrack.Seek(Beatmap.Value.Beatmap.HitObjects.First().StartTime - 1000); Add(new ModNightcore.NightcoreBeatContainer()); diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index dc52300cdb..af692486b7 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -236,7 +236,7 @@ namespace osu.Game.Overlays var track = musicController.CurrentTrack; - if (track.IsDummyDevice == false) + if (!track.IsDummyDevice) { progressBar.EndTime = track.Length; progressBar.CurrentTime = track.CurrentTime; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index d556d948f6..e1702d3eff 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; @@ -64,8 +63,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline waveform.Waveform = b.NewValue.Waveform; track = musicController.CurrentTrack; - Debug.Assert(track != null); - if (track.Length > 0) { MaxZoom = getZoomLevelForVisibleMilliseconds(500); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 78fa6c74b0..6722d9179c 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Edit beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); // Todo: should probably be done at a DrawableRuleset level to share logic with Player. - clock = new EditorClock(Beatmap.Value, musicController.CurrentTrack.Length, beatDivisor) { IsCoupled = false }; + clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(musicController.CurrentTrack); dependencies.CacheAs(clock); @@ -348,7 +348,7 @@ namespace osu.Game.Screens.Edit private void resetTrack(bool seekToStart = false) { - musicController.Stop(); + musicController.CurrentTrack.Stop(); if (seekToStart) { diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index fbfa397795..d0e265adb0 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -25,8 +25,8 @@ namespace osu.Game.Screens.Edit private readonly DecoupleableInterpolatingFramedClock underlyingClock; - public EditorClock(WorkingBeatmap beatmap, double trackLength, BindableBeatDivisor beatDivisor) - : this(beatmap.Beatmap.ControlPointInfo, trackLength, beatDivisor) + public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) + : this(beatmap.Beatmap.ControlPointInfo, beatmap.GetTrack().Length, beatDivisor) { } diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 6e85abf7dc..389629445c 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Menu if (setInfo != null) { initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - UsingThemedIntro = initialBeatmap.GetTrack().IsDummyDevice == false; + UsingThemedIntro = !initialBeatmap.GetTrack().IsDummyDevice; } return UsingThemedIntro; From b66f303e71cf9083c2f764964cf3424bb4433f64 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Aug 2020 00:48:45 +0900 Subject: [PATCH 44/86] Add annotation --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index af6a67ad3f..bec2679103 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; @@ -249,6 +250,7 @@ namespace osu.Game.Beatmaps protected abstract Texture GetBackground(); private readonly RecyclableLazy background; + [NotNull] public Track GetTrack() => GetBeatmapTrack() ?? GetVirtualTrack(1000); protected abstract Track GetBeatmapTrack(); From eec94e1f535e1a5f9d3a17561bfd1ca6d2e5ccab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Aug 2020 00:50:56 +0900 Subject: [PATCH 45/86] Make track not-null in GameplayClockContainer/FailAnimation --- osu.Game/Screens/Play/FailAnimation.cs | 5 ++++- osu.Game/Screens/Play/GameplayClockContainer.cs | 10 +++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index 122ae505ca..6ebee209e2 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.UI; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; @@ -26,6 +27,8 @@ namespace osu.Game.Screens.Play public Action OnComplete; private readonly DrawableRuleset drawableRuleset; + + [NotNull] private readonly ITrack track; private readonly BindableDouble trackFreq = new BindableDouble(1); @@ -34,7 +37,7 @@ namespace osu.Game.Screens.Play private SampleChannel failSample; - public FailAnimation(DrawableRuleset drawableRuleset, ITrack track) + public FailAnimation(DrawableRuleset drawableRuleset, [NotNull] ITrack track) { this.drawableRuleset = drawableRuleset; this.track = track; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index c4f368e1f5..f3466a562e 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using osu.Framework; @@ -27,6 +28,7 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private readonly IReadOnlyList mods; + [NotNull] private ITrack track; public readonly BindableBool IsPaused = new BindableBool(); @@ -60,7 +62,7 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; - public GameplayClockContainer(ITrack track, WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) + public GameplayClockContainer([NotNull] ITrack track, WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) { this.beatmap = beatmap; this.mods = mods; @@ -196,9 +198,6 @@ namespace osu.Game.Screens.Play /// public void StopUsingBeatmapClock() { - if (track == null) - return; - removeSourceClockAdjustments(); track = new TrackVirtual(track.Length); @@ -217,8 +216,6 @@ namespace osu.Game.Screens.Play private void updateRate() { - if (track == null) return; - speedAdjustmentsApplied = true; track.ResetSpeedAdjustments(); @@ -233,7 +230,6 @@ namespace osu.Game.Screens.Play { base.Dispose(isDisposing); removeSourceClockAdjustments(); - track = null; } private void removeSourceClockAdjustments() From 688e4479506645bdacee7cdc7ae9ee9deaa5f1b4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Aug 2020 01:33:06 +0900 Subject: [PATCH 46/86] Fix potential hierarchy mutation from async context --- osu.Game/Overlays/MusicController.cs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 813ad26ae4..c18b564b4f 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -317,11 +317,28 @@ namespace osu.Game.Overlays private void changeTrack() { - CurrentTrack.Expire(); - CurrentTrack = new DrawableTrack(current.GetTrack()); - CurrentTrack.Completed += () => onTrackCompleted(current); + var lastTrack = CurrentTrack; - AddInternal(CurrentTrack); + var newTrack = new DrawableTrack(current.GetTrack()); + newTrack.Completed += () => onTrackCompleted(current); + + CurrentTrack = newTrack; + + // At this point we may potentially be in an async context from tests. This is extremely dangerous but we have to make do for now. + // CurrentTrack is immediately updated above for situations where a immediate knowledge about the new track is required, + // but the mutation of the hierarchy is scheduled to avoid exceptions. + Schedule(() => + { + lastTrack.Expire(); + + if (newTrack == CurrentTrack) + AddInternal(newTrack); + else + { + // If the track has changed via changeTrack() being called multiple times in a single update, force disposal on the old track. + newTrack.Dispose(); + } + }); } private void onTrackCompleted(WorkingBeatmap workingBeatmap) From e47a1eb313f86d9c0f635e58545644139d5cbf34 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Aug 2020 01:41:21 +0900 Subject: [PATCH 47/86] Use adjustable ITrack --- osu.Game/Rulesets/Mods/ModDaycore.cs | 4 ++-- osu.Game/Rulesets/Mods/ModNightcore.cs | 4 ++-- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 2 +- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 4 ++-- osu.Game/Screens/Play/FailAnimation.cs | 4 ++-- osu.Game/Screens/Play/GameplayClockContainer.cs | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 800312d047..61ad7db706 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Mods public override void ApplyToTrack(ITrack track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) - (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } } } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 4932df08f1..4004953cd1 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -41,8 +41,8 @@ namespace osu.Game.Rulesets.Mods public override void ApplyToTrack(ITrack track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) - (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index ae7077c67b..fec21764b0 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods public virtual void ApplyToTrack(ITrack track) { - (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); + track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); } public virtual void ApplyToSample(SampleChannel sample) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index b904cf007b..20c8d0f3e7 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -89,9 +89,9 @@ namespace osu.Game.Rulesets.Mods private void applyPitchAdjustment(ValueChangedEvent adjustPitchSetting) { // remove existing old adjustment - (track as IAdjustableAudioComponent)?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); + track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - (track as IAdjustableAudioComponent)?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); + track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); } private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue) diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index 6ebee209e2..dade904180 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Play Expire(); }); - (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, trackFreq); + track.AddAdjustment(AdjustableProperty.Frequency, trackFreq); applyToPlayfield(drawableRuleset.Playfield); drawableRuleset.Playfield.HitObjectContainer.FlashColour(Color4.Red, 500); @@ -108,7 +108,7 @@ namespace osu.Game.Screens.Play protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - (track as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); + track?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); } } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index f3466a562e..59e26cdf55 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -219,8 +219,8 @@ namespace osu.Game.Screens.Play speedAdjustmentsApplied = true; track.ResetSpeedAdjustments(); - (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); - (track as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); + track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); foreach (var mod in mods.OfType()) mod.ApplyToTrack(track); From c0031955c9ed6c0b74fd655366f988b33ba34ae6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Aug 2020 01:50:18 +0900 Subject: [PATCH 48/86] Update with further framework changes --- osu.Game/Screens/Menu/IntroTriangles.cs | 2 +- osu.Game/Screens/Play/GameplayClockContainer.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 86f7dbdd6f..a9ef20436f 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Menu LoadComponentAsync(new TrianglesIntroSequence(logo, background) { RelativeSizeAxes = Axes.Both, - Clock = new FramedClock(UsingThemedIntro ? (IAdjustableClock)Track : null), + Clock = new FramedClock(UsingThemedIntro ? Track : null), LoadMenu = LoadMenu }, t => { diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 59e26cdf55..f0bbcf957a 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -132,7 +132,7 @@ namespace osu.Game.Screens.Play Schedule(() => { - adjustableClock.ChangeSource((IAdjustableClock)track); + adjustableClock.ChangeSource(track); updateRate(); if (!IsPaused.Value) @@ -201,7 +201,7 @@ namespace osu.Game.Screens.Play removeSourceClockAdjustments(); track = new TrackVirtual(track.Length); - adjustableClock.ChangeSource((IAdjustableClock)track); + adjustableClock.ChangeSource(track); } protected override void Update() From 45876bc55aca3d28034c8ba7d6b3ea5322708c23 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Aug 2020 23:50:33 +0900 Subject: [PATCH 49/86] Fix reference to non-existent variable --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index ab6cf60a79..3c559765d4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -194,7 +194,7 @@ namespace osu.Game.Rulesets.Osu.Tests addSeekStep(0); - AddStep("adjust track rate", () => track.AddAdjustment(AdjustableProperty.Tempo, new BindableDouble(rate))); + AddStep("adjust track rate", () => MusicController.CurrentTrack.AddAdjustment(AdjustableProperty.Tempo, new BindableDouble(rate))); // autoplay replay frames use track time; // if a spin takes 1000ms in track time and we're playing with a 2x rate adjustment, the spin will take 500ms of *real* time. // therefore we need to apply the rate adjustment to the replay itself to change from track time to real time, From 91e28b849de0ed31402536b63069b8b2d5383f4b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Aug 2020 00:29:23 +0900 Subject: [PATCH 50/86] Fix incorrect BeatmapManager construction --- .../Visual/UserInterface/TestSceneDeleteLocalScore.cs | 3 ++- osu.Game/Beatmaps/BeatmapManager.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index eb4750a597..e54292f7cc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -6,6 +6,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Graphics.Cursor; using osu.Framework.Platform; using osu.Framework.Testing; @@ -79,7 +80,7 @@ namespace osu.Game.Tests.Visual.UserInterface var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); dependencies.Cache(rulesetStore = new RulesetStore(ContextFactory)); - dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesetStore, null, Audio, dependencies.Get(), Beatmap.Default)); + dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesetStore, null, dependencies.Get(), dependencies.Get(), Beatmap.Default)); dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, null, ContextFactory)); beatmap = beatmapManager.Import(TestResources.GetTestBeatmapForImport()).Result.Beatmaps[0]; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6f01580998..0cadcf5947 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -9,6 +9,7 @@ using System.Linq.Expressions; using System.Text; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -67,7 +68,7 @@ namespace osu.Game.Beatmaps private readonly TextureStore textureStore; private readonly ITrackStore trackStore; - public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null, + public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, GameHost host = null, WorkingBeatmap defaultBeatmap = null) : base(storage, contextFactory, api, new BeatmapStore(contextFactory), host) { From a6708c4286d3973c8ed68be43176228da1137237 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 16 Aug 2020 23:04:49 +0900 Subject: [PATCH 51/86] Rename resolved variable in MainMenu --- osu.Game/Screens/Menu/MainMenu.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 470e8ca9a6..fac9e9eb49 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Menu private GameHost host { get; set; } [Resolved] - private MusicController music { get; set; } + private MusicController musicController { get; set; } [Resolved(canBeNull: true)] private LoginOverlay login { get; set; } @@ -176,12 +176,12 @@ namespace osu.Game.Screens.Menu var metadata = Beatmap.Value.Metadata; - if (last is IntroScreen && music.TrackLoaded) + if (last is IntroScreen && musicController.TrackLoaded) { - if (!music.CurrentTrack.IsRunning) + if (!musicController.CurrentTrack.IsRunning) { - music.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * music.CurrentTrack.Length); - music.CurrentTrack.Start(); + musicController.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.CurrentTrack.Length); + musicController.CurrentTrack.Start(); } } @@ -256,7 +256,7 @@ namespace osu.Game.Screens.Menu // we may have consumed our preloaded instance, so let's make another. preloadSongSelect(); - music.EnsurePlayingSomething(); + musicController.EnsurePlayingSomething(); } public override bool OnExiting(IScreen next) From d9debef1568a393f0da721759d09206ffe5c3701 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Aug 2020 15:38:16 +0900 Subject: [PATCH 52/86] Add explicit LoadTrack method --- .../TestSceneGameplayClockContainer.cs | 4 +++- .../Gameplay/TestSceneStoryboardSamples.cs | 5 ++-- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 3 ++- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 23 ++++++++++++++++++- osu.Game/Overlays/MusicController.cs | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 2 +- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- .../Screens/Play/GameplayClockContainer.cs | 4 ++-- osu.Game/Screens/Play/Player.cs | 2 +- 10 files changed, 37 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs index bb60ae73db..dc9f540907 100644 --- a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs @@ -22,7 +22,9 @@ namespace osu.Game.Tests.Gameplay AddStep("create container", () => { var working = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - Add(gcc = new GameplayClockContainer(working.GetTrack(), working, Array.Empty(), 0)); + working.LoadTrack(); + + Add(gcc = new GameplayClockContainer(working, Array.Empty(), 0)); }); AddStep("start track", () => gcc.Start()); diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index 360e7eccdc..6f788a070e 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -60,8 +60,9 @@ namespace osu.Game.Tests.Gameplay AddStep("create container", () => { var working = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + working.LoadTrack(); - Add(gameplayContainer = new GameplayClockContainer(working.GetTrack(), working, Array.Empty(), 0)); + Add(gameplayContainer = new GameplayClockContainer(working, Array.Empty(), 0)); gameplayContainer.Add(sample = new DrawableStoryboardSample(new StoryboardSampleInfo(string.Empty, 0, 1)) { @@ -105,7 +106,7 @@ namespace osu.Game.Tests.Gameplay Beatmap.Value = new TestCustomSkinWorkingBeatmap(new OsuRuleset().RulesetInfo, Audio); SelectedMods.Value = new[] { testedMod }; - Add(gameplayContainer = new GameplayClockContainer(MusicController.CurrentTrack, Beatmap.Value, SelectedMods.Value, 0)); + Add(gameplayContainer = new GameplayClockContainer(Beatmap.Value, SelectedMods.Value, 0)); gameplayContainer.Add(sample = new TestDrawableStoryboardSample(new StoryboardSampleInfo("test-sample", 1, 1)) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 58fd760fc3..c7e5e2a7ec 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -33,8 +33,9 @@ namespace osu.Game.Tests.Visual.Gameplay increment = skip_time; var working = CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); + working.LoadTrack(); - Child = gameplayClockContainer = new GameplayClockContainer(working.GetTrack(), working, Array.Empty(), 0) + Child = gameplayClockContainer = new GameplayClockContainer(working, Array.Empty(), 0) { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index e020625b99..88d73fd7c4 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -58,6 +58,6 @@ namespace osu.Game.Beatmaps /// /// Retrieves the which this provides. /// - Track GetTrack(); + Track LoadTrack(); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index bec2679103..b4046a4e95 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -250,8 +250,29 @@ namespace osu.Game.Beatmaps protected abstract Texture GetBackground(); private readonly RecyclableLazy background; + private Track loadedTrack; + + /// + /// Load a new audio track instance for this beatmap. + /// + /// A fresh track instance, which will also be available via . [NotNull] - public Track GetTrack() => GetBeatmapTrack() ?? GetVirtualTrack(1000); + public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000); + + /// + /// Get the loaded audio track instance. must have first been called. + /// This generally happens via MusicController when changing the global beatmap. + /// + public Track Track + { + get + { + if (loadedTrack == null) + throw new InvalidOperationException($"Cannot access {nameof(Track)} without first calling {nameof(LoadTrack)}."); + + return loadedTrack; + } + } protected abstract Track GetBeatmapTrack(); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index c18b564b4f..8bbae33811 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -319,7 +319,7 @@ namespace osu.Game.Overlays { var lastTrack = CurrentTrack; - var newTrack = new DrawableTrack(current.GetTrack()); + var newTrack = new DrawableTrack(current.LoadTrack()); newTrack.Completed += () => onTrackCompleted(current); CurrentTrack = newTrack; diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index d0e265adb0..634a6f7e25 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Edit private readonly DecoupleableInterpolatingFramedClock underlyingClock; public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) - : this(beatmap.Beatmap.ControlPointInfo, beatmap.GetTrack().Length, beatDivisor) + : this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor) { } diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 389629445c..3e4320ae44 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Menu if (setInfo != null) { initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - UsingThemedIntro = !initialBeatmap.GetTrack().IsDummyDevice; + UsingThemedIntro = !initialBeatmap.LoadTrack().IsDummyDevice; } return UsingThemedIntro; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index f0bbcf957a..50a7331e4f 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -62,12 +62,12 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; - public GameplayClockContainer([NotNull] ITrack track, WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) + public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) { this.beatmap = beatmap; this.mods = mods; this.gameplayStartTime = gameplayStartTime; - this.track = track; + track = beatmap.Track; firstHitObjectTime = beatmap.Beatmap.HitObjects.First().StartTime; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e92164de7c..ccdd4ea8a4 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -179,7 +179,7 @@ namespace osu.Game.Screens.Play if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = new GameplayClockContainer(musicController.CurrentTrack, Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); + InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); From 93a8bc3d5aa330cb6ef008ac8858ae4d005434aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Aug 2020 22:36:03 +0900 Subject: [PATCH 53/86] Remove local reset method in GameplayClockContainer --- .../TestSceneGameplayClockContainer.cs | 4 +-- .../Gameplay/TestSceneStoryboardSamples.cs | 4 +-- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 4 +-- .../Screens/Play/GameplayClockContainer.cs | 31 +++++++------------ osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Tests/Visual/PlayerTestScene.cs | 2 ++ 6 files changed, 19 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs index dc9f540907..891537c4ad 100644 --- a/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneGameplayClockContainer.cs @@ -1,10 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using NUnit.Framework; using osu.Framework.Testing; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; using osu.Game.Tests.Visual; @@ -24,7 +22,7 @@ namespace osu.Game.Tests.Gameplay var working = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); working.LoadTrack(); - Add(gcc = new GameplayClockContainer(working, Array.Empty(), 0)); + Add(gcc = new GameplayClockContainer(working, 0)); }); AddStep("start track", () => gcc.Start()); diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index 6f788a070e..a690eb3b59 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -62,7 +62,7 @@ namespace osu.Game.Tests.Gameplay var working = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); working.LoadTrack(); - Add(gameplayContainer = new GameplayClockContainer(working, Array.Empty(), 0)); + Add(gameplayContainer = new GameplayClockContainer(working, 0)); gameplayContainer.Add(sample = new DrawableStoryboardSample(new StoryboardSampleInfo(string.Empty, 0, 1)) { @@ -106,7 +106,7 @@ namespace osu.Game.Tests.Gameplay Beatmap.Value = new TestCustomSkinWorkingBeatmap(new OsuRuleset().RulesetInfo, Audio); SelectedMods.Value = new[] { testedMod }; - Add(gameplayContainer = new GameplayClockContainer(Beatmap.Value, SelectedMods.Value, 0)); + Add(gameplayContainer = new GameplayClockContainer(Beatmap.Value, 0)); gameplayContainer.Add(sample = new TestDrawableStoryboardSample(new StoryboardSampleInfo("test-sample", 1, 1)) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index c7e5e2a7ec..841722a8f1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; using osuTK; @@ -35,7 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay var working = CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); working.LoadTrack(); - Child = gameplayClockContainer = new GameplayClockContainer(working, Array.Empty(), 0) + Child = gameplayClockContainer = new GameplayClockContainer(working, 0) { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 50a7331e4f..7a9cb3dddd 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; @@ -16,7 +15,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Rulesets.Mods; namespace osu.Game.Screens.Play { @@ -26,7 +24,6 @@ namespace osu.Game.Screens.Play public class GameplayClockContainer : Container { private readonly WorkingBeatmap beatmap; - private readonly IReadOnlyList mods; [NotNull] private ITrack track; @@ -62,10 +59,9 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; - public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) + public GameplayClockContainer(WorkingBeatmap beatmap, double gameplayStartTime) { this.beatmap = beatmap; - this.mods = mods; this.gameplayStartTime = gameplayStartTime; track = beatmap.Track; @@ -122,13 +118,10 @@ namespace osu.Game.Screens.Play public void Restart() { - // The Reset() call below causes speed adjustments to be reset in an async context, leading to deadlocks. - // The deadlock can be prevented by resetting the track synchronously before entering the async context. - track.ResetSpeedAdjustments(); - Task.Run(() => { - track.Reset(); + track.Seek(0); + track.Stop(); Schedule(() => { @@ -216,14 +209,13 @@ namespace osu.Game.Screens.Play private void updateRate() { - speedAdjustmentsApplied = true; - track.ResetSpeedAdjustments(); + if (speedAdjustmentsApplied) + return; track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); - foreach (var mod in mods.OfType()) - mod.ApplyToTrack(track); + speedAdjustmentsApplied = true; } protected override void Dispose(bool isDisposing) @@ -234,11 +226,12 @@ namespace osu.Game.Screens.Play private void removeSourceClockAdjustments() { - if (speedAdjustmentsApplied) - { - track.ResetSpeedAdjustments(); - speedAdjustmentsApplied = false; - } + if (!speedAdjustmentsApplied) return; + + track.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + track.RemoveAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); + + speedAdjustmentsApplied = false; } private class HardwareCorrectionOffsetClock : FramedOffsetClock diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ccdd4ea8a4..cc70995b26 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -179,7 +179,7 @@ namespace osu.Game.Screens.Play if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); + InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime); AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 2c46e7f6d3..7d06c99133 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -29,6 +29,8 @@ namespace osu.Game.Tests.Visual { Dependencies.Cache(LocalConfig = new OsuConfigManager(LocalStorage)); LocalConfig.GetBindable(OsuSetting.DimLevel).Value = 1.0; + + MusicController.AllowRateAdjustments = true; } [SetUpSteps] From 083bcde3cf260147304b110d4a0956285690e4ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Aug 2020 13:01:35 +0900 Subject: [PATCH 54/86] Fix beatmap transfer not working --- osu.Game/Beatmaps/WorkingBeatmap.cs | 7 +++++++ osu.Game/Overlays/MusicController.cs | 13 ++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index b4046a4e95..c9a60d7948 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -259,6 +259,13 @@ namespace osu.Game.Beatmaps [NotNull] public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000); + /// + /// 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. + /// + /// The track to transfer. + public void TransferTrack([NotNull] Track track) => loadedTrack = track ?? throw new ArgumentNullException(nameof(track)); + /// /// Get the loaded audio track instance. must have first been called. /// This generally happens via MusicController when changing the global beatmap. diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 8bbae33811..c1116ff651 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -282,10 +282,10 @@ namespace osu.Game.Overlays { TrackChangeDirection direction = TrackChangeDirection.None; + bool audioEquals = beatmap.NewValue?.BeatmapInfo?.AudioEquals(current?.BeatmapInfo) ?? false; + if (current != null) { - bool audioEquals = beatmap.NewValue?.BeatmapInfo?.AudioEquals(current.BeatmapInfo) ?? false; - if (audioEquals) direction = TrackChangeDirection.None; else if (queuedDirection.HasValue) @@ -305,8 +305,15 @@ namespace osu.Game.Overlays current = beatmap.NewValue; - if (CurrentTrack.IsDummyDevice || !beatmap.OldValue.BeatmapInfo.AudioEquals(current?.BeatmapInfo)) + if (!audioEquals || CurrentTrack.IsDummyDevice) + { changeTrack(); + } + else + { + // transfer still valid track to new working beatmap + current.TransferTrack(beatmap.OldValue.Track); + } TrackChanged?.Invoke(current, direction); From 526f06be4c714410061a732dfb041c84c3c45f0d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 13:53:12 +0900 Subject: [PATCH 55/86] Add back track loaded bool in WorkingBeatmap --- osu.Game/Beatmaps/WorkingBeatmap.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 051d66af7b..8d5543cadb 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -275,6 +275,11 @@ namespace osu.Game.Beatmaps /// The track to transfer. public void TransferTrack([NotNull] Track track) => loadedTrack = track ?? throw new ArgumentNullException(nameof(track)); + /// + /// Whether this beatmap's track has been loaded via . + /// + public bool TrackLoaded => loadedTrack != null; + /// /// Get the loaded audio track instance. must have first been called. /// This generally happens via MusicController when changing the global beatmap. @@ -283,7 +288,7 @@ namespace osu.Game.Beatmaps { get { - if (loadedTrack == null) + if (!TrackLoaded) throw new InvalidOperationException($"Cannot access {nameof(Track)} without first calling {nameof(LoadTrack)}."); return loadedTrack; From 0b0ff626477a611a161ece951ffb9f0682dd8a44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 14:46:23 +0900 Subject: [PATCH 56/86] Switch timeline to use track directly from beatmap again --- .../Compose/Components/Timeline/Timeline.cs | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index e1702d3eff..96c48c0ddc 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -30,6 +30,28 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [Resolved] private MusicController musicController { get; set; } + /// + /// The timeline's scroll position in the last frame. + /// + private float lastScrollPosition; + + /// + /// The track time in the last frame. + /// + private double lastTrackTime; + + /// + /// Whether the user is currently dragging the timeline. + /// + private bool handlingDragInput; + + /// + /// Whether the track was playing before a user drag event. + /// + private bool trackWasPlaying; + + private ITrack track; + public Timeline() { ZoomDuration = 200; @@ -61,9 +83,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Beatmap.BindValueChanged(b => { waveform.Waveform = b.NewValue.Waveform; - track = musicController.CurrentTrack; + track = b.NewValue.Track; - if (track.Length > 0) + // todo: i don't think this is safe, the track may not be loaded yet. + if (b.NewValue.Track.Length > 0) { MaxZoom = getZoomLevelForVisibleMilliseconds(500); MinZoom = getZoomLevelForVisibleMilliseconds(10000); @@ -74,28 +97,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private float getZoomLevelForVisibleMilliseconds(double milliseconds) => (float)(track.Length / milliseconds); - /// - /// The timeline's scroll position in the last frame. - /// - private float lastScrollPosition; - - /// - /// The track time in the last frame. - /// - private double lastTrackTime; - - /// - /// Whether the user is currently dragging the timeline. - /// - private bool handlingDragInput; - - /// - /// Whether the track was playing before a user drag event. - /// - private bool trackWasPlaying; - - private ITrack track; - protected override void Update() { base.Update(); From d2c2e8bbe89536f5fed2a35ea35aa514029ac28d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 15:05:56 +0900 Subject: [PATCH 57/86] Revert some more usage of MusicController back to WorkingBeatmap --- .../TestSceneHoldNoteInput.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs | 2 +- .../Skinning/TestSceneDrawableTaikoMascot.cs | 4 ++-- .../Skinning/TestSceneTaikoPlayfield.cs | 2 +- osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs | 10 +++++++--- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 ++ osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs | 3 +-- 9 files changed, 17 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 19b69bac6d..95072cf4f8 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -343,7 +343,7 @@ namespace osu.Game.Rulesets.Mania.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs index 744ad46c28..854626d362 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs @@ -385,7 +385,7 @@ namespace osu.Game.Rulesets.Osu.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 1690f648f9..b543b6fa94 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -366,7 +366,7 @@ namespace osu.Game.Rulesets.Osu.Tests judgementResults = new List(); }); - AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack.CurrentTime == 0); + AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs index 6141bf062e..47d8a5c012 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs @@ -175,11 +175,11 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning private void createDrawableRuleset() { - AddUntilStep("wait for beatmap to be loaded", () => MusicController.CurrentTrack.TrackLoaded); + AddUntilStep("wait for beatmap to be loaded", () => Beatmap.Value.Track.IsLoaded); AddStep("create drawable ruleset", () => { - MusicController.CurrentTrack.Start(); + Beatmap.Value.Track.Start(); SetContents(() => { diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs index a3d3bc81c4..7b7e2c43d1 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }); - MusicController.CurrentTrack.Start(); + Beatmap.Value.Track.Start(); }); AddStep("Load playfield", () => SetContents(() => new TaikoPlayfield(new ControlPointInfo()) diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index 49b40daf99..eff430ac25 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -18,17 +19,20 @@ namespace osu.Game.Tests.Skins [Resolved] private BeatmapManager beatmaps { get; set; } + private WorkingBeatmap beatmap; + [BackgroundDependencyLoader] private void load() { var imported = beatmaps.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-beatmap.osz"))).Result; - Beatmap.Value = beatmaps.GetWorkingBeatmap(imported.Beatmaps[0]); + beatmap = beatmaps.GetWorkingBeatmap(imported.Beatmaps[0]); + beatmap.LoadTrack(); } [Test] - public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => Beatmap.Value.Skin.GetSample(new SampleInfo("sample")) != null); + public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => beatmap.Skin.GetSample(new SampleInfo("sample")) != null); [Test] - public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => !MusicController.CurrentTrack.IsDummyDevice); + public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => !(beatmap.Track is TrackVirtual)); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 8d5543cadb..6a89739e6f 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -278,7 +278,7 @@ namespace osu.Game.Beatmaps /// /// Whether this beatmap's track has been loaded via . /// - public bool TrackLoaded => loadedTrack != null; + public virtual bool TrackLoaded => loadedTrack != null; /// /// Get the loaded audio track instance. must have first been called. diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index d091da3206..bfcb2403c1 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -27,6 +27,8 @@ namespace osu.Game.Tests.Beatmaps this.storyboard = storyboard; } + public override bool TrackLoaded => true; + public override bool BeatmapLoaded => true; protected override IBeatmap GetBeatmap() => beatmap; diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index 7651285970..ad24ffc7b8 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -13,8 +13,7 @@ namespace osu.Game.Tests.Visual base.Update(); // note that this will override any mod rate application - if (MusicController.TrackLoaded) - MusicController.CurrentTrack.Tempo.Value = Clock.Rate; + Beatmap.Value.Track.Tempo.Value = Clock.Rate; } } } From f7e4feee3449630475a11a2291803997fb23e029 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 15:25:57 +0900 Subject: [PATCH 58/86] Update remaining Player components to use WorkingBeatmap again --- osu.Game/Screens/Play/FailAnimation.cs | 13 ++++++------- osu.Game/Screens/Play/Player.cs | 8 ++++---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index dade904180..54c644c999 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -6,12 +6,12 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.UI; using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Graphics; using osu.Framework.Utils; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Graphics; @@ -28,24 +28,23 @@ namespace osu.Game.Screens.Play private readonly DrawableRuleset drawableRuleset; - [NotNull] - private readonly ITrack track; - private readonly BindableDouble trackFreq = new BindableDouble(1); + private Track track; + private const float duration = 2500; private SampleChannel failSample; - public FailAnimation(DrawableRuleset drawableRuleset, [NotNull] ITrack track) + public FailAnimation(DrawableRuleset drawableRuleset) { this.drawableRuleset = drawableRuleset; - this.track = track; } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load(AudioManager audio, IBindable beatmap) { + track = beatmap.Value.Track; failSample = audio.Samples.Get(@"Gameplay/failsound"); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index cc70995b26..a8fda10604 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -151,7 +151,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuConfigManager config, MusicController musicController) + private void load(AudioManager audio, OsuConfigManager config) { Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); @@ -188,7 +188,7 @@ namespace osu.Game.Screens.Play addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, Beatmap.Value, playableBeatmap); - addOverlayComponents(GameplayClockContainer, Beatmap.Value, musicController.CurrentTrack); + addOverlayComponents(GameplayClockContainer, Beatmap.Value); if (!DrawableRuleset.AllowGameplayOverlays) { @@ -265,7 +265,7 @@ namespace osu.Game.Screens.Play }); } - private void addOverlayComponents(Container target, WorkingBeatmap working, ITrack track) + private void addOverlayComponents(Container target, WorkingBeatmap working) { target.AddRange(new[] { @@ -332,7 +332,7 @@ namespace osu.Game.Screens.Play performImmediateExit(); }, }, - failAnimation = new FailAnimation(DrawableRuleset, track) { OnComplete = onFailComplete, }, + failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, }, }); } From 0ae460fb8f4e7b9c235ce0cb27ae933157d162c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 15:50:14 +0900 Subject: [PATCH 59/86] Avoid beatmap load call in IntroScreen --- osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs | 3 ++- osu.Game/Screens/Menu/IntroScreen.cs | 3 ++- osu.Game/Screens/Menu/IntroTriangles.cs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs index 29be250b12..5f135febf4 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Screens; +using osu.Framework.Utils; using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.Menus @@ -15,7 +16,7 @@ namespace osu.Game.Tests.Visual.Menus public TestSceneIntroWelcome() { AddUntilStep("wait for load", () => MusicController.TrackLoaded); - + AddAssert("correct track", () => Precision.AlmostEquals(MusicController.CurrentTrack.Length, 48000, 1)); AddAssert("check if menu music loops", () => MusicController.CurrentTrack.Looping); } } diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 3e4320ae44..363933694d 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -66,6 +66,7 @@ namespace osu.Game.Screens.Menu /// /// Whether the is provided by osu! resources, rather than a user beatmap. + /// Only valid during or after . /// protected bool UsingThemedIntro { get; private set; } @@ -115,7 +116,6 @@ namespace osu.Game.Screens.Menu if (setInfo != null) { initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - UsingThemedIntro = !initialBeatmap.LoadTrack().IsDummyDevice; } return UsingThemedIntro; @@ -169,6 +169,7 @@ namespace osu.Game.Screens.Menu { beatmap.Value = initialBeatmap; Track = musicController.CurrentTrack; + UsingThemedIntro = !initialBeatmap.LoadTrack().IsDummyDevice; logo.MoveTo(new Vector2(0.5f)); logo.ScaleTo(Vector2.One); diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index a9ef20436f..52281967ee 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader] private void load() { - if (MenuVoice.Value && !UsingThemedIntro) + if (MenuVoice.Value) welcome = audio.Samples.Get(@"Intro/welcome"); } From 3b03116179c3e0ec88b815dd2bcfc32961058510 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 16:45:59 +0900 Subject: [PATCH 60/86] Remove unnecessary using statement --- osu.Game/Screens/Play/Player.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a8fda10604..9be4fd6a65 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -8,7 +8,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From 70697cf1a0e36e57b3533613a5795bdb8722a746 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 16:58:45 +0900 Subject: [PATCH 61/86] Restore remaining editor components to use Beatmap.Track --- osu.Game.Tests/Visual/Editing/TimelineTestScene.cs | 11 ++++++----- .../Screens/Edit/Components/BottomBarContainer.cs | 2 ++ osu.Game/Screens/Edit/Components/PlaybackControl.cs | 8 ++------ .../Timelines/Summary/Parts/TimelinePart.cs | 8 ++------ .../Edit/Compose/Components/Timeline/Timeline.cs | 6 +++--- .../Components/Timeline/TimelineTickDisplay.cs | 7 ++++--- osu.Game/Screens/Edit/Editor.cs | 10 ++++------ osu.Game/Screens/Edit/EditorClock.cs | 10 +++++----- osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 ++- 9 files changed, 30 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index 4988a09650..fdb8781563 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -3,11 +3,12 @@ using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; @@ -64,10 +65,10 @@ namespace osu.Game.Tests.Visual.Editing private readonly Drawable marker; [Resolved] - private EditorClock editorClock { get; set; } + private IBindable beatmap { get; set; } [Resolved] - private MusicController musicController { get; set; } + private EditorClock editorClock { get; set; } public AudioVisualiser() { @@ -93,8 +94,8 @@ namespace osu.Game.Tests.Visual.Editing { base.Update(); - if (musicController.TrackLoaded) - marker.X = (float)(editorClock.CurrentTime / musicController.CurrentTrack.Length); + if (beatmap.Value.Track.IsLoaded) + marker.X = (float)(editorClock.CurrentTime / beatmap.Value.Track.Length); } } diff --git a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs index 8d8c59b2ee..cb5078a479 100644 --- a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs +++ b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,6 +18,7 @@ namespace osu.Game.Screens.Edit.Components private const float contents_padding = 15; protected readonly IBindable Beatmap = new Bindable(); + protected Track Track => Beatmap.Value.Track; private readonly Drawable background; private readonly Container content; diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 5bafc120af..59b3d1c565 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -16,7 +16,6 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays; using osuTK.Input; namespace osu.Game.Screens.Edit.Components @@ -28,9 +27,6 @@ namespace osu.Game.Screens.Edit.Components [Resolved] private EditorClock editorClock { get; set; } - [Resolved] - private MusicController musicController { get; set; } - private readonly BindableNumber tempo = new BindableDouble(1); [BackgroundDependencyLoader] @@ -66,12 +62,12 @@ namespace osu.Game.Screens.Edit.Components } }; - musicController.CurrentTrack.AddAdjustment(AdjustableProperty.Tempo, tempo); + Track?.AddAdjustment(AdjustableProperty.Tempo, tempo); } protected override void Dispose(bool isDisposing) { - musicController?.CurrentTrack.RemoveAdjustment(AdjustableProperty.Tempo, tempo); + Track?.RemoveAdjustment(AdjustableProperty.Tempo, tempo); base.Dispose(isDisposing); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index c8a470c58a..4a7c3f26bc 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -8,7 +8,6 @@ using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; -using osu.Game.Overlays; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { @@ -27,9 +26,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected override Container Content => content; - [Resolved] - private MusicController musicController { get; set; } - public TimelinePart(Container content = null) { AddInternal(this.content = content ?? new Container { RelativeSizeAxes = Axes.Both }); @@ -50,14 +46,14 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts private void updateRelativeChildSize() { // the track may not be loaded completely (only has a length once it is). - if (!musicController.TrackLoaded) + if (!Beatmap.Value.Track.IsLoaded) { content.RelativeChildSize = Vector2.One; Schedule(updateRelativeChildSize); return; } - content.RelativeChildSize = new Vector2((float)Math.Max(1, musicController.CurrentTrack.Length), 1); + content.RelativeChildSize = new Vector2((float)Math.Max(1, Beatmap.Value.Track.Length), 1); } protected virtual void LoadBeatmap(WorkingBeatmap beatmap) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 96c48c0ddc..c6bfdda698 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline /// private bool trackWasPlaying; - private ITrack track; + private Track track; public Timeline() { @@ -134,7 +134,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void seekTrackToCurrent() { - if (!musicController.TrackLoaded) + if (!track.IsLoaded) return; editorClock.Seek(Current / Content.DrawWidth * track.Length); @@ -142,7 +142,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void scrollToTrackTime() { - if (!musicController.TrackLoaded || track.Length == 0) + if (!track.IsLoaded || track.Length == 0) return; ScrollTo((float)(editorClock.CurrentTime / track.Length) * Content.DrawWidth, false); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index cb122c590e..36ee976bf7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -3,9 +3,10 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Overlays; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; @@ -17,7 +18,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private EditorBeatmap beatmap { get; set; } [Resolved] - private MusicController musicController { get; set; } + private Bindable working { get; set; } [Resolved] private BindableBeatDivisor beatDivisor { get; set; } @@ -43,7 +44,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) { var point = beatmap.ControlPointInfo.TimingPoints[i]; - var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : musicController.CurrentTrack.Length; + var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; int beat = 0; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 6722d9179c..d92f3922c3 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -14,6 +14,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Platform; +using osu.Framework.Timing; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; @@ -27,7 +28,6 @@ using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; -using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Setup; @@ -53,9 +53,6 @@ namespace osu.Game.Screens.Edit [Resolved] private BeatmapManager beatmapManager { get; set; } - [Resolved] - private MusicController musicController { get; set; } - private Box bottomBackground; private Container screenContainer; @@ -82,8 +79,9 @@ namespace osu.Game.Screens.Edit beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); // Todo: should probably be done at a DrawableRuleset level to share logic with Player. + var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; - clock.ChangeSource(musicController.CurrentTrack); + clock.ChangeSource(sourceClock); dependencies.CacheAs(clock); AddInternal(clock); @@ -348,7 +346,7 @@ namespace osu.Game.Screens.Edit private void resetTrack(bool seekToStart = false) { - musicController.CurrentTrack.Stop(); + Beatmap.Value.Track?.Stop(); if (seekToStart) { diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 634a6f7e25..d4d0feb813 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -30,11 +30,6 @@ namespace osu.Game.Screens.Edit { } - public EditorClock() - : this(new ControlPointInfo(), 1000, new BindableBeatDivisor()) - { - } - public EditorClock(ControlPointInfo controlPointInfo, double trackLength, BindableBeatDivisor beatDivisor) { this.beatDivisor = beatDivisor; @@ -45,6 +40,11 @@ namespace osu.Game.Screens.Edit underlyingClock = new DecoupleableInterpolatingFramedClock(); } + public EditorClock() + : this(new ControlPointInfo(), 1000, new BindableBeatDivisor()) + { + } + /// /// Seek to the closest snappable beat from a time. /// diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 59c9329d37..f0ec638fc9 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Events; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit; @@ -43,7 +44,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(ValueChangedEvent e) { Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; - Clock.ChangeSource(MusicController.CurrentTrack); + Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock()); Clock.ProcessFrame(); } From a47b8222b53a00daab14556988952824e59ec1ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 16:59:11 +0900 Subject: [PATCH 62/86] Restore multiplayer to use beatmap track --- osu.Game/Screens/Multi/Multiplayer.cs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 1a39d80f8d..4912df17b1 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Multi private readonly Bindable currentFilter = new Bindable(new FilterCriteria()); [Resolved] - private MusicController musicController { get; set; } + private MusicController music { get; set; } [Cached(Type = typeof(IRoomManager))] private RoomManager roomManager; @@ -343,10 +343,15 @@ namespace osu.Game.Screens.Multi { if (screenStack.CurrentScreen is MatchSubScreen) { - musicController.CurrentTrack.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - musicController.CurrentTrack.Looping = true; + var track = Beatmap.Value?.Track; - musicController.EnsurePlayingSomething(); + if (track != null) + { + track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; + track.Looping = true; + + music.EnsurePlayingSomething(); + } } else { @@ -356,8 +361,13 @@ namespace osu.Game.Screens.Multi private void cancelLooping() { - musicController.CurrentTrack.Looping = false; - musicController.CurrentTrack.RestartPoint = 0; + var track = Beatmap?.Value?.Track; + + if (track != null) + { + track.Looping = false; + track.RestartPoint = 0; + } } protected override void Dispose(bool isDisposing) From d5cbb589c2ff6fa2a8cfac96ef881d3406149ca9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 17:21:08 +0900 Subject: [PATCH 63/86] Revert some test scene changes to use Beatmap.Track where relevant --- .../Gameplay/TestSceneCompletionCancellation.cs | 6 +++--- .../Visual/Gameplay/TestSceneGameplayRewinding.cs | 12 ++++-------- .../Gameplay/TestSceneNightcoreBeatContainer.cs | 4 ++-- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 2 +- .../Visual/Gameplay/TestScenePlayerLoader.cs | 8 ++++---- .../Visual/Gameplay/TestSceneStoryboard.cs | 14 ++++++++++---- 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs index b39cfc3699..6fd5511e5a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Gameplay base.SetUpSteps(); // Ensure track has actually running before attempting to seek - AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); } [Test] @@ -70,13 +70,13 @@ namespace osu.Game.Tests.Visual.Gameplay private void complete() { - AddStep("seek to completion", () => MusicController.SeekTo(5000)); + AddStep("seek to completion", () => Beatmap.Value.Track.Seek(5000)); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); } private void cancel() { - AddStep("rewind to cancel", () => MusicController.SeekTo(4000)); + AddStep("rewind to cancel", () => Beatmap.Value.Track.Seek(4000)); AddUntilStep("completion cleared by processor", () => !Player.ScoreProcessor.HasCompleted.Value); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 6bdc65078a..73c6970482 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -8,7 +8,6 @@ using osu.Framework.Audio; using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Beatmaps; -using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Storyboards; @@ -21,16 +20,13 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private AudioManager audioManager { get; set; } - [Resolved] - private MusicController musicController { get; set; } - - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) - => new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); [Test] public void TestNoJudgementsOnRewind() { - AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); addSeekStep(3000); AddAssert("all judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7)); @@ -43,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void addSeekStep(double time) { - AddStep($"seek to {time}", () => MusicController.SeekTo(time)); + AddStep($"seek to {time}", () => Beatmap.Value.Track.Seek(time)); // Allow a few frames of lenience AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs index 53e06a632e..951ee1489d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs @@ -19,8 +19,8 @@ namespace osu.Game.Tests.Visual.Gameplay Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - MusicController.CurrentTrack.Start(); - MusicController.CurrentTrack.Seek(Beatmap.Value.Beatmap.HitObjects.First().StartTime - 1000); + Beatmap.Value.Track.Start(); + Beatmap.Value.Track.Seek(Beatmap.Value.Beatmap.HitObjects.First().StartTime - 1000); Add(new ModNightcore.NightcoreBeatContainer()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index e7dd586f4e..420bf29429 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -288,7 +288,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void confirmNoTrackAdjustments() { - AddAssert("track has no adjustments", () => MusicController.CurrentTrack.AggregateFrequency.Value == 1); + AddAssert("track has no adjustments", () => Beatmap.Value.Track.AggregateFrequency.Value == 1); } private void restart() => AddStep("restart", () => Player.Restart()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index c3be6aee2b..4fac7bb45f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tests.Visual.Gameplay Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); foreach (var mod in SelectedMods.Value.OfType()) - mod.ApplyToTrack(MusicController.CurrentTrack); + mod.ApplyToTrack(Beatmap.Value.Track); InputManager.Child = container; } @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for not current", () => !loader.IsCurrentScreen()); AddAssert("player did not load", () => player == null); AddUntilStep("player disposed", () => loader.DisposalTask == null); - AddAssert("mod rate still applied", () => MusicController.CurrentTrack.Rate != 1); + AddAssert("mod rate still applied", () => Beatmap.Value.Track.Rate != 1); } /// @@ -88,13 +88,13 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("load dummy beatmap", () => ResetPlayer(false, () => SelectedMods.Value = new[] { new OsuModNightcore() })); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddAssert("mod rate applied", () => MusicController.CurrentTrack.Rate != 1); + AddAssert("mod rate applied", () => Beatmap.Value.Track.Rate != 1); AddUntilStep("wait for non-null player", () => player != null); AddStep("exit loader", () => loader.Exit()); AddUntilStep("wait for not current", () => !loader.IsCurrentScreen()); AddAssert("player did not load", () => !player.IsLoaded); AddUntilStep("player disposed", () => loader.DisposalTask?.IsCompleted == true); - AddAssert("mod rate still applied", () => MusicController.CurrentTrack.Rate != 1); + AddAssert("mod rate still applied", () => Beatmap.Value.Track.Rate != 1); } [Test] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index c11a47d62b..9f1492a25f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -25,12 +25,16 @@ namespace osu.Game.Tests.Visual.Gameplay private readonly Container storyboardContainer; private DrawableStoryboard storyboard; + [Cached] + private MusicController musicController = new MusicController(); + public TestSceneStoryboard() { Clock = new FramedClock(); AddRange(new Drawable[] { + musicController, new Container { RelativeSizeAxes = Axes.Both, @@ -83,9 +87,11 @@ namespace osu.Game.Tests.Visual.Gameplay private void restart() { - MusicController.CurrentTrack.Reset(); + var track = Beatmap.Value.Track; + + track.Reset(); loadStoryboard(Beatmap.Value); - MusicController.CurrentTrack.Start(); + track.Start(); } private void loadStoryboard(WorkingBeatmap working) @@ -100,7 +106,7 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard.Passing = false; storyboardContainer.Add(storyboard); - decoupledClock.ChangeSource(MusicController.CurrentTrack); + decoupledClock.ChangeSource(working.Track); } private void loadStoryboardNoVideo() @@ -123,7 +129,7 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard = sb.CreateDrawable(Beatmap.Value); storyboardContainer.Add(storyboard); - decoupledClock.ChangeSource(MusicController.CurrentTrack); + decoupledClock.ChangeSource(Beatmap.Value.Track); } } } From 1edafc39bac27e54ebb32dfb44124382ec3b55b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 18:33:24 +0900 Subject: [PATCH 64/86] Fix intro welcome playing double due to missing conditional --- osu.Game/Screens/Menu/IntroTriangles.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 52281967ee..a96fddb5ad 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -64,7 +64,8 @@ namespace osu.Game.Screens.Menu }, t => { AddInternal(t); - welcome?.Play(); + if (!UsingThemedIntro) + welcome?.Play(); StartTrack(); }); From 308d9f59679033e0585cd96b4d5e550c9d2b31d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 18:43:58 +0900 Subject: [PATCH 65/86] Ensure locally executed methods are always loaded before propagation --- osu.Game/Overlays/MusicController.cs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index c1116ff651..112026d9e2 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -231,9 +231,7 @@ namespace osu.Game.Overlays if (playable != null) { - if (beatmap is Bindable working) - working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); - + changeBeatmap(beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value)); restartTrack(); return PreviousTrackResult.Previous; } @@ -257,9 +255,7 @@ namespace osu.Game.Overlays if (playable != null) { - if (beatmap is Bindable working) - working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); - + changeBeatmap(beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value)); restartTrack(); return true; } @@ -278,11 +274,15 @@ namespace osu.Game.Overlays private TrackChangeDirection? queuedDirection; - private void beatmapChanged(ValueChangedEvent beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) => changeBeatmap(beatmap.NewValue); + + private void changeBeatmap(WorkingBeatmap newWorking) { + var lastWorking = current; + TrackChangeDirection direction = TrackChangeDirection.None; - bool audioEquals = beatmap.NewValue?.BeatmapInfo?.AudioEquals(current?.BeatmapInfo) ?? false; + bool audioEquals = newWorking?.BeatmapInfo?.AudioEquals(current?.BeatmapInfo) ?? false; if (current != null) { @@ -297,13 +297,13 @@ namespace osu.Game.Overlays { // figure out the best direction based on order in playlist. var last = BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - var next = beatmap.NewValue == null ? -1 : BeatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); + var next = newWorking == null ? -1 : BeatmapSets.TakeWhile(b => b.ID != newWorking.BeatmapSetInfo?.ID).Count(); direction = last > next ? TrackChangeDirection.Prev : TrackChangeDirection.Next; } } - current = beatmap.NewValue; + current = newWorking; if (!audioEquals || CurrentTrack.IsDummyDevice) { @@ -312,7 +312,7 @@ namespace osu.Game.Overlays else { // transfer still valid track to new working beatmap - current.TransferTrack(beatmap.OldValue.Track); + current.TransferTrack(lastWorking.Track); } TrackChanged?.Invoke(current, direction); @@ -320,6 +320,11 @@ namespace osu.Game.Overlays ResetTrackAdjustments(); queuedDirection = null; + + // this will be a noop if coming from the beatmapChanged event. + // the exception is local operations like next/prev, where we want to complete loading the track before sending out a change. + if (beatmap.Value != current && beatmap is Bindable working) + working.Value = current; } private void changeTrack() From 4239e9f684e7e1594fc652be1640a940d9092cd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 18:44:14 +0900 Subject: [PATCH 66/86] Fix storyboard test not actually working due to incorrect track referencing --- .../Visual/Gameplay/TestSceneStoryboard.cs | 50 ++++++++----------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index 9f1492a25f..5a2b8d22fd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -22,19 +22,32 @@ namespace osu.Game.Tests.Visual.Gameplay [TestFixture] public class TestSceneStoryboard : OsuTestScene { - private readonly Container storyboardContainer; + private Container storyboardContainer; private DrawableStoryboard storyboard; - [Cached] - private MusicController musicController = new MusicController(); + [Test] + public void TestStoryboard() + { + AddStep("Restart", restart); + AddToggleStep("Passing", passing => + { + if (storyboard != null) storyboard.Passing = passing; + }); + } - public TestSceneStoryboard() + [Test] + public void TestStoryboardMissingVideo() + { + AddStep("Load storyboard with missing video", loadStoryboardNoVideo); + } + + [BackgroundDependencyLoader] + private void load() { Clock = new FramedClock(); AddRange(new Drawable[] { - musicController, new Container { RelativeSizeAxes = Axes.Both, @@ -58,32 +71,11 @@ namespace osu.Game.Tests.Visual.Gameplay State = { Value = Visibility.Visible }, } }); + + Beatmap.BindValueChanged(beatmapChanged, true); } - [Test] - public void TestStoryboard() - { - AddStep("Restart", restart); - AddToggleStep("Passing", passing => - { - if (storyboard != null) storyboard.Passing = passing; - }); - } - - [Test] - public void TestStoryboardMissingVideo() - { - AddStep("Load storyboard with missing video", loadStoryboardNoVideo); - } - - [BackgroundDependencyLoader] - private void load() - { - Beatmap.ValueChanged += beatmapChanged; - } - - private void beatmapChanged(ValueChangedEvent e) - => loadStoryboard(e.NewValue); + private void beatmapChanged(ValueChangedEvent e) => loadStoryboard(e.NewValue); private void restart() { From f63d1ba612df01640d3abe79a1db5217a947f54a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Aug 2020 18:52:53 +0900 Subject: [PATCH 67/86] Remove stray call to LoadTrack that was forgotten --- osu.Game/Screens/Menu/IntroScreen.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 363933694d..884cbfe107 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -12,7 +12,6 @@ using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.IO.Archives; -using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osu.Game.Skinning; using osuTK; @@ -61,9 +60,6 @@ namespace osu.Game.Screens.Menu [Resolved] private AudioManager audio { get; set; } - [Resolved] - private MusicController musicController { get; set; } - /// /// Whether the is provided by osu! resources, rather than a user beatmap. /// Only valid during or after . @@ -168,8 +164,8 @@ namespace osu.Game.Screens.Menu if (!resuming) { beatmap.Value = initialBeatmap; - Track = musicController.CurrentTrack; - UsingThemedIntro = !initialBeatmap.LoadTrack().IsDummyDevice; + Track = initialBeatmap.Track; + UsingThemedIntro = !initialBeatmap.Track.IsDummyDevice; logo.MoveTo(new Vector2(0.5f)); logo.ScaleTo(Vector2.One); From b72f06fef68a219b599671cefe3ce2e2b252d3e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Aug 2020 19:42:34 +0900 Subject: [PATCH 68/86] Centralise and clarify LoadTrack documentation --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 10 +++++++++- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 ---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 88d73fd7c4..bcd94d76fd 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -56,8 +56,16 @@ namespace osu.Game.Beatmaps IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods = null, TimeSpan? timeout = null); /// - /// Retrieves the which this provides. + /// Load a new audio track instance for this beatmap. This should be called once before accessing . + /// The caller of this method is responsible for the lifetime of the track. /// + /// + /// In a standard game context, the loading of the track is managed solely by MusicController, which will + /// automatically load the track of the current global IBindable WorkingBeatmap. + /// As such, this method should only be called in very special scenarios, such as external tests or apps which are + /// outside of the game context. + /// + /// A fresh track instance, which will also be available via . Track LoadTrack(); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 6a89739e6f..6a161e6e04 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -261,10 +261,6 @@ namespace osu.Game.Beatmaps private Track loadedTrack; - /// - /// Load a new audio track instance for this beatmap. - /// - /// A fresh track instance, which will also be available via . [NotNull] public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000); From db5226042747b7e5078903cdb14d3a36f9e4af73 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Aug 2020 19:44:54 +0900 Subject: [PATCH 69/86] Rename and clarify comment regarding "previous" track disposal --- osu.Game/Overlays/MusicController.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 112026d9e2..6d5b5d43cd 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -331,10 +331,10 @@ namespace osu.Game.Overlays { var lastTrack = CurrentTrack; - var newTrack = new DrawableTrack(current.LoadTrack()); - newTrack.Completed += () => onTrackCompleted(current); + var queuedTrack = new DrawableTrack(current.LoadTrack()); + queuedTrack.Completed += () => onTrackCompleted(current); - CurrentTrack = newTrack; + CurrentTrack = queuedTrack; // At this point we may potentially be in an async context from tests. This is extremely dangerous but we have to make do for now. // CurrentTrack is immediately updated above for situations where a immediate knowledge about the new track is required, @@ -343,12 +343,13 @@ namespace osu.Game.Overlays { lastTrack.Expire(); - if (newTrack == CurrentTrack) - AddInternal(newTrack); + if (queuedTrack == CurrentTrack) + AddInternal(queuedTrack); else { - // If the track has changed via changeTrack() being called multiple times in a single update, force disposal on the old track. - newTrack.Dispose(); + // If the track has changed since the call to changeTrack, it is safe to dispose the + // queued track rather than consume it. + queuedTrack.Dispose(); } }); } From 122265ff0e233a72a48a329370e8f6f8c1fde6e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Aug 2020 19:47:05 +0900 Subject: [PATCH 70/86] Revert non-track usage --- osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index c6bfdda698..c617950c64 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline track = b.NewValue.Track; // todo: i don't think this is safe, the track may not be loaded yet. - if (b.NewValue.Track.Length > 0) + if (track.Length > 0) { MaxZoom = getZoomLevelForVisibleMilliseconds(500); MinZoom = getZoomLevelForVisibleMilliseconds(10000); From dca307e93379e258c15b5423130014afb9f8f03a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 24 Aug 2020 13:02:39 +0900 Subject: [PATCH 71/86] Use beatmap directly in ReadyButton --- osu.Game/Screens/Multi/Match/Components/ReadyButton.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index 384d3bd5a5..a64f24dd7e 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -10,7 +10,6 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; -using osu.Game.Overlays; namespace osu.Game.Screens.Multi.Match.Components { @@ -27,9 +26,6 @@ namespace osu.Game.Screens.Multi.Match.Components [Resolved] private BeatmapManager beatmaps { get; set; } - [Resolved] - private MusicController musicController { get; set; } - private bool hasBeatmap; public ReadyButton() @@ -104,7 +100,7 @@ namespace osu.Game.Screens.Multi.Match.Components return; } - bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(musicController.CurrentTrack.Length) < endDate.Value; + bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value; Enabled.Value = hasBeatmap && hasEnoughTime; } From f65991f31fbe30fcfd55a30e921b890b0709715d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Aug 2020 23:28:58 +0900 Subject: [PATCH 72/86] Revert some usages based on review feedback --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 8 ++------ osu.Game/Overlays/Music/PlaylistOverlay.cs | 9 +++------ .../Edit/Compose/Components/Timeline/Timeline.cs | 4 ---- osu.Game/Screens/Menu/LogoVisualisation.cs | 12 ++++-------- 4 files changed, 9 insertions(+), 24 deletions(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 69021e1634..1c9cdc174a 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -7,7 +7,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Overlays; namespace osu.Game.Graphics.Containers { @@ -15,9 +14,6 @@ namespace osu.Game.Graphics.Containers { protected readonly IBindable Beatmap = new Bindable(); - [Resolved] - private MusicController musicController { get; set; } - private int lastBeat; private TimingControlPoint lastTimingPoint; @@ -58,9 +54,9 @@ namespace osu.Game.Graphics.Containers TimingControlPoint timingPoint = null; EffectControlPoint effectPoint = null; - if (musicController.TrackLoaded && Beatmap.Value.BeatmapLoaded) + if (Beatmap.Value.TrackLoaded && Beatmap.Value.BeatmapLoaded) { - track = musicController.CurrentTrack; + track = Beatmap.Value.Track; beatmap = Beatmap.Value.Beatmap; } diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 7471e31923..b45d84049f 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -30,9 +30,6 @@ namespace osu.Game.Overlays.Music [Resolved] private BeatmapManager beatmaps { get; set; } - [Resolved] - private MusicController musicController { get; set; } - private FilterControl filter; private Playlist list; @@ -85,7 +82,7 @@ namespace osu.Game.Overlays.Music if (toSelect != null) { beatmap.Value = beatmaps.GetWorkingBeatmap(toSelect); - musicController.CurrentTrack.Restart(); + beatmap.Value.Track.Restart(); } }; } @@ -119,12 +116,12 @@ namespace osu.Game.Overlays.Music { if (set.ID == (beatmap.Value?.BeatmapSetInfo?.ID ?? -1)) { - musicController.CurrentTrack.Seek(0); + beatmap.Value?.Track.Seek(0); return; } beatmap.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First()); - musicController.CurrentTrack.Restart(); + beatmap.Value.Track.Restart(); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index c617950c64..8c0e35b80e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Audio; using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osuTK; @@ -27,9 +26,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [Resolved] private EditorClock editorClock { get; set; } - [Resolved] - private MusicController musicController { get; set; } - /// /// The timeline's scroll position in the last frame. /// diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 4d95ee9b7b..ebbb19636c 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -20,7 +20,6 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Utils; -using osu.Game.Overlays; namespace osu.Game.Screens.Menu { @@ -75,9 +74,6 @@ namespace osu.Game.Screens.Menu /// public float Magnitude { get; set; } = 1; - [Resolved] - private MusicController musicController { get; set; } - private readonly float[] frequencyAmplitudes = new float[256]; private IShader shader; @@ -107,15 +103,15 @@ namespace osu.Game.Screens.Menu private void updateAmplitudes() { - var effect = beatmap.Value.BeatmapLoaded && musicController.TrackLoaded - ? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(musicController.CurrentTrack.CurrentTime) + var effect = beatmap.Value.BeatmapLoaded && beatmap.Value.TrackLoaded + ? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(beatmap.Value.Track.CurrentTime) : null; for (int i = 0; i < temporalAmplitudes.Length; i++) temporalAmplitudes[i] = 0; - if (musicController.TrackLoaded) - addAmplitudesFromSource(musicController.CurrentTrack); + if (beatmap.Value.TrackLoaded) + addAmplitudesFromSource(beatmap.Value.Track); foreach (var source in amplitudeSources) addAmplitudesFromSource(source); From fcf703864288ea6b974f21f8bf049cd254ab4036 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Aug 2020 00:21:50 +0900 Subject: [PATCH 73/86] Fix a couple of missed cases --- osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs | 4 ++-- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs index cd46e8c545..3d100e4b1c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep("enable autoplay", () => autoplay = true); base.SetUpSteps(); - AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); double startTime = hitObjects[sliderIndex].StartTime; retrieveDrawableSlider(sliderIndex); @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep("have autoplay", () => autoplay = true); base.SetUpSteps(); - AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); double startTime = hitObjects[sliderIndex].StartTime; retrieveDrawableSlider(sliderIndex); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 3c559765d4..f7909071ea 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Tests { base.SetUpSteps(); - AddUntilStep("wait for track to start running", () => MusicController.IsPlaying); + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)Player.DrawableRuleset.Playfield.AllHitObjects.First()); } From 5949a281fc54e94b34843ec5d91d8b819b1851b4 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 27 Aug 2020 19:29:18 +0200 Subject: [PATCH 74/86] Make Introduce bindable property OverlayActivationMode in OsuScreen --- osu.Game/OsuGame.cs | 5 ++++- osu.Game/Screens/IOsuScreen.cs | 4 ++-- osu.Game/Screens/OsuScreen.cs | 6 +++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 053eb01dcd..6a390942b7 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -972,9 +972,12 @@ namespace osu.Game break; } + if (current is IOsuScreen currentOsuScreen) + OverlayActivationMode.UnbindFrom(currentOsuScreen.OverlayActivationMode); + if (newScreen is IOsuScreen newOsuScreen) { - OverlayActivationMode.Value = newOsuScreen.InitialOverlayActivationMode; + OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode); MusicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments; diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 761f842c22..c9dce310af 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -39,9 +39,9 @@ namespace osu.Game.Screens bool HideOverlaysOnEnter { get; } /// - /// Whether overlays should be able to be opened once this screen is entered or resumed. + /// Whether overlays should be able to be opened when this screen is current. /// - OverlayActivation InitialOverlayActivationMode { get; } + public Bindable OverlayActivationMode { get; } /// /// The amount of parallax to be applied while this screen is displayed. diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 872a1cd39a..c687c34ce9 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -44,10 +44,12 @@ namespace osu.Game.Screens public virtual bool HideOverlaysOnEnter => false; /// - /// Whether overlays should be able to be opened once this screen is entered or resumed. + /// The initial initial overlay activation mode to use when this screen is entered for the first time. /// public virtual OverlayActivation InitialOverlayActivationMode => OverlayActivation.All; + public Bindable OverlayActivationMode { get; } + public virtual bool CursorVisible => true; protected new OsuGameBase Game => base.Game as OsuGameBase; @@ -138,6 +140,8 @@ namespace osu.Game.Screens { Anchor = Anchor.Centre; Origin = Anchor.Centre; + + OverlayActivationMode = new Bindable(InitialOverlayActivationMode); } [BackgroundDependencyLoader(true)] From ad223bc460ea0d1a6a4d07a86d17cfa3ad0b5b38 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 27 Aug 2020 20:07:24 +0200 Subject: [PATCH 75/86] Make game bindable immutable. --- osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs | 7 ++++++- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 2 +- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/Toolbar/Toolbar.cs | 2 +- osu.Game/Screens/Menu/ButtonSystem.cs | 3 --- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index f819ae4682..841860accb 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -91,7 +91,12 @@ namespace osu.Game.Tests.Visual.Menus public class TestToolbar : Toolbar { - public new Bindable OverlayActivationMode => base.OverlayActivationMode; + public TestToolbar() + { + base.OverlayActivationMode.BindTo(OverlayActivationMode); + } + + public new Bindable OverlayActivationMode { get; } = new Bindable(OverlayActivation.All); } } } diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 93ac69bdbf..751ccc8f15 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -35,7 +35,7 @@ namespace osu.Game.Graphics.Containers [Resolved] private PreviewTrackManager previewTrackManager { get; set; } - protected readonly Bindable OverlayActivationMode = new Bindable(OverlayActivation.All); + protected readonly IBindable OverlayActivationMode = new Bindable(OverlayActivation.All); [BackgroundDependencyLoader(true)] private void load(AudioManager audio) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6a390942b7..e6d96df927 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -88,7 +88,7 @@ namespace osu.Game private IdleTracker idleTracker; - public readonly Bindable OverlayActivationMode = new Bindable(); + public readonly IBindable OverlayActivationMode = new Bindable(); protected OsuScreenStack ScreenStack; diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 3bf9e85428..393e349bd0 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Toolbar private const double transition_time = 500; - protected readonly Bindable OverlayActivationMode = new Bindable(OverlayActivation.All); + protected readonly IBindable OverlayActivationMode = new Bindable(OverlayActivation.All); // Toolbar components like RulesetSelector should receive keyboard input events even when the toolbar is hidden. public override bool PropagateNonPositionalInputSubTree => true; diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 5ba7a8ddc3..4becdd58cd 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -270,9 +270,6 @@ namespace osu.Game.Screens.Menu ButtonSystemState lastState = state; state = value; - if (game != null) - game.OverlayActivationMode.Value = state == ButtonSystemState.Exit ? OverlayActivation.Disabled : OverlayActivation.All; - updateLogoState(lastState); Logger.Log($"{nameof(ButtonSystem)}'s state changed from {lastState} to {state}"); From 8de7744b52e98d0e42a9b88ec08b10ac1a5c2f6f Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 28 Aug 2020 09:55:14 +0200 Subject: [PATCH 76/86] Add back disabling of overlays on exiting game. --- osu.Game/Screens/Menu/MainMenu.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 57252d557e..859184834b 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -280,6 +280,7 @@ namespace osu.Game.Screens.Menu } buttons.State = ButtonSystemState.Exit; + OverlayActivationMode.Value = OverlayActivation.Disabled; songTicker.Hide(); From 03b7c8b88969ae337ac52bcddd56c0c5d034f111 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 29 Aug 2020 19:39:50 +0200 Subject: [PATCH 77/86] Remove unneeded access modifier. --- osu.Game/Screens/IOsuScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index c9dce310af..ead8e4bc22 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens /// /// Whether overlays should be able to be opened when this screen is current. /// - public Bindable OverlayActivationMode { get; } + Bindable OverlayActivationMode { get; } /// /// The amount of parallax to be applied while this screen is displayed. From dd093f44d8826af623ed5232e6a38d8f39b0ce20 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 31 Aug 2020 11:16:13 +0200 Subject: [PATCH 78/86] Cast base immutable bindable to mutable for testing purposes and make InitialOverlayActivationMode property protected --- osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs | 7 +------ osu.Game/Screens/OsuScreen.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/StartupScreen.cs | 2 +- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 841860accb..2a4486812c 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -91,12 +91,7 @@ namespace osu.Game.Tests.Visual.Menus public class TestToolbar : Toolbar { - public TestToolbar() - { - base.OverlayActivationMode.BindTo(OverlayActivationMode); - } - - public new Bindable OverlayActivationMode { get; } = new Bindable(OverlayActivation.All); + public new Bindable OverlayActivationMode => base.OverlayActivationMode as Bindable; } } } diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index c687c34ce9..c10deaf1e5 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens /// /// The initial initial overlay activation mode to use when this screen is entered for the first time. /// - public virtual OverlayActivation InitialOverlayActivationMode => OverlayActivation.All; + protected virtual OverlayActivation InitialOverlayActivationMode => OverlayActivation.All; public Bindable OverlayActivationMode { get; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 541275cf55..0a5158c6dc 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Play public override bool HideOverlaysOnEnter => true; - public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; + protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; /// /// Whether gameplay should pause when the game window focus is lost. diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index c3e36c8e9d..e5e134fd39 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -18,6 +18,6 @@ namespace osu.Game.Screens public override bool AllowRateAdjustments => false; - public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; + protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; } } From 26b4226b5538c9f95657fdc985b9a873c763b4f1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Sep 2020 16:55:10 +0900 Subject: [PATCH 79/86] Fix ModTimeRamp not working --- osu.Game/Screens/Play/Player.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 9be4fd6a65..07be482529 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -52,6 +52,9 @@ namespace osu.Game.Screens.Play public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; + // We are managing our own adjustments (see OnEntering/OnExiting). + public override bool AllowRateAdjustments => false; + /// /// Whether gameplay should pause when the game window focus is lost. /// @@ -627,6 +630,10 @@ namespace osu.Game.Screens.Play foreach (var mod in Mods.Value.OfType()) mod.ApplyToHUD(HUDOverlay); + + Beatmap.Value.Track.ResetSpeedAdjustments(); + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToTrack(Beatmap.Value.Track); } public override void OnSuspending(IScreen next) @@ -660,6 +667,8 @@ namespace osu.Game.Screens.Play // as we are no longer the current screen, we cannot guarantee the track is still usable. GameplayClockContainer?.StopUsingBeatmapClock(); + Beatmap.Value.Track.ResetSpeedAdjustments(); + fadeOut(); return base.OnExiting(next); } From 7e1844ed773368a4b932ea0e2d7fc87fa0fc53b4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Sep 2020 18:07:19 +0900 Subject: [PATCH 80/86] Fix track adjusments being reset incorrectly --- osu.Game/Screens/Play/Player.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 07be482529..82c446f5e4 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -80,6 +80,9 @@ namespace osu.Game.Screens.Play [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private MusicController musicController { get; set; } + private SampleChannel sampleRestart; public BreakOverlay BreakOverlay; @@ -631,9 +634,12 @@ namespace osu.Game.Screens.Play foreach (var mod in Mods.Value.OfType()) mod.ApplyToHUD(HUDOverlay); - Beatmap.Value.Track.ResetSpeedAdjustments(); + // Our mods are local copies of the global mods so they need to be re-applied to the track. + // This is done through the music controller (for now), because resetting speed adjustments on the beatmap track also removes adjustments provided by DrawableTrack. + // Todo: In the future, player will receive in a track and will probably not have to worry about this... + musicController.ResetTrackAdjustments(); foreach (var mod in Mods.Value.OfType()) - mod.ApplyToTrack(Beatmap.Value.Track); + mod.ApplyToTrack(musicController.CurrentTrack); } public override void OnSuspending(IScreen next) @@ -667,7 +673,7 @@ namespace osu.Game.Screens.Play // as we are no longer the current screen, we cannot guarantee the track is still usable. GameplayClockContainer?.StopUsingBeatmapClock(); - Beatmap.Value.Track.ResetSpeedAdjustments(); + musicController.ResetTrackAdjustments(); fadeOut(); return base.OnExiting(next); From f793bf66e5e34c94c374b4f19391c83ce08fd361 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Sep 2020 14:25:24 +0900 Subject: [PATCH 81/86] Remove rate adjustment from player test scene --- osu.Game/Tests/Visual/PlayerTestScene.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 7d06c99133..2c46e7f6d3 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -29,8 +29,6 @@ namespace osu.Game.Tests.Visual { Dependencies.Cache(LocalConfig = new OsuConfigManager(LocalStorage)); LocalConfig.GetBindable(OsuSetting.DimLevel).Value = 1.0; - - MusicController.AllowRateAdjustments = true; } [SetUpSteps] From 5195da3ceb6abc93db51e711c94086a009bf197d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Sep 2020 15:18:51 +0900 Subject: [PATCH 82/86] Add message box in bracket editor explaining how to get started --- .../Screens/Editors/LadderEditorScreen.cs | 12 ++++++ osu.Game.Tournament/TournamentGame.cs | 25 +----------- osu.Game.Tournament/WarningBox.cs | 40 +++++++++++++++++++ 3 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 osu.Game.Tournament/WarningBox.cs diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index f3eecf8afe..efec4cffdd 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -26,6 +26,8 @@ namespace osu.Game.Tournament.Screens.Editors [Cached] private LadderEditorInfo editorInfo = new LadderEditorInfo(); + private WarningBox rightClickMessage; + protected override bool DrawLoserPaths => true; [BackgroundDependencyLoader] @@ -37,6 +39,16 @@ namespace osu.Game.Tournament.Screens.Editors Origin = Anchor.TopRight, Margin = new MarginPadding(5) }); + + AddInternal(rightClickMessage = new WarningBox("Right click to place and link matches")); + + LadderInfo.Matches.CollectionChanged += (_, __) => updateMessage(); + updateMessage(); + } + + private void updateMessage() + { + rightClickMessage.Alpha = LadderInfo.Matches.Count > 0 ? 0 : 1; } public void BeginJoin(TournamentMatch match, bool losers) diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 307ee1c773..bbe4a53d8f 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -87,30 +87,7 @@ namespace osu.Game.Tournament }, } }, - heightWarning = new Container - { - Masking = true, - CornerRadius = 5, - Depth = float.MinValue, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - Colour = Color4.Red, - RelativeSizeAxes = Axes.Both, - }, - new TournamentSpriteText - { - Text = "Please make the window wider", - Font = OsuFont.Torus.With(weight: FontWeight.Bold), - Colour = Color4.White, - Padding = new MarginPadding(20) - } - } - }, + heightWarning = new WarningBox("Please make the window wider"), new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tournament/WarningBox.cs b/osu.Game.Tournament/WarningBox.cs new file mode 100644 index 0000000000..814482aea4 --- /dev/null +++ b/osu.Game.Tournament/WarningBox.cs @@ -0,0 +1,40 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osuTK.Graphics; + +namespace osu.Game.Tournament +{ + internal class WarningBox : Container + { + public WarningBox(string text) + { + Masking = true; + CornerRadius = 5; + Depth = float.MinValue; + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new Box + { + Colour = Color4.Red, + RelativeSizeAxes = Axes.Both, + }, + new TournamentSpriteText + { + Text = text, + Font = OsuFont.Torus.With(weight: FontWeight.Bold), + Colour = Color4.White, + Padding = new MarginPadding(20) + } + }; + } + } +} From 555b2196b734cbce88a2acd2a0832367bf1c33d4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Sep 2020 15:23:50 +0900 Subject: [PATCH 83/86] Add xmldoc to MusicController.ResetTrackAdjustments() --- osu.Game/Overlays/MusicController.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 6d5b5d43cd..c831584248 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -382,6 +382,12 @@ namespace osu.Game.Overlays } } + /// + /// Resets the speed adjustments currently applied on and applies the mod adjustments if is true. + /// + /// + /// Does not reset speed adjustments applied directly to the beatmap track. + /// public void ResetTrackAdjustments() { CurrentTrack.ResetSpeedAdjustments(); From 6a765d2d765dd01f4bd145560d6b30542aae7813 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Sep 2020 20:04:56 +0900 Subject: [PATCH 84/86] Add smooth fading between audio tracks on transition --- osu.Game/Overlays/MusicController.cs | 6 +++++- osu.Game/Screens/Menu/IntroScreen.cs | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index c831584248..17877a69a5 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -341,10 +342,13 @@ namespace osu.Game.Overlays // but the mutation of the hierarchy is scheduled to avoid exceptions. Schedule(() => { - lastTrack.Expire(); + lastTrack.VolumeTo(0, 500, Easing.Out).Expire(); if (queuedTrack == CurrentTrack) + { AddInternal(queuedTrack); + queuedTrack.VolumeTo(0).Then().VolumeTo(1, 300, Easing.Out); + } else { // If the track has changed since the call to changeTrack, it is safe to dispose the diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 884cbfe107..473e6b0364 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -12,6 +12,7 @@ using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.IO.Archives; +using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osu.Game.Skinning; using osuTK; @@ -60,6 +61,9 @@ namespace osu.Game.Screens.Menu [Resolved] private AudioManager audio { get; set; } + [Resolved] + private MusicController musicController { get; set; } + /// /// Whether the is provided by osu! resources, rather than a user beatmap. /// Only valid during or after . @@ -167,6 +171,9 @@ namespace osu.Game.Screens.Menu Track = initialBeatmap.Track; UsingThemedIntro = !initialBeatmap.Track.IsDummyDevice; + // ensure the track starts at maximum volume + musicController.CurrentTrack.FinishTransforms(); + logo.MoveTo(new Vector2(0.5f)); logo.ScaleTo(Vector2.One); logo.Hide(); From 3fc6a74fdfa1bfd30c05b4748b7712c97530a923 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 2 Sep 2020 19:55:46 +0200 Subject: [PATCH 85/86] Expose an immutable bindable in interface. --- osu.Game/Screens/IOsuScreen.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index ead8e4bc22..e19037c2c4 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens /// /// Whether overlays should be able to be opened when this screen is current. /// - Bindable OverlayActivationMode { get; } + IBindable OverlayActivationMode { get; } /// /// The amount of parallax to be applied while this screen is displayed. diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index c10deaf1e5..cb8f2d21fe 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -48,7 +48,9 @@ namespace osu.Game.Screens /// protected virtual OverlayActivation InitialOverlayActivationMode => OverlayActivation.All; - public Bindable OverlayActivationMode { get; } + protected readonly Bindable OverlayActivationMode; + + IBindable IOsuScreen.OverlayActivationMode => OverlayActivationMode; public virtual bool CursorVisible => true; From 754274a146522ce3a8e69bda0ff4541819b539a2 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 2 Sep 2020 20:55:26 +0200 Subject: [PATCH 86/86] Fix and add XMLDoc --- osu.Game/OsuGame.cs | 3 +++ osu.Game/Screens/OsuScreen.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e6d96df927..31926a6845 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -88,6 +88,9 @@ namespace osu.Game private IdleTracker idleTracker; + /// + /// Whether overlays should be able to be opened game-wide. Value is sourced from the current active screen. + /// public readonly IBindable OverlayActivationMode = new Bindable(); protected OsuScreenStack ScreenStack; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index cb8f2d21fe..a44d14fb5c 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens public virtual bool HideOverlaysOnEnter => false; /// - /// The initial initial overlay activation mode to use when this screen is entered for the first time. + /// The initial overlay activation mode to use when this screen is entered for the first time. /// protected virtual OverlayActivation InitialOverlayActivationMode => OverlayActivation.All;