diff --git a/.editorconfig b/.editorconfig index 8cdb92d11c..67f98f94eb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -135,7 +135,7 @@ csharp_preferred_modifier_order = public,private,protected,internal,new,abstract csharp_style_expression_bodied_accessors = true:warning csharp_style_expression_bodied_constructors = false:none csharp_style_expression_bodied_indexers = true:warning -csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_methods = false:silent csharp_style_expression_bodied_operators = true:warning csharp_style_expression_bodied_properties = true:warning csharp_style_expression_bodied_local_functions = true:silent diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimelineBlueprintContainer.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimelineBlueprintContainer.cs index e7b2508ac7..3c75fd5310 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimelineBlueprintContainer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimelineBlueprintContainer.cs @@ -1,146 +1,15 @@ // 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 System.Collections.Generic; using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects; -using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestSceneTimelineBlueprintContainer : EditorClockTestScene + public class TestSceneTimelineBlueprintContainer : TimelineTestScene { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(TimelineArea), - typeof(Timeline), - typeof(TimelineButton), - typeof(CentreMarker) - }; - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - Beatmap.Value = new WaveformTestBeatmap(audio); - - var editorBeatmap = new EditorBeatmap((Beatmap)Beatmap.Value.Beatmap, BeatDivisor); - - Dependencies.Cache(editorBeatmap); - Dependencies.CacheAs(editorBeatmap); - - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - Children = new Drawable[] - { - new StartStopButton(), - new AudioVisualiser(), - } - }, - new TimelineArea - { - Child = new TimelineBlueprintContainer(), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Size = new Vector2(0.8f, 100) - } - }; - } - - private class AudioVisualiser : CompositeDrawable - { - private readonly Drawable marker; - - [Resolved] - private IBindable beatmap { get; set; } - - [Resolved] - private IAdjustableClock adjustableClock { get; set; } - - public AudioVisualiser() - { - Size = new Vector2(250, 25); - - InternalChildren = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.25f, - }, - marker = new Box - { - RelativePositionAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Width = 2, - } - }; - } - - protected override void Update() - { - base.Update(); - - if (beatmap.Value.Track.IsLoaded) - marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length); - } - } - - private class StartStopButton : OsuButton - { - private IAdjustableClock adjustableClock; - private bool started; - - public StartStopButton() - { - BackgroundColour = Color4.SlateGray; - Size = new Vector2(100, 50); - Text = "Start"; - - Action = onClick; - } - - [BackgroundDependencyLoader] - private void load(IAdjustableClock adjustableClock) - { - this.adjustableClock = adjustableClock; - } - - private void onClick() - { - if (started) - { - adjustableClock.Stop(); - Text = "Start"; - } - else - { - adjustableClock.Start(); - Text = "Stop"; - } - - started = !started; - } - } + public override Drawable CreateTestComponent() => new TimelineBlueprintContainer(); } } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimelineTickDisplay.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimelineTickDisplay.cs new file mode 100644 index 0000000000..43a3cd6122 --- /dev/null +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimelineTickDisplay.cs @@ -0,0 +1,32 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Screens.Edit.Compose.Components.Timeline; +using osuTK; + +namespace osu.Game.Tests.Visual.Editor +{ + [TestFixture] + public class TestSceneTimelineTickDisplay : TimelineTestScene + { + public override Drawable CreateTestComponent() => new TimelineTickDisplay(); + + [BackgroundDependencyLoader] + private void load() + { + BeatDivisor.Value = 4; + + Add(new BeatDivisorControl(BeatDivisor) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding(30), + Size = new Vector2(90) + }); + } + } +} diff --git a/osu.Game.Tests/Visual/Editor/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editor/TimelineTestScene.cs new file mode 100644 index 0000000000..b5e526d3c2 --- /dev/null +++ b/osu.Game.Tests/Visual/Editor/TimelineTestScene.cs @@ -0,0 +1,148 @@ +// 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 System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects; +using osu.Game.Screens.Edit; +using osu.Game.Screens.Edit.Compose.Components.Timeline; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Editor +{ + public abstract class TimelineTestScene : EditorClockTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(TimelineArea), + typeof(Timeline), + typeof(TimelineButton), + typeof(CentreMarker) + }; + + protected TimelineArea TimelineArea { get; private set; } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + Beatmap.Value = new WaveformTestBeatmap(audio); + + var editorBeatmap = new EditorBeatmap((Beatmap)Beatmap.Value.Beatmap, BeatDivisor); + + Dependencies.Cache(editorBeatmap); + Dependencies.CacheAs(editorBeatmap); + + AddRange(new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + new StartStopButton(), + new AudioVisualiser(), + } + }, + TimelineArea = new TimelineArea + { + Child = CreateTestComponent(), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Size = new Vector2(0.8f, 100), + } + }); + } + + public abstract Drawable CreateTestComponent(); + + private class AudioVisualiser : CompositeDrawable + { + private readonly Drawable marker; + + [Resolved] + private IBindable beatmap { get; set; } + + [Resolved] + private IAdjustableClock adjustableClock { get; set; } + + public AudioVisualiser() + { + Size = new Vector2(250, 25); + + InternalChildren = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.25f, + }, + marker = new Box + { + RelativePositionAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Width = 2, + } + }; + } + + protected override void Update() + { + base.Update(); + + if (beatmap.Value.Track.IsLoaded) + marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length); + } + } + + private class StartStopButton : OsuButton + { + private IAdjustableClock adjustableClock; + private bool started; + + public StartStopButton() + { + BackgroundColour = Color4.SlateGray; + Size = new Vector2(100, 50); + Text = "Start"; + + Action = onClick; + } + + [BackgroundDependencyLoader] + private void load(IAdjustableClock adjustableClock) + { + this.adjustableClock = adjustableClock; + } + + private void onClick() + { + if (started) + { + adjustableClock.Stop(); + Text = "Start"; + } + else + { + adjustableClock.Start(); + Text = "Stop"; + } + + started = !started; + } + } + } +} diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index 471f67b7b6..0908e527a6 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -65,10 +66,14 @@ namespace osu.Game.Tests.Visual.Menus game.Dispose(); } + // see MouseSettings + var frameworkConfig = host.Dependencies.Get(); + frameworkConfig.GetBindable(FrameworkSetting.CursorSensitivity).Disabled = false; + game = new TestOsuGame(LocalStorage, API); game.SetHost(host); - // todo: this can be removed once we can run audio trakcs without a device present + // todo: this can be removed once we can run audio tracks without a device present // see https://github.com/ppy/osu/issues/1302 game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles); diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 8134c10750..3d63e2b07e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -8,6 +8,8 @@ using osu.Game.Online.API.Requests; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Overlays.Comments; +using osu.Game.Overlays; +using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.Online { @@ -28,6 +30,9 @@ namespace osu.Game.Tests.Visual.Online protected override bool UseOnlineAPI => true; + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + public TestSceneCommentsContainer() { BasicScrollContainer scroll; diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs index bc3e0eff1a..a60f220e4b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Game.Overlays; using osu.Game.Overlays.Comments; namespace osu.Game.Tests.Visual.Online @@ -19,6 +21,9 @@ namespace osu.Game.Tests.Visual.Online typeof(SortTabControl), }; + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + private readonly Bindable sort = new Bindable(); private readonly BindableBool showDeleted = new BindableBool(); diff --git a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs index f14c75084f..8ecbf0891b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs @@ -7,6 +7,8 @@ using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Game.Overlays.Comments; using osu.Framework.Utils; +using osu.Framework.Allocation; +using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { @@ -17,6 +19,9 @@ namespace osu.Game.Tests.Visual.Online typeof(TotalCommentsCounter), }; + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + public TestSceneTotalCommentsCounter() { var count = new BindableInt(); diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 98b8e3c5d6..fc06780431 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -118,6 +118,7 @@ namespace osu.Game.Tests.Visual.SongSelect InputManager.ReleaseKey(Key.Enter); }); + AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); AddAssert("ensure selection changed", () => selected != Beatmap.Value); AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen()); @@ -145,6 +146,7 @@ namespace osu.Game.Tests.Visual.SongSelect InputManager.ReleaseKey(Key.Down); }); + AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); AddAssert("ensure selection didn't change", () => selected == Beatmap.Value); AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen()); @@ -176,6 +178,7 @@ namespace osu.Game.Tests.Visual.SongSelect InputManager.ReleaseKey(Key.Enter); }); + AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); AddAssert("ensure selection changed", () => selected != Beatmap.Value); AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen()); @@ -208,6 +211,7 @@ namespace osu.Game.Tests.Visual.SongSelect InputManager.ReleaseButton(MouseButton.Left); }); + AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); AddAssert("ensure selection didn't change", () => selected == Beatmap.Value); AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen()); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs index be0933e9d4..c899ccb9eb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs @@ -7,9 +7,7 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; -using osu.Framework.Graphics.Sprites; using osu.Framework.Allocation; -using osu.Framework.Graphics.Textures; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; @@ -27,6 +25,7 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(TestStringTabControlHeader), typeof(TestEnumTabControlHeader), typeof(TestBreadcrumbControlHeader), + typeof(OverlayHeaderBackground) }; private readonly FillFlowContainer flow; @@ -52,10 +51,11 @@ namespace osu.Game.Tests.Visual.UserInterface } }); + addHeader("Orange OverlayHeader (no background)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange); addHeader("Blue OverlayHeader", new TestNoControlHeader(), OverlayColourScheme.Blue); addHeader("Green TabControlOverlayHeader (string)", new TestStringTabControlHeader(), OverlayColourScheme.Green); addHeader("Pink TabControlOverlayHeader (enum)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink); - addHeader("Red BreadcrumbControlOverlayHeader", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red); + addHeader("Red BreadcrumbControlOverlayHeader (no background)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red); } private void addHeader(string name, OverlayHeader header, OverlayColourScheme colourScheme) @@ -98,16 +98,21 @@ namespace osu.Game.Tests.Visual.UserInterface } } + private class TestNoBackgroundHeader : OverlayHeader + { + protected override ScreenTitle CreateTitle() => new TestTitle(); + } + private class TestNoControlHeader : OverlayHeader { - protected override Drawable CreateBackground() => new TestBackground(); + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/changelog"); protected override ScreenTitle CreateTitle() => new TestTitle(); } private class TestStringTabControlHeader : TabControlOverlayHeader { - protected override Drawable CreateBackground() => new TestBackground(); + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/news"); protected override ScreenTitle CreateTitle() => new TestTitle(); @@ -120,7 +125,7 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestEnumTabControlHeader : TabControlOverlayHeader { - protected override Drawable CreateBackground() => new TestBackground(); + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/rankings"); protected override ScreenTitle CreateTitle() => new TestTitle(); } @@ -134,8 +139,6 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestBreadcrumbControlHeader : BreadcrumbControlOverlayHeader { - protected override Drawable CreateBackground() => new TestBackground(); - protected override ScreenTitle CreateTitle() => new TestTitle(); public TestBreadcrumbControlHeader() @@ -146,21 +149,6 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestBackground : Sprite - { - public TestBackground() - { - RelativeSizeAxes = Axes.Both; - FillMode = FillMode.Fill; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Texture = textures.Get(@"Headers/changelog"); - } - } - private class TestTitle : ScreenTitle { public TestTitle() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs new file mode 100644 index 0000000000..5a0b28e24a --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osuTK; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneOverlayHeaderBackground : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OverlayHeaderBackground) + }; + + public TestSceneOverlayHeaderBackground() + { + Add(new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Children = new[] + { + new OverlayHeaderBackground(@"Headers/changelog"), + new OverlayHeaderBackground(@"Headers/news"), + new OverlayHeaderBackground(@"Headers/rankings"), + new OverlayHeaderBackground(@"Headers/search"), + } + } + }); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 2112aac6a3..5c6c7aeafd 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -36,6 +36,11 @@ namespace osu.Game.Graphics.UserInterface public virtual string TooltipText { get; private set; } + /// + /// Whether to format the tooltip as a percentage or the actual value. + /// + public bool DisplayAsPercentage { get; set; } + private Color4 accentColour; public Color4 AccentColour @@ -169,11 +174,11 @@ namespace osu.Game.Graphics.UserInterface else { double floatValue = value.ToDouble(NumberFormatInfo.InvariantInfo); - double floatMinValue = CurrentNumber.MinValue.ToDouble(NumberFormatInfo.InvariantInfo); - double floatMaxValue = CurrentNumber.MaxValue.ToDouble(NumberFormatInfo.InvariantInfo); - if (floatMaxValue == 1 && floatMinValue >= -1) + if (DisplayAsPercentage) + { TooltipText = floatValue.ToString("P0"); + } else { var decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 2fbfdec3d1..4165a180da 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -4,12 +4,9 @@ using System; 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.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; @@ -67,7 +64,7 @@ namespace osu.Game.Overlays.Changelog } } - protected override Drawable CreateBackground() => new HeaderBackground(); + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/changelog"); protected override Drawable CreateContent() => new Container { @@ -95,21 +92,6 @@ namespace osu.Game.Overlays.Changelog Streams.Current.Value = Streams.Items.FirstOrDefault(s => s.Name == Current.Value.UpdateStream.Name); } - public class HeaderBackground : Sprite - { - public HeaderBackground() - { - RelativeSizeAxes = Axes.Both; - FillMode = FillMode.Fill; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Texture = textures.Get(@"Headers/changelog"); - } - } - private class ChangelogHeaderTitle : ScreenTitle { public string Version diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index d252083411..78df73eb0d 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -8,7 +8,6 @@ using osu.Game.Online.API.Requests; using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using System.Threading; using System.Linq; @@ -27,28 +26,26 @@ namespace osu.Game.Overlays.Comments [Resolved] private IAPIProvider api { get; set; } - [Resolved] - private OsuColour colours { get; set; } - private GetCommentsRequest request; private CancellationTokenSource loadCancellation; private int currentPage; - private readonly Box background; - private readonly FillFlowContainer content; - private readonly DeletedChildrenPlaceholder deletedChildrenPlaceholder; - private readonly CommentsShowMoreButton moreButton; - private readonly TotalCommentsCounter commentCounter; + private FillFlowContainer content; + private DeletedChildrenPlaceholder deletedChildrenPlaceholder; + private CommentsShowMoreButton moreButton; + private TotalCommentsCounter commentCounter; - public CommentsContainer() + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; AddRangeInternal(new Drawable[] { - background = new Box + new Box { RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background5 }, new FillFlowContainer { @@ -78,7 +75,7 @@ namespace osu.Game.Overlays.Comments new Box { RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.2f) + Colour = colourProvider.Background4 }, new FillFlowContainer { @@ -113,12 +110,6 @@ namespace osu.Game.Overlays.Comments }); } - [BackgroundDependencyLoader] - private void load() - { - background.Colour = colours.Gray2; - } - protected override void LoadComplete() { Sort.BindValueChanged(_ => refetchComments(), true); diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 6a7a678cc7..ad80e67330 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -76,9 +76,9 @@ namespace osu.Game.Overlays.Comments } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OverlayColourProvider colourProvider) { - background.Colour = colours.Gray3; + background.Colour = colourProvider.Background4; } private class ShowDeletedButton : HeaderButton diff --git a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs index b0174e7b1a..ab65c9c63a 100644 --- a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs +++ b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs @@ -1,8 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Comments @@ -11,11 +11,12 @@ namespace osu.Game.Overlays.Comments { public readonly BindableInt Current = new BindableInt(); - public CommentsShowMoreButton() + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) { - IdleColour = OsuColour.Gray(0.3f); - HoverColour = OsuColour.Gray(0.4f); - ChevronIconColour = OsuColour.Gray(0.5f); + IdleColour = colourProvider.Background2; + HoverColour = colourProvider.Background1; + ChevronIconColour = colourProvider.Foreground1; } protected override void LoadComplete() diff --git a/osu.Game/Overlays/Comments/HeaderButton.cs b/osu.Game/Overlays/Comments/HeaderButton.cs index 8789cf5830..fdc8db35ab 100644 --- a/osu.Game/Overlays/Comments/HeaderButton.cs +++ b/osu.Game/Overlays/Comments/HeaderButton.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; @@ -45,9 +44,9 @@ namespace osu.Game.Overlays.Comments } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OverlayColourProvider colourProvider) { - background.Colour = colours.Gray4; + background.Colour = colourProvider.Background3; } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Overlays/Comments/SortTabControl.cs b/osu.Game/Overlays/Comments/SortTabControl.cs index a114197b8d..700d63351f 100644 --- a/osu.Game/Overlays/Comments/SortTabControl.cs +++ b/osu.Game/Overlays/Comments/SortTabControl.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Comments public readonly BindableBool Active = new BindableBool(); [Resolved] - private OsuColour colours { get; set; } + private OverlayColourProvider colourProvider { get; set; } private readonly SpriteText text; @@ -78,7 +78,7 @@ namespace osu.Game.Overlays.Comments updateBackgroundState(); text.Font = text.Font.With(weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium); - text.Colour = active.NewValue ? colours.BlueLighter : Color4.White; + text.Colour = active.NewValue ? colourProvider.Light1 : Color4.White; }, true); } diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs index 376853c1de..1bb9b52689 100644 --- a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -17,9 +16,10 @@ namespace osu.Game.Overlays.Comments { public readonly BindableInt Current = new BindableInt(); - private readonly SpriteText counter; + private OsuSpriteText counter; - public TotalCommentsCounter() + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) { RelativeSizeAxes = Axes.X; Height = 50; @@ -38,6 +38,7 @@ namespace osu.Game.Overlays.Comments Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: 20, italics: true), + Colour = colourProvider.Light1, Text = @"Comments" }, new CircularContainer @@ -51,14 +52,15 @@ namespace osu.Game.Overlays.Comments new Box { RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.05f) + Colour = colourProvider.Background6 }, counter = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), + Colour = colourProvider.Foreground1 } }, } @@ -66,12 +68,6 @@ namespace osu.Game.Overlays.Comments }); } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - counter.Colour = colours.BlueLighter; - } - protected override void LoadComplete() { Current.BindValueChanged(value => counter.Text = value.NewValue.ToString("N0"), true); diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 2f9cde1687..b525ba7a82 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -1,11 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Game.Graphics.UserInterface; using System; @@ -53,25 +50,10 @@ namespace osu.Game.Overlays.News } } - protected override Drawable CreateBackground() => new NewsHeaderBackground(); + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/news"); protected override ScreenTitle CreateTitle() => title = new NewsHeaderTitle(); - private class NewsHeaderBackground : Sprite - { - public NewsHeaderBackground() - { - RelativeSizeAxes = Axes.Both; - FillMode = FillMode.Fill; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Texture = textures.Get(@"Headers/news"); - } - } - private class NewsHeaderTitle : ScreenTitle { private const string post_string = "post"; diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 0575f6f296..5596f71dd0 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -14,16 +14,10 @@ namespace osu.Game.Overlays public abstract class OverlayHeader : Container { private readonly Box titleBackground; - private readonly Container background; private readonly ScreenTitle title; protected readonly FillFlowContainer HeaderInfo; - protected float BackgroundHeight - { - set => background.Height = value; - } - protected OverlayHeader() { RelativeSizeAxes = Axes.X; @@ -42,15 +36,9 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Depth = -float.MaxValue, - Children = new Drawable[] + Children = new[] { - background = new Container - { - RelativeSizeAxes = Axes.X, - Height = 80, - Masking = true, - Child = CreateBackground() - }, + CreateBackground(), new Container { RelativeSizeAxes = Axes.X, @@ -86,10 +74,11 @@ namespace osu.Game.Overlays title.AccentColour = colourProvider.Highlight1; } - protected abstract Drawable CreateBackground(); + [NotNull] + protected virtual Drawable CreateContent() => Drawable.Empty(); [NotNull] - protected virtual Drawable CreateContent() => new Container(); + protected virtual Drawable CreateBackground() => Drawable.Empty(); protected abstract ScreenTitle CreateTitle(); } diff --git a/osu.Game/Overlays/OverlayHeaderBackground.cs b/osu.Game/Overlays/OverlayHeaderBackground.cs new file mode 100644 index 0000000000..2fef593285 --- /dev/null +++ b/osu.Game/Overlays/OverlayHeaderBackground.cs @@ -0,0 +1,43 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Overlays +{ + public class OverlayHeaderBackground : CompositeDrawable + { + public OverlayHeaderBackground(string textureName) + { + Height = 80; + RelativeSizeAxes = Axes.X; + Masking = true; + InternalChild = new Background(textureName); + } + + private class Background : Sprite + { + private readonly string textureName; + + public Background(string textureName) + { + this.textureName = textureName; + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fill; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(textureName); + } + } + } +} diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 203df2ec12..3e78423a5a 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -25,8 +25,6 @@ namespace osu.Game.Overlays.Profile public ProfileHeader() { - BackgroundHeight = 150; - User.ValueChanged += e => updateDisplay(e.NewValue); TabControl.AddItem("info"); @@ -38,7 +36,9 @@ namespace osu.Game.Overlays.Profile protected override Drawable CreateBackground() => new Container { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + Height = 150, + Masking = true, Children = new Drawable[] { coverContainer = new UserCoverBackground diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 0124f7090e..bda677ecd6 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -17,10 +17,34 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { Children = new Drawable[] { - new SettingsSlider { LabelText = "Master", Bindable = audio.Volume, KeyboardStep = 0.01f }, - new SettingsSlider { LabelText = "Master (window inactive)", Bindable = config.GetBindable(OsuSetting.VolumeInactive), KeyboardStep = 0.01f }, - new SettingsSlider { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.01f }, - new SettingsSlider { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.01f }, + new SettingsSlider + { + LabelText = "Master", + Bindable = audio.Volume, + KeyboardStep = 0.01f, + DisplayAsPercentage = true + }, + new SettingsSlider + { + LabelText = "Master (window inactive)", + Bindable = config.GetBindable(OsuSetting.VolumeInactive), + KeyboardStep = 0.01f, + DisplayAsPercentage = true + }, + new SettingsSlider + { + LabelText = "Effect", + Bindable = audio.VolumeSample, + KeyboardStep = 0.01f, + DisplayAsPercentage = true + }, + new SettingsSlider + { + LabelText = "Music", + Bindable = audio.VolumeTrack, + KeyboardStep = 0.01f, + DisplayAsPercentage = true + }, }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 08bc67e43e..2d2cd42213 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -21,13 +21,15 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Background dim", Bindable = config.GetBindable(OsuSetting.DimLevel), - KeyboardStep = 0.01f + KeyboardStep = 0.01f, + DisplayAsPercentage = true }, new SettingsSlider { LabelText = "Background blur", Bindable = config.GetBindable(OsuSetting.BlurLevel), - KeyboardStep = 0.01f + KeyboardStep = 0.01f, + DisplayAsPercentage = true }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 02b9edd975..efbb08b7df 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -98,25 +98,29 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { LabelText = "Horizontal position", Bindable = scalingPositionX, - KeyboardStep = 0.01f + KeyboardStep = 0.01f, + DisplayAsPercentage = true }, new SettingsSlider { LabelText = "Vertical position", Bindable = scalingPositionY, - KeyboardStep = 0.01f + KeyboardStep = 0.01f, + DisplayAsPercentage = true }, new SettingsSlider { LabelText = "Horizontal scale", Bindable = scalingSizeX, - KeyboardStep = 0.01f + KeyboardStep = 0.01f, + DisplayAsPercentage = true }, new SettingsSlider { LabelText = "Vertical scale", Bindable = scalingSizeY, - KeyboardStep = 0.01f + KeyboardStep = 0.01f, + DisplayAsPercentage = true }, } }, diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 96c0279a7b..9fc3379b94 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings @@ -22,16 +23,32 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X }; + /// + /// When set, value changes based on user input are only transferred to any bound control's Current on commit. + /// This is useful if the UI interaction could be adversely affected by the value changing, such as the position of the on the screen. + /// public bool TransferValueOnCommit { get => ((TSlider)Control).TransferValueOnCommit; set => ((TSlider)Control).TransferValueOnCommit = value; } + /// + /// A custom step value for each key press which actuates a change on this control. + /// public float KeyboardStep { get => ((TSlider)Control).KeyboardStep; set => ((TSlider)Control).KeyboardStep = value; } + + /// + /// Whether to format the tooltip as a percentage or the actual value. + /// + public bool DisplayAsPercentage + { + get => ((TSlider)Control).DisplayAsPercentage; + set => ((TSlider)Control).DisplayAsPercentage = value; + } } } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 9ee3bacf9b..c413d25f09 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -137,12 +137,12 @@ namespace osu.Game.Rulesets.Edit } }; - toolboxCollection.Items = - CompositionTools.Select(t => new RadioButton(t.Name, () => selectTool(t))) - .Prepend(new RadioButton("Select", () => selectTool(null))) - .ToList(); + toolboxCollection.Items = CompositionTools + .Prepend(new SelectTool()) + .Select(t => new RadioButton(t.Name, () => toolSelected(t))) + .ToList(); - toolboxCollection.Items[0].Select(); + toolboxCollection.Items.First().Select(); blueprintContainer.SelectionChanged += selectionChanged; } @@ -187,11 +187,11 @@ namespace osu.Game.Rulesets.Edit showGridFor(hitObjects); } - private void selectTool(HitObjectCompositionTool tool) + private void toolSelected(HitObjectCompositionTool tool) { blueprintContainer.CurrentTool = tool; - if (tool == null) + if (tool is SelectTool) distanceSnapGridContainer.Hide(); else showGridFor(Enumerable.Empty()); diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs index 825c63e6ee..0631031302 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -13,5 +13,7 @@ namespace osu.Game.Rulesets.Edit.Tools } public abstract PlacementBlueprint CreatePlacementBlueprint(); + + public override string ToString() => Name; } } diff --git a/osu.Game/Rulesets/Edit/Tools/SelectTool.cs b/osu.Game/Rulesets/Edit/Tools/SelectTool.cs new file mode 100644 index 0000000000..b96eeb0790 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Tools/SelectTool.cs @@ -0,0 +1,15 @@ +// 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.Rulesets.Edit.Tools +{ + public class SelectTool : HitObjectCompositionTool + { + public SelectTool() + : base("Select") + { + } + + public override PlacementBlueprint CreatePlacementBlueprint() => null; + } +} diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index ce95d81f54..d9477dd4bc 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -52,30 +52,52 @@ namespace osu.Game.Screens.Edit { switch (beatDivisor) { + case 1: + return Color4.White; + case 2: - return colours.BlueLight; + return colours.Red; case 4: return colours.Blue; case 8: - return colours.BlueDarker; + return colours.Yellow; case 16: return colours.PurpleDark; case 3: - return colours.YellowLight; + return colours.Purple; case 6: - return colours.Yellow; + return colours.YellowDark; case 12: return colours.YellowDarker; default: - return Color4.White; + return Color4.Red; } } + + /// + /// Retrieves the applicable divisor for a specific beat index. + /// + /// The 0-based beat index. + /// The beat divisor. + /// The applicable divisor. + public static int GetDivisorForBeatIndex(int index, int beatDivisor) + { + int beat = index % beatDivisor; + + foreach (var divisor in BindableBeatDivisor.VALID_DIVISORS) + { + if ((beat * divisor) % beatDivisor == 0) + return divisor; + } + + return 0; + } } } diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs index 5854d66aa8..7be91f4e8e 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -37,8 +36,8 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons { this.button = button; - Text = button.Text; - Action = button.Action; + Text = button.Item.ToString(); + Action = button.Select; RelativeSizeAxes = Axes.X; @@ -100,19 +99,6 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons bubble.Colour = button.Selected.Value ? selectedBubbleColour : defaultBubbleColour; } - protected override bool OnClick(ClickEvent e) - { - if (button.Selected.Value) - return true; - - if (!Enabled.Value) - return true; - - button.Selected.Value = true; - - return base.OnClick(e); - } - protected override SpriteText CreateText() => new OsuSpriteText { Depth = -1, diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs index 3692c0437b..b515d7c8bd 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs @@ -15,33 +15,37 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons public readonly BindableBool Selected; /// - /// The text that should be displayed in this button. + /// The item related to this button. /// - public string Text; + public object Item; - /// - /// The that should be invoked when this button is selected. - /// - public Action Action; + private readonly Action action; - public RadioButton(string text, Action action) + public RadioButton(object item, Action action) { - Text = text; - Action = action; + Item = item; + this.action = action; Selected = new BindableBool(); } - public RadioButton(string text) - : this(text, null) + public RadioButton(string item) + : this(item, null) { - Text = text; - Action = null; + Item = item; + action = null; } /// /// Selects this . /// - public void Select() => Selected.Value = true; + public void Select() + { + if (!Selected.Value) + { + Selected.Value = true; + action?.Invoke(); + } + } /// /// Deselects this . diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs index 9c00cce57a..1ac960039e 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs @@ -12,7 +12,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations /// public class PointVisualisation : Box { - protected PointVisualisation(double startTime) + public PointVisualisation(double startTime) { Origin = Anchor.TopCentre; diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 53c5cf97fa..3bbccd612b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -130,19 +130,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// The applicable colour. protected ColourInfo GetColourForBeatIndex(int index) { - int beat = (index + 1) % beatDivisor.Value; - ColourInfo colour = Colours.Gray5; - - for (int i = 0; i < BindableBeatDivisor.VALID_DIVISORS.Length; i++) - { - int divisor = BindableBeatDivisor.VALID_DIVISORS[i]; - - if ((beat * divisor) % beatDivisor.Value == 0) - { - colour = BindableBeatDivisor.GetColourFor(divisor, Colours); - break; - } - } + var colour = BindableBeatDivisor.GetColourFor(BindableBeatDivisor.GetDivisorForBeatIndex(index + 1, beatDivisor.Value), Colours); int repeatIndex = index / beatDivisor.Value; return colour.MultiplyAlpha(0.5f / (repeatIndex + 1)); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs new file mode 100644 index 0000000000..f9b92c0504 --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -0,0 +1,90 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; + +namespace osu.Game.Screens.Edit.Compose.Components.Timeline +{ + public class TimelineTickDisplay : TimelinePart + { + [Resolved] + private EditorBeatmap beatmap { get; set; } + + [Resolved] + private Bindable working { get; set; } + + [Resolved] + private BindableBeatDivisor beatDivisor { get; set; } + + [Resolved] + private OsuColour colours { get; set; } + + public TimelineTickDisplay() + { + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + beatDivisor.BindValueChanged(_ => createLines(), true); + } + + private void createLines() + { + Clear(); + + for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) + { + var point = beatmap.ControlPointInfo.TimingPoints[i]; + var until = beatmap.ControlPointInfo.TimingPoints.Count < i + 1 ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; + + int beat = 0; + + for (double t = point.Time; t < until; t += point.BeatLength / beatDivisor.Value) + { + var indexInBeat = beat % beatDivisor.Value; + + if (indexInBeat == 0) + { + Add(new PointVisualisation(t) + { + Colour = BindableBeatDivisor.GetColourFor(1, colours), + Origin = Anchor.TopCentre, + }); + } + else + { + var divisor = BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value); + var colour = BindableBeatDivisor.GetColourFor(divisor, colours); + var height = 0.1f - (float)divisor / BindableBeatDivisor.VALID_DIVISORS.Last() * 0.08f; + + Add(new PointVisualisation(t) + { + Colour = colour, + Height = height, + Origin = Anchor.TopCentre, + }); + + Add(new PointVisualisation(t) + { + Colour = colour, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomCentre, + Height = height, + }); + } + + beat++; + } + } + } + } +} diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 8967f24185..7ee1005add 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -102,7 +102,11 @@ namespace osu.Game.Screens.Edit LoadComponentAsync(new TimelineArea { RelativeSizeAxes = Axes.Both, - Child = CreateTimelineContent() + Children = new[] + { + new TimelineTickDisplay(), + CreateTimelineContent(), + } }, timelineContainer.Add); }); } diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index ff64f35a18..9db3a587fa 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -27,12 +27,18 @@ namespace osu.Game.Screens.Play.PlayerSettings { Text = "Background dim:" }, - dimSliderBar = new PlayerSliderBar(), + dimSliderBar = new PlayerSliderBar + { + DisplayAsPercentage = true + }, new OsuSpriteText { Text = "Background blur:" }, - blurSliderBar = new PlayerSliderBar(), + blurSliderBar = new PlayerSliderBar + { + DisplayAsPercentage = true + }, new OsuSpriteText { Text = "Toggles:" diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index b7f60a8370..56c400e869 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -117,9 +117,20 @@ namespace osu.Game.Screens.Select.Details mod.ApplyToDifficulty(adjustedDifficulty); } - // Account for mania differences - firstValue.Title = (Beatmap?.Ruleset?.ID ?? 0) == 3 ? "Key Amount" : "Circle Size"; - firstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize); + switch (Beatmap?.Ruleset?.ID ?? 0) + { + case 3: + // Account for mania differences locally for now + // Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes + firstValue.Title = "Key Count"; + firstValue.Value = (baseDifficulty?.CircleSize ?? 0, null); + break; + + default: + firstValue.Title = "Circle Size"; + firstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize); + break; + } starDifficulty.Value = ((float)(Beatmap?.StarDifficulty ?? 0), null); diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 6d131bf423..e3b64c03b9 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -1,4 +1,4 @@ - + True True True @@ -245,7 +245,7 @@ RequiredForMultiline Explicit ExpressionBody - ExpressionBody + BlockBody True NEXT_LINE True