From 4858d3fd4282e0f2ea48f3a5f1138f341d00edc6 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 7 Mar 2023 02:00:40 +0900 Subject: [PATCH 01/28] Added ability to edit mod presets --- .../UserInterface/TestSceneModPresetColumn.cs | 171 +++++++++++++++++- osu.Game/Overlays/Mods/EditPresetPopover.cs | 140 ++++++++++++++ osu.Game/Overlays/Mods/ModPresetPanel.cs | 8 +- 3 files changed, 316 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Overlays/Mods/EditPresetPopover.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 1090764788..f48c52ad40 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -243,7 +243,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); AddStep("click delete", () => { - var deleteItem = this.ChildrenOfType().Single(); + var deleteItem = this.ChildrenOfType().ElementAt(1); InputManager.MoveMouseTo(deleteItem); InputManager.Click(MouseButton.Left); }); @@ -261,6 +261,175 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("preset soft-deleted", () => Realm.Run(r => r.All().Count(preset => preset.DeletePending) == 1)); } + [Test] + public void TestEditPresentName() + { + ModPresetColumn modPresetColumn = null!; + string presetName = 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); + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + presetName = panel.Preset.Value.Name; + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddStep("clear preset name", () => popover.ChildrenOfType().First().Current.Value = ""); + AddStep("attempt preset edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + AddWaitStep("wait some", 3); + AddAssert("present is not changed", () => this.ChildrenOfType().First().Preset.Value.Name == presetName); + AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); + AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); + AddStep("attempt preset edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddAssert("present is changed", () => this.ChildrenOfType().First().Preset.Value.Name != presetName); + } + + [Test] + public void TestEditPresetMod() + { + ModPresetColumn modPresetColumn = null!; + var mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() }; + + 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); + AddStep("select mods", () => SelectedMods.Value = mods); + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddStep("enable switch", () => popover.ChildrenOfType().Single().Current.Value = true); + AddStep("attempt preset edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); + } + + [Test] + public void TestEditModSwitchDisableWithNoModSelest() + { + 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); + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + } + + [Test] + public void TestEditModSwitchDisableWithPresetSelest() + { + 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); + AddStep("select first preset mod", () => + SelectedMods.Value = this.ChildrenOfType().First().Preset.Value.Mods.ToList()); + + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddAssert("use current mod is enabled", () => popover.ChildrenOfType().Single().Current.Value == true); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + } + private ICollection createTestPresets() => new[] { new ModPreset diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs new file mode 100644 index 0000000000..270b6f43d9 --- /dev/null +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -0,0 +1,140 @@ +// 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; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Extensions; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Localisation; +using osu.Game.Rulesets.Mods; +using osuTK; + +namespace osu.Game.Overlays.Mods +{ + internal partial class EditPresetPopover : OsuPopover + { + private readonly ModPresetPanel button; + + private readonly LabelledTextBox nameTextBox; + private readonly LabelledTextBox descriptionTextBox; + private readonly LabelledSwitchButton useCurrentSwitch; + private readonly ShearedButton createButton; + + [Resolved] + private Bindable> selectedMods { get; set; } = null!; + + private readonly ModPreset preset; + + public EditPresetPopover(ModPresetPanel modPresetPanel) + { + button = modPresetPanel; + preset = button.Preset.Value; + + Child = new FillFlowContainer + { + Width = 300, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(7), + Children = new Drawable[] + { + nameTextBox = new LabelledTextBox + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Label = CommonStrings.Name, + TabbableContentContainer = this + }, + descriptionTextBox = new LabelledTextBox + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Label = CommonStrings.Description, + TabbableContentContainer = this + }, + useCurrentSwitch = new LabelledSwitchButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Label = "Use Current Mod select", + }, + createButton = new ShearedButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = CommonStrings.MenuBarEdit, + Action = tryEditPreset + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider, OsuColour colours) + { + Body.BorderThickness = 3; + Body.BorderColour = colours.Orange1; + + nameTextBox.Current.Value = preset.Name; + descriptionTextBox.Current.Value = preset.Description; + + selectedMods.BindValueChanged(_ => updateMods(), true); + + createButton.DarkerColour = colours.Orange1; + createButton.LighterColour = colours.Orange0; + createButton.TextColour = colourProvider.Background6; + } + + private void updateMods() + { + useCurrentSwitch.Current.Disabled = false; + + // disable the switch when mod is equal. + if (button.Active.Value) + { + useCurrentSwitch.Current.Value = true; + useCurrentSwitch.Current.Disabled = true; + } + else + { + useCurrentSwitch.Current.Value = false; + useCurrentSwitch.Current.Disabled = !selectedMods.Value.Any(); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(nameTextBox)); + } + + private void tryEditPreset() + { + if (string.IsNullOrWhiteSpace(nameTextBox.Current.Value)) + { + Body.Shake(); + return; + } + + button.Preset.PerformWrite(s => + { + s.Name = nameTextBox.Current.Value; + s.Description = descriptionTextBox.Current.Value; + + if (useCurrentSwitch.Current.Value) + { + s.Mods = selectedMods.Value.ToArray(); + } + }); + + this.HidePopover(); + } + } +} diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 6e12e34124..f4f1af50df 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; @@ -17,7 +18,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu + public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu, IHasPopover { public readonly Live Preset; @@ -91,7 +92,8 @@ namespace osu.Game.Overlays.Mods public MenuItem[] ContextMenuItems => new MenuItem[] { - new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))) + new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), + new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), }; #endregion @@ -102,5 +104,7 @@ namespace osu.Game.Overlays.Mods settingChangeTracker?.Dispose(); } + + public Popover GetPopover() => new EditPresetPopover(this); } } From 0095fd85cad0a7b8dcddd29c983991af959a57fb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 7 Mar 2023 02:18:34 +0900 Subject: [PATCH 02/28] remove `== true` --- .../Visual/UserInterface/TestSceneModPresetColumn.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index f48c52ad40..8fbc8940c7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -386,7 +386,7 @@ namespace osu.Game.Tests.Visual.UserInterface OsuPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); } [Test] @@ -422,12 +422,12 @@ namespace osu.Game.Tests.Visual.UserInterface OsuPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); - AddAssert("use current mod is enabled", () => popover.ChildrenOfType().Single().Current.Value == true); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + AddAssert("use current mod is enabled", () => popover.ChildrenOfType().Single().Current.Value); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); } private ICollection createTestPresets() => new[] From 54564e05578df03133636cad564becd6b892378f Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 7 Mar 2023 21:13:35 +0900 Subject: [PATCH 03/28] new design --- .../UserInterface/TestSceneModPresetColumn.cs | 86 ++----------------- osu.Game/Overlays/Mods/EditPresetPopover.cs | 62 ++++++------- 2 files changed, 38 insertions(+), 110 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 8fbc8940c7..d6065374ac 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -296,7 +296,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("clear preset name", () => popover.ChildrenOfType().First().Current.Value = ""); AddStep("attempt preset edit", () => { - InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); @@ -306,7 +306,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); AddStep("attempt preset edit", () => { - InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); @@ -345,91 +345,15 @@ namespace osu.Game.Tests.Visual.UserInterface OsuPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); - AddStep("enable switch", () => popover.ChildrenOfType().Single().Current.Value = true); - AddStep("attempt preset edit", () => + AddStep("click use current mods", () => { - InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); InputManager.Click(MouseButton.Left); }); - AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); } - [Test] - public void TestEditModSwitchDisableWithNoModSelest() - { - 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); - AddStep("right click first panel", () => - { - var panel = this.ChildrenOfType().First(); - InputManager.MoveMouseTo(panel); - InputManager.Click(MouseButton.Right); - }); - - AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); - AddStep("click edit", () => - { - var editItem = this.ChildrenOfType().ElementAt(0); - InputManager.MoveMouseTo(editItem); - InputManager.Click(MouseButton.Left); - }); - - OsuPopover? popover = null; - AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); - AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); - } - - [Test] - public void TestEditModSwitchDisableWithPresetSelest() - { - 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); - AddStep("select first preset mod", () => - SelectedMods.Value = this.ChildrenOfType().First().Preset.Value.Mods.ToList()); - - AddStep("right click first panel", () => - { - var panel = this.ChildrenOfType().First(); - InputManager.MoveMouseTo(panel); - InputManager.Click(MouseButton.Right); - }); - - AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); - AddStep("click edit", () => - { - var editItem = this.ChildrenOfType().ElementAt(0); - InputManager.MoveMouseTo(editItem); - InputManager.Click(MouseButton.Left); - }); - - OsuPopover? popover = null; - AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); - AddAssert("use current mod is enabled", () => popover.ChildrenOfType().Single().Current.Value); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); - - AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); - AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); - } - private ICollection createTestPresets() => new[] { new ModPreset diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 270b6f43d9..4eaf5e19db 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox nameTextBox; private readonly LabelledTextBox descriptionTextBox; - private readonly LabelledSwitchButton useCurrentSwitch; + private readonly ShearedButton useCurrentModButton; private readonly ShearedButton createButton; [Resolved] @@ -42,6 +42,7 @@ namespace osu.Game.Overlays.Mods Width = 300, AutoSizeAxes = Axes.Y, Spacing = new Vector2(7), + Direction = FillDirection.Vertical, Children = new Drawable[] { nameTextBox = new LabelledTextBox @@ -58,18 +59,30 @@ namespace osu.Game.Overlays.Mods Label = CommonStrings.Description, TabbableContentContainer = this }, - useCurrentSwitch = new LabelledSwitchButton + new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Label = "Use Current Mod select", - }, - createButton = new ShearedButton - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = CommonStrings.MenuBarEdit, - Action = tryEditPreset + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(7), + Children = new Drawable[] + { + useCurrentModButton = new ShearedButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Use Current Mods", + Action = trySaveCurrentMod + }, + createButton = new ShearedButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = Resources.Localisation.Web.CommonStrings.ButtonsSave, + Action = tryEditPreset + }, + } } } }; @@ -84,28 +97,24 @@ namespace osu.Game.Overlays.Mods nameTextBox.Current.Value = preset.Name; descriptionTextBox.Current.Value = preset.Description; - selectedMods.BindValueChanged(_ => updateMods(), true); - createButton.DarkerColour = colours.Orange1; createButton.LighterColour = colours.Orange0; createButton.TextColour = colourProvider.Background6; + + useCurrentModButton.DarkerColour = colours.Blue1; + useCurrentModButton.LighterColour = colours.Blue0; + useCurrentModButton.TextColour = colourProvider.Background6; } - private void updateMods() + private void trySaveCurrentMod() { - useCurrentSwitch.Current.Disabled = false; + if (button.Active.Value || !selectedMods.Value.Any()) + return; - // disable the switch when mod is equal. - if (button.Active.Value) + button.Preset.PerformWrite(s => { - useCurrentSwitch.Current.Value = true; - useCurrentSwitch.Current.Disabled = true; - } - else - { - useCurrentSwitch.Current.Value = false; - useCurrentSwitch.Current.Disabled = !selectedMods.Value.Any(); - } + s.Mods = selectedMods.Value.ToArray(); + }); } protected override void LoadComplete() @@ -127,11 +136,6 @@ namespace osu.Game.Overlays.Mods { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; - - if (useCurrentSwitch.Current.Value) - { - s.Mods = selectedMods.Value.ToArray(); - } }); this.HidePopover(); From 5a1316f0e5eb0d7acd8c813e84849cef5c584dbb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 9 Mar 2023 22:23:13 +0900 Subject: [PATCH 04/28] split save logic --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 8 ++------ osu.Game/Overlays/Mods/ModPresetPanel.cs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 4eaf5e19db..32d4aeae76 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -2,7 +2,6 @@ // 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; @@ -108,13 +107,10 @@ namespace osu.Game.Overlays.Mods private void trySaveCurrentMod() { - if (button.Active.Value || !selectedMods.Value.Any()) + if (button.SaveCurrentMod()) return; - button.Preset.PerformWrite(s => - { - s.Mods = selectedMods.Value.ToArray(); - }); + Body.Shake(); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index f4f1af50df..f861245007 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -98,6 +98,20 @@ namespace osu.Game.Overlays.Mods #endregion + public bool SaveCurrentMod() + { + if (!checkCurrentModCanBeSave()) + return false; + + Preset.PerformWrite(s => + { + s.Mods = selectedMods.Value.ToArray(); + }); + return true; + } + + private bool checkCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 3d746e8dfbb6cfbd7a08a480eda3d56a3262ed67 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 9 Mar 2023 22:43:11 +0900 Subject: [PATCH 05/28] content Menu --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index f861245007..f3fb5b5bb0 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -90,11 +90,24 @@ namespace osu.Game.Overlays.Mods #region IHasContextMenu - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), - new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), - }; + get + { + var menu = new List + { + new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), + new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), + }; + + if (checkCurrentModCanBeSave()) + { + menu.Insert(1, new OsuMenuItem("Use Current Mods", MenuItemType.Destructive, () => SaveCurrentMod())); + } + + return menu.ToArray(); + } + } #endregion From d009cd8422780247f035bb586851790bac37f6b5 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 9 Mar 2023 22:45:33 +0900 Subject: [PATCH 06/28] test --- .../UserInterface/TestSceneModPresetColumn.cs | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index d6065374ac..b67f67db2b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -327,6 +327,32 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddStep("click use current mods", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); + InputManager.Click(MouseButton.Left); + }); + AddWaitStep("wait some", 3); + AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); + AddAssert("present mod not changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 1); + AddStep("select mods", () => SelectedMods.Value = mods); AddStep("right click first panel", () => { @@ -343,14 +369,57 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - OsuPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); AddStep("click use current mods", () => { InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); InputManager.Click(MouseButton.Left); }); - AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); + AddWaitStep("wait some", 3); + AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); + } + + [Test] + public void TestEditPresetModInContextMenu() + { + ModPresetColumn modPresetColumn = null!; + var mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() }; + + 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); + + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddAssert("No Use Current Mods", () => this.ChildrenOfType().Count() == 2); + + AddStep("select mods", () => SelectedMods.Value = mods); + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddAssert("Have Use Current Mods", () => this.ChildrenOfType().Count() == 3); + AddStep("Click Use Current Mods", () => + { + var editItem = this.ChildrenOfType().ElementAt(1); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); } From ca416175bb6e168c3c8fa469b296d059a8991541 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 9 Mar 2023 22:58:44 +0900 Subject: [PATCH 07/28] remove useless property --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 32d4aeae76..3043f4a544 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -26,9 +26,6 @@ namespace osu.Game.Overlays.Mods private readonly ShearedButton useCurrentModButton; private readonly ShearedButton createButton; - [Resolved] - private Bindable> selectedMods { get; set; } = null!; - private readonly ModPreset preset; public EditPresetPopover(ModPresetPanel modPresetPanel) From f4e262040275e4466f4e43def09980a6a1b6d432 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 10 Mar 2023 00:56:22 +0900 Subject: [PATCH 08/28] fix test --- .../UserInterface/TestSceneModPresetColumn.cs | 22 +++++++++++-------- osu.Game/Overlays/Mods/EditPresetPopover.cs | 2 -- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index b67f67db2b..eaa3664623 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -266,6 +266,7 @@ namespace osu.Game.Tests.Visual.UserInterface { ModPresetColumn modPresetColumn = null!; string presetName = null!; + ModPresetPanel panel = null!; AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn @@ -277,7 +278,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); AddStep("right click first panel", () => { - var panel = this.ChildrenOfType().First(); + panel = this.ChildrenOfType().First(); presetName = panel.Preset.Value.Name; InputManager.MoveMouseTo(panel); InputManager.Click(MouseButton.Right); @@ -301,7 +302,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddWaitStep("wait some", 3); - AddAssert("present is not changed", () => this.ChildrenOfType().First().Preset.Value.Name == presetName); + AddAssert("present is not changed", () => panel.Preset.Value.Name == presetName); AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); AddStep("attempt preset edit", () => @@ -310,7 +311,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); - AddAssert("present is changed", () => this.ChildrenOfType().First().Preset.Value.Name != presetName); + AddAssert("present is changed", () => panel.Preset.Value.Name != presetName); } [Test] @@ -351,7 +352,8 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddWaitStep("wait some", 3); AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); - AddAssert("present mod not changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 1); + AddAssert("present mod not changed", () => + !new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); AddStep("select mods", () => SelectedMods.Value = mods); AddStep("right click first panel", () => @@ -377,14 +379,15 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddWaitStep("wait some", 3); AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); - AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); + AddAssert("present mod is changed", () => + new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } [Test] public void TestEditPresetModInContextMenu() { ModPresetColumn modPresetColumn = null!; - var mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() }; + var mods = new Mod[] { new OsuModHidden() }; AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn @@ -405,9 +408,9 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("No Use Current Mods", () => this.ChildrenOfType().Count() == 2); AddStep("select mods", () => SelectedMods.Value = mods); - AddStep("right click first panel", () => + AddStep("right click second panel", () => { - var panel = this.ChildrenOfType().First(); + var panel = this.ChildrenOfType().ElementAt(1); InputManager.MoveMouseTo(panel); InputManager.Click(MouseButton.Right); }); @@ -420,7 +423,8 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(editItem); InputManager.Click(MouseButton.Left); }); - AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); + AddAssert("present mod is changed", () => + new HashSet(this.ChildrenOfType().ElementAt(1).Preset.Value.Mods).SetEquals(mods)); } private ICollection createTestPresets() => new[] diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 3043f4a544..a5c562914b 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -1,9 +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.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From 8b0f127ff2a652cb2d8381d4c500c6cd040b878e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 11 Mar 2023 11:25:52 +0900 Subject: [PATCH 09/28] split ModPresetRow --- osu.Game/Overlays/Mods/ModPresetRow.cs | 64 ++++++++++++++++++++++ osu.Game/Overlays/Mods/ModPresetTooltip.cs | 54 ------------------ 2 files changed, 64 insertions(+), 54 deletions(-) create mode 100644 osu.Game/Overlays/Mods/ModPresetRow.cs diff --git a/osu.Game/Overlays/Mods/ModPresetRow.cs b/osu.Game/Overlays/Mods/ModPresetRow.cs new file mode 100644 index 0000000000..4829e93b87 --- /dev/null +++ b/osu.Game/Overlays/Mods/ModPresetRow.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +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 partial class ModPresetRow : FillFlowContainer + { + public ModPresetRow(Mod mod) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Spacing = new Vector2(4); + InternalChildren = 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), + Anchor = Anchor.CentreLeft, + Origin = 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 } + } + } + } + }; + + if (!string.IsNullOrEmpty(mod.SettingDescription)) + { + AddInternal(new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = 14 }, + Text = mod.SettingDescription + }); + } + } + } +} diff --git a/osu.Game/Overlays/Mods/ModPresetTooltip.cs b/osu.Game/Overlays/Mods/ModPresetTooltip.cs index ff4f00da69..8e8259de45 100644 --- a/osu.Game/Overlays/Mods/ModPresetTooltip.cs +++ b/osu.Game/Overlays/Mods/ModPresetTooltip.cs @@ -6,11 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -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 @@ -61,55 +57,5 @@ namespace osu.Game.Overlays.Mods protected override void PopOut() => this.FadeOut(transition_duration, Easing.OutQuint); public void Move(Vector2 pos) => Position = pos; - - private partial class ModPresetRow : FillFlowContainer - { - public ModPresetRow(Mod mod) - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - Spacing = new Vector2(4); - InternalChildren = 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), - Anchor = Anchor.CentreLeft, - Origin = 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 } - } - } - } - }; - - if (!string.IsNullOrEmpty(mod.SettingDescription)) - { - AddInternal(new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 14 }, - Text = mod.SettingDescription - }); - } - } - } } } From 1cd565193e3a546e0e6d8e603e4eebc09688a0fd Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 11 Mar 2023 11:39:35 +0900 Subject: [PATCH 10/28] public CheckCurrentModCanBeSave --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index f3fb5b5bb0..d01981d18c 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -100,7 +100,7 @@ namespace osu.Game.Overlays.Mods new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), }; - if (checkCurrentModCanBeSave()) + if (CheckCurrentModCanBeSave()) { menu.Insert(1, new OsuMenuItem("Use Current Mods", MenuItemType.Destructive, () => SaveCurrentMod())); } @@ -113,7 +113,7 @@ namespace osu.Game.Overlays.Mods public bool SaveCurrentMod() { - if (!checkCurrentModCanBeSave()) + if (!CheckCurrentModCanBeSave()) return false; Preset.PerformWrite(s => @@ -123,7 +123,7 @@ namespace osu.Game.Overlays.Mods return true; } - private bool checkCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); + public bool CheckCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); protected override void Dispose(bool isDisposing) { From 15f11bb1e8ff7ea4d5ed8defa45ea0069fbd303f Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 11 Mar 2023 12:31:33 +0900 Subject: [PATCH 11/28] scorll container and save mod after popover hidden Requires manual handling of many visual effects --- .../UserInterface/TestSceneModPresetColumn.cs | 12 ++- osu.Game/Overlays/Mods/EditPresetPopover.cs | 76 +++++++++++++++++-- osu.Game/Overlays/Mods/ModPresetPanel.cs | 12 ++- osu.Game/Overlays/Mods/ModPresetTooltip.cs | 13 ++-- 4 files changed, 95 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index eaa3664623..68efb2a5f4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -353,7 +353,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddWaitStep("wait some", 3); AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); AddAssert("present mod not changed", () => - !new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); + !new HashSet(this.ChildrenOfType().First().Mods.Value).SetEquals(mods)); AddStep("select mods", () => SelectedMods.Value = mods); AddStep("right click first panel", () => @@ -378,8 +378,16 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); AddWaitStep("wait some", 3); - AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); AddAssert("present mod is changed", () => + new HashSet(this.ChildrenOfType().First().Mods.Value).SetEquals(mods)); + + AddStep("click edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); + InputManager.Click(MouseButton.Left); + }); + AddAssert("present mod in realm is changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index a5c562914b..92860e96a6 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -1,12 +1,16 @@ // 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; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Extensions; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; @@ -23,8 +27,19 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox descriptionTextBox; private readonly ShearedButton useCurrentModButton; private readonly ShearedButton createButton; + private readonly FillFlowContainer scrollContent; private readonly ModPreset preset; + private List saveModAfterClosed = new List(); + + [Resolved] + private Bindable> selectedMods { get; set; } = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; public EditPresetPopover(ModPresetPanel modPresetPanel) { @@ -53,6 +68,19 @@ namespace osu.Game.Overlays.Mods Label = CommonStrings.Description, TabbableContentContainer = this }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.X, + Height = 100, + Padding = new MarginPadding(7), + Child = scrollContent = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding(7), + Spacing = new Vector2(7), + } + }, new FillFlowContainer { Anchor = Anchor.TopCentre, @@ -83,7 +111,7 @@ namespace osu.Game.Overlays.Mods } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, OsuColour colours) + private void load() { Body.BorderThickness = 3; Body.BorderColour = colours.Orange1; @@ -95,17 +123,40 @@ namespace osu.Game.Overlays.Mods createButton.LighterColour = colours.Orange0; createButton.TextColour = colourProvider.Background6; - useCurrentModButton.DarkerColour = colours.Blue1; - useCurrentModButton.LighterColour = colours.Blue0; - useCurrentModButton.TextColour = colourProvider.Background6; + selectedMods.BindValueChanged(_ => updateActiveState(), true); + + scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); } private void trySaveCurrentMod() { - if (button.SaveCurrentMod()) + if (!button.CheckCurrentModCanBeSave()) + { + Body.Shake(); return; + } - Body.Shake(); + saveModAfterClosed = selectedMods.Value.ToList(); + scrollContent.Clear(); + scrollContent.ChildrenEnumerable = saveModAfterClosed.Select(mod => new ModPresetRow(mod)); + button.Mods.Value = saveModAfterClosed; + updateActiveState(); + } + + private void updateActiveState() + { + if (button.CheckCurrentModCanBeSave()) + { + useCurrentModButton.DarkerColour = colours.Blue1; + useCurrentModButton.LighterColour = colours.Blue0; + useCurrentModButton.TextColour = colourProvider.Background6; + } + else + { + useCurrentModButton.DarkerColour = colours.Blue3; + useCurrentModButton.LighterColour = colours.Blue4; + useCurrentModButton.TextColour = colourProvider.Background2; + } } protected override void LoadComplete() @@ -131,5 +182,18 @@ namespace osu.Game.Overlays.Mods this.HidePopover(); } + + protected override void UpdateState(ValueChangedEvent state) + { + base.UpdateState(state); + + if (state.NewValue == Visibility.Hidden && saveModAfterClosed.Any()) + { + button.Preset.PerformWrite(s => + { + s.Mods = saveModAfterClosed; + }); + } + } } } diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index d01981d18c..49437c5bb1 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -18,10 +18,12 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu, IHasPopover + public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip>, IHasContextMenu, IHasPopover { public readonly Live Preset; + public readonly Bindable> Mods = new Bindable>(); + public override BindableBool Active { get; } = new BindableBool(); [Resolved] @@ -35,6 +37,7 @@ namespace osu.Game.Overlays.Mods public ModPresetPanel(Live preset) { Preset = preset; + Mods.Value = preset.Value.Mods.ToList(); Title = preset.Value.Name; Description = preset.Value.Description; @@ -51,6 +54,7 @@ namespace osu.Game.Overlays.Mods base.LoadComplete(); selectedMods.BindValueChanged(_ => selectedModsChanged(), true); + Mods.BindValueChanged(_ => updateActiveState(), true); } protected override void Select() @@ -78,13 +82,13 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { - Active.Value = new HashSet(Preset.Value.Mods).SetEquals(selectedMods.Value); + Active.Value = new HashSet(Mods.Value).SetEquals(selectedMods.Value); } #region IHasCustomTooltip - public ModPreset TooltipContent => Preset.Value; - public ITooltip GetCustomTooltip() => new ModPresetTooltip(ColourProvider); + public List TooltipContent => Mods.Value; + public ITooltip> GetCustomTooltip() => new ModPresetTooltip(ColourProvider); #endregion diff --git a/osu.Game/Overlays/Mods/ModPresetTooltip.cs b/osu.Game/Overlays/Mods/ModPresetTooltip.cs index 8e8259de45..0b31a97064 100644 --- a/osu.Game/Overlays/Mods/ModPresetTooltip.cs +++ b/osu.Game/Overlays/Mods/ModPresetTooltip.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.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -11,7 +12,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public partial class ModPresetTooltip : VisibilityContainer, ITooltip + public partial class ModPresetTooltip : VisibilityContainer, ITooltip> { protected override Container Content { get; } @@ -42,15 +43,15 @@ namespace osu.Game.Overlays.Mods }; } - private ModPreset? lastPreset; + private List? lastPreset; - public void SetContent(ModPreset preset) + public void SetContent(List mods) { - if (ReferenceEquals(preset, lastPreset)) + if (ReferenceEquals(mods, lastPreset)) return; - lastPreset = preset; - Content.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); + lastPreset = mods; + Content.ChildrenEnumerable = mods.Select(mod => new ModPresetRow(mod)); } protected override void PopIn() => this.FadeIn(transition_duration, Easing.OutQuint); From 42bcc8bafc01005ad91035dde8d80d027b3552f5 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 16 Mar 2023 19:15:50 +0900 Subject: [PATCH 12/28] revert mod store --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 12 ++++-------- osu.Game/Overlays/Mods/ModPresetTooltip.cs | 13 ++++++------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 49437c5bb1..d01981d18c 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -18,12 +18,10 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip>, IHasContextMenu, IHasPopover + public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu, IHasPopover { public readonly Live Preset; - public readonly Bindable> Mods = new Bindable>(); - public override BindableBool Active { get; } = new BindableBool(); [Resolved] @@ -37,7 +35,6 @@ namespace osu.Game.Overlays.Mods public ModPresetPanel(Live preset) { Preset = preset; - Mods.Value = preset.Value.Mods.ToList(); Title = preset.Value.Name; Description = preset.Value.Description; @@ -54,7 +51,6 @@ namespace osu.Game.Overlays.Mods base.LoadComplete(); selectedMods.BindValueChanged(_ => selectedModsChanged(), true); - Mods.BindValueChanged(_ => updateActiveState(), true); } protected override void Select() @@ -82,13 +78,13 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { - Active.Value = new HashSet(Mods.Value).SetEquals(selectedMods.Value); + Active.Value = new HashSet(Preset.Value.Mods).SetEquals(selectedMods.Value); } #region IHasCustomTooltip - public List TooltipContent => Mods.Value; - public ITooltip> GetCustomTooltip() => new ModPresetTooltip(ColourProvider); + public ModPreset TooltipContent => Preset.Value; + public ITooltip GetCustomTooltip() => new ModPresetTooltip(ColourProvider); #endregion diff --git a/osu.Game/Overlays/Mods/ModPresetTooltip.cs b/osu.Game/Overlays/Mods/ModPresetTooltip.cs index 0b31a97064..8e8259de45 100644 --- a/osu.Game/Overlays/Mods/ModPresetTooltip.cs +++ b/osu.Game/Overlays/Mods/ModPresetTooltip.cs @@ -1,7 +1,6 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +11,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public partial class ModPresetTooltip : VisibilityContainer, ITooltip> + public partial class ModPresetTooltip : VisibilityContainer, ITooltip { protected override Container Content { get; } @@ -43,15 +42,15 @@ namespace osu.Game.Overlays.Mods }; } - private List? lastPreset; + private ModPreset? lastPreset; - public void SetContent(List mods) + public void SetContent(ModPreset preset) { - if (ReferenceEquals(mods, lastPreset)) + if (ReferenceEquals(preset, lastPreset)) return; - lastPreset = mods; - Content.ChildrenEnumerable = mods.Select(mod => new ModPresetRow(mod)); + lastPreset = preset; + Content.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); } protected override void PopIn() => this.FadeIn(transition_duration, Easing.OutQuint); From d025c441ca2249489b6d0c523d55b44ef1da6108 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 16 Mar 2023 19:38:52 +0900 Subject: [PATCH 13/28] delay mod save after click save or not popover hidden --- .../UserInterface/TestSceneModPresetColumn.cs | 20 ++++++----- osu.Game/Overlays/Mods/EditPresetPopover.cs | 36 ++++++++++--------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 68efb2a5f4..c4c5584c5e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -319,6 +319,7 @@ namespace osu.Game.Tests.Visual.UserInterface { ModPresetColumn modPresetColumn = null!; var mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() }; + List previousMod = null!; AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn @@ -332,6 +333,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("right click first panel", () => { var panel = this.ChildrenOfType().First(); + previousMod = panel.Preset.Value.Mods.ToList(); InputManager.MoveMouseTo(panel); InputManager.Click(MouseButton.Right); }); @@ -350,10 +352,14 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); InputManager.Click(MouseButton.Left); }); + AddStep("attempt preset edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); + InputManager.Click(MouseButton.Left); + }); AddWaitStep("wait some", 3); - AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); AddAssert("present mod not changed", () => - !new HashSet(this.ChildrenOfType().First().Mods.Value).SetEquals(mods)); + new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(previousMod)); AddStep("select mods", () => SelectedMods.Value = mods); AddStep("right click first panel", () => @@ -377,17 +383,13 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); InputManager.Click(MouseButton.Left); }); - AddWaitStep("wait some", 3); - AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); - AddAssert("present mod is changed", () => - new HashSet(this.ChildrenOfType().First().Mods.Value).SetEquals(mods)); - - AddStep("click edit", () => + AddStep("attempt preset edit", () => { InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); - AddAssert("present mod in realm is changed", () => + AddWaitStep("wait some", 3); + AddAssert("present mod is changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 92860e96a6..0e21260493 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -130,7 +130,7 @@ namespace osu.Game.Overlays.Mods private void trySaveCurrentMod() { - if (!button.CheckCurrentModCanBeSave()) + if (!checkCanBeSave()) { Body.Shake(); return; @@ -139,13 +139,12 @@ namespace osu.Game.Overlays.Mods saveModAfterClosed = selectedMods.Value.ToList(); scrollContent.Clear(); scrollContent.ChildrenEnumerable = saveModAfterClosed.Select(mod => new ModPresetRow(mod)); - button.Mods.Value = saveModAfterClosed; updateActiveState(); } private void updateActiveState() { - if (button.CheckCurrentModCanBeSave()) + if (checkCanBeSave()) { useCurrentModButton.DarkerColour = colours.Blue1; useCurrentModButton.LighterColour = colours.Blue0; @@ -159,6 +158,19 @@ namespace osu.Game.Overlays.Mods } } + private bool checkCanBeSave() + { + if (!selectedMods.Value.Any()) + return false; + + if (saveModAfterClosed.Any()) + { + return !new HashSet(saveModAfterClosed).SetEquals(selectedMods.Value); + } + + return button.CheckCurrentModCanBeSave(); + } + protected override void LoadComplete() { base.LoadComplete(); @@ -178,22 +190,14 @@ namespace osu.Game.Overlays.Mods { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; + + if (saveModAfterClosed.Any()) + { + s.Mods = saveModAfterClosed; + } }); this.HidePopover(); } - - protected override void UpdateState(ValueChangedEvent state) - { - base.UpdateState(state); - - if (state.NewValue == Visibility.Hidden && saveModAfterClosed.Any()) - { - button.Preset.PerformWrite(s => - { - s.Mods = saveModAfterClosed; - }); - } - } } } From 3a15783a3c53e610b86ff71c891df125d3651bb1 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 22:56:47 +0900 Subject: [PATCH 14/28] remove wait, use AddUntilStep --- .../Visual/UserInterface/TestSceneModPresetColumn.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index c4c5584c5e..55fe142d9f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -301,7 +301,6 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - AddWaitStep("wait some", 3); AddAssert("present is not changed", () => panel.Preset.Value.Name == presetName); AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); @@ -357,8 +356,8 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); - AddWaitStep("wait some", 3); - AddAssert("present mod not changed", () => + + AddUntilStep("present mod not changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(previousMod)); AddStep("select mods", () => SelectedMods.Value = mods); @@ -388,8 +387,8 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); - AddWaitStep("wait some", 3); - AddAssert("present mod is changed", () => + + AddUntilStep("present mod is changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } From c609e6345cf6c3b41b57917fe1dac841b1be9a4c Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:01:31 +0900 Subject: [PATCH 15/28] remove `Use Current Mods` menu item --- .../UserInterface/TestSceneModPresetColumn.cs | 44 ------------------- osu.Game/Overlays/Mods/ModPresetPanel.cs | 21 ++------- 2 files changed, 4 insertions(+), 61 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 55fe142d9f..0cbbe00311 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -392,50 +392,6 @@ namespace osu.Game.Tests.Visual.UserInterface new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } - [Test] - public void TestEditPresetModInContextMenu() - { - ModPresetColumn modPresetColumn = null!; - var mods = new Mod[] { new OsuModHidden() }; - - 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); - - AddStep("right click first panel", () => - { - var panel = this.ChildrenOfType().First(); - InputManager.MoveMouseTo(panel); - InputManager.Click(MouseButton.Right); - }); - AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); - AddAssert("No Use Current Mods", () => this.ChildrenOfType().Count() == 2); - - AddStep("select mods", () => SelectedMods.Value = mods); - AddStep("right click second panel", () => - { - var panel = this.ChildrenOfType().ElementAt(1); - InputManager.MoveMouseTo(panel); - InputManager.Click(MouseButton.Right); - }); - - AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); - AddAssert("Have Use Current Mods", () => this.ChildrenOfType().Count() == 3); - AddStep("Click Use Current Mods", () => - { - var editItem = this.ChildrenOfType().ElementAt(1); - InputManager.MoveMouseTo(editItem); - InputManager.Click(MouseButton.Left); - }); - AddAssert("present mod is changed", () => - new HashSet(this.ChildrenOfType().ElementAt(1).Preset.Value.Mods).SetEquals(mods)); - } - private ICollection createTestPresets() => new[] { new ModPreset diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index d01981d18c..6999f2cede 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -90,24 +90,11 @@ namespace osu.Game.Overlays.Mods #region IHasContextMenu - public MenuItem[] ContextMenuItems + public MenuItem[] ContextMenuItems => new MenuItem[] { - get - { - var menu = new List - { - new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), - new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), - }; - - if (CheckCurrentModCanBeSave()) - { - menu.Insert(1, new OsuMenuItem("Use Current Mods", MenuItemType.Destructive, () => SaveCurrentMod())); - } - - return menu.ToArray(); - } - } + new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), + new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), + }; #endregion From aa5a026c676c0503f6110c0d4fa610b3669bc9fd Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:14:24 +0900 Subject: [PATCH 16/28] remove local button handle --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 27 ++++++--------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 0e21260493..77980ea629 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -95,7 +95,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Use Current Mods", - Action = trySaveCurrentMod + Action = saveCurrentMod }, createButton = new ShearedButton { @@ -123,19 +123,17 @@ namespace osu.Game.Overlays.Mods createButton.LighterColour = colours.Orange0; createButton.TextColour = colourProvider.Background6; + useCurrentModButton.DarkerColour = colours.Blue1; + useCurrentModButton.LighterColour = colours.Blue0; + useCurrentModButton.TextColour = colourProvider.Background6; + selectedMods.BindValueChanged(_ => updateActiveState(), true); scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); } - private void trySaveCurrentMod() + private void saveCurrentMod() { - if (!checkCanBeSave()) - { - Body.Shake(); - return; - } - saveModAfterClosed = selectedMods.Value.ToList(); scrollContent.Clear(); scrollContent.ChildrenEnumerable = saveModAfterClosed.Select(mod => new ModPresetRow(mod)); @@ -144,18 +142,7 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { - if (checkCanBeSave()) - { - useCurrentModButton.DarkerColour = colours.Blue1; - useCurrentModButton.LighterColour = colours.Blue0; - useCurrentModButton.TextColour = colourProvider.Background6; - } - else - { - useCurrentModButton.DarkerColour = colours.Blue3; - useCurrentModButton.LighterColour = colours.Blue4; - useCurrentModButton.TextColour = colourProvider.Background2; - } + useCurrentModButton.Enabled.Value = checkCanBeSave(); } private bool checkCanBeSave() From f4b1264cc9859acd275e0f99bf68c2b6cd59306b Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:22:46 +0900 Subject: [PATCH 17/28] use button `Enable` status to ensure preset name is not null --- osu.Game/Overlays/Mods/AddPresetPopover.cs | 15 ++++++------- osu.Game/Overlays/Mods/EditPresetPopover.cs | 25 ++++++++++----------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/Mods/AddPresetPopover.cs b/osu.Game/Overlays/Mods/AddPresetPopover.cs index 33d72ff383..6fd4231f2c 100644 --- a/osu.Game/Overlays/Mods/AddPresetPopover.cs +++ b/osu.Game/Overlays/Mods/AddPresetPopover.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = ModSelectOverlayStrings.AddPreset, - Action = tryCreatePreset + Action = createPreset } } }; @@ -89,16 +89,15 @@ namespace osu.Game.Overlays.Mods base.LoadComplete(); ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(nameTextBox)); + + nameTextBox.Current.BindValueChanged(s => + { + createButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); + }, true); } - private void tryCreatePreset() + private void createPreset() { - if (string.IsNullOrWhiteSpace(nameTextBox.Current.Value)) - { - Body.Shake(); - return; - } - realm.Write(r => r.Add(new ModPreset { Name = nameTextBox.Current.Value, diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 77980ea629..451c1ec712 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox nameTextBox; private readonly LabelledTextBox descriptionTextBox; private readonly ShearedButton useCurrentModButton; - private readonly ShearedButton createButton; + private readonly ShearedButton editButton; private readonly FillFlowContainer scrollContent; private readonly ModPreset preset; @@ -97,12 +97,12 @@ namespace osu.Game.Overlays.Mods Text = "Use Current Mods", Action = saveCurrentMod }, - createButton = new ShearedButton + editButton = new ShearedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = Resources.Localisation.Web.CommonStrings.ButtonsSave, - Action = tryEditPreset + Action = editPreset }, } } @@ -119,9 +119,9 @@ namespace osu.Game.Overlays.Mods nameTextBox.Current.Value = preset.Name; descriptionTextBox.Current.Value = preset.Description; - createButton.DarkerColour = colours.Orange1; - createButton.LighterColour = colours.Orange0; - createButton.TextColour = colourProvider.Background6; + editButton.DarkerColour = colours.Orange1; + editButton.LighterColour = colours.Orange0; + editButton.TextColour = colourProvider.Background6; useCurrentModButton.DarkerColour = colours.Blue1; useCurrentModButton.LighterColour = colours.Blue0; @@ -130,6 +130,11 @@ namespace osu.Game.Overlays.Mods selectedMods.BindValueChanged(_ => updateActiveState(), true); scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); + + nameTextBox.Current.BindValueChanged(s => + { + editButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); + }, true); } private void saveCurrentMod() @@ -165,14 +170,8 @@ namespace osu.Game.Overlays.Mods ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(nameTextBox)); } - private void tryEditPreset() + private void editPreset() { - if (string.IsNullOrWhiteSpace(nameTextBox.Current.Value)) - { - Body.Shake(); - return; - } - button.Preset.PerformWrite(s => { s.Name = nameTextBox.Current.Value; From debbd376bd6e8155612ea8a2b6e2fe1db2a9c884 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:24:14 +0900 Subject: [PATCH 18/28] move `scrollContent` update logic to `updateActiveState()` --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 451c1ec712..e96168d8ff 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -129,8 +129,6 @@ namespace osu.Game.Overlays.Mods selectedMods.BindValueChanged(_ => updateActiveState(), true); - scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); - nameTextBox.Current.BindValueChanged(s => { editButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); @@ -141,12 +139,12 @@ namespace osu.Game.Overlays.Mods { saveModAfterClosed = selectedMods.Value.ToList(); scrollContent.Clear(); - scrollContent.ChildrenEnumerable = saveModAfterClosed.Select(mod => new ModPresetRow(mod)); updateActiveState(); } private void updateActiveState() { + scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); useCurrentModButton.Enabled.Value = checkCanBeSave(); } From 967e801f9c77cc4b745fd32625c674fd708d25e9 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:26:58 +0900 Subject: [PATCH 19/28] code inspect --- osu.Game/Overlays/Mods/AddPresetPopover.cs | 1 - osu.Game/Overlays/Mods/EditPresetPopover.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/AddPresetPopover.cs b/osu.Game/Overlays/Mods/AddPresetPopover.cs index 6fd4231f2c..d9e350e560 100644 --- a/osu.Game/Overlays/Mods/AddPresetPopover.cs +++ b/osu.Game/Overlays/Mods/AddPresetPopover.cs @@ -9,7 +9,6 @@ using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Database; -using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index e96168d8ff..7f7b9472a7 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -8,7 +8,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; From 0a584f065235d3317067b9ed2860a686fe419122 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:07:09 +0900 Subject: [PATCH 20/28] Simplify check logic and improve variable naming --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 7f7b9472a7..9015218910 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -29,7 +29,8 @@ namespace osu.Game.Overlays.Mods private readonly FillFlowContainer scrollContent; private readonly ModPreset preset; - private List saveModAfterClosed = new List(); + + private HashSet? newMods; [Resolved] private Bindable> selectedMods { get; set; } = null!; @@ -136,7 +137,7 @@ namespace osu.Game.Overlays.Mods private void saveCurrentMod() { - saveModAfterClosed = selectedMods.Value.ToList(); + newMods = selectedMods.Value.ToHashSet(); scrollContent.Clear(); updateActiveState(); } @@ -144,18 +145,16 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); - useCurrentModButton.Enabled.Value = checkCanBeSave(); + useCurrentModButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); } - private bool checkCanBeSave() + private bool checkSelectedModsDiffersFromSaved() { if (!selectedMods.Value.Any()) return false; - if (saveModAfterClosed.Any()) - { - return !new HashSet(saveModAfterClosed).SetEquals(selectedMods.Value); - } + if (newMods?.SetEquals(selectedMods.Value) == false) + return true; return button.CheckCurrentModCanBeSave(); } @@ -174,10 +173,8 @@ namespace osu.Game.Overlays.Mods s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; - if (saveModAfterClosed.Any()) - { - s.Mods = saveModAfterClosed; - } + if (newMods != null) + s.Mods = newMods; }); this.HidePopover(); From b7abab6d8aff61e2e79c17f7fd367999f72857de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:10:05 +0900 Subject: [PATCH 21/28] More variable improvements --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 32 ++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 9015218910..91beea8e38 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -24,8 +24,8 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox nameTextBox; private readonly LabelledTextBox descriptionTextBox; - private readonly ShearedButton useCurrentModButton; - private readonly ShearedButton editButton; + private readonly ShearedButton useCurrentModsButton; + private readonly ShearedButton saveButton; private readonly FillFlowContainer scrollContent; private readonly ModPreset preset; @@ -90,19 +90,19 @@ namespace osu.Game.Overlays.Mods Spacing = new Vector2(7), Children = new Drawable[] { - useCurrentModButton = new ShearedButton + useCurrentModsButton = new ShearedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Use Current Mods", - Action = saveCurrentMod + Action = useCurrentMods }, - editButton = new ShearedButton + saveButton = new ShearedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = Resources.Localisation.Web.CommonStrings.ButtonsSave, - Action = editPreset + Action = save }, } } @@ -119,23 +119,23 @@ namespace osu.Game.Overlays.Mods nameTextBox.Current.Value = preset.Name; descriptionTextBox.Current.Value = preset.Description; - editButton.DarkerColour = colours.Orange1; - editButton.LighterColour = colours.Orange0; - editButton.TextColour = colourProvider.Background6; + saveButton.DarkerColour = colours.Orange1; + saveButton.LighterColour = colours.Orange0; + saveButton.TextColour = colourProvider.Background6; - useCurrentModButton.DarkerColour = colours.Blue1; - useCurrentModButton.LighterColour = colours.Blue0; - useCurrentModButton.TextColour = colourProvider.Background6; + useCurrentModsButton.DarkerColour = colours.Blue1; + useCurrentModsButton.LighterColour = colours.Blue0; + useCurrentModsButton.TextColour = colourProvider.Background6; selectedMods.BindValueChanged(_ => updateActiveState(), true); nameTextBox.Current.BindValueChanged(s => { - editButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); + saveButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); }, true); } - private void saveCurrentMod() + private void useCurrentMods() { newMods = selectedMods.Value.ToHashSet(); scrollContent.Clear(); @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); - useCurrentModButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); + useCurrentModsButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); } private bool checkSelectedModsDiffersFromSaved() @@ -166,7 +166,7 @@ namespace osu.Game.Overlays.Mods ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(nameTextBox)); } - private void editPreset() + private void save() { button.Preset.PerformWrite(s => { From be995f1359e19de4d9573fe1ad76645400c0949b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:11:19 +0900 Subject: [PATCH 22/28] Add localisation support for new button string --- osu.Game/Localisation/ModSelectOverlayStrings.cs | 5 +++++ osu.Game/Overlays/Mods/EditPresetPopover.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Localisation/ModSelectOverlayStrings.cs b/osu.Game/Localisation/ModSelectOverlayStrings.cs index d6a01c4794..f11c52ee20 100644 --- a/osu.Game/Localisation/ModSelectOverlayStrings.cs +++ b/osu.Game/Localisation/ModSelectOverlayStrings.cs @@ -34,6 +34,11 @@ namespace osu.Game.Localisation /// public static LocalisableString AddPreset => new TranslatableString(getKey(@"add_preset"), @"Add preset"); + /// + /// "Use current mods" + /// + public static LocalisableString UseCurrentMods => new TranslatableString(getKey(@"use_current_mods"), @"Use current mods"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 91beea8e38..b826bdf944 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -94,7 +94,7 @@ namespace osu.Game.Overlays.Mods { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = "Use Current Mods", + Text = ModSelectOverlayStrings.UseCurrentMods, Action = useCurrentMods }, saveButton = new ShearedButton From 99d2616c34d51b8e4027543f01b73a8efe499475 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:14:51 +0900 Subject: [PATCH 23/28] Move drawable construction to `load` for simplicity --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 58 ++++++++++----------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index b826bdf944..f02c200654 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -20,13 +20,13 @@ namespace osu.Game.Overlays.Mods { internal partial class EditPresetPopover : OsuPopover { - private readonly ModPresetPanel button; + private readonly ModPresetPanel presetPanel; - private readonly LabelledTextBox nameTextBox; - private readonly LabelledTextBox descriptionTextBox; - private readonly ShearedButton useCurrentModsButton; - private readonly ShearedButton saveButton; - private readonly FillFlowContainer scrollContent; + private LabelledTextBox nameTextBox = null!; + private LabelledTextBox descriptionTextBox = null!; + private ShearedButton useCurrentModsButton = null!; + private ShearedButton saveButton = null!; + private FillFlowContainer scrollContent = null!; private readonly ModPreset preset; @@ -41,11 +41,15 @@ namespace osu.Game.Overlays.Mods [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; - public EditPresetPopover(ModPresetPanel modPresetPanel) + public EditPresetPopover(ModPresetPanel presetPanel) { - button = modPresetPanel; - preset = button.Preset.Value; + this.presetPanel = presetPanel; + preset = presetPanel.Preset.Value; + } + [BackgroundDependencyLoader] + private void load() + { Child = new FillFlowContainer { Width = 300, @@ -59,14 +63,16 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Label = CommonStrings.Name, - TabbableContentContainer = this + TabbableContentContainer = this, + Current = { Value = preset.Name }, }, descriptionTextBox = new LabelledTextBox { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Label = CommonStrings.Description, - TabbableContentContainer = this + TabbableContentContainer = this, + Current = { Value = preset.Description }, }, new OsuScrollContainer { @@ -95,40 +101,30 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = ModSelectOverlayStrings.UseCurrentMods, - Action = useCurrentMods + DarkerColour = colours.Blue1, + LighterColour = colours.Blue0, + TextColour = colourProvider.Background6, + Action = useCurrentMods, }, saveButton = new ShearedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = Resources.Localisation.Web.CommonStrings.ButtonsSave, - Action = save + DarkerColour = colours.Orange1, + LighterColour = colours.Orange0, + TextColour = colourProvider.Background6, + Action = save, }, } } } }; - } - [BackgroundDependencyLoader] - private void load() - { Body.BorderThickness = 3; Body.BorderColour = colours.Orange1; - nameTextBox.Current.Value = preset.Name; - descriptionTextBox.Current.Value = preset.Description; - - saveButton.DarkerColour = colours.Orange1; - saveButton.LighterColour = colours.Orange0; - saveButton.TextColour = colourProvider.Background6; - - useCurrentModsButton.DarkerColour = colours.Blue1; - useCurrentModsButton.LighterColour = colours.Blue0; - useCurrentModsButton.TextColour = colourProvider.Background6; - selectedMods.BindValueChanged(_ => updateActiveState(), true); - nameTextBox.Current.BindValueChanged(s => { saveButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); @@ -156,7 +152,7 @@ namespace osu.Game.Overlays.Mods if (newMods?.SetEquals(selectedMods.Value) == false) return true; - return button.CheckCurrentModCanBeSave(); + return presetPanel.CheckCurrentModCanBeSave(); } protected override void LoadComplete() @@ -168,7 +164,7 @@ namespace osu.Game.Overlays.Mods private void save() { - button.Preset.PerformWrite(s => + presetPanel.Preset.PerformWrite(s => { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; From b12d139317b55d47046eb0eaaf50756aaf07fb67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:16:52 +0900 Subject: [PATCH 24/28] Remove dead code --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 6999f2cede..3f5a764ab1 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -98,18 +98,6 @@ namespace osu.Game.Overlays.Mods #endregion - public bool SaveCurrentMod() - { - if (!CheckCurrentModCanBeSave()) - return false; - - Preset.PerformWrite(s => - { - s.Mods = selectedMods.Value.ToArray(); - }); - return true; - } - public bool CheckCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); protected override void Dispose(bool isDisposing) From 49fb5da1a237c30768f753d98d793733750bea5a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:19:09 +0900 Subject: [PATCH 25/28] Stop passing preset panel to popover --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 23 ++++++++------------- osu.Game/Overlays/Mods/ModPresetPanel.cs | 4 +--- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index f02c200654..3f5eca8ad0 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -20,15 +21,13 @@ namespace osu.Game.Overlays.Mods { internal partial class EditPresetPopover : OsuPopover { - private readonly ModPresetPanel presetPanel; - private LabelledTextBox nameTextBox = null!; private LabelledTextBox descriptionTextBox = null!; private ShearedButton useCurrentModsButton = null!; private ShearedButton saveButton = null!; private FillFlowContainer scrollContent = null!; - private readonly ModPreset preset; + private readonly Live preset; private HashSet? newMods; @@ -41,10 +40,9 @@ namespace osu.Game.Overlays.Mods [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; - public EditPresetPopover(ModPresetPanel presetPanel) + public EditPresetPopover(Live preset) { - this.presetPanel = presetPanel; - preset = presetPanel.Preset.Value; + this.preset = preset; } [BackgroundDependencyLoader] @@ -64,7 +62,7 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.TopCentre, Label = CommonStrings.Name, TabbableContentContainer = this, - Current = { Value = preset.Name }, + Current = { Value = preset.PerformRead(p => p.Name) }, }, descriptionTextBox = new LabelledTextBox { @@ -72,7 +70,7 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.TopCentre, Label = CommonStrings.Description, TabbableContentContainer = this, - Current = { Value = preset.Description }, + Current = { Value = preset.PerformRead(p => p.Description) }, }, new OsuScrollContainer { @@ -140,7 +138,7 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { - scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); + scrollContent.ChildrenEnumerable = preset.PerformRead(p => p.Mods.Select(mod => new ModPresetRow(mod))); useCurrentModsButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); } @@ -149,10 +147,7 @@ namespace osu.Game.Overlays.Mods if (!selectedMods.Value.Any()) return false; - if (newMods?.SetEquals(selectedMods.Value) == false) - return true; - - return presetPanel.CheckCurrentModCanBeSave(); + return newMods?.SetEquals(selectedMods.Value) == false; } protected override void LoadComplete() @@ -164,7 +159,7 @@ namespace osu.Game.Overlays.Mods private void save() { - presetPanel.Preset.PerformWrite(s => + preset.PerformWrite(s => { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 3f5a764ab1..8bcb5e4e4e 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -98,8 +98,6 @@ namespace osu.Game.Overlays.Mods #endregion - public bool CheckCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -107,6 +105,6 @@ namespace osu.Game.Overlays.Mods settingChangeTracker?.Dispose(); } - public Popover GetPopover() => new EditPresetPopover(this); + public Popover GetPopover() => new EditPresetPopover(Preset); } } From 26b8c5b852d31b1e0d340d0926821dfcd0910fa5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:23:51 +0900 Subject: [PATCH 26/28] Fix mod list display not updating after clicking "use current" This is not a regression from my changes. It was broken before them. --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 3f5eca8ad0..82d0bdb51e 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Mods private readonly Live preset; - private HashSet? newMods; + private HashSet saveableMods; [Resolved] private Bindable> selectedMods { get; set; } = null!; @@ -43,6 +43,7 @@ namespace osu.Game.Overlays.Mods public EditPresetPopover(Live preset) { this.preset = preset; + saveableMods = preset.PerformRead(p => p.Mods).ToHashSet(); } [BackgroundDependencyLoader] @@ -122,7 +123,7 @@ namespace osu.Game.Overlays.Mods Body.BorderThickness = 3; Body.BorderColour = colours.Orange1; - selectedMods.BindValueChanged(_ => updateActiveState(), true); + selectedMods.BindValueChanged(_ => updateState(), true); nameTextBox.Current.BindValueChanged(s => { saveButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); @@ -131,14 +132,14 @@ namespace osu.Game.Overlays.Mods private void useCurrentMods() { - newMods = selectedMods.Value.ToHashSet(); + saveableMods = selectedMods.Value.ToHashSet(); scrollContent.Clear(); - updateActiveState(); + updateState(); } - private void updateActiveState() + private void updateState() { - scrollContent.ChildrenEnumerable = preset.PerformRead(p => p.Mods.Select(mod => new ModPresetRow(mod))); + scrollContent.ChildrenEnumerable = saveableMods.Select(mod => new ModPresetRow(mod)); useCurrentModsButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); } @@ -147,7 +148,7 @@ namespace osu.Game.Overlays.Mods if (!selectedMods.Value.Any()) return false; - return newMods?.SetEquals(selectedMods.Value) == false; + return !saveableMods.SetEquals(selectedMods.Value); } protected override void LoadComplete() @@ -163,9 +164,7 @@ namespace osu.Game.Overlays.Mods { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; - - if (newMods != null) - s.Mods = newMods; + s.Mods = saveableMods; }); this.HidePopover(); From 0034124d79ee949f00dc5ec7fcd98fe8780d250e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:25:10 +0900 Subject: [PATCH 27/28] Remove unnecessary content clear --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 82d0bdb51e..5220f6a391 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -133,7 +133,6 @@ namespace osu.Game.Overlays.Mods private void useCurrentMods() { saveableMods = selectedMods.Value.ToHashSet(); - scrollContent.Clear(); updateState(); } From e43fc23606e4b579fdf46ee54aa3fb144bb85d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 18:46:36 +0200 Subject: [PATCH 28/28] Fix typos in test --- .../Visual/UserInterface/TestSceneModPresetColumn.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 0cbbe00311..3efdba8754 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -262,7 +262,7 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestEditPresentName() + public void TestEditPresetName() { ModPresetColumn modPresetColumn = null!; string presetName = null!; @@ -301,7 +301,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - AddAssert("present is not changed", () => panel.Preset.Value.Name == presetName); + AddAssert("preset is not changed", () => panel.Preset.Value.Name == presetName); AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); AddStep("attempt preset edit", () => @@ -310,7 +310,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); - AddAssert("present is changed", () => panel.Preset.Value.Name != presetName); + AddAssert("preset is changed", () => panel.Preset.Value.Name != presetName); } [Test] @@ -357,7 +357,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - AddUntilStep("present mod not changed", () => + AddUntilStep("preset mod not changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(previousMod)); AddStep("select mods", () => SelectedMods.Value = mods); @@ -388,7 +388,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - AddUntilStep("present mod is changed", () => + AddUntilStep("preset mod is changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); }