diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaEditorSaving.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaEditorSaving.cs index ebaa8bcea2..7b45d87c5e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaEditorSaving.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaEditorSaving.cs @@ -20,10 +20,10 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Test] public void TestKeyCountChange() { - FormSliderBar keyCount = null!; + FormSliderBar keyCount = null!; AddStep("go to setup screen", () => InputManager.Key(Key.F4)); - AddUntilStep("retrieve key count slider", () => keyCount = Editor.ChildrenOfType().Single().ChildrenOfType>().First(), () => Is.Not.Null); + AddUntilStep("retrieve key count slider", () => keyCount = Editor.ChildrenOfType().Single().ChildrenOfType>().First(), () => Is.Not.Null); AddAssert("key count is 5", () => keyCount.Current.Value, () => Is.EqualTo(5)); AddStep("change key count to 8", () => { @@ -41,5 +41,32 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor AddStep("acquiesce", () => InputManager.Key(Key.Number1)); AddUntilStep("beatmap became 8K", () => Game.Beatmap.Value.BeatmapInfo.Difficulty.CircleSize, () => Is.EqualTo(8)); } + + [Test] + public void TestDualStagesChange() + { + FormCheckBox dualStages = null!; + FormSliderBar keyCount = null!; + + AddStep("go to setup screen", () => InputManager.Key(Key.F4)); + AddUntilStep("retrieve dual stages checkbox", () => dualStages = Editor.ChildrenOfType().Single().ChildrenOfType().First(), () => Is.Not.Null); + AddUntilStep("retrieve key count slider", () => keyCount = Editor.ChildrenOfType().Single().ChildrenOfType>().First(), () => Is.Not.Null); + AddAssert("key count is 5", () => keyCount.Current.Value, () => Is.EqualTo(5)); + AddStep("set dual stages", () => + { + dualStages.Current.Value = true; + }); + AddUntilStep("dialog visible", () => Game.ChildrenOfType().SingleOrDefault()?.CurrentDialog, Is.InstanceOf); + AddStep("refuse", () => InputManager.Key(Key.Number2)); + AddAssert("key count is 5", () => keyCount.Current.Value, () => Is.EqualTo(5)); + + AddStep("set dual stages again", () => + { + dualStages.Current.Value = true; + }); + AddUntilStep("dialog visible", () => Game.ChildrenOfType().Single().CurrentDialog, Is.InstanceOf); + AddStep("acquiesce", () => InputManager.Key(Key.Number1)); + AddUntilStep("beatmap became 12K", () => Game.Beatmap.Value.BeatmapInfo.Difficulty.CircleSize, () => Is.EqualTo(12)); + } } } diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs index 835a37e064..fe5c437e40 100644 --- a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs +++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaDifficultySection.cs @@ -7,6 +7,7 @@ using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Formats; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Resources.Localisation.Web; @@ -19,13 +20,22 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup { public override LocalisableString Title => EditorSetupStrings.DifficultyHeader; - private FormSliderBar keyCountSlider { get; set; } = null!; + private FormSliderBar keyCountSlider { get; set; } = null!; + private FormCheckBox dualStages { get; set; } = null!; private FormCheckBox specialStyle { get; set; } = null!; private FormSliderBar healthDrainSlider { get; set; } = null!; private FormSliderBar overallDifficultySlider { get; set; } = null!; private FormSliderBar baseVelocitySlider { get; set; } = null!; private FormSliderBar tickRateSlider { get; set; } = null!; + private readonly BindableInt singleStageKeyCount = new BindableInt + { + Default = (int)BeatmapDifficulty.DEFAULT_DIFFICULTY, + Precision = 1, + }; + + private readonly BindableInt actualKeyCount = new BindableInt(); + [Resolved] private Editor? editor { get; set; } @@ -37,20 +47,19 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup { Children = new Drawable[] { - keyCountSlider = new FormSliderBar + keyCountSlider = new FormSliderBar { Caption = BeatmapsetsStrings.ShowStatsCsMania, HintText = "The number of columns in the beatmap", - Current = new BindableFloat(Beatmap.Difficulty.CircleSize) - { - Default = BeatmapDifficulty.DEFAULT_DIFFICULTY, - MinValue = 0, - MaxValue = 10, - Precision = 1, - }, + Current = singleStageKeyCount, TransferValueOnCommit = true, TabbableContentContainer = this, }, + dualStages = new FormCheckBox + { + Caption = "Dual stages", + HintText = "Doubles the number of keys by adding a second stage." + }, specialStyle = new FormCheckBox { Caption = "Use special (N+1) style", @@ -117,16 +126,54 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup }, }; - keyCountSlider.Current.BindValueChanged(updateKeyCount); + setStateFromActualKeyCount((int)Beatmap.Difficulty.CircleSize); + + keyCountSlider.Current.BindValueChanged(_ => calculateActualKeyCount()); + dualStages.Current.BindValueChanged(_ => + { + updateSingleStageKeyCountBounds(); + calculateActualKeyCount(); + }); + actualKeyCount.BindValueChanged(updateKeyCount); + healthDrainSlider.Current.BindValueChanged(_ => updateValues()); overallDifficultySlider.Current.BindValueChanged(_ => updateValues()); baseVelocitySlider.Current.BindValueChanged(_ => updateValues()); tickRateSlider.Current.BindValueChanged(_ => updateValues()); } + private void updateSingleStageKeyCountBounds() + { + singleStageKeyCount.MinValue = dualStages.Current.Value ? ManiaRuleset.MAX_STAGE_KEYS / 2 + 1 : 1; + singleStageKeyCount.MaxValue = dualStages.Current.Value ? LegacyBeatmapDecoder.MAX_MANIA_KEY_COUNT / 2 : ManiaRuleset.MAX_STAGE_KEYS; + } + + private void setStateFromActualKeyCount(int keyCount) + { + actualKeyCount.Value = keyCount; + + if (keyCount > 10) + { + dualStages.Current.Value = true; + singleStageKeyCount.Value = keyCount / 2; + } + else + { + dualStages.Current.Value = false; + singleStageKeyCount.Value = keyCount; + } + + updateSingleStageKeyCountBounds(); + } + + private void calculateActualKeyCount() + { + actualKeyCount.Value = keyCountSlider.Current.Value * (dualStages.Current.Value ? 2 : 1); + } + private bool updatingKeyCount; - private void updateKeyCount(ValueChangedEvent keyCount) + private void updateKeyCount(ValueChangedEvent keyCount) { if (updatingKeyCount) return; @@ -143,7 +190,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup Schedule(() => { changeHandler!.RestoreState(-1); - Beatmap.Difficulty.CircleSize = keyCountSlider.Current.Value = keyCount.OldValue; + Beatmap.Difficulty.CircleSize = keyCount.OldValue; + setStateFromActualKeyCount(keyCount.OldValue); updatingKeyCount = false; }); } @@ -158,7 +206,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup { // for now, update these on commit rather than making BeatmapMetadata bindables. // after switching database engines we can reconsider if switching to bindables is a good direction. - Beatmap.Difficulty.CircleSize = keyCountSlider.Current.Value; + Beatmap.Difficulty.CircleSize = actualKeyCount.Value; Beatmap.SpecialStyle = specialStyle.Current.Value; Beatmap.Difficulty.DrainRate = healthDrainSlider.Current.Value; Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value;