diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index bc5d02258f..5625028707 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -13,13 +13,11 @@ using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield, IApplicableToDrawableRuleset + public class OsuModRelax : ModRelax, IUpdatableByPlayfield, IApplicableToDrawableRuleset { public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); - public bool AllowFail => false; - public void Update(Playfield playfield) { bool requiresHold = false; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 795f0b43f7..1da7c7ec1d 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -77,6 +77,7 @@ namespace osu.Game.Configuration Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); Set(OsuSetting.ShowInterface, true); + Set(OsuSetting.ShowHealthDisplayWhenCantFail, true); Set(OsuSetting.KeyOverlay, false); Set(OsuSetting.FloatingComments, false); @@ -131,6 +132,7 @@ namespace osu.Game.Configuration KeyOverlay, FloatingComments, ShowInterface, + ShowHealthDisplayWhenCantFail, MouseDisableButtons, MouseDisableWheel, AudioOffset, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 997d1354b3..9142492610 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -35,6 +35,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay Bindable = config.GetBindable(OsuSetting.ShowInterface) }, new SettingsCheckbox + { + LabelText = "Show health display even when you can't fail", + Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), + }, + new SettingsCheckbox { LabelText = "Always show key overlay", Bindable = config.GetBindable(OsuSetting.KeyOverlay) diff --git a/osu.Game/Rulesets/Mods/IApplicableToHUD.cs b/osu.Game/Rulesets/Mods/IApplicableToHUD.cs new file mode 100644 index 0000000000..4fb535a0b3 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableToHUD.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Screens.Play; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// An interface for mods that apply changes to the . + /// + public interface IApplicableToHUD : IApplicableMod + { + /// + /// Provide a . Called once on initialisation of a play instance. + /// + void ApplyToHUD(HUDOverlay overlay); + } +} diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs new file mode 100644 index 0000000000..26efc3932d --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Screens.Play; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModBlockFail : Mod, IApplicableFailOverride, IApplicableToHUD, IReadFromConfig + { + private Bindable showHealthBar; + + /// + /// We never fail, 'yo. + /// + public bool AllowFail => false; + + public void ReadFromConfig(OsuConfigManager config) + { + showHealthBar = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail); + } + + public void ApplyToHUD(HUDOverlay overlay) + { + overlay.ShowHealthbar.BindTo(showHealthBar); + } + } +} diff --git a/osu.Game/Rulesets/Mods/ModNoFail.cs b/osu.Game/Rulesets/Mods/ModNoFail.cs index 1ee1f92d8c..49ee3354c3 100644 --- a/osu.Game/Rulesets/Mods/ModNoFail.cs +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModNoFail : Mod, IApplicableFailOverride + public abstract class ModNoFail : ModBlockFail { public override string Name => "No Fail"; public override string Acronym => "NF"; @@ -17,10 +17,5 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 0.5; public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModAutoplay) }; - - /// - /// We never fail, 'yo. - /// - public bool AllowFail => false; } } diff --git a/osu.Game/Rulesets/Mods/ModRelax.cs b/osu.Game/Rulesets/Mods/ModRelax.cs index 4feb89186c..7c355577d4 100644 --- a/osu.Game/Rulesets/Mods/ModRelax.cs +++ b/osu.Game/Rulesets/Mods/ModRelax.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModRelax : Mod + public abstract class ModRelax : ModBlockFail { public override string Name => "Relax"; public override string Acronym => "RX"; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 017bf70133..43b9491750 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -23,7 +23,8 @@ namespace osu.Game.Screens.Play { public class HUDOverlay : Container { - private const int duration = 100; + private const int duration = 250; + private const Easing easing = Easing.OutQuint; public readonly KeyCounterDisplay KeyCounter; public readonly RollingCounter ComboCounter; @@ -35,6 +36,8 @@ namespace osu.Game.Screens.Play public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; + public Bindable ShowHealthbar = new Bindable(true); + private readonly ScoreProcessor scoreProcessor; private readonly DrawableRuleset drawableRuleset; private readonly IReadOnlyList mods; @@ -47,6 +50,8 @@ namespace osu.Game.Screens.Play public Action RequestSeek; + private readonly Container topScoreContainer; + public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) { this.scoreProcessor = scoreProcessor; @@ -62,11 +67,10 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Container + topScoreContainer = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Y = 30, AutoSizeAxes = Axes.Both, AutoSizeDuration = 200, AutoSizeEasing = Easing.Out, @@ -113,8 +117,21 @@ namespace osu.Game.Screens.Play ModDisplay.Current.Value = mods; showHud = config.GetBindable(OsuSetting.ShowInterface); - showHud.ValueChanged += visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); - showHud.TriggerChange(); + showHud.BindValueChanged(visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration, easing), true); + + ShowHealthbar.BindValueChanged(healthBar => + { + 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) { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 30a3bc2fc6..0da9c77f25 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -498,6 +498,9 @@ namespace osu.Game.Screens.Play GameplayClockContainer.Restart(); GameplayClockContainer.FadeInFromZero(750, Easing.OutQuint); + + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToHUD(HUDOverlay); } public override void OnSuspending(IScreen next)