diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs new file mode 100644 index 0000000000..ddc1c8c128 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs @@ -0,0 +1,40 @@ +// 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 NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays; +using osu.Game.Overlays.Mods; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; + +namespace osu.Game.Tests.Visual.UserInterface +{ + [TestFixture] + public class TestSceneModSettingsArea : OsuTestScene + { + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + + [Test] + public void TestModToggleArea() + { + ModSettingsArea modSettingsArea = null; + + AddStep("create content", () => Child = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Child = modSettingsArea = new ModSettingsArea() + }); + AddStep("set DT", () => modSettingsArea.SelectedMods.Value = new[] { new OsuModDoubleTime() }); + AddStep("set DA", () => modSettingsArea.SelectedMods.Value = new Mod[] { new OsuModDifficultyAdjust() }); + AddStep("set FL+WU+DA+AD", () => modSettingsArea.SelectedMods.Value = new Mod[] { new OsuModFlashlight(), new ModWindUp(), new OsuModDifficultyAdjust(), new OsuModApproachDifferent() }); + AddStep("set empty", () => modSettingsArea.SelectedMods.Value = Array.Empty()); + } + } +} diff --git a/osu.Game/Overlays/Mods/ModSettingsArea.cs b/osu.Game/Overlays/Mods/ModSettingsArea.cs new file mode 100644 index 0000000000..e0a30f60c2 --- /dev/null +++ b/osu.Game/Overlays/Mods/ModSettingsArea.cs @@ -0,0 +1,176 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; +using osuTK; + +namespace osu.Game.Overlays.Mods +{ + public class ModSettingsArea : CompositeDrawable + { + public Bindable> SelectedMods { get; } = new Bindable>(); + + private readonly Box background; + private readonly FillFlowContainer modSettingsFlow; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } + + public ModSettingsArea() + { + RelativeSizeAxes = Axes.X; + Height = 250; + + Anchor = Anchor.BottomRight; + Origin = Anchor.BottomRight; + + InternalChild = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = 2, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new OsuScrollContainer(Direction.Horizontal) + { + RelativeSizeAxes = Axes.Both, + ScrollbarOverlapsContent = false, + Child = modSettingsFlow = new FillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding { Vertical = 7, Horizontal = 70 }, + Spacing = new Vector2(7), + Direction = FillDirection.Horizontal + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load() + { + background.Colour = colourProvider.Dark3; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + SelectedMods.BindValueChanged(_ => updateMods()); + } + + private void updateMods() + { + modSettingsFlow.Clear(); + + foreach (var mod in SelectedMods.Value.OrderBy(mod => mod.Type).ThenBy(mod => mod.Acronym)) + { + var settings = mod.CreateSettingsControls().ToList(); + + if (settings.Count > 0) + { + if (modSettingsFlow.Any()) + { + modSettingsFlow.Add(new Box + { + RelativeSizeAxes = Axes.Y, + Width = 2, + Colour = colourProvider.Dark4, + }); + } + + modSettingsFlow.Add(new ModSettingsColumn(mod, settings)); + } + } + } + + protected override bool OnMouseDown(MouseDownEvent e) => true; + protected override bool OnHover(HoverEvent e) => true; + + private class ModSettingsColumn : CompositeDrawable + { + public ModSettingsColumn(Mod mod, IEnumerable settingsControls) + { + Width = 250; + RelativeSizeAxes = Axes.Y; + Padding = new MarginPadding { Bottom = 7 }; + + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, 10), + new Dimension() + }, + Content = new[] + { + new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7), + Children = new Drawable[] + { + new ModSwitchTiny(mod) + { + Active = { Value = true }, + Scale = new Vector2(0.6f), + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft + }, + new OsuSpriteText + { + Text = mod.Name, + Font = OsuFont.Default.With(size: 16, weight: FontWeight.SemiBold), + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Margin = new MarginPadding { Bottom = 2 } + } + } + } + }, + new[] { Empty() }, + new Drawable[] + { + new OsuScrollContainer(Direction.Vertical) + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Right = 7 }, + ChildrenEnumerable = settingsControls, + Spacing = new Vector2(0, 7) + } + } + } + } + }; + } + } + } +}