mirror of
https://github.com/ppy/osu.git
synced 2025-01-31 08:33:21 +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
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -11,19 +12,20 @@ using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Footer;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
/// <summary>
|
||||
/// A sheared overlay which provides a header and footer and basic animations.
|
||||
/// Exposes <see cref="TopLevelContent"/>, <see cref="MainAreaContent"/> and <see cref="Footer"/> as valid targets for content.
|
||||
/// A sheared overlay which provides a header and basic animations.
|
||||
/// Exposes <see cref="TopLevelContent"/> and <see cref="MainAreaContent"/> as valid targets for content.
|
||||
/// </summary>
|
||||
public abstract partial class ShearedOverlayContainer : OsuFocusedOverlayContainer
|
||||
{
|
||||
protected const float PADDING = 14;
|
||||
public const float PADDING = 14;
|
||||
|
||||
[Cached]
|
||||
protected readonly OverlayColourProvider ColourProvider;
|
||||
public readonly OverlayColourProvider ColourProvider;
|
||||
|
||||
/// <summary>
|
||||
/// The overlay's header.
|
||||
@ -35,6 +37,13 @@ namespace osu.Game.Overlays.Mods
|
||||
/// </summary>
|
||||
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>
|
||||
/// A container containing all content, including the header and footer.
|
||||
/// May be used for overlay-wide animations.
|
||||
@ -65,7 +74,7 @@ namespace osu.Game.Overlays.Mods
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
const float footer_height = 50;
|
||||
const float footer_height = ScreenFooter.HEIGHT;
|
||||
|
||||
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)
|
||||
{
|
||||
if (State.Value == Visibility.Visible)
|
||||
@ -131,7 +145,13 @@ namespace osu.Game.Overlays.Mods
|
||||
this.FadeIn(fade_in_duration, Easing.OutQuint);
|
||||
|
||||
Header.MoveToY(0, fade_in_duration, Easing.OutQuint);
|
||||
Footer.MoveToY(0, fade_in_duration, Easing.OutQuint);
|
||||
|
||||
if (UseNewFooter && footer != null)
|
||||
{
|
||||
footer.SetOverlayContent(this);
|
||||
}
|
||||
else
|
||||
Footer.MoveToY(0, fade_in_duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
@ -142,7 +162,13 @@ namespace osu.Game.Overlays.Mods
|
||||
this.FadeOut(fade_out_duration, Easing.OutQuint);
|
||||
|
||||
Header.MoveToY(-Header.DrawHeight, fade_out_duration, Easing.OutQuint);
|
||||
Footer.MoveToY(Footer.DrawHeight, fade_out_duration, Easing.OutQuint);
|
||||
|
||||
if (UseNewFooter && footer != null)
|
||||
{
|
||||
footer.ClearOverlayContent();
|
||||
}
|
||||
else
|
||||
Footer.MoveToY(Footer.DrawHeight, fade_out_duration, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,8 +115,11 @@ namespace osu.Game.Screens.Footer
|
||||
|
||||
public void SetButtons(IReadOnlyList<ScreenFooterButton> buttons)
|
||||
{
|
||||
temporarilyHiddenButtons.Clear();
|
||||
overlays.Clear();
|
||||
|
||||
ClearOverlayContent();
|
||||
|
||||
var oldButtons = buttonsFlow.ToArray();
|
||||
|
||||
for (int i = 0; i < oldButtons.Length; i++)
|
||||
@ -127,9 +130,9 @@ namespace osu.Game.Screens.Footer
|
||||
removedButtonsContainer.Add(oldButton);
|
||||
|
||||
if (buttons.Count > 0)
|
||||
makeButtonDisappearToRightAndExpire(oldButton, i, oldButtons.Length);
|
||||
makeButtonDisappearToRight(oldButton, i, oldButtons.Length, true);
|
||||
else
|
||||
makeButtonDisappearToBottomAndExpire(oldButton, i, oldButtons.Length);
|
||||
makeButtonDisappearToBottom(oldButton, i, oldButtons.Length, true);
|
||||
}
|
||||
|
||||
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)
|
||||
=> button.AppearFromLeft(startDelay + (count - index) * delay_per_button);
|
||||
|
||||
private void makeButtonAppearFromBottom(ScreenFooterButton button, int index)
|
||||
=> button.AppearFromBottom(index * delay_per_button);
|
||||
|
||||
private void makeButtonDisappearToRightAndExpire(ScreenFooterButton button, int index, int count)
|
||||
=> button.DisappearToRightAndExpire((count - index) * delay_per_button);
|
||||
private void makeButtonDisappearToRight(ScreenFooterButton button, int index, int count, bool expire)
|
||||
=> button.DisappearToRight((count - index) * delay_per_button, expire);
|
||||
|
||||
private void makeButtonDisappearToBottomAndExpire(ScreenFooterButton button, int index, int count)
|
||||
=> button.DisappearToBottomAndExpire((count - index) * delay_per_button);
|
||||
private void makeButtonDisappearToBottom(ScreenFooterButton button, int index, int count, bool expire)
|
||||
=> button.DisappearToBottom((count - index) * delay_per_button, expire);
|
||||
|
||||
private void showOverlay(OverlayContainer overlay)
|
||||
{
|
||||
|
@ -243,22 +243,24 @@ namespace osu.Game.Screens.Footer
|
||||
.FadeIn(240, Easing.OutCubic);
|
||||
}
|
||||
|
||||
public void DisappearToRightAndExpire(double delay)
|
||||
public void DisappearToRight(double delay, bool expire)
|
||||
{
|
||||
Content.Delay(delay)
|
||||
.FadeOut(240, Easing.InOutCubic)
|
||||
.MoveToX(300f, 360, Easing.InOutCubic);
|
||||
|
||||
this.Delay(Content.LatestTransformEndTime - Time.Current).Expire();
|
||||
if (expire)
|
||||
this.Delay(Content.LatestTransformEndTime - Time.Current).Expire();
|
||||
}
|
||||
|
||||
public void DisappearToBottomAndExpire(double delay)
|
||||
public void DisappearToBottom(double delay, bool expire)
|
||||
{
|
||||
Content.Delay(delay)
|
||||
.FadeOut(240, Easing.InOutCubic)
|
||||
.MoveToY(100f, 240, Easing.InOutCubic);
|
||||
|
||||
this.Delay(Content.LatestTransformEndTime - Time.Current).Expire();
|
||||
if (expire)
|
||||
this.Delay(Content.LatestTransformEndTime - Time.Current).Expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user