From 0d8a7246dd6e6093c0d467eb2fc0f283d9f1a67b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 16:35:53 +0900 Subject: [PATCH 01/10] Add basic implementation of clock --- .../Visual/Menus/TestSceneToolbarClock.cs | 64 +++++++ osu.Game/Overlays/Toolbar/Toolbar.cs | 1 + osu.Game/Overlays/Toolbar/ToolbarClock.cs | 165 ++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs create mode 100644 osu.Game/Overlays/Toolbar/ToolbarClock.cs diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs new file mode 100644 index 0000000000..56ac1b24f1 --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays.Toolbar; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Menus +{ + [TestFixture] + public class TestSceneToolbarClock : OsuManualInputManagerTestScene + { + public TestSceneToolbarClock() + { + Children = new Drawable[] + { + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = Toolbar.HEIGHT, + Scale = new Vector2(4), + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new Box + { + Colour = Color4.DarkRed, + RelativeSizeAxes = Axes.Y, + Width = 2, + }, + new ToolbarClock(), + new Box + { + Colour = Color4.DarkRed, + RelativeSizeAxes = Axes.Y, + Width = 2, + }, + } + }, + } + }, + }; + } + } +} diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 776f7ad7b7..b7fb2e45be 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -104,6 +104,7 @@ namespace osu.Game.Overlays.Toolbar // Icon = FontAwesome.Solid.search //}, userButton = new ToolbarUserButton(), + new ToolbarClock(), new ToolbarNotificationButton(), } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs new file mode 100644 index 0000000000..b8dc7ccbbd --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -0,0 +1,165 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Toolbar +{ + public class ToolbarClock : CompositeDrawable + { + public ToolbarClock() + { + RelativeSizeAxes = Axes.Y; + Width = 110; + + Padding = new MarginPadding(10); + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new AnalogDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new DigitalDisplay + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + } + }; + } + + private class DigitalDisplay : ClockDisplay + { + private OsuSpriteText text; + + [BackgroundDependencyLoader] + private void load() + { + AutoSizeAxes = Axes.Y; + Width = 50; + + InternalChildren = new Drawable[] + { + text = new OsuSpriteText + { + Text = "00:00:00", + } + }; + } + + protected override void UpdateDisplay(DateTimeOffset now) + { + text.Text = $"{now:HH:mm:ss}"; + } + } + + private class AnalogDisplay : ClockDisplay + { + private Drawable hour; + private Drawable minute; + private Drawable second; + + [BackgroundDependencyLoader] + private void load() + { + Size = new Vector2(30); + + InternalChildren = new[] + { + new Circle + { + RelativeSizeAxes = Axes.Both, + }, + hour = new Hand + { + Colour = Color4.Orange, + Size = new Vector2(0.3f, 1.2f), + }, + minute = new Hand + { + Colour = Color4.Green, + Size = new Vector2(0.45f, 1), + }, + second = new Hand + { + Colour = Color4.Blue, + Size = new Vector2(0.48f, 0.5f), + }, + new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(1.5f), + Colour = Color4.Black, + }, + }; + } + + private class Hand : Circle + { + public Hand() + { + Anchor = Anchor.Centre; + Origin = Anchor.CentreLeft; + + RelativeSizeAxes = Axes.X; + } + } + + protected override void UpdateDisplay(DateTimeOffset now) + { + float secondFractional = now.Second / 60f; + float minuteFractional = (now.Minute + secondFractional) / 60f; + float hourFractional = ((minuteFractional + now.Hour) % 12) / 12f; + + updateRotation(hour, hourFractional); + updateRotation(minute, minuteFractional); + updateRotation(second, secondFractional); + } + + private void updateRotation(Drawable hand, float fraction) + { + const float duration = 320; + + float rotation = fraction * 360 - 90; + + if (Math.Abs(hand.Rotation - rotation) > 180) + hand.RotateTo(rotation); + else + hand.RotateTo(rotation, duration, Easing.OutElastic); + } + } + + private abstract class ClockDisplay : CompositeDrawable + { + private int lastSecond; + + protected override void Update() + { + base.Update(); + + var now = DateTimeOffset.Now; + + if (now.Second != lastSecond) + { + lastSecond = now.Second; + UpdateDisplay(now); + } + } + + protected abstract void UpdateDisplay(DateTimeOffset now); + } + } +} From e8f5a8e3d6cad69b1d55b66458ddbfc36fb9d7b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 17:22:48 +0900 Subject: [PATCH 02/10] Refactor hands for legibility (visual and code) --- osu.Game/Overlays/Toolbar/ToolbarClock.cs | 105 +++++++++++++++++----- 1 file changed, 82 insertions(+), 23 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index b8dc7ccbbd..a3c2994ffc 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -14,6 +15,8 @@ namespace osu.Game.Overlays.Toolbar { public class ToolbarClock : CompositeDrawable { + private const float hand_thickness = 2.2f; + public ToolbarClock() { RelativeSizeAxes = Axes.Y; @@ -72,7 +75,7 @@ namespace osu.Game.Overlays.Toolbar private Drawable second; [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { Size = new Vector2(30); @@ -82,38 +85,94 @@ namespace osu.Game.Overlays.Toolbar { RelativeSizeAxes = Axes.Both, }, - hour = new Hand - { - Colour = Color4.Orange, - Size = new Vector2(0.3f, 1.2f), - }, - minute = new Hand - { - Colour = Color4.Green, - Size = new Vector2(0.45f, 1), - }, - second = new Hand - { - Colour = Color4.Blue, - Size = new Vector2(0.48f, 0.5f), - }, - new Circle + hour = new LargeHand(0.3f), + minute = new LargeHand(0.45f), + second = new SecondHand(), + new CentreCircle { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(1.5f), - Colour = Color4.Black, - }, + } }; } - private class Hand : Circle + private class CentreCircle : CompositeDrawable { - public Hand() + public CentreCircle() + { + InternalChildren = new Drawable[] + { + new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(hand_thickness), + Colour = Color4.Black, + }, + new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(hand_thickness * 0.7f), + Colour = Color4.White, + }, + }; + } + } + + private class SecondHand : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.X; + Width = 0.54f; + + Height = hand_thickness / 2; + Anchor = Anchor.Centre; + Origin = Anchor.Custom; + + OriginPosition = new Vector2(Height * 2, Height / 2); + + InternalChildren = new Drawable[] + { + new Circle + { + Colour = colours.YellowDark, + RelativeSizeAxes = Axes.Both, + }, + }; + } + } + + private class LargeHand : CompositeDrawable + { + public LargeHand(float length) + { + Width = length; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) { Anchor = Anchor.Centre; Origin = Anchor.CentreLeft; + Origin = Anchor.Custom; + OriginPosition = new Vector2(hand_thickness / 2); // offset x also, to ensure the centre of the line is centered on the face. + Height = hand_thickness; + + InternalChildren = new Drawable[] + { + new Circle + { + Colour = colours.PurpleLight, + RelativeSizeAxes = Axes.Both, + BorderThickness = 0.5f, + BorderColour = colours.Purple, + }, + }; + RelativeSizeAxes = Axes.X; } } @@ -144,7 +203,7 @@ namespace osu.Game.Overlays.Toolbar private abstract class ClockDisplay : CompositeDrawable { - private int lastSecond; + private int? lastSecond; protected override void Update() { From 999ae88af2209af542acee1a55f38b80650fec0c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 17:55:33 +0900 Subject: [PATCH 03/10] Show game time display in clock --- .../Visual/Menus/TestSceneToolbarClock.cs | 17 ++++++- osu.Game/Overlays/Toolbar/ToolbarClock.cs | 46 ++++++++++++------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs index 56ac1b24f1..a8d25242ee 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; using osu.Game.Overlays.Toolbar; using osuTK; using osuTK.Graphics; @@ -14,11 +15,13 @@ namespace osu.Game.Tests.Visual.Menus [TestFixture] public class TestSceneToolbarClock : OsuManualInputManagerTestScene { + private readonly Container mainContainer; + public TestSceneToolbarClock() { Children = new Drawable[] { - new Container + mainContainer = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -60,5 +63,17 @@ namespace osu.Game.Tests.Visual.Menus }, }; } + + [Test] + public void TestRealGameTime() + { + AddStep("Set game time real", () => mainContainer.Clock = Clock); + } + + [Test] + public void TestLongGameTime() + { + AddStep("Set game time long", () => mainContainer.Clock = new FramedOffsetClock(Clock, false) { Offset = 3600.0 * 24 * 1000 * 98 }); + } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index a3c2994ffc..f7a92ebbe6 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Toolbar public ToolbarClock() { RelativeSizeAxes = Axes.Y; - Width = 110; + AutoSizeAxes = Axes.X; Padding = new MarginPadding(10); } @@ -28,43 +28,55 @@ namespace osu.Game.Overlays.Toolbar [BackgroundDependencyLoader] private void load() { - InternalChildren = new Drawable[] + InternalChild = new FillFlowContainer { - new AnalogDisplay + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - new DigitalDisplay - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, + new AnalogDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new DigitalDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } } }; } private class DigitalDisplay : ClockDisplay { - private OsuSpriteText text; + private OsuSpriteText realTime; + private OsuSpriteText gameTime; [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { AutoSizeAxes = Axes.Y; - Width = 50; + Width = 70; // Allows for space for game time up to 99 days. InternalChildren = new Drawable[] { - text = new OsuSpriteText + realTime = new OsuSpriteText(), + gameTime = new OsuSpriteText { - Text = "00:00:00", + Y = 14, + Colour = colours.PurpleLight, + Scale = new Vector2(0.6f) } }; } protected override void UpdateDisplay(DateTimeOffset now) { - text.Text = $"{now:HH:mm:ss}"; + realTime.Text = $"{now:HH:mm:ss}"; + gameTime.Text = $"running {new TimeSpan(TimeSpan.TicksPerSecond * (int)(Clock.CurrentTime / 1000)):c}"; } } @@ -75,7 +87,7 @@ namespace osu.Game.Overlays.Toolbar private Drawable second; [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { Size = new Vector2(30); From 252d1924e757331d23f2f6849e09497f864b5773 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 18:13:33 +0900 Subject: [PATCH 04/10] Adjust metrics for better legibility at small sizes --- osu.Game/Overlays/Toolbar/ToolbarClock.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index f7a92ebbe6..3cbf07c875 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Toolbar RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; - Padding = new MarginPadding(10); + Padding = new MarginPadding(5); } [BackgroundDependencyLoader] @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Toolbar private void load(OsuColour colours) { AutoSizeAxes = Axes.Y; - Width = 70; // Allows for space for game time up to 99 days. + Width = 66; // Allows for space for game time up to 99 days (in the padding area since this is quite rare). InternalChildren = new Drawable[] { @@ -89,7 +89,7 @@ namespace osu.Game.Overlays.Toolbar [BackgroundDependencyLoader] private void load() { - Size = new Vector2(30); + Size = new Vector2(20); InternalChildren = new[] { From 622458e8570309fb23ccf9064ad573d3af6dbbda Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 18:56:28 +0900 Subject: [PATCH 05/10] Allow scaling display in the test scene --- osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs index a8d25242ee..064d6f82fd 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs @@ -27,7 +27,6 @@ namespace osu.Game.Tests.Visual.Menus Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, Height = Toolbar.HEIGHT, - Scale = new Vector2(4), Children = new Drawable[] { new Box @@ -62,6 +61,8 @@ namespace osu.Game.Tests.Visual.Menus } }, }; + + AddSliderStep("scale", 0.5, 4, 1, scale => mainContainer.Scale = new Vector2((float)scale)); } [Test] From 97e9049a2c47945ad08f234216713abfc469b213 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 18:56:40 +0900 Subject: [PATCH 06/10] Adjust metrics and colours to better match the actual toolbar --- osu.Game/Overlays/Toolbar/ToolbarClock.cs | 40 ++++++++++++++--------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index 3cbf07c875..1cbad6a471 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Toolbar { public class ToolbarClock : CompositeDrawable { - private const float hand_thickness = 2.2f; + private const float hand_thickness = 2.4f; public ToolbarClock() { @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Toolbar gameTime = new OsuSpriteText { Y = 14, - Colour = colours.PurpleLight, + Colour = colours.PinkLight, Scale = new Vector2(0.6f) } }; @@ -89,16 +89,25 @@ namespace osu.Game.Overlays.Toolbar [BackgroundDependencyLoader] private void load() { - Size = new Vector2(20); + Size = new Vector2(22); InternalChildren = new[] { - new Circle + new CircularContainer { RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = 2, + BorderColour = Color4.White, + Child = new Box + { + AlwaysPresent = true, + Alpha = 0, + RelativeSizeAxes = Axes.Both + }, }, - hour = new LargeHand(0.3f), - minute = new LargeHand(0.45f), + hour = new LargeHand(0.34f), + minute = new LargeHand(0.48f), second = new SecondHand(), new CentreCircle { @@ -110,7 +119,8 @@ namespace osu.Game.Overlays.Toolbar private class CentreCircle : CompositeDrawable { - public CentreCircle() + [BackgroundDependencyLoader] + private void load(OsuColour colours) { InternalChildren = new Drawable[] { @@ -119,14 +129,14 @@ namespace osu.Game.Overlays.Toolbar Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(hand_thickness), - Colour = Color4.Black, + Colour = Color4.White, }, new Circle { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(hand_thickness * 0.7f), - Colour = Color4.White, + Colour = colours.PinkLight, }, }; } @@ -138,9 +148,9 @@ namespace osu.Game.Overlays.Toolbar private void load(OsuColour colours) { RelativeSizeAxes = Axes.X; - Width = 0.54f; + Width = 0.66f; - Height = hand_thickness / 2; + Height = hand_thickness * 0.7f; Anchor = Anchor.Centre; Origin = Anchor.Custom; @@ -150,7 +160,7 @@ namespace osu.Game.Overlays.Toolbar { new Circle { - Colour = colours.YellowDark, + Colour = colours.PinkLight, RelativeSizeAxes = Axes.Both, }, }; @@ -178,10 +188,10 @@ namespace osu.Game.Overlays.Toolbar { new Circle { - Colour = colours.PurpleLight, + Colour = Color4.White, RelativeSizeAxes = Axes.Both, - BorderThickness = 0.5f, - BorderColour = colours.Purple, + BorderThickness = 0.7f, + BorderColour = colours.Gray2, }, }; From 4ddf3cb1d9293d9e374a3c945bbfcb74d9fbe1c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 19:18:41 +0900 Subject: [PATCH 07/10] Add ability to cycle between clock display modes --- osu.Game/Configuration/OsuConfigManager.cs | 3 + .../Configuration/ToolbarClockDisplayMode.cs | 13 +++ osu.Game/Overlays/Toolbar/ToolbarClock.cs | 85 ++++++++++++++++++- 3 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Configuration/ToolbarClockDisplayMode.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index c279ce1220..e8f13ba902 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -44,6 +44,8 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2f, 1f); + SetDefault(OsuSetting.ToolbarClockDisplayMode, ToolbarClockDisplayMode.Full); + // Online settings SetDefault(OsuSetting.Username, string.Empty); SetDefault(OsuSetting.Token, string.Empty); @@ -295,6 +297,7 @@ namespace osu.Game.Configuration RandomSelectAlgorithm, ShowFpsDisplay, ChatDisplayHeight, + ToolbarClockDisplayMode, Version, ShowConvertedBeatmaps, Skin, diff --git a/osu.Game/Configuration/ToolbarClockDisplayMode.cs b/osu.Game/Configuration/ToolbarClockDisplayMode.cs new file mode 100644 index 0000000000..2f42f7a9b5 --- /dev/null +++ b/osu.Game/Configuration/ToolbarClockDisplayMode.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Configuration +{ + public enum ToolbarClockDisplayMode + { + Analog, + Digital, + DigitalWithRuntime, + Full + } +} diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index 1cbad6a471..68772d8fc3 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -3,9 +3,12 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; @@ -15,6 +18,11 @@ namespace osu.Game.Overlays.Toolbar { public class ToolbarClock : CompositeDrawable { + private Bindable clockDisplayMode; + + private DigitalDisplay digital; + private AnalogDisplay analog; + private const float hand_thickness = 2.4f; public ToolbarClock() @@ -26,8 +34,10 @@ namespace osu.Game.Overlays.Toolbar } [BackgroundDependencyLoader] - private void load() + private void load(OsuConfigManager config) { + clockDisplayMode = config.GetBindable(OsuSetting.ToolbarClockDisplayMode); + InternalChild = new FillFlowContainer { RelativeSizeAxes = Axes.Y, @@ -36,12 +46,12 @@ namespace osu.Game.Overlays.Toolbar Spacing = new Vector2(5), Children = new Drawable[] { - new AnalogDisplay + analog = new AnalogDisplay { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, - new DigitalDisplay + digital = new DigitalDisplay { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -50,16 +60,75 @@ namespace osu.Game.Overlays.Toolbar }; } + protected override void LoadComplete() + { + base.LoadComplete(); + + clockDisplayMode.BindValueChanged(displayMode => + { + bool showAnalog = displayMode.NewValue == ToolbarClockDisplayMode.Analog || displayMode.NewValue == ToolbarClockDisplayMode.Full; + bool showDigital = displayMode.NewValue != ToolbarClockDisplayMode.Analog; + bool showRuntime = displayMode.NewValue == ToolbarClockDisplayMode.DigitalWithRuntime || displayMode.NewValue == ToolbarClockDisplayMode.Full; + + digital.FadeTo(showDigital ? 1 : 0); + digital.ShowRuntime = showRuntime; + + analog.FadeTo(showAnalog ? 1 : 0); + }, true); + } + + protected override bool OnClick(ClickEvent e) + { + cycleDisplayMode(); + return true; + } + + private void cycleDisplayMode() + { + switch (clockDisplayMode.Value) + { + case ToolbarClockDisplayMode.Analog: + clockDisplayMode.Value = ToolbarClockDisplayMode.Full; + break; + + case ToolbarClockDisplayMode.Digital: + clockDisplayMode.Value = ToolbarClockDisplayMode.Analog; + break; + + case ToolbarClockDisplayMode.DigitalWithRuntime: + clockDisplayMode.Value = ToolbarClockDisplayMode.Digital; + break; + + case ToolbarClockDisplayMode.Full: + clockDisplayMode.Value = ToolbarClockDisplayMode.DigitalWithRuntime; + break; + } + } + private class DigitalDisplay : ClockDisplay { private OsuSpriteText realTime; private OsuSpriteText gameTime; + private bool showRuntime = true; + + public bool ShowRuntime + { + get => showRuntime; + set + { + if (showRuntime == value) + return; + + showRuntime = value; + updateMetrics(); + } + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { AutoSizeAxes = Axes.Y; - Width = 66; // Allows for space for game time up to 99 days (in the padding area since this is quite rare). InternalChildren = new Drawable[] { @@ -71,6 +140,8 @@ namespace osu.Game.Overlays.Toolbar Scale = new Vector2(0.6f) } }; + + updateMetrics(); } protected override void UpdateDisplay(DateTimeOffset now) @@ -78,6 +149,12 @@ namespace osu.Game.Overlays.Toolbar realTime.Text = $"{now:HH:mm:ss}"; gameTime.Text = $"running {new TimeSpan(TimeSpan.TicksPerSecond * (int)(Clock.CurrentTime / 1000)):c}"; } + + private void updateMetrics() + { + Width = showRuntime ? 66 : 45; // Allows for space for game time up to 99 days (in the padding area since this is quite rare). + gameTime.FadeTo(showRuntime ? 1 : 0); + } } private class AnalogDisplay : ClockDisplay From ab8db3b7dc1c4b68cfbc2885ba03e1840096357e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 20:34:17 +0900 Subject: [PATCH 08/10] Move nested classes to own files --- .../Overlays/Toolbar/AnalogClockDisplay.cs | 159 ++++++++++++ osu.Game/Overlays/Toolbar/ClockDisplay.cs | 28 +++ .../Overlays/Toolbar/DigitalClockDisplay.cs | 64 +++++ osu.Game/Overlays/Toolbar/ToolbarClock.cs | 230 +----------------- 4 files changed, 255 insertions(+), 226 deletions(-) create mode 100644 osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs create mode 100644 osu.Game/Overlays/Toolbar/ClockDisplay.cs create mode 100644 osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs diff --git a/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs b/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs new file mode 100644 index 0000000000..e100ee0c06 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs @@ -0,0 +1,159 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Toolbar +{ + public class AnalogClockDisplay : ClockDisplay + { + private const float hand_thickness = 2.4f; + + private Drawable hour; + private Drawable minute; + private Drawable second; + + [BackgroundDependencyLoader] + private void load() + { + Size = new Vector2(22); + + InternalChildren = new[] + { + new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = 2, + BorderColour = Color4.White, + Child = new Box + { + AlwaysPresent = true, + Alpha = 0, + RelativeSizeAxes = Axes.Both + }, + }, + hour = new LargeHand(0.34f), + minute = new LargeHand(0.48f), + second = new SecondHand(), + new CentreCircle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + + protected override void UpdateDisplay(DateTimeOffset now) + { + float secondFractional = now.Second / 60f; + float minuteFractional = (now.Minute + secondFractional) / 60f; + float hourFractional = ((minuteFractional + now.Hour) % 12) / 12f; + + updateRotation(hour, hourFractional); + updateRotation(minute, minuteFractional); + updateRotation(second, secondFractional); + } + + private void updateRotation(Drawable hand, float fraction) + { + const float duration = 320; + + float rotation = fraction * 360 - 90; + + if (Math.Abs(hand.Rotation - rotation) > 180) + hand.RotateTo(rotation); + else + hand.RotateTo(rotation, duration, Easing.OutElastic); + } + + private class CentreCircle : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChildren = new Drawable[] + { + new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(hand_thickness), + Colour = Color4.White, + }, + new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(hand_thickness * 0.7f), + Colour = colours.PinkLight, + }, + }; + } + } + + private class SecondHand : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.X; + Width = 0.66f; + + Height = hand_thickness * 0.7f; + Anchor = Anchor.Centre; + Origin = Anchor.Custom; + + OriginPosition = new Vector2(Height * 2, Height / 2); + + InternalChildren = new Drawable[] + { + new Circle + { + Colour = colours.PinkLight, + RelativeSizeAxes = Axes.Both, + }, + }; + } + } + + private class LargeHand : CompositeDrawable + { + public LargeHand(float length) + { + Width = length; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Anchor = Anchor.Centre; + Origin = Anchor.CentreLeft; + + Origin = Anchor.Custom; + OriginPosition = new Vector2(hand_thickness / 2); // offset x also, to ensure the centre of the line is centered on the face. + Height = hand_thickness; + + InternalChildren = new Drawable[] + { + new Circle + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + BorderThickness = 0.7f, + BorderColour = colours.Gray2, + }, + }; + + RelativeSizeAxes = Axes.X; + } + } + } +} diff --git a/osu.Game/Overlays/Toolbar/ClockDisplay.cs b/osu.Game/Overlays/Toolbar/ClockDisplay.cs new file mode 100644 index 0000000000..c1befbb198 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ClockDisplay.cs @@ -0,0 +1,28 @@ +// 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.Graphics.Containers; + +namespace osu.Game.Overlays.Toolbar +{ + public abstract class ClockDisplay : CompositeDrawable + { + private int? lastSecond; + + protected override void Update() + { + base.Update(); + + var now = DateTimeOffset.Now; + + if (now.Second != lastSecond) + { + lastSecond = now.Second; + UpdateDisplay(now); + } + } + + protected abstract void UpdateDisplay(DateTimeOffset now); + } +} diff --git a/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs b/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs new file mode 100644 index 0000000000..090f8c4a0f --- /dev/null +++ b/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs @@ -0,0 +1,64 @@ +// 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.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Overlays.Toolbar +{ + public class DigitalClockDisplay : ClockDisplay + { + private OsuSpriteText realTime; + private OsuSpriteText gameTime; + + private bool showRuntime = true; + + public bool ShowRuntime + { + get => showRuntime; + set + { + if (showRuntime == value) + return; + + showRuntime = value; + updateMetrics(); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AutoSizeAxes = Axes.Y; + + InternalChildren = new Drawable[] + { + realTime = new OsuSpriteText(), + gameTime = new OsuSpriteText + { + Y = 14, + Colour = colours.PinkLight, + Scale = new Vector2(0.6f) + } + }; + + updateMetrics(); + } + + protected override void UpdateDisplay(DateTimeOffset now) + { + realTime.Text = $"{now:HH:mm:ss}"; + gameTime.Text = $"running {new TimeSpan(TimeSpan.TicksPerSecond * (int)(Clock.CurrentTime / 1000)):c}"; + } + + private void updateMetrics() + { + Width = showRuntime ? 66 : 45; // Allows for space for game time up to 99 days (in the padding area since this is quite rare). + gameTime.FadeTo(showRuntime ? 1 : 0); + } + } +} diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index 68772d8fc3..332bfdf638 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -1,18 +1,13 @@ // 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.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Configuration; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Toolbar { @@ -20,10 +15,8 @@ namespace osu.Game.Overlays.Toolbar { private Bindable clockDisplayMode; - private DigitalDisplay digital; - private AnalogDisplay analog; - - private const float hand_thickness = 2.4f; + private DigitalClockDisplay digital; + private AnalogClockDisplay analog; public ToolbarClock() { @@ -46,12 +39,12 @@ namespace osu.Game.Overlays.Toolbar Spacing = new Vector2(5), Children = new Drawable[] { - analog = new AnalogDisplay + analog = new AnalogClockDisplay { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, - digital = new DigitalDisplay + digital = new DigitalClockDisplay { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -104,220 +97,5 @@ namespace osu.Game.Overlays.Toolbar break; } } - - private class DigitalDisplay : ClockDisplay - { - private OsuSpriteText realTime; - private OsuSpriteText gameTime; - - private bool showRuntime = true; - - public bool ShowRuntime - { - get => showRuntime; - set - { - if (showRuntime == value) - return; - - showRuntime = value; - updateMetrics(); - } - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AutoSizeAxes = Axes.Y; - - InternalChildren = new Drawable[] - { - realTime = new OsuSpriteText(), - gameTime = new OsuSpriteText - { - Y = 14, - Colour = colours.PinkLight, - Scale = new Vector2(0.6f) - } - }; - - updateMetrics(); - } - - protected override void UpdateDisplay(DateTimeOffset now) - { - realTime.Text = $"{now:HH:mm:ss}"; - gameTime.Text = $"running {new TimeSpan(TimeSpan.TicksPerSecond * (int)(Clock.CurrentTime / 1000)):c}"; - } - - private void updateMetrics() - { - Width = showRuntime ? 66 : 45; // Allows for space for game time up to 99 days (in the padding area since this is quite rare). - gameTime.FadeTo(showRuntime ? 1 : 0); - } - } - - private class AnalogDisplay : ClockDisplay - { - private Drawable hour; - private Drawable minute; - private Drawable second; - - [BackgroundDependencyLoader] - private void load() - { - Size = new Vector2(22); - - InternalChildren = new[] - { - new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = 2, - BorderColour = Color4.White, - Child = new Box - { - AlwaysPresent = true, - Alpha = 0, - RelativeSizeAxes = Axes.Both - }, - }, - hour = new LargeHand(0.34f), - minute = new LargeHand(0.48f), - second = new SecondHand(), - new CentreCircle - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - }; - } - - private class CentreCircle : CompositeDrawable - { - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - InternalChildren = new Drawable[] - { - new Circle - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(hand_thickness), - Colour = Color4.White, - }, - new Circle - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(hand_thickness * 0.7f), - Colour = colours.PinkLight, - }, - }; - } - } - - private class SecondHand : CompositeDrawable - { - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - RelativeSizeAxes = Axes.X; - Width = 0.66f; - - Height = hand_thickness * 0.7f; - Anchor = Anchor.Centre; - Origin = Anchor.Custom; - - OriginPosition = new Vector2(Height * 2, Height / 2); - - InternalChildren = new Drawable[] - { - new Circle - { - Colour = colours.PinkLight, - RelativeSizeAxes = Axes.Both, - }, - }; - } - } - - private class LargeHand : CompositeDrawable - { - public LargeHand(float length) - { - Width = length; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Anchor = Anchor.Centre; - Origin = Anchor.CentreLeft; - - Origin = Anchor.Custom; - OriginPosition = new Vector2(hand_thickness / 2); // offset x also, to ensure the centre of the line is centered on the face. - Height = hand_thickness; - - InternalChildren = new Drawable[] - { - new Circle - { - Colour = Color4.White, - RelativeSizeAxes = Axes.Both, - BorderThickness = 0.7f, - BorderColour = colours.Gray2, - }, - }; - - RelativeSizeAxes = Axes.X; - } - } - - protected override void UpdateDisplay(DateTimeOffset now) - { - float secondFractional = now.Second / 60f; - float minuteFractional = (now.Minute + secondFractional) / 60f; - float hourFractional = ((minuteFractional + now.Hour) % 12) / 12f; - - updateRotation(hour, hourFractional); - updateRotation(minute, minuteFractional); - updateRotation(second, secondFractional); - } - - private void updateRotation(Drawable hand, float fraction) - { - const float duration = 320; - - float rotation = fraction * 360 - 90; - - if (Math.Abs(hand.Rotation - rotation) > 180) - hand.RotateTo(rotation); - else - hand.RotateTo(rotation, duration, Easing.OutElastic); - } - } - - private abstract class ClockDisplay : CompositeDrawable - { - private int? lastSecond; - - protected override void Update() - { - base.Update(); - - var now = DateTimeOffset.Now; - - if (now.Second != lastSecond) - { - lastSecond = now.Second; - UpdateDisplay(now); - } - } - - protected abstract void UpdateDisplay(DateTimeOffset now); - } } } From 9b7b897b3cd14508ff0bee285093480ba4dae9f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Mar 2022 20:34:50 +0900 Subject: [PATCH 09/10] Adjust padding to fit better --- osu.Game/Overlays/Toolbar/ToolbarClock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index 332bfdf638..ad5c9ac7a1 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Toolbar RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; - Padding = new MarginPadding(5); + Padding = new MarginPadding(10); } [BackgroundDependencyLoader] From b6822f81909bea1f3fabd95e50dc9f50f410447a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 26 Mar 2022 14:55:19 +0300 Subject: [PATCH 10/10] Remove redundant/outdated `Origin` line --- osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs b/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs index e100ee0c06..9228900e99 100644 --- a/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs @@ -135,10 +135,10 @@ namespace osu.Game.Overlays.Toolbar private void load(OsuColour colours) { Anchor = Anchor.Centre; - Origin = Anchor.CentreLeft; - Origin = Anchor.Custom; + OriginPosition = new Vector2(hand_thickness / 2); // offset x also, to ensure the centre of the line is centered on the face. + Height = hand_thickness; InternalChildren = new Drawable[]