1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 22:07:25 +08:00

Merge pull request #3188 from peppy/fix-mod-reselection

Fix mod re-selection
This commit is contained in:
Dan Balasescu 2018-08-08 15:45:28 +09:00 committed by GitHub
commit 0d8f60bff2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 102 additions and 71 deletions

View File

@ -2,7 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.ComponentModel;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Overlays.Mods;
@ -13,11 +12,11 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
using System.Linq;
using System.Collections.Generic;
using osu.Game.Rulesets.Osu;
using NUnit.Framework;
using osu.Framework.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.Sprites;
using osu.Game.Overlays.Mods.Sections;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Mania.Mods;
using osu.Game.Rulesets.UI;
using OpenTK.Graphics;
@ -50,11 +49,6 @@ namespace osu.Game.Tests.Visual
private void load(RulesetStore rulesets)
{
this.rulesets = rulesets;
}
protected override void LoadComplete()
{
base.LoadComplete();
Add(modSelect = new TestModSelectOverlay
{
@ -71,34 +65,25 @@ namespace osu.Game.Tests.Visual
Position = new Vector2(0, 25),
});
modDisplay.Current.UnbindBindings();
modDisplay.Current.BindTo(modSelect.SelectedMods);
AddStep("Toggle", modSelect.ToggleVisibility);
AddStep("Hide", modSelect.Hide);
AddStep("Show", modSelect.Show);
foreach (var rulesetInfo in rulesets.AvailableRulesets)
{
Ruleset ruleset = rulesetInfo.CreateInstance();
AddStep($"switch to {ruleset.Description}", () => Ruleset.Value = rulesetInfo);
switch (ruleset)
{
case OsuRuleset or:
testOsuMods(or);
break;
case ManiaRuleset mr:
testManiaMods(mr);
break;
}
}
AddStep("Toggle", modSelect.ToggleVisibility);
AddStep("Toggle", modSelect.ToggleVisibility);
}
private void testOsuMods(OsuRuleset ruleset)
[Test]
public void TestOsuMods()
{
var easierMods = ruleset.GetModsFor(ModType.DifficultyReduction);
var harderMods = ruleset.GetModsFor(ModType.DifficultyIncrease);
var assistMods = ruleset.GetModsFor(ModType.Automation);
var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 0);
AddStep("change ruleset", () => { Ruleset.Value = ruleset; });
var instance = ruleset.CreateInstance();
var easierMods = instance.GetModsFor(ModType.DifficultyReduction);
var harderMods = instance.GetModsFor(ModType.DifficultyIncrease);
var assistMods = instance.GetModsFor(ModType.Automation);
var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail);
var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden);
@ -120,9 +105,40 @@ namespace osu.Game.Tests.Visual
testUnimplementedMod(autoPilotMod);
}
private void testManiaMods(ManiaRuleset ruleset)
[Test]
public void TestManiaMods()
{
testRankedText(ruleset.GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom));
var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 3);
AddStep("change ruleset", () => { Ruleset.Value = ruleset; });
testRankedText(ruleset.CreateInstance().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom));
}
[Test]
public void TestRulesetChanges()
{
var rulesetOsu = rulesets.AvailableRulesets.First(r => r.ID == 0);
var rulesetMania = rulesets.AvailableRulesets.First(r => r.ID == 3);
AddStep("change ruleset to null", () => { Ruleset.Value = null; });
var instance = rulesetOsu.CreateInstance();
var easierMods = instance.GetModsFor(ModType.DifficultyReduction);
var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail);
AddStep("set mods externally", () => { modDisplay.Current.Value = new[] { noFailMod }; });
AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; });
AddAssert("ensure mods still selected", () => modDisplay.Current.Value.Single(m => m is OsuModNoFail) != null);
AddStep("change ruleset to mania", () => { Ruleset.Value = rulesetMania; });
AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any(m => m is OsuModNoFail));
AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; });
AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any());
}
private void testSingleMod(Mod mod)
@ -237,6 +253,8 @@ namespace osu.Game.Tests.Visual
private class TestModSelectOverlay : ModSelectOverlay
{
public new Bindable<IEnumerable<Mod>> SelectedMods => base.SelectedMods;
public ModButton GetModButton(Mod mod)
{
var section = ModSectionsContainer.Children.Single(s => s.ModType == mod.Type);

View File

@ -99,7 +99,9 @@ namespace osu.Game
private readonly List<OverlayContainer> overlays = new List<OverlayContainer>();
// todo: move this to SongSelect once Screen has the ability to unsuspend.
public readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>(new List<Mod>());
[Cached]
[Cached(Type = typeof(IBindable<IEnumerable<Mod>>))]
private readonly Bindable<IEnumerable<Mod>> selectedMods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
public OsuGame(string[] args = null)
{

View File

@ -39,9 +39,39 @@ namespace osu.Game.Overlays.Mods
protected readonly FillFlowContainer<ModSection> ModSectionsContainer;
public readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>();
protected readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
public readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
protected readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
[BackgroundDependencyLoader(true)]
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IEnumerable<Mod>> selectedMods)
{
LowMultiplierColour = colours.Red;
HighMultiplierColour = colours.Green;
UnrankedLabel.Colour = colours.Blue;
Ruleset.BindTo(ruleset);
if (selectedMods != null) SelectedMods.BindTo(selectedMods);
sampleOn = audio.Sample.Get(@"UI/check-on");
sampleOff = audio.Sample.Get(@"UI/check-off");
}
protected override void LoadComplete()
{
base.LoadComplete();
Ruleset.BindValueChanged(rulesetChanged, true);
SelectedMods.BindValueChanged(selectedModsChanged, true);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
Ruleset.UnbindAll();
SelectedMods.UnbindAll();
}
private void rulesetChanged(RulesetInfo newRuleset)
{
@ -51,33 +81,16 @@ namespace osu.Game.Overlays.Mods
foreach (ModSection section in ModSectionsContainer.Children)
section.Mods = instance.GetModsFor(section.ModType);
// attempt to re-select any already selected mods.
// this may be the first time we are receiving the ruleset, in which case they will still match.
selectedModsChanged(SelectedMods.Value);
// write the mods back to the SelectedMods bindable in the case a change was not applicable.
// this generally isn't required as the previous line will perform deselection; just here for safety.
refreshSelectedMods();
}
[BackgroundDependencyLoader]
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio)
{
SelectedMods.ValueChanged += selectedModsChanged;
LowMultiplierColour = colours.Red;
HighMultiplierColour = colours.Green;
UnrankedLabel.Colour = colours.Blue;
Ruleset.BindTo(ruleset);
Ruleset.BindValueChanged(rulesetChanged, true);
sampleOn = audio.Sample.Get(@"UI/check-on");
sampleOff = audio.Sample.Get(@"UI/check-off");
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
Ruleset.UnbindAll();
SelectedMods.UnbindAll();
}
private void selectedModsChanged(IEnumerable<Mod> obj)
{
foreach (ModSection section in ModSectionsContainer.Children)
@ -176,10 +189,7 @@ namespace osu.Game.Overlays.Mods
refreshSelectedMods();
}
private void refreshSelectedMods()
{
SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
}
private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
public ModSelectOverlay()
{

View File

@ -50,13 +50,14 @@ namespace osu.Game.Screens.Select
private SampleChannel sampleConfirm;
public readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>(new List<Mod>());
[Cached]
[Cached(Type = typeof(IBindable<IEnumerable<Mod>>))]
private readonly Bindable<IEnumerable<Mod>> selectedMods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
[BackgroundDependencyLoader(true)]
private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, OsuGame osu)
private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable<IEnumerable<Mod>> selectedMods)
{
if (osu != null) SelectedMods.BindTo(osu.SelectedMods);
modSelect.SelectedMods.BindTo(SelectedMods);
if (selectedMods != null) this.selectedMods.BindTo(selectedMods);
sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection");
@ -84,7 +85,7 @@ namespace osu.Game.Screens.Select
protected override void UpdateBeatmap(WorkingBeatmap beatmap)
{
beatmap.Mods.BindTo(SelectedMods);
beatmap.Mods.BindTo(selectedMods);
base.UpdateBeatmap(beatmap);
@ -131,7 +132,7 @@ namespace osu.Game.Screens.Select
if (Beatmap.Value.Track != null)
Beatmap.Value.Track.Looping = false;
SelectedMods.UnbindAll();
selectedMods.UnbindAll();
Beatmap.Value.Mods.Value = new Mod[] { };
return false;
@ -147,10 +148,10 @@ namespace osu.Game.Screens.Select
var auto = Ruleset.Value.CreateInstance().GetAutoplayMod();
var autoType = auto.GetType();
var mods = modSelect.SelectedMods.Value;
var mods = selectedMods.Value;
if (mods.All(m => m.GetType() != autoType))
{
modSelect.SelectedMods.Value = mods.Append(auto);
selectedMods.Value = mods.Append(auto);
removeAutoModOnResume = true;
}
}