mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 09:32:55 +08:00
Merge pull request #7168 from peppy/improve-hud-hiding
Improve HUD hiding
This commit is contained in:
commit
267d832ecc
81
osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs
Normal file
81
osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
|
{
|
||||||
|
public class TestSceneHUDOverlay : ManualInputManagerTestScene
|
||||||
|
{
|
||||||
|
private HUDOverlay hudOverlay;
|
||||||
|
|
||||||
|
private Drawable hideTarget => hudOverlay.KeyCounter; // best way of checking hideTargets without exposing.
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuConfigManager config { get; set; }
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestShownByDefault()
|
||||||
|
{
|
||||||
|
createNew();
|
||||||
|
|
||||||
|
AddAssert("showhud is set", () => hudOverlay.ShowHud.Value);
|
||||||
|
|
||||||
|
AddAssert("hidetarget is visible", () => hideTarget.IsPresent);
|
||||||
|
AddAssert("pause button is visible", () => hudOverlay.HoldToQuit.IsPresent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestFadesInOnLoadComplete()
|
||||||
|
{
|
||||||
|
float? initialAlpha = null;
|
||||||
|
|
||||||
|
createNew(h => h.OnLoadComplete += _ => initialAlpha = hideTarget.Alpha);
|
||||||
|
AddUntilStep("wait for load", () => hudOverlay.IsAlive);
|
||||||
|
AddAssert("initial alpha was less than 1", () => initialAlpha != null && initialAlpha < 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHideExternally()
|
||||||
|
{
|
||||||
|
createNew();
|
||||||
|
|
||||||
|
AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false);
|
||||||
|
|
||||||
|
AddUntilStep("hidetarget is hidden", () => !hideTarget.IsPresent);
|
||||||
|
AddAssert("pause button is still visible", () => hudOverlay.HoldToQuit.IsPresent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestExternalHideDoesntAffectConfig()
|
||||||
|
{
|
||||||
|
bool originalConfigValue = false;
|
||||||
|
|
||||||
|
createNew();
|
||||||
|
|
||||||
|
AddStep("get original config value", () => originalConfigValue = config.Get<bool>(OsuSetting.ShowInterface));
|
||||||
|
|
||||||
|
AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false);
|
||||||
|
AddAssert("config unchanged", () => originalConfigValue == config.Get<bool>(OsuSetting.ShowInterface));
|
||||||
|
|
||||||
|
AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true);
|
||||||
|
AddAssert("config unchanged", () => originalConfigValue == config.Get<bool>(OsuSetting.ShowInterface));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNew(Action<HUDOverlay> action = null)
|
||||||
|
{
|
||||||
|
AddStep("create overlay", () =>
|
||||||
|
{
|
||||||
|
Child = hudOverlay = new HUDOverlay(null, null, Array.Empty<Mod>());
|
||||||
|
|
||||||
|
action?.Invoke(hudOverlay);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,8 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
processor.NewJudgement += onNewJudgement;
|
if (processor != null)
|
||||||
|
processor.NewJudgement += onNewJudgement;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -96,7 +97,9 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
processor.NewJudgement -= onNewJudgement;
|
|
||||||
|
if (processor != null)
|
||||||
|
processor.NewJudgement -= onNewJudgement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
@ -23,8 +24,8 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
public class HUDOverlay : Container
|
public class HUDOverlay : Container
|
||||||
{
|
{
|
||||||
private const int duration = 250;
|
private const float fade_duration = 400;
|
||||||
private const Easing easing = Easing.OutQuint;
|
private const Easing fade_easing = Easing.Out;
|
||||||
|
|
||||||
public readonly KeyCounterDisplay KeyCounter;
|
public readonly KeyCounterDisplay KeyCounter;
|
||||||
public readonly RollingCounter<int> ComboCounter;
|
public readonly RollingCounter<int> ComboCounter;
|
||||||
@ -43,8 +44,15 @@ namespace osu.Game.Screens.Play
|
|||||||
private readonly DrawableRuleset drawableRuleset;
|
private readonly DrawableRuleset drawableRuleset;
|
||||||
private readonly IReadOnlyList<Mod> mods;
|
private readonly IReadOnlyList<Mod> mods;
|
||||||
|
|
||||||
private Bindable<bool> showHud;
|
/// <summary>
|
||||||
|
/// Whether the elements that can optionally be hidden should be visible.
|
||||||
|
/// </summary>
|
||||||
|
public Bindable<bool> ShowHud { get; } = new BindableBool();
|
||||||
|
|
||||||
|
private Bindable<bool> configShowHud;
|
||||||
|
|
||||||
private readonly Container visibilityContainer;
|
private readonly Container visibilityContainer;
|
||||||
|
|
||||||
private readonly BindableBool replayLoaded = new BindableBool();
|
private readonly BindableBool replayLoaded = new BindableBool();
|
||||||
|
|
||||||
private static bool hasShownNotificationOnce;
|
private static bool hasShownNotificationOnce;
|
||||||
@ -53,6 +61,8 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private readonly Container topScoreContainer;
|
private readonly Container topScoreContainer;
|
||||||
|
|
||||||
|
private IEnumerable<Drawable> hideTargets => new Drawable[] { visibilityContainer, KeyCounter };
|
||||||
|
|
||||||
public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods)
|
public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods)
|
||||||
{
|
{
|
||||||
this.scoreProcessor = scoreProcessor;
|
this.scoreProcessor = scoreProcessor;
|
||||||
@ -68,13 +78,12 @@ namespace osu.Game.Screens.Play
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
|
HealthDisplay = CreateHealthDisplay(),
|
||||||
topScoreContainer = new Container
|
topScoreContainer = new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
AutoSizeDuration = 200,
|
|
||||||
AutoSizeEasing = Easing.Out,
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
AccuracyCounter = CreateAccuracyCounter(),
|
AccuracyCounter = CreateAccuracyCounter(),
|
||||||
@ -82,19 +91,20 @@ namespace osu.Game.Screens.Play
|
|||||||
ComboCounter = CreateComboCounter(),
|
ComboCounter = CreateComboCounter(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
HealthDisplay = CreateHealthDisplay(),
|
|
||||||
Progress = CreateProgress(),
|
Progress = CreateProgress(),
|
||||||
ModDisplay = CreateModsContainer(),
|
ModDisplay = CreateModsContainer(),
|
||||||
HitErrorDisplay = CreateHitErrorDisplayOverlay(),
|
HitErrorDisplay = CreateHitErrorDisplayOverlay(),
|
||||||
|
PlayerSettingsOverlay = CreatePlayerSettingsOverlay(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PlayerSettingsOverlay = CreatePlayerSettingsOverlay(),
|
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.BottomRight,
|
Anchor = Anchor.BottomRight,
|
||||||
Origin = Anchor.BottomRight,
|
Origin = Anchor.BottomRight,
|
||||||
Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y),
|
Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y),
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
|
LayoutDuration = fade_duration / 2,
|
||||||
|
LayoutEasing = fade_easing,
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -108,34 +118,24 @@ namespace osu.Game.Screens.Play
|
|||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(OsuConfigManager config, NotificationOverlay notificationOverlay)
|
private void load(OsuConfigManager config, NotificationOverlay notificationOverlay)
|
||||||
{
|
{
|
||||||
BindProcessor(scoreProcessor);
|
if (scoreProcessor != null)
|
||||||
BindDrawableRuleset(drawableRuleset);
|
BindProcessor(scoreProcessor);
|
||||||
|
|
||||||
Progress.Objects = drawableRuleset.Objects;
|
if (drawableRuleset != null)
|
||||||
Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value;
|
{
|
||||||
Progress.RequestSeek = time => RequestSeek(time);
|
BindDrawableRuleset(drawableRuleset);
|
||||||
Progress.ReferenceClock = drawableRuleset.FrameStableClock;
|
|
||||||
|
Progress.Objects = drawableRuleset.Objects;
|
||||||
|
Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value;
|
||||||
|
Progress.RequestSeek = time => RequestSeek(time);
|
||||||
|
Progress.ReferenceClock = drawableRuleset.FrameStableClock;
|
||||||
|
}
|
||||||
|
|
||||||
ModDisplay.Current.Value = mods;
|
ModDisplay.Current.Value = mods;
|
||||||
|
|
||||||
showHud = config.GetBindable<bool>(OsuSetting.ShowInterface);
|
configShowHud = config.GetBindable<bool>(OsuSetting.ShowInterface);
|
||||||
showHud.BindValueChanged(visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration, easing), true);
|
|
||||||
|
|
||||||
ShowHealthbar.BindValueChanged(healthBar =>
|
if (!configShowHud.Value && !hasShownNotificationOnce)
|
||||||
{
|
|
||||||
if (healthBar.NewValue)
|
|
||||||
{
|
|
||||||
HealthDisplay.FadeIn(duration, easing);
|
|
||||||
topScoreContainer.MoveToY(30, duration, easing);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HealthDisplay.FadeOut(duration, easing);
|
|
||||||
topScoreContainer.MoveToY(0, duration, easing);
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
if (!showHud.Value && !hasShownNotificationOnce)
|
|
||||||
{
|
{
|
||||||
hasShownNotificationOnce = true;
|
hasShownNotificationOnce = true;
|
||||||
|
|
||||||
@ -144,12 +144,39 @@ namespace osu.Game.Screens.Play
|
|||||||
Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab."
|
Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start all elements hidden
|
||||||
|
hideTargets.ForEach(d => d.Hide());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Hide() => throw new InvalidOperationException($"{nameof(HUDOverlay)} should not be hidden as it will remove the ability of a user to quit. Use {nameof(ShowHud)} instead.");
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
|
ShowHud.BindValueChanged(visible => hideTargets.ForEach(d => d.FadeTo(visible.NewValue ? 1 : 0, fade_duration, fade_easing)));
|
||||||
|
|
||||||
|
ShowHealthbar.BindValueChanged(healthBar =>
|
||||||
|
{
|
||||||
|
if (healthBar.NewValue)
|
||||||
|
{
|
||||||
|
HealthDisplay.FadeIn(fade_duration, fade_easing);
|
||||||
|
topScoreContainer.MoveToY(30, fade_duration, fade_easing);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HealthDisplay.FadeOut(fade_duration, fade_easing);
|
||||||
|
topScoreContainer.MoveToY(0, fade_duration, fade_easing);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
configShowHud.BindValueChanged(visible =>
|
||||||
|
{
|
||||||
|
if (!ShowHud.Disabled)
|
||||||
|
ShowHud.Value = visible.NewValue;
|
||||||
|
}, true);
|
||||||
|
|
||||||
replayLoaded.BindValueChanged(replayLoadedValueChanged, true);
|
replayLoaded.BindValueChanged(replayLoadedValueChanged, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +216,7 @@ namespace osu.Game.Screens.Play
|
|||||||
switch (e.Key)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
case Key.Tab:
|
case Key.Tab:
|
||||||
showHud.Value = !showHud.Value;
|
configShowHud.Value = !configShowHud.Value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +284,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Margin = new MarginPadding { Top = 20, Right = 10 },
|
Margin = new MarginPadding { Top = 20, Right = 10 },
|
||||||
};
|
};
|
||||||
|
|
||||||
protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.FirstAvailableHitWindows);
|
protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset?.FirstAvailableHitWindows);
|
||||||
|
|
||||||
protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay();
|
protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user