From ddaf28d7f641d02a94dc36f269e2873c9e971013 Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 14 Sep 2017 14:28:53 +0200 Subject: [PATCH 01/13] Integrate storyboards with gameplay. --- osu.Game/Beatmaps/Beatmap.cs | 15 ++++++++ osu.Game/Beatmaps/BeatmapInfo.cs | 1 + osu.Game/Screens/Play/Player.cs | 34 ++++++++++++++++--- .../Drawables/DrawableStoryboard.cs | 10 ++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 458c2304f2..23fc7ca9ea 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -46,6 +46,21 @@ namespace osu.Game.Beatmaps /// public Storyboard Storyboard = new Storyboard(); + /// + /// Whether this beatmap's Storyboard uses the background texture in its Background layer. + /// + public bool StoryboardUsesBackground + { + get + { + var backgroundPath = BeatmapInfo.BeatmapSet.Metadata.BackgroundFile?.ToLowerInvariant(); + if (backgroundPath == null) + return false; + + return Storyboard.GetLayer("Background").Elements.Any(e => e.Path.ToLowerInvariant() == backgroundPath); + } + } + /// /// Constructs a new beatmap. /// diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 0776669811..2dc4b44ed7 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -75,6 +75,7 @@ namespace osu.Game.Beatmaps public bool LetterboxInBreaks { get; set; } public bool WidescreenStoryboard { get; set; } + public float StoryboardAspect => WidescreenStoryboard ? 16 / 9f : 4 / 3f; // Editor // This bookmarks stuff is necessary because DB doesn't know how to store int[] diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 593abb7d26..d9e962a9b2 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -24,6 +24,8 @@ using osu.Game.Screens.Ranking; using osu.Framework.Audio.Sample; using osu.Game.Beatmaps; using osu.Game.Online.API; +using osu.Game.Storyboards.Drawables; +using OpenTK.Graphics; namespace osu.Game.Screens.Play { @@ -66,6 +68,9 @@ namespace osu.Game.Screens.Play #endregion + private DrawableStoryboard storyboard; + private bool storyboardUsesBackground; + private HUDOverlay hudOverlay; private FailOverlay failOverlay; @@ -145,6 +150,15 @@ namespace osu.Game.Screens.Play Children = new Drawable[] { + new Container + { + RelativeSizeAxes = Axes.Both, + Clock = offsetClock, + Children = new Drawable[] + { + storyboard = beatmap.Storyboard.CreateDrawable(), + } + }, pauseContainer = new PauseContainer { AudioClock = decoupledClock, @@ -196,6 +210,10 @@ namespace osu.Game.Screens.Play scoreProcessor = RulesetContainer.CreateScoreProcessor(); + storyboardUsesBackground = beatmap.StoryboardUsesBackground; + storyboard.Width = storyboard.Height * beatmap.BeatmapInfo.StoryboardAspect; + storyboard.Masking = true; + hudOverlay.BindProcessor(scoreProcessor); hudOverlay.BindRulesetContainer(RulesetContainer); @@ -266,12 +284,11 @@ namespace osu.Game.Screens.Play return; (Background as BackgroundScreenBeatmap)?.BlurTo(Vector2.Zero, 1500, Easing.OutQuint); - Background?.FadeTo(1 - (float)dimLevel, 1500, Easing.OutQuint); + + applyDim(); + dimLevel.ValueChanged += newDim => applyDim(); Content.Alpha = 0; - - dimLevel.ValueChanged += newDim => Background?.FadeTo(1 - (float)newDim, 800); - Content .ScaleTo(0.7f) .ScaleTo(1, 750, Easing.OutQuint) @@ -310,6 +327,15 @@ namespace osu.Game.Screens.Play return true; } + private void applyDim() + { + var opacity = 1 - (float)dimLevel; + storyboard.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); + storyboard.FadeTo(opacity == 0 ? 0 : 1); + + Background?.FadeTo(storyboardUsesBackground ? 0 : opacity, 800, Easing.OutQuint); + } + private void fadeOut() { const float fade_out_duration = 250; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index f88e5d118f..73fb942eb2 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -14,6 +14,9 @@ namespace osu.Game.Storyboards.Drawables { public Storyboard Storyboard { get; private set; } + private readonly Container content; + protected override Container Content => content; + protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480); public override bool HandleInput => false; @@ -39,6 +42,13 @@ namespace osu.Game.Storyboards.Drawables Size = new Vector2(640, 480); Anchor = Anchor.Centre; Origin = Anchor.Centre; + + AddInternal(content = new Container + { + Size = new Vector2(640, 480), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); } [BackgroundDependencyLoader] From cb8029af9ee2fa9d21994c659a55a0bff760f481 Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 14 Sep 2017 15:44:36 +0200 Subject: [PATCH 02/13] Add a setting to hide storyboards. --- osu.Game/Configuration/OsuConfigManager.cs | 3 +++ .../Sections/Graphics/DetailSettings.cs | 17 +++++++++++++++++ osu.Game/Screens/Play/Player.cs | 14 +++++++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 44a6af841c..713207170e 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -54,6 +54,8 @@ namespace osu.Game.Configuration // Graphics Set(OsuSetting.ShowFpsDisplay, false); + Set(OsuSetting.ShowStoryboard, true); + Set(OsuSetting.MenuParallax, true); Set(OsuSetting.SnakingInSliders, true); @@ -87,6 +89,7 @@ namespace osu.Game.Configuration GameplayCursorSize, AutoCursorSize, DimLevel, + ShowStoryboard, KeyOverlay, FloatingComments, PlaybackSpeed, diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index c068da8129..66b5dbfe06 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -1,10 +1,27 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Configuration; + namespace osu.Game.Overlays.Settings.Sections.Graphics { public class DetailSettings : SettingsSubsection { protected override string Header => "Detail Settings"; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + Children = new Drawable[] + { + new SettingsCheckbox + { + LabelText = "Storyboards", + Bindable = config.GetBindable(OsuSetting.ShowStoryboard) + }, + }; + } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d9e962a9b2..a7124dee63 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -61,6 +61,7 @@ namespace osu.Game.Screens.Play #region User Settings private Bindable dimLevel; + private Bindable showStoryboard; private Bindable mouseWheelDisabled; private Bindable userAudioOffset; @@ -82,6 +83,7 @@ namespace osu.Game.Screens.Play this.api = api; dimLevel = config.GetBindable(OsuSetting.DimLevel); + showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); @@ -213,6 +215,7 @@ namespace osu.Game.Screens.Play storyboardUsesBackground = beatmap.StoryboardUsesBackground; storyboard.Width = storyboard.Height * beatmap.BeatmapInfo.StoryboardAspect; storyboard.Masking = true; + storyboard.Alpha = showStoryboard ? 1 : 0; hudOverlay.BindProcessor(scoreProcessor); hudOverlay.BindRulesetContainer(RulesetContainer); @@ -285,8 +288,9 @@ namespace osu.Game.Screens.Play (Background as BackgroundScreenBeatmap)?.BlurTo(Vector2.Zero, 1500, Easing.OutQuint); - applyDim(); - dimLevel.ValueChanged += newDim => applyDim(); + dimLevel.ValueChanged += value => updateBackgroundElements(); + showStoryboard.ValueChanged += value => updateBackgroundElements(); + updateBackgroundElements(); Content.Alpha = 0; Content @@ -327,13 +331,13 @@ namespace osu.Game.Screens.Play return true; } - private void applyDim() + private void updateBackgroundElements() { var opacity = 1 - (float)dimLevel; storyboard.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); - storyboard.FadeTo(opacity == 0 ? 0 : 1); + storyboard.FadeTo(!showStoryboard || opacity == 0 ? 0 : 1, 800); - Background?.FadeTo(storyboardUsesBackground ? 0 : opacity, 800, Easing.OutQuint); + Background?.FadeTo(showStoryboard && storyboardUsesBackground ? 0 : opacity, 800, Easing.OutQuint); } private void fadeOut() From 7c3ce7e830c9783c89ac6c8fafb943a831e5b6fb Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 14 Sep 2017 15:58:55 +0200 Subject: [PATCH 03/13] Unbind events affecting the background after gameplay has ended. --- osu.Game/Screens/Play/Player.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a7124dee63..d0f0280c74 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -288,8 +288,8 @@ namespace osu.Game.Screens.Play (Background as BackgroundScreenBeatmap)?.BlurTo(Vector2.Zero, 1500, Easing.OutQuint); - dimLevel.ValueChanged += value => updateBackgroundElements(); - showStoryboard.ValueChanged += value => updateBackgroundElements(); + dimLevel.ValueChanged += dimLevel_ValueChanged; + showStoryboard.ValueChanged += showStoryboard_ValueChanged; updateBackgroundElements(); Content.Alpha = 0; @@ -331,6 +331,12 @@ namespace osu.Game.Screens.Play return true; } + private void dimLevel_ValueChanged(double newValue) + => updateBackgroundElements(); + + private void showStoryboard_ValueChanged(bool newValue) + => updateBackgroundElements(); + private void updateBackgroundElements() { var opacity = 1 - (float)dimLevel; @@ -342,6 +348,9 @@ namespace osu.Game.Screens.Play private void fadeOut() { + dimLevel.ValueChanged -= dimLevel_ValueChanged; + showStoryboard.ValueChanged -= showStoryboard_ValueChanged; + const float fade_out_duration = 250; RulesetContainer?.FadeOut(fade_out_duration); From c8cdf6787e6d029eb91d801c63ad05540e21393f Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 14 Sep 2017 16:26:18 +0200 Subject: [PATCH 04/13] Better property name. --- osu.Game/Beatmaps/Beatmap.cs | 4 ++-- osu.Game/Screens/Play/Player.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 23fc7ca9ea..44331d9679 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -47,9 +47,9 @@ namespace osu.Game.Beatmaps public Storyboard Storyboard = new Storyboard(); /// - /// Whether this beatmap's Storyboard uses the background texture in its Background layer. + /// Whether this beatmap's background should be hidden while its storyboard is being displayed. /// - public bool StoryboardUsesBackground + public bool StoryboardReplacesBackground { get { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d0f0280c74..7675ba0ee4 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -70,7 +70,7 @@ namespace osu.Game.Screens.Play #endregion private DrawableStoryboard storyboard; - private bool storyboardUsesBackground; + private bool storyboardReplacesBackground; private HUDOverlay hudOverlay; private FailOverlay failOverlay; @@ -212,7 +212,7 @@ namespace osu.Game.Screens.Play scoreProcessor = RulesetContainer.CreateScoreProcessor(); - storyboardUsesBackground = beatmap.StoryboardUsesBackground; + storyboardReplacesBackground = beatmap.StoryboardReplacesBackground; storyboard.Width = storyboard.Height * beatmap.BeatmapInfo.StoryboardAspect; storyboard.Masking = true; storyboard.Alpha = showStoryboard ? 1 : 0; @@ -341,9 +341,9 @@ namespace osu.Game.Screens.Play { var opacity = 1 - (float)dimLevel; storyboard.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); - storyboard.FadeTo(!showStoryboard || opacity == 0 ? 0 : 1, 800); + storyboard.FadeTo(!showStoryboard || opacity == 0 ? 0 : 1, 200); - Background?.FadeTo(showStoryboard && storyboardUsesBackground ? 0 : opacity, 800, Easing.OutQuint); + Background?.FadeTo(showStoryboard && storyboardReplacesBackground ? 0 : opacity, 800, Easing.OutQuint); } private void fadeOut() From 4a1576213923c7e663b1d8007c3bd174e0df1d39 Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 14 Sep 2017 16:50:10 +0200 Subject: [PATCH 05/13] Don't create drawables for hidden storyboards. --- osu.Game/Screens/Play/Player.cs | 34 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7675ba0ee4..8a82c14d2d 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -69,6 +69,7 @@ namespace osu.Game.Screens.Play #endregion + private Container storyboardContainer; private DrawableStoryboard storyboard; private bool storyboardReplacesBackground; @@ -152,14 +153,10 @@ namespace osu.Game.Screens.Play Children = new Drawable[] { - new Container + storyboardContainer = new Container { RelativeSizeAxes = Axes.Both, Clock = offsetClock, - Children = new Drawable[] - { - storyboard = beatmap.Storyboard.CreateDrawable(), - } }, pauseContainer = new PauseContainer { @@ -212,10 +209,8 @@ namespace osu.Game.Screens.Play scoreProcessor = RulesetContainer.CreateScoreProcessor(); - storyboardReplacesBackground = beatmap.StoryboardReplacesBackground; - storyboard.Width = storyboard.Height * beatmap.BeatmapInfo.StoryboardAspect; - storyboard.Masking = true; - storyboard.Alpha = showStoryboard ? 1 : 0; + if (showStoryboard) + initializeStoryboard(); hudOverlay.BindProcessor(scoreProcessor); hudOverlay.BindRulesetContainer(RulesetContainer); @@ -232,6 +227,17 @@ namespace osu.Game.Screens.Play scoreProcessor.Failed += onFail; } + private void initializeStoryboard() + { + var beatmap = Beatmap.Value.Beatmap; + + storyboardReplacesBackground = beatmap.StoryboardReplacesBackground; + + storyboardContainer.Add(storyboard = beatmap.Storyboard.CreateDrawable()); + storyboard.Width = storyboard.Height * beatmap.BeatmapInfo.StoryboardAspect; + storyboard.Masking = true; + } + public void Restart() { sampleRestart?.Play(); @@ -340,10 +346,14 @@ namespace osu.Game.Screens.Play private void updateBackgroundElements() { var opacity = 1 - (float)dimLevel; - storyboard.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); - storyboard.FadeTo(!showStoryboard || opacity == 0 ? 0 : 1, 200); - Background?.FadeTo(showStoryboard && storyboardReplacesBackground ? 0 : opacity, 800, Easing.OutQuint); + if (showStoryboard && storyboard == null) + initializeStoryboard(); + + storyboard?.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); + storyboard?.FadeTo(showStoryboard && opacity > 0 ? 1 : 0, 200); + + Background?.FadeTo(!showStoryboard || !storyboardReplacesBackground ? opacity : 0, 800, Easing.OutQuint); } private void fadeOut() From f5368505abc9ff8d6d1ca97e90d647dea87097b2 Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 14 Sep 2017 18:56:01 +0200 Subject: [PATCH 06/13] Load the storyboard asynchronously if it wasn't loaded with the beatmap. --- osu.Game/Screens/Play/Player.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 8a82c14d2d..1db83eab32 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -209,8 +209,9 @@ namespace osu.Game.Screens.Play scoreProcessor = RulesetContainer.CreateScoreProcessor(); + storyboardReplacesBackground = beatmap.StoryboardReplacesBackground; if (showStoryboard) - initializeStoryboard(); + initializeStoryboard(false); hudOverlay.BindProcessor(scoreProcessor); hudOverlay.BindRulesetContainer(RulesetContainer); @@ -227,15 +228,15 @@ namespace osu.Game.Screens.Play scoreProcessor.Failed += onFail; } - private void initializeStoryboard() + private void initializeStoryboard(bool asyncLoad) { var beatmap = Beatmap.Value.Beatmap; - storyboardReplacesBackground = beatmap.StoryboardReplacesBackground; - - storyboardContainer.Add(storyboard = beatmap.Storyboard.CreateDrawable()); + storyboard = beatmap.Storyboard.CreateDrawable(); storyboard.Width = storyboard.Height * beatmap.BeatmapInfo.StoryboardAspect; storyboard.Masking = true; + + storyboardContainer.Add(asyncLoad ? new AsyncLoadWrapper(storyboard) { RelativeSizeAxes = Axes.Both } : (Drawable)storyboard); } public void Restart() @@ -348,7 +349,7 @@ namespace osu.Game.Screens.Play var opacity = 1 - (float)dimLevel; if (showStoryboard && storyboard == null) - initializeStoryboard(); + initializeStoryboard(true); storyboard?.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); storyboard?.FadeTo(showStoryboard && opacity > 0 ? 1 : 0, 200); From 757a159516299df37b4016d0624afb46cbeb13bc Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 15 Sep 2017 11:23:37 +0200 Subject: [PATCH 07/13] Display a non-parallax background at the appropriate size when storyboards do not replace it. --- osu.Game/Beatmaps/Beatmap.cs | 2 +- osu.Game/Screens/Play/Player.cs | 14 +++++++++----- .../Drawables/DrawableStoryboard.cs | 18 ++++++++++++++++++ osu.Game/Storyboards/IStoryboardElement.cs | 2 ++ osu.Game/Storyboards/Storyboard.cs | 2 ++ osu.Game/Storyboards/StoryboardSample.cs | 2 ++ osu.Game/Storyboards/StoryboardSprite.cs | 2 ++ 7 files changed, 36 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 44331d9679..ea3aa3cdff 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -53,7 +53,7 @@ namespace osu.Game.Beatmaps { get { - var backgroundPath = BeatmapInfo.BeatmapSet.Metadata.BackgroundFile?.ToLowerInvariant(); + var backgroundPath = BeatmapInfo.BeatmapSet.Metadata?.BackgroundFile?.ToLowerInvariant(); if (backgroundPath == null) return false; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 1db83eab32..fd1eeaa395 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -71,7 +71,6 @@ namespace osu.Game.Screens.Play private Container storyboardContainer; private DrawableStoryboard storyboard; - private bool storyboardReplacesBackground; private HUDOverlay hudOverlay; private FailOverlay failOverlay; @@ -157,6 +156,7 @@ namespace osu.Game.Screens.Play { RelativeSizeAxes = Axes.Both, Clock = offsetClock, + Alpha = 0, }, pauseContainer = new PauseContainer { @@ -209,7 +209,6 @@ namespace osu.Game.Screens.Play scoreProcessor = RulesetContainer.CreateScoreProcessor(); - storyboardReplacesBackground = beatmap.StoryboardReplacesBackground; if (showStoryboard) initializeStoryboard(false); @@ -236,6 +235,8 @@ namespace osu.Game.Screens.Play storyboard.Width = storyboard.Height * beatmap.BeatmapInfo.StoryboardAspect; storyboard.Masking = true; + if (!beatmap.StoryboardReplacesBackground) + storyboard.BackgroundTexture = Beatmap.Value.Background; storyboardContainer.Add(asyncLoad ? new AsyncLoadWrapper(storyboard) { RelativeSizeAxes = Axes.Both } : (Drawable)storyboard); } @@ -351,10 +352,13 @@ namespace osu.Game.Screens.Play if (showStoryboard && storyboard == null) initializeStoryboard(true); - storyboard?.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); - storyboard?.FadeTo(showStoryboard && opacity > 0 ? 1 : 0, 200); + var beatmap = Beatmap.Value; + var storyboardVisible = showStoryboard && beatmap.Beatmap.Storyboard.HasDrawable; - Background?.FadeTo(!showStoryboard || !storyboardReplacesBackground ? opacity : 0, 800, Easing.OutQuint); + storyboardContainer.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); + storyboardContainer.FadeTo(storyboardVisible && opacity > 0 ? 1 : 0); + + Background?.FadeTo(!storyboardVisible || beatmap.Background == null ? opacity : 0, 800, Easing.OutQuint); } private void fadeOut() diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 73fb942eb2..5df88b342f 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -5,6 +5,7 @@ using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.IO; @@ -14,6 +15,13 @@ namespace osu.Game.Storyboards.Drawables { public Storyboard Storyboard { get; private set; } + private readonly Background background; + public Texture BackgroundTexture + { + get { return background.Texture; } + set { background.Texture = value; } + } + private readonly Container content; protected override Container Content => content; @@ -43,6 +51,11 @@ namespace osu.Game.Storyboards.Drawables Anchor = Anchor.Centre; Origin = Anchor.Centre; + AddInternal(background = new Background + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); AddInternal(content = new Container { Size = new Vector2(640, 480), @@ -65,5 +78,10 @@ namespace osu.Game.Storyboards.Drawables foreach (var layer in Children) layer.Enabled = passing ? layer.Layer.EnabledWhenPassing : layer.Layer.EnabledWhenFailing; } + + private class Background : Sprite + { + protected override Vector2 DrawScale => Texture != null ? new Vector2(Parent.DrawHeight / Texture.DisplayHeight) : base.DrawScale; + } } } diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index d5fc86b0f7..74b6a8d8bc 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -8,6 +8,8 @@ namespace osu.Game.Storyboards public interface IStoryboardElement { string Path { get; } + bool IsDrawable { get; } + Drawable CreateDrawable(); } } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 111cdd5d41..2e7188f28c 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -12,6 +12,8 @@ namespace osu.Game.Storyboards private readonly Dictionary layers = new Dictionary(); public IEnumerable Layers => layers.Values; + public bool HasDrawable => Layers.Any(l => l.Elements.Any(e => e.IsDrawable)); + public Storyboard() { layers.Add("Background", new StoryboardLayer("Background", 3)); diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index bcf6a4329d..8e769e7fcf 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -8,6 +8,8 @@ namespace osu.Game.Storyboards public class StoryboardSample : IStoryboardElement { public string Path { get; set; } + public bool IsDrawable => false; + public double Time; public float Volume; diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 598167d720..349a59dee0 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -16,6 +16,8 @@ namespace osu.Game.Storyboards private readonly List triggers = new List(); public string Path { get; set; } + public bool IsDrawable => HasCommands; + public Anchor Origin; public Vector2 InitialPosition; From 291486a4d1750298656ecca2f484cfbdaaeda2dd Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 15 Sep 2017 13:35:41 +0200 Subject: [PATCH 08/13] Only create drawables for storyboard elements that will be visible. --- .../Drawables/DrawableStoryboardAnimation.cs | 10 ++-------- .../Storyboards/Drawables/DrawableStoryboardLayer.cs | 5 ++--- .../Storyboards/Drawables/DrawableStoryboardSprite.cs | 10 ++-------- osu.Game/Storyboards/StoryboardSample.cs | 5 ++++- 4 files changed, 10 insertions(+), 20 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index d8b7d05ee9..9757756316 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -14,9 +14,6 @@ namespace osu.Game.Storyboards.Drawables { public StoryboardAnimation Animation { get; private set; } - protected override bool ShouldBeAlive => Animation.HasCommands && base.ShouldBeAlive; - public override bool RemoveWhenNotAlive => !Animation.HasCommands || base.RemoveWhenNotAlive; - public bool FlipH { get; set; } public bool FlipV { get; set; } @@ -59,11 +56,8 @@ namespace osu.Game.Storyboards.Drawables Position = animation.InitialPosition; Repeat = animation.LoopType == AnimationLoopType.LoopForever; - if (animation.HasCommands) - { - LifetimeStart = animation.StartTime; - LifetimeEnd = animation.EndTime; - } + LifetimeStart = animation.StartTime; + LifetimeEnd = animation.EndTime; } [BackgroundDependencyLoader] diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 2b5db5b6fa..737704f6d0 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs @@ -28,9 +28,8 @@ namespace osu.Game.Storyboards.Drawables { foreach (var element in Layer.Elements) { - var drawable = element.CreateDrawable(); - if (drawable != null) - Add(drawable); + if (element.IsDrawable) + Add(element.CreateDrawable()); } } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 4b491fa008..9153b3e514 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -14,9 +14,6 @@ namespace osu.Game.Storyboards.Drawables { public StoryboardSprite Sprite { get; private set; } - protected override bool ShouldBeAlive => Sprite.HasCommands && base.ShouldBeAlive; - public override bool RemoveWhenNotAlive => !Sprite.HasCommands || base.RemoveWhenNotAlive; - public bool FlipH { get; set; } public bool FlipV { get; set; } @@ -58,11 +55,8 @@ namespace osu.Game.Storyboards.Drawables Origin = sprite.Origin; Position = sprite.InitialPosition; - if (sprite.HasCommands) - { - LifetimeStart = sprite.StartTime; - LifetimeEnd = sprite.EndTime; - } + LifetimeStart = sprite.StartTime; + LifetimeEnd = sprite.EndTime; } [BackgroundDependencyLoader] diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index 8e769e7fcf..e7a157c2f4 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; +using System; namespace osu.Game.Storyboards { @@ -21,6 +22,8 @@ namespace osu.Game.Storyboards } public Drawable CreateDrawable() - => null; + { + throw new InvalidOperationException(); + } } } From d9bde5ad5a0ff9bb509e1233df293c1492da1b65 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 15 Sep 2017 14:15:26 +0200 Subject: [PATCH 09/13] Fix TestCaseStoryboard Restart button. --- osu.Desktop.Tests/Visual/TestCaseStoryboard.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs b/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs index 878198e8d2..e236da2235 100644 --- a/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs +++ b/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs @@ -80,11 +80,15 @@ namespace osu.Desktop.Tests.Visual storyboardContainer.Remove(storyboard); var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true }; - decoupledClock.ChangeSource(working.Track); storyboardContainer.Clock = decoupledClock; - storyboardContainer.Add(storyboard = working.Beatmap.Storyboard.CreateDrawable()); + storyboard = working.Beatmap.Storyboard.CreateDrawable(); storyboard.Passing = false; + if (!working.Beatmap.StoryboardReplacesBackground) + storyboard.BackgroundTexture = working.Background; + + storyboardContainer.Add(storyboard); + decoupledClock.ChangeSource(working.Track); } } } From 5f6b300a3a86266426e183d256b9c4b93f1fd256 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 15 Sep 2017 15:12:16 +0200 Subject: [PATCH 10/13] Fix visual test crash when BeatmapInfo doesn't have a BeatmapSet. --- osu.Game/Beatmaps/Beatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index ea3aa3cdff..84db2f9943 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -53,7 +53,7 @@ namespace osu.Game.Beatmaps { get { - var backgroundPath = BeatmapInfo.BeatmapSet.Metadata?.BackgroundFile?.ToLowerInvariant(); + var backgroundPath = BeatmapInfo.BeatmapSet?.Metadata?.BackgroundFile?.ToLowerInvariant(); if (backgroundPath == null) return false; From 2201fc745e4514cc9eff3104aa8f8e16e0585e86 Mon Sep 17 00:00:00 2001 From: Damnae Date: Sat, 16 Sep 2017 13:15:16 +0200 Subject: [PATCH 11/13] Fix storyboard loops start time when none of their commands start at 0. --- osu.Game/Storyboards/CommandLoop.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index 02b5eb0122..0d8b57e46c 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -10,8 +10,8 @@ namespace osu.Game.Storyboards public double LoopStartTime; public int LoopCount; - public override double StartTime => LoopStartTime; - public override double EndTime => LoopStartTime + CommandsDuration * LoopCount; + public override double StartTime => LoopStartTime + CommandsStartTime; + public override double EndTime => StartTime + CommandsDuration * LoopCount; public CommandLoop(double startTime, int loopCount) { From 09968671129fd5bf97d309744571a68ace8af67f Mon Sep 17 00:00:00 2001 From: Damnae Date: Mon, 25 Sep 2017 10:40:22 +0200 Subject: [PATCH 12/13] Move StoryboardReplacesBackground and StoryboardAspect properties to Storyboard. --- osu.Game/Beatmaps/Beatmap.cs | 15 --------------- osu.Game/Beatmaps/BeatmapInfo.cs | 1 - osu.Game/Screens/Play/Player.cs | 4 ++-- osu.Game/Storyboards/Storyboard.cs | 16 ++++++++++++++++ osu.Game/Tests/Visual/TestCaseStoryboard.cs | 4 +++- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 84db2f9943..458c2304f2 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -46,21 +46,6 @@ namespace osu.Game.Beatmaps /// public Storyboard Storyboard = new Storyboard(); - /// - /// Whether this beatmap's background should be hidden while its storyboard is being displayed. - /// - public bool StoryboardReplacesBackground - { - get - { - var backgroundPath = BeatmapInfo.BeatmapSet?.Metadata?.BackgroundFile?.ToLowerInvariant(); - if (backgroundPath == null) - return false; - - return Storyboard.GetLayer("Background").Elements.Any(e => e.Path.ToLowerInvariant() == backgroundPath); - } - } - /// /// Constructs a new beatmap. /// diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 2dc4b44ed7..0776669811 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -75,7 +75,6 @@ namespace osu.Game.Beatmaps public bool LetterboxInBreaks { get; set; } public bool WidescreenStoryboard { get; set; } - public float StoryboardAspect => WidescreenStoryboard ? 16 / 9f : 4 / 3f; // Editor // This bookmarks stuff is necessary because DB doesn't know how to store int[] diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fd1eeaa395..75a5dd8f7d 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -232,10 +232,10 @@ namespace osu.Game.Screens.Play var beatmap = Beatmap.Value.Beatmap; storyboard = beatmap.Storyboard.CreateDrawable(); - storyboard.Width = storyboard.Height * beatmap.BeatmapInfo.StoryboardAspect; + storyboard.Width = storyboard.Height * beatmap.Storyboard.AspectRatio(beatmap.BeatmapInfo); storyboard.Masking = true; - if (!beatmap.StoryboardReplacesBackground) + if (!beatmap.Storyboard.ReplacesBackground(beatmap.BeatmapInfo)) storyboard.BackgroundTexture = Beatmap.Value.Background; storyboardContainer.Add(asyncLoad ? new AsyncLoadWrapper(storyboard) { RelativeSizeAxes = Axes.Both } : (Drawable)storyboard); } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 2e7188f28c..f74074e977 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps; using osu.Game.Storyboards.Drawables; using System.Collections.Generic; using System.Linq; @@ -31,6 +32,21 @@ namespace osu.Game.Storyboards return layer; } + /// + /// Whether the beatmap's background should be hidden while this storyboard is being displayed. + /// + public bool ReplacesBackground(BeatmapInfo beatmapInfo) + { + var backgroundPath = beatmapInfo.BeatmapSet?.Metadata?.BackgroundFile?.ToLowerInvariant(); + if (backgroundPath == null) + return false; + + return GetLayer("Background").Elements.Any(e => e.Path.ToLowerInvariant() == backgroundPath); + } + + public float AspectRatio(BeatmapInfo beatmapInfo) + => beatmapInfo.WidescreenStoryboard ? 16 / 9f : 4 / 3f; + public DrawableStoryboard CreateDrawable() => new DrawableStoryboard(this); } diff --git a/osu.Game/Tests/Visual/TestCaseStoryboard.cs b/osu.Game/Tests/Visual/TestCaseStoryboard.cs index c9601ffefc..75e23db475 100644 --- a/osu.Game/Tests/Visual/TestCaseStoryboard.cs +++ b/osu.Game/Tests/Visual/TestCaseStoryboard.cs @@ -83,7 +83,9 @@ namespace osu.Game.Tests.Visual storyboard = working.Beatmap.Storyboard.CreateDrawable(); storyboard.Passing = false; - if (!working.Beatmap.StoryboardReplacesBackground) + + var beatmap = working.Beatmap; + if (!beatmap.Storyboard.ReplacesBackground(beatmap.BeatmapInfo)) storyboard.BackgroundTexture = working.Background; storyboardContainer.Add(storyboard); From 2d4616fd43cb22ac7d6ae5d704651347238b017f Mon Sep 17 00:00:00 2001 From: Damnae Date: Mon, 25 Sep 2017 11:03:57 +0200 Subject: [PATCH 13/13] Apply beatmap settings when creating the DrawableStoryboard. --- osu.Game/Screens/Play/Player.cs | 5 +---- osu.Game/Storyboards/Storyboard.cs | 14 ++++++++++++-- osu.Game/Tests/Visual/TestCaseStoryboard.cs | 6 +----- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 75a5dd8f7d..e120c7f193 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -231,12 +231,9 @@ namespace osu.Game.Screens.Play { var beatmap = Beatmap.Value.Beatmap; - storyboard = beatmap.Storyboard.CreateDrawable(); - storyboard.Width = storyboard.Height * beatmap.Storyboard.AspectRatio(beatmap.BeatmapInfo); + storyboard = beatmap.Storyboard.CreateDrawable(Beatmap.Value); storyboard.Masking = true; - if (!beatmap.Storyboard.ReplacesBackground(beatmap.BeatmapInfo)) - storyboard.BackgroundTexture = Beatmap.Value.Background; storyboardContainer.Add(asyncLoad ? new AsyncLoadWrapper(storyboard) { RelativeSizeAxes = Axes.Both } : (Drawable)storyboard); } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index f74074e977..59cbe74650 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -47,7 +47,17 @@ namespace osu.Game.Storyboards public float AspectRatio(BeatmapInfo beatmapInfo) => beatmapInfo.WidescreenStoryboard ? 16 / 9f : 4 / 3f; - public DrawableStoryboard CreateDrawable() - => new DrawableStoryboard(this); + public DrawableStoryboard CreateDrawable(WorkingBeatmap working = null) + { + var drawable = new DrawableStoryboard(this); + if (working != null) + { + var beatmapInfo = working.Beatmap.BeatmapInfo; + drawable.Width = drawable.Height * AspectRatio(beatmapInfo); + if (!ReplacesBackground(beatmapInfo)) + drawable.BackgroundTexture = working.Background; + } + return drawable; + } } } diff --git a/osu.Game/Tests/Visual/TestCaseStoryboard.cs b/osu.Game/Tests/Visual/TestCaseStoryboard.cs index 75e23db475..c6ef3f4ecf 100644 --- a/osu.Game/Tests/Visual/TestCaseStoryboard.cs +++ b/osu.Game/Tests/Visual/TestCaseStoryboard.cs @@ -81,13 +81,9 @@ namespace osu.Game.Tests.Visual var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true }; storyboardContainer.Clock = decoupledClock; - storyboard = working.Beatmap.Storyboard.CreateDrawable(); + storyboard = working.Beatmap.Storyboard.CreateDrawable(beatmapBacking); storyboard.Passing = false; - var beatmap = working.Beatmap; - if (!beatmap.Storyboard.ReplacesBackground(beatmap.BeatmapInfo)) - storyboard.BackgroundTexture = working.Background; - storyboardContainer.Add(storyboard); decoupledClock.ChangeSource(working.Track); }