Skip to content

Hide HoldForMenuButton on non-touch devices #26128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Testing;
using osu.Game.Screens.Play.HUD;
using osuTK;
using osuTK.Input;
Expand All @@ -23,26 +22,29 @@ public partial class TestSceneHoldForMenuButton : OsuManualInputManagerTestScene

private HoldForMenuButton holdForMenuButton;

[SetUpSteps]
public void SetUpSteps()
private void setupSteps(bool autoHide)
{
AddStep("create button", () =>
{
InputManager.MoveMouseTo(Vector2.One);

exitAction = false;

Child = holdForMenuButton = new HoldForMenuButton
{
Scale = new Vector2(2),
Origin = Anchor.CentreRight,
Anchor = Anchor.CentreRight,
Action = () => exitAction = true
Action = () => exitAction = true,
AutoHide = { Value = autoHide },
};
});
}

[Test]
public void TestMovementAndTrigger()
public void TestFullMovementAndTrigger()
{
setupSteps(autoHide: false);
AddStep("Trigger text fade in", () => InputManager.MoveMouseTo(holdForMenuButton));
AddUntilStep("Text visible", () => getSpriteText().IsPresent && !exitAction);
AddStep("Trigger text fade out", () => InputManager.MoveMouseTo(Vector2.One));
Expand All @@ -63,11 +65,31 @@ public void TestMovementAndTrigger()
}

[Test]
public void TestFadeOnNoInput()
public void TestAutoHide()
{
setupSteps(autoHide: true);
AddAssert("Container initially invisible", () => holdForMenuButton.Alpha < .01f);
AddStep("Trigger fade in", () => InputManager.MoveMouseTo(holdForMenuButton));
AddUntilStep("Container visible", () => holdForMenuButton.Alpha >= 1f && !exitAction);
AddStep("Trigger fade out", () => InputManager.MoveMouseTo(Vector2.One));
AddUntilStep("Container invisible", () => holdForMenuButton.Alpha < .01f && !exitAction);

// Make sure container hasn't disappeared
AddStep("Trigger exit action", () =>
{
InputManager.MoveMouseTo(holdForMenuButton);
InputManager.PressButton(MouseButton.Left);
});
AddUntilStep($"{nameof(holdForMenuButton.Action)} was triggered", () => exitAction);
}

[Test]
public void TestPartialFadeOnNoInput()
{
setupSteps(autoHide: false);
AddStep("move mouse away", () => InputManager.MoveMouseTo(Vector2.One));
AddUntilStep("wait for text fade out", () => !getSpriteText().IsPresent);
AddUntilStep("wait for button fade out", () => holdForMenuButton.Alpha < 0.1f);
AddUntilStep("wait for button fade out", () => holdForMenuButton.Alpha < 1f);
}

private SpriteText getSpriteText() => holdForMenuButton.Children.OfType<SpriteText>().First();
Expand Down
18 changes: 16 additions & 2 deletions osu.Game/Screens/Play/HUD/HoldForMenuButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public partial class HoldForMenuButton : FillFlowContainer

public readonly Bindable<bool> ReplayLoaded = new Bindable<bool>();

/// <summary>
/// Disable the entering animation and stay fully hidden until the cursor is nearby.
/// </summary>
public readonly Bindable<bool> AutoHide = new Bindable<bool>();

private HoldButton button;

public Action Action { get; set; }
Expand All @@ -41,6 +46,7 @@ public partial class HoldForMenuButton : FillFlowContainer

public HoldForMenuButton()
{
Alpha = .001f;
Direction = FillDirection.Horizontal;
Spacing = new Vector2(20, 0);
Margin = new MarginPadding(10);
Expand All @@ -53,6 +59,7 @@ private void load(Player player)
{
text = new OsuSpriteText
{
Alpha = 0f,
Font = OsuFont.GetFont(weight: FontWeight.Bold),
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft
Expand All @@ -78,7 +85,12 @@ protected override void LoadComplete()
: "press for menu";
}, true);

text.FadeInFromZero(500, Easing.OutQuint).Delay(1500).FadeOut(500, Easing.OutQuint);
if (!AutoHide.Value)
{
text.FadeInFromZero(500, Easing.OutQuint)
.Delay(1500)
.FadeOut(500, Easing.OutQuint);
}

base.LoadComplete();
}
Expand All @@ -99,9 +111,11 @@ protected override void Update()
Alpha = 1;
else
{
float minAlpha = AutoHide.Value ? .001f : .07f;
Copy link
Contributor Author

@rushiiMachine rushiiMachine Dec 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried allowing the alpha to clamp to 0, (and enabling AlwaysPresent on the container), however ran into issues with testing as the interpolation below seemed to never reach a fixed value.


Alpha = Interpolation.ValueAt(
Math.Clamp(Clock.ElapsedFrameTime, 0, 200),
Alpha, Math.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint);
Alpha, Math.Clamp(1 - positionalAdjust, minAlpha, 1), 0, 200, Easing.OutQuint);
}
}

Expand Down
5 changes: 3 additions & 2 deletions osu.Game/Screens/Play/HUDOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public HUDOverlay([CanBeNull] DrawableRuleset drawableRuleset, IReadOnlyList<Mod
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
HoldToQuit = CreateHoldForMenuButton(),
HoldToQuit = CreateHoldForMenuButton(touchDevice: mods.Any(m => m is ModTouchDevice)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than doing this, use SessionStatics from within the class, don't pass anything in.

[BackgroundDependencyLoader]
private void load(SessionStatics statics)
{
touchActive = statics.GetBindable<bool>(Static.TouchInputActive);
touchActive.BindValueChanged(_ => updateState());
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't self resolve issues. This isn't even fixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I misunderstood it as "dont pass anything to CreateHoldForMenuButton", I assume you meant inject it from within HoldForMenuButton?

}
},
LeaderboardFlow = new FillFlowContainer
Expand Down Expand Up @@ -354,10 +354,11 @@ protected virtual void BindDrawableRuleset(DrawableRuleset drawableRuleset)
ShowHealth = { BindTarget = ShowHealthBar }
};

protected HoldForMenuButton CreateHoldForMenuButton() => new HoldForMenuButton
protected HoldForMenuButton CreateHoldForMenuButton(bool touchDevice) => new HoldForMenuButton
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
AutoHide = { Value = !touchDevice },
};

protected ModDisplay CreateModsContainer() => new ModDisplay
Expand Down