From d879b96d9f70869d001b4dfc62481eab93591390 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Jun 2018 13:43:56 +0900 Subject: [PATCH 01/10] Implement storyboard samples --- .../Drawables/DrawableStoryboardSample.cs | 68 +++++++++++++++++++ osu.Game/Storyboards/StoryboardSample.cs | 9 +-- 2 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs new file mode 100644 index 0000000000..9a539072d0 --- /dev/null +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.IO; +using osu.Framework.Allocation; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; + +namespace osu.Game.Storyboards.Drawables +{ + public class DrawableStoryboardSample : Component + { + /// + /// The amount of time allowable beyond the start time of the sample, for the sample to start. + /// + private const double allowable_late_start = 100; + + private readonly StoryboardSample sample; + private SampleChannel channel; + + public override bool RemoveWhenNotAlive => false; + + public DrawableStoryboardSample(StoryboardSample sample) + { + this.sample = sample; + LifetimeStart = sample.Time; + } + + [BackgroundDependencyLoader] + private void load(IBindableBeatmap beatmap) + { + // Try first with the full name, then attempt with no path + channel = beatmap.Value.Skin.GetSample(sample.Path) ?? beatmap.Value.Skin.GetSample(Path.ChangeExtension(sample.Path, null)); + + if (channel != null) + channel.Volume.Value = sample.Volume / 100; + } + + protected override void Update() + { + base.Update(); + + if (Time.Current < sample.Time) + { + // We've rewound before the start time of the sample + channel?.Stop(); + + // In the case that the user fast-forwards to a point far beyond the start time of the sample, + // we want to be able to fall into the if-conditional below (therefore we must not have a life time end) + LifetimeStart = sample.Time; + LifetimeEnd = double.MaxValue; + } + else if (Time.Current - Time.Elapsed < sample.Time) + { + // We've passed the start time of the sample. We only play the sample if we're within an allowable range + // from the sample's start, to reduce layering if we've been fast-forwarded far into the future + if (Time.Current - sample.Time < allowable_late_start) + channel?.Play(); + + // In the case that the user rewinds to a point far behind the start time of the sample, + // we want to be able to fall into the if-conditional above (therefore we must not have a life time start) + LifetimeStart = double.MinValue; + LifetimeEnd = sample.Time; + } + } + } +} diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index d0555493a6..c34a39a7bf 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -2,14 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using System; +using osu.Game.Storyboards.Drawables; namespace osu.Game.Storyboards { public class StoryboardSample : IStoryboardElement { public string Path { get; set; } - public bool IsDrawable => false; + public bool IsDrawable => true; public double Time; public float Volume; @@ -21,9 +21,6 @@ public StoryboardSample(string path, double time, float volume) Volume = volume; } - public Drawable CreateDrawable() - { - throw new InvalidOperationException(); - } + public Drawable CreateDrawable() => new DrawableStoryboardSample(this); } } From 157ca8b2a44d27e4f10f8330d302a4bbcd3b4118 Mon Sep 17 00:00:00 2001 From: Ethan Yang Date: Sun, 8 Jul 2018 11:47:39 -0700 Subject: [PATCH 02/10] Change osu key bindings --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index ce80537b93..b8ba1e2945 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -31,8 +31,8 @@ public class OsuRuleset : Ruleset public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { - new KeyBinding(InputKey.Z, OsuAction.LeftButton), - new KeyBinding(InputKey.X, OsuAction.RightButton), + new KeyBinding(InputKey.A, OsuAction.LeftButton), + new KeyBinding(InputKey.S, OsuAction.RightButton), new KeyBinding(InputKey.MouseLeft, OsuAction.LeftButton), new KeyBinding(InputKey.MouseRight, OsuAction.RightButton), }; From 7f315d79c27cea08e07a8c321cb69094232ab19e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Jul 2018 13:06:03 +0900 Subject: [PATCH 03/10] Fix pixel gap in user profile when scrolling --- osu.Game/Overlays/Profile/ProfileHeader.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index c5510d3d70..9d09836d25 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -158,6 +158,13 @@ public ProfileHeader(User user) } } }, + new Box // this is a temporary workaround for incorrect masking behaviour of FillMode.Fill used in UserCoverBackground (see https://github.com/ppy/osu-framework/issues/1675) + { + RelativeSizeAxes = Axes.X, + Height = 1, + Y = cover_height, + Colour = OsuColour.Gray(34), + }, infoTextLeft = new LinkFlowContainer(t => t.TextSize = 14) { X = UserProfileOverlay.CONTENT_X_MARGIN, From 7157428882545b367e4bc975556a9361a620e735 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Jul 2018 02:59:00 +0900 Subject: [PATCH 04/10] Fix import failure of beatmap sets containing duplicate beatmap difficulties --- osu.Game/Beatmaps/BeatmapManager.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index fd24e4297b..fc4d43080e 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -92,7 +92,7 @@ protected override void Populate(BeatmapSetInfo model, ArchiveReader archive) // by setting the model here, we can update the noline set id below. b.BeatmapSet = model; - fetchAndPopulateOnlineIDs(b); + fetchAndPopulateOnlineIDs(b, model.Beatmaps); } // check if a set already exists with the same online id, delete if it does. @@ -396,9 +396,10 @@ private List createBeatmapDifficulties(ArchiveReader reader) /// Query the API to populate mising OnlineBeatmapID / OnlineBeatmapSetID properties. /// /// The beatmap to populate. + /// The other beatmaps contained within this set. /// Whether to re-query if the provided beatmap already has populated values. /// True if population was successful. - private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, bool force = false) + private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, IEnumerable otherBeatmaps, bool force = false) { if (!force && beatmap.OnlineBeatmapID != null && beatmap.BeatmapSet.OnlineBeatmapSetID != null) return true; @@ -418,6 +419,12 @@ private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, bool force = false) Logger.Log($"Successfully mapped to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.", LoggingTarget.Database); + if (otherBeatmaps.Any(b => b.OnlineBeatmapID == res.OnlineBeatmapID)) + { + Logger.Log("Another beatmap in the same set already mapped to this ID. We'll skip adding it this time.", LoggingTarget.Database); + return false; + } + beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; beatmap.OnlineBeatmapID = res.OnlineBeatmapID; return true; From 159b26509bf4e0be715afce89a603e80ce82f841 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 17:15:06 +0900 Subject: [PATCH 05/10] Improve visuals of difficulty icons --- .../Drawables/DifficultyColouredContainer.cs | 4 +-- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 28 +++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs index 025ab0037f..7d00c35862 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs @@ -9,14 +9,14 @@ namespace osu.Game.Beatmaps.Drawables { - public class DifficultyColouredContainer : Container, IHasAccentColour + public abstract class DifficultyColouredContainer : Container, IHasAccentColour { public Color4 AccentColour { get; set; } private readonly BeatmapInfo beatmap; private OsuColour palette; - public DifficultyColouredContainer(BeatmapInfo beatmap) + protected DifficultyColouredContainer(BeatmapInfo beatmap) { this.beatmap = beatmap; } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 42c98aef24..24604711d4 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -3,10 +3,14 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Beatmaps.Drawables { @@ -14,7 +18,8 @@ public class DifficultyIcon : DifficultyColouredContainer { private readonly BeatmapInfo beatmap; - public DifficultyIcon(BeatmapInfo beatmap) : base(beatmap) + public DifficultyIcon(BeatmapInfo beatmap) + : base(beatmap) { if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); @@ -28,16 +33,29 @@ private void load() { Children = new Drawable[] { - new SpriteIcon + new CircularContainer { + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.84f), Anchor = Anchor.Centre, Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = AccentColour, - Icon = FontAwesome.fa_circle + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.08f), + Type = EdgeEffectType.Shadow, + Radius = 5, + }, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = AccentColour, + }, }, new ConstrainedIconContainer { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) Icon = beatmap.Ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.fa_question_circle_o } From 2d602c0e3c4e599564ef165f3f4159aec185af65 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 18:23:12 +0900 Subject: [PATCH 06/10] Add todo regarding playback skip logic --- osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index 9a539072d0..cdec8c042f 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -41,6 +41,7 @@ protected override void Update() { base.Update(); + // TODO: this logic will need to be consolidated with other game samples like hitsounds. if (Time.Current < sample.Time) { // We've rewound before the start time of the sample From 3f44f5c60e8fca9f82abbb37d03b359500214134 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 18:34:38 +0900 Subject: [PATCH 07/10] Remove migration log output --- osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.cs b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.cs index 98ce5def08..1f3c015614 100644 --- a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.cs +++ b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.cs @@ -8,7 +8,6 @@ public partial class UpdateTaikoDefaultBindings : Migration protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.Sql("DELETE FROM KeyBinding WHERE RulesetID = 1"); - Logger.Log("osu!taiko bindings have been reset due to new defaults", LoggingTarget.Runtime, LogLevel.Important); } protected override void Down(MigrationBuilder migrationBuilder) From 96eb44425b26910f69594d8808beda2acb636380 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 20:32:22 +0900 Subject: [PATCH 08/10] Fix informational overlays not hiding when user toggles other overlay views Closes #3014. --- osu.Game/OsuGame.cs | 48 ++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b654e5d53f..557b6e4469 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -19,6 +19,7 @@ using System.Threading; using System.Threading.Tasks; using osu.Framework.Audio; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Platform; @@ -322,24 +323,6 @@ protected override void LoadComplete() dependencies.Cache(notifications); dependencies.Cache(dialogOverlay); - // ensure only one of these overlays are open at once. - var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct }; - overlays.AddRange(singleDisplayOverlays); - - foreach (var overlay in singleDisplayOverlays) - { - overlay.StateChanged += state => - { - if (state == Visibility.Hidden) return; - - foreach (var c in singleDisplayOverlays) - { - if (c == overlay) continue; - c.State = Visibility.Hidden; - } - }; - } - var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications }; overlays.AddRange(singleDisplaySideOverlays); @@ -348,12 +331,7 @@ protected override void LoadComplete() overlay.StateChanged += state => { if (state == Visibility.Hidden) return; - - foreach (var c in singleDisplaySideOverlays) - { - if (c == overlay) continue; - c.State = Visibility.Hidden; - } + singleDisplaySideOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); }; } @@ -366,12 +344,24 @@ protected override void LoadComplete() overlay.StateChanged += state => { if (state == Visibility.Hidden) return; + informationalOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); + }; + } - foreach (var c in informationalOverlays) - { - if (c == overlay) continue; - c.State = Visibility.Hidden; - } + // ensure only one of these overlays are open at once. + var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct }; + overlays.AddRange(singleDisplayOverlays); + + foreach (var overlay in singleDisplayOverlays) + { + overlay.StateChanged += state => + { + // informational overlays should be dismissed on a show or hide of a full overlay. + informationalOverlays.ForEach(o => o.Hide()); + + if (state == Visibility.Hidden) return; + + singleDisplayOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); }; } From 3308f8f823e0844c0f62868a6de5717c0e1daab3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 20:37:49 +0900 Subject: [PATCH 09/10] Fix focused overlays not blocking select action --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 1d832d1c54..2e2e018fcb 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -69,10 +69,13 @@ protected override bool OnClick(InputState state) public virtual bool OnPressed(GlobalAction action) { - if (action == GlobalAction.Back) + switch (action) { - State = Visibility.Hidden; - return true; + case GlobalAction.Back: + State = Visibility.Hidden; + return true; + case GlobalAction.Select: + return true; } return false; From 67e7e371ccae21b8c3d7b0c0cc5dec51236d2faa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 20:40:49 +0900 Subject: [PATCH 10/10] Also block keyboard completely --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 2e2e018fcb..0dc6297ad2 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -22,8 +22,11 @@ public class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrack protected virtual bool PlaySamplesOnStateChange => true; + protected override bool BlockPassThroughKeyboard => true; + private PreviewTrackManager previewTrackManager; + protected readonly Bindable OverlayActivationMode = new Bindable(OverlayActivation.All); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)