From b15838b22027746fd9174e5fb72e10ade6a68cd2 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Fri, 16 Apr 2021 00:59:10 -0400 Subject: [PATCH] Move storyboard outro logic to DrawableStoryboard --- .../Gameplay/TestSceneStoryboardWithOutro.cs | 17 +++++++++++-- .../Multiplayer/MultiplayerPlayer.cs | 3 +-- osu.Game/Screens/Play/DimmableStoryboard.cs | 3 +++ .../Screens/Play/GameplayClockContainer.cs | 20 --------------- osu.Game/Screens/Play/Player.cs | 25 ++++++++----------- osu.Game/Screens/Play/PlayerConfiguration.cs | 9 ++----- .../Drawables/DrawableStoryboard.cs | 23 +++++++++++++++++ ...on.cs => IStoryboardElementHasDuration.cs} | 2 +- osu.Game/Storyboards/Storyboard.cs | 2 +- osu.Game/Storyboards/StoryboardSprite.cs | 2 +- 10 files changed, 57 insertions(+), 49 deletions(-) rename osu.Game/Storyboards/{IHasDuration.cs => IStoryboardElementHasDuration.cs} (81%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 1c8b33bb09..27d203d5d6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -6,12 +6,14 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Storyboards; using osuTK; @@ -36,6 +38,16 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard.GetLayer("Background").Add(sprite); } + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + AddStep("ignore user settings", () => + { + Player.DimmableStoryboard.IgnoreUserSettings.Value = true; + }); + } + [Test] public void TestStoryboardSkipOutro() { @@ -50,8 +62,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); AddUntilStep("storyboard ends", () => Player.HUDOverlay.Progress.ReferenceClock.CurrentTime >= storyboard_duration); - AddWaitStep("wait for score", 10); - AddAssert("score shown", () => Player.IsScoreShown); + AddUntilStep("wait for score shown", () => Player.IsScoreShown); } [Test] @@ -85,6 +96,8 @@ namespace osu.Game.Tests.Visual.Gameplay public bool IsScoreShown => !this.IsCurrentScreen() && this.GetChildScreen() is ResultsScreen; + public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; + public OutroPlayer() : base(false) { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index b4e8c13e83..ae2042fbe8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -48,8 +48,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { AllowPause = false, AllowRestart = false, - AllowSkippingIntro = false, - AllowSkippingOutro = false, + AllowSkipping = false, }) { this.userIds = userIds; diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 58eb95b7c6..bebde1b15b 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Containers; using osu.Game.Storyboards; @@ -61,5 +62,7 @@ namespace osu.Game.Screens.Play Add(storyboard); OverlayLayerContainer.Add(storyboard.OverlayLayer.CreateProxy()); } + + public IBindable HasStoryboardEnded => drawableStoryboard?.HasStoryboardEnded; } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index fc45d661cf..95419c0b35 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -240,8 +240,6 @@ namespace osu.Game.Screens.Play userOffsetClock.ProcessFrame(); } - updateHasStoryboardEnded(); - base.Update(); } @@ -303,23 +301,5 @@ namespace osu.Game.Screens.Play { } } - - # region Storyboard outro logic - - public IBindable HasStoryboardEnded => hasStoryboardEnded; - - public bool HasTimeLeftInStoryboard => GameplayClock.CurrentTime <= StoryboardEndTime; - - private readonly BindableBool hasStoryboardEnded = new BindableBool(true); - - private void updateHasStoryboardEnded() - { - if (StoryboardEndTime == 0) - return; - - hasStoryboardEnded.Value = GameplayClock.CurrentTime >= StoryboardEndTime; - } - - # endregion } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 14ba9e7e02..81d2621647 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -74,8 +74,6 @@ namespace osu.Game.Screens.Play private Bindable mouseWheelDisabled; - private Bindable storyboardEnabled; - private readonly Bindable storyboardReplacesBackground = new Bindable(); protected readonly Bindable LocalUserPlaying = new Bindable(); @@ -106,7 +104,7 @@ namespace osu.Game.Screens.Play private BreakTracker breakTracker; - private SkipOverlay skipOverlay; + private SkipOverlay skipIntroOverlay; private SkipOverlay skipOutroOverlay; @@ -194,8 +192,6 @@ namespace osu.Game.Screens.Play mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); - storyboardEnabled = config.GetBindable(OsuSetting.ShowStoryboard); - if (game != null) gameActive.BindTo(game.IsActive); @@ -250,7 +246,7 @@ namespace osu.Game.Screens.Play HUDOverlay.ShowHud.Value = false; HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); - skipOverlay.Hide(); + skipIntroOverlay.Hide(); } DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => @@ -292,7 +288,8 @@ namespace osu.Game.Screens.Play HealthProcessor.Failed += onFail; // Keep track of whether the storyboard ended after the playable portion - GameplayClockContainer.HasStoryboardEnded.ValueChanged += updateCompletionState; + if (DimmableStoryboard.HasStoryboardEnded != null) + DimmableStoryboard.HasStoryboardEnded.ValueChanged += updateCompletionState; foreach (var mod in Mods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); @@ -365,7 +362,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre }, - skipOverlay = new SkipOverlay(DrawableRuleset.GameplayStartTime) + skipIntroOverlay = new SkipOverlay(DrawableRuleset.GameplayStartTime) { RequestSkip = performUserRequestedSkip }, @@ -399,11 +396,8 @@ namespace osu.Game.Screens.Play } }; - if (!Configuration.AllowSkippingIntro) - skipOverlay.Expire(); - - if (!Configuration.AllowSkippingOutro) - skipOutroOverlay.Expire(); + if (!Configuration.AllowSkipping) + skipIntroOverlay.Expire(); if (Configuration.AllowRestart) { @@ -637,8 +631,9 @@ namespace osu.Game.Screens.Play return score.ScoreInfo; }); - // show skip overlay if storyboard is enabled and has an outro - if (storyboardEnabled.Value && GameplayClockContainer.HasTimeLeftInStoryboard) + var storyboardHasOutro = DimmableStoryboard.ContentDisplayed && (!DimmableStoryboard.HasStoryboardEnded?.Value ?? false); + + if (storyboardHasOutro) { skipOutroOverlay.Show(); completionProgressDelegate = null; diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index ad29563d54..18ee73374f 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -21,13 +21,8 @@ namespace osu.Game.Screens.Play public bool AllowRestart { get; set; } = true; /// - /// Whether the player should be allowed to skip the intro, advancing to the start of gameplay. + /// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard. /// - public bool AllowSkippingIntro { get; set; } = true; - - /// - /// Whether the player should be allowed to skip the outro, advancing to the end of a storyboard. - /// - public bool AllowSkippingOutro { get; set; } = true; + public bool AllowSkipping { get; set; } = true; } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index af4615c895..08c2bf1b4a 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using osuTK; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; @@ -82,5 +83,27 @@ namespace osu.Game.Storyboards.Drawables foreach (var layer in Children) layer.Enabled = passing ? layer.Layer.VisibleWhenPassing : layer.Layer.VisibleWhenFailing; } + + protected override void Update() + { + base.Update(); + updateHasStoryboardEnded(); + } + + /// + /// Whether the storyboard has ended after the gameplay portion of the beatmap. + /// + public IBindable HasStoryboardEnded => hasStoryboardEnded; + + private readonly BindableBool hasStoryboardEnded = new BindableBool(true); + + private void updateHasStoryboardEnded() + { + if (Storyboard.LatestEventTime == null) + return; + + var time = Clock.CurrentTime; + hasStoryboardEnded.Value = time >= Storyboard.LatestEventTime; + } } } diff --git a/osu.Game/Storyboards/IHasDuration.cs b/osu.Game/Storyboards/IStoryboardElementHasDuration.cs similarity index 81% rename from osu.Game/Storyboards/IHasDuration.cs rename to osu.Game/Storyboards/IStoryboardElementHasDuration.cs index 98f75b8ee2..e6ee373812 100644 --- a/osu.Game/Storyboards/IHasDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementHasDuration.cs @@ -3,7 +3,7 @@ namespace osu.Game.Storyboards { - public interface IHasDuration + public interface IStoryboardElementHasDuration { double EndTime { get; } } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 669f6ccc43..4fa64b7c34 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -40,7 +40,7 @@ namespace osu.Game.Storyboards /// Across all layers, find the latest point in time that a storyboard element ends at. /// Will return null if there are no elements. /// - public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; + public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; /// /// Depth of the currently front-most storyboard layer, excluding the overlay layer. diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 8f2c1e9e0c..51bdce3321 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -11,7 +11,7 @@ using JetBrains.Annotations; namespace osu.Game.Storyboards { - public class StoryboardSprite : IStoryboardElement, IHasDuration + public class StoryboardSprite : IStoryboardElement, IStoryboardElementHasDuration { private readonly List loops = new List(); private readonly List triggers = new List();