Move storyboard outro logic to DrawableStoryboard

This commit is contained in:
Christine Chen 2021-04-16 00:59:10 -04:00
parent 0e545e1ed9
commit b15838b220
10 changed files with 57 additions and 49 deletions

View File

@ -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)
{

View File

@ -48,8 +48,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
AllowPause = false,
AllowRestart = false,
AllowSkippingIntro = false,
AllowSkippingOutro = false,
AllowSkipping = false,
})
{
this.userIds = userIds;

View File

@ -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<bool> HasStoryboardEnded => drawableStoryboard?.HasStoryboardEnded;
}
}

View File

@ -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<bool> 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
}
}

View File

@ -74,8 +74,6 @@ namespace osu.Game.Screens.Play
private Bindable<bool> mouseWheelDisabled;
private Bindable<bool> storyboardEnabled;
private readonly Bindable<bool> storyboardReplacesBackground = new Bindable<bool>();
protected readonly Bindable<bool> LocalUserPlaying = new Bindable<bool>();
@ -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<bool>(OsuSetting.MouseDisableWheel);
storyboardEnabled = config.GetBindable<bool>(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<IApplicableToScoreProcessor>())
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;

View File

@ -21,13 +21,8 @@ namespace osu.Game.Screens.Play
public bool AllowRestart { get; set; } = true;
/// <summary>
/// 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.
/// </summary>
public bool AllowSkippingIntro { get; set; } = true;
/// <summary>
/// Whether the player should be allowed to skip the outro, advancing to the end of a storyboard.
/// </summary>
public bool AllowSkippingOutro { get; set; } = true;
public bool AllowSkipping { get; set; } = true;
}
}

View File

@ -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();
}
/// <summary>
/// Whether the storyboard has ended after the gameplay portion of the beatmap.
/// </summary>
public IBindable<bool> 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;
}
}
}

View File

@ -3,7 +3,7 @@
namespace osu.Game.Storyboards
{
public interface IHasDuration
public interface IStoryboardElementHasDuration
{
double EndTime { get; }
}

View File

@ -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.
/// </summary>
public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType<IHasDuration>()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime;
public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType<IStoryboardElementHasDuration>()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime;
/// <summary>
/// Depth of the currently front-most storyboard layer, excluding the overlay layer.

View File

@ -11,7 +11,7 @@ using JetBrains.Annotations;
namespace osu.Game.Storyboards
{
public class StoryboardSprite : IStoryboardElement, IHasDuration
public class StoryboardSprite : IStoryboardElement, IStoryboardElementHasDuration
{
private readonly List<CommandLoop> loops = new List<CommandLoop>();
private readonly List<CommandTrigger> triggers = new List<CommandTrigger>();