diff --git a/osu.Game/Screens/OnlinePlay/FooterButtonFreeModsV2.cs b/osu.Game/Screens/OnlinePlay/FooterButtonFreeModsV2.cs index a2194a5d2f..612eca9474 100644 --- a/osu.Game/Screens/OnlinePlay/FooterButtonFreeModsV2.cs +++ b/osu.Game/Screens/OnlinePlay/FooterButtonFreeModsV2.cs @@ -11,22 +11,22 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Framework.Utils; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Footer; using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.SelectV2; using osuTK; namespace osu.Game.Screens.OnlinePlay { public partial class FooterButtonFreeModsV2 : ScreenFooterButton { - private const float bar_height = 30f; - public readonly Bindable> FreeMods = new Bindable>([]); public readonly Bindable Freestyle = new Bindable(); @@ -44,7 +44,7 @@ namespace osu.Game.Screens.OnlinePlay private Container modsWedge = null!; private ModDisplay modDisplay = null!; private Container modContainer = null!; - private ModCountText overflowModCountDisplay = null!; + private FooterButtonMods.ModCountText overflowModCountDisplay = null!; public FooterButtonFreeModsV2(ModSelectOverlay overlay) : base(overlay) @@ -65,7 +65,7 @@ namespace osu.Game.Screens.OnlinePlay Origin = Anchor.BottomLeft, Shear = OsuGame.SHEAR, CornerRadius = CORNER_RADIUS, - Size = new Vector2(BUTTON_WIDTH, bar_height), + Size = new Vector2(BUTTON_WIDTH, FooterButtonMods.BAR_HEIGHT), Masking = true, EdgeEffect = new EdgeEffectParameters { @@ -90,11 +90,6 @@ namespace osu.Game.Screens.OnlinePlay Masking = true, Children = new Drawable[] { - new Box - { - Colour = colourProvider.Background3, - RelativeSizeAxes = Axes.Both, - }, modDisplay = new ModDisplay(showExtendedInformation: true) { Anchor = Anchor.Centre, @@ -104,10 +99,9 @@ namespace osu.Game.Screens.OnlinePlay Current = { BindTarget = FreeMods }, ExpansionMode = ExpansionMode.AlwaysContracted, }, - overflowModCountDisplay = new ModCountText + overflowModCountDisplay = new FooterButtonMods.ModCountText { Mods = { BindTarget = FreeMods }, - Freestyle = { BindTarget = Freestyle } }, } }, @@ -119,13 +113,17 @@ namespace osu.Game.Screens.OnlinePlay { base.LoadComplete(); - Freestyle.BindValueChanged(f => Enabled.Value = !f.NewValue, true); + Freestyle.BindValueChanged(f => + { + Enabled.Value = !f.NewValue; + overflowModCountDisplay.CustomText = f.NewValue ? ModSelectOverlayStrings.AllMods.ToUpper() : (LocalisableString?)null; + }, true); FreeMods.BindValueChanged(m => { - if (m.NewValue.Count == 0) - modsWedge.FadeOut(200); + if (m.NewValue.Count == 0 && !Freestyle.Value) + modsWedge.FadeOut(300, Easing.OutExpo); else - modsWedge.FadeIn(200); + modsWedge.FadeIn(300, Easing.OutExpo); }, true); } @@ -133,58 +131,21 @@ namespace osu.Game.Screens.OnlinePlay { base.Update(); - if (modDisplay.DrawWidth * modDisplay.Scale.X > modContainer.DrawWidth) + // If there are freemods selected but the display has no width, it's still loading. + // Don't update visibility in this state or we will cause an awkward flash. + if (FreeMods.Value.Count > 0 && Precision.AlmostEquals(modDisplay.DrawWidth, 0)) + return; + + bool showCountText = + // When freestyle is enabled this text shows "ALL MODS" + Freestyle.Value + // Standard flow where mods are overflowing so we show count text. + || modDisplay.DrawWidth * modDisplay.Scale.X > modContainer.DrawWidth; + + if (showCountText) overflowModCountDisplay.Show(); else overflowModCountDisplay.Hide(); } - - private partial class ModCountText : CompositeDrawable - { - public readonly Bindable> Mods = new Bindable>(); - public readonly Bindable Freestyle = new Bindable(); - - private OsuSpriteText text = null!; - - [Resolved] - private OverlayColourProvider colourProvider { get; set; } = null!; - - protected override void LoadComplete() - { - base.LoadComplete(); - - RelativeSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] - { - new Box - { - Colour = colourProvider.Background3, - Alpha = 0.8f, - RelativeSizeAxes = Axes.Both, - }, - text = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.Torus.With(size: 14f, weight: FontWeight.Bold), - Shear = -OsuGame.SHEAR, - } - }; - - Mods.BindValueChanged(_ => updateText()); - Freestyle.BindValueChanged(_ => updateText()); - - updateText(); - } - - private void updateText() - { - if (Freestyle.Value) - text.Text = ModSelectOverlayStrings.AllMods.ToUpper(); - else - text.Text = ModSelectOverlayStrings.Mods(Mods.Value.Count).ToUpper(); - } - } } } diff --git a/osu.Game/Screens/SelectV2/FooterButtonMods.cs b/osu.Game/Screens/SelectV2/FooterButtonMods.cs index 112f53a53e..27e0ac68f9 100644 --- a/osu.Game/Screens/SelectV2/FooterButtonMods.cs +++ b/osu.Game/Screens/SelectV2/FooterButtonMods.cs @@ -36,7 +36,8 @@ namespace osu.Game.Screens.SelectV2 { public Action? RequestDeselectAllMods { get; init; } - private const float bar_height = 30f; + public const float BAR_HEIGHT = 30f; + private const float mod_display_portion = 0.65f; private readonly BindableWithCurrent> current = new BindableWithCurrent>(Array.Empty()); @@ -92,7 +93,7 @@ namespace osu.Game.Screens.SelectV2 Origin = Anchor.BottomLeft, Shear = OsuGame.SHEAR, CornerRadius = CORNER_RADIUS, - Size = new Vector2(BUTTON_WIDTH, bar_height), + Size = new Vector2(BUTTON_WIDTH, BAR_HEIGHT), Masking = true, EdgeEffect = new EdgeEffectParameters { @@ -257,10 +258,26 @@ namespace osu.Game.Screens.SelectV2 overflowModCountDisplay.Hide(); } - private partial class ModCountText : CompositeDrawable, IHasCustomTooltip> + public partial class ModCountText : VisibilityContainer, IHasCustomTooltip> { public readonly Bindable> Mods = new Bindable>(); + private LocalisableString? customText; + + /// + /// When set, this will be shown instead of a mod count. + /// + public LocalisableString? CustomText + { + get => customText; + set + { + customText = value; + if (IsLoaded) + updateText(); + } + } + private OsuSpriteText text = null!; [Resolved] @@ -289,16 +306,27 @@ namespace osu.Game.Screens.SelectV2 } }; - Mods.BindValueChanged(v => text.Text = ModSelectOverlayStrings.Mods(v.NewValue.Count).ToUpper(), true); + Mods.BindValueChanged(_ => updateText(), true); } public ITooltip> GetCustomTooltip() => new ModOverflowTooltip(colourProvider); public IReadOnlyList? TooltipContent => Mods.Value; + protected override void PopIn() => this.FadeIn(300, Easing.OutExpo); + protected override void PopOut() => this.FadeOut(300, Easing.OutExpo); + + private void updateText() + { + if (CustomText != null) + text.Text = CustomText.Value; + else + text.Text = ModSelectOverlayStrings.Mods(Mods.Value.Count).ToUpper(); + } + public partial class ModOverflowTooltip : VisibilityContainer, ITooltip> { - private ModDisplay extendedModDisplay = null!; + private ModFlowDisplay extendedModDisplay = null!; [Cached] private OverlayColourProvider colourProvider; @@ -322,11 +350,12 @@ namespace osu.Game.Screens.SelectV2 RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background5, }, - extendedModDisplay = new ModDisplay + extendedModDisplay = new ModFlowDisplay { + AutoSizeAxes = Axes.Both, + MaximumSize = new Vector2(400, 0), Margin = new MarginPadding { Vertical = 2f, Horizontal = 10f }, Scale = new Vector2(0.6f), - ExpansionMode = ExpansionMode.AlwaysExpanded, }, }; } @@ -356,7 +385,7 @@ namespace osu.Game.Screens.SelectV2 Shear = OsuGame.SHEAR; CornerRadius = CORNER_RADIUS; AutoSizeAxes = Axes.X; - Height = bar_height; + Height = BAR_HEIGHT; Masking = true; BorderColour = Color4.White; BorderThickness = 2f;