From 0f1fe1d6832d0c6dd2f29e30a5d142b2fbfc023e Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 9 Jan 2023 21:48:53 +0100 Subject: [PATCH 01/31] refactor(hud/gameplay/SongProgress): Add interface to designate `SongProgressBar`s --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 16 +++++++++++++--- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 2 +- osu.Game/Screens/Play/HUD/DefaultSongProgress.cs | 2 +- osu.Game/Screens/Play/HUD/ISongProgressBar.cs | 16 ++++++++++++++++ osu.Game/Screens/Play/HUD/SongProgressBar.cs | 10 ++++------ 5 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/ISongProgressBar.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 29fadd151fa6..713183ebaf3c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -188,7 +188,7 @@ public void TestHoldForMenuDoesWorkWhenHidden() [Test] public void TestInputDoesntWorkWhenHUDHidden() { - SongProgressBar? getSongProgress() => hudOverlay.ChildrenOfType().SingleOrDefault(); + ISongProgressBar? getSongProgress() => hudOverlay.ChildrenOfType().SingleOrDefault(); bool seeked = false; @@ -204,7 +204,7 @@ public void TestInputDoesntWorkWhenHUDHidden() Debug.Assert(progress != null); - progress.ShowHandle = true; + progress.Interactive = true; progress.OnSeek += _ => seeked = true; }); @@ -213,7 +213,17 @@ public void TestInputDoesntWorkWhenHUDHidden() AddStep("attempt seek", () => { - InputManager.MoveMouseTo(getSongProgress()); + switch (getSongProgress()) + { + case SongProgressBar defaultBar: + InputManager.MoveMouseTo(defaultBar); + break; + + case ArgonSongProgressBar argonBar: + InputManager.MoveMouseTo(argonBar); + break; + } + InputManager.Click(MouseButton.Left); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index c2036984c189..dd891b456cac 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -121,7 +121,7 @@ public void TestSpectatorPlayerInteractiveElementsHidden() AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && - p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); + p.ChildrenOfType().SingleOrDefault()?.Interactive == false)); AddStep("restore config hud visibility", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); } diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs index 53866312a015..cb629a0b77bd 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs @@ -133,7 +133,7 @@ protected override void Update() private void updateBarVisibility() { - bar.ShowHandle = AllowSeeking.Value; + bar.Interactive = AllowSeeking.Value; updateInfoMargin(); } diff --git a/osu.Game/Screens/Play/HUD/ISongProgressBar.cs b/osu.Game/Screens/Play/HUD/ISongProgressBar.cs new file mode 100644 index 000000000000..f1a219e18ba0 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ISongProgressBar.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Screens.Play.HUD +{ + public interface ISongProgressBar + { + public Action? OnSeek { get; set; } + public double StartTime { set; } + public double EndTime { set; } + public double CurrentTime { set; } + public bool Interactive { get; set; } + } +} diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/SongProgressBar.cs index 28059d4911d8..fade562e3c47 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressBar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osuTK; using osuTK.Graphics; @@ -15,9 +13,9 @@ namespace osu.Game.Screens.Play.HUD { - public partial class SongProgressBar : SliderBar + public partial class SongProgressBar : SliderBar, ISongProgressBar { - public Action OnSeek; + public Action? OnSeek { get; set; } private readonly Box fill; private readonly Container handleBase; @@ -25,7 +23,7 @@ public partial class SongProgressBar : SliderBar private bool showHandle; - public bool ShowHandle + public bool Interactive { get => showHandle; set @@ -142,7 +140,7 @@ protected override void Update() handleBase.X = newX; } - private ScheduledDelegate scheduledSeek; + private ScheduledDelegate? scheduledSeek; protected override void OnUserChange(double value) { From f6265197e84a44fe76df79a53feb3a54976cd6c2 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 9 Jan 2023 21:55:10 +0100 Subject: [PATCH 02/31] feat(hud/gameplay): Add Argon variant of `SongProgressBar` --- .../Screens/Play/HUD/ArgonSongProgressBar.cs | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs new file mode 100644 index 000000000000..3ac7223f1deb --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -0,0 +1,249 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Framework.Threading; +using osu.Framework.Utils; +using osu.Game.Graphics; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play.HUD +{ + public partial class ArgonSongProgressBar : SliderBar, ISongProgressBar + { + private readonly float baseHeight; + private readonly float catchupBaseDepth; + + private readonly RoundedBar playfieldBar; + private readonly RoundedBar catchupBar; + + private readonly Box background; + + private readonly BindableBool showBackground = new BindableBool(); + + public bool ShowBackground + { + get => showBackground.Value; + set => showBackground.Value = value; + } + + private const float alpha_threshold = 2500; + + public Action? OnSeek { get; set; } + + public double StartTime + { + private get => CurrentNumber.MinValue; + set => CurrentNumber.MinValue = value; + } + + public double EndTime + { + private get => CurrentNumber.MaxValue; + set => CurrentNumber.MaxValue = value; + } + + public double CurrentTime + { + private get => CurrentNumber.Value; + set => CurrentNumber.Value = value; + } + + public double ReferenceTime + { + private get => currentReference.Value; + set => currentReference.Value = value; + } + + private double length => EndTime - StartTime; + + private readonly BindableNumber currentReference; + + public bool Interactive { get; set; } + + public ArgonSongProgressBar(float barHeight) + { + currentReference = new BindableDouble(); + setupAlternateValue(); + + StartTime = 0; + EndTime = 1; + + RelativeSizeAxes = Axes.X; + baseHeight = barHeight; + Height = baseHeight; + + CornerRadius = 5; + Masking = true; + + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + catchupBar = new RoundedBar + { + Name = "Audio bar", + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + CornerRadius = 5, + AlwaysPresent = true, + RelativeSizeAxes = Axes.Both + }, + playfieldBar = new RoundedBar + { + Name = "Playfield bar", + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + CornerRadius = 5, + AccentColour = Color4.White, + RelativeSizeAxes = Axes.Both + }, + }; + catchupBaseDepth = catchupBar.Depth; + } + + private void setupAlternateValue() + { + CurrentNumber.MaxValueChanged += v => currentReference.MaxValue = v; + CurrentNumber.MinValueChanged += v => currentReference.MinValue = v; + CurrentNumber.PrecisionChanged += v => currentReference.Precision = v; + } + + private float normalizedReference + { + get + { + if (EndTime - StartTime == 0) + return 1; + + return (float)((ReferenceTime - StartTime) / length); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + catchupBar.AccentColour = colours.BlueLight; + showBackground.BindValueChanged(_ => updateBackground(), true); + } + + private void updateBackground() + { + background.FadeTo(showBackground.Value ? 1 : 0, 200, Easing.In); + } + + protected override bool OnHover(HoverEvent e) + { + if (Interactive) + this.ResizeHeightTo(baseHeight * 3.5f, 200, Easing.Out); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + if (Interactive) + this.ResizeHeightTo(baseHeight, 200, Easing.In); + + base.OnHoverLost(e); + } + + protected override void UpdateValue(float value) + { + // + } + + protected override void Update() + { + base.Update(); + + playfieldBar.Length = (float)Interpolation.Lerp(playfieldBar.Length, NormalizedValue, Math.Clamp(Time.Elapsed / 40, 0, 1)); + catchupBar.Length = (float)Interpolation.Lerp(catchupBar.Length, normalizedReference, Math.Clamp(Time.Elapsed / 40, 0, 1)); + + if (ReferenceTime < CurrentTime) + ChangeChildDepth(catchupBar, playfieldBar.Depth - 0.1f); + else + ChangeChildDepth(catchupBar, catchupBaseDepth); + + float timeDelta = (float)(Math.Abs(CurrentTime - ReferenceTime)); + catchupBar.Alpha = MathHelper.Clamp(timeDelta, 0, alpha_threshold) / alpha_threshold; + } + + private ScheduledDelegate? scheduledSeek; + + protected override void OnUserChange(double value) + { + scheduledSeek?.Cancel(); + scheduledSeek = Schedule(() => + { + if (Interactive) + OnSeek?.Invoke(value); + }); + } + + private partial class RoundedBar : Container + { + private readonly Box fill; + private readonly Container mask; + private float length; + + public RoundedBar() + { + Masking = true; + Children = new[] + { + mask = new Container + { + Masking = true, + RelativeSizeAxes = Axes.Y, + Size = new Vector2(1), + Child = fill = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.White + } + } + }; + } + + public float Length + { + get => length; + set + { + length = value; + mask.Width = value * DrawWidth; + fill.Width = value * DrawWidth; + } + } + + public new float CornerRadius + { + get => base.CornerRadius; + set + { + base.CornerRadius = value; + mask.CornerRadius = value; + } + } + + public ColourInfo AccentColour + { + get => fill.Colour; + set => fill.Colour = value; + } + } + } +} From 28d2d766ebdb595b138761f4da03149e0894e7af Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 9 Jan 2023 21:57:32 +0100 Subject: [PATCH 03/31] refactor(hud/gameplay/SongProgressInfo): minor changes to text positioning, font and colour --- osu.Game/Screens/Play/HUD/SongProgressInfo.cs | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs index fb5f5cc916a3..8a5c24a1f107 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using System; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Screens.Play.HUD { @@ -27,13 +28,33 @@ public partial class SongProgressInfo : Container private double songLength => endTime - startTime; - private const int margin = 10; + public FontUsage Font + { + set + { + timeCurrent.Font = value; + timeLeft.Font = value; + progress.Font = value; + } + } + + public Colour4 TextColour + { + set + { + timeCurrent.Colour = value; + timeLeft.Colour = value; + progress.Colour = value; + } + } public double StartTime { set => startTime = value; } + public bool ShowProgress = true; + public double EndTime { set => endTime = value; @@ -76,6 +97,7 @@ private void load(OsuColour colours, IGameplayClock clock) Origin = Anchor.Centre, Anchor = Anchor.Centre, AutoSizeAxes = Axes.Both, + Alpha = ShowProgress ? 1 : 0, Child = new UprightAspectMaintainingContainer { Origin = Anchor.Centre, @@ -99,15 +121,15 @@ private void load(OsuColour colours, IGameplayClock clock) AutoSizeAxes = Axes.Both, Child = new UprightAspectMaintainingContainer { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, + Origin = Anchor.CentreRight, + Anchor = Anchor.CentreRight, AutoSizeAxes = Axes.Both, Scaling = ScaleMode.Vertical, ScalingFactor = 0.5f, Child = timeLeft = new SizePreservingSpriteText { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, + Origin = Anchor.CentreRight, + Anchor = Anchor.CentreRight, Colour = colours.BlueLighter, Font = OsuFont.Numeric, } @@ -128,7 +150,7 @@ protected override void Update() if (currentPercent != previousPercent) { - progress.Text = currentPercent.ToString() + @"%"; + progress.Text = currentPercent + @"%"; previousPercent = currentPercent; } From 5952cd08a22e16d96f20815f21d3b7b50dcec71a Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 9 Jan 2023 21:58:53 +0100 Subject: [PATCH 04/31] feat(hud/gameplay): implement Argon song progress density graph (SegmentedGraph) --- .../Play/HUD/ArgonSongProgressGraph.cs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs new file mode 100644 index 000000000000..2c82faf7b2a3 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs @@ -0,0 +1,62 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Play.HUD +{ + public partial class ArgonSongProgressGraph : SegmentedGraph + { + private IEnumerable? objects; + + public IEnumerable Objects + { + set + { + objects = value; + + const int granularity = 300; + int[] values = new int[granularity]; + + if (!objects.Any()) + return; + + double firstHit = objects.First().StartTime; + double lastHit = objects.Max(o => o.GetEndTime()); + + if (lastHit == 0) + lastHit = objects.Last().StartTime; + + double interval = (lastHit - firstHit + 1) / granularity; + + foreach (var h in objects) + { + double endTime = h.GetEndTime(); + + Debug.Assert(endTime >= h.StartTime); + + int startRange = (int)((h.StartTime - firstHit) / interval); + int endRange = (int)((endTime - firstHit) / interval); + for (int i = startRange; i <= endRange; i++) + values[i]++; + } + + Values = values; + } + } + + public ArgonSongProgressGraph() + : base(5) + { + for (int i = 0; i < 5; i++) + { + TierColours[i] = Colour4.White.Opacity(1 / 5f * 0.85f); + } + } + } +} From 91cde5ffbff37689c318d7f49aef1f1819843f62 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 9 Jan 2023 21:59:48 +0100 Subject: [PATCH 05/31] feat(hud/gameplay): implement Argon variant of `SongProgress` --- .../Screens/Play/HUD/ArgonSongProgress.cs | 139 ++++++++++++++++++ osu.Game/Skinning/ArgonSkin.cs | 9 +- 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Screens/Play/HUD/ArgonSongProgress.cs diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs new file mode 100644 index 000000000000..c36f881ec284 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -0,0 +1,139 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Timing; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Screens.Play.HUD +{ + public partial class ArgonSongProgress : SongProgress + { + private readonly SongProgressInfo info; + private readonly ArgonSongProgressGraph graph; + private readonly ArgonSongProgressBar bar; + + private const float bar_height = 10; + + public readonly Bindable AllowSeeking = new BindableBool(); + + [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] + public Bindable ShowGraph { get; } = new BindableBool(true); + + [Resolved] + private DrawableRuleset? drawableRuleset { get; set; } + + private IClock referenceClock => drawableRuleset?.FrameStableClock ?? GameplayClock; + + [Resolved] + private Player? player { get; set; } + + public ArgonSongProgress() + { + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + Children = new Drawable[] + { + info = new SongProgressInfo + { + Origin = Anchor.TopLeft, + Name = "Info", + Anchor = Anchor.TopLeft, + RelativeSizeAxes = Axes.X, + ShowProgress = false + }, + graph = new ArgonSongProgressGraph + { + Name = "Difficulty graph", + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Masking = true, + CornerRadius = 5, + }, + bar = new ArgonSongProgressBar(bar_height) + { + Name = "Seek bar", + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + OnSeek = time => player?.Seek(time), + } + }; + RelativeSizeAxes = Axes.X; + } + + [BackgroundDependencyLoader] + private void load() + { + base.LoadComplete(); + + if (drawableRuleset != null) + { + if (player?.Configuration.AllowUserInteraction == true) + ((IBindable)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded); + } + + info.ShowProgress = false; + info.TextColour = Colour4.White; + info.Font = OsuFont.Torus.With(size: 18, weight: FontWeight.Bold); + } + + protected override void LoadComplete() + { + AllowSeeking.BindValueChanged(_ => updateBarVisibility(), true); + ShowGraph.BindValueChanged(_ => updateGraphVisibility(), true); + } + + protected override void UpdateObjects(IEnumerable objects) + { + graph.Objects = objects; + + info.StartTime = bar.StartTime = FirstHitTime; + info.EndTime = bar.EndTime = LastHitTime; + } + + private void updateBarVisibility() + { + bar.Interactive = AllowSeeking.Value; + } + + private void updateGraphVisibility() + { + graph.FadeTo(ShowGraph.Value ? 1 : 0, 200, Easing.In); + bar.ShowBackground = !ShowGraph.Value; + } + + protected override void Update() + { + base.Update(); + Height = bar.Height + bar_height + info.Height; + graph.Height = bar.Height; + } + + protected override void PopIn() + { + this.FadeIn(500, Easing.OutQuint); + } + + protected override void PopOut() + { + this.FadeOut(100); + } + + protected override void UpdateProgress(double progress, bool isIntro) + { + bar.ReferenceTime = GameplayClock.CurrentTime; + + if (isIntro) + bar.CurrentTime = 0; + else + bar.CurrentTime = referenceClock.CurrentTime; + } + } +} diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index d78147aaea61..53c6c1e5ceb1 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -108,6 +108,7 @@ public ArgonSkin(SkinInfo skin, IStorageResourceProvider resources) var accuracy = container.OfType().FirstOrDefault(); var combo = container.OfType().FirstOrDefault(); var ppCounter = container.OfType().FirstOrDefault(); + var songProgress = container.OfType().FirstOrDefault(); if (score != null) { @@ -158,6 +159,12 @@ public ArgonSkin(SkinInfo skin, IStorageResourceProvider resources) // origin flipped to match scale above. hitError2.Origin = Anchor.CentreLeft; } + + if (songProgress != null) + { + songProgress.Position = new Vector2(0, -10); + songProgress.Scale = new Vector2(0.9f, 1); + } } }) { @@ -167,7 +174,7 @@ public ArgonSkin(SkinInfo skin, IStorageResourceProvider resources) new DefaultScoreCounter(), new DefaultAccuracyCounter(), new DefaultHealthDisplay(), - new DefaultSongProgress(), + new ArgonSongProgress(), new BarHitErrorMeter(), new BarHitErrorMeter(), new PerformancePointsCounter() From 48deef4056a3b0a25f6dda5e440aacaac69dfa23 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 9 Jan 2023 22:07:18 +0100 Subject: [PATCH 06/31] test: adapt and create tests to cover new components --- .../Archives/modified-argon-20221024.osk | Bin 0 -> 1412 bytes .../Skins/SkinDeserialisationTest.cs | 2 + .../SkinnableHUDComponentTestScene.cs | 5 +- .../TestSceneArgonSongProgressGraph.cs | 73 ++++++++++++++++++ .../Visual/Gameplay/TestSceneSongProgress.cs | 2 + 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Resources/Archives/modified-argon-20221024.osk create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs diff --git a/osu.Game.Tests/Resources/Archives/modified-argon-20221024.osk b/osu.Game.Tests/Resources/Archives/modified-argon-20221024.osk new file mode 100644 index 0000000000000000000000000000000000000000..28b6a001ebd37b63c3e6c1b64d2cab3af0b9e0a5 GIT binary patch literal 1412 zcmWIWW@Zs#U|`^2*fJ?1H1DEC$y^|BJ6ME)p*TA;PcJhsQ?yU#0!|wxs6MaP; zdzJ`Zio6+_sVX-6j+*73+fz@=Ddunf;8}N&Wp|_Gv)})wsK&52`R$p0vXFo61|e-9 z3nsOx4X>iU)Uj=urek7!Vuo2la7?jyoKPt{Z(p}a+qudl9+sz8TSXKnEOI@%_vE|u zq^=k8YP)rO|HeO+sD3EZ^(r7VTB9lAy5%Nrx$SD!swbU0f>2l803Y_ytI71tm6E<)z6*=1q6KZKI0p@DJbBSzFufZN1&IE*ZK3^fk77x zj0}t}gX&+xkqqC+{OAbWM=?)V1{?zTT%jxr`&!0|zULZ8D@~CQOrRvO1 z)tNsl=T&C@3~2s(r*YZ~*7WpePg9>QeQnwFhT&t0NWvtqJuzDuP#tJ`-1GGgMh1r0 zK-Y-@9q5~wndcGe;+&sbke`>DS5gdi>Dy_6*|!Y@j^F40%cpjJ+k{s~HnLTon3UUS zm^Q6Ue<}Z}s=^~8E9a!Fko^5_a`^Goucy7dWVR(5{8<0_e@oq*ck9ldU-Y8-bJwDa zskQuz%`cwV)m0;4t&rWxaBQMe_pCMRrloL72WIZyuseG9hN&ML3b*k0FJ9l^7iqls z$#r4(Zh;uZGdv-3t$m9Z?Yin!*YfL99ka3V)N6}(_{K*pulZq{v+!=9fcznGY2!l{ z&nxeoES+$fb7B9X{=G-VU%O^se3E~4tBBOEb+Hbwk5`oyD{mK@z4T?=ubx#Qz4rID z!};!1e`P3-{oR!P-m$=z$^Vi9N7$+T&Rc$P9`b#1BD!(EW_`Ks20OlQ^2b*{@`yX6 zEIVJSpQ#|ZP`#(+kk;e74U2=#6c;vsKKUbl{`|f>hLaw+N8{Hunu%t)%{2P{(%LSS{*LbeYD9784v0|*ks+ClG?0RBJpBb64Sq#;wnp5tDK#7{Tb)|74oU2A-DK1 zRJg34b=@ZA;%~vd(gyx}nh%@&JKNH@k~8A<{>w2_H(t2ue>u)4%z6i>UVn^?Nz3iK zb{js|Z2Qj|;LXS+!hpN<0R|WZG=eBtS%j_&J;OuwFfcS8hU$W6e{`+rSrMT%1sGx2 gGbXwj=uwO?BY+tr!UMcn*+2?dfbbKLu3-W3058Krn*aa+ literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs index ff665499ae17..2e8eb48f0bc6 100644 --- a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs +++ b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs @@ -41,6 +41,8 @@ public class SkinDeserialisationTest "Archives/modified-default-20220818.osk", // Covers longest combo counter "Archives/modified-default-20221012.osk", + // Covers Argon variant of song progress bar + "Archives/modified-argon-20221024.osk", // Covers TextElement and BeatmapInfoDrawable "Archives/modified-default-20221102.osk" }; diff --git a/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs b/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs index 545b3c2cf422..f54f50795e68 100644 --- a/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs +++ b/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs @@ -20,7 +20,9 @@ public void SetUp() => Schedule(() => { var implementation = skin is LegacySkin ? CreateLegacyImplementation() - : CreateDefaultImplementation(); + : skin is ArgonSkin + ? CreateArgonImplementation() + : CreateDefaultImplementation(); implementation.Anchor = Anchor.Centre; implementation.Origin = Anchor.Centre; @@ -29,6 +31,7 @@ public void SetUp() => Schedule(() => }); protected abstract Drawable CreateDefaultImplementation(); + protected virtual Drawable CreateArgonImplementation() => CreateDefaultImplementation(); protected abstract Drawable CreateLegacyImplementation(); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs new file mode 100644 index 000000000000..159ee849e1af --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs @@ -0,0 +1,73 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Diagnostics; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Testing; +using osu.Framework.Utils; +using osu.Game.Rulesets.Objects; +using osu.Game.Screens.Play.HUD; + +namespace osu.Game.Tests.Visual.Gameplay +{ + [TestFixture] + public partial class TestSceneArgonSongProgressGraph : OsuTestScene + { + private TestArgonSongProgressGraph? graph; + + [SetUpSteps] + public void SetupSteps() + { + AddStep("add new big graph", () => + { + if (graph != null) + { + graph.Expire(); + graph = null; + } + + Add(graph = new TestArgonSongProgressGraph + { + RelativeSizeAxes = Axes.X, + Height = 200, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }); + }); + } + + [Test] + public void TestGraphRecreation() + { + AddAssert("ensure not created", () => graph!.CreationCount == 0); + AddStep("display values", displayRandomValues); + AddUntilStep("wait for creation count", () => graph!.CreationCount == 1); + AddRepeatStep("new values", displayRandomValues, 5); + AddWaitStep("wait some", 5); + AddAssert("ensure recreation debounced", () => graph!.CreationCount == 2); + } + + private void displayRandomValues() + { + Debug.Assert(graph != null); + var objects = new List(); + for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000) + objects.Add(new HitObject { StartTime = i }); + + graph.Objects = objects; + } + + private partial class TestArgonSongProgressGraph : ArgonSongProgressGraph + { + public int CreationCount { get; private set; } + + protected override void RecreateGraph() + { + base.RecreateGraph(); + CreationCount++; + } + } + } +} diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 2e579cc5227d..415a3c5b079c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -72,6 +72,8 @@ private void setHitObjects() protected override Drawable CreateDefaultImplementation() => new DefaultSongProgress(); + protected override Drawable CreateArgonImplementation() => new ArgonSongProgress(); + protected override Drawable CreateLegacyImplementation() => new LegacySongProgress(); } } From eac8e9f6fb2756b4a5529dec30065dc8706ed3c1 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 9 Jan 2023 22:21:34 +0100 Subject: [PATCH 07/31] test: make test not actually test anything --- .../Visual/Gameplay/TestSceneArgonSongProgressGraph.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs index 159ee849e1af..e7feadc72b08 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs @@ -39,14 +39,10 @@ public void SetupSteps() } [Test] - public void TestGraphRecreation() + public void Test() { AddAssert("ensure not created", () => graph!.CreationCount == 0); AddStep("display values", displayRandomValues); - AddUntilStep("wait for creation count", () => graph!.CreationCount == 1); - AddRepeatStep("new values", displayRandomValues, 5); - AddWaitStep("wait some", 5); - AddAssert("ensure recreation debounced", () => graph!.CreationCount == 2); } private void displayRandomValues() From 4439698867b7f9b98d862d49903524d244edb215 Mon Sep 17 00:00:00 2001 From: Ruki Date: Thu, 12 Jan 2023 13:19:03 +0100 Subject: [PATCH 08/31] Update osu.Game/Screens/Play/HUD/ArgonSongProgress.cs --- osu.Game/Screens/Play/HUD/ArgonSongProgress.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index c36f881ec284..e5ee42e72a2f 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -54,8 +54,6 @@ public ArgonSongProgress() Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, - Masking = true, - CornerRadius = 5, }, bar = new ArgonSongProgressBar(bar_height) { From b62b5714e89199159341757688bd5abe01b008ea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Jan 2023 18:07:11 +0900 Subject: [PATCH 09/31] Fix `TierColours` assignment --- osu.Game/Graphics/UserInterface/SegmentedGraph.cs | 9 +++------ osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs | 8 +++++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/SegmentedGraph.cs b/osu.Game/Graphics/UserInterface/SegmentedGraph.cs index 8ccba710b8e2..dab7ec0559f5 100644 --- a/osu.Game/Graphics/UserInterface/SegmentedGraph.cs +++ b/osu.Game/Graphics/UserInterface/SegmentedGraph.cs @@ -48,17 +48,14 @@ public T[] Values } } - private Colour4[] tierColours; + private IReadOnlyList tierColours; - public Colour4[] TierColours + public IReadOnlyList TierColours { get => tierColours; set { - if (value.Length == 0 || value == tierColours) - return; - - tierCount = value.Length; + tierCount = value.Count; tierColours = value; graphNeedsUpdate = true; diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs index 2c82faf7b2a3..577d79886cdf 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs @@ -53,10 +53,12 @@ public IEnumerable Objects public ArgonSongProgressGraph() : base(5) { + var colours = new List(); + for (int i = 0; i < 5; i++) - { - TierColours[i] = Colour4.White.Opacity(1 / 5f * 0.85f); - } + colours.Add(Colour4.White.Opacity(1 / 5f * 0.85f)); + + TierColours = colours; } } } From 66441d4421ac3a1a6cf4a4748424aa72bf3558af Mon Sep 17 00:00:00 2001 From: tsrk Date: Tue, 17 Jan 2023 13:16:11 +0000 Subject: [PATCH 10/31] test: remove test for ArgonSongProgressGraph --- .../TestSceneArgonSongProgressGraph.cs | 69 ------------------- 1 file changed, 69 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs deleted file mode 100644 index e7feadc72b08..000000000000 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneArgonSongProgressGraph.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using System.Diagnostics; -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Framework.Testing; -using osu.Framework.Utils; -using osu.Game.Rulesets.Objects; -using osu.Game.Screens.Play.HUD; - -namespace osu.Game.Tests.Visual.Gameplay -{ - [TestFixture] - public partial class TestSceneArgonSongProgressGraph : OsuTestScene - { - private TestArgonSongProgressGraph? graph; - - [SetUpSteps] - public void SetupSteps() - { - AddStep("add new big graph", () => - { - if (graph != null) - { - graph.Expire(); - graph = null; - } - - Add(graph = new TestArgonSongProgressGraph - { - RelativeSizeAxes = Axes.X, - Height = 200, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - }); - }); - } - - [Test] - public void Test() - { - AddAssert("ensure not created", () => graph!.CreationCount == 0); - AddStep("display values", displayRandomValues); - } - - private void displayRandomValues() - { - Debug.Assert(graph != null); - var objects = new List(); - for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000) - objects.Add(new HitObject { StartTime = i }); - - graph.Objects = objects; - } - - private partial class TestArgonSongProgressGraph : ArgonSongProgressGraph - { - public int CreationCount { get; private set; } - - protected override void RecreateGraph() - { - base.RecreateGraph(); - CreationCount++; - } - } - } -} From d91aa341e511285d00e682ea8781ac31a1dfc16b Mon Sep 17 00:00:00 2001 From: tsrk Date: Tue, 17 Jan 2023 13:16:47 +0000 Subject: [PATCH 11/31] refactor(ArgonSongProgress): reorder layering and make density graph visible for past time --- .../Screens/Play/HUD/ArgonSongProgress.cs | 29 +++++++++++++------ .../Screens/Play/HUD/ArgonSongProgressBar.cs | 19 ++++++++++-- .../Play/HUD/ArgonSongProgressGraph.cs | 4 +-- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index e5ee42e72a2f..8446abecd2f1 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Configuration; using osu.Game.Graphics; @@ -18,6 +19,7 @@ public partial class ArgonSongProgress : SongProgress private readonly SongProgressInfo info; private readonly ArgonSongProgressGraph graph; private readonly ArgonSongProgressBar bar; + private readonly Container graphContainer; private const float bar_height = 10; @@ -38,6 +40,8 @@ public ArgonSongProgress() { Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; + Masking = true; + CornerRadius = 5; Children = new Drawable[] { info = new SongProgressInfo @@ -48,20 +52,27 @@ public ArgonSongProgress() RelativeSizeAxes = Axes.X, ShowProgress = false }, - graph = new ArgonSongProgressGraph - { - Name = "Difficulty graph", - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - }, bar = new ArgonSongProgressBar(bar_height) { Name = "Seek bar", Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, OnSeek = time => player?.Seek(time), - } + }, + graphContainer = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Masking = true, + CornerRadius = 5, + Child = graph = new ArgonSongProgressGraph + { + Name = "Difficulty graph", + RelativeSizeAxes = Axes.Both, + Blending = BlendingParameters.Additive + }, + RelativeSizeAxes = Axes.X, + }, }; RelativeSizeAxes = Axes.X; } @@ -111,7 +122,7 @@ protected override void Update() { base.Update(); Height = bar.Height + bar_height + info.Height; - graph.Height = bar.Height; + graphContainer.Height = bar.Height; } protected override void PopIn() diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 3ac7223f1deb..d87359397eda 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -30,12 +31,19 @@ public partial class ArgonSongProgressBar : SliderBar, ISongProgressBar private readonly BindableBool showBackground = new BindableBool(); + private readonly ColourInfo mainColour; + private readonly ColourInfo mainColourDarkened; + private ColourInfo altColour; + private ColourInfo altColourDarkened; + public bool ShowBackground { get => showBackground.Value; set => showBackground.Value = value; } + public BindableBool Darken = new BindableBool(); + private const float alpha_threshold = 2500; public Action? OnSeek { get; set; } @@ -91,6 +99,7 @@ public ArgonSongProgressBar(float barHeight) { RelativeSizeAxes = Axes.Both, Alpha = 0, + Colour = Colour4.White.Darken(1 + 1 / 4f) }, catchupBar = new RoundedBar { @@ -107,11 +116,12 @@ public ArgonSongProgressBar(float barHeight) Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, CornerRadius = 5, - AccentColour = Color4.White, + AccentColour = mainColour = Color4.White, RelativeSizeAxes = Axes.Both }, }; catchupBaseDepth = catchupBar.Depth; + mainColourDarkened = Colour4.White.Darken(1 / 3f); } private void setupAlternateValue() @@ -135,13 +145,16 @@ private float normalizedReference [BackgroundDependencyLoader] private void load(OsuColour colours) { - catchupBar.AccentColour = colours.BlueLight; + catchupBar.AccentColour = altColour = colours.BlueLight; + altColourDarkened = colours.BlueLight.Darken(1 / 3f); showBackground.BindValueChanged(_ => updateBackground(), true); } private void updateBackground() { - background.FadeTo(showBackground.Value ? 1 : 0, 200, Easing.In); + background.FadeTo(showBackground.Value ? 1 / 4f : 0, 200, Easing.In); + catchupBar.TransformTo(nameof(catchupBar.AccentColour), ShowBackground ? altColour : altColourDarkened, 200, Easing.In); + playfieldBar.TransformTo(nameof(playfieldBar.AccentColour), ShowBackground ? mainColour : mainColourDarkened, 200, Easing.In); } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs index 577d79886cdf..0899476ed49c 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs @@ -20,7 +20,7 @@ public IEnumerable Objects { objects = value; - const int granularity = 300; + const int granularity = 200; int[] values = new int[granularity]; if (!objects.Any()) @@ -56,7 +56,7 @@ public ArgonSongProgressGraph() var colours = new List(); for (int i = 0; i < 5; i++) - colours.Add(Colour4.White.Opacity(1 / 5f * 0.85f)); + colours.Add(Colour4.White.Darken(1 + 1 / 5f).Opacity(1 / 5f)); TierColours = colours; } From f1989ba24d93717eac9843dfd8eb9984941a65dc Mon Sep 17 00:00:00 2001 From: tsrk Date: Tue, 17 Jan 2023 17:26:05 +0000 Subject: [PATCH 12/31] quality: remove unused `Darken` bindable boolean --- osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index d87359397eda..ff999aa6a332 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -42,8 +42,6 @@ public bool ShowBackground set => showBackground.Value = value; } - public BindableBool Darken = new BindableBool(); - private const float alpha_threshold = 2500; public Action? OnSeek { get; set; } From 45c5bd840310904dd36da949559777b8d4f66e69 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 14:37:09 +0900 Subject: [PATCH 13/31] Simplify HUD test to not require casting to specific `ProgressBar` type --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 713183ebaf3c..145f9380f88c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -213,17 +213,7 @@ public void TestInputDoesntWorkWhenHUDHidden() AddStep("attempt seek", () => { - switch (getSongProgress()) - { - case SongProgressBar defaultBar: - InputManager.MoveMouseTo(defaultBar); - break; - - case ArgonSongProgressBar argonBar: - InputManager.MoveMouseTo(argonBar); - break; - } - + InputManager.MoveMouseTo(getSongProgress() as Drawable); InputManager.Click(MouseButton.Left); }); From afc12e0b835adf6eae3447a7b2ddb611d04462b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 14:43:20 +0900 Subject: [PATCH 14/31] Tidy up `ISongProgressBar` interface --- osu.Game/Screens/Play/HUD/ISongProgressBar.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ISongProgressBar.cs b/osu.Game/Screens/Play/HUD/ISongProgressBar.cs index f1a219e18ba0..683037577d8e 100644 --- a/osu.Game/Screens/Play/HUD/ISongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ISongProgressBar.cs @@ -7,10 +7,14 @@ namespace osu.Game.Screens.Play.HUD { public interface ISongProgressBar { - public Action? OnSeek { get; set; } - public double StartTime { set; } - public double EndTime { set; } - public double CurrentTime { set; } + /// + /// Whether the progress bar should allow interaction, ie. to perform seek operations. + /// public bool Interactive { get; set; } + + /// + /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. + /// + public Action? OnSeek { get; set; } } } From 5429979049c822167dec6c86f8be5d52a14dcb7d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 14:55:41 +0900 Subject: [PATCH 15/31] Combine common code into `SongProgress` base class --- .../Visual/Gameplay/TestSceneSongProgress.cs | 6 +-- .../Screens/Play/HUD/ArgonSongProgress.cs | 34 ++------------- .../Screens/Play/HUD/DefaultSongProgress.cs | 43 +++---------------- osu.Game/Screens/Play/HUD/SongProgress.cs | 31 ++++++++++--- osu.Game/Skinning/LegacySongProgress.cs | 14 ++---- 5 files changed, 40 insertions(+), 88 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 415a3c5b079c..cecc24a807bc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -54,10 +54,10 @@ public void TestToggleSeeking() void applyToDefaultProgress(Action action) => this.ChildrenOfType().ForEach(action); - AddStep("allow seeking", () => applyToDefaultProgress(s => s.AllowSeeking.Value = true)); + AddStep("allow seeking", () => applyToDefaultProgress(s => s.Interactive.Value = true)); AddStep("hide graph", () => applyToDefaultProgress(s => s.ShowGraph.Value = false)); - AddStep("disallow seeking", () => applyToDefaultProgress(s => s.AllowSeeking.Value = false)); - AddStep("allow seeking", () => applyToDefaultProgress(s => s.AllowSeeking.Value = true)); + AddStep("disallow seeking", () => applyToDefaultProgress(s => s.Interactive.Value = false)); + AddStep("allow seeking", () => applyToDefaultProgress(s => s.Interactive.Value = true)); AddStep("show graph", () => applyToDefaultProgress(s => s.ShowGraph.Value = true)); } diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index 8446abecd2f1..4951ad174bb5 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -3,11 +3,9 @@ using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; @@ -23,11 +21,6 @@ public partial class ArgonSongProgress : SongProgress private const float bar_height = 10; - public readonly Bindable AllowSeeking = new BindableBool(); - - [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] - public Bindable ShowGraph { get; } = new BindableBool(true); - [Resolved] private DrawableRuleset? drawableRuleset { get; set; } @@ -80,14 +73,6 @@ public ArgonSongProgress() [BackgroundDependencyLoader] private void load() { - base.LoadComplete(); - - if (drawableRuleset != null) - { - if (player?.Configuration.AllowUserInteraction == true) - ((IBindable)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded); - } - info.ShowProgress = false; info.TextColour = Colour4.White; info.Font = OsuFont.Torus.With(size: 18, weight: FontWeight.Bold); @@ -95,7 +80,9 @@ private void load() protected override void LoadComplete() { - AllowSeeking.BindValueChanged(_ => updateBarVisibility(), true); + base.LoadComplete(); + + Interactive.BindValueChanged(_ => bar.Interactive = Interactive.Value, true); ShowGraph.BindValueChanged(_ => updateGraphVisibility(), true); } @@ -107,11 +94,6 @@ protected override void UpdateObjects(IEnumerable objects) info.EndTime = bar.EndTime = LastHitTime; } - private void updateBarVisibility() - { - bar.Interactive = AllowSeeking.Value; - } - private void updateGraphVisibility() { graph.FadeTo(ShowGraph.Value ? 1 : 0, 200, Easing.In); @@ -125,16 +107,6 @@ protected override void Update() graphContainer.Height = bar.Height; } - protected override void PopIn() - { - this.FadeIn(500, Easing.OutQuint); - } - - protected override void PopOut() - { - this.FadeOut(100); - } - protected override void UpdateProgress(double progress, bool isIntro) { bar.ReferenceTime = GameplayClock.CurrentTime; diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs index cb629a0b77bd..747f292e3099 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs @@ -3,12 +3,9 @@ using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.UI; using osuTK; namespace osu.Game.Screens.Play.HUD @@ -27,23 +24,9 @@ public partial class DefaultSongProgress : SongProgress private readonly SongProgressGraph graph; private readonly SongProgressInfo info; - /// - /// Whether seeking is allowed and the progress bar should be shown. - /// - public readonly Bindable AllowSeeking = new Bindable(); - - [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] - public Bindable ShowGraph { get; } = new BindableBool(true); - - public override bool HandleNonPositionalInput => AllowSeeking.Value; - public override bool HandlePositionalInput => AllowSeeking.Value; - [Resolved] private Player? player { get; set; } - [Resolved] - private DrawableRuleset? drawableRuleset { get; set; } - public DefaultSongProgress() { RelativeSizeAxes = Axes.X; @@ -75,34 +58,18 @@ public DefaultSongProgress() }; } - [BackgroundDependencyLoader(true)] + [BackgroundDependencyLoader] private void load(OsuColour colours) { - base.LoadComplete(); - - if (drawableRuleset != null) - { - if (player?.Configuration.AllowUserInteraction == true) - ((IBindable)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded); - } - graph.FillColour = bar.FillColour = colours.BlueLighter; } protected override void LoadComplete() { - AllowSeeking.BindValueChanged(_ => updateBarVisibility(), true); + Interactive.BindValueChanged(_ => updateBarVisibility(), true); ShowGraph.BindValueChanged(_ => updateGraphVisibility(), true); - } - protected override void PopIn() - { - this.FadeIn(500, Easing.OutQuint); - } - - protected override void PopOut() - { - this.FadeOut(100); + base.LoadComplete(); } protected override void UpdateObjects(IEnumerable objects) @@ -133,7 +100,7 @@ protected override void Update() private void updateBarVisibility() { - bar.Interactive = AllowSeeking.Value; + bar.Interactive = Interactive.Value; updateInfoMargin(); } @@ -150,7 +117,7 @@ private void updateGraphVisibility() private void updateInfoMargin() { - float finalMargin = bottom_bar_height + (AllowSeeking.Value ? handle_size.Y : 0) + (ShowGraph.Value ? graph_height : 0); + float finalMargin = bottom_bar_height + (Interactive.Value ? handle_size.Y : 0) + (ShowGraph.Value ? graph_height : 0); info.TransformTo(nameof(info.Margin), new MarginPadding { Bottom = finalMargin }, transition_duration, Easing.In); } } diff --git a/osu.Game/Screens/Play/HUD/SongProgress.cs b/osu.Game/Screens/Play/HUD/SongProgress.cs index 4504745eb90e..a708b07fc82c 100644 --- a/osu.Game/Screens/Play/HUD/SongProgress.cs +++ b/osu.Game/Screens/Play/HUD/SongProgress.cs @@ -4,8 +4,11 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; +using osu.Game.Configuration; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; using osu.Game.Skinning; @@ -16,18 +19,27 @@ public abstract partial class SongProgress : OverlayContainer, ISkinnableDrawabl { // Some implementations of this element allow seeking during gameplay playback. // Set a sane default of never handling input to override the behaviour provided by OverlayContainer. - public override bool HandleNonPositionalInput => false; - public override bool HandlePositionalInput => false; + public override bool HandleNonPositionalInput => Interactive.Value; + public override bool HandlePositionalInput => Interactive.Value; + protected override bool BlockScrollInput => false; + /// + /// Whether interaction should be allowed (ie. seeking). If false, interaction controls will not be displayed. + /// + /// + /// By default, this will be automatically decided based on the gameplay state. + /// + public readonly Bindable Interactive = new Bindable(); + + [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] + public Bindable ShowGraph { get; } = new BindableBool(true); + public bool UsesFixedAnchor { get; set; } [Resolved] protected IGameplayClock GameplayClock { get; private set; } = null!; - [Resolved(canBeNull: true)] - private DrawableRuleset? drawableRuleset { get; set; } - private IClock? referenceClock; private IEnumerable? objects; @@ -58,15 +70,22 @@ protected override void LoadComplete() protected virtual void UpdateObjects(IEnumerable objects) { } [BackgroundDependencyLoader] - private void load() + private void load(DrawableRuleset? drawableRuleset, Player? player) { if (drawableRuleset != null) { + if (player?.Configuration.AllowUserInteraction == true) + ((IBindable)Interactive).BindTo(drawableRuleset.HasReplayLoaded); + Objects = drawableRuleset.Objects; referenceClock = drawableRuleset.FrameStableClock; } } + protected override void PopIn() => this.FadeIn(500, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(100); + protected override void Update() { base.Update(); diff --git a/osu.Game/Skinning/LegacySongProgress.cs b/osu.Game/Skinning/LegacySongProgress.cs index 10d1431ed4ab..22aea99291b3 100644 --- a/osu.Game/Skinning/LegacySongProgress.cs +++ b/osu.Game/Skinning/LegacySongProgress.cs @@ -15,6 +15,10 @@ public partial class LegacySongProgress : SongProgress { private CircularProgress circularProgress = null!; + // Legacy song progress doesn't support interaction for now. + public override bool HandleNonPositionalInput => false; + public override bool HandlePositionalInput => false; + [BackgroundDependencyLoader] private void load() { @@ -56,16 +60,6 @@ private void load() }; } - protected override void PopIn() - { - this.FadeIn(500, Easing.OutQuint); - } - - protected override void PopOut() - { - this.FadeOut(100); - } - protected override void UpdateProgress(double progress, bool isIntro) { if (isIntro) From f9dd3f6defcf56255338de446931cbaa1f39ecdc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 15:10:01 +0900 Subject: [PATCH 16/31] Switch test to specifically target the argon verison of the progress bar --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 145f9380f88c..c7a4071d54b1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -188,7 +188,7 @@ public void TestHoldForMenuDoesWorkWhenHidden() [Test] public void TestInputDoesntWorkWhenHUDHidden() { - ISongProgressBar? getSongProgress() => hudOverlay.ChildrenOfType().SingleOrDefault(); + ArgonSongProgress? getSongProgress() => hudOverlay.ChildrenOfType().SingleOrDefault(); bool seeked = false; @@ -204,8 +204,8 @@ public void TestInputDoesntWorkWhenHUDHidden() Debug.Assert(progress != null); - progress.Interactive = true; - progress.OnSeek += _ => seeked = true; + progress.Interactive.Value = true; + progress.ChildrenOfType().Single().OnSeek += _ => seeked = true; }); AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false); From e8770b84cd2f81f6cf14aada7fa9f51e3ecf6d7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 15:11:13 +0900 Subject: [PATCH 17/31] Remove no longer necessary interface type --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- .../TestSceneMultiSpectatorScreen.cs | 2 +- .../Screens/Play/HUD/ArgonSongProgressBar.cs | 2 +- osu.Game/Screens/Play/HUD/ISongProgressBar.cs | 20 ------------------- osu.Game/Screens/Play/HUD/SongProgressBar.cs | 20 ++++++++++++------- 5 files changed, 16 insertions(+), 30 deletions(-) delete mode 100644 osu.Game/Screens/Play/HUD/ISongProgressBar.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index c7a4071d54b1..5e1412d79b85 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -213,7 +213,7 @@ public void TestInputDoesntWorkWhenHUDHidden() AddStep("attempt seek", () => { - InputManager.MoveMouseTo(getSongProgress() as Drawable); + InputManager.MoveMouseTo(getSongProgress()); InputManager.Click(MouseButton.Left); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index dd891b456cac..e09496b6e908 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -121,7 +121,7 @@ public void TestSpectatorPlayerInteractiveElementsHidden() AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && - p.ChildrenOfType().SingleOrDefault()?.Interactive == false)); + p.ChildrenOfType().SingleOrDefault()?.Interactive == false)); AddStep("restore config hud visibility", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); } diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index ff999aa6a332..a76b3d4b50bd 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Play.HUD { - public partial class ArgonSongProgressBar : SliderBar, ISongProgressBar + public partial class ArgonSongProgressBar : SliderBar { private readonly float baseHeight; private readonly float catchupBaseDepth; diff --git a/osu.Game/Screens/Play/HUD/ISongProgressBar.cs b/osu.Game/Screens/Play/HUD/ISongProgressBar.cs deleted file mode 100644 index 683037577d8e..000000000000 --- a/osu.Game/Screens/Play/HUD/ISongProgressBar.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; - -namespace osu.Game.Screens.Play.HUD -{ - public interface ISongProgressBar - { - /// - /// Whether the progress bar should allow interaction, ie. to perform seek operations. - /// - public bool Interactive { get; set; } - - /// - /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. - /// - public Action? OnSeek { get; set; } - } -} diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/SongProgressBar.cs index fade562e3c47..c2889d7e8ad0 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressBar.cs @@ -13,16 +13,16 @@ namespace osu.Game.Screens.Play.HUD { - public partial class SongProgressBar : SliderBar, ISongProgressBar + public partial class SongProgressBar : SliderBar { + /// + /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. + /// public Action? OnSeek { get; set; } - private readonly Box fill; - private readonly Container handleBase; - private readonly Container handleContainer; - - private bool showHandle; - + /// + /// Whether the progress bar should allow interaction, ie. to perform seek operations. + /// public bool Interactive { get => showHandle; @@ -57,6 +57,12 @@ public double CurrentTime set => CurrentNumber.Value = value; } + private readonly Box fill; + private readonly Container handleBase; + private readonly Container handleContainer; + + private bool showHandle; + public SongProgressBar(float barHeight, float handleBarHeight, Vector2 handleSize) { CurrentNumber.MinValue = 0; From 742a02607710b79e1c34a61581919815e20befd4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 15:24:03 +0900 Subject: [PATCH 18/31] Add comment mentioning why reference clock fallback logic is required --- osu.Game/Screens/Play/HUD/ArgonSongProgress.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index 4951ad174bb5..7f4123b09464 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -24,6 +24,8 @@ public partial class ArgonSongProgress : SongProgress [Resolved] private DrawableRuleset? drawableRuleset { get; set; } + // Even though `FrameStabilityContainer` caches as a `GameplayClock`, we need to check it directly via `drawableRuleset` + // as this calculator is not contained within the `FrameStabilityContainer` and won't see the dependency. private IClock referenceClock => drawableRuleset?.FrameStableClock ?? GameplayClock; [Resolved] From 7266d8e10d49027dc8117824f793ab8dc7108ee4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 15:31:55 +0900 Subject: [PATCH 19/31] Move "show difficulty graph" settings back to respective implementations to avoid legacy version showing it --- osu.Game/Screens/Play/HUD/ArgonSongProgress.cs | 5 +++++ osu.Game/Screens/Play/HUD/DefaultSongProgress.cs | 5 +++++ osu.Game/Screens/Play/HUD/SongProgress.cs | 4 ---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index 7f4123b09464..1290101138f6 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; @@ -21,6 +23,9 @@ public partial class ArgonSongProgress : SongProgress private const float bar_height = 10; + [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] + public Bindable ShowGraph { get; } = new BindableBool(true); + [Resolved] private DrawableRuleset? drawableRuleset { get; set; } diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs index 747f292e3099..a8bbe87e86e0 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osuTK; @@ -24,6 +26,9 @@ public partial class DefaultSongProgress : SongProgress private readonly SongProgressGraph graph; private readonly SongProgressInfo info; + [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] + public Bindable ShowGraph { get; } = new BindableBool(true); + [Resolved] private Player? player { get; set; } diff --git a/osu.Game/Screens/Play/HUD/SongProgress.cs b/osu.Game/Screens/Play/HUD/SongProgress.cs index a708b07fc82c..4ae79bda5d01 100644 --- a/osu.Game/Screens/Play/HUD/SongProgress.cs +++ b/osu.Game/Screens/Play/HUD/SongProgress.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; -using osu.Game.Configuration; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; using osu.Game.Skinning; @@ -32,9 +31,6 @@ public abstract partial class SongProgress : OverlayContainer, ISkinnableDrawabl /// public readonly Bindable Interactive = new Bindable(); - [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] - public Bindable ShowGraph { get; } = new BindableBool(true); - public bool UsesFixedAnchor { get; set; } [Resolved] From 1e5dd9165a270aca3a519124e4751912d38a5cb8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 15:37:46 +0900 Subject: [PATCH 20/31] Adjust `SkinnableTestScene` to give more breathing room to `RelativeSize` components --- osu.Game/Tests/Visual/SkinnableTestScene.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Tests/Visual/SkinnableTestScene.cs b/osu.Game/Tests/Visual/SkinnableTestScene.cs index e8f51f9afa9a..aab1b7299067 100644 --- a/osu.Game/Tests/Visual/SkinnableTestScene.cs +++ b/osu.Game/Tests/Visual/SkinnableTestScene.cs @@ -91,7 +91,7 @@ private Drawable createProvider(Skin skin, Func creationFunctio { RelativeSizeAxes = Axes.Both, BorderColour = Color4.White, - BorderThickness = 5, + BorderThickness = 3, Masking = true, Children = new Drawable[] @@ -142,8 +142,15 @@ void updateSizing() c.AutoSizeAxes = Axes.None; c.Size = Vector2.Zero; - c.RelativeSizeAxes = !autoSize ? Axes.Both : Axes.None; - c.AutoSizeAxes = autoSize ? Axes.Both : Axes.None; + if (autoSize) + c.AutoSizeAxes = Axes.Both; + else + { + c.RelativeSizeAxes = Axes.Both; + c.Anchor = Anchor.Centre; + c.Origin = Anchor.Centre; + c.Size = new Vector2(0.97f); + } } outlineBox.Alpha = autoSize ? 1 : 0; From 04c0a5d7283ff1185349e30666893e0e9cc71708 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 15:44:19 +0900 Subject: [PATCH 21/31] Update `TestSceneSongProgress` to properly work with new implementation --- .../Visual/Gameplay/TestSceneSongProgress.cs | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index cecc24a807bc..bd6a42f9c0d9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; @@ -38,29 +39,39 @@ public void SetupSteps() { AddStep("reset clock", () => gameplayClockContainer.Reset()); AddStep("set hit objects", setHitObjects); - } - - [Test] - public void TestDisplay() - { + AddStep("hook seeking", () => + { + applyToDefaultProgress(d => d.ChildrenOfType().Single().OnSeek += t => gameplayClockContainer.Seek(t)); + applyToArgonProgress(d => d.ChildrenOfType().Single().OnSeek += t => gameplayClockContainer.Seek(t)); + }); AddStep("seek to intro", () => gameplayClockContainer.Seek(skip_target_time)); AddStep("start", gameplayClockContainer.Start); - AddStep("stop", gameplayClockContainer.Stop); } [Test] - public void TestToggleSeeking() + public void TestBasic() { - void applyToDefaultProgress(Action action) => - this.ChildrenOfType().ForEach(action); - - AddStep("allow seeking", () => applyToDefaultProgress(s => s.Interactive.Value = true)); - AddStep("hide graph", () => applyToDefaultProgress(s => s.ShowGraph.Value = false)); - AddStep("disallow seeking", () => applyToDefaultProgress(s => s.Interactive.Value = false)); - AddStep("allow seeking", () => applyToDefaultProgress(s => s.Interactive.Value = true)); - AddStep("show graph", () => applyToDefaultProgress(s => s.ShowGraph.Value = true)); + AddToggleStep("toggle seeking", b => + { + applyToDefaultProgress(s => s.Interactive.Value = b); + applyToArgonProgress(s => s.Interactive.Value = b); + }); + + AddToggleStep("toggle graph", b => + { + applyToDefaultProgress(s => s.ShowGraph.Value = b); + applyToArgonProgress(s => s.ShowGraph.Value = b); + }); + + AddStep("stop", gameplayClockContainer.Stop); } + private void applyToArgonProgress(Action action) => + this.ChildrenOfType().ForEach(action); + + private void applyToDefaultProgress(Action action) => + this.ChildrenOfType().ForEach(action); + private void setHitObjects() { var objects = new List(); From bfb75730a99da5543172053741c3872aea813e87 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 15:45:16 +0900 Subject: [PATCH 22/31] Prefix subclasses of `DefaultSongProgress` with `Default` --- ...gressGraph.cs => TestSceneDefaultSongProgressGraph.cs} | 4 ++-- osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs | 2 +- osu.Game/Screens/Play/HUD/DefaultSongProgress.cs | 8 ++++---- .../HUD/{SongProgressBar.cs => DefaultSongProgressBar.cs} | 4 ++-- .../{SongProgressGraph.cs => DefaultSongProgressGraph.cs} | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) rename osu.Game.Tests/Visual/Gameplay/{TestSceneSongProgressGraph.cs => TestSceneDefaultSongProgressGraph.cs} (93%) rename osu.Game/Screens/Play/HUD/{SongProgressBar.cs => DefaultSongProgressBar.cs} (96%) rename osu.Game/Screens/Play/HUD/{SongProgressGraph.cs => DefaultSongProgressGraph.cs} (95%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgressGraph.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs similarity index 93% rename from osu.Game.Tests/Visual/Gameplay/TestSceneSongProgressGraph.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs index 5a6150297888..66671a506f39 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgressGraph.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public partial class TestSceneSongProgressGraph : OsuTestScene + public partial class TestSceneDefaultSongProgressGraph : OsuTestScene { private TestSongProgressGraph graph; @@ -59,7 +59,7 @@ private void displayRandomValues() graph.Objects = objects; } - private partial class TestSongProgressGraph : SongProgressGraph + private partial class TestSongProgressGraph : DefaultSongProgressGraph { public int CreationCount { get; private set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index bd6a42f9c0d9..61b15c092bd5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -41,7 +41,7 @@ public void SetupSteps() AddStep("set hit objects", setHitObjects); AddStep("hook seeking", () => { - applyToDefaultProgress(d => d.ChildrenOfType().Single().OnSeek += t => gameplayClockContainer.Seek(t)); + applyToDefaultProgress(d => d.ChildrenOfType().Single().OnSeek += t => gameplayClockContainer.Seek(t)); applyToArgonProgress(d => d.ChildrenOfType().Single().OnSeek += t => gameplayClockContainer.Seek(t)); }); AddStep("seek to intro", () => gameplayClockContainer.Seek(skip_target_time)); diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs index a8bbe87e86e0..91a34fe374ca 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs @@ -22,8 +22,8 @@ public partial class DefaultSongProgress : SongProgress private const float transition_duration = 200; - private readonly SongProgressBar bar; - private readonly SongProgressGraph graph; + private readonly DefaultSongProgressBar bar; + private readonly DefaultSongProgressGraph graph; private readonly SongProgressInfo info; [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] @@ -46,7 +46,7 @@ public DefaultSongProgress() Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, }, - graph = new SongProgressGraph + graph = new DefaultSongProgressGraph { RelativeSizeAxes = Axes.X, Origin = Anchor.BottomLeft, @@ -54,7 +54,7 @@ public DefaultSongProgress() Height = graph_height, Margin = new MarginPadding { Bottom = bottom_bar_height }, }, - bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size) + bar = new DefaultSongProgressBar(bottom_bar_height, graph_height, handle_size) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs similarity index 96% rename from osu.Game/Screens/Play/HUD/SongProgressBar.cs rename to osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs index c2889d7e8ad0..0e16067dccd8 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Play.HUD { - public partial class SongProgressBar : SliderBar + public partial class DefaultSongProgressBar : SliderBar { /// /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. @@ -63,7 +63,7 @@ public double CurrentTime private bool showHandle; - public SongProgressBar(float barHeight, float handleBarHeight, Vector2 handleSize) + public DefaultSongProgressBar(float barHeight, float handleBarHeight, Vector2 handleSize) { CurrentNumber.MinValue = 0; CurrentNumber.MaxValue = 1; diff --git a/osu.Game/Screens/Play/HUD/SongProgressGraph.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgressGraph.cs similarity index 95% rename from osu.Game/Screens/Play/HUD/SongProgressGraph.cs rename to osu.Game/Screens/Play/HUD/DefaultSongProgressGraph.cs index f69a1eccd658..bee5978817cf 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgressGraph.cs @@ -10,7 +10,7 @@ namespace osu.Game.Screens.Play.HUD { - public partial class SongProgressGraph : SquareGraph + public partial class DefaultSongProgressGraph : SquareGraph { private IEnumerable objects; From 8bfd8538897aa288af5a15663c817bff2a4216e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 16:04:14 +0900 Subject: [PATCH 23/31] Fix missing comment --- osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index a76b3d4b50bd..7483d9cb51e0 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -173,7 +173,7 @@ protected override void OnHoverLost(HoverLostEvent e) protected override void UpdateValue(float value) { - // + // Handled in Update } protected override void Update() From 8030194cd58fddf5b30e90597d339684f509f1f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 16:04:07 +0900 Subject: [PATCH 24/31] Use actual beatmap's hitobjects in test to better display density --- .../Visual/Gameplay/TestSceneSongProgress.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 61b15c092bd5..561d34285b5b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -2,14 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Testing; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; @@ -38,7 +36,7 @@ private void load() public void SetupSteps() { AddStep("reset clock", () => gameplayClockContainer.Reset()); - AddStep("set hit objects", setHitObjects); + AddStep("set hit objects", () => this.ChildrenOfType().ForEach(progress => progress.Objects = Beatmap.Value.Beatmap.HitObjects)); AddStep("hook seeking", () => { applyToDefaultProgress(d => d.ChildrenOfType().Single().OnSeek += t => gameplayClockContainer.Seek(t)); @@ -72,15 +70,6 @@ private void applyToArgonProgress(Action action) => private void applyToDefaultProgress(Action action) => this.ChildrenOfType().ForEach(action); - private void setHitObjects() - { - var objects = new List(); - for (double i = 0; i < 5000; i++) - objects.Add(new HitObject { StartTime = i }); - - this.ChildrenOfType().ForEach(progress => progress.Objects = objects); - } - protected override Drawable CreateDefaultImplementation() => new DefaultSongProgress(); protected override Drawable CreateArgonImplementation() => new ArgonSongProgress(); From 5ead85f461eb99775896d09f3931005e0857d030 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 16:13:43 +0900 Subject: [PATCH 25/31] Limit catch-up speed in test to emulate gameplay --- .../Visual/Gameplay/TestSceneSongProgress.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 561d34285b5b..05e0c05b61b0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; using osu.Game.Skinning; @@ -27,9 +28,17 @@ private void load() { Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - Add(gameplayClockContainer = new MasterGameplayClockContainer(Beatmap.Value, skip_target_time)); + FrameStabilityContainer frameStabilityContainer; - Dependencies.CacheAs(gameplayClockContainer); + Add(gameplayClockContainer = new MasterGameplayClockContainer(Beatmap.Value, skip_target_time) + { + Child = frameStabilityContainer = new FrameStabilityContainer + { + MaxCatchUpFrames = 1 + } + }); + + Dependencies.CacheAs(frameStabilityContainer); } [SetUpSteps] From 42e9b2b48cd8031ba9a75933845a09be14127ae9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 16:29:42 +0900 Subject: [PATCH 26/31] Tidy up clock logic in all `SongProgress` classes --- .../Visual/Gameplay/TestSceneSongProgress.cs | 3 ++- .../Screens/Play/HUD/ArgonSongProgress.cs | 13 ++--------- .../Screens/Play/HUD/ArgonSongProgressBar.cs | 22 +++++++++---------- .../ClicksPerSecondCalculator.cs | 8 +++---- osu.Game/Screens/Play/HUD/SongProgress.cs | 15 ++++++++----- osu.Game/Screens/Play/Player.cs | 1 + 6 files changed, 29 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 05e0c05b61b0..76cd1b56d762 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -38,7 +38,8 @@ private void load() } }); - Dependencies.CacheAs(frameStabilityContainer); + Dependencies.CacheAs(gameplayClockContainer); + Dependencies.CacheAs(frameStabilityContainer); } [SetUpSteps] diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index 1290101138f6..3a2cd6fe2ac1 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -6,11 +6,9 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Timing; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Play.HUD { @@ -26,13 +24,6 @@ public partial class ArgonSongProgress : SongProgress [SettingSource("Show difficulty graph", "Whether a graph displaying difficulty throughout the beatmap should be shown")] public Bindable ShowGraph { get; } = new BindableBool(true); - [Resolved] - private DrawableRuleset? drawableRuleset { get; set; } - - // Even though `FrameStabilityContainer` caches as a `GameplayClock`, we need to check it directly via `drawableRuleset` - // as this calculator is not contained within the `FrameStabilityContainer` and won't see the dependency. - private IClock referenceClock => drawableRuleset?.FrameStableClock ?? GameplayClock; - [Resolved] private Player? player { get; set; } @@ -116,12 +107,12 @@ protected override void Update() protected override void UpdateProgress(double progress, bool isIntro) { - bar.ReferenceTime = GameplayClock.CurrentTime; + bar.TrackTime = GameplayClock.CurrentTime; if (isIntro) bar.CurrentTime = 0; else - bar.CurrentTime = referenceClock.CurrentTime; + bar.CurrentTime = FrameStableClock.CurrentTime; } } } diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 7483d9cb51e0..f69d56873d1a 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -64,21 +64,21 @@ public double CurrentTime set => CurrentNumber.Value = value; } - public double ReferenceTime + public double TrackTime { - private get => currentReference.Value; - set => currentReference.Value = value; + private get => currentTrackTime.Value; + set => currentTrackTime.Value = value; } private double length => EndTime - StartTime; - private readonly BindableNumber currentReference; + private readonly BindableNumber currentTrackTime; public bool Interactive { get; set; } public ArgonSongProgressBar(float barHeight) { - currentReference = new BindableDouble(); + currentTrackTime = new BindableDouble(); setupAlternateValue(); StartTime = 0; @@ -124,9 +124,9 @@ public ArgonSongProgressBar(float barHeight) private void setupAlternateValue() { - CurrentNumber.MaxValueChanged += v => currentReference.MaxValue = v; - CurrentNumber.MinValueChanged += v => currentReference.MinValue = v; - CurrentNumber.PrecisionChanged += v => currentReference.Precision = v; + CurrentNumber.MaxValueChanged += v => currentTrackTime.MaxValue = v; + CurrentNumber.MinValueChanged += v => currentTrackTime.MinValue = v; + CurrentNumber.PrecisionChanged += v => currentTrackTime.Precision = v; } private float normalizedReference @@ -136,7 +136,7 @@ private float normalizedReference if (EndTime - StartTime == 0) return 1; - return (float)((ReferenceTime - StartTime) / length); + return (float)((TrackTime - StartTime) / length); } } @@ -183,12 +183,12 @@ protected override void Update() playfieldBar.Length = (float)Interpolation.Lerp(playfieldBar.Length, NormalizedValue, Math.Clamp(Time.Elapsed / 40, 0, 1)); catchupBar.Length = (float)Interpolation.Lerp(catchupBar.Length, normalizedReference, Math.Clamp(Time.Elapsed / 40, 0, 1)); - if (ReferenceTime < CurrentTime) + if (TrackTime < CurrentTime) ChangeChildDepth(catchupBar, playfieldBar.Depth - 0.1f); else ChangeChildDepth(catchupBar, catchupBaseDepth); - float timeDelta = (float)(Math.Abs(CurrentTime - ReferenceTime)); + float timeDelta = (float)(Math.Abs(CurrentTime - TrackTime)); catchupBar.Alpha = MathHelper.Clamp(timeDelta, 0, alpha_threshold) / alpha_threshold; } diff --git a/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs b/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs index bf1f508d7b0a..ba0c47dc8b36 100644 --- a/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs +++ b/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs @@ -15,14 +15,12 @@ public partial class ClicksPerSecondCalculator : Component [Resolved] private IGameplayClock gameplayClock { get; set; } = null!; - [Resolved(canBeNull: true)] - private DrawableRuleset? drawableRuleset { get; set; } + [Resolved] + private IFrameStableClock? frameStableClock { get; set; } public int Value { get; private set; } - // Even though `FrameStabilityContainer` caches as a `GameplayClock`, we need to check it directly via `drawableRuleset` - // as this calculator is not contained within the `FrameStabilityContainer` and won't see the dependency. - private IGameplayClock clock => drawableRuleset?.FrameStableClock ?? gameplayClock; + private IGameplayClock clock => frameStableClock ?? gameplayClock; public ClicksPerSecondCalculator() { diff --git a/osu.Game/Screens/Play/HUD/SongProgress.cs b/osu.Game/Screens/Play/HUD/SongProgress.cs index 4ae79bda5d01..4647c0352bb3 100644 --- a/osu.Game/Screens/Play/HUD/SongProgress.cs +++ b/osu.Game/Screens/Play/HUD/SongProgress.cs @@ -36,7 +36,15 @@ public abstract partial class SongProgress : OverlayContainer, ISkinnableDrawabl [Resolved] protected IGameplayClock GameplayClock { get; private set; } = null!; - private IClock? referenceClock; + [Resolved] + private IFrameStableClock? frameStableClock { get; set; } + + /// + /// The reference clock is used to accurately tell the current playfield's time (including catch-up lag). + /// However, if none is available (i.e. used in tests), we fall back to the gameplay clock. + /// + protected IClock FrameStableClock => frameStableClock ?? GameplayClock; + private IEnumerable? objects; public IEnumerable Objects @@ -74,7 +82,6 @@ private void load(DrawableRuleset? drawableRuleset, Player? player) ((IBindable)Interactive).BindTo(drawableRuleset.HasReplayLoaded); Objects = drawableRuleset.Objects; - referenceClock = drawableRuleset.FrameStableClock; } } @@ -89,9 +96,7 @@ protected override void Update() if (objects == null) return; - // The reference clock is used to accurately tell the playfield's time. This is obtained from the drawable ruleset. - // However, if no drawable ruleset is available (i.e. used in tests), we fall back to the gameplay clock. - double currentTime = referenceClock?.CurrentTime ?? GameplayClock.CurrentTime; + double currentTime = FrameStableClock.CurrentTime; bool isInIntro = currentTime < FirstHitTime; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 05133fba3560..d3ab936a384e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -225,6 +225,7 @@ private void load(AudioManager audio, OsuConfigManager config, OsuGameBase game, DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, gameplayMods); dependencies.CacheAs(DrawableRuleset); + dependencies.CacheAs(DrawableRuleset.FrameStableClock); ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor.Mods.Value = gameplayMods; From f3677ab33dde950ef65d742b9a0169cbc17d6bb1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 16:38:21 +0900 Subject: [PATCH 27/31] Simplify depth change logic --- osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index f69d56873d1a..43969f2593fb 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -22,7 +22,6 @@ namespace osu.Game.Screens.Play.HUD public partial class ArgonSongProgressBar : SliderBar { private readonly float baseHeight; - private readonly float catchupBaseDepth; private readonly RoundedBar playfieldBar; private readonly RoundedBar catchupBar; @@ -118,7 +117,7 @@ public ArgonSongProgressBar(float barHeight) RelativeSizeAxes = Axes.Both }, }; - catchupBaseDepth = catchupBar.Depth; + mainColourDarkened = Colour4.White.Darken(1 / 3f); } @@ -184,9 +183,9 @@ protected override void Update() catchupBar.Length = (float)Interpolation.Lerp(catchupBar.Length, normalizedReference, Math.Clamp(Time.Elapsed / 40, 0, 1)); if (TrackTime < CurrentTime) - ChangeChildDepth(catchupBar, playfieldBar.Depth - 0.1f); + ChangeChildDepth(catchupBar, -1); else - ChangeChildDepth(catchupBar, catchupBaseDepth); + ChangeChildDepth(catchupBar, 0); float timeDelta = (float)(Math.Abs(CurrentTime - TrackTime)); catchupBar.Alpha = MathHelper.Clamp(timeDelta, 0, alpha_threshold) / alpha_threshold; From 01558a919952c0965c4661b6f538ceae1fe2d3c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 16:56:07 +0900 Subject: [PATCH 28/31] Tidy up height logic and allow hovering above bar for easier interaction --- .../Screens/Play/HUD/ArgonSongProgressBar.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 43969f2593fb..028ba7e35ba5 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -21,7 +20,12 @@ namespace osu.Game.Screens.Play.HUD { public partial class ArgonSongProgressBar : SliderBar { - private readonly float baseHeight; + public Action? OnSeek { get; set; } + + // Parent will handle restricting the area of valid input. + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + + private readonly float barHeight; private readonly RoundedBar playfieldBar; private readonly RoundedBar catchupBar; @@ -32,8 +36,8 @@ public partial class ArgonSongProgressBar : SliderBar private readonly ColourInfo mainColour; private readonly ColourInfo mainColourDarkened; - private ColourInfo altColour; - private ColourInfo altColourDarkened; + private ColourInfo catchUpColour; + private ColourInfo catchUpColourDarkened; public bool ShowBackground { @@ -43,8 +47,6 @@ public bool ShowBackground private const float alpha_threshold = 2500; - public Action? OnSeek { get; set; } - public double StartTime { private get => CurrentNumber.MinValue; @@ -84,8 +86,7 @@ public ArgonSongProgressBar(float barHeight) EndTime = 1; RelativeSizeAxes = Axes.X; - baseHeight = barHeight; - Height = baseHeight; + Height = this.barHeight = barHeight; CornerRadius = 5; Masking = true; @@ -142,31 +143,30 @@ private float normalizedReference [BackgroundDependencyLoader] private void load(OsuColour colours) { - catchupBar.AccentColour = altColour = colours.BlueLight; - altColourDarkened = colours.BlueLight.Darken(1 / 3f); + catchUpColour = colours.BlueLight; + catchUpColourDarkened = colours.BlueDark; + showBackground.BindValueChanged(_ => updateBackground(), true); } private void updateBackground() { background.FadeTo(showBackground.Value ? 1 / 4f : 0, 200, Easing.In); - catchupBar.TransformTo(nameof(catchupBar.AccentColour), ShowBackground ? altColour : altColourDarkened, 200, Easing.In); + catchupBar.TransformTo(nameof(catchupBar.AccentColour), ShowBackground ? catchUpColour : catchUpColourDarkened, 200, Easing.In); playfieldBar.TransformTo(nameof(playfieldBar.AccentColour), ShowBackground ? mainColour : mainColourDarkened, 200, Easing.In); } protected override bool OnHover(HoverEvent e) { if (Interactive) - this.ResizeHeightTo(baseHeight * 3.5f, 200, Easing.Out); + this.ResizeHeightTo(barHeight * 3.5f, 200, Easing.Out); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - if (Interactive) - this.ResizeHeightTo(baseHeight, 200, Easing.In); - + this.ResizeHeightTo(barHeight, 800, Easing.OutQuint); base.OnHoverLost(e); } From 67b40dd2343d279ac13b11b8f5c090e2a9fd1326 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 17:09:39 +0900 Subject: [PATCH 29/31] Adjust the seek effect to feel better --- osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 028ba7e35ba5..6db1072fbbc1 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -45,8 +45,6 @@ public bool ShowBackground set => showBackground.Value = value; } - private const float alpha_threshold = 2500; - public double StartTime { private get => CurrentNumber.MinValue; @@ -152,7 +150,6 @@ private void load(OsuColour colours) private void updateBackground() { background.FadeTo(showBackground.Value ? 1 / 4f : 0, 200, Easing.In); - catchupBar.TransformTo(nameof(catchupBar.AccentColour), ShowBackground ? catchUpColour : catchUpColourDarkened, 200, Easing.In); playfieldBar.TransformTo(nameof(playfieldBar.AccentColour), ShowBackground ? mainColour : mainColourDarkened, 200, Easing.In); } @@ -188,7 +185,17 @@ protected override void Update() ChangeChildDepth(catchupBar, 0); float timeDelta = (float)(Math.Abs(CurrentTime - TrackTime)); - catchupBar.Alpha = MathHelper.Clamp(timeDelta, 0, alpha_threshold) / alpha_threshold; + + const float colour_transition_threshold = 20000; + + catchupBar.AccentColour = Interpolation.ValueAt( + Math.Min(timeDelta, colour_transition_threshold), + ShowBackground ? mainColour : mainColourDarkened, + ShowBackground ? catchUpColour : catchUpColourDarkened, + 0, colour_transition_threshold, + Easing.OutQuint); + + catchupBar.Alpha = Math.Max(1, catchupBar.Length); } private ScheduledDelegate? scheduledSeek; From d4f2cd244db510f7d0096ad514e5af6214ad2067 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jan 2023 18:12:40 +0900 Subject: [PATCH 30/31] Fix broken test step --- osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 76cd1b56d762..5855838d3cf0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -53,7 +53,7 @@ public void SetupSteps() applyToArgonProgress(d => d.ChildrenOfType().Single().OnSeek += t => gameplayClockContainer.Seek(t)); }); AddStep("seek to intro", () => gameplayClockContainer.Seek(skip_target_time)); - AddStep("start", gameplayClockContainer.Start); + AddStep("start", () => gameplayClockContainer.Start()); } [Test] From b8b7442eb826f74d30383c3c8d81d50f097a48f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 18 Jan 2023 23:35:02 +0100 Subject: [PATCH 31/31] Make `SongProgressInfo.ShowProgress` init-only (and remove duplicate init) --- osu.Game/Screens/Play/HUD/ArgonSongProgress.cs | 1 - osu.Game/Screens/Play/HUD/SongProgressInfo.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index 3a2cd6fe2ac1..bfee6d295e40 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -71,7 +71,6 @@ public ArgonSongProgress() [BackgroundDependencyLoader] private void load() { - info.ShowProgress = false; info.TextColour = Colour4.White; info.Font = OsuFont.Torus.With(size: 18, weight: FontWeight.Bold); } diff --git a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs index 8a5c24a1f107..7f9f353dedf8 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs @@ -53,7 +53,7 @@ public double StartTime set => startTime = value; } - public bool ShowProgress = true; + public bool ShowProgress { get; init; } = true; public double EndTime {