mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 12:33:01 +08:00
Merge pull request #1702 from Aergwyn/add-deselect-mods-button
Added Deselect All button to ModSelectOverlay
This commit is contained in:
commit
2f02e062fd
@ -8,17 +8,25 @@ using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[Description("mod select and icon display")]
|
||||
internal class TestCaseMods : OsuTestCase
|
||||
{
|
||||
private ModSelectOverlay modSelect;
|
||||
private ModDisplay modDisplay;
|
||||
private const string unranked_suffix = " (Unranked)";
|
||||
|
||||
private RulesetStore rulesets;
|
||||
|
||||
private ModDisplay modDisplay;
|
||||
private TestModSelectOverlay modSelect;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
@ -30,7 +38,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Add(modSelect = new ModSelectOverlay
|
||||
Add(modSelect = new TestModSelectOverlay
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Origin = Anchor.BottomCentre,
|
||||
@ -48,9 +56,156 @@ namespace osu.Game.Tests.Visual
|
||||
modDisplay.Current.BindTo(modSelect.SelectedMods);
|
||||
|
||||
AddStep("Toggle", modSelect.ToggleVisibility);
|
||||
AddStep("Hide", modSelect.Hide);
|
||||
AddStep("Show", modSelect.Show);
|
||||
|
||||
foreach (var ruleset in rulesets.AvailableRulesets)
|
||||
AddStep(ruleset.CreateInstance().Description, () => modSelect.Ruleset.Value = ruleset);
|
||||
foreach (var rulesetInfo in rulesets.AvailableRulesets)
|
||||
{
|
||||
Ruleset ruleset = rulesetInfo.CreateInstance();
|
||||
AddStep($"switch to {ruleset.Description}", () => modSelect.Ruleset.Value = rulesetInfo);
|
||||
|
||||
switch (ruleset) {
|
||||
case OsuRuleset or:
|
||||
testOsuMods(or);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void testOsuMods(OsuRuleset ruleset)
|
||||
{
|
||||
var easierMods = ruleset.GetModsFor(ModType.DifficultyReduction);
|
||||
var harderMods = ruleset.GetModsFor(ModType.DifficultyIncrease);
|
||||
var assistMods = ruleset.GetModsFor(ModType.Special);
|
||||
|
||||
var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail);
|
||||
var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden);
|
||||
var doubleTimeMod = harderMods.OfType<MultiMod>().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime));
|
||||
var autoPilotMod = assistMods.FirstOrDefault(m => m is OsuModAutopilot);
|
||||
|
||||
testSingleMod(noFailMod);
|
||||
testMultiMod(doubleTimeMod);
|
||||
testIncompatibleMods(noFailMod, autoPilotMod);
|
||||
testDeselectAll(easierMods.Where(m => !(m is MultiMod)));
|
||||
testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour);
|
||||
testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour);
|
||||
testMultiplierTextUnranked(autoPilotMod);
|
||||
}
|
||||
|
||||
private void testSingleMod(Mod mod)
|
||||
{
|
||||
selectNext(mod);
|
||||
checkSelected(mod);
|
||||
|
||||
selectPrevious(mod);
|
||||
checkNotSelected(mod);
|
||||
|
||||
selectNext(mod);
|
||||
selectNext(mod);
|
||||
checkNotSelected(mod);
|
||||
|
||||
selectPrevious(mod);
|
||||
selectPrevious(mod);
|
||||
checkNotSelected(mod);
|
||||
}
|
||||
|
||||
private void testMultiMod(MultiMod multiMod)
|
||||
{
|
||||
foreach (var mod in multiMod.Mods)
|
||||
{
|
||||
selectNext(mod);
|
||||
checkSelected(mod);
|
||||
}
|
||||
|
||||
for (int index = multiMod.Mods.Length - 1; index >= 0; index--)
|
||||
selectPrevious(multiMod.Mods[index]);
|
||||
|
||||
foreach (var mod in multiMod.Mods)
|
||||
checkNotSelected(mod);
|
||||
}
|
||||
|
||||
private void testIncompatibleMods(Mod modA, Mod modB)
|
||||
{
|
||||
selectNext(modA);
|
||||
checkSelected(modA);
|
||||
checkNotSelected(modB);
|
||||
|
||||
selectNext(modB);
|
||||
checkSelected(modB);
|
||||
checkNotSelected(modA);
|
||||
|
||||
selectPrevious(modB);
|
||||
checkNotSelected(modA);
|
||||
checkNotSelected(modB);
|
||||
}
|
||||
|
||||
private void testDeselectAll(IEnumerable<Mod> mods)
|
||||
{
|
||||
foreach (var mod in mods)
|
||||
selectNext(mod);
|
||||
|
||||
AddAssert("check for any selection", () => modSelect.SelectedMods.Value.Any());
|
||||
AddStep("deselect all", modSelect.DeselectAllButton.Action.Invoke);
|
||||
AddAssert("check for no selection", () => !modSelect.SelectedMods.Value.Any());
|
||||
}
|
||||
|
||||
private void testMultiplierTextColour(Mod mod, Color4 colour)
|
||||
{
|
||||
checkLabelColor(Color4.White);
|
||||
selectNext(mod);
|
||||
AddWaitStep(1, "wait for changing colour");
|
||||
checkLabelColor(colour);
|
||||
selectPrevious(mod);
|
||||
AddWaitStep(1, "wait for changing colour");
|
||||
checkLabelColor(Color4.White);
|
||||
}
|
||||
|
||||
private void testMultiplierTextUnranked(Mod mod)
|
||||
{
|
||||
AddAssert("check for ranked", () => !modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix));
|
||||
selectNext(mod);
|
||||
AddAssert("check for unranked", () => modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix));
|
||||
selectPrevious(mod);
|
||||
AddAssert("check for ranked", () => !modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix));
|
||||
}
|
||||
|
||||
private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext());
|
||||
|
||||
private void selectPrevious(Mod mod) => AddStep($"right click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectPrevious());
|
||||
|
||||
private void checkSelected(Mod mod)
|
||||
{
|
||||
AddAssert($"check {mod.Name} is selected", () =>
|
||||
{
|
||||
var button = modSelect.GetModButton(mod);
|
||||
return modSelect.SelectedMods.Value.Single(m => m.Name == mod.Name) != null && button.SelectedMod.GetType() == mod.GetType() && button.Selected;
|
||||
});
|
||||
}
|
||||
|
||||
private void checkNotSelected(Mod mod)
|
||||
{
|
||||
AddAssert($"check {mod.Name} is not selected", () =>
|
||||
{
|
||||
var button = modSelect.GetModButton(mod);
|
||||
return modSelect.SelectedMods.Value.All(m => m.GetType() != mod.GetType()) && button.SelectedMod?.GetType() != mod.GetType();
|
||||
});
|
||||
}
|
||||
|
||||
private void checkLabelColor(Color4 color) => AddAssert("check label has expected colour", () => modSelect.MultiplierLabel.Colour.AverageColour == color);
|
||||
|
||||
private class TestModSelectOverlay : ModSelectOverlay
|
||||
{
|
||||
public ModButton GetModButton(Mod mod)
|
||||
{
|
||||
var section = ModSectionsContainer.Children.Single(s => s.ModType == mod.Type);
|
||||
return section.ButtonsContainer.OfType<ModButton>().Single(b => b.Mods.Any(m => m.GetType() == mod.GetType()));
|
||||
}
|
||||
|
||||
public new OsuSpriteText MultiplierLabel => base.MultiplierLabel;
|
||||
public new TriangleButton DeselectAllButton => base.DeselectAllButton;
|
||||
|
||||
public new Color4 LowMultiplierColour => base.LowMultiplierColour;
|
||||
public new Color4 HighMultiplierColour => base.HighMultiplierColour;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,22 +17,21 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class ModSelectOverlay : WaveOverlayContainer
|
||||
{
|
||||
private const int button_duration = 700;
|
||||
private const int ranked_multiplier_duration = 700;
|
||||
private const float content_width = 0.8f;
|
||||
|
||||
private Color4 lowMultiplierColour, highMultiplierColour;
|
||||
protected Color4 LowMultiplierColour, HighMultiplierColour;
|
||||
|
||||
private readonly OsuSpriteText rankedLabel;
|
||||
private readonly OsuSpriteText multiplierLabel;
|
||||
private readonly FillFlowContainer rankedMultiplerContainer;
|
||||
protected readonly TriangleButton DeselectAllButton;
|
||||
protected readonly OsuSpriteText MultiplierLabel;
|
||||
private readonly FillFlowContainer footerContainer;
|
||||
|
||||
private readonly FillFlowContainer<ModSection> modSectionsContainer;
|
||||
protected readonly FillFlowContainer<ModSection> ModSectionsContainer;
|
||||
|
||||
public readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>();
|
||||
|
||||
@ -42,7 +41,7 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
var instance = newRuleset.CreateInstance();
|
||||
|
||||
foreach (ModSection section in modSectionsContainer.Children)
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.Mods = instance.GetModsFor(section.ModType);
|
||||
refreshSelectedMods();
|
||||
}
|
||||
@ -50,8 +49,8 @@ namespace osu.Game.Overlays.Mods
|
||||
[BackgroundDependencyLoader(permitNulls: true)]
|
||||
private void load(OsuColour colours, OsuGame osu, RulesetStore rulesets)
|
||||
{
|
||||
lowMultiplierColour = colours.Red;
|
||||
highMultiplierColour = colours.Green;
|
||||
LowMultiplierColour = colours.Red;
|
||||
HighMultiplierColour = colours.Green;
|
||||
|
||||
if (osu != null)
|
||||
Ruleset.BindTo(osu.Ruleset);
|
||||
@ -66,14 +65,14 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
base.PopOut();
|
||||
|
||||
rankedMultiplerContainer.MoveToX(rankedMultiplerContainer.DrawSize.X, APPEAR_DURATION, Easing.InSine);
|
||||
rankedMultiplerContainer.FadeOut(APPEAR_DURATION, Easing.InSine);
|
||||
footerContainer.MoveToX(footerContainer.DrawSize.X, DISAPPEAR_DURATION, Easing.InSine);
|
||||
footerContainer.FadeOut(DISAPPEAR_DURATION, Easing.InSine);
|
||||
|
||||
foreach (ModSection section in modSectionsContainer.Children)
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), APPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.MoveToX(100f, APPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.FadeOut(APPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.MoveToX(100f, DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.FadeOut(DISAPPEAR_DURATION, Easing.InSine);
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,27 +80,28 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
base.PopIn();
|
||||
|
||||
rankedMultiplerContainer.MoveToX(0, ranked_multiplier_duration, Easing.OutQuint);
|
||||
rankedMultiplerContainer.FadeIn(ranked_multiplier_duration, Easing.OutQuint);
|
||||
footerContainer.MoveToX(0, APPEAR_DURATION, Easing.OutQuint);
|
||||
footerContainer.FadeIn(APPEAR_DURATION, Easing.OutQuint);
|
||||
|
||||
foreach (ModSection section in modSectionsContainer.Children)
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), button_duration, Easing.OutQuint);
|
||||
section.ButtonsContainer.MoveToX(0, button_duration, Easing.OutQuint);
|
||||
section.ButtonsContainer.FadeIn(button_duration, Easing.OutQuint);
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.MoveToX(0, APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.FadeIn(APPEAR_DURATION, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeselectAll()
|
||||
{
|
||||
foreach (ModSection section in modSectionsContainer.Children)
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.DeselectAll();
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
public void DeselectTypes(Type[] modTypes)
|
||||
{
|
||||
if (modTypes.Length == 0) return;
|
||||
foreach (ModSection section in modSectionsContainer.Children)
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.DeselectTypes(modTypes);
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
private void refreshSelectedMods()
|
||||
{
|
||||
SelectedMods.Value = modSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||
SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||
|
||||
double multiplier = 1.0;
|
||||
bool ranked = true;
|
||||
@ -129,16 +129,16 @@ namespace osu.Game.Overlays.Mods
|
||||
// 1.05x
|
||||
// 1.20x
|
||||
|
||||
multiplierLabel.Text = $"{multiplier:N2}x";
|
||||
string rankedString = ranked ? "Ranked" : "Unranked";
|
||||
rankedLabel.Text = $@"{rankedString}, Score Multiplier: ";
|
||||
MultiplierLabel.Text = $"{multiplier:N2}x";
|
||||
if (!ranked)
|
||||
MultiplierLabel.Text += " (Unranked)";
|
||||
|
||||
if (multiplier > 1.0)
|
||||
multiplierLabel.FadeColour(highMultiplierColour, 200);
|
||||
MultiplierLabel.FadeColour(HighMultiplierColour, 200);
|
||||
else if (multiplier < 1.0)
|
||||
multiplierLabel.FadeColour(lowMultiplierColour, 200);
|
||||
MultiplierLabel.FadeColour(LowMultiplierColour, 200);
|
||||
else
|
||||
multiplierLabel.FadeColour(Color4.White, 200);
|
||||
MultiplierLabel.FadeColour(Color4.White, 200);
|
||||
}
|
||||
|
||||
public ModSelectOverlay()
|
||||
@ -232,7 +232,7 @@ namespace osu.Game.Overlays.Mods
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = @"Others are just for fun",
|
||||
Text = @"Others are just for fun.",
|
||||
TextSize = 18,
|
||||
Shadow = true,
|
||||
},
|
||||
@ -241,7 +241,7 @@ namespace osu.Game.Overlays.Mods
|
||||
},
|
||||
},
|
||||
// Body
|
||||
modSectionsContainer = new FillFlowContainer<ModSection>
|
||||
ModSectionsContainer = new FillFlowContainer<ModSection>
|
||||
{
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
@ -289,7 +289,7 @@ namespace osu.Game.Overlays.Mods
|
||||
Colour = new Color4(172, 20, 116, 255),
|
||||
Alpha = 0.5f,
|
||||
},
|
||||
rankedMultiplerContainer = new FillFlowContainer
|
||||
footerContainer = new FillFlowContainer
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
@ -299,26 +299,42 @@ namespace osu.Game.Overlays.Mods
|
||||
Direction = FillDirection.Horizontal,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = 20,
|
||||
Bottom = 20,
|
||||
Vertical = 15
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
rankedLabel = new OsuSpriteText
|
||||
DeselectAllButton = new TriangleButton
|
||||
{
|
||||
Text = @"Ranked, Score Multiplier: ",
|
||||
Width = 180,
|
||||
Text = "Deselect All",
|
||||
Action = DeselectAll,
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Right = 20
|
||||
}
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = @"Score Multiplier: ",
|
||||
TextSize = 30,
|
||||
Shadow = true,
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Top = 5
|
||||
}
|
||||
},
|
||||
multiplierLabel = new OsuSpriteText
|
||||
MultiplierLabel = new OsuSpriteText
|
||||
{
|
||||
Font = @"Exo2.0-Bold",
|
||||
Text = @"1.00x",
|
||||
TextSize = 30,
|
||||
Shadow = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Top = 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user