From ddaf28d7f641d02a94dc36f269e2873c9e971013 Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 14 Sep 2017 14:28:53 +0200 Subject: [PATCH 01/53] 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/53] 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/53] 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/53] 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/53] 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/53] 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/53] 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/53] 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/53] 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/53] 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/53] 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 10efdffe49f449f3a7e2c522a49c029b73e556a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Sep 2017 15:33:15 +0900 Subject: [PATCH 12/53] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index e4101103d7..eef7736254 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e4101103d744edc3c8c2abd4a715962bc2fb064e +Subproject commit eef77362549a7da60d1a7c27edca0f105ef0f280 From 67d3861226407269bc2a91f384f932b93907b1c4 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 19 Sep 2017 23:09:08 +0900 Subject: [PATCH 13/53] Initial implementation of the EditorTimingTimeline in TestCaseEditorTimingTimeline Will probably rename this to MiniTimeline or something... But the basic structure is there plus most of functionality minus keyboard input. --- osu-framework | 2 +- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- .../Visual/TestCaseEditorTimingTimeline.cs | 371 ++++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 4 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs diff --git a/osu-framework b/osu-framework index eef7736254..cdb031c3a8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit eef77362549a7da60d1a7c27edca0f105ef0f280 +Subproject commit cdb031c3a8ef693cd71458c5e19c68127ab72938 diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 0776669811..e031f25fa2 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -84,7 +84,7 @@ namespace osu.Game.Beatmaps [JsonIgnore] public int[] Bookmarks { - get { return StoredBookmarks.Split(',').Select(int.Parse).ToArray(); } + get { return StoredBookmarks?.Split(',').Select(int.Parse).ToArray() ?? new int[0]; } set { StoredBookmarks = string.Join(",", value); } } diff --git a/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs new file mode 100644 index 0000000000..da6a326b2e --- /dev/null +++ b/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs @@ -0,0 +1,371 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Framework.Lists; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Timing; +using osu.Game.Graphics; + +namespace osu.Game.Tests.Visual +{ + internal class TestCaseEditorTimingTimeline : OsuTestCase + { + public TestCaseEditorTimingTimeline() + { + Add(new TimingTimeline + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500, 50) + }); + } + + private class TimingTimeline : CompositeDrawable + { + private const float corner_radius = 5; + private const float contents_padding = 15; + private const float marker_bar_width = 2; + + private readonly Drawable background; + + private readonly Container markerContainer; + + private readonly Drawable timelineBar; + private readonly Drawable marker; + + private readonly Bindable beatmap = new Bindable(); + + public TimingTimeline() + { + Masking = true; + CornerRadius = 5; + + InternalChildren = new Drawable[] + { + background = new Box { RelativeSizeAxes = Axes.Both }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, + Children = new Drawable[] + { + markerContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Child = marker = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new Triangle + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + Scale = new Vector2(1, -1), + Size = new Vector2(10, 5), + }, + new Triangle + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(10, 5) + }, + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = 2, + EdgeSmoothness = new Vector2(1, 0) + } + } + } + }, + new ControlPointTimeline + { + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, + new BookmarkTimeline + { + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, + timelineBar = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Circle + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Size = new Vector2(5) + }, + new Box + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + Height = 1, + EdgeSmoothness = new Vector2(0, 1), + }, + new Circle + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, + Size = new Vector2(5) + }, + } + }, + new BreakTimeline + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.25f + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame, OsuColour colours) + { + background.Colour = colours.Gray1; + marker.Colour = colours.Red; + timelineBar.Colour = colours.Gray5; + + beatmap.BindTo(osuGame.Beatmap); + + markerContainer.RelativeChildSize = new Vector2((float)beatmap.Value.Track.Length, 1); + } + + protected override bool OnDragStart(InputState state) => true; + + protected override bool OnDrag(InputState state) + { + seekToPosition(state.Mouse.NativeState.Position); + return true; + } + + protected override bool OnDragEnd(InputState state) => true; + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + seekToPosition(state.Mouse.NativeState.Position); + return true; + } + + private void seekToPosition(Vector2 screenPosition) + { + float markerPos = MathHelper.Clamp(markerContainer.ToLocalSpace(screenPosition).X, 0, markerContainer.DrawWidth); + seekTo(markerPos / markerContainer.DrawWidth * beatmap.Value.Track.Length); + } + + private void seekTo(double time) => beatmap.Value.Track.Seek(time); + + protected override void Update() + { + base.Update(); + + marker.X = (float)beatmap.Value.Track.CurrentTime; + } + + private class ControlPointTimeline : Timeline + { + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame, OsuColour colours) + { + var beatmap = osuGame.Beatmap.Value; + if (beatmap == null) + return; + + ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; + + cpi.TimingPoints.ForEach(addTimingPoint); + + // Consider all non-timing points as the same type + cpi.SoundPoints.Select(c => (ControlPoint)c) + .Concat(cpi.EffectPoints) + .Concat(cpi.DifficultyPoints) + .Distinct() + // Non-timing points should not be added where there are timing points + .Where(c => cpi.TimingPointAt(c.Time).Time != c.Time) + .ForEach(addNonTimingPoint); + } + + private void addTimingPoint(ControlPoint controlPoint) => Add(new TimingPointVisualisation(controlPoint)); + private void addNonTimingPoint(ControlPoint controlPoint) => Add(new NonTimingPointVisualisation(controlPoint)); + + private class TimingPointVisualisation : ControlPointVisualisation + { + public TimingPointVisualisation(ControlPoint controlPoint) + : base(controlPoint) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.YellowDark; + } + + private class NonTimingPointVisualisation : ControlPointVisualisation + { + public NonTimingPointVisualisation(ControlPoint controlPoint) + : base(controlPoint) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Green; + } + + private abstract class ControlPointVisualisation : PointVisualisation + { + public readonly ControlPoint ControlPoint; + + public ControlPointVisualisation(ControlPoint controlPoint) + : base(controlPoint.Time) + { + ControlPoint = controlPoint; + } + } + } + + private class BookmarkTimeline : Timeline + { + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame) + { + var beatmap = osuGame.Beatmap.Value; + if (beatmap == null) + return; + + foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks) + Add(new BookmarkVisualisation(bookmark)); + } + + private class BookmarkVisualisation : PointVisualisation + { + public BookmarkVisualisation(double startTime) + : base(startTime) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Blue; + } + } + + private class BreakTimeline : Timeline + { + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame) + { + var beatmap = osuGame.Beatmap.Value; + if (beatmap == null) + return; + + foreach (var breakPeriod in beatmap.Beatmap.Breaks) + Add(new BreakVisualisation(breakPeriod)); + } + + private class BreakVisualisation : DurationVisualisation + { + public BreakVisualisation(BreakPeriod breakPeriod) + : base(breakPeriod.StartTime, breakPeriod.EndTime) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Yellow; + } + } + + private abstract class Timeline : CompositeDrawable + { + private readonly Container timeline; + + public Timeline() + { + AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame) + { + var beatmap = osuGame.Beatmap.Value; + if (beatmap == null) + return; + + timeline.RelativeChildSize = new Vector2((float)beatmap.Track.Length, 1); + } + + protected void Add(PointVisualisation visualisation) => timeline.Add(visualisation); + + protected void Add(DurationVisualisation visualisation) => timeline.Add(visualisation); + } + + private class PointVisualisation : Box + { + public readonly double StartTime; + + public PointVisualisation(double startTime) + { + StartTime = startTime; + + Origin = Anchor.TopCentre; + + RelativeSizeAxes = Axes.Y; + Width = 1; + EdgeSmoothness = new Vector2(1, 0); + + RelativePositionAxes = Axes.X; + X = (float)startTime; + } + } + + private class DurationVisualisation : Container + { + public readonly double StartTime; + public readonly double EndTIme; + + public DurationVisualisation(double startTime, double endTime) + { + StartTime = startTime; + EndTIme = endTime; + + Masking = true; + CornerRadius = corner_radius; + + RelativePositionAxes = Axes.X; + RelativeSizeAxes = Axes.Both; + X = (float)startTime; + Width = (float)(endTime - startTime); + + AddInternal(new Box { RelativeSizeAxes = Axes.Both }); + } + } + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2d286fe1b8..3ca7f393f1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -733,6 +733,7 @@ + From 01c3818ea050d1e93fdf743732c296a0fc520b17 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 15:40:27 +0900 Subject: [PATCH 14/53] Make EditorTimingTimeline support beatmap changes --- .../Visual/TestCaseEditorTimingTimeline.cs | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs index da6a326b2e..b6df81148e 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.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 System; using System.Collections.Generic; using System.Linq; using OpenTK; @@ -13,6 +14,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Lists; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Timing; @@ -158,7 +160,8 @@ namespace osu.Game.Tests.Visual beatmap.BindTo(osuGame.Beatmap); - markerContainer.RelativeChildSize = new Vector2((float)beatmap.Value.Track.Length, 1); + markerContainer.RelativeChildSize = new Vector2((float)Math.Max(1, beatmap.Value.Track.Length), 1); + beatmap.ValueChanged += b => markerContainer.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); } protected override bool OnDragStart(InputState state) => true; @@ -194,13 +197,8 @@ namespace osu.Game.Tests.Visual private class ControlPointTimeline : Timeline { - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame, OsuColour colours) + protected override void LoadBeatmap(WorkingBeatmap beatmap) { - var beatmap = osuGame.Beatmap.Value; - if (beatmap == null) - return; - ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; cpi.TimingPoints.ForEach(addTimingPoint); @@ -254,13 +252,8 @@ namespace osu.Game.Tests.Visual private class BookmarkTimeline : Timeline { - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame) + protected override void LoadBeatmap(WorkingBeatmap beatmap) { - var beatmap = osuGame.Beatmap.Value; - if (beatmap == null) - return; - foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks) Add(new BookmarkVisualisation(bookmark)); } @@ -279,13 +272,8 @@ namespace osu.Game.Tests.Visual private class BreakTimeline : Timeline { - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame) + protected override void LoadBeatmap(WorkingBeatmap beatmap) { - var beatmap = osuGame.Beatmap.Value; - if (beatmap == null) - return; - foreach (var breakPeriod in beatmap.Beatmap.Breaks) Add(new BreakVisualisation(breakPeriod)); } @@ -314,16 +302,21 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(OsuGameBase osuGame) { - var beatmap = osuGame.Beatmap.Value; - if (beatmap == null) - return; + osuGame.Beatmap.ValueChanged += b => + { + timeline.Clear(); + timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); + LoadBeatmap(b); + }; - timeline.RelativeChildSize = new Vector2((float)beatmap.Track.Length, 1); + timeline.RelativeChildSize = new Vector2((float)Math.Max(1, osuGame.Beatmap.Value.Track.Length), 1); + LoadBeatmap(osuGame.Beatmap); } protected void Add(PointVisualisation visualisation) => timeline.Add(visualisation); - protected void Add(DurationVisualisation visualisation) => timeline.Add(visualisation); + + protected abstract void LoadBeatmap(WorkingBeatmap beatmap); } private class PointVisualisation : Box From 252121968d7b1840cd545407daded52cdef0da7c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 15:40:42 +0900 Subject: [PATCH 15/53] Actually load a beatmap for TestCaseEditorTimingTimeline --- .../Tests/Visual/TestCaseEditorTimingTimeline.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs index b6df81148e..14dc19da57 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs @@ -34,6 +34,21 @@ namespace osu.Game.Tests.Visual }); } + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame, BeatmapManager beatmaps) + { + BeatmapSetInfo setInfo = null; + + var sets = beatmaps.GetAllUsableBeatmapSets(false); + if (sets.Count > 0) + setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID); + + if (setInfo == null) + return; + + osuGame.Beatmap.Value = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); + } + private class TimingTimeline : CompositeDrawable { private const float corner_radius = 5; From fd278256ad6b6f3330bae8a6cd4f1c8391c86175 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 15:50:32 +0900 Subject: [PATCH 16/53] EditorTimingTimeline -> EditorMiniTimeline --- ...TimingTimeline.cs => TestCaseEditorMiniTimeline.cs} | 10 +++++----- osu.Game/osu.Game.csproj | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename osu.Game/Tests/Visual/{TestCaseEditorTimingTimeline.cs => TestCaseEditorMiniTimeline.cs} (96%) diff --git a/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs similarity index 96% rename from osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs rename to osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs index 14dc19da57..ecf6d90cef 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorTimingTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs @@ -22,11 +22,11 @@ using osu.Game.Graphics; namespace osu.Game.Tests.Visual { - internal class TestCaseEditorTimingTimeline : OsuTestCase + internal class TestCaseEditorMiniTimeline : OsuTestCase { - public TestCaseEditorTimingTimeline() + public TestCaseEditorMiniTimeline() { - Add(new TimingTimeline + Add(new MiniTimeline { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual osuGame.Beatmap.Value = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); } - private class TimingTimeline : CompositeDrawable + private class MiniTimeline : CompositeDrawable { private const float corner_radius = 5; private const float contents_padding = 15; @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual private readonly Bindable beatmap = new Bindable(); - public TimingTimeline() + public MiniTimeline() { Masking = true; CornerRadius = 5; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3ca7f393f1..facbc525e5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -733,7 +733,7 @@ - + From 01d84893a09022b4c0d4feb504f35d2764c8c7ae Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 15:55:23 +0900 Subject: [PATCH 17/53] Cleanup + commenting --- .../Visual/TestCaseEditorMiniTimeline.cs | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs index ecf6d90cef..f33c7301d5 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs @@ -49,6 +49,9 @@ namespace osu.Game.Tests.Visual osuGame.Beatmap.Value = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); } + /// + /// The timeline that sits at the bottom of the editor. + /// private class MiniTimeline : CompositeDrawable { private const float corner_radius = 5; @@ -180,21 +183,23 @@ namespace osu.Game.Tests.Visual } protected override bool OnDragStart(InputState state) => true; - + protected override bool OnDragEnd(InputState state) => true; protected override bool OnDrag(InputState state) { seekToPosition(state.Mouse.NativeState.Position); return true; } - protected override bool OnDragEnd(InputState state) => true; - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { seekToPosition(state.Mouse.NativeState.Position); return true; } + /// + /// Seeks the to the time closest to a position on the screen relative to the . + /// + /// The position in screen coordinates. private void seekToPosition(Vector2 screenPosition) { float markerPos = MathHelper.Clamp(markerContainer.ToLocalSpace(screenPosition).X, 0, markerContainer.DrawWidth); @@ -206,10 +211,12 @@ namespace osu.Game.Tests.Visual protected override void Update() { base.Update(); - marker.X = (float)beatmap.Value.Track.CurrentTime; } + /// + /// The part of the timeline that displays the control points. + /// private class ControlPointTimeline : Timeline { protected override void LoadBeatmap(WorkingBeatmap beatmap) @@ -265,6 +272,9 @@ namespace osu.Game.Tests.Visual } } + /// + /// The part of the timeline that displays bookmarks. + /// private class BookmarkTimeline : Timeline { protected override void LoadBeatmap(WorkingBeatmap beatmap) @@ -285,6 +295,9 @@ namespace osu.Game.Tests.Visual } } + /// + /// The part of the timeline that displays breaks in the song. + /// private class BreakTimeline : Timeline { protected override void LoadBeatmap(WorkingBeatmap beatmap) @@ -305,6 +318,9 @@ namespace osu.Game.Tests.Visual } } + /// + /// Represents a part of the editor timeline. + /// private abstract class Timeline : CompositeDrawable { private readonly Container timeline; @@ -334,6 +350,9 @@ namespace osu.Game.Tests.Visual protected abstract void LoadBeatmap(WorkingBeatmap beatmap); } + /// + /// Represents a singular point on a . + /// private class PointVisualisation : Box { public readonly double StartTime; @@ -353,6 +372,9 @@ namespace osu.Game.Tests.Visual } } + /// + /// Represents a spanning point on a . + /// private class DurationVisualisation : Container { public readonly double StartTime; From 967bfa404e5335569bd36050e8d20d78d6751bee Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 16:40:37 +0900 Subject: [PATCH 18/53] Generate a set beatmap instead of using the available beatmaps --- .../Visual/TestCaseEditorMiniTimeline.cs | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs index f33c7301d5..4e81ee1990 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs @@ -7,11 +7,13 @@ using System.Linq; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Framework.Lists; using osu.Framework.MathUtils; @@ -24,8 +26,13 @@ namespace osu.Game.Tests.Visual { internal class TestCaseEditorMiniTimeline : OsuTestCase { + private const int length = 60000; + private readonly Random random; + public TestCaseEditorMiniTimeline() { + random = new Random(1337); + Add(new MiniTimeline { Anchor = Anchor.Centre, @@ -37,16 +44,50 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(OsuGameBase osuGame, BeatmapManager beatmaps) { - BeatmapSetInfo setInfo = null; + var beatmap = new Beatmap(); - var sets = beatmaps.GetAllUsableBeatmapSets(false); - if (sets.Count > 0) - setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID); + for (int i = 0; i < random.Next(1, 10); i++) + beatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { Time = random.Next(0, length) }); - if (setInfo == null) - return; + for (int i = 0; i < random.Next(1, 5); i++) + beatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { Time = random.Next(0, length) }); - osuGame.Beatmap.Value = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); + for (int i = 0; i < random.Next(1, 5); i++) + beatmap.ControlPointInfo.EffectPoints.Add(new EffectControlPoint { Time = random.Next(0, length) }); + + for (int i = 0; i < random.Next(1, 5); i++) + beatmap.ControlPointInfo.SoundPoints.Add(new SoundControlPoint { Time = random.Next(0, length) }); + + beatmap.BeatmapInfo.Bookmarks = new int[random.Next(10, 30)]; + for (int i = 0; i < beatmap.BeatmapInfo.Bookmarks.Length; i++) + beatmap.BeatmapInfo.Bookmarks[i] = random.Next(0, length); + + osuGame.Beatmap.Value = new TestWorkingBeatmap(beatmap); + } + + private class TestWorkingBeatmap : WorkingBeatmap + { + private readonly Beatmap beatmap; + + public TestWorkingBeatmap(Beatmap beatmap) + : base(beatmap.BeatmapInfo) + { + this.beatmap = beatmap; + } + + protected override Texture GetBackground() => null; + + protected override Beatmap GetBeatmap() => beatmap; + + protected override Track GetTrack() => new TestTrack(); + + private class TestTrack : TrackVirtual + { + public TestTrack() + { + Length = length; + } + } } /// From 5978668d2b7387f09ce58783d86cc3ee569fa7f6 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 16:48:30 +0900 Subject: [PATCH 19/53] Mini -> Summary --- ...iTimeline.cs => TestCaseEditorSummaryTimeline.cs} | 12 ++++++------ osu.Game/osu.Game.csproj | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Tests/Visual/{TestCaseEditorMiniTimeline.cs => TestCaseEditorSummaryTimeline.cs} (95%) diff --git a/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs similarity index 95% rename from osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs rename to osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs index 4e81ee1990..0f170e7a6e 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorMiniTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs @@ -24,16 +24,16 @@ using osu.Game.Graphics; namespace osu.Game.Tests.Visual { - internal class TestCaseEditorMiniTimeline : OsuTestCase + internal class TestCaseEditorSummaryTimeline : OsuTestCase { private const int length = 60000; private readonly Random random; - public TestCaseEditorMiniTimeline() + public TestCaseEditorSummaryTimeline() { random = new Random(1337); - Add(new MiniTimeline + Add(new SummaryTimeline { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual /// /// The timeline that sits at the bottom of the editor. /// - private class MiniTimeline : CompositeDrawable + private class SummaryTimeline : CompositeDrawable { private const float corner_radius = 5; private const float contents_padding = 15; @@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual private readonly Bindable beatmap = new Bindable(); - public MiniTimeline() + public SummaryTimeline() { Masking = true; CornerRadius = 5; @@ -238,7 +238,7 @@ namespace osu.Game.Tests.Visual } /// - /// Seeks the to the time closest to a position on the screen relative to the . + /// Seeks the to the time closest to a position on the screen relative to the . /// /// The position in screen coordinates. private void seekToPosition(Vector2 screenPosition) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index facbc525e5..fde6133aac 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -733,7 +733,7 @@ - + From 3da3ef1a504bf6c571a97bdc56171b5628cc9cd6 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 16:53:01 +0900 Subject: [PATCH 20/53] CI fixes --- .../Visual/TestCaseEditorSummaryTimeline.cs | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs index 0f170e7a6e..9c9c7e963b 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs @@ -2,10 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using System.Linq; using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Configuration; @@ -15,8 +13,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Framework.Input; -using osu.Framework.Lists; -using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Timing; @@ -42,7 +38,7 @@ namespace osu.Game.Tests.Visual } [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame, BeatmapManager beatmaps) + private void load(OsuGameBase osuGame) { var beatmap = new Beatmap(); @@ -113,14 +109,14 @@ namespace osu.Game.Tests.Visual Masking = true; CornerRadius = 5; - InternalChildren = new Drawable[] + InternalChildren = new[] { background = new Box { RelativeSizeAxes = Axes.Both }, new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, - Children = new Drawable[] + Children = new[] { markerContainer = new Container { @@ -303,12 +299,9 @@ namespace osu.Game.Tests.Visual private abstract class ControlPointVisualisation : PointVisualisation { - public readonly ControlPoint ControlPoint; - - public ControlPointVisualisation(ControlPoint controlPoint) + protected ControlPointVisualisation(ControlPoint controlPoint) : base(controlPoint.Time) { - ControlPoint = controlPoint; } } } @@ -366,7 +359,7 @@ namespace osu.Game.Tests.Visual { private readonly Container timeline; - public Timeline() + protected Timeline() { AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); } @@ -396,12 +389,8 @@ namespace osu.Game.Tests.Visual /// private class PointVisualisation : Box { - public readonly double StartTime; - - public PointVisualisation(double startTime) + protected PointVisualisation(double startTime) { - StartTime = startTime; - Origin = Anchor.TopCentre; RelativeSizeAxes = Axes.Y; @@ -418,14 +407,8 @@ namespace osu.Game.Tests.Visual /// private class DurationVisualisation : Container { - public readonly double StartTime; - public readonly double EndTIme; - - public DurationVisualisation(double startTime, double endTime) + protected DurationVisualisation(double startTime, double endTime) { - StartTime = startTime; - EndTIme = endTime; - Masking = true; CornerRadius = corner_radius; From f9568619e7a71655192b56556b4a30f8c93f2dc7 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 16:59:03 +0900 Subject: [PATCH 21/53] Move SummaryTimeline into /Edit/Components/SummaryTimeline --- .../Edit/Components/SummaryTimeline.cs | 356 ++++++++++++++++++ .../Visual/TestCaseEditorSummaryTimeline.cs | 340 +---------------- osu.Game/osu.Game.csproj | 1 + 3 files changed, 361 insertions(+), 336 deletions(-) create mode 100644 osu.Game/Screens/Edit/Components/SummaryTimeline.cs diff --git a/osu.Game/Screens/Edit/Components/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/SummaryTimeline.cs new file mode 100644 index 0000000000..ffb54ba7b1 --- /dev/null +++ b/osu.Game/Screens/Edit/Components/SummaryTimeline.cs @@ -0,0 +1,356 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Timing; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Edit.Components +{ + /// + /// The timeline that sits at the bottom of the editor. + /// + public class SummaryTimeline : CompositeDrawable + { + private const float corner_radius = 5; + private const float contents_padding = 15; + private const float marker_bar_width = 2; + + private readonly Drawable background; + + private readonly Container markerContainer; + + private readonly Drawable timelineBar; + private readonly Drawable marker; + + private readonly Bindable beatmap = new Bindable(); + + public SummaryTimeline() + { + Masking = true; + CornerRadius = 5; + + InternalChildren = new[] + { + background = new Box { RelativeSizeAxes = Axes.Both }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, + Children = new[] + { + markerContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Child = marker = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new Triangle + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + Scale = new Vector2(1, -1), + Size = new Vector2(10, 5), + }, + new Triangle + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(10, 5) + }, + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = 2, + EdgeSmoothness = new Vector2(1, 0) + } + } + } + }, + new ControlPointTimeline + { + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, + new BookmarkTimeline + { + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, + timelineBar = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Circle + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Size = new Vector2(5) + }, + new Box + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + Height = 1, + EdgeSmoothness = new Vector2(0, 1), + }, + new Circle + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, + Size = new Vector2(5) + }, + } + }, + new BreakTimeline + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.25f + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame, OsuColour colours) + { + background.Colour = colours.Gray1; + marker.Colour = colours.Red; + timelineBar.Colour = colours.Gray5; + + beatmap.BindTo(osuGame.Beatmap); + + markerContainer.RelativeChildSize = new Vector2((float)Math.Max(1, beatmap.Value.Track.Length), 1); + beatmap.ValueChanged += b => markerContainer.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); + } + + protected override bool OnDragStart(InputState state) => true; + protected override bool OnDragEnd(InputState state) => true; + protected override bool OnDrag(InputState state) + { + seekToPosition(state.Mouse.NativeState.Position); + return true; + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + seekToPosition(state.Mouse.NativeState.Position); + return true; + } + + /// + /// Seeks the to the time closest to a position on the screen relative to the . + /// + /// The position in screen coordinates. + private void seekToPosition(Vector2 screenPosition) + { + float markerPos = MathHelper.Clamp(markerContainer.ToLocalSpace(screenPosition).X, 0, markerContainer.DrawWidth); + seekTo(markerPos / markerContainer.DrawWidth * beatmap.Value.Track.Length); + } + + private void seekTo(double time) => beatmap.Value.Track.Seek(time); + + protected override void Update() + { + base.Update(); + marker.X = (float)beatmap.Value.Track.CurrentTime; + } + + /// + /// The part of the timeline that displays the control points. + /// + private class ControlPointTimeline : Timeline + { + protected override void LoadBeatmap(WorkingBeatmap beatmap) + { + ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; + + cpi.TimingPoints.ForEach(addTimingPoint); + + // Consider all non-timing points as the same type + cpi.SoundPoints.Select(c => (ControlPoint)c) + .Concat(cpi.EffectPoints) + .Concat(cpi.DifficultyPoints) + .Distinct() + // Non-timing points should not be added where there are timing points + .Where(c => cpi.TimingPointAt(c.Time).Time != c.Time) + .ForEach(addNonTimingPoint); + } + + private void addTimingPoint(ControlPoint controlPoint) => Add(new TimingPointVisualisation(controlPoint)); + private void addNonTimingPoint(ControlPoint controlPoint) => Add(new NonTimingPointVisualisation(controlPoint)); + + private class TimingPointVisualisation : ControlPointVisualisation + { + public TimingPointVisualisation(ControlPoint controlPoint) + : base(controlPoint) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.YellowDark; + } + + private class NonTimingPointVisualisation : ControlPointVisualisation + { + public NonTimingPointVisualisation(ControlPoint controlPoint) + : base(controlPoint) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Green; + } + + private abstract class ControlPointVisualisation : PointVisualisation + { + protected ControlPointVisualisation(ControlPoint controlPoint) + : base(controlPoint.Time) + { + } + } + } + + /// + /// The part of the timeline that displays bookmarks. + /// + private class BookmarkTimeline : Timeline + { + protected override void LoadBeatmap(WorkingBeatmap beatmap) + { + foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks) + Add(new BookmarkVisualisation(bookmark)); + } + + private class BookmarkVisualisation : PointVisualisation + { + public BookmarkVisualisation(double startTime) + : base(startTime) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Blue; + } + } + + /// + /// The part of the timeline that displays breaks in the song. + /// + private class BreakTimeline : Timeline + { + protected override void LoadBeatmap(WorkingBeatmap beatmap) + { + foreach (var breakPeriod in beatmap.Beatmap.Breaks) + Add(new BreakVisualisation(breakPeriod)); + } + + private class BreakVisualisation : DurationVisualisation + { + public BreakVisualisation(BreakPeriod breakPeriod) + : base(breakPeriod.StartTime, breakPeriod.EndTime) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Yellow; + } + } + + /// + /// Represents a part of the editor timeline. + /// + private abstract class Timeline : CompositeDrawable + { + private readonly Container timeline; + + protected Timeline() + { + AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame) + { + osuGame.Beatmap.ValueChanged += b => + { + timeline.Clear(); + timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); + LoadBeatmap(b); + }; + + timeline.RelativeChildSize = new Vector2((float)Math.Max(1, osuGame.Beatmap.Value.Track.Length), 1); + LoadBeatmap(osuGame.Beatmap); + } + + protected void Add(PointVisualisation visualisation) => timeline.Add(visualisation); + protected void Add(DurationVisualisation visualisation) => timeline.Add(visualisation); + + protected abstract void LoadBeatmap(WorkingBeatmap beatmap); + } + + /// + /// Represents a singular point on a . + /// + private class PointVisualisation : Box + { + protected PointVisualisation(double startTime) + { + Origin = Anchor.TopCentre; + + RelativeSizeAxes = Axes.Y; + Width = 1; + EdgeSmoothness = new Vector2(1, 0); + + RelativePositionAxes = Axes.X; + X = (float)startTime; + } + } + + /// + /// Represents a spanning point on a . + /// + private class DurationVisualisation : Container + { + protected DurationVisualisation(double startTime, double endTime) + { + Masking = true; + CornerRadius = corner_radius; + + RelativePositionAxes = Axes.X; + RelativeSizeAxes = Axes.Both; + X = (float)startTime; + Width = (float)(endTime - startTime); + + AddInternal(new Box { RelativeSizeAxes = Axes.Both }); + } + } + } +} diff --git a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs index 9c9c7e963b..ee7f54f771 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Linq; using OpenTK; using osu.Framework.Allocation; @@ -17,6 +18,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; +using osu.Game.Screens.Edit.Components; namespace osu.Game.Tests.Visual { @@ -25,6 +27,8 @@ namespace osu.Game.Tests.Visual private const int length = 60000; private readonly Random random; + public override IReadOnlyList RequiredTypes => new Type[] { typeof(SummaryTimeline) }; + public TestCaseEditorSummaryTimeline() { random = new Random(1337); @@ -85,341 +89,5 @@ namespace osu.Game.Tests.Visual } } } - - /// - /// The timeline that sits at the bottom of the editor. - /// - private class SummaryTimeline : CompositeDrawable - { - private const float corner_radius = 5; - private const float contents_padding = 15; - private const float marker_bar_width = 2; - - private readonly Drawable background; - - private readonly Container markerContainer; - - private readonly Drawable timelineBar; - private readonly Drawable marker; - - private readonly Bindable beatmap = new Bindable(); - - public SummaryTimeline() - { - Masking = true; - CornerRadius = 5; - - InternalChildren = new[] - { - background = new Box { RelativeSizeAxes = Axes.Both }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, - Children = new[] - { - markerContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Child = marker = new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - new Triangle - { - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, - Scale = new Vector2(1, -1), - Size = new Vector2(10, 5), - }, - new Triangle - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Size = new Vector2(10, 5) - }, - new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = 2, - EdgeSmoothness = new Vector2(1, 0) - } - } - } - }, - new ControlPointTimeline - { - Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.Both, - Height = 0.35f - }, - new BookmarkTimeline - { - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Height = 0.35f - }, - timelineBar = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Circle - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, - Size = new Vector2(5) - }, - new Box - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - Height = 1, - EdgeSmoothness = new Vector2(0, 1), - }, - new Circle - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreLeft, - Size = new Vector2(5) - }, - } - }, - new BreakTimeline - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Height = 0.25f - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame, OsuColour colours) - { - background.Colour = colours.Gray1; - marker.Colour = colours.Red; - timelineBar.Colour = colours.Gray5; - - beatmap.BindTo(osuGame.Beatmap); - - markerContainer.RelativeChildSize = new Vector2((float)Math.Max(1, beatmap.Value.Track.Length), 1); - beatmap.ValueChanged += b => markerContainer.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); - } - - protected override bool OnDragStart(InputState state) => true; - protected override bool OnDragEnd(InputState state) => true; - protected override bool OnDrag(InputState state) - { - seekToPosition(state.Mouse.NativeState.Position); - return true; - } - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - seekToPosition(state.Mouse.NativeState.Position); - return true; - } - - /// - /// Seeks the to the time closest to a position on the screen relative to the . - /// - /// The position in screen coordinates. - private void seekToPosition(Vector2 screenPosition) - { - float markerPos = MathHelper.Clamp(markerContainer.ToLocalSpace(screenPosition).X, 0, markerContainer.DrawWidth); - seekTo(markerPos / markerContainer.DrawWidth * beatmap.Value.Track.Length); - } - - private void seekTo(double time) => beatmap.Value.Track.Seek(time); - - protected override void Update() - { - base.Update(); - marker.X = (float)beatmap.Value.Track.CurrentTime; - } - - /// - /// The part of the timeline that displays the control points. - /// - private class ControlPointTimeline : Timeline - { - protected override void LoadBeatmap(WorkingBeatmap beatmap) - { - ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; - - cpi.TimingPoints.ForEach(addTimingPoint); - - // Consider all non-timing points as the same type - cpi.SoundPoints.Select(c => (ControlPoint)c) - .Concat(cpi.EffectPoints) - .Concat(cpi.DifficultyPoints) - .Distinct() - // Non-timing points should not be added where there are timing points - .Where(c => cpi.TimingPointAt(c.Time).Time != c.Time) - .ForEach(addNonTimingPoint); - } - - private void addTimingPoint(ControlPoint controlPoint) => Add(new TimingPointVisualisation(controlPoint)); - private void addNonTimingPoint(ControlPoint controlPoint) => Add(new NonTimingPointVisualisation(controlPoint)); - - private class TimingPointVisualisation : ControlPointVisualisation - { - public TimingPointVisualisation(ControlPoint controlPoint) - : base(controlPoint) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.YellowDark; - } - - private class NonTimingPointVisualisation : ControlPointVisualisation - { - public NonTimingPointVisualisation(ControlPoint controlPoint) - : base(controlPoint) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.Green; - } - - private abstract class ControlPointVisualisation : PointVisualisation - { - protected ControlPointVisualisation(ControlPoint controlPoint) - : base(controlPoint.Time) - { - } - } - } - - /// - /// The part of the timeline that displays bookmarks. - /// - private class BookmarkTimeline : Timeline - { - protected override void LoadBeatmap(WorkingBeatmap beatmap) - { - foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks) - Add(new BookmarkVisualisation(bookmark)); - } - - private class BookmarkVisualisation : PointVisualisation - { - public BookmarkVisualisation(double startTime) - : base(startTime) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.Blue; - } - } - - /// - /// The part of the timeline that displays breaks in the song. - /// - private class BreakTimeline : Timeline - { - protected override void LoadBeatmap(WorkingBeatmap beatmap) - { - foreach (var breakPeriod in beatmap.Beatmap.Breaks) - Add(new BreakVisualisation(breakPeriod)); - } - - private class BreakVisualisation : DurationVisualisation - { - public BreakVisualisation(BreakPeriod breakPeriod) - : base(breakPeriod.StartTime, breakPeriod.EndTime) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.Yellow; - } - } - - /// - /// Represents a part of the editor timeline. - /// - private abstract class Timeline : CompositeDrawable - { - private readonly Container timeline; - - protected Timeline() - { - AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); - } - - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame) - { - osuGame.Beatmap.ValueChanged += b => - { - timeline.Clear(); - timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); - LoadBeatmap(b); - }; - - timeline.RelativeChildSize = new Vector2((float)Math.Max(1, osuGame.Beatmap.Value.Track.Length), 1); - LoadBeatmap(osuGame.Beatmap); - } - - protected void Add(PointVisualisation visualisation) => timeline.Add(visualisation); - protected void Add(DurationVisualisation visualisation) => timeline.Add(visualisation); - - protected abstract void LoadBeatmap(WorkingBeatmap beatmap); - } - - /// - /// Represents a singular point on a . - /// - private class PointVisualisation : Box - { - protected PointVisualisation(double startTime) - { - Origin = Anchor.TopCentre; - - RelativeSizeAxes = Axes.Y; - Width = 1; - EdgeSmoothness = new Vector2(1, 0); - - RelativePositionAxes = Axes.X; - X = (float)startTime; - } - } - - /// - /// Represents a spanning point on a . - /// - private class DurationVisualisation : Container - { - protected DurationVisualisation(double startTime, double endTime) - { - Masking = true; - CornerRadius = corner_radius; - - RelativePositionAxes = Axes.X; - RelativeSizeAxes = Axes.Both; - X = (float)startTime; - Width = (float)(endTime - startTime); - - AddInternal(new Box { RelativeSizeAxes = Axes.Both }); - } - } - } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index fde6133aac..768d46dce4 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -604,6 +604,7 @@ + From 7588f1b6caee6f0f0e81a269ff9c49d51fd274f6 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 17:09:38 +0900 Subject: [PATCH 22/53] Add SummaryTimeline to Editor --- osu.Game/Screens/Edit/Editor.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index be9098e3be..04f45d9a34 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -13,6 +13,8 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Menus; +using osu.Game.Screens.Edit.Components; +using OpenTK; namespace osu.Game.Screens.Edit { @@ -189,6 +191,23 @@ namespace osu.Game.Screens.Edit } } }); + + Add(new FillFlowContainer + { + Name = "Bottom bar", + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 60, + Padding = new MarginPadding { Top = 5, Bottom = 5, Left = 10, Right = 10 }, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new[] + { + new SummaryTimeline { RelativeSizeAxes = Axes.Both } + } + }); + } protected override void OnResuming(Screen last) From 58b09a161f65a5e053c35b1ada6264cbc1929dda Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 17:16:12 +0900 Subject: [PATCH 23/53] CI fixes --- .../Tests/Visual/TestCaseEditorSummaryTimeline.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs index ee7f54f771..68c34269f8 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs @@ -3,22 +3,14 @@ using System; using System.Collections.Generic; -using System.Linq; -using OpenTK; using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; -using osu.Framework.Input; +using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Timing; -using osu.Game.Graphics; using osu.Game.Screens.Edit.Components; +using OpenTK; namespace osu.Game.Tests.Visual { @@ -27,7 +19,7 @@ namespace osu.Game.Tests.Visual private const int length = 60000; private readonly Random random; - public override IReadOnlyList RequiredTypes => new Type[] { typeof(SummaryTimeline) }; + public override IReadOnlyList RequiredTypes => new[] { typeof(SummaryTimeline) }; public TestCaseEditorSummaryTimeline() { From 7168e8fd99e20dc43b7f80e78540ebdd089d5b7f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 18:16:03 +0900 Subject: [PATCH 24/53] Improve layout of bottom bar in the Editor --- osu.Game/Screens/Edit/Editor.cs | 44 +++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 04f45d9a34..b482061cd8 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -15,17 +15,18 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Menus; using osu.Game.Screens.Edit.Components; using OpenTK; +using osu.Framework.Allocation; namespace osu.Game.Screens.Edit { - internal class Editor : ScreenWhiteBox + internal class Editor : OsuScreen { - protected override IEnumerable PossibleChildren => new[] { typeof(EditSongSelect) }; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); internal override bool ShowOverlays => false; + private readonly Box bottomBackground; + public Editor() { Add(new Container @@ -192,22 +193,45 @@ namespace osu.Game.Screens.Edit } }); - Add(new FillFlowContainer + Add(new Container { - Name = "Bottom bar", Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = 60, - Padding = new MarginPadding { Top = 5, Bottom = 5, Left = 10, Right = 10 }, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new[] + Children = new Drawable[] { - new SummaryTimeline { RelativeSizeAxes = Axes.Both } + bottomBackground = new Box { RelativeSizeAxes = Axes.Both }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 5, Bottom = 5, Left = 10, Right = 10 }, + Child = new FillFlowContainer + { + Name = "Bottom bar", + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new[] + { + new SummaryTimeline + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Width = 0.65f + } + } + } + } } }); + } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + bottomBackground.Colour = colours.Gray2; } protected override void OnResuming(Screen last) From e65a17ad96697b051b41744c77f588b573f6dfde Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 20 Sep 2017 18:40:41 +0900 Subject: [PATCH 25/53] Remove redundant usings --- osu.Game/Screens/Edit/Editor.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index b482061cd8..c91ea9d686 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -1,12 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.Collections.Generic; using OpenTK.Graphics; using osu.Framework.Screens; using osu.Game.Screens.Backgrounds; -using osu.Game.Screens.Select; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; From 09968671129fd5bf97d309744571a68ace8af67f Mon Sep 17 00:00:00 2001 From: Damnae Date: Mon, 25 Sep 2017 10:40:22 +0200 Subject: [PATCH 26/53] 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 d787c740fa22e83be06b4022814d8bb362084836 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 25 Sep 2017 17:46:51 +0900 Subject: [PATCH 27/53] Fix bookmarks not working We should be dealing with the array in every situation, with the exception of the database. --- osu.Game/Beatmaps/BeatmapInfo.cs | 14 +++++++------- .../Screens/Edit/Components/SummaryTimeline.cs | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index e031f25fa2..3cd6294b4a 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -78,15 +78,15 @@ namespace osu.Game.Beatmaps // Editor // This bookmarks stuff is necessary because DB doesn't know how to store int[] - public string StoredBookmarks { get; set; } + [JsonIgnore] + public string StoredBookmarks + { + get { return string.Join(",", Bookmarks); } + set { Bookmarks = value?.Split(',').Select(v => int.Parse(v.Trim())).ToArray() ?? new int[0]; } + } [Ignore] - [JsonIgnore] - public int[] Bookmarks - { - get { return StoredBookmarks?.Split(',').Select(int.Parse).ToArray() ?? new int[0]; } - set { StoredBookmarks = string.Join(",", value); } - } + public int[] Bookmarks { get; set; } = new int[0]; public double DistanceSpacing { get; set; } public int BeatDivisor { get; set; } diff --git a/osu.Game/Screens/Edit/Components/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/SummaryTimeline.cs index ffb54ba7b1..80250eebc3 100644 --- a/osu.Game/Screens/Edit/Components/SummaryTimeline.cs +++ b/osu.Game/Screens/Edit/Components/SummaryTimeline.cs @@ -96,6 +96,7 @@ namespace osu.Game.Screens.Edit.Components new BookmarkTimeline { Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, Height = 0.35f }, From d86e81f07c860efdba6a407297d75cbd370d238b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 25 Sep 2017 17:52:57 +0900 Subject: [PATCH 28/53] Better expression to avoid invalid values --- osu.Game/Beatmaps/BeatmapInfo.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 3cd6294b4a..5e4e122fb5 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -82,7 +82,21 @@ namespace osu.Game.Beatmaps public string StoredBookmarks { get { return string.Join(",", Bookmarks); } - set { Bookmarks = value?.Split(',').Select(v => int.Parse(v.Trim())).ToArray() ?? new int[0]; } + set + { + if (string.IsNullOrEmpty(value)) + { + Bookmarks = new int[0]; + return; + } + + Bookmarks = value.Split(',').Select(v => + { + int val; + bool result = int.TryParse(v, out val); + return new { result, val }; + }).Where(p => p.result).Select(p => p.val).ToArray(); + } } [Ignore] From 2d4616fd43cb22ac7d6ae5d704651347238b017f Mon Sep 17 00:00:00 2001 From: Damnae Date: Mon, 25 Sep 2017 11:03:57 +0200 Subject: [PATCH 29/53] 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); } From a1f88a17b1afa97d4e02bd85b6670c807d12de99 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Sep 2017 15:44:40 +0900 Subject: [PATCH 30/53] Re-namespace and split out timeline parts from the SummaryTimeline --- .../Timelines/Summary/Parts/BookmarkPart.cs | 30 +++++++++ .../Timelines/Summary/Parts/BreakPart.cs | 31 +++++++++ .../Summary/Parts/ControlPointPart.cs | 65 +++++++++++++++++++ .../Timelines/Summary/Parts/TimelinePart.cs | 40 ++++++++++++ .../Visualisations/DurationVisualisation.cs | 25 +++++++ .../Visualisations/PointVisualisation.cs | 24 +++++++ osu.Game/osu.Game.csproj | 6 ++ 7 files changed, 221 insertions(+) create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs new file mode 100644 index 0000000000..5680b85c08 --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs @@ -0,0 +1,30 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts +{ + /// + /// The part of the timeline that displays bookmarks. + /// + internal class BookmarkPart : TimelinePart + { + protected override void LoadBeatmap(WorkingBeatmap beatmap) + { + foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks) + Add(new BookmarkVisualisation(bookmark)); + } + + private class BookmarkVisualisation : PointVisualisation + { + public BookmarkVisualisation(double startTime) + : base(startTime) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Blue; + } + } +} diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs new file mode 100644 index 0000000000..fefb3d5f10 --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -0,0 +1,31 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Timing; +using osu.Game.Graphics; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts +{ + /// + /// The part of the timeline that displays breaks in the song. + /// + internal class BreakPart : TimelinePart + { + protected override void LoadBeatmap(WorkingBeatmap beatmap) + { + foreach (var breakPeriod in beatmap.Beatmap.Breaks) + Add(new BreakVisualisation(breakPeriod)); + } + + private class BreakVisualisation : DurationVisualisation + { + public BreakVisualisation(BreakPeriod breakPeriod) + : base(breakPeriod.StartTime, breakPeriod.EndTime) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Yellow; + } + } +} diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs new file mode 100644 index 0000000000..12b3624123 --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -0,0 +1,65 @@ +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts +{ + /// + /// The part of the timeline that displays the control points. + /// + internal class ControlPointPart : TimelinePart + { + protected override void LoadBeatmap(WorkingBeatmap beatmap) + { + ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; + + cpi.TimingPoints.ForEach(addTimingPoint); + + // Consider all non-timing points as the same type + cpi.SoundPoints.Select(c => (ControlPoint)c) + .Concat(cpi.EffectPoints) + .Concat(cpi.DifficultyPoints) + .Distinct() + // Non-timing points should not be added where there are timing points + .Where(c => cpi.TimingPointAt(c.Time).Time != c.Time) + .ForEach(addNonTimingPoint); + } + + private void addTimingPoint(ControlPoint controlPoint) => Add(new TimingPointVisualisation(controlPoint)); + private void addNonTimingPoint(ControlPoint controlPoint) => Add(new NonTimingPointVisualisation(controlPoint)); + + private class TimingPointVisualisation : ControlPointVisualisation + { + public TimingPointVisualisation(ControlPoint controlPoint) + : base(controlPoint) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.YellowDark; + } + + private class NonTimingPointVisualisation : ControlPointVisualisation + { + public NonTimingPointVisualisation(ControlPoint controlPoint) + : base(controlPoint) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Green; + } + + private abstract class ControlPointVisualisation : PointVisualisation + { + protected ControlPointVisualisation(ControlPoint controlPoint) + : base(controlPoint.Time) + { + } + } + } +} diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs new file mode 100644 index 0000000000..30786a80ff --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -0,0 +1,40 @@ +using System; +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts +{ + /// + /// Represents a part of the summary timeline.. + /// + internal abstract class TimelinePart : CompositeDrawable + { + private readonly Container timeline; + + protected TimelinePart() + { + AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame) + { + osuGame.Beatmap.ValueChanged += b => + { + timeline.Clear(); + timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); + LoadBeatmap(b); + }; + + timeline.RelativeChildSize = new Vector2((float)Math.Max(1, osuGame.Beatmap.Value.Track.Length), 1); + LoadBeatmap(osuGame.Beatmap); + } + + protected void Add(Drawable visualisation) => timeline.Add(visualisation); + + protected abstract void LoadBeatmap(WorkingBeatmap beatmap); + } +} diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs new file mode 100644 index 0000000000..9718e9df5f --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs @@ -0,0 +1,25 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations +{ + /// + /// Represents a spanning point on a . + /// + internal class DurationVisualisation : Container + { + protected DurationVisualisation(double startTime, double endTime) + { + Masking = true; + CornerRadius = 5; + + RelativePositionAxes = Axes.X; + RelativeSizeAxes = Axes.Both; + X = (float)startTime; + Width = (float)(endTime - startTime); + + AddInternal(new Box { RelativeSizeAxes = Axes.Both }); + } + } +} diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs new file mode 100644 index 0000000000..f0eb2ed499 --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs @@ -0,0 +1,24 @@ +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations +{ + /// + /// Represents a singular point on a . + /// + internal class PointVisualisation : Box + { + protected PointVisualisation(double startTime) + { + Origin = Anchor.TopCentre; + + RelativeSizeAxes = Axes.Y; + Width = 1; + EdgeSmoothness = new Vector2(1, 0); + + RelativePositionAxes = Axes.X; + X = (float)startTime; + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e43f6cfd8c..33eaff8ff5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -606,6 +606,12 @@ + + + + + + From 85cb541fef7898353bf042f1b056afc396a1cbfc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Sep 2017 15:44:59 +0900 Subject: [PATCH 31/53] Implement MarkerPart for the marker --- .../Timelines/Summary/Parts/MarkerPart.cs | 108 ++++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 2 files changed, 109 insertions(+) create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs new file mode 100644 index 0000000000..9c1587801e --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -0,0 +1,108 @@ +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Beatmaps; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts +{ + /// + /// The part of the timeline that displays the current position of the song. + /// + internal class MarkerPart : TimelinePart + { + private WorkingBeatmap beatmap; + + private readonly Drawable marker; + + public MarkerPart() + { + Add(marker = new MarkerVisualisation()); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + marker.Colour = colours.Red; + } + + protected override void LoadBeatmap(WorkingBeatmap beatmap) + { + this.beatmap = beatmap; + } + + protected override bool OnDragStart(InputState state) => true; + protected override bool OnDragEnd(InputState state) => true; + protected override bool OnDrag(InputState state) + { + seekToPosition(state.Mouse.NativeState.Position); + return true; + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + seekToPosition(state.Mouse.NativeState.Position); + return true; + } + + /// + /// Seeks the to the time closest to a position on the screen relative to the . + /// + /// The position in screen coordinates. + private void seekToPosition(Vector2 screenPosition) + { + float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); + seekTo(markerPos / DrawWidth * beatmap.Track.Length); + } + + private void seekTo(double time) => beatmap.Track.Seek(time); + + protected override void Update() + { + base.Update(); + marker.X = (float)beatmap.Track.CurrentTime; + } + + private class MarkerVisualisation : CompositeDrawable + { + public MarkerVisualisation() + { + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + RelativePositionAxes = Axes.X; + RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; + InternalChildren = new Drawable[] + { + new Triangle + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + Scale = new Vector2(1, -1), + Size = new Vector2(10, 5), + }, + new Triangle + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(10, 5) + }, + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = 2, + EdgeSmoothness = new Vector2(1, 0) + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Red; + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 33eaff8ff5..0a983bccb0 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -609,6 +609,7 @@ + From 5953c1084e023812216a7e4acb8397b401479ae4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Sep 2017 15:45:27 +0900 Subject: [PATCH 32/53] Re-namespace SummaryTimeline --- .../Edit/Components/SummaryTimeline.cs | 357 ------------------ .../Timelines/Summary/SummaryTimeline.cs | 110 ++++++ osu.Game/Screens/Edit/Editor.cs | 2 +- .../Visual/TestCaseEditorSummaryTimeline.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- 5 files changed, 113 insertions(+), 360 deletions(-) delete mode 100644 osu.Game/Screens/Edit/Components/SummaryTimeline.cs create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs diff --git a/osu.Game/Screens/Edit/Components/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/SummaryTimeline.cs deleted file mode 100644 index 80250eebc3..0000000000 --- a/osu.Game/Screens/Edit/Components/SummaryTimeline.cs +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using OpenTK; -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Timing; -using osu.Game.Graphics; - -namespace osu.Game.Screens.Edit.Components -{ - /// - /// The timeline that sits at the bottom of the editor. - /// - public class SummaryTimeline : CompositeDrawable - { - private const float corner_radius = 5; - private const float contents_padding = 15; - private const float marker_bar_width = 2; - - private readonly Drawable background; - - private readonly Container markerContainer; - - private readonly Drawable timelineBar; - private readonly Drawable marker; - - private readonly Bindable beatmap = new Bindable(); - - public SummaryTimeline() - { - Masking = true; - CornerRadius = 5; - - InternalChildren = new[] - { - background = new Box { RelativeSizeAxes = Axes.Both }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, - Children = new[] - { - markerContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Child = marker = new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - new Triangle - { - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, - Scale = new Vector2(1, -1), - Size = new Vector2(10, 5), - }, - new Triangle - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Size = new Vector2(10, 5) - }, - new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = 2, - EdgeSmoothness = new Vector2(1, 0) - } - } - } - }, - new ControlPointTimeline - { - Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.Both, - Height = 0.35f - }, - new BookmarkTimeline - { - Anchor = Anchor.Centre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Both, - Height = 0.35f - }, - timelineBar = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Circle - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, - Size = new Vector2(5) - }, - new Box - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - Height = 1, - EdgeSmoothness = new Vector2(0, 1), - }, - new Circle - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreLeft, - Size = new Vector2(5) - }, - } - }, - new BreakTimeline - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Height = 0.25f - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame, OsuColour colours) - { - background.Colour = colours.Gray1; - marker.Colour = colours.Red; - timelineBar.Colour = colours.Gray5; - - beatmap.BindTo(osuGame.Beatmap); - - markerContainer.RelativeChildSize = new Vector2((float)Math.Max(1, beatmap.Value.Track.Length), 1); - beatmap.ValueChanged += b => markerContainer.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); - } - - protected override bool OnDragStart(InputState state) => true; - protected override bool OnDragEnd(InputState state) => true; - protected override bool OnDrag(InputState state) - { - seekToPosition(state.Mouse.NativeState.Position); - return true; - } - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - seekToPosition(state.Mouse.NativeState.Position); - return true; - } - - /// - /// Seeks the to the time closest to a position on the screen relative to the . - /// - /// The position in screen coordinates. - private void seekToPosition(Vector2 screenPosition) - { - float markerPos = MathHelper.Clamp(markerContainer.ToLocalSpace(screenPosition).X, 0, markerContainer.DrawWidth); - seekTo(markerPos / markerContainer.DrawWidth * beatmap.Value.Track.Length); - } - - private void seekTo(double time) => beatmap.Value.Track.Seek(time); - - protected override void Update() - { - base.Update(); - marker.X = (float)beatmap.Value.Track.CurrentTime; - } - - /// - /// The part of the timeline that displays the control points. - /// - private class ControlPointTimeline : Timeline - { - protected override void LoadBeatmap(WorkingBeatmap beatmap) - { - ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; - - cpi.TimingPoints.ForEach(addTimingPoint); - - // Consider all non-timing points as the same type - cpi.SoundPoints.Select(c => (ControlPoint)c) - .Concat(cpi.EffectPoints) - .Concat(cpi.DifficultyPoints) - .Distinct() - // Non-timing points should not be added where there are timing points - .Where(c => cpi.TimingPointAt(c.Time).Time != c.Time) - .ForEach(addNonTimingPoint); - } - - private void addTimingPoint(ControlPoint controlPoint) => Add(new TimingPointVisualisation(controlPoint)); - private void addNonTimingPoint(ControlPoint controlPoint) => Add(new NonTimingPointVisualisation(controlPoint)); - - private class TimingPointVisualisation : ControlPointVisualisation - { - public TimingPointVisualisation(ControlPoint controlPoint) - : base(controlPoint) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.YellowDark; - } - - private class NonTimingPointVisualisation : ControlPointVisualisation - { - public NonTimingPointVisualisation(ControlPoint controlPoint) - : base(controlPoint) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.Green; - } - - private abstract class ControlPointVisualisation : PointVisualisation - { - protected ControlPointVisualisation(ControlPoint controlPoint) - : base(controlPoint.Time) - { - } - } - } - - /// - /// The part of the timeline that displays bookmarks. - /// - private class BookmarkTimeline : Timeline - { - protected override void LoadBeatmap(WorkingBeatmap beatmap) - { - foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks) - Add(new BookmarkVisualisation(bookmark)); - } - - private class BookmarkVisualisation : PointVisualisation - { - public BookmarkVisualisation(double startTime) - : base(startTime) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.Blue; - } - } - - /// - /// The part of the timeline that displays breaks in the song. - /// - private class BreakTimeline : Timeline - { - protected override void LoadBeatmap(WorkingBeatmap beatmap) - { - foreach (var breakPeriod in beatmap.Beatmap.Breaks) - Add(new BreakVisualisation(breakPeriod)); - } - - private class BreakVisualisation : DurationVisualisation - { - public BreakVisualisation(BreakPeriod breakPeriod) - : base(breakPeriod.StartTime, breakPeriod.EndTime) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.Yellow; - } - } - - /// - /// Represents a part of the editor timeline. - /// - private abstract class Timeline : CompositeDrawable - { - private readonly Container timeline; - - protected Timeline() - { - AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); - } - - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame) - { - osuGame.Beatmap.ValueChanged += b => - { - timeline.Clear(); - timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); - LoadBeatmap(b); - }; - - timeline.RelativeChildSize = new Vector2((float)Math.Max(1, osuGame.Beatmap.Value.Track.Length), 1); - LoadBeatmap(osuGame.Beatmap); - } - - protected void Add(PointVisualisation visualisation) => timeline.Add(visualisation); - protected void Add(DurationVisualisation visualisation) => timeline.Add(visualisation); - - protected abstract void LoadBeatmap(WorkingBeatmap beatmap); - } - - /// - /// Represents a singular point on a . - /// - private class PointVisualisation : Box - { - protected PointVisualisation(double startTime) - { - Origin = Anchor.TopCentre; - - RelativeSizeAxes = Axes.Y; - Width = 1; - EdgeSmoothness = new Vector2(1, 0); - - RelativePositionAxes = Axes.X; - X = (float)startTime; - } - } - - /// - /// Represents a spanning point on a . - /// - private class DurationVisualisation : Container - { - protected DurationVisualisation(double startTime, double endTime) - { - Masking = true; - CornerRadius = corner_radius; - - RelativePositionAxes = Axes.X; - RelativeSizeAxes = Axes.Both; - X = (float)startTime; - Width = (float)(endTime - startTime); - - AddInternal(new Box { RelativeSizeAxes = Axes.Both }); - } - } - } -} diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs new file mode 100644 index 0000000000..31c40861ea --- /dev/null +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs @@ -0,0 +1,110 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Timing; +using osu.Game.Graphics; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; + +namespace osu.Game.Screens.Edit.Components.Timelines.Summary +{ + /// + /// The timeline that sits at the bottom of the editor. + /// + public class SummaryTimeline : CompositeDrawable + { + private const float corner_radius = 5; + private const float contents_padding = 15; + private const float marker_bar_width = 2; + + private readonly Drawable background; + + private readonly Drawable timelineBar; + + public SummaryTimeline() + { + Masking = true; + CornerRadius = corner_radius; + + InternalChildren = new[] + { + background = new Box { RelativeSizeAxes = Axes.Both }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, + Children = new[] + { + new MarkerPart { RelativeSizeAxes = Axes.Both }, + new ControlPointPart + { + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, + new BookmarkPart + { + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, + timelineBar = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Circle + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Size = new Vector2(5) + }, + new Box + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + Height = 1, + EdgeSmoothness = new Vector2(0, 1), + }, + new Circle + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, + Size = new Vector2(5) + }, + } + }, + new BreakPart + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.25f + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame, OsuColour colours) + { + background.Colour = colours.Gray1; + timelineBar.Colour = colours.Gray5; + } + } +} diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index c91ea9d686..7afbbc33bb 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Menus; -using osu.Game.Screens.Edit.Components; +using osu.Game.Screens.Edit.Components.Timelines.Summary; using OpenTK; using osu.Framework.Allocation; diff --git a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs index 68c34269f8..59037ce151 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs @@ -9,8 +9,8 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Screens.Edit.Components; using OpenTK; +using osu.Game.Screens.Edit.Components.Timelines.Summary; namespace osu.Game.Tests.Visual { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0a983bccb0..d6383ecc22 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -605,7 +605,6 @@ - @@ -613,6 +612,7 @@ + From 10e5fe40b29b75f046383014e8a4f247d051ab50 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Sep 2017 15:51:45 +0900 Subject: [PATCH 33/53] A bit of cleanup --- .../Components/Timelines/Summary/SummaryTimeline.cs | 11 +---------- .../Summary/Visualisations/DurationVisualisation.cs | 2 +- .../Summary/Visualisations/PointVisualisation.cs | 2 +- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs index 31c40861ea..0712936bf9 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs @@ -1,19 +1,11 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.Linq; using OpenTK; using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; @@ -26,7 +18,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary { private const float corner_radius = 5; private const float contents_padding = 15; - private const float marker_bar_width = 2; private readonly Drawable background; @@ -101,7 +92,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary } [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame, OsuColour colours) + private void load(OsuColour colours) { background.Colour = colours.Gray1; timelineBar.Colour = colours.Gray5; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs index 9718e9df5f..8926a2f55d 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations { /// - /// Represents a spanning point on a . + /// Represents a spanning point on a timeline part. /// internal class DurationVisualisation : Container { diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs index f0eb2ed499..bf52d28d97 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations { /// - /// Represents a singular point on a . + /// Represents a singular point on a timeline part. /// internal class PointVisualisation : Box { From 3937ebdc3dfe642fcac4cfe3e33f6ecc096b0a04 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Sep 2017 15:55:55 +0900 Subject: [PATCH 34/53] Add missing license headers --- .../Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs | 3 +++ .../Edit/Components/Timelines/Summary/Parts/BreakPart.cs | 3 +++ .../Components/Timelines/Summary/Parts/ControlPointPart.cs | 3 +++ .../Edit/Components/Timelines/Summary/Parts/MarkerPart.cs | 3 +++ .../Edit/Components/Timelines/Summary/Parts/TimelinePart.cs | 3 +++ .../Timelines/Summary/Visualisations/DurationVisualisation.cs | 3 +++ .../Timelines/Summary/Visualisations/PointVisualisation.cs | 3 +++ 7 files changed, 21 insertions(+) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs index 5680b85c08..8afec62a08 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs @@ -1,3 +1,6 @@ +// 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.Game.Beatmaps; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs index fefb3d5f10..721825270b 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -1,3 +1,6 @@ +// 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.Game.Beatmaps; using osu.Game.Beatmaps.Timing; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs index 12b3624123..e7f4f03f9b 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; 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 9c1587801e..d7aa0bcf96 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics; 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 30786a80ff..be3b116711 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System; using OpenTK; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs index 8926a2f55d..aee8e250c3 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs index bf52d28d97..9d7272808b 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; From 3b9c2d1d5fe929991f6e2ff1b7371e1e73e1a385 Mon Sep 17 00:00:00 2001 From: Sinnoh <30382015+Xinnoh@users.noreply.github.com> Date: Tue, 26 Sep 2017 16:50:12 +0800 Subject: [PATCH 35/53] changed description for hidden ctb doesn't have approach circles --- osu.Game.Rulesets.Catch/Mods/CatchMod.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchMod.cs b/osu.Game.Rulesets.Catch/Mods/CatchMod.cs index b0880d7e1d..66261b0f0f 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchMod.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchMod.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Mods public class CatchModHidden : ModHidden { - public override string Description => @"Play with no approach circles and fading notes for a slight score advantage."; + public override string Description => @"Play with fading notes for a slight score advantage."; public override double ScoreMultiplier => 1.06; } From c578509a20d35e730d4edde2f6ddee297dadd98e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Sep 2017 17:56:16 +0900 Subject: [PATCH 36/53] Bind to the screen Beatmap instead of the game-wide Beatmap --- .../Timelines/Summary/Parts/MarkerPart.cs | 62 +++++----- .../Timelines/Summary/Parts/TimelinePart.cs | 17 ++- .../Timelines/Summary/SummaryTimeline.cs | 115 ++++++++++-------- osu.Game/Screens/Edit/Editor.cs | 5 +- .../Visual/TestCaseEditorSummaryTimeline.cs | 34 ++++-- 5 files changed, 125 insertions(+), 108 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 d7aa0bcf96..115aa60446 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; -using osu.Game.Beatmaps; using osu.Game.Graphics; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts @@ -17,8 +16,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// internal class MarkerPart : TimelinePart { - private WorkingBeatmap beatmap; - private readonly Drawable marker; public MarkerPart() @@ -32,11 +29,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts marker.Colour = colours.Red; } - protected override void LoadBeatmap(WorkingBeatmap beatmap) - { - this.beatmap = beatmap; - } - protected override bool OnDragStart(InputState state) => true; protected override bool OnDragEnd(InputState state) => true; protected override bool OnDrag(InputState state) @@ -57,16 +49,22 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// The position in screen coordinates. private void seekToPosition(Vector2 screenPosition) { + if (Beatmap.Value == null) + return; + float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); - seekTo(markerPos / DrawWidth * beatmap.Track.Length); + seekTo(markerPos / DrawWidth * Beatmap.Value.Track.Length); } - private void seekTo(double time) => beatmap.Track.Seek(time); + private void seekTo(double time) => Beatmap.Value?.Track.Seek(time); protected override void Update() { base.Update(); - marker.X = (float)beatmap.Track.CurrentTime; + + if (Beatmap.Value == null) + return; + marker.X = (float)Beatmap.Value.Track.CurrentTime; } private class MarkerVisualisation : CompositeDrawable @@ -80,27 +78,27 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts AutoSizeAxes = Axes.X; InternalChildren = new Drawable[] { - new Triangle - { - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, - Scale = new Vector2(1, -1), - Size = new Vector2(10, 5), - }, - new Triangle - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Size = new Vector2(10, 5) - }, - new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = 2, - EdgeSmoothness = new Vector2(1, 0) - } + new Triangle + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + Scale = new Vector2(1, -1), + Size = new Vector2(10, 5), + }, + new Triangle + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(10, 5) + }, + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = 2, + EdgeSmoothness = new Vector2(1, 0) + } }; } 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 be3b116711..f5d4124b19 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -3,7 +3,7 @@ using System; using OpenTK; -using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -15,29 +15,26 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// internal abstract class TimelinePart : CompositeDrawable { + public Bindable Beatmap = new Bindable(); + private readonly Container timeline; protected TimelinePart() { AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); - } - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame) - { - osuGame.Beatmap.ValueChanged += b => + Beatmap.ValueChanged += b => { timeline.Clear(); timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); LoadBeatmap(b); }; - - timeline.RelativeChildSize = new Vector2((float)Math.Max(1, osuGame.Beatmap.Value.Track.Length), 1); - LoadBeatmap(osuGame.Beatmap); } protected void Add(Drawable visualisation) => timeline.Add(visualisation); - protected abstract void LoadBeatmap(WorkingBeatmap beatmap); + protected virtual void LoadBeatmap(WorkingBeatmap beatmap) + { + } } } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs index 0712936bf9..4d925f7584 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs @@ -3,9 +3,11 @@ using OpenTK; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; @@ -19,6 +21,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary private const float corner_radius = 5; private const float contents_padding = 15; + public Bindable Beatmap = new Bindable(); + private readonly Drawable background; private readonly Drawable timelineBar; @@ -28,67 +32,74 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary Masking = true; CornerRadius = corner_radius; + TimelinePart markerPart, controlPointPart, bookmarkPart, breakPart; + InternalChildren = new[] { - background = new Box { RelativeSizeAxes = Axes.Both }, - new Container + background = new Box { RelativeSizeAxes = Axes.Both }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, + Children = new[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, - Children = new[] + markerPart = new MarkerPart { RelativeSizeAxes = Axes.Both }, + controlPointPart = new ControlPointPart { - new MarkerPart { RelativeSizeAxes = Axes.Both }, - new ControlPointPart + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, + bookmarkPart = new BookmarkPart + { + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Height = 0.35f + }, + timelineBar = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.Both, - Height = 0.35f - }, - new BookmarkPart - { - Anchor = Anchor.Centre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Both, - Height = 0.35f - }, - timelineBar = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + new Circle { - new Circle - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, - Size = new Vector2(5) - }, - new Box - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - Height = 1, - EdgeSmoothness = new Vector2(0, 1), - }, - new Circle - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreLeft, - Size = new Vector2(5) - }, - } - }, - new BreakPart - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Height = 0.25f + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Size = new Vector2(5) + }, + new Box + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + Height = 1, + EdgeSmoothness = new Vector2(0, 1), + }, + new Circle + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, + Size = new Vector2(5) + }, } + }, + breakPart = new BreakPart + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.25f } } - }; + } + }; + + markerPart.Beatmap.BindTo(Beatmap); + controlPointPart.Beatmap.BindTo(Beatmap); + bookmarkPart.Beatmap.BindTo(Beatmap); + breakPart.Beatmap.BindTo(Beatmap); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 7afbbc33bb..3ffd7754c1 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -190,6 +190,7 @@ namespace osu.Game.Screens.Edit } }); + SummaryTimeline summaryTimeline; Add(new Container { Anchor = Anchor.BottomLeft, @@ -211,7 +212,7 @@ namespace osu.Game.Screens.Edit Spacing = new Vector2(10, 0), Children = new[] { - new SummaryTimeline + summaryTimeline = new SummaryTimeline { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -223,6 +224,8 @@ namespace osu.Game.Screens.Edit } } }); + + summaryTimeline.Beatmap.BindTo(Beatmap); } [BackgroundDependencyLoader] diff --git a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs index 59037ce151..c35355aefd 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorSummaryTimeline.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics; @@ -11,6 +10,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using OpenTK; using osu.Game.Screens.Edit.Components.Timelines.Summary; +using osu.Framework.Configuration; namespace osu.Game.Tests.Visual { @@ -21,40 +21,48 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { typeof(SummaryTimeline) }; + private readonly Bindable beatmap = new Bindable(); + public TestCaseEditorSummaryTimeline() { random = new Random(1337); - Add(new SummaryTimeline + SummaryTimeline summaryTimeline; + Add(summaryTimeline = new SummaryTimeline { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(500, 50) }); + + summaryTimeline.Beatmap.BindTo(beatmap); + + AddStep("New beatmap", newBeatmap); + + newBeatmap(); } - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame) + private void newBeatmap() { - var beatmap = new Beatmap(); + var b = new Beatmap(); for (int i = 0; i < random.Next(1, 10); i++) - beatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { Time = random.Next(0, length) }); + b.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { Time = random.Next(0, length) }); for (int i = 0; i < random.Next(1, 5); i++) - beatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { Time = random.Next(0, length) }); + b.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { Time = random.Next(0, length) }); for (int i = 0; i < random.Next(1, 5); i++) - beatmap.ControlPointInfo.EffectPoints.Add(new EffectControlPoint { Time = random.Next(0, length) }); + b.ControlPointInfo.EffectPoints.Add(new EffectControlPoint { Time = random.Next(0, length) }); for (int i = 0; i < random.Next(1, 5); i++) - beatmap.ControlPointInfo.SoundPoints.Add(new SoundControlPoint { Time = random.Next(0, length) }); + b.ControlPointInfo.SoundPoints.Add(new SoundControlPoint { Time = random.Next(0, length) }); - beatmap.BeatmapInfo.Bookmarks = new int[random.Next(10, 30)]; - for (int i = 0; i < beatmap.BeatmapInfo.Bookmarks.Length; i++) - beatmap.BeatmapInfo.Bookmarks[i] = random.Next(0, length); + b.BeatmapInfo.Bookmarks = new int[random.Next(10, 30)]; + for (int i = 0; i < b.BeatmapInfo.Bookmarks.Length; i++) + b.BeatmapInfo.Bookmarks[i] = random.Next(0, length); - osuGame.Beatmap.Value = new TestWorkingBeatmap(beatmap); + beatmap.Value = new TestWorkingBeatmap(b); } private class TestWorkingBeatmap : WorkingBeatmap From 10dbd68c1ee89be95c1844d62a8a698ab19c321d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Sep 2017 20:11:45 +0900 Subject: [PATCH 37/53] Simplify null check --- .../Edit/Components/Timelines/Summary/Parts/MarkerPart.cs | 4 +--- 1 file changed, 1 insertion(+), 3 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 115aa60446..d4a1177c4f 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -62,9 +62,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { base.Update(); - if (Beatmap.Value == null) - return; - marker.X = (float)Beatmap.Value.Track.CurrentTime; + marker.X = (float)(Beatmap.Value?.Track.CurrentTime ?? 0); } private class MarkerVisualisation : CompositeDrawable From 708632bca84655c894e24da82a225112a9727f14 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 10:06:36 +0800 Subject: [PATCH 38/53] Remove second unnecessary colour set --- .../Edit/Components/Timelines/Summary/Parts/MarkerPart.cs | 3 --- 1 file changed, 3 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 d4a1177c4f..290412d170 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -99,9 +99,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts } }; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.Red; } } } From eae29820c069324333e37024315e7699ecc4da1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 11:06:33 +0800 Subject: [PATCH 39/53] Fix marker being cleared each beatmap change --- .../Components/Timelines/Summary/Parts/BookmarkPart.cs | 1 + .../Edit/Components/Timelines/Summary/Parts/BreakPart.cs | 1 + .../Components/Timelines/Summary/Parts/ControlPointPart.cs | 2 ++ .../Edit/Components/Timelines/Summary/Parts/MarkerPart.cs | 7 ++++++- .../Components/Timelines/Summary/Parts/TimelinePart.cs | 2 +- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs index 8afec62a08..1793cb4334 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs @@ -15,6 +15,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { protected override void LoadBeatmap(WorkingBeatmap beatmap) { + base.LoadBeatmap(beatmap); foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks) Add(new BookmarkVisualisation(bookmark)); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs index 721825270b..004491d489 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -16,6 +16,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { protected override void LoadBeatmap(WorkingBeatmap beatmap) { + base.LoadBeatmap(beatmap); foreach (var breakPeriod in beatmap.Beatmap.Breaks) Add(new BreakVisualisation(breakPeriod)); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs index e7f4f03f9b..d230578e13 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -18,6 +18,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { protected override void LoadBeatmap(WorkingBeatmap beatmap) { + base.LoadBeatmap(beatmap); + ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo; cpi.TimingPoints.ForEach(addTimingPoint); 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 290412d170..228d32cee4 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; +using osu.Game.Beatmaps; using osu.Game.Graphics; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts @@ -61,10 +62,14 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected override void Update() { base.Update(); - marker.X = (float)(Beatmap.Value?.Track.CurrentTime ?? 0); } + protected override void LoadBeatmap(WorkingBeatmap beatmap) + { + // block base call so we don't clear our marker (can be reused on beatmap change). + } + private class MarkerVisualisation : CompositeDrawable { public MarkerVisualisation() 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 f5d4124b19..8071aa9c59 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -25,7 +25,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts Beatmap.ValueChanged += b => { - timeline.Clear(); timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); LoadBeatmap(b); }; @@ -35,6 +34,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected virtual void LoadBeatmap(WorkingBeatmap beatmap) { + timeline.Clear(); } } } From 7ad21d9a6d09ba31c90041264b60f5e61a7ab79d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 11:07:23 +0800 Subject: [PATCH 40/53] Simplify marker part construction --- .../Components/Timelines/Summary/Parts/MarkerPart.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 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 228d32cee4..2e7eaf99f8 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -17,17 +17,15 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// internal class MarkerPart : TimelinePart { - private readonly Drawable marker; - - public MarkerPart() - { - Add(marker = new MarkerVisualisation()); - } + private Drawable marker; [BackgroundDependencyLoader] private void load(OsuColour colours) { - marker.Colour = colours.Red; + Add(marker = new MarkerVisualisation + { + Colour = colours.Red + }); } protected override bool OnDragStart(InputState state) => true; From d5ed218488aac139909012bb0343a69edf357421 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 11:07:43 +0800 Subject: [PATCH 41/53] Fix timeline sizes being updated potentially before the track has a length --- .../Timelines/Summary/Parts/TimelinePart.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) 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 8071aa9c59..75651640d5 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -25,11 +25,31 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts Beatmap.ValueChanged += b => { - timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1); + updateRelativeChildSize(); LoadBeatmap(b); }; } + private void updateRelativeChildSize() + { + if (!Beatmap.Value.TrackLoaded) + { + timeline.RelativeChildSize = Vector2.One; + return; + } + + var track = Beatmap.Value.Track; + + if (!track.IsLoaded) + { + // the track may not be loaded completely (only has a length once it is). + Schedule(updateRelativeChildSize); + return; + } + + timeline.RelativeChildSize = new Vector2((float)Math.Max(1, track.Length), 1); + } + protected void Add(Drawable visualisation) => timeline.Add(visualisation); protected virtual void LoadBeatmap(WorkingBeatmap beatmap) From 3018d32b13ec02cfb531ea38b9f237927105c564 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 11:22:47 +0800 Subject: [PATCH 42/53] Close BeatmapSetOverlay when clicking outside of it --- osu.Game/Overlays/BeatmapSetOverlay.cs | 3 +++ osu.Game/Overlays/UserProfileOverlay.cs | 1 + 2 files changed, 4 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 8e28ad33c5..7a4c6338a1 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -23,6 +23,9 @@ namespace osu.Game.Overlays private readonly Header header; private readonly Info info; + // receive input outside our bounds so we can trigger a close event on ourselves. + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + public BeatmapSetOverlay() { FirstWaveColour = OsuColour.Gray(0.4f); diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index f03ef3f1ed..088b0a1335 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -34,6 +34,7 @@ namespace osu.Game.Overlays public const float CONTENT_X_MARGIN = 50; + // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; protected override bool OnClick(InputState state) From bbc990a6fd8be9ade98a74a7ad5c5bd19866660d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 11:26:56 +0800 Subject: [PATCH 43/53] Assign a name to individual import tests to avoid file contention --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index be48c997ea..9277310efc 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps.IO public void TestImportWhenClosed() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. - using (HeadlessGameHost host = new HeadlessGameHost()) + using (HeadlessGameHost host = new HeadlessGameHost("TestImportWhenClosed")) { var osu = loadOsu(host); @@ -69,7 +69,7 @@ namespace osu.Game.Tests.Beatmaps.IO public void TestImportWhenFileOpen() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. - using (HeadlessGameHost host = new HeadlessGameHost()) + using (HeadlessGameHost host = new HeadlessGameHost("TestImportWhenFileOpen")) { var osu = loadOsu(host); From 05c6829debe91a01c5a3b9ba0afe60b20f4a1773 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 12:18:24 +0800 Subject: [PATCH 44/53] Move all APIAccess State changes to the local thread Previously changes to the state were triggering events like Logout, which could get things into a bad state. --- osu.Game/Online/API/APIAccess.cs | 55 ++++++++++---------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 57f5c54a18..00abeea444 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -101,18 +101,16 @@ namespace osu.Game.Online.API } break; case APIState.Offline: + case APIState.Connecting: //work to restore a connection... if (!HasLogin) { - //OsuGame.Scheduler.Add(() => { OsuGame.ShowLogin(); }); - State = APIState.Offline; - Thread.Sleep(500); + Thread.Sleep(50); continue; } - if (State < APIState.Connecting) - State = APIState.Connecting; + State = APIState.Connecting; if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, Password)) { @@ -125,7 +123,8 @@ namespace osu.Game.Online.API var userReq = new GetUserRequest(); - userReq.Success += u => { + userReq.Success += u => + { LocalUser.Value = u; //we're connected! State = APIState.Online; @@ -133,16 +132,14 @@ namespace osu.Game.Online.API }; if (!handleRequest(userReq)) - { - State = APIState.Failing; continue; - } break; } //hard bail if we can't get a valid access token. if (authentication.RequestAccessToken() == null) { + Logout(false); State = APIState.Offline; continue; } @@ -162,20 +159,12 @@ namespace osu.Game.Online.API } } - private void clearCredentials() - { - Username = null; - Password = null; - } - public void Login(string username, string password) { Debug.Assert(State == APIState.Offline); Username = username; Password = password; - - State = APIState.Connecting; } /// @@ -204,7 +193,7 @@ namespace osu.Game.Online.API switch (statusCode) { case HttpStatusCode.Unauthorized: - State = APIState.Offline; + Logout(false); return true; case HttpStatusCode.RequestTimeout: failureCount++; @@ -215,6 +204,7 @@ namespace osu.Game.Online.API return false; State = APIState.Failing; + flushQueue(); return true; } @@ -242,26 +232,14 @@ namespace osu.Game.Online.API state = value; - switch (state) - { - case APIState.Failing: - case APIState.Offline: - flushQueue(); - break; - } - if (oldState != newState) { - //OsuGame.Scheduler.Add(delegate + log.Add($@"We just went {newState}!"); + Scheduler.Add(delegate { - //NotificationOverlay.ShowMessage($@"We just went {newState}!", newState == APIState.Online ? Color4.YellowGreen : Color4.OrangeRed, 5000); - log.Add($@"We just went {newState}!"); - Scheduler.Add(delegate - { - components.ForEach(c => c.APIStateChanged(this, newState)); - OnStateChange?.Invoke(oldState, newState); - }); - } + components.ForEach(c => c.APIStateChanged(this, newState)); + OnStateChange?.Invoke(oldState, newState); + }); } } } @@ -292,11 +270,12 @@ namespace osu.Game.Online.API } } - public void Logout() + public void Logout(bool clearUsername = true) { - clearCredentials(); + flushQueue(); + if (clearUsername) Username = null; + Password = null; authentication.Clear(); - State = APIState.Offline; LocalUser.Value = createGuestUser(); } From ec50834e98c2ac2a3ca3010fda4227a4555d2a89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 12:23:48 +0800 Subject: [PATCH 45/53] Load osu!direct overlay to "newest maps" tab by default --- osu.Game/Overlays/Direct/Header.cs | 2 +- osu.Game/Overlays/DirectOverlay.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Direct/Header.cs b/osu.Game/Overlays/Direct/Header.cs index 2c50fb453f..77743a3a4b 100644 --- a/osu.Game/Overlays/Direct/Header.cs +++ b/osu.Game/Overlays/Direct/Header.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Direct public Header() { - Tabs.Current.Value = DirectTab.Search; + Tabs.Current.Value = DirectTab.NewestMaps; Tabs.Current.TriggerChange(); } } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 9c07e1087f..5b5003b30f 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -251,7 +251,7 @@ namespace osu.Game.Overlays if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return; - getSetsRequest = new GetBeatmapSetsRequest(currentQuery, + getSetsRequest = new GetBeatmapSetsRequest(currentQuery.Value ?? string.Empty, ((FilterControl)Filter).Ruleset.Value, Filter.DisplayStyleControl.Dropdown.Current.Value, Filter.Tabs.Current.Value); //todo: sort direction (?) From faad3fc7d39291f59a6feb679b585224bf9e82dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 12:40:32 +0800 Subject: [PATCH 46/53] Arbitrarily move colour assignment --- .../Timelines/Summary/Parts/MarkerPart.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 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 2e7eaf99f8..0bdd081907 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -17,15 +17,11 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// internal class MarkerPart : TimelinePart { - private Drawable marker; + private readonly Drawable marker; - [BackgroundDependencyLoader] - private void load(OsuColour colours) + public MarkerPart() { - Add(marker = new MarkerVisualisation - { - Colour = colours.Red - }); + Add(marker = new MarkerVisualisation()); } protected override bool OnDragStart(InputState state) => true; @@ -102,6 +98,9 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts } }; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) => Colour = colours.Red; } } } From e64860ad45b44dfe27d36c1389d30af79e498e17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 12:46:34 +0800 Subject: [PATCH 47/53] Fix test case not working as expected --- .../Timelines/Summary/Parts/TimelinePart.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) 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 75651640d5..378ce78c67 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -32,22 +32,15 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts private void updateRelativeChildSize() { - if (!Beatmap.Value.TrackLoaded) + // the track may not be loaded completely (only has a length once it is). + if (!Beatmap.Value.Track.IsLoaded) { timeline.RelativeChildSize = Vector2.One; - return; - } - - var track = Beatmap.Value.Track; - - if (!track.IsLoaded) - { - // the track may not be loaded completely (only has a length once it is). Schedule(updateRelativeChildSize); return; } - timeline.RelativeChildSize = new Vector2((float)Math.Max(1, track.Length), 1); + timeline.RelativeChildSize = new Vector2((float)Math.Max(1, Beatmap.Value.Track.Length), 1); } protected void Add(Drawable visualisation) => timeline.Add(visualisation); From 4a95d64239eb10b207604a9aaaa45a79c3024653 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 13:06:57 +0800 Subject: [PATCH 48/53] Fix yellow line in login overlay not following size correctly Also allows right click context menu to correctly extrude beyond the local masking. --- osu.Game/Overlays/LoginOverlay.cs | 49 ++++++++++++++++++------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index 58b259fcbb..0a47637589 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Overlays.Settings.Sections.General; using OpenTK.Graphics; @@ -28,35 +29,43 @@ namespace osu.Game.Overlays { Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.6f, - }, new OsuContextMenuContainer { Width = 360, AutoSizeAxes = Axes.Y, - Masking = true, - AutoSizeDuration = transition_time, - AutoSizeEasing = Easing.OutQuint, Children = new Drawable[] { - settingsSection = new LoginSettings - { - Padding = new MarginPadding(10), - RequestHide = Hide, - }, new Box { - RelativeSizeAxes = Axes.X, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Height = 3, - Colour = colours.Yellow, - Alpha = 1, + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Masking = true, + AutoSizeDuration = transition_time, + AutoSizeEasing = Easing.OutQuint, + Children = new Drawable[] + { + settingsSection = new LoginSettings + { + Padding = new MarginPadding(10), + RequestHide = Hide, + }, + new Box + { + RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Height = 3, + Colour = colours.Yellow, + Alpha = 1, + }, + } + } } } }; From a17cc04cdedc2455b19563977d3bf6b971de532e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 13:16:17 +0800 Subject: [PATCH 49/53] Make APIAccess's state only privately settable --- osu.Game/Online/API/APIAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 00abeea444..bb72efb750 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -225,7 +225,7 @@ namespace osu.Game.Online.API public APIState State { get { return state; } - set + private set { APIState oldState = state; APIState newState = value; From 990ef3ca56d05cb424657545aa1770687ba63d4e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Sep 2017 14:38:12 +0800 Subject: [PATCH 50/53] Make import tests more resilient to race condition failures Also centralises wait-or-assert logic. --- .../Beatmaps/IO/ImportBeatmapTest.cs | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 9277310efc..35bebf2d4f 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Beatmaps.IO ensureLoaded(osu); - Assert.IsFalse(File.Exists(temp)); + waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000); } } @@ -61,14 +61,13 @@ namespace osu.Game.Tests.Beatmaps.IO ensureLoaded(osu); - Assert.IsFalse(File.Exists(temp)); + waitForOrAssert(() => !File.Exists(temp), "Temporary still exists after IPC import", 5000); } } [Test] public void TestImportWhenFileOpen() { - //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new HeadlessGameHost("TestImportWhenFileOpen")) { var osu = loadOsu(host); @@ -101,8 +100,7 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = new OsuGameBase(); Task.Run(() => host.Run(osu)); - while (!osu.IsLoaded) - Thread.Sleep(1); + waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time"); return osu; } @@ -113,30 +111,17 @@ namespace osu.Game.Tests.Beatmaps.IO var store = osu.Dependencies.Get(); - Action waitAction = () => - { - while (!(resultSets = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526)).Any()) - Thread.Sleep(50); - }; - - Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout), - @"BeatmapSet did not import to the database in allocated time."); + waitForOrAssert(() => (resultSets = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526)).Any(), + @"BeatmapSet did not import to the database in allocated time.", timeout); //ensure we were stored to beatmap database backing... - Assert.IsTrue(resultSets.Count() == 1, $@"Incorrect result count found ({resultSets.Count()} but should be 1)."); IEnumerable resultBeatmaps = null; //if we don't re-check here, the set will be inserted but the beatmaps won't be present yet. - waitAction = () => - { - while ((resultBeatmaps = store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() != 12) - Thread.Sleep(50); - }; - - Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout), - @"Beatmaps did not import to the database in allocated time"); + waitForOrAssert(() => (resultBeatmaps = store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() == 12, + @"Beatmaps did not import to the database in allocated time", timeout); var set = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526).First(); @@ -160,5 +145,11 @@ namespace osu.Game.Tests.Beatmaps.IO beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); } + + private void waitForOrAssert(Func result, string failureMessage, int timeout = 60000) + { + Action waitAction = () => { while (!result()) Thread.Sleep(20); }; + Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout), failureMessage); + } } } From 4eaf6b4b94ac2850a15f1b9a775dba8201d7ebae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Sep 2017 00:08:42 +0800 Subject: [PATCH 51/53] Remove single usage of dynamic and stop referencing Microsoft.CSharp.dll --- osu.Game/Online/API/Requests/GetScoresRequest.cs | 2 +- osu.Game/Rulesets/Scoring/Score.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageScore.cs | 4 ++-- osu.Game/osu.Game.csproj | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 13bd8d288d..537fce2548 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -80,7 +80,7 @@ namespace osu.Game.Online.API.Requests } [JsonProperty(@"statistics")] - private Dictionary jsonStats + private Dictionary jsonStats { set { diff --git a/osu.Game/Rulesets/Scoring/Score.cs b/osu.Game/Rulesets/Scoring/Score.cs index 7f053ec1c5..c4ffa4e93c 100644 --- a/osu.Game/Rulesets/Scoring/Score.cs +++ b/osu.Game/Rulesets/Scoring/Score.cs @@ -38,6 +38,6 @@ namespace osu.Game.Rulesets.Scoring public DateTimeOffset Date; - public Dictionary Statistics = new Dictionary(); + public Dictionary Statistics = new Dictionary(); } } diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index bf406ff912..b01410cff5 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -186,9 +186,9 @@ namespace osu.Game.Screens.Ranking private class DrawableScoreStatistic : Container { - private readonly KeyValuePair statistic; + private readonly KeyValuePair statistic; - public DrawableScoreStatistic(KeyValuePair statistic) + public DrawableScoreStatistic(KeyValuePair statistic) { this.statistic = statistic; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a6860e4e8c..bdca48ccdf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -124,7 +124,6 @@ $(SolutionDir)\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll True - $(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll True From 75cd6eeb1c1b740cc62e713066e6d805f899bbe9 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Thu, 28 Sep 2017 14:20:19 +0300 Subject: [PATCH 52/53] Clean up Wave in WaveOverlayContainer --- osu.Game/Overlays/WaveOverlayContainer.cs | 37 +++-------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 4f9783a762..77c532350b 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Containers; @@ -165,10 +164,8 @@ namespace osu.Game.Overlays wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y)); } - private class Wave : Container, IStateful + private class Wave : VisibilityContainer { - public event Action StateChanged; - public float FinalPosition; public Wave() @@ -183,13 +180,7 @@ namespace osu.Game.Overlays Radius = 20f, }; - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - }, - }; + Child = new Box { RelativeSizeAxes = Axes.Both }; } protected override void Update() @@ -201,28 +192,8 @@ namespace osu.Game.Overlays Height = Parent.Parent.DrawSize.Y * 1.5f; } - private Visibility state; - - public Visibility State - { - get { return state; } - set - { - state = value; - - switch (value) - { - case Visibility.Hidden: - this.MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide); - break; - case Visibility.Visible: - this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show); - break; - } - - StateChanged?.Invoke(State); - } - } + protected override void PopIn() => this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show); + protected override void PopOut() => this.MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide); } } } From ca1f96208a00864209a8fa760a978fe75a217e0d Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Thu, 28 Sep 2017 14:31:02 +0300 Subject: [PATCH 53/53] Fix TestCaseContextMenu not being updated inline with previous changes --- osu.Game/Tests/Visual/TestCaseContextMenu.cs | 43 ++++++++++---------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/osu.Game/Tests/Visual/TestCaseContextMenu.cs b/osu.Game/Tests/Visual/TestCaseContextMenu.cs index 28aae1f5b9..91a766f8c7 100644 --- a/osu.Game/Tests/Visual/TestCaseContextMenu.cs +++ b/osu.Game/Tests/Visual/TestCaseContextMenu.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using OpenTK; using OpenTK.Graphics; +using osu.Game.Graphics.Cursor; namespace osu.Game.Tests.Visual { @@ -23,32 +24,32 @@ namespace osu.Game.Tests.Visual public TestCaseContextMenu() { - Add(container = new MyContextMenuContainer + Add(new OsuContextMenuContainer { - Size = new Vector2(200), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Box + container = new MyContextMenuContainer { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Green, - } - } - }); - - Add(new AnotherContextMenuContainer - { - Size = new Vector2(200), - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Children = new Drawable[] - { - new Box + Size = new Vector2(200), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Green, + } + }, + new AnotherContextMenuContainer { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Red, + Size = new Vector2(200), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Red, + } } } });