From dd5cc592501115d2584ae032cf97a0b6dd939315 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Fri, 23 Mar 2018 22:53:06 +0300 Subject: [PATCH 01/28] Introduce 'Capture menu cursor' setting --- osu.Game/Configuration/OsuConfigManager.cs | 4 +++- osu.Game/Graphics/ScreenshotManager.cs | 3 +++ .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 70260b349e..d55cd6bf2c 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -84,6 +84,7 @@ namespace osu.Game.Configuration Set(OsuSetting.Version, string.Empty); Set(OsuSetting.ScreenshotFormat, ScreenshotFormat.Jpg); + Set(OsuSetting.ScreenshotCaptureMenuCursor, false); } public OsuConfigManager(Storage storage) : base(storage) @@ -128,6 +129,7 @@ namespace osu.Game.Configuration ShowConvertedBeatmaps, SpeedChangeVisualisation, Skin, - ScreenshotFormat + ScreenshotFormat, + ScreenshotCaptureMenuCursor } } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index b0cd997837..68ac6e9df4 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -22,6 +22,8 @@ namespace osu.Game.Graphics public class ScreenshotManager : Container, IKeyBindingHandler, IHandleGlobalInput { private Bindable screenshotFormat; + private Bindable captureMenuCursor; + private GameHost host; private Storage storage; private NotificationOverlay notificationOverlay; @@ -36,6 +38,7 @@ namespace osu.Game.Graphics this.notificationOverlay = notificationOverlay; screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); + captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); shutter = audio.Sample.Get("UI/shutter"); } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index fa57a85454..e124d4cf7e 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -30,6 +30,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { LabelText = "Screenshot format", Bindable = config.GetBindable(OsuSetting.ScreenshotFormat) + }, + new SettingsCheckbox + { + LabelText = "Capture menu cursor", + Bindable = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor) } }; } From e91d24f31a9f1059b98650a2a0ccdce5e11fe476 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 24 Mar 2018 12:53:01 +0300 Subject: [PATCH 02/28] Use ScreenshotCaptureMenuCursor in ScreenshotManager --- osu.Game/Graphics/ScreenshotManager.cs | 23 ++++++++++++++++++++++- osu.Game/OsuGameBase.cs | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 68ac6e9df4..7d50a298ec 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -4,15 +4,19 @@ using System; using System.Drawing.Imaging; using System.IO; +using System.Threading; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Configuration; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Platform; using osu.Game.Configuration; +using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -29,13 +33,15 @@ namespace osu.Game.Graphics private NotificationOverlay notificationOverlay; private SampleChannel shutter; + private CursorContainer menuCursorContainer; [BackgroundDependencyLoader] - private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio) + private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio, CursorOverrideContainer cursorOverrideContainer) { this.host = host; this.storage = storage.GetStorageForDirectory(@"screenshots"); this.notificationOverlay = notificationOverlay; + this.menuCursorContainer = cursorOverrideContainer.Cursor; screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); @@ -60,6 +66,18 @@ namespace osu.Game.Graphics public async void TakeScreenshotAsync() { + var menuCursorWasHidden = false; + if (!captureMenuCursor.Value && menuCursorContainer.State == Visibility.Visible) + { + menuCursorContainer.ToggleVisibility(); + await Task.Run(() => + { + while (menuCursorContainer.ActiveCursor.Alpha > 0) + Thread.Sleep(1); + }); + menuCursorWasHidden = true; + } + using (var bitmap = await host.TakeScreenshotAsync()) { var fileName = getFileName(); @@ -89,6 +107,9 @@ namespace osu.Game.Graphics } }); } + + if (menuCursorWasHidden) + menuCursorContainer.ToggleVisibility(); } private string getFileName() diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 54a279e977..ac5e300f16 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -214,7 +214,7 @@ namespace osu.Game GlobalActionContainer globalBinding; - CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both }; + dependencies.Cache(CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both }); CursorOverrideContainer.Child = globalBinding = new GlobalActionContainer(this) { RelativeSizeAxes = Axes.Both, From 458594d24d19511882960d2105b930cd09801659 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Tue, 27 Mar 2018 18:03:57 +0300 Subject: [PATCH 03/28] Qualifier 'this.' is redundant --- osu.Game/Graphics/ScreenshotManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 7d50a298ec..434a9d0a72 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -41,7 +41,7 @@ namespace osu.Game.Graphics this.host = host; this.storage = storage.GetStorageForDirectory(@"screenshots"); this.notificationOverlay = notificationOverlay; - this.menuCursorContainer = cursorOverrideContainer.Cursor; + menuCursorContainer = cursorOverrideContainer.Cursor; screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); From 640be621ac4e178f1e1b6f24283e13719e7f7ef6 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sat, 7 Apr 2018 13:29:46 +0300 Subject: [PATCH 04/28] Handle multiple song previews playing in different beatmap categories on profile --- .../Beatmaps/PaginatedBeatmapContainer.cs | 4 ++++ .../Profile/Sections/BeatmapsSection.cs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index da070d1cc2..637985e3cd 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using OpenTK; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -19,6 +20,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps private DirectPanel currentlyPlaying; + public event Action BeatmapAdded; + public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string header, string missing = "None... yet.") : base(user, header, missing) { @@ -63,6 +66,7 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps currentlyPlaying = panel; }; + BeatmapAdded?.Invoke(panel); } }; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index 760054716f..928ac677a4 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Game.Online.API.Requests; +using osu.Game.Overlays.Direct; using osu.Game.Overlays.Profile.Sections.Beatmaps; namespace osu.Game.Overlays.Profile.Sections @@ -12,6 +14,8 @@ namespace osu.Game.Overlays.Profile.Sections public override string Identifier => "beatmaps"; + private DirectPanel currentlyPlaying; + public BeatmapsSection() { Children = new[] @@ -21,6 +25,19 @@ namespace osu.Game.Overlays.Profile.Sections new PaginatedBeatmapContainer(BeatmapSetType.Unranked, User, "Pending Beatmaps"), new PaginatedBeatmapContainer(BeatmapSetType.Graveyard, User, "Graveyarded Beatmaps"), }; + + foreach (var beatmapContainer in Children.OfType()) + { + beatmapContainer.BeatmapAdded += panel => panel.PreviewPlaying.ValueChanged += isPlaying => + { + if (!isPlaying) return; + + if (currentlyPlaying != null && currentlyPlaying != panel) + currentlyPlaying.PreviewPlaying.Value = false; + + currentlyPlaying = panel; + }; + } } } } From 6cdfaffcf7c6da6beda62118397af17dcf243e44 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Wed, 11 Apr 2018 16:19:21 +0300 Subject: [PATCH 05/28] PaginatedBeatmapContainer.BeganPlayingPreview --- .../Beatmaps/PaginatedBeatmapContainer.cs | 12 +++++++++--- .../Overlays/Profile/Sections/BeatmapsSection.cs | 15 +++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 637985e3cd..6e22d51958 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps private DirectPanel currentlyPlaying; - public event Action BeatmapAdded; + public event Action BeganPlayingPreview; public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string header, string missing = "None... yet.") : base(user, header, missing) @@ -61,16 +61,22 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps { if (!isPlaying) return; + BeganPlayingPreview?.Invoke(this); if (currentlyPlaying != null && currentlyPlaying != panel) - currentlyPlaying.PreviewPlaying.Value = false; + StopPlayingPreview(); currentlyPlaying = panel; }; - BeatmapAdded?.Invoke(panel); } }; Api.Queue(req); } + + public void StopPlayingPreview() + { + if (currentlyPlaying != null) + currentlyPlaying.PreviewPlaying.Value = false; + } } } diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index 928ac677a4..f1f2421237 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -26,16 +26,15 @@ namespace osu.Game.Overlays.Profile.Sections new PaginatedBeatmapContainer(BeatmapSetType.Graveyard, User, "Graveyarded Beatmaps"), }; - foreach (var beatmapContainer in Children.OfType()) + foreach (var paginatedBeatmapContainer in Children.OfType()) { - beatmapContainer.BeatmapAdded += panel => panel.PreviewPlaying.ValueChanged += isPlaying => + paginatedBeatmapContainer.BeganPlayingPreview += (BeatmapContainer) => { - if (!isPlaying) return; - - if (currentlyPlaying != null && currentlyPlaying != panel) - currentlyPlaying.PreviewPlaying.Value = false; - - currentlyPlaying = panel; + foreach (var bc in Children.OfType()) + { + if (bc != BeatmapContainer) + bc.StopPlayingPreview(); + } }; } } From 6a8f568f66b9e8bc14f2ce892f6c31110ecf96ff Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Wed, 11 Apr 2018 16:32:58 +0300 Subject: [PATCH 06/28] BeatmapContainer -> beatmapContainer --- osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index f1f2421237..a0d37ffe71 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -28,11 +28,11 @@ namespace osu.Game.Overlays.Profile.Sections foreach (var paginatedBeatmapContainer in Children.OfType()) { - paginatedBeatmapContainer.BeganPlayingPreview += (BeatmapContainer) => + paginatedBeatmapContainer.BeganPlayingPreview += beatmapContainer => { foreach (var bc in Children.OfType()) { - if (bc != BeatmapContainer) + if (bc != beatmapContainer) bc.StopPlayingPreview(); } }; From d7812ab12e37e70abc948fb437dec84d96f784d1 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Wed, 11 Apr 2018 21:22:52 +0300 Subject: [PATCH 07/28] CursorOverrideContainer.ShowMenuCursor --- .../Graphics/Cursor/CursorOverrideContainer.cs | 9 +++++++++ osu.Game/Graphics/ScreenshotManager.cs | 16 ++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs index 0fae4579fa..73fa065919 100644 --- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -21,6 +21,7 @@ namespace osu.Game.Graphics.Cursor /// Whether any cursors can be displayed. /// public bool CanShowCursor = true; + public bool ShowMenuCursor = true; public CursorContainer Cursor { get; } public bool ProvidingUserCursor => true; @@ -53,6 +54,14 @@ namespace osu.Game.Graphics.Cursor return; } + if (currentTarget?.Cursor is MenuCursor) + { + if (ShowMenuCursor && currentTarget?.Cursor.State == Visibility.Hidden) + currentTarget?.Cursor?.Show(); + else if (!ShowMenuCursor && currentTarget?.Cursor.State == Visibility.Visible) + currentTarget?.Cursor?.Hide(); + } + var newTarget = inputManager.HoveredDrawables.OfType().FirstOrDefault(t => t.ProvidingUserCursor) ?? this; if (currentTarget == newTarget) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 434a9d0a72..e918ff016e 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -11,7 +11,6 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Configuration; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Platform; @@ -33,7 +32,7 @@ namespace osu.Game.Graphics private NotificationOverlay notificationOverlay; private SampleChannel shutter; - private CursorContainer menuCursorContainer; + private CursorOverrideContainer cursorOverrideContainer; [BackgroundDependencyLoader] private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio, CursorOverrideContainer cursorOverrideContainer) @@ -41,7 +40,7 @@ namespace osu.Game.Graphics this.host = host; this.storage = storage.GetStorageForDirectory(@"screenshots"); this.notificationOverlay = notificationOverlay; - menuCursorContainer = cursorOverrideContainer.Cursor; + this.cursorOverrideContainer = cursorOverrideContainer; screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); @@ -66,16 +65,14 @@ namespace osu.Game.Graphics public async void TakeScreenshotAsync() { - var menuCursorWasHidden = false; - if (!captureMenuCursor.Value && menuCursorContainer.State == Visibility.Visible) + if (!captureMenuCursor.Value) { - menuCursorContainer.ToggleVisibility(); + cursorOverrideContainer.ShowMenuCursor = false; await Task.Run(() => { - while (menuCursorContainer.ActiveCursor.Alpha > 0) + while (cursorOverrideContainer.Cursor.ActiveCursor.Alpha > 0) Thread.Sleep(1); }); - menuCursorWasHidden = true; } using (var bitmap = await host.TakeScreenshotAsync()) @@ -108,8 +105,7 @@ namespace osu.Game.Graphics }); } - if (menuCursorWasHidden) - menuCursorContainer.ToggleVisibility(); + cursorOverrideContainer.ShowMenuCursor = true; } private string getFileName() From 0bede523817eacea0b2f6656cb3f800cb1e87991 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Wed, 28 Mar 2018 17:57:15 -0300 Subject: [PATCH 08/28] Move the waves portion of WaveOverlayContainer to WaveContainer to allow usage in other places. --- .../Visual/TestCaseWaveContainer.cs | 54 ++++++ osu.Game/Graphics/Containers/WaveContainer.cs | 167 +++++++++++++++++ osu.Game/Overlays/BeatmapSetOverlay.cs | 12 +- osu.Game/Overlays/DirectOverlay.cs | 8 +- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 31 ++- osu.Game/Overlays/SocialOverlay.cs | 8 +- osu.Game/Overlays/UserProfileOverlay.cs | 12 +- osu.Game/Overlays/WaveOverlayContainer.cs | 176 +----------------- 8 files changed, 261 insertions(+), 207 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseWaveContainer.cs create mode 100644 osu.Game/Graphics/Containers/WaveContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseWaveContainer.cs b/osu.Game.Tests/Visual/TestCaseWaveContainer.cs new file mode 100644 index 0000000000..e332777053 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseWaveContainer.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseWaveContainer : OsuTestCase + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + WaveContainer container; + Add(container = new WaveContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(400), + FirstWaveColour = colours.Red, + SecondWaveColour = colours.Green, + ThirdWaveColour = colours.Blue, + FourthWaveColour = colours.Pink, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.5f), + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + TextSize = 20, + Text = @"Wave Container", + }, + }, + }); + + AddStep(@"show", container.Show); + AddStep(@"hide", container.Hide); + } + } +} diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs new file mode 100644 index 0000000000..f112a6477e --- /dev/null +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -0,0 +1,167 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using OpenTK.Graphics; + +namespace osu.Game.Graphics.Containers +{ + public class WaveContainer : VisibilityContainer + { + public const float APPEAR_DURATION = 800; + public const float DISAPPEAR_DURATION = 500; + + private const Easing easing_show = Easing.OutSine; + private const Easing easing_hide = Easing.InSine; + + private readonly Wave firstWave; + private readonly Wave secondWave; + private readonly Wave thirdWave; + private readonly Wave fourthWave; + + private readonly Container wavesContainer; + private readonly Container contentContainer; + + protected override Container Content => contentContainer; + + public Color4 FirstWaveColour + { + get => firstWave.Colour; + set => firstWave.Colour = value; + } + + public Color4 SecondWaveColour + { + get => secondWave.Colour; + set => secondWave.Colour = value; + } + + public Color4 ThirdWaveColour + { + get => thirdWave.Colour; + set => thirdWave.Colour = value; + } + + public Color4 FourthWaveColour + { + get => fourthWave.Colour; + set => fourthWave.Colour = value; + } + + public WaveContainer() + { + Masking = true; + + AddInternal(wavesContainer = new Container + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Masking = true, + Children = new[] + { + firstWave = new Wave + { + Rotation = 13, + FinalPosition = -930, + }, + secondWave = new Wave + { + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + Rotation = -7, + FinalPosition = -560, + }, + thirdWave = new Wave + { + Rotation = 4, + FinalPosition = -390, + }, + fourthWave = new Wave + { + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + Rotation = -2, + FinalPosition = -220, + }, + }, + }); + + AddInternal(contentContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }); + } + + protected override void PopIn() + { + foreach (var w in wavesContainer.Children) + w.State = Visibility.Visible; + + this.FadeIn(100, Easing.OutQuint); + contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint); + + this.FadeIn(100, Easing.OutQuint); + } + + protected override void PopOut() + { + this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); + contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In); + + foreach (var w in wavesContainer.Children) + w.State = Visibility.Hidden; + + this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + // This is done as an optimization, such that invisible parts of the waves + // are masked away, and thus do not consume fill rate. + wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y)); + } + + private class Wave : VisibilityContainer + { + public float FinalPosition; + + protected override bool StartHidden => true; + + public Wave() + { + RelativeSizeAxes = Axes.X; + Width = 1.5f; + Masking = true; + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(50), + Radius = 20f, + }; + + Child = new Box { RelativeSizeAxes = Axes.Both }; + } + + protected override void Update() + { + base.Update(); + + // We can not use RelativeSizeAxes for Height, because the height + // of our parent diminishes as the content moves up. + Height = Parent.Parent.DrawSize.Y * 1.5f; + } + + 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); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index f0f8a6ef10..448ff2d7c9 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -40,10 +40,10 @@ namespace osu.Game.Overlays public BeatmapSetOverlay() { - FirstWaveColour = OsuColour.Gray(0.4f); - SecondWaveColour = OsuColour.Gray(0.3f); - ThirdWaveColour = OsuColour.Gray(0.2f); - FourthWaveColour = OsuColour.Gray(0.1f); + Waves.FirstWaveColour = OsuColour.Gray(0.4f); + Waves.SecondWaveColour = OsuColour.Gray(0.3f); + Waves.ThirdWaveColour = OsuColour.Gray(0.2f); + Waves.FourthWaveColour = OsuColour.Gray(0.1f); Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; @@ -123,14 +123,14 @@ namespace osu.Game.Overlays protected override void PopIn() { base.PopIn(); - FadeEdgeEffectTo(0.25f, APPEAR_DURATION, Easing.In); + FadeEdgeEffectTo(0.25f, WaveContainer.APPEAR_DURATION, Easing.In); } protected override void PopOut() { base.PopOut(); header.Details.StopPreview(); - FadeEdgeEffectTo(0, DISAPPEAR_DURATION, Easing.Out); + FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } protected override bool OnClick(InputState state) diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 3f1aa04c36..bfd2d94287 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -89,10 +89,10 @@ namespace osu.Game.Overlays // osu!direct colours are not part of the standard palette - FirstWaveColour = OsuColour.FromHex(@"19b0e2"); - SecondWaveColour = OsuColour.FromHex(@"2280a2"); - ThirdWaveColour = OsuColour.FromHex(@"005774"); - FourthWaveColour = OsuColour.FromHex(@"003a4e"); + Waves.FirstWaveColour = OsuColour.FromHex(@"19b0e2"); + Waves.SecondWaveColour = OsuColour.FromHex(@"2280a2"); + Waves.ThirdWaveColour = OsuColour.FromHex(@"005774"); + Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e"); ScrollFlow.Children = new Drawable[] { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index d8c95da94f..bf91d3f508 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -18,6 +18,7 @@ using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; using osu.Game.Rulesets; using osu.Game.Graphics.UserInterface; @@ -113,14 +114,14 @@ namespace osu.Game.Overlays.Mods { base.PopOut(); - footerContainer.MoveToX(footerContainer.DrawSize.X, DISAPPEAR_DURATION, Easing.InSine); - footerContainer.FadeOut(DISAPPEAR_DURATION, Easing.InSine); + footerContainer.MoveToX(footerContainer.DrawSize.X, WaveContainer.DISAPPEAR_DURATION, Easing.InSine); + footerContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine); foreach (ModSection section in ModSectionsContainer.Children) { - section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), DISAPPEAR_DURATION, Easing.InSine); - section.ButtonsContainer.MoveToX(100f, DISAPPEAR_DURATION, Easing.InSine); - section.ButtonsContainer.FadeOut(DISAPPEAR_DURATION, Easing.InSine); + section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), WaveContainer.DISAPPEAR_DURATION, Easing.InSine); + section.ButtonsContainer.MoveToX(100f, WaveContainer.DISAPPEAR_DURATION, Easing.InSine); + section.ButtonsContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine); } } @@ -128,14 +129,14 @@ namespace osu.Game.Overlays.Mods { base.PopIn(); - footerContainer.MoveToX(0, APPEAR_DURATION, Easing.OutQuint); - footerContainer.FadeIn(APPEAR_DURATION, Easing.OutQuint); + footerContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + footerContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); foreach (ModSection section in ModSectionsContainer.Children) { - section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), APPEAR_DURATION, Easing.OutQuint); - section.ButtonsContainer.MoveToX(0, APPEAR_DURATION, Easing.OutQuint); - section.ButtonsContainer.FadeIn(APPEAR_DURATION, Easing.OutQuint); + section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), WaveContainer.APPEAR_DURATION, Easing.OutQuint); + section.ButtonsContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + section.ButtonsContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); } } @@ -181,14 +182,12 @@ namespace osu.Game.Overlays.Mods public ModSelectOverlay() { - FirstWaveColour = OsuColour.FromHex(@"19b0e2"); - SecondWaveColour = OsuColour.FromHex(@"2280a2"); - ThirdWaveColour = OsuColour.FromHex(@"005774"); - FourthWaveColour = OsuColour.FromHex(@"003a4e"); + Waves.FirstWaveColour = OsuColour.FromHex(@"19b0e2"); + Waves.SecondWaveColour = OsuColour.FromHex(@"2280a2"); + Waves.ThirdWaveColour = OsuColour.FromHex(@"005774"); + Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e"); Height = 510; - Content.RelativeSizeAxes = Axes.X; - Content.AutoSizeAxes = Axes.Y; Children = new Drawable[] { new Container diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index ddcb933e5d..295c2965a0 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -48,10 +48,10 @@ namespace osu.Game.Overlays public SocialOverlay() { - FirstWaveColour = OsuColour.FromHex(@"cb5fa0"); - SecondWaveColour = OsuColour.FromHex(@"b04384"); - ThirdWaveColour = OsuColour.FromHex(@"9b2b6e"); - FourthWaveColour = OsuColour.FromHex(@"6d214d"); + Waves.FirstWaveColour = OsuColour.FromHex(@"cb5fa0"); + Waves.SecondWaveColour = OsuColour.FromHex(@"b04384"); + Waves.ThirdWaveColour = OsuColour.FromHex(@"9b2b6e"); + Waves.FourthWaveColour = OsuColour.FromHex(@"6d214d"); Add(loading = new LoadingAnimation()); diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index aed0a6d7c6..08646cd044 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -35,10 +35,10 @@ namespace osu.Game.Overlays public UserProfileOverlay() { - FirstWaveColour = OsuColour.Gray(0.4f); - SecondWaveColour = OsuColour.Gray(0.3f); - ThirdWaveColour = OsuColour.Gray(0.2f); - FourthWaveColour = OsuColour.Gray(0.1f); + Waves.FirstWaveColour = OsuColour.Gray(0.4f); + Waves.SecondWaveColour = OsuColour.Gray(0.3f); + Waves.ThirdWaveColour = OsuColour.Gray(0.2f); + Waves.FourthWaveColour = OsuColour.Gray(0.1f); RelativeSizeAxes = Axes.Both; RelativePositionAxes = Axes.Both; @@ -64,13 +64,13 @@ namespace osu.Game.Overlays protected override void PopIn() { base.PopIn(); - FadeEdgeEffectTo(0.5f, APPEAR_DURATION, Easing.In); + FadeEdgeEffectTo(0.5f, WaveContainer.APPEAR_DURATION, Easing.In); } protected override void PopOut() { base.PopOut(); - FadeEdgeEffectTo(0, DISAPPEAR_DURATION, Easing.Out); + FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } public void ShowUser(long userId) diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 074d83a5ad..8a9065eccb 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -1,203 +1,37 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; -using System; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; namespace osu.Game.Overlays { public abstract class WaveOverlayContainer : OsuFocusedOverlayContainer { - protected const float APPEAR_DURATION = 800; - protected const float DISAPPEAR_DURATION = 500; - - private const Easing easing_show = Easing.OutSine; - private const Easing easing_hide = Easing.InSine; - - private readonly Wave firstWave; - private readonly Wave secondWave; - private readonly Wave thirdWave; - private readonly Wave fourthWave; - - private readonly Container wavesContainer; - - private readonly Container contentContainer; + protected readonly WaveContainer Waves; protected override bool BlockPassThroughKeyboard => true; - - protected override Container Content => contentContainer; - - protected Color4 FirstWaveColour - { - get - { - return firstWave.Colour; - } - set - { - if (firstWave.Colour == value) return; - firstWave.Colour = value; - } - } - - protected Color4 SecondWaveColour - { - get - { - return secondWave.Colour; - } - set - { - if (secondWave.Colour == value) return; - secondWave.Colour = value; - } - } - - protected Color4 ThirdWaveColour - { - get - { - return thirdWave.Colour; - } - set - { - if (thirdWave.Colour == value) return; - thirdWave.Colour = value; - } - } - - protected Color4 FourthWaveColour - { - get - { - return fourthWave.Colour; - } - set - { - if (fourthWave.Colour == value) return; - fourthWave.Colour = value; - } - } + protected override Container Content => Waves; protected WaveOverlayContainer() { - Masking = true; - - AddInternal(wavesContainer = new Container - { - RelativeSizeAxes = Axes.X, - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Masking = true, - Children = new[] - { - firstWave = new Wave - { - Rotation = 13, - FinalPosition = -930, - }, - secondWave = new Wave - { - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, - Rotation = -7, - FinalPosition = -560, - }, - thirdWave = new Wave - { - Rotation = 4, - FinalPosition = -390, - }, - fourthWave = new Wave - { - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, - Rotation = -2, - FinalPosition = -220, - }, - }, - }); - - AddInternal(contentContainer = new Container + AddInternal(Waves = new WaveContainer { RelativeSizeAxes = Axes.Both, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, }); } protected override void PopIn() { base.PopIn(); - - foreach (var w in wavesContainer.Children) - w.State = Visibility.Visible; - - this.FadeIn(100, Easing.OutQuint); - contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint); - - this.FadeIn(100, Easing.OutQuint); + Waves.Show(); } protected override void PopOut() { base.PopOut(); - - this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); - contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In); - - foreach (var w in wavesContainer.Children) - w.State = Visibility.Hidden; - - this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - // This is done as an optimization, such that invisible parts of the waves - // are masked away, and thus do not consume fill rate. - wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y)); - } - - private class Wave : VisibilityContainer - { - public float FinalPosition; - - protected override bool StartHidden => true; - - public Wave() - { - RelativeSizeAxes = Axes.X; - Width = 1.5f; - Masking = true; - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(50), - Radius = 20f, - }; - - Child = new Box { RelativeSizeAxes = Axes.Both }; - } - - protected override void Update() - { - base.Update(); - - // We can not use RelativeSizeAxes for Height, because the height - // of our parent diminishes as the content moves up. - Height = Parent.Parent.DrawSize.Y * 1.5f; - } - - 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); + Waves.Hide(); } } } From ebe36f061292b658cc6eb87dc1e5720fe53f2948 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Apr 2018 17:27:10 +0900 Subject: [PATCH 09/28] Instantly hide cursor for required frames while taking screenshot --- .../Cursor/CursorOverrideContainer.cs | 20 ++++++------ osu.Game/Graphics/Cursor/MenuCursor.cs | 3 ++ osu.Game/Graphics/ScreenshotManager.cs | 32 +++++++++++++++---- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs index 73fa065919..58d566c34b 100644 --- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -21,16 +21,22 @@ namespace osu.Game.Graphics.Cursor /// Whether any cursors can be displayed. /// public bool CanShowCursor = true; - public bool ShowMenuCursor = true; - public CursorContainer Cursor { get; } + public bool ShowMenuCursor + { + get => cursor.ShowCursor; + set => cursor.ShowCursor = value; + } + + private readonly MenuCursor cursor; + public CursorContainer Cursor => cursor; public bool ProvidingUserCursor => true; public CursorOverrideContainer() { AddRangeInternal(new Drawable[] { - Cursor = new MenuCursor { State = Visibility.Hidden }, + cursor = new MenuCursor { State = Visibility.Hidden }, content = new Container { RelativeSizeAxes = Axes.Both } }); } @@ -54,14 +60,6 @@ namespace osu.Game.Graphics.Cursor return; } - if (currentTarget?.Cursor is MenuCursor) - { - if (ShowMenuCursor && currentTarget?.Cursor.State == Visibility.Hidden) - currentTarget?.Cursor?.Show(); - else if (!ShowMenuCursor && currentTarget?.Cursor.State == Visibility.Visible) - currentTarget?.Cursor?.Hide(); - } - var newTarget = inputManager.HoveredDrawables.OfType().FirstOrDefault(t => t.ProvidingUserCursor) ?? this; if (currentTarget == newTarget) diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index bdee7d289d..4edac3e050 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -18,6 +18,9 @@ namespace osu.Game.Graphics.Cursor { public class MenuCursor : CursorContainer { + public bool ShowCursor = true; + public override bool IsPresent => ShowCursor && base.IsPresent; + protected override Drawable CreateCursor() => new Cursor(); private Bindable cursorRotate; diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index e918ff016e..0d77af8f81 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Platform; +using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; @@ -63,20 +64,31 @@ namespace osu.Game.Graphics public bool OnReleased(GlobalAction action) => false; - public async void TakeScreenshotAsync() + private volatile int screenShotTasks; + + public async Task TakeScreenshotAsync() => Task.Run(async () => { + Interlocked.Increment(ref screenShotTasks); + if (!captureMenuCursor.Value) { cursorOverrideContainer.ShowMenuCursor = false; - await Task.Run(() => - { - while (cursorOverrideContainer.Cursor.ActiveCursor.Alpha > 0) - Thread.Sleep(1); - }); + + // We need to wait for at most 3 draw nodes to be drawn, following which we can be assured at least one DrawNode has been generated/drawn with the set value + const int frames_to_wait = 3; + + int framesWaited = 0; + ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => framesWaited++, 0, true); + while (framesWaited < frames_to_wait) + Thread.Sleep(10); + + waitDelegate.Cancel(); } using (var bitmap = await host.TakeScreenshotAsync()) { + Interlocked.Decrement(ref screenShotTasks); + var fileName = getFileName(); if (fileName == null) return; @@ -104,8 +116,14 @@ namespace osu.Game.Graphics } }); } + }); - cursorOverrideContainer.ShowMenuCursor = true; + protected override void Update() + { + base.Update(); + + if (Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) + cursorOverrideContainer.ShowMenuCursor = true; } private string getFileName() From 826a8552e598dc55cc59d11982fdcda470011f70 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Apr 2018 17:30:02 +0900 Subject: [PATCH 10/28] Reword options item to include "screenshot" --- osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index e124d4cf7e..3060cfdea9 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, new SettingsCheckbox { - LabelText = "Capture menu cursor", + LabelText = "Show menu cursor in screenshots", Bindable = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor) } }; From 2e5bbe707499549c225b7a5f55f463fb535835ae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Apr 2018 17:36:38 +0900 Subject: [PATCH 11/28] Don't expose CursorOverrideContainer via DI + internalise access --- .../Graphics/Cursor/CursorOverrideContainer.cs | 16 +++++----------- osu.Game/Graphics/ScreenshotManager.cs | 14 +++++++++----- osu.Game/OsuGame.cs | 2 +- osu.Game/OsuGameBase.cs | 2 +- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs index 58d566c34b..810847349a 100644 --- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -20,23 +20,17 @@ namespace osu.Game.Graphics.Cursor /// /// Whether any cursors can be displayed. /// - public bool CanShowCursor = true; - - public bool ShowMenuCursor - { - get => cursor.ShowCursor; - set => cursor.ShowCursor = value; - } - - private readonly MenuCursor cursor; - public CursorContainer Cursor => cursor; + internal bool CanShowCursor = true; + internal readonly MenuCursor MenuCursor; + + public CursorContainer Cursor => MenuCursor; public bool ProvidingUserCursor => true; public CursorOverrideContainer() { AddRangeInternal(new Drawable[] { - cursor = new MenuCursor { State = Visibility.Hidden }, + MenuCursor = new MenuCursor { State = Visibility.Hidden }, content = new Container { RelativeSizeAxes = Axes.Both } }); } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 0d77af8f81..1f4b5cee3e 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -33,15 +33,19 @@ namespace osu.Game.Graphics private NotificationOverlay notificationOverlay; private SampleChannel shutter; - private CursorOverrideContainer cursorOverrideContainer; + private readonly MenuCursor menuCursor; + + public ScreenshotManager(MenuCursor menuCursor) + { + this.menuCursor = menuCursor; + } [BackgroundDependencyLoader] - private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio, CursorOverrideContainer cursorOverrideContainer) + private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio) { this.host = host; this.storage = storage.GetStorageForDirectory(@"screenshots"); this.notificationOverlay = notificationOverlay; - this.cursorOverrideContainer = cursorOverrideContainer; screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); @@ -72,7 +76,7 @@ namespace osu.Game.Graphics if (!captureMenuCursor.Value) { - cursorOverrideContainer.ShowMenuCursor = false; + menuCursor.ShowCursor = false; // We need to wait for at most 3 draw nodes to be drawn, following which we can be assured at least one DrawNode has been generated/drawn with the set value const int frames_to_wait = 3; @@ -123,7 +127,7 @@ namespace osu.Game.Graphics base.Update(); if (Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) - cursorOverrideContainer.ShowMenuCursor = true; + menuCursor.ShowCursor = true; } private string getFileName() diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 89447b8ed6..b95def9c73 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -239,7 +239,7 @@ namespace osu.Game loadComponentSingleFile(volume = new VolumeOverlay(), overlayContent.Add); loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); - loadComponentSingleFile(new ScreenshotManager(), Add); + loadComponentSingleFile(new ScreenshotManager(CursorOverrideContainer.MenuCursor), Add); //overlay elements loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index ac5e300f16..54a279e977 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -214,7 +214,7 @@ namespace osu.Game GlobalActionContainer globalBinding; - dependencies.Cache(CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both }); + CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both }; CursorOverrideContainer.Child = globalBinding = new GlobalActionContainer(this) { RelativeSizeAxes = Axes.Both, From 0235eba9deef9a4e00b7214ff5ea94174b384220 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Apr 2018 17:50:59 +0900 Subject: [PATCH 12/28] Make TakeScreenshotAsync await on the internal task --- osu.Game/Graphics/Cursor/CursorOverrideContainer.cs | 2 +- osu.Game/Graphics/ScreenshotManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs index 810847349a..30e9b36252 100644 --- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.Cursor /// internal bool CanShowCursor = true; internal readonly MenuCursor MenuCursor; - + public CursorContainer Cursor => MenuCursor; public bool ProvidingUserCursor => true; diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 1f4b5cee3e..d7746647c4 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -70,7 +70,7 @@ namespace osu.Game.Graphics private volatile int screenShotTasks; - public async Task TakeScreenshotAsync() => Task.Run(async () => + public async Task TakeScreenshotAsync() => await Task.Run(async () => { Interlocked.Increment(ref screenShotTasks); From cd594ce12bcc4960d943d05f2af5a2835ae84f3f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Apr 2018 20:46:01 +0900 Subject: [PATCH 13/28] BDL cache screenshot manager --- osu.Game/OsuGame.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b95def9c73..b65e9de663 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -56,6 +56,8 @@ namespace osu.Game private BeatmapSetOverlay beatmapSetOverlay; + private ScreenshotManager screenshotManager; + public virtual Storage GetStorageForStableInstall() => null; private Intro intro @@ -125,6 +127,7 @@ namespace osu.Game } dependencies.CacheAs(this); + dependencies.Cache(screenshotManager = new ScreenshotManager()); // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); @@ -239,7 +242,8 @@ namespace osu.Game loadComponentSingleFile(volume = new VolumeOverlay(), overlayContent.Add); loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); - loadComponentSingleFile(new ScreenshotManager(CursorOverrideContainer.MenuCursor), Add); + + loadComponentSingleFile(screenshotManager, Add); //overlay elements loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); From 34adb2527c2be60ac304cdf13726b24002e557b4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Apr 2018 21:12:33 +0900 Subject: [PATCH 14/28] A lot more protection from outsiders --- .../Cursor/CursorOverrideContainer.cs | 5 ++--- osu.Game/Graphics/Cursor/MenuCursor.cs | 22 ++++++++++++------- osu.Game/Graphics/ScreenshotManager.cs | 21 +++++++++--------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs index 30e9b36252..7dffc6491a 100644 --- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -21,16 +21,15 @@ namespace osu.Game.Graphics.Cursor /// Whether any cursors can be displayed. /// internal bool CanShowCursor = true; - internal readonly MenuCursor MenuCursor; - public CursorContainer Cursor => MenuCursor; + public CursorContainer Cursor { get; } public bool ProvidingUserCursor => true; public CursorOverrideContainer() { AddRangeInternal(new Drawable[] { - MenuCursor = new MenuCursor { State = Visibility.Hidden }, + Cursor = new MenuCursor { State = Visibility.Hidden }, content = new Container { RelativeSizeAxes = Axes.Both } }); } diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 4edac3e050..b0b15c8572 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -12,14 +12,15 @@ using osu.Framework.Input; using osu.Game.Configuration; using System; using System.Diagnostics; +using JetBrains.Annotations; using osu.Framework.Graphics.Textures; namespace osu.Game.Graphics.Cursor { public class MenuCursor : CursorContainer { - public bool ShowCursor = true; - public override bool IsPresent => ShowCursor && base.IsPresent; + private readonly IBindable screenshotCursorVisibility = new Bindable(true); + public override bool IsPresent => screenshotCursorVisibility.Value && base.IsPresent; protected override Drawable CreateCursor() => new Cursor(); @@ -28,6 +29,17 @@ namespace osu.Game.Graphics.Cursor private bool startRotation; + private ScreenshotManager screenshotManager; + + [BackgroundDependencyLoader(true)] + private void load([NotNull] OsuConfigManager config, [CanBeNull] ScreenshotManager screenshotManager) + { + cursorRotate = config.GetBindable(OsuSetting.CursorRotation); + + if (screenshotManager != null) + screenshotCursorVisibility.BindTo(screenshotManager.CursorVisibility); + } + protected override bool OnMouseMove(InputState state) { if (cursorRotate && dragging) @@ -107,12 +119,6 @@ namespace osu.Game.Graphics.Cursor ActiveCursor.ScaleTo(0.6f, 250, Easing.In); } - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - cursorRotate = config.GetBindable(OsuSetting.CursorRotation); - } - public class Cursor : Container { private Container cursorContainer; diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index d7746647c4..fb111f2786 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -16,7 +16,6 @@ using osu.Framework.Input.Bindings; using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Configuration; -using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -25,6 +24,14 @@ namespace osu.Game.Graphics { public class ScreenshotManager : Container, IKeyBindingHandler, IHandleGlobalInput { + private readonly BindableBool cursorVisibility = new BindableBool(true); + + /// + /// Invoked when screenshots are or have finished being taken, to control whether cursors should be visible. + /// If cursors should not be visible, cursors have 3 frames to hide themselves. + /// + public IBindable CursorVisibility => cursorVisibility; + private Bindable screenshotFormat; private Bindable captureMenuCursor; @@ -33,12 +40,6 @@ namespace osu.Game.Graphics private NotificationOverlay notificationOverlay; private SampleChannel shutter; - private readonly MenuCursor menuCursor; - - public ScreenshotManager(MenuCursor menuCursor) - { - this.menuCursor = menuCursor; - } [BackgroundDependencyLoader] private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio) @@ -76,7 +77,7 @@ namespace osu.Game.Graphics if (!captureMenuCursor.Value) { - menuCursor.ShowCursor = false; + cursorVisibility.Value = false; // We need to wait for at most 3 draw nodes to be drawn, following which we can be assured at least one DrawNode has been generated/drawn with the set value const int frames_to_wait = 3; @@ -126,8 +127,8 @@ namespace osu.Game.Graphics { base.Update(); - if (Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) - menuCursor.ShowCursor = true; + if (cursorVisibility == false && Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) + cursorVisibility.Value = true; } private string getFileName() From cf658335725ee15bacafee32b438336dd3d52123 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Apr 2018 21:15:08 +0900 Subject: [PATCH 15/28] Reword xmldoc --- osu.Game/Graphics/ScreenshotManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 0626bc98b7..90580c50df 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -27,7 +27,7 @@ namespace osu.Game.Graphics private readonly BindableBool cursorVisibility = new BindableBool(true); /// - /// Invoked when screenshots are or have finished being taken, to control whether cursors should be visible. + /// Changed when screenshots are being or have finished being taken, to control whether cursors should be visible. /// If cursors should not be visible, cursors have 3 frames to hide themselves. /// public IBindable CursorVisibility => cursorVisibility; From 3ece54e1c33a709efba79df82369e3be6006987e Mon Sep 17 00:00:00 2001 From: FreezyLemon Date: Sat, 14 Apr 2018 00:08:54 +0200 Subject: [PATCH 16/28] make buttons only accept input when expanded both other states are "inactive"/invisible so should never accept keyboard input --- osu.Game/Screens/Menu/Button.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 33e423a558..542ddd2c92 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -222,7 +222,7 @@ namespace osu.Game.Screens.Menu boxHoverLayer.FadeOut(800, Easing.OutExpo); } - public override bool HandleKeyboardInput => state != ButtonState.Exploded; + public override bool HandleKeyboardInput => state == ButtonState.Expanded; public override bool HandleMouseInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f; protected override void Update() From 069d48ac14a29ac0bf20647a5cafe815500697f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 15 Apr 2018 15:29:00 +0900 Subject: [PATCH 17/28] Remove unused variable --- osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index ae3c10228b..78a3bd7468 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Game.Online.API.Requests; -using osu.Game.Overlays.Direct; using osu.Game.Overlays.Profile.Sections.Beatmaps; namespace osu.Game.Overlays.Profile.Sections @@ -14,8 +13,6 @@ namespace osu.Game.Overlays.Profile.Sections public override string Identifier => "beatmaps"; - private DirectPanel currentlyPlaying; - public BeatmapsSection() { Children = new[] From fd54ae3c87eab25df96bb90990ff1f8dead1d6df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 15 Apr 2018 16:12:42 +0900 Subject: [PATCH 18/28] Simplify logic --- osu.Game/Overlays/Direct/PlayButton.cs | 3 ++- .../Beatmaps/PaginatedBeatmapContainer.cs | 17 +++++++++-------- .../Profile/Sections/BeatmapsSection.cs | 7 ++----- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 9f36d5acb7..44e24d8157 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -173,8 +173,9 @@ namespace osu.Game.Overlays.Direct if (trackLoader != d) return; Preview = d?.Preview; - Playing.TriggerChange(); + updatePreviewTrack(Playing); loading = false; + Add(trackLoader); }); } diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 31433e64b3..3fec9d8697 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -59,13 +59,13 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps panel.PreviewPlaying.ValueChanged += isPlaying => { - if (!isPlaying) return; + StopPlayingPreview(); - BeganPlayingPreview?.Invoke(this); - if (currentlyPlaying != null && currentlyPlaying != panel) - StopPlayingPreview(); - - currentlyPlaying = panel; + if (isPlaying) + { + BeganPlayingPreview?.Invoke(this); + currentlyPlaying = panel; + } }; } }; @@ -75,8 +75,9 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps public void StopPlayingPreview() { - if (currentlyPlaying != null) - currentlyPlaying.PreviewPlaying.Value = false; + if (currentlyPlaying == null) return; + currentlyPlaying.PreviewPlaying.Value = false; + currentlyPlaying = null; } } } diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index 78a3bd7468..92abd20f93 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -25,13 +25,10 @@ namespace osu.Game.Overlays.Profile.Sections foreach (var paginatedBeatmapContainer in Children.OfType()) { - paginatedBeatmapContainer.BeganPlayingPreview += beatmapContainer => + paginatedBeatmapContainer.BeganPlayingPreview += _ => { foreach (var bc in Children.OfType()) - { - if (bc != beatmapContainer) - bc.StopPlayingPreview(); - } + bc.StopPlayingPreview(); }; } } From c095fe1919c3d8e5d7f2262f726896accdf84457 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Apr 2018 00:21:03 +0900 Subject: [PATCH 19/28] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index eb6362eaf1..f155804739 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit eb6362eaf1317b0fa27b2c9e559bd9a0f1ce357c +Subproject commit f155804739b8bf6e8e04cbdbadca88618d325a32 From 96ef564f442d4d94742cd00ac7cf33f5ba8e8552 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Apr 2018 00:25:05 +0900 Subject: [PATCH 20/28] Remove unused field --- osu.Game/Graphics/Cursor/MenuCursor.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 575e2979cd..5f57fb76b0 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -29,8 +29,6 @@ namespace osu.Game.Graphics.Cursor private bool startRotation; - private ScreenshotManager screenshotManager; - [BackgroundDependencyLoader(true)] private void load([NotNull] OsuConfigManager config, [CanBeNull] ScreenshotManager screenshotManager) { From 2eefe722f3d213ac0507ef7269e5f6dbc66db610 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Apr 2018 00:38:32 +0900 Subject: [PATCH 21/28] Move cache to a slightly more familiar place and add comment --- osu.Game/OsuGame.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4265cc0140..941e49e87e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -131,7 +131,6 @@ namespace osu.Game } dependencies.CacheAs(this); - dependencies.Cache(screenshotManager = new ScreenshotManager()); // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); @@ -203,6 +202,9 @@ namespace osu.Game protected override void LoadComplete() { + // this needs to be cached before base.LoadComplete as it is used by CursorOverrideContainer. + dependencies.Cache(screenshotManager = new ScreenshotManager()); + base.LoadComplete(); // The next time this is updated is in UpdateAfterChildren, which occurs too late and results From c3086531e08ea6a60b2878841c34a6b7d14550cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Apr 2018 02:54:24 +0900 Subject: [PATCH 22/28] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index f155804739..7e8788e601 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit f155804739b8bf6e8e04cbdbadca88618d325a32 +Subproject commit 7e8788e601b62577e51197a29e24f56eeeac0286 From 6ca714d93b9e92d9f2869e31379a38fb6ab55e06 Mon Sep 17 00:00:00 2001 From: jorolf Date: Sun, 15 Apr 2018 23:44:59 +0200 Subject: [PATCH 23/28] add badges to ProfileHeader --- osu.Game.Tests/Visual/TestCaseRankGraph.cs | 2 +- osu.Game.Tests/Visual/TestCaseUserProfile.cs | 61 ++++-- .../Overlays/Profile/Header/BadgeContainer.cs | 190 ++++++++++++++++++ .../Profile/{ => Header}/RankGraph.cs | 8 +- .../Profile/{ => Header}/SupporterIcon.cs | 4 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 22 +- osu.Game/Users/Badge.cs | 20 ++ osu.Game/Users/User.cs | 3 + osu.Game/Users/UserPanel.cs | 2 +- 9 files changed, 281 insertions(+), 31 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Header/BadgeContainer.cs rename osu.Game/Overlays/Profile/{ => Header}/RankGraph.cs (99%) rename osu.Game/Overlays/Profile/{ => Header}/SupporterIcon.cs (98%) create mode 100644 osu.Game/Users/Badge.cs diff --git a/osu.Game.Tests/Visual/TestCaseRankGraph.cs b/osu.Game.Tests/Visual/TestCaseRankGraph.cs index 45f6651537..f5558620ad 100644 --- a/osu.Game.Tests/Visual/TestCaseRankGraph.cs +++ b/osu.Game.Tests/Visual/TestCaseRankGraph.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Overlays.Profile; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using OpenTK; @@ -11,6 +10,7 @@ using System.Collections.Generic; using System; using NUnit.Framework; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Profile.Header; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index b060b9f2f8..86af26098a 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osu.Game.Overlays.Profile; +using osu.Game.Overlays.Profile.Header; using osu.Game.Users; namespace osu.Game.Tests.Visual @@ -23,6 +24,7 @@ namespace osu.Game.Tests.Visual typeof(UserProfileOverlay), typeof(RankGraph), typeof(LineGraph), + typeof(BadgeContainer) }; public TestCaseUserProfile() @@ -34,27 +36,24 @@ namespace osu.Game.Tests.Visual { base.LoadComplete(); - AddStep("Show offline dummy", () => profile.ShowUser(new User + AddStep("Show offline dummy", () => profile.ShowUser(createDummyUser(new Badge[0]), false)); + + AddStep("Show with badge", () => profile.ShowUser(createDummyUser(new[] { - Username = @"Somebody", - Id = 1, - Country = new Country { FullName = @"Alien" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", - JoinDate = DateTimeOffset.Now.AddDays(-1), - LastVisit = DateTimeOffset.Now, - Age = 1, - ProfileOrder = new[] { "me" }, - Statistics = new UserStatistics + new Badge { - Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 }, - PP = 4567.89m, - }, - RankHistory = new User.RankHistoryData - { - Mode = @"osu", - Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() + AwardedAt = DateTimeOffset.FromUnixTimeSeconds(1505741569), + Description = "Outstanding help by being a voluntary test subject.", + ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg" } - }, false)); + }), false)); + + AddStep("Show many badges", () => profile.ShowUser(createDummyUser(Enumerable.Range(0, 10).Select(i => new Badge + { + AwardedAt = DateTimeOffset.Now, + Description = i.ToString(), + ImageUrl = "Flags/__" + }).ToArray()), false)); checkSupporterTag(false); @@ -95,6 +94,32 @@ namespace osu.Game.Tests.Visual AddAssert("no supporter", () => profile.Header.SupporterTag.Alpha == 0); } + private User createDummyUser(Badge[] badges) + { + return new User + { + Username = @"Somebody", + Id = 1, + Country = new Country { FullName = @"Alien" }, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", + JoinDate = DateTimeOffset.Now.AddDays(-1), + LastVisit = DateTimeOffset.Now, + Age = 1, + ProfileOrder = new[] { "me" }, + Statistics = new UserStatistics + { + Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 }, + PP = 4567.89m, + }, + RankHistory = new User.RankHistoryData + { + Mode = @"osu", + Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() + }, + Badges = badges + }; + } + private class TestUserProfileOverlay : UserProfileOverlay { public new ProfileHeader Header => base.Header; diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs new file mode 100644 index 0000000000..b4d0705e50 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -0,0 +1,190 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Users; +using OpenTK; + +namespace osu.Game.Overlays.Profile.Header +{ + public class BadgeContainer : Container + { + private const float outer_container_width = 98; + private const float outer_container_padding = 3; + private static readonly Vector2 badge_size = new Vector2(outer_container_width - outer_container_padding * 2, 46); + + private OsuSpriteText badgeCountText; + private FillFlowContainer badgeFlowContainer; + private FillFlowContainer outerBadgeContainer; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Child = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Masking = true, + CornerRadius = 4, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray3 + }, + outerBadgeContainer = new OuterBadgeContainer(onOuterHover, onOuterHoverLost) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(outer_container_padding), + Width = outer_container_width, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + badgeCountText = new OsuSpriteText + { + Alpha = 0, + TextSize = 12, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Font = "Exo2.0-Regular" + }, + new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + Child = badgeFlowContainer = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + } + } + } + }, + } + }; + + Scheduler.AddDelayed(rotateBadges, 3000, true); + } + + private void rotateBadges() + { + if (outerBadgeContainer.IsHovered) return; + + visibleBadge = (visibleBadge + 1) % badgeCount; + + badgeFlowContainer.MoveToX(-badge_size.X * visibleBadge, 500, Easing.InOutQuad); + } + + private int visibleBadge; + private int badgeCount; + + public void ShowBadges(Badge[] badges) + { + switch (badges.Length) + { + case 0: + Hide(); + return; + case 1: + badgeCountText.Hide(); + break; + default: + badgeCountText.Show(); + badgeCountText.Text = $"{badges.Length} badges"; + break; + } + + Show(); + badgeCount = badges.Length; + visibleBadge = 0; + + foreach (var badge in badges) + { + LoadComponentAsync(new DrawableBadge(badge) + { + Size = badge_size, + }, badgeFlowContainer.Add); + } + } + + private void onOuterHover() + { + badgeFlowContainer.ClearTransforms(); + badgeFlowContainer.X = 0; + badgeFlowContainer.Direction = FillDirection.Full; + outerBadgeContainer.AutoSizeAxes = Axes.Both; + + badgeFlowContainer.MaximumSize = new Vector2(ChildSize.X, float.MaxValue); + } + + private void onOuterHoverLost() + { + rotateBadges(); + badgeFlowContainer.Direction = FillDirection.Horizontal; + outerBadgeContainer.AutoSizeAxes = Axes.Y; + outerBadgeContainer.Width = outer_container_width; + } + + private class OuterBadgeContainer : FillFlowContainer + { + private readonly Action hoverAction; + private readonly Action hoverLostAction; + + public OuterBadgeContainer(Action hoverAction, Action hoverLostAction) + { + this.hoverAction = hoverAction; + this.hoverLostAction = hoverLostAction; + } + + protected override bool OnHover(InputState state) + { + hoverAction(); + return true; + } + + protected override void OnHoverLost(InputState state) => hoverLostAction(); + } + + private class DrawableBadge : Container, IHasTooltip + { + private readonly Badge badge; + + public DrawableBadge(Badge badge) + { + this.badge = badge; + Padding = new MarginPadding(3); + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Child = new Sprite + { + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(badge.ImageUrl), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + OnLoadComplete = d => d.FadeInFromZero(200) + }; + } + + public string TooltipText => badge.Description; + } + } +} diff --git a/osu.Game/Overlays/Profile/RankGraph.cs b/osu.Game/Overlays/Profile/Header/RankGraph.cs similarity index 99% rename from osu.Game/Overlays/Profile/RankGraph.cs rename to osu.Game/Overlays/Profile/Header/RankGraph.cs index 72dd4352f6..2c70507536 100644 --- a/osu.Game/Overlays/Profile/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/RankGraph.cs @@ -2,9 +2,10 @@ // 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; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -14,10 +15,9 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Users; -using System.Collections.Generic; -using osu.Framework.Configuration; +using OpenTK; -namespace osu.Game.Overlays.Profile +namespace osu.Game.Overlays.Profile.Header { public class RankGraph : Container { diff --git a/osu.Game/Overlays/Profile/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs similarity index 98% rename from osu.Game/Overlays/Profile/SupporterIcon.cs rename to osu.Game/Overlays/Profile/Header/SupporterIcon.cs index e8d52bf50e..37ad63464c 100644 --- a/osu.Game/Overlays/Profile/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 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; using osu.Framework.Graphics.Containers; @@ -9,8 +8,9 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; +using OpenTK; -namespace osu.Game.Overlays.Profile +namespace osu.Game.Overlays.Profile.Header { public class SupporterIcon : CircularContainer, IHasTooltip { diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 4a88431cc4..189eaf0bdf 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -17,6 +17,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Profile.Header; using osu.Game.Users; namespace osu.Game.Overlays.Profile @@ -35,6 +36,7 @@ namespace osu.Game.Overlays.Profile private readonly GradeBadge gradeSSPlus, gradeSS, gradeSPlus, gradeS, gradeA; private readonly Box colourBar; private readonly DrawableFlag countryFlag; + private readonly BadgeContainer badgeContainer; private const float cover_height = 350; private const float info_height = 150; @@ -42,6 +44,7 @@ namespace osu.Game.Overlays.Profile private const float avatar_size = 110; private const float level_position = 30; private const float level_height = 60; + private const float stats_width = 280; public ProfileHeader(User user) { @@ -66,9 +69,9 @@ namespace osu.Game.Overlays.Profile { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - X = UserProfileOverlay.CONTENT_X_MARGIN, - Y = -20, - AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN, Bottom = 20, Right = stats_width + UserProfileOverlay.CONTENT_X_MARGIN }, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, Children = new Drawable[] { new UpdateableAvatar @@ -116,7 +119,14 @@ namespace osu.Game.Overlays.Profile Height = 20 } } - } + }, + badgeContainer = new BadgeContainer + { + RelativeSizeAxes = Axes.Both, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Bottom = 5 }, + Alpha = 0, + }, } }, colourBar = new Box @@ -156,7 +166,7 @@ namespace osu.Game.Overlays.Profile { X = -UserProfileOverlay.CONTENT_X_MARGIN, RelativeSizeAxes = Axes.Y, - Width = 280, + Width = stats_width, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Children = new Drawable[] @@ -417,6 +427,8 @@ namespace osu.Game.Overlays.Profile rankGraph.User.Value = user; } + + badgeContainer.ShowBadges(user.Badges); } private void tryAddInfoRightLine(FontAwesome icon, string str, string url = null) diff --git a/osu.Game/Users/Badge.cs b/osu.Game/Users/Badge.cs new file mode 100644 index 0000000000..25ef8ffdf4 --- /dev/null +++ b/osu.Game/Users/Badge.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using Newtonsoft.Json; + +namespace osu.Game.Users +{ + public class Badge + { + [JsonProperty("awarded_at")] + public DateTimeOffset AwardedAt; + + [JsonProperty("description")] + public string Description; + + [JsonProperty("image_url")] + public string ImageUrl; + } +} diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 441e4ffd28..b983b639f0 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -137,6 +137,9 @@ namespace osu.Game.Users [JsonProperty(@"rankHistory")] public RankHistoryData RankHistory; + [JsonProperty("badges")] + public Badge[] Badges; + public override string ToString() => Username; } } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 424d7b7a8f..bcb91c1955 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -17,7 +17,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Containers; -using osu.Game.Overlays.Profile; +using osu.Game.Overlays.Profile.Header; namespace osu.Game.Users { From af0c49cca88d08c83cf02f88b8da8ae993935bfc Mon Sep 17 00:00:00 2001 From: jorolf Date: Mon, 16 Apr 2018 18:27:18 +0200 Subject: [PATCH 24/28] badge_size is the actual badge size now also fixes rotateBadges bug when hover is lost --- .../Overlays/Profile/Header/BadgeContainer.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index b4d0705e50..c22bba9a43 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -19,9 +19,8 @@ namespace osu.Game.Overlays.Profile.Header { public class BadgeContainer : Container { - private const float outer_container_width = 98; - private const float outer_container_padding = 3; - private static readonly Vector2 badge_size = new Vector2(outer_container_width - outer_container_padding * 2, 46); + private static readonly Vector2 badge_size = new Vector2(86, 40); + private static readonly MarginPadding outer_padding = new MarginPadding(3); private OsuSpriteText badgeCountText; private FillFlowContainer badgeFlowContainer; @@ -49,8 +48,8 @@ namespace osu.Game.Overlays.Profile.Header Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Direction = FillDirection.Vertical, - Padding = new MarginPadding(outer_container_padding), - Width = outer_container_width, + Padding = outer_padding, + Width = badge_size.X + outer_padding.TotalHorizontal * 2, AutoSizeAxes = Axes.Y, Children = new Drawable[] { @@ -117,7 +116,7 @@ namespace osu.Game.Overlays.Profile.Header { LoadComponentAsync(new DrawableBadge(badge) { - Size = badge_size, + Size = badge_size + outer_padding.Total, }, badgeFlowContainer.Add); } } @@ -134,10 +133,10 @@ namespace osu.Game.Overlays.Profile.Header private void onOuterHoverLost() { - rotateBadges(); + badgeFlowContainer.MoveToX(-badge_size.X * visibleBadge, 500, Easing.InOutQuad); badgeFlowContainer.Direction = FillDirection.Horizontal; outerBadgeContainer.AutoSizeAxes = Axes.Y; - outerBadgeContainer.Width = outer_container_width; + outerBadgeContainer.Width = badge_size.X + outer_padding.TotalHorizontal * 2; } private class OuterBadgeContainer : FillFlowContainer From 2a18b4c3f8b46da5417ec071d7d2da243ff85f0d Mon Sep 17 00:00:00 2001 From: jorolf Date: Mon, 16 Apr 2018 18:51:35 +0200 Subject: [PATCH 25/28] add a DRAWABLE_BADGE_SIZE const and center badges --- osu.Game.Tests/Visual/TestCaseUserProfile.cs | 2 +- .../Overlays/Profile/Header/BadgeContainer.cs | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index 86af26098a..f691279093 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual { AwardedAt = DateTimeOffset.Now, Description = i.ToString(), - ImageUrl = "Flags/__" + ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg" }).ToArray()), false)); checkSupporterTag(false); diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index c22bba9a43..7d8bdc6009 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Profile.Header Origin = Anchor.BottomLeft, Direction = FillDirection.Vertical, Padding = outer_padding, - Width = badge_size.X + outer_padding.TotalHorizontal * 2, + Width = DrawableBadge.DRAWABLE_BADGE_SIZE.X + outer_padding.TotalHorizontal, AutoSizeAxes = Axes.Y, Children = new Drawable[] { @@ -68,6 +68,8 @@ namespace osu.Game.Overlays.Profile.Header AutoSizeAxes = Axes.Both, Child = badgeFlowContainer = new FillFlowContainer { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, } @@ -86,7 +88,7 @@ namespace osu.Game.Overlays.Profile.Header visibleBadge = (visibleBadge + 1) % badgeCount; - badgeFlowContainer.MoveToX(-badge_size.X * visibleBadge, 500, Easing.InOutQuad); + badgeFlowContainer.MoveToX(-DrawableBadge.DRAWABLE_BADGE_SIZE.X * visibleBadge, 500, Easing.InOutQuad); } private int visibleBadge; @@ -116,7 +118,8 @@ namespace osu.Game.Overlays.Profile.Header { LoadComponentAsync(new DrawableBadge(badge) { - Size = badge_size + outer_padding.Total, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, }, badgeFlowContainer.Add); } } @@ -136,7 +139,7 @@ namespace osu.Game.Overlays.Profile.Header badgeFlowContainer.MoveToX(-badge_size.X * visibleBadge, 500, Easing.InOutQuad); badgeFlowContainer.Direction = FillDirection.Horizontal; outerBadgeContainer.AutoSizeAxes = Axes.Y; - outerBadgeContainer.Width = badge_size.X + outer_padding.TotalHorizontal * 2; + outerBadgeContainer.Width = DrawableBadge.DRAWABLE_BADGE_SIZE.X + outer_padding.TotalHorizontal; } private class OuterBadgeContainer : FillFlowContainer @@ -161,12 +164,15 @@ namespace osu.Game.Overlays.Profile.Header private class DrawableBadge : Container, IHasTooltip { + public static readonly Vector2 DRAWABLE_BADGE_SIZE = badge_size + outer_padding.Total; + private readonly Badge badge; public DrawableBadge(Badge badge) { this.badge = badge; - Padding = new MarginPadding(3); + Padding = outer_padding; + Size = DRAWABLE_BADGE_SIZE; } [BackgroundDependencyLoader] From 046412f962ed7b85f5279097fa2d595f6702aa8f Mon Sep 17 00:00:00 2001 From: jorolf Date: Mon, 16 Apr 2018 18:52:09 +0200 Subject: [PATCH 26/28] make hover lost transition instant (similar to hover transition) --- osu.Game/Overlays/Profile/Header/BadgeContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index 7d8bdc6009..7bff7efa48 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -136,7 +136,7 @@ namespace osu.Game.Overlays.Profile.Header private void onOuterHoverLost() { - badgeFlowContainer.MoveToX(-badge_size.X * visibleBadge, 500, Easing.InOutQuad); + badgeFlowContainer.X = -DrawableBadge.DRAWABLE_BADGE_SIZE.X * visibleBadge; badgeFlowContainer.Direction = FillDirection.Horizontal; outerBadgeContainer.AutoSizeAxes = Axes.Y; outerBadgeContainer.Width = DrawableBadge.DRAWABLE_BADGE_SIZE.X + outer_padding.TotalHorizontal; From de9f15f620c827af040805e99f2de450f1c7c0e6 Mon Sep 17 00:00:00 2001 From: jorolf Date: Mon, 16 Apr 2018 19:22:11 +0200 Subject: [PATCH 27/28] add new test case and fix rotation not working --- .../Visual/TestCaseBadgeContainer.cs | 62 +++++++++++++++++ osu.Game.Tests/Visual/TestCaseUserProfile.cs | 68 ++++++++----------- .../Overlays/Profile/Header/BadgeContainer.cs | 5 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 3 +- 4 files changed, 92 insertions(+), 46 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseBadgeContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseBadgeContainer.cs b/osu.Game.Tests/Visual/TestCaseBadgeContainer.cs new file mode 100644 index 0000000000..8177e2e272 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseBadgeContainer.cs @@ -0,0 +1,62 @@ +// Copyright (c) 2007-2018 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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Overlays.Profile.Header; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseBadgeContainer : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(BadgeContainer) }; + + public TestCaseBadgeContainer() + { + BadgeContainer badgeContainer; + + Child = badgeContainer = new BadgeContainer + { + RelativeSizeAxes = Axes.Both + }; + + AddStep("Show 1 badge", () => badgeContainer.ShowBadges(new[] + { + new Badge + { + AwardedAt = DateTimeOffset.Now, + Description = "Appreciates compasses", + ImageUrl = "https://assets.ppy.sh/profile-badges/mg2018-1star.png", + } + })); + + AddStep("Show 2 badges", () => badgeContainer.ShowBadges(new[] + { + new Badge + { + AwardedAt = DateTimeOffset.Now, + Description = "Contributed to osu!lazer testing", + ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.png", + }, + new Badge + { + AwardedAt = DateTimeOffset.Now, + Description = "Appreciates compasses", + ImageUrl = "https://assets.ppy.sh/profile-badges/mg2018-1star.png", + } + })); + + AddStep("Show many badges", () => badgeContainer.ShowBadges(Enumerable.Range(1, 20).Select(i => new Badge + { + AwardedAt = DateTimeOffset.Now, + Description = $"Contributed to osu!lazer testing {i} times", + ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg", + }).ToArray())); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index f691279093..0fdc01a974 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -36,24 +36,36 @@ namespace osu.Game.Tests.Visual { base.LoadComplete(); - AddStep("Show offline dummy", () => profile.ShowUser(createDummyUser(new Badge[0]), false)); - - AddStep("Show with badge", () => profile.ShowUser(createDummyUser(new[] + AddStep("Show offline dummy", () => profile.ShowUser(new User { - new Badge + Username = @"Somebody", + Id = 1, + Country = new Country { FullName = @"Alien" }, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", + JoinDate = DateTimeOffset.Now.AddDays(-1), + LastVisit = DateTimeOffset.Now, + Age = 1, + ProfileOrder = new[] { "me" }, + Statistics = new UserStatistics { - AwardedAt = DateTimeOffset.FromUnixTimeSeconds(1505741569), - Description = "Outstanding help by being a voluntary test subject.", - ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg" + Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 }, + PP = 4567.89m, + }, + RankHistory = new User.RankHistoryData + { + Mode = @"osu", + Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() + }, + Badges = new[] + { + new Badge + { + AwardedAt = DateTimeOffset.FromUnixTimeSeconds(1505741569), + Description = "Outstanding help by being a voluntary test subject.", + ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg" + } } - }), false)); - - AddStep("Show many badges", () => profile.ShowUser(createDummyUser(Enumerable.Range(0, 10).Select(i => new Badge - { - AwardedAt = DateTimeOffset.Now, - Description = i.ToString(), - ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg" - }).ToArray()), false)); + }, false)); checkSupporterTag(false); @@ -94,32 +106,6 @@ namespace osu.Game.Tests.Visual AddAssert("no supporter", () => profile.Header.SupporterTag.Alpha == 0); } - private User createDummyUser(Badge[] badges) - { - return new User - { - Username = @"Somebody", - Id = 1, - Country = new Country { FullName = @"Alien" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", - JoinDate = DateTimeOffset.Now.AddDays(-1), - LastVisit = DateTimeOffset.Now, - Age = 1, - ProfileOrder = new[] { "me" }, - Statistics = new UserStatistics - { - Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 }, - PP = 4567.89m, - }, - RankHistory = new User.RankHistoryData - { - Mode = @"osu", - Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() - }, - Badges = badges - }; - } - private class TestUserProfileOverlay : UserProfileOverlay { public new ProfileHeader Header => base.Header; diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index 7bff7efa48..a44940de1c 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -31,8 +31,6 @@ namespace osu.Game.Overlays.Profile.Header { Child = new Container { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, Masking = true, CornerRadius = 4, AutoSizeAxes = Axes.Both, @@ -68,8 +66,6 @@ namespace osu.Game.Overlays.Profile.Header AutoSizeAxes = Axes.Both, Child = badgeFlowContainer = new FillFlowContainer { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, } @@ -114,6 +110,7 @@ namespace osu.Game.Overlays.Profile.Header badgeCount = badges.Length; visibleBadge = 0; + badgeFlowContainer.Clear(); foreach (var badge in badges) { LoadComponentAsync(new DrawableBadge(badge) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 189eaf0bdf..ec0e45d5ca 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -122,7 +122,8 @@ namespace osu.Game.Overlays.Profile }, badgeContainer = new BadgeContainer { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Origin = Anchor.BottomLeft, Margin = new MarginPadding { Bottom = 5 }, Alpha = 0, From a827fb51bc05b340779f488a245ec3b8978eaaa1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Apr 2018 11:42:55 +0900 Subject: [PATCH 28/28] Simplify child definition --- osu.Game/Overlays/Profile/Header/BadgeContainer.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index a44940de1c..291db45e97 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -180,12 +180,15 @@ namespace osu.Game.Overlays.Profile.Header FillMode = FillMode.Fit, RelativeSizeAxes = Axes.Both, Texture = textures.Get(badge.ImageUrl), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - OnLoadComplete = d => d.FadeInFromZero(200) }; } + protected override void LoadComplete() + { + base.LoadComplete(); + Child.FadeInFromZero(200); + } + public string TooltipText => badge.Description; } }