mirror of
https://github.com/ppy/osu.git
synced 2025-01-31 13:33:20 +08:00
Use ScreenFooter
for displaying footer buttons from overlays
This commit is contained in:
parent
892659de0f
commit
68b8a4fb2a
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -11,19 +12,20 @@ using osu.Framework.Input.Events;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Screens.Footer;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Mods
|
namespace osu.Game.Overlays.Mods
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sheared overlay which provides a header and footer and basic animations.
|
/// A sheared overlay which provides a header and basic animations.
|
||||||
/// Exposes <see cref="TopLevelContent"/>, <see cref="MainAreaContent"/> and <see cref="Footer"/> as valid targets for content.
|
/// Exposes <see cref="TopLevelContent"/> and <see cref="MainAreaContent"/> as valid targets for content.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract partial class ShearedOverlayContainer : OsuFocusedOverlayContainer
|
public abstract partial class ShearedOverlayContainer : OsuFocusedOverlayContainer
|
||||||
{
|
{
|
||||||
protected const float PADDING = 14;
|
public const float PADDING = 14;
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
protected readonly OverlayColourProvider ColourProvider;
|
public readonly OverlayColourProvider ColourProvider;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The overlay's header.
|
/// The overlay's header.
|
||||||
@ -35,6 +37,13 @@ namespace osu.Game.Overlays.Mods
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected Container Footer { get; private set; }
|
protected Container Footer { get; private set; }
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
[CanBeNull]
|
||||||
|
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;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A container containing all content, including the header and footer.
|
/// A container containing all content, including the header and footer.
|
||||||
/// May be used for overlay-wide animations.
|
/// May be used for overlay-wide animations.
|
||||||
@ -65,7 +74,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
const float footer_height = 50;
|
const float footer_height = ScreenFooter.HEIGHT;
|
||||||
|
|
||||||
Child = TopLevelContent = new Container
|
Child = TopLevelContent = new Container
|
||||||
{
|
{
|
||||||
@ -113,6 +122,11 @@ namespace osu.Game.Overlays.Mods
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates content to be displayed on the game-wide footer.
|
||||||
|
/// </summary>
|
||||||
|
public virtual Drawable CreateFooterContent() => Empty();
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnClick(ClickEvent e)
|
||||||
{
|
{
|
||||||
if (State.Value == Visibility.Visible)
|
if (State.Value == Visibility.Visible)
|
||||||
@ -131,6 +145,12 @@ namespace osu.Game.Overlays.Mods
|
|||||||
this.FadeIn(fade_in_duration, Easing.OutQuint);
|
this.FadeIn(fade_in_duration, Easing.OutQuint);
|
||||||
|
|
||||||
Header.MoveToY(0, fade_in_duration, Easing.OutQuint);
|
Header.MoveToY(0, fade_in_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
if (UseNewFooter && footer != null)
|
||||||
|
{
|
||||||
|
footer.SetOverlayContent(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
Footer.MoveToY(0, fade_in_duration, Easing.OutQuint);
|
Footer.MoveToY(0, fade_in_duration, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +162,12 @@ namespace osu.Game.Overlays.Mods
|
|||||||
this.FadeOut(fade_out_duration, Easing.OutQuint);
|
this.FadeOut(fade_out_duration, Easing.OutQuint);
|
||||||
|
|
||||||
Header.MoveToY(-Header.DrawHeight, fade_out_duration, Easing.OutQuint);
|
Header.MoveToY(-Header.DrawHeight, fade_out_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
if (UseNewFooter && footer != null)
|
||||||
|
{
|
||||||
|
footer.ClearOverlayContent();
|
||||||
|
}
|
||||||
|
else
|
||||||
Footer.MoveToY(Footer.DrawHeight, fade_out_duration, Easing.OutQuint);
|
Footer.MoveToY(Footer.DrawHeight, fade_out_duration, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,8 +115,11 @@ namespace osu.Game.Screens.Footer
|
|||||||
|
|
||||||
public void SetButtons(IReadOnlyList<ScreenFooterButton> buttons)
|
public void SetButtons(IReadOnlyList<ScreenFooterButton> buttons)
|
||||||
{
|
{
|
||||||
|
temporarilyHiddenButtons.Clear();
|
||||||
overlays.Clear();
|
overlays.Clear();
|
||||||
|
|
||||||
|
ClearOverlayContent();
|
||||||
|
|
||||||
var oldButtons = buttonsFlow.ToArray();
|
var oldButtons = buttonsFlow.ToArray();
|
||||||
|
|
||||||
for (int i = 0; i < oldButtons.Length; i++)
|
for (int i = 0; i < oldButtons.Length; i++)
|
||||||
@ -127,9 +130,9 @@ namespace osu.Game.Screens.Footer
|
|||||||
removedButtonsContainer.Add(oldButton);
|
removedButtonsContainer.Add(oldButton);
|
||||||
|
|
||||||
if (buttons.Count > 0)
|
if (buttons.Count > 0)
|
||||||
makeButtonDisappearToRightAndExpire(oldButton, i, oldButtons.Length);
|
makeButtonDisappearToRight(oldButton, i, oldButtons.Length, true);
|
||||||
else
|
else
|
||||||
makeButtonDisappearToBottomAndExpire(oldButton, i, oldButtons.Length);
|
makeButtonDisappearToBottom(oldButton, i, oldButtons.Length, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < buttons.Count; i++)
|
for (int i = 0; i < buttons.Count; i++)
|
||||||
@ -158,17 +161,85 @@ namespace osu.Game.Screens.Footer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ShearedOverlayContainer? activeOverlay;
|
||||||
|
private Container? contentContainer;
|
||||||
|
private readonly List<ScreenFooterButton> temporarilyHiddenButtons = new List<ScreenFooterButton>();
|
||||||
|
|
||||||
|
public void SetOverlayContent(ShearedOverlayContainer overlay)
|
||||||
|
{
|
||||||
|
if (contentContainer != null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(@"Cannot set overlay content while one is already present. " +
|
||||||
|
$@"The previous overlay whose content is {contentContainer.Child.GetType().Name} should be hidden first.");
|
||||||
|
}
|
||||||
|
|
||||||
|
activeOverlay = overlay;
|
||||||
|
|
||||||
|
Debug.Assert(temporarilyHiddenButtons.Count == 0);
|
||||||
|
|
||||||
|
var targetButton = buttonsFlow.SingleOrDefault(b => b.Overlay == overlay);
|
||||||
|
|
||||||
|
temporarilyHiddenButtons.AddRange(targetButton != null
|
||||||
|
? buttonsFlow.SkipWhile(b => b != targetButton).Skip(1)
|
||||||
|
: buttonsFlow);
|
||||||
|
|
||||||
|
for (int i = 0; i < temporarilyHiddenButtons.Count; i++)
|
||||||
|
makeButtonDisappearToBottom(temporarilyHiddenButtons[i], 0, 0, false);
|
||||||
|
|
||||||
|
var fallbackPosition = buttonsFlow.Any()
|
||||||
|
? buttonsFlow.ToSpaceOfOtherDrawable(Vector2.Zero, this)
|
||||||
|
: BackButton.ToSpaceOfOtherDrawable(BackButton.LayoutRectangle.TopRight + new Vector2(5f, 0f), this);
|
||||||
|
|
||||||
|
var targetPosition = targetButton?.ToSpaceOfOtherDrawable(targetButton.LayoutRectangle.TopRight, this) ?? fallbackPosition;
|
||||||
|
|
||||||
|
var content = overlay.CreateFooterContent();
|
||||||
|
|
||||||
|
Add(contentContainer = new Container
|
||||||
|
{
|
||||||
|
Y = -15f,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Left = targetPosition.X },
|
||||||
|
Child = content,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (temporarilyHiddenButtons.Count > 0)
|
||||||
|
this.Delay(60).Schedule(() => content.Show());
|
||||||
|
else
|
||||||
|
content.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearOverlayContent()
|
||||||
|
{
|
||||||
|
if (contentContainer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
contentContainer.Child.Hide();
|
||||||
|
|
||||||
|
double timeUntilRun = contentContainer.Child.LatestTransformEndTime - Time.Current;
|
||||||
|
|
||||||
|
Container expireTarget = contentContainer;
|
||||||
|
contentContainer = null;
|
||||||
|
activeOverlay = null;
|
||||||
|
|
||||||
|
for (int i = 0; i < temporarilyHiddenButtons.Count; i++)
|
||||||
|
makeButtonAppearFromBottom(temporarilyHiddenButtons[i], 0);
|
||||||
|
|
||||||
|
temporarilyHiddenButtons.Clear();
|
||||||
|
|
||||||
|
expireTarget.Delay(timeUntilRun).Expire();
|
||||||
|
}
|
||||||
|
|
||||||
private void makeButtonAppearFromLeft(ScreenFooterButton button, int index, int count, float startDelay)
|
private void makeButtonAppearFromLeft(ScreenFooterButton button, int index, int count, float startDelay)
|
||||||
=> button.AppearFromLeft(startDelay + (count - index) * delay_per_button);
|
=> button.AppearFromLeft(startDelay + (count - index) * delay_per_button);
|
||||||
|
|
||||||
private void makeButtonAppearFromBottom(ScreenFooterButton button, int index)
|
private void makeButtonAppearFromBottom(ScreenFooterButton button, int index)
|
||||||
=> button.AppearFromBottom(index * delay_per_button);
|
=> button.AppearFromBottom(index * delay_per_button);
|
||||||
|
|
||||||
private void makeButtonDisappearToRightAndExpire(ScreenFooterButton button, int index, int count)
|
private void makeButtonDisappearToRight(ScreenFooterButton button, int index, int count, bool expire)
|
||||||
=> button.DisappearToRightAndExpire((count - index) * delay_per_button);
|
=> button.DisappearToRight((count - index) * delay_per_button, expire);
|
||||||
|
|
||||||
private void makeButtonDisappearToBottomAndExpire(ScreenFooterButton button, int index, int count)
|
private void makeButtonDisappearToBottom(ScreenFooterButton button, int index, int count, bool expire)
|
||||||
=> button.DisappearToBottomAndExpire((count - index) * delay_per_button);
|
=> button.DisappearToBottom((count - index) * delay_per_button, expire);
|
||||||
|
|
||||||
private void showOverlay(OverlayContainer overlay)
|
private void showOverlay(OverlayContainer overlay)
|
||||||
{
|
{
|
||||||
|
@ -243,21 +243,23 @@ namespace osu.Game.Screens.Footer
|
|||||||
.FadeIn(240, Easing.OutCubic);
|
.FadeIn(240, Easing.OutCubic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisappearToRightAndExpire(double delay)
|
public void DisappearToRight(double delay, bool expire)
|
||||||
{
|
{
|
||||||
Content.Delay(delay)
|
Content.Delay(delay)
|
||||||
.FadeOut(240, Easing.InOutCubic)
|
.FadeOut(240, Easing.InOutCubic)
|
||||||
.MoveToX(300f, 360, Easing.InOutCubic);
|
.MoveToX(300f, 360, Easing.InOutCubic);
|
||||||
|
|
||||||
|
if (expire)
|
||||||
this.Delay(Content.LatestTransformEndTime - Time.Current).Expire();
|
this.Delay(Content.LatestTransformEndTime - Time.Current).Expire();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisappearToBottomAndExpire(double delay)
|
public void DisappearToBottom(double delay, bool expire)
|
||||||
{
|
{
|
||||||
Content.Delay(delay)
|
Content.Delay(delay)
|
||||||
.FadeOut(240, Easing.InOutCubic)
|
.FadeOut(240, Easing.InOutCubic)
|
||||||
.MoveToY(100f, 240, Easing.InOutCubic);
|
.MoveToY(100f, 240, Easing.InOutCubic);
|
||||||
|
|
||||||
|
if (expire)
|
||||||
this.Delay(Content.LatestTransformEndTime - Time.Current).Expire();
|
this.Delay(Content.LatestTransformEndTime - Time.Current).Expire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user