diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 5a8cf32f14..1f1d2cea5f 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -12,7 +13,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; -using osu.Game.Utils; using osuTK; using osuTK.Graphics; @@ -61,7 +61,7 @@ namespace osu.Desktop.Overlays }, new OsuSpriteText { - Colour = DebugUtils.IsDebug ? colours.Red : Color4.White, + Colour = DebugUtils.IsDebugBuild ? colours.Red : Color4.White, Text = game.Version }, } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index c04c7127fd..5a903b9417 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -216,13 +216,13 @@ namespace osu.Game.Tests.Visual.UserInterface private void testRankedText(Mod mod) { - AddWaitStep("wait for fade", 1); + waitForLoad(); AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); selectNext(mod); - AddWaitStep("wait for fade", 1); + waitForLoad(); AddAssert("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); selectPrevious(mod); - AddWaitStep("wait for fade", 1); + waitForLoad(); AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); } @@ -232,6 +232,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void checkSelected(Mod mod) { + waitForLoad(); AddAssert($"check {mod.Name} is selected", () => { var button = modSelect.GetModButton(mod); @@ -239,8 +240,14 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + private void waitForLoad() + { + AddUntilStep("wait for icons to load", () => modSelect.AllLoaded); + } + private void checkNotSelected(Mod mod) { + waitForLoad(); AddAssert($"check {mod.Name} is not selected", () => { var button = modSelect.GetModButton(mod); @@ -254,6 +261,8 @@ namespace osu.Game.Tests.Visual.UserInterface { public new Bindable> SelectedMods => base.SelectedMods; + public bool AllLoaded => ModSectionsContainer.Children.All(c => c.ModIconsLoaded); + public ModButton GetModButton(Mod mod) { var section = ModSectionsContainer.Children.Single(s => s.ModType == mod.Type); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f38eecef81..692e7189a3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -184,6 +184,8 @@ namespace osu.Game LocalConfig.BindWith(OsuSetting.VolumeInactive, userInactiveVolume); IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true); + + Beatmap.BindValueChanged(beatmapChanged, true); } private ExternalLinkOpener externalLinkOpener; @@ -284,6 +286,23 @@ namespace osu.Game }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); } + #region Beatmap jukebox progression + + private void beatmapChanged(ValueChangedEvent beatmap) + { + var nextBeatmap = beatmap.NewValue; + if (nextBeatmap?.Track != null) + nextBeatmap.Track.Completed += currentTrackCompleted; + } + + private void currentTrackCompleted() + { + if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled) + musicController.NextTrack(); + } + + #endregion + private ScheduledDelegate performFromMainMenuTask; /// @@ -446,7 +465,7 @@ namespace osu.Game Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(new MusicController + loadComponentSingleFile(musicController = new MusicController { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -719,8 +738,11 @@ namespace osu.Game private Container topMostOverlayContent; private FrameworkConfigManager frameworkConfig; + private ScalingContainer screenContainer; + private MusicController musicController; + protected override bool OnExiting() { if (screenStack.CurrentScreen is Loader) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 637708a0e5..87ff721bbb 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; +using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.IO.Stores; @@ -34,7 +35,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Skinning; using osuTK.Input; -using DebugUtils = osu.Game.Utils.DebugUtils; namespace osu.Game { @@ -97,7 +97,7 @@ namespace osu.Game get { if (!IsDeployedBuild) - return @"local " + (DebugUtils.IsDebug ? @"debug" : @"release"); + return @"local " + (DebugUtils.IsDebugBuild ? @"debug" : @"release"); var version = AssemblyVersion; return $@"{version.Major}.{version.Minor}.{version.Build}"; diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 4c44aad87d..dedd397fa5 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Mods; using System; using System.Linq; using System.Collections.Generic; +using System.Threading; using osu.Framework.Input.Events; using osu.Game.Graphics; @@ -33,6 +34,13 @@ namespace osu.Game.Overlays.Mods public IEnumerable SelectedMods => buttons.Select(b => b.SelectedMod).Where(m => m != null); + private CancellationTokenSource modsLoadCts; + + /// + /// True when all mod icons have completed loading. + /// + public bool ModIconsLoaded { get; private set; } = true; + public IEnumerable Mods { set @@ -48,7 +56,15 @@ namespace osu.Game.Overlays.Mods }; }).ToArray(); - ButtonsContainer.Children = modContainers; + modsLoadCts?.Cancel(); + ModIconsLoaded = false; + + LoadComponentsAsync(modContainers, c => + { + ModIconsLoaded = true; + ButtonsContainer.ChildrenEnumerable = c; + }, (modsLoadCts = new CancellationTokenSource()).Token); + buttons = modContainers.OfType().ToArray(); if (value.Any()) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 8b9bac877b..36937def2b 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -70,9 +70,6 @@ namespace osu.Game.Overlays { Width = 400; Margin = new MarginPadding(10); - - // required to let MusicController handle beatmap cycling. - AlwaysPresent = true; } [BackgroundDependencyLoader] @@ -349,18 +346,11 @@ namespace osu.Game.Overlays direction = last > next ? TransformDirection.Prev : TransformDirection.Next; } - - //current.Track.Completed -= currentTrackCompleted; } - current = beatmap.NewValue; - - if (current != null) - current.Track.Completed += currentTrackCompleted; - progressBar.CurrentTime = 0; - updateDisplay(current, direction); + updateDisplay(current = beatmap.NewValue, direction); updateAudioAdjustments(); queuedDirection = null; @@ -378,12 +368,6 @@ namespace osu.Game.Overlays mod.ApplyToClock(track); } - private void currentTrackCompleted() => Schedule(() => - { - if (!current.Track.Looping && !beatmap.Disabled && beatmapSets.Any()) - next(); - }); - private ScheduledDelegate pendingBeatmapSwitch; private void updateDisplay(WorkingBeatmap beatmap, TransformDirection direction) @@ -447,10 +431,6 @@ namespace osu.Game.Overlays { base.PopOut(); - // This is here mostly as a performance fix. - // If the playlist is not hidden it will update children even when the music controller is hidden (due to AlwaysPresent). - playlist.Hide(); - this.FadeOut(transition_length, Easing.OutQuint); dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint); } @@ -548,5 +528,10 @@ namespace osu.Game.Overlays return base.OnDragEnd(e); } } + + /// + /// Play the next random or playlist track. + /// + public void NextTrack() => next(); } } diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index b5ee4b4f0c..a815480094 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -12,7 +13,6 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; -using DebugUtils = osu.Game.Utils.DebugUtils; namespace osu.Game.Overlays.Settings { @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Settings Text = game.Name, Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), }, - new BuildDisplay(game.Version, DebugUtils.IsDebug) + new BuildDisplay(game.Version, DebugUtils.IsDebugBuild) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 51ca9902d2..4ceb82d4cc 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -143,10 +143,10 @@ namespace osu.Game.Screens.Select.Carousel Origin = Anchor.Centre, FillMode = FillMode.Fill, }, - new FillFlowContainer + // Todo: This should be a fill flow, but has invalidation issues (see https://github.com/ppy/osu-framework/issues/223) + new Container { Depth = -1, - Direction = FillDirection.Horizontal, RelativeSizeAxes = Axes.Both, // This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle Shear = new Vector2(0.8f, 0), @@ -157,6 +157,7 @@ namespace osu.Game.Screens.Select.Carousel new Box { RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, Colour = Color4.Black, Width = 0.4f, }, @@ -164,20 +165,26 @@ namespace osu.Game.Screens.Select.Carousel new Box { RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, Colour = ColourInfo.GradientHorizontal(Color4.Black, new Color4(0f, 0f, 0f, 0.9f)), Width = 0.05f, + X = 0.4f, }, new Box { RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)), Width = 0.2f, + X = 0.45f, }, new Box { RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)), Width = 0.05f, + X = 0.65f, }, } }, diff --git a/osu.Game/Utils/DebugUtils.cs b/osu.Game/Utils/DebugUtils.cs deleted file mode 100644 index 9b1d355a83..0000000000 --- a/osu.Game/Utils/DebugUtils.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Utils -{ - public static class DebugUtils - { - public static bool IsDebug - { - get - { - // ReSharper disable once RedundantAssignment - bool isDebug = false; - // Debug.Assert conditions are only evaluated in debug mode - System.Diagnostics.Debug.Assert(isDebug = true); - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - return isDebug; - } - } - } -}