diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs
index 674eaa2ff8..0a632793cc 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs
@@ -181,12 +181,6 @@ namespace osu.Game.Tests.Visual.SongSelect
#endregion
- protected override void Update()
- {
- base.Update();
- Stack.Padding = new MarginPadding { Bottom = screenScreenFooter.DrawHeight - screenScreenFooter.Y };
- }
-
private void updateFooter(IScreen? _, IScreen? newScreen)
{
if (newScreen is IOsuScreen osuScreen && osuScreen.ShowFooter)
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index cf32daab00..3862fea0e2 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -51,6 +51,7 @@ using osu.Game.Online.Chat;
using osu.Game.Online.Rooms;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapListing;
+using osu.Game.Overlays.Mods;
using osu.Game.Overlays.Music;
using osu.Game.Overlays.Notifications;
using osu.Game.Overlays.SkinEditor;
@@ -132,8 +133,12 @@ namespace osu.Game
private Container topMostOverlayContent;
+ private Container footerBasedOverlayContent;
+
protected ScalingContainer ScreenContainer { get; private set; }
+ private Container logoContainer;
+
protected Container ScreenOffsetContainer { get; private set; }
private Container overlayOffsetContainer;
@@ -156,8 +161,6 @@ namespace osu.Game
private float toolbarOffset => (Toolbar?.Position.Y ?? 0) + (Toolbar?.DrawHeight ?? 0);
- private float screenFooterOffset => (ScreenFooter?.DrawHeight ?? 0) - (ScreenFooter?.Position.Y ?? 0);
-
private IdleTracker idleTracker;
///
@@ -242,7 +245,11 @@ namespace osu.Game
throw new ArgumentException($@"{overlayContainer} has already been registered via {nameof(IOverlayManager.RegisterBlockingOverlay)} once.");
externalOverlays.Add(overlayContainer);
- overlayContent.Add(overlayContainer);
+
+ if (overlayContainer is ShearedOverlayContainer)
+ footerBasedOverlayContent.Add(overlayContainer);
+ else
+ overlayContent.Add(overlayContainer);
if (overlayContainer is OsuFocusedOverlayContainer focusedOverlayContainer)
focusedOverlays.Add(focusedOverlayContainer);
@@ -290,6 +297,8 @@ namespace osu.Game
if (hideToolbar) Toolbar.Hide();
}
+ public void ChangeLogoDepth(bool inFrontOfFooter) => ScreenContainer.ChangeChildDepth(logoContainer, inFrontOfFooter ? float.MinValue : 0);
+
protected override UserInputManager CreateUserInputManager()
{
var userInputManager = base.CreateUserInputManager();
@@ -934,7 +943,6 @@ namespace osu.Game
return string.Join(" / ", combinations);
};
- Container logoContainer;
ScreenFooter.BackReceptor backReceptor;
dependencies.CacheAs(idleTracker = new GameIdleTracker(6000));
@@ -976,8 +984,15 @@ namespace osu.Game
Origin = Anchor.BottomLeft,
Action = () => ScreenFooter.OnBack?.Invoke(),
},
+ logoContainer = new Container { RelativeSizeAxes = Axes.Both },
+ footerBasedOverlayContent = new Container
+ {
+ Depth = -1,
+ RelativeSizeAxes = Axes.Both,
+ },
new PopoverContainer
{
+ Depth = -1,
RelativeSizeAxes = Axes.Both,
Child = ScreenFooter = new ScreenFooter(backReceptor)
{
@@ -991,7 +1006,6 @@ namespace osu.Game
}
},
},
- logoContainer = new Container { RelativeSizeAxes = Axes.Both },
}
},
}
@@ -1025,7 +1039,7 @@ namespace osu.Game
if (!IsDeployedBuild)
{
- dependencies.Cache(versionManager = new VersionManager { Depth = int.MinValue });
+ dependencies.Cache(versionManager = new VersionManager());
loadComponentSingleFile(versionManager, ScreenContainer.Add);
}
@@ -1072,7 +1086,7 @@ namespace osu.Game
loadComponentSingleFile(CreateUpdateManager(), Add, true);
// overlay elements
- loadComponentSingleFile(FirstRunOverlay = new FirstRunSetupOverlay(), overlayContent.Add, true);
+ loadComponentSingleFile(FirstRunOverlay = new FirstRunSetupOverlay(), footerBasedOverlayContent.Add, true);
loadComponentSingleFile(new ManageCollectionsDialog(), overlayContent.Add, true);
loadComponentSingleFile(beatmapListing = new BeatmapListingOverlay(), overlayContent.Add, true);
loadComponentSingleFile(dashboard = new DashboardOverlay(), overlayContent.Add, true);
@@ -1137,7 +1151,7 @@ namespace osu.Game
}
// ensure only one of these overlays are open at once.
- var singleDisplayOverlays = new OverlayContainer[] { FirstRunOverlay, chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay, wikiOverlay };
+ var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay, wikiOverlay };
foreach (var overlay in singleDisplayOverlays)
{
@@ -1485,7 +1499,6 @@ namespace osu.Game
ScreenOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset };
overlayOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset };
- ScreenStack.Padding = new MarginPadding { Bottom = screenFooterOffset };
float horizontalOffset = 0f;
diff --git a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs
index c9c3c62404..b5435e7e58 100644
--- a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs
+++ b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs
@@ -1,10 +1,8 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-#nullable disable
-
-using JetBrains.Annotations;
using osu.Framework.Allocation;
+using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@@ -30,16 +28,15 @@ namespace osu.Game.Overlays.Mods
///
/// The overlay's header.
///
- protected ShearedOverlayHeader Header { get; private set; }
+ protected ShearedOverlayHeader Header { get; private set; } = null!;
///
/// The overlay's footer.
///
protected Container Footer { get; private set; }
- [Resolved(canBeNull: true)]
- [CanBeNull]
- private ScreenFooter footer { get; set; }
+ [Resolved]
+ private ScreenFooter? footer { get; set; }
// todo: very temporary property that will be removed once ModSelectOverlay and FirstRunSetupOverlay are updated to use new footer.
public virtual bool UseNewFooter => false;
@@ -48,12 +45,12 @@ namespace osu.Game.Overlays.Mods
/// A container containing all content, including the header and footer.
/// May be used for overlay-wide animations.
///
- protected Container TopLevelContent { get; private set; }
+ protected Container TopLevelContent { get; private set; } = null!;
///
/// A container for content that is to be displayed between the header and footer.
///
- protected Container MainAreaContent { get; private set; }
+ protected Container MainAreaContent { get; private set; } = null!;
///
/// A container for content that is to be displayed inside the footer.
@@ -64,6 +61,10 @@ namespace osu.Game.Overlays.Mods
protected override bool BlockNonPositionalInput => true;
+ // ShearedOverlayContainers are placed at a layer within the screen container as they rely on ScreenFooter which must be placed there.
+ // Therefore, dimming must be managed locally, since DimMainContent dims the entire screen layer.
+ protected sealed override bool DimMainContent => false;
+
protected ShearedOverlayContainer(OverlayColourScheme colourScheme)
{
RelativeSizeAxes = Axes.Both;
@@ -81,6 +82,11 @@ namespace osu.Game.Overlays.Mods
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = ColourProvider.Background6.Opacity(0.75f),
+ },
Header = new ShearedOverlayHeader
{
Anchor = Anchor.TopCentre,
diff --git a/osu.Game/Screens/Footer/ScreenFooter.cs b/osu.Game/Screens/Footer/ScreenFooter.cs
index cef891f8c0..dcf64e9291 100644
--- a/osu.Game/Screens/Footer/ScreenFooter.cs
+++ b/osu.Game/Screens/Footer/ScreenFooter.cs
@@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
+using osu.Framework.Threading;
using osu.Game.Graphics.Containers;
using osu.Game.Input.Bindings;
using osu.Game.Overlays;
@@ -24,6 +25,7 @@ namespace osu.Game.Screens.Footer
{
private const int padding = 60;
private const float delay_per_button = 30;
+ private const double transition_duration = 400;
public const int HEIGHT = 50;
@@ -37,6 +39,9 @@ namespace osu.Game.Screens.Footer
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
+ [Resolved]
+ private OsuGame? game { get; set; }
+
public ScreenBackButton BackButton { get; private set; } = null!;
public Action? OnBack;
@@ -101,19 +106,35 @@ namespace osu.Game.Screens.Footer
};
}
- public void StartTrackingLogo(OsuLogo logo, float duration = 0, Easing easing = Easing.None) => logoTrackingContainer.StartTracking(logo, duration, easing);
- public void StopTrackingLogo() => logoTrackingContainer.StopTracking();
+ private ScheduledDelegate? changeLogoDepthDelegate;
+
+ public void StartTrackingLogo(OsuLogo logo, float duration = 0, Easing easing = Easing.None)
+ {
+ changeLogoDepthDelegate?.Cancel();
+ changeLogoDepthDelegate = null;
+
+ logoTrackingContainer.StartTracking(logo, duration, easing);
+ game?.ChangeLogoDepth(inFrontOfFooter: true);
+ }
+
+ public void StopTrackingLogo()
+ {
+ logoTrackingContainer.StopTracking();
+
+ if (game != null)
+ changeLogoDepthDelegate = Scheduler.AddDelayed(() => game.ChangeLogoDepth(inFrontOfFooter: false), transition_duration);
+ }
protected override void PopIn()
{
- this.MoveToY(0, 400, Easing.OutQuint)
- .FadeIn(400, Easing.OutQuint);
+ this.MoveToY(0, transition_duration, Easing.OutQuint)
+ .FadeIn(transition_duration, Easing.OutQuint);
}
protected override void PopOut()
{
- this.MoveToY(HEIGHT, 400, Easing.OutQuint)
- .FadeOut(400, Easing.OutQuint);
+ this.MoveToY(HEIGHT, transition_duration, Easing.OutQuint)
+ .FadeOut(transition_duration, Easing.OutQuint);
}
public void SetButtons(IReadOnlyList buttons)
diff --git a/osu.Game/Screens/SelectV2/SongSelectV2.cs b/osu.Game/Screens/SelectV2/SongSelectV2.cs
index 10ed7783c4..a8730ad808 100644
--- a/osu.Game/Screens/SelectV2/SongSelectV2.cs
+++ b/osu.Game/Screens/SelectV2/SongSelectV2.cs
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Cursor;
using osu.Framework.Screens;
using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
@@ -23,6 +22,8 @@ namespace osu.Game.Screens.SelectV2
///
public partial class SongSelectV2 : OsuScreen
{
+ private const float logo_scale = 0.4f;
+
private readonly ModSelectOverlay modSelectOverlay = new SoloModSelectOverlay();
[Cached]
@@ -30,15 +31,14 @@ namespace osu.Game.Screens.SelectV2
public override bool ShowFooter => true;
+ [Resolved]
+ private OsuLogo? logo { get; set; }
+
[BackgroundDependencyLoader]
private void load()
{
AddRangeInternal(new Drawable[]
{
- new PopoverContainer
- {
- RelativeSizeAxes = Axes.Both,
- },
modSelectOverlay,
});
}
@@ -50,6 +50,17 @@ namespace osu.Game.Screens.SelectV2
new ScreenFooterButtonOptions(),
};
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ modSelectOverlay.State.BindValueChanged(v =>
+ {
+ logo?.ScaleTo(v.NewValue == Visibility.Visible ? 0f : logo_scale, 400, Easing.OutQuint)
+ .FadeTo(v.NewValue == Visibility.Visible ? 0f : 1f, 200, Easing.OutQuint);
+ }, true);
+ }
+
public override void OnEntering(ScreenTransitionEvent e)
{
this.FadeIn();
@@ -74,17 +85,6 @@ namespace osu.Game.Screens.SelectV2
return base.OnExiting(e);
}
- public override bool OnBackButton()
- {
- if (modSelectOverlay.State.Value == Visibility.Visible)
- {
- modSelectOverlay.Hide();
- return true;
- }
-
- return false;
- }
-
protected override void LogoArriving(OsuLogo logo, bool resuming)
{
base.LogoArriving(logo, resuming);
@@ -99,7 +99,7 @@ namespace osu.Game.Screens.SelectV2
}
logo.FadeIn(240, Easing.OutQuint);
- logo.ScaleTo(0.4f, 240, Easing.OutQuint);
+ logo.ScaleTo(logo_scale, 240, Easing.OutQuint);
logo.Action = () =>
{
@@ -122,14 +122,9 @@ namespace osu.Game.Screens.SelectV2
logo.FadeOut(120, Easing.Out);
}
- private partial class SoloModSelectOverlay : ModSelectOverlay
+ private partial class SoloModSelectOverlay : UserModSelectOverlay
{
protected override bool ShowPresets => true;
-
- public SoloModSelectOverlay()
- : base(OverlayColourScheme.Aquamarine)
- {
- }
}
private partial class PlayerLoaderV2 : PlayerLoader