Skip to content

Commit

Permalink
Merge pull request #29136 from Cai1Hsu/hover-open-mod-customise
Browse files Browse the repository at this point in the history
Hover to expand mod customise panel
  • Loading branch information
bdach committed Aug 7, 2024
2 parents 437812e + f83d43c commit 8d89751
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ public void TestCustomisationNotAvailable()

AddStep("select difficulty adjust", () => freeModSelectOverlay.SelectedMods.Value = new[] { new OsuModDifficultyAdjust() });
AddWaitStep("wait some", 3);
AddAssert("customisation area not expanded", () => !this.ChildrenOfType<ModCustomisationPanel>().Single().Expanded.Value);
AddAssert("customisation area not expanded",
() => this.ChildrenOfType<ModCustomisationPanel>().Single().ExpandedState.Value,
() => Is.EqualTo(ModCustomisationPanel.ModCustomisationPanelState.Collapsed));
}

[Test]
Expand Down
108 changes: 104 additions & 4 deletions osu.Game.Tests/Visual/UserInterface/TestSceneModCustomisationPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
Expand All @@ -10,6 +11,8 @@
using osu.Game.Overlays.Mods;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
using osuTK;
using osuTK.Input;

namespace osu.Game.Tests.Visual.UserInterface
{
Expand All @@ -19,10 +22,15 @@ public partial class TestSceneModCustomisationPanel : OsuManualInputManagerTestS
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);

private ModCustomisationPanel panel = null!;
private ModCustomisationHeader header = null!;
private Container content = null!;

[SetUp]
public void SetUp() => Schedule(() =>
{
SelectedMods.Value = Array.Empty<Mod>();
InputManager.MoveMouseTo(Vector2.One);
Child = new Container
{
RelativeSizeAxes = Axes.Both,
Expand All @@ -36,6 +44,9 @@ public void SetUp() => Schedule(() =>
SelectedMods = { BindTarget = SelectedMods },
}
};
header = panel.Children.OfType<ModCustomisationHeader>().First();
content = panel.Children.OfType<Container>().First();
});

[Test]
Expand All @@ -44,23 +55,112 @@ public void TestDisplay()
AddStep("set DT", () =>
{
SelectedMods.Value = new[] { new OsuModDoubleTime() };
panel.Enabled.Value = panel.Expanded.Value = true;
panel.Enabled.Value = true;
panel.ExpandedState.Value = ModCustomisationPanel.ModCustomisationPanelState.Expanded;
});
AddStep("set DA", () =>
{
SelectedMods.Value = new Mod[] { new OsuModDifficultyAdjust() };
panel.Enabled.Value = panel.Expanded.Value = true;
panel.Enabled.Value = true;
panel.ExpandedState.Value = ModCustomisationPanel.ModCustomisationPanelState.Expanded;
});
AddStep("set FL+WU+DA+AD", () =>
{
SelectedMods.Value = new Mod[] { new OsuModFlashlight(), new ModWindUp(), new OsuModDifficultyAdjust(), new OsuModApproachDifferent() };
panel.Enabled.Value = panel.Expanded.Value = true;
panel.Enabled.Value = true;
panel.ExpandedState.Value = ModCustomisationPanel.ModCustomisationPanelState.Expanded;
});
AddStep("set empty", () =>
{
SelectedMods.Value = Array.Empty<Mod>();
panel.Enabled.Value = panel.Expanded.Value = false;
panel.Enabled.Value = false;
panel.ExpandedState.Value = ModCustomisationPanel.ModCustomisationPanelState.Collapsed;
});
}

[Test]
public void TestHoverDoesNotExpandWhenNoCustomisableMods()
{
AddStep("hover header", () => InputManager.MoveMouseTo(header));

checkExpanded(false);

AddStep("hover content", () => InputManager.MoveMouseTo(content));

checkExpanded(false);

AddStep("left from content", () => InputManager.MoveMouseTo(Vector2.One));
}

[Test]
public void TestHoverExpandsWithCustomisableMods()
{
AddStep("add customisable mod", () =>
{
SelectedMods.Value = new[] { new OsuModDoubleTime() };
panel.Enabled.Value = true;
});

AddStep("hover header", () => InputManager.MoveMouseTo(header));
checkExpanded(true);

AddStep("move to content", () => InputManager.MoveMouseTo(content));
checkExpanded(true);

AddStep("move away", () => InputManager.MoveMouseTo(Vector2.One));
checkExpanded(false);

AddStep("hover header", () => InputManager.MoveMouseTo(header));
checkExpanded(true);

AddStep("move away", () => InputManager.MoveMouseTo(Vector2.One));
checkExpanded(false);
}

[Test]
public void TestExpandedStatePersistsWhenClicked()
{
AddStep("add customisable mod", () =>
{
SelectedMods.Value = new[] { new OsuModDoubleTime() };
panel.Enabled.Value = true;
});

AddStep("hover header", () => InputManager.MoveMouseTo(header));
checkExpanded(true);

AddStep("click", () => InputManager.Click(MouseButton.Left));
checkExpanded(false);
AddStep("click", () => InputManager.Click(MouseButton.Left));
checkExpanded(true);

AddStep("move away", () => InputManager.MoveMouseTo(Vector2.One));
checkExpanded(true);

AddStep("click", () => InputManager.Click(MouseButton.Left));
checkExpanded(false);
}

[Test]
public void TestHoverExpandsAndCollapsesWhenHeaderClicked()
{
AddStep("add customisable mod", () =>
{
SelectedMods.Value = new[] { new OsuModDoubleTime() };
panel.Enabled.Value = true;
});

AddStep("hover header", () => InputManager.MoveMouseTo(header));
checkExpanded(true);

AddStep("click", () => InputManager.Click(MouseButton.Left));
checkExpanded(false);
}

private void checkExpanded(bool expanded)
{
AddUntilStep(expanded ? "is expanded" : "not expanded", () => panel.ExpandedState.Value,
() => expanded ? Is.Not.EqualTo(ModCustomisationPanel.ModCustomisationPanelState.Collapsed) : Is.EqualTo(ModCustomisationPanel.ModCustomisationPanelState.Collapsed));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public void SetUpSteps()
AddStep("reset ruleset", () => Ruleset.Value = rulesetStore.GetRuleset(0));
AddStep("reset mods", () => SelectedMods.SetDefault());
AddStep("reset config", () => configManager.SetValue(OsuSetting.ModSelectTextSearchStartsActive, true));
AddStep("reset mouse", () => InputManager.MoveMouseTo(Vector2.One));
AddStep("set beatmap", () => Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo));
AddStep("set up presets", () =>
{
Expand Down Expand Up @@ -998,7 +999,9 @@ public void TestCustomisationPanelAbsorbsInput([Values] bool textSearchStartsAct
AddStep("press mouse", () => InputManager.PressButton(MouseButton.Left));
AddAssert("search still not focused", () => !this.ChildrenOfType<ShearedSearchTextBox>().Single().HasFocus);
AddStep("release mouse", () => InputManager.ReleaseButton(MouseButton.Left));
AddAssert("customisation panel closed by click", () => !this.ChildrenOfType<ModCustomisationPanel>().Single().Expanded.Value);
AddAssert("customisation panel closed by click",
() => this.ChildrenOfType<ModCustomisationPanel>().Single().ExpandedState.Value,
() => Is.EqualTo(ModCustomisationPanel.ModCustomisationPanelState.Collapsed));

if (textSearchStartsActive)
AddAssert("search focused", () => this.ChildrenOfType<ShearedSearchTextBox>().Single().HasFocus);
Expand All @@ -1021,7 +1024,9 @@ private void changeRuleset(int id)
private void assertCustomisationToggleState(bool disabled, bool active)
{
AddUntilStep($"customisation panel is {(disabled ? "" : "not ")}disabled", () => modSelectOverlay.ChildrenOfType<ModCustomisationPanel>().Single().Enabled.Value == !disabled);
AddAssert($"customisation panel is {(active ? "" : "not ")}active", () => modSelectOverlay.ChildrenOfType<ModCustomisationPanel>().Single().Expanded.Value == active);
AddAssert($"customisation panel is {(active ? "" : "not ")}active",
() => modSelectOverlay.ChildrenOfType<ModCustomisationPanel>().Single().ExpandedState.Value,
() => active ? Is.Not.EqualTo(ModCustomisationPanel.ModCustomisationPanelState.Collapsed) : Is.EqualTo(ModCustomisationPanel.ModCustomisationPanelState.Collapsed));
}

private T getSelectedMod<T>() where T : Mod => SelectedMods.Value.OfType<T>().Single();
Expand Down
52 changes: 47 additions & 5 deletions osu.Game/Overlays/Mods/ModCustomisationHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Localisation;
using osuTK;
using osuTK.Graphics;
using static osu.Game.Overlays.Mods.ModCustomisationPanel;

namespace osu.Game.Overlays.Mods
{
Expand All @@ -29,11 +31,13 @@ public partial class ModCustomisationHeader : OsuHoverContainer

protected override IEnumerable<Drawable> EffectTargets => new[] { background };

public readonly BindableBool Expanded = new BindableBool();
public readonly Bindable<ModCustomisationPanelState> ExpandedState = new Bindable<ModCustomisationPanelState>(ModCustomisationPanelState.Collapsed);

public ModCustomisationHeader()
private readonly ModCustomisationPanel panel;

public ModCustomisationHeader(ModCustomisationPanel panel)
{
Action = Expanded.Toggle;
this.panel = panel;
Enabled.Value = false;
}

Expand Down Expand Up @@ -102,10 +106,48 @@ protected override void LoadComplete()
}
}, true);

Expanded.BindValueChanged(v =>
ExpandedState.BindValueChanged(v =>
{
icon.ScaleTo(v.NewValue ? new Vector2(1, -1) : Vector2.One, 300, Easing.OutQuint);
icon.ScaleTo(v.NewValue > ModCustomisationPanelState.Collapsed ? new Vector2(1, -1) : Vector2.One, 300, Easing.OutQuint);
}, true);
}

protected override bool OnClick(ClickEvent e)
{
if (Enabled.Value)
{
ExpandedState.Value = ExpandedState.Value switch
{
ModCustomisationPanelState.Collapsed => ModCustomisationPanelState.Expanded,
_ => ModCustomisationPanelState.Collapsed
};
}

return base.OnClick(e);
}

private bool touchedThisFrame;

protected override bool OnTouchDown(TouchDownEvent e)
{
if (Enabled.Value)
{
touchedThisFrame = true;
Schedule(() => touchedThisFrame = false);
}

return base.OnTouchDown(e);
}

protected override bool OnHover(HoverEvent e)
{
if (Enabled.Value)
{
if (!touchedThisFrame && panel.ExpandedState.Value == ModCustomisationPanelState.Collapsed)
panel.ExpandedState.Value = ModCustomisationPanelState.ExpandedByHover;
}

return base.OnHover(e);
}
}
}
Loading

0 comments on commit 8d89751

Please sign in to comment.