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/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/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index f825e4f1e9..523de4e38f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(TabControlOverlayHeader.OverlayHeaderTabControl), + typeof(TabControlOverlayHeader<>.OverlayHeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index eb812f5d5a..fc06780431 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -14,6 +14,7 @@ using osu.Framework.Extensions; using osu.Framework.Utils; using osu.Framework.Platform; using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Overlays; @@ -25,6 +26,7 @@ using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Screens.Select.Filter; +using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect { @@ -95,6 +97,127 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("filter count is 1", () => songSelect.FilterCount == 1); } + [Test] + public void TestChangeBeatmapBeforeEnter() + { + addRulesetImportStep(0); + + createSongSelect(); + + AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault); + + WorkingBeatmap selected = null; + + AddStep("store selected beatmap", () => selected = Beatmap.Value); + + AddStep("select next and enter", () => + { + InputManager.PressKey(Key.Down); + InputManager.ReleaseKey(Key.Down); + InputManager.PressKey(Key.Enter); + 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()); + AddUntilStep("bindable lease returned", () => !Beatmap.Disabled); + } + + [Test] + public void TestChangeBeatmapAfterEnter() + { + addRulesetImportStep(0); + + createSongSelect(); + + AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault); + + WorkingBeatmap selected = null; + + AddStep("store selected beatmap", () => selected = Beatmap.Value); + + AddStep("select next and enter", () => + { + InputManager.PressKey(Key.Enter); + InputManager.ReleaseKey(Key.Enter); + InputManager.PressKey(Key.Down); + 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()); + AddUntilStep("bindable lease returned", () => !Beatmap.Disabled); + } + + [Test] + public void TestChangeBeatmapViaMouseBeforeEnter() + { + addRulesetImportStep(0); + + createSongSelect(); + + AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault); + + WorkingBeatmap selected = null; + + AddStep("store selected beatmap", () => selected = Beatmap.Value); + + AddStep("select next and enter", () => + { + InputManager.MoveMouseTo(songSelect.Carousel.ChildrenOfType() + .First(b => ((CarouselBeatmap)b.Item).Beatmap != songSelect.Carousel.SelectedBeatmap)); + + InputManager.PressButton(MouseButton.Left); + InputManager.ReleaseButton(MouseButton.Left); + + InputManager.PressKey(Key.Enter); + 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()); + AddUntilStep("bindable lease returned", () => !Beatmap.Disabled); + } + + [Test] + public void TestChangeBeatmapViaMouseAfterEnter() + { + addRulesetImportStep(0); + + createSongSelect(); + + AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault); + + WorkingBeatmap selected = null; + + AddStep("store selected beatmap", () => selected = Beatmap.Value); + + AddStep("select next and enter", () => + { + InputManager.MoveMouseTo(songSelect.Carousel.ChildrenOfType() + .First(b => ((CarouselBeatmap)b.Item).Beatmap != songSelect.Carousel.SelectedBeatmap)); + + InputManager.PressButton(MouseButton.Left); + + InputManager.PressKey(Key.Enter); + InputManager.ReleaseKey(Key.Enter); + + 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()); + AddUntilStep("bindable lease returned", () => !Beatmap.Disabled); + } + [Test] public void TestNoFilterOnSimpleResume() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs new file mode 100644 index 0000000000..c899ccb9eb --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs @@ -0,0 +1,163 @@ +// 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 osu.Game.Graphics.Sprites; +using osu.Framework.Allocation; +using osu.Game.Graphics.UserInterface; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneOverlayHeader : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OverlayHeader), + typeof(TabControlOverlayHeader<>), + typeof(BreadcrumbControlOverlayHeader), + typeof(TestNoControlHeader), + typeof(TestStringTabControlHeader), + typeof(TestEnumTabControlHeader), + typeof(TestBreadcrumbControlHeader), + typeof(OverlayHeaderBackground) + }; + + private readonly FillFlowContainer flow; + + public TestSceneOverlayHeader() + { + AddRange(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = flow = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical + } + } + }); + + 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 (no background)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red); + } + + private void addHeader(string name, OverlayHeader header, OverlayColourScheme colourScheme) + { + flow.Add(new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding(20), + Text = name, + }, + new ColourProvidedContainer(colourScheme, header) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + } + } + }); + } + + private class ColourProvidedContainer : Container + { + [Cached] + private readonly OverlayColourProvider colourProvider; + + public ColourProvidedContainer(OverlayColourScheme colourScheme, OverlayHeader header) + { + colourProvider = new OverlayColourProvider(colourScheme); + + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + Add(header); + } + } + + private class TestNoBackgroundHeader : OverlayHeader + { + protected override ScreenTitle CreateTitle() => new TestTitle(); + } + + private class TestNoControlHeader : OverlayHeader + { + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/changelog"); + + protected override ScreenTitle CreateTitle() => new TestTitle(); + } + + private class TestStringTabControlHeader : TabControlOverlayHeader + { + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/news"); + + protected override ScreenTitle CreateTitle() => new TestTitle(); + + public TestStringTabControlHeader() + { + TabControl.AddItem("tab1"); + TabControl.AddItem("tab2"); + } + } + + private class TestEnumTabControlHeader : TabControlOverlayHeader + { + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/rankings"); + + protected override ScreenTitle CreateTitle() => new TestTitle(); + } + + private enum TestEnum + { + Some, + Cool, + Tabs + } + + private class TestBreadcrumbControlHeader : BreadcrumbControlOverlayHeader + { + protected override ScreenTitle CreateTitle() => new TestTitle(); + + public TestBreadcrumbControlHeader() + { + TabControl.AddItem("tab1"); + TabControl.AddItem("tab2"); + TabControl.Current.Value = "tab2"; + } + } + + private class TestTitle : ScreenTitle + { + public TestTitle() + { + Title = "title"; + Section = "section"; + } + + protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/changelog"); + } + } +} 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/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 1bfbee4a60..9fa6085035 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -21,6 +21,22 @@ namespace osu.Game.Graphics.UserInterface { public class OsuTabControl : TabControl { + private Color4 accentColour; + + public virtual Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + + if (Dropdown is IHasAccentColour dropdown) + dropdown.AccentColour = value; + foreach (var i in TabContainer.Children.OfType()) + i.AccentColour = value; + } + } + private readonly Box strip; protected override Dropdown CreateDropdown() => new OsuTabDropdown(); @@ -62,21 +78,6 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Blue; } - private Color4 accentColour; - - public Color4 AccentColour - { - get => accentColour; - set - { - accentColour = value; - if (Dropdown is IHasAccentColour dropdown) - dropdown.AccentColour = value; - foreach (var i in TabContainer.Children.OfType()) - i.AccentColour = value; - } - } - public Color4 StripColour { get => strip.Colour; diff --git a/osu.Game/IO/Legacy/SerializationWriter.cs b/osu.Game/IO/Legacy/SerializationWriter.cs index c75de93bc8..bb8014fe54 100644 --- a/osu.Game/IO/Legacy/SerializationWriter.cs +++ b/osu.Game/IO/Legacy/SerializationWriter.cs @@ -130,91 +130,91 @@ namespace osu.Game.IO.Legacy } else { - switch (obj.GetType().Name) + switch (obj) { - case "Boolean": + case bool boolObj: Write((byte)ObjType.boolType); - Write((bool)obj); + Write(boolObj); break; - case "Byte": + case byte byteObj: Write((byte)ObjType.byteType); - Write((byte)obj); + Write(byteObj); break; - case "UInt16": + case ushort ushortObj: Write((byte)ObjType.uint16Type); - Write((ushort)obj); + Write(ushortObj); break; - case "UInt32": + case uint uintObj: Write((byte)ObjType.uint32Type); - Write((uint)obj); + Write(uintObj); break; - case "UInt64": + case ulong ulongObj: Write((byte)ObjType.uint64Type); - Write((ulong)obj); + Write(ulongObj); break; - case "SByte": + case sbyte sbyteObj: Write((byte)ObjType.sbyteType); - Write((sbyte)obj); + Write(sbyteObj); break; - case "Int16": + case short shortObj: Write((byte)ObjType.int16Type); - Write((short)obj); + Write(shortObj); break; - case "Int32": + case int intObj: Write((byte)ObjType.int32Type); - Write((int)obj); + Write(intObj); break; - case "Int64": + case long longObj: Write((byte)ObjType.int64Type); - Write((long)obj); + Write(longObj); break; - case "Char": + case char charObj: Write((byte)ObjType.charType); - base.Write((char)obj); + base.Write(charObj); break; - case "String": + case string stringObj: Write((byte)ObjType.stringType); - base.Write((string)obj); + base.Write(stringObj); break; - case "Single": + case float floatObj: Write((byte)ObjType.singleType); - Write((float)obj); + Write(floatObj); break; - case "Double": + case double doubleObj: Write((byte)ObjType.doubleType); - Write((double)obj); + Write(doubleObj); break; - case "Decimal": + case decimal decimalObj: Write((byte)ObjType.decimalType); - Write((decimal)obj); + Write(decimalObj); break; - case "DateTime": + case DateTime dateTimeObj: Write((byte)ObjType.dateTimeType); - Write((DateTime)obj); + Write(dateTimeObj); break; - case "Byte[]": + case byte[] byteArray: Write((byte)ObjType.byteArrayType); - base.Write((byte[])obj); + base.Write(byteArray); break; - case "Char[]": + case char[] charArray: Write((byte)ObjType.charArrayType); - base.Write((char[])obj); + base.Write(charArray); break; default: diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs index c3f35b4313..1d8411dfcc 100644 --- a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs @@ -1,24 +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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays { - public abstract class BreadcrumbControlOverlayHeader : OverlayHeader + public abstract class BreadcrumbControlOverlayHeader : TabControlOverlayHeader { - protected OverlayHeaderBreadcrumbControl BreadcrumbControl; - - protected override TabControl CreateTabControl() => BreadcrumbControl = new OverlayHeaderBreadcrumbControl(); - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - BreadcrumbControl.AccentColour = colourProvider.Highlight1; - } + protected override OsuTabControl CreateTabControl() => new OverlayHeaderBreadcrumbControl(); public class OverlayHeaderBreadcrumbControl : BreadcrumbControl { diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 7755c0f64b..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; @@ -27,8 +24,8 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeader() { - BreadcrumbControl.AddItem(listing_string); - BreadcrumbControl.Current.ValueChanged += e => + TabControl.AddItem(listing_string); + TabControl.Current.ValueChanged += e => { if (e.NewValue == listing_string) ListingSelected?.Invoke(); @@ -48,12 +45,12 @@ namespace osu.Game.Overlays.Changelog private void showBuild(ValueChangedEvent e) { if (e.OldValue != null) - BreadcrumbControl.RemoveItem(e.OldValue.ToString()); + TabControl.RemoveItem(e.OldValue.ToString()); if (e.NewValue != null) { - BreadcrumbControl.AddItem(e.NewValue.ToString()); - BreadcrumbControl.Current.Value = e.NewValue.ToString(); + TabControl.AddItem(e.NewValue.ToString()); + TabControl.Current.Value = e.NewValue.ToString(); updateCurrentStream(); @@ -61,13 +58,13 @@ namespace osu.Game.Overlays.Changelog } else { - BreadcrumbControl.Current.Value = listing_string; + TabControl.Current.Value = listing_string; Streams.Current.Value = null; title.Version = null; } } - 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 1152d9044b..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; @@ -23,9 +20,9 @@ namespace osu.Game.Overlays.News public NewsHeader() { - BreadcrumbControl.AddItem(front_page_string); + TabControl.AddItem(front_page_string); - BreadcrumbControl.Current.ValueChanged += e => + TabControl.Current.ValueChanged += e => { if (e.NewValue == front_page_string) ShowFrontPage?.Invoke(); @@ -37,41 +34,26 @@ namespace osu.Game.Overlays.News private void showPost(ValueChangedEvent e) { if (e.OldValue != null) - BreadcrumbControl.RemoveItem(e.OldValue); + TabControl.RemoveItem(e.OldValue); if (e.NewValue != null) { - BreadcrumbControl.AddItem(e.NewValue); - BreadcrumbControl.Current.Value = e.NewValue; + TabControl.AddItem(e.NewValue); + TabControl.Current.Value = e.NewValue; title.IsReadingPost = true; } else { - BreadcrumbControl.Current.Value = front_page_string; + TabControl.Current.Value = front_page_string; title.IsReadingPost = false; } } - 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 bc58a17401..5596f71dd0 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; @@ -15,14 +14,9 @@ namespace osu.Game.Overlays public abstract class OverlayHeader : Container { private readonly Box titleBackground; - private readonly Box controlBackground; - private readonly Container background; private readonly ScreenTitle title; - protected float BackgroundHeight - { - set => background.Height = value; - } + protected readonly FillFlowContainer HeaderInfo; protected OverlayHeader() { @@ -36,46 +30,36 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new[] { - background = new Container - { - RelativeSizeAxes = Axes.X, - Height = 80, - Masking = true, - Child = CreateBackground() - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - titleBackground = new Box - { - RelativeSizeAxes = Axes.Both, - }, - title = CreateTitle().With(title => - { - title.Margin = new MarginPadding - { - Vertical = 10, - Left = UserProfileOverlay.CONTENT_X_MARGIN - }; - }) - } - }, - new Container + HeaderInfo = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, Depth = -float.MaxValue, - Children = new Drawable[] + Children = new[] { - controlBackground = new Box + CreateBackground(), + new Container { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + titleBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + title = CreateTitle().With(title => + { + title.Margin = new MarginPadding + { + Vertical = 10, + Left = UserProfileOverlay.CONTENT_X_MARGIN + }; + }) + } }, - CreateTabControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) } }, CreateContent() @@ -88,16 +72,14 @@ namespace osu.Game.Overlays { titleBackground.Colour = colourProvider.Dark5; title.AccentColour = colourProvider.Highlight1; - controlBackground.Colour = colourProvider.Dark4; } - 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(); - - protected abstract TabControl CreateTabControl(); } } 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/OverlayTabControl.cs b/osu.Game/Overlays/OverlayTabControl.cs index 812f8963c9..aa96f0e19b 100644 --- a/osu.Game/Overlays/OverlayTabControl.cs +++ b/osu.Game/Overlays/OverlayTabControl.cs @@ -13,41 +13,25 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public abstract class OverlayTabControl : TabControl + public abstract class OverlayTabControl : OsuTabControl { private readonly Box bar; - private Color4 accentColour = Color4.White; - - public Color4 AccentColour - { - get => accentColour; - set - { - if (accentColour == value) - return; - - accentColour = value; - bar.Colour = value; - - foreach (TabItem tabItem in TabContainer) - { - ((OverlayTabItem)tabItem).AccentColour = value; - } - } - } - - public new MarginPadding Padding - { - get => TabContainer.Padding; - set => TabContainer.Padding = value; - } - protected float BarHeight { set => bar.Height = value; } + public override Color4 AccentColour + { + get => base.AccentColour; + set + { + base.AccentColour = value; + bar.Colour = value; + } + } + protected OverlayTabControl() { TabContainer.Masking = false; @@ -66,7 +50,7 @@ namespace osu.Game.Overlays protected override TabItem CreateTabItem(T value) => new OverlayTabItem(value); - protected class OverlayTabItem : TabItem + protected class OverlayTabItem : TabItem, IHasAccentColour { protected readonly ExpandingBar Bar; protected readonly OsuSpriteText Text; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index f8eb03770a..3e78423a5a 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -14,7 +14,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.Profile { - public class ProfileHeader : TabControlOverlayHeader + public class ProfileHeader : TabControlOverlayHeader { private UserCoverBackground coverContainer; @@ -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/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index 0c55b8383b..b410739b25 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -1,28 +1,56 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osuTK; namespace osu.Game.Overlays { - public abstract class TabControlOverlayHeader : OverlayHeader + /// + /// An overlay header which contains a . + /// + /// The type of item to be represented by tabs. + public abstract class TabControlOverlayHeader : OverlayHeader { - protected OverlayHeaderTabControl TabControl; + protected OsuTabControl TabControl; - protected override TabControl CreateTabControl() => TabControl = new OverlayHeaderTabControl(); + private readonly Box controlBackground; + + protected TabControlOverlayHeader() + { + HeaderInfo.Add(new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + controlBackground = new Box + { + RelativeSizeAxes = Axes.Both, + }, + TabControl = CreateTabControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) + } + }); + } [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { TabControl.AccentColour = colourProvider.Highlight1; + controlBackground.Colour = colourProvider.Dark4; } - public class OverlayHeaderTabControl : OverlayTabControl + [NotNull] + protected virtual OsuTabControl CreateTabControl() => new OverlayHeaderTabControl(); + + public class OverlayHeaderTabControl : OverlayTabControl { public OverlayHeaderTabControl() { @@ -34,10 +62,7 @@ namespace osu.Game.Overlays Height = 35; } - protected override TabItem CreateTabItem(string value) => new OverlayHeaderTabItem(value) - { - AccentColour = AccentColour, - }; + protected override TabItem CreateTabItem(T value) => new OverlayHeaderTabItem(value); protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer { @@ -49,10 +74,10 @@ namespace osu.Game.Overlays private class OverlayHeaderTabItem : OverlayTabItem { - public OverlayHeaderTabItem(string value) + public OverlayHeaderTabItem(T value) : base(value) { - Text.Text = value; + Text.Text = value.ToString().ToLower(); Text.Font = OsuFont.GetFont(size: 14); Bar.ExpandedSize = 5; } 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 be1e121a99..d9477dd4bc 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -91,10 +91,8 @@ namespace osu.Game.Screens.Edit { int beat = index % beatDivisor; - for (int i = 0; i < BindableBeatDivisor.VALID_DIVISORS.Length; i++) + foreach (var divisor in BindableBeatDivisor.VALID_DIVISORS) { - int divisor = BindableBeatDivisor.VALID_DIVISORS[i]; - if ((beat * divisor) % beatDivisor == 0) return divisor; } 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/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/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 4433543ca1..2bb5ba612e 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -56,6 +56,9 @@ namespace osu.Game.Screens.Select public override bool HandleNonPositionalInput => AllowSelection; public override bool HandlePositionalInput => AllowSelection; + public override bool PropagatePositionalInputSubTree => AllowSelection; + public override bool PropagateNonPositionalInputSubTree => AllowSelection; + /// /// Whether carousel items have completed asynchronously loaded. /// @@ -449,8 +452,6 @@ namespace osu.Game.Screens.Select return true; } - protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) => ReceivePositionalInputAt(screenSpacePos); - protected override void Update() { base.Update(); 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.Game/Tests/Visual/ManualInputManagerTestScene.cs b/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs index 86191609a4..a0af07013c 100644 --- a/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs +++ b/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs @@ -8,6 +8,7 @@ using osu.Framework.Testing.Input; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Input.Bindings; using osuTK; using osuTK.Graphics; @@ -30,7 +31,11 @@ namespace osu.Game.Tests.Visual InputManager = new ManualInputManager { UseParentInput = true, - Child = content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }, + Child = new GlobalActionContainer(null) + { + RelativeSizeAxes = Axes.Both, + Child = content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both } + }, }, new Container { 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