diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index d76ff3f332..05ed03f01d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -1,6 +1,7 @@ // 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 System.Linq; using NUnit.Framework; @@ -10,16 +11,19 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Framework.Graphics.Cursor; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Rulesets; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; +using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneModPresetColumn : OsuTestScene + public class TestSceneModPresetColumn : OsuManualInputManagerTestScene { protected override bool UseFreshStoragePerRun => true; @@ -146,6 +150,61 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("3 panels visible", () => this.ChildrenOfType().Count() == 3); } + [Test] + public void TestAddingFlow() + { + ModPresetColumn modPresetColumn = null!; + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + AddAssert("add preset button disabled", () => !this.ChildrenOfType().Single().Enabled.Value); + + AddStep("set mods", () => SelectedMods.Value = new Mod[] { new OsuModDaycore(), new OsuModClassic() }); + AddAssert("add preset button enabled", () => this.ChildrenOfType().Single().Enabled.Value); + + AddStep("click add preset button", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddStep("attempt preset creation", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddWaitStep("wait some", 3); + AddAssert("preset creation did not occur", () => this.ChildrenOfType().Count() == 3); + AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); + + AddStep("fill preset name", () => popover.ChildrenOfType().First().Current.Value = "new preset"); + AddStep("attempt preset creation", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddUntilStep("preset creation occurred", () => this.ChildrenOfType().Count() == 4); + + AddStep("click add preset button", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + } + private ICollection createTestPresets() => new[] { new ModPreset diff --git a/osu.Game/Overlays/Mods/AddPresetButton.cs b/osu.Game/Overlays/Mods/AddPresetButton.cs index 44bdaeb9ac..e3aeb21f1d 100644 --- a/osu.Game/Overlays/Mods/AddPresetButton.cs +++ b/osu.Game/Overlays/Mods/AddPresetButton.cs @@ -1,6 +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 System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -8,9 +10,13 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; +using osu.Game.Database; +using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osuTK; using osu.Game.Localisation; @@ -21,6 +27,9 @@ namespace osu.Game.Overlays.Mods [Resolved] private OsuColour colours { get; set; } = null!; + [Resolved] + private Bindable> selectedMods { get; set; } = null!; + public AddPresetButton() : base(1) { @@ -35,6 +44,18 @@ namespace osu.Game.Overlays.Mods TextSize = 30; } + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedMods.BindValueChanged(val => Enabled.Value = val.NewValue.Any(), true); + Enabled.BindValueChanged(val => + { + if (!val.NewValue) + Active.Value = false; + }); + } + protected override void UpdateActiveState() { DarkerColour = Active.Value ? colours.Orange1 : ColourProvider.Background3; @@ -57,6 +78,15 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox descriptionTextBox; private readonly ShearedButton createButton; + [Resolved] + private Bindable ruleset { get; set; } = null!; + + [Resolved] + private Bindable> selectedMods { get; set; } = null!; + + [Resolved] + private RealmAccess realm { get; set; } = null!; + public AddPresetPopover(AddPresetButton addPresetButton) { button = addPresetButton; @@ -87,7 +117,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = ModSelectOverlayStrings.AddPreset, - Action = this.HidePopover + Action = tryCreatePreset } } }; @@ -104,6 +134,25 @@ namespace osu.Game.Overlays.Mods createButton.TextColour = colourProvider.Background6; } + private void tryCreatePreset() + { + if (string.IsNullOrWhiteSpace(nameTextBox.Current.Value)) + { + Body.Shake(); + return; + } + + realm.Write(r => r.Add(new ModPreset + { + Name = nameTextBox.Current.Value, + Description = descriptionTextBox.Current.Value, + Mods = selectedMods.Value.ToArray(), + Ruleset = r.Find(ruleset.Value.ShortName) + })); + + this.HidePopover(); + } + protected override void UpdateState(ValueChangedEvent state) { base.UpdateState(state);