1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 07:22:54 +08:00

Refactor ScreenFooter to prepare for global usage and add transitions

This commit is contained in:
Salman Ahmed 2024-05-16 06:24:58 +03:00
parent a2794922d5
commit d0e8632fbf

View File

@ -2,54 +2,33 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Screens.Footer
{
public partial class ScreenFooter : InputBlockingContainer
public partial class ScreenFooter : OverlayContainer
{
private const int height = 60;
private const int padding = 60;
private const float delay_per_button = 30;
public const int HEIGHT = 60;
private readonly List<OverlayContainer> overlays = new List<OverlayContainer>();
/// <param name="button">The button to be added.</param>
/// <param name="overlay">The <see cref="OverlayContainer"/> to be toggled by this button.</param>
public void AddButton(ScreenFooterButton button, OverlayContainer? overlay = null)
{
if (overlay != null)
{
overlays.Add(overlay);
button.Action = () => showOverlay(overlay);
button.OverlayState.BindTo(overlay.State);
}
buttons.Add(button);
}
private void showOverlay(OverlayContainer overlay)
{
foreach (var o in overlays)
{
if (o == overlay)
o.ToggleVisibility();
else
o.Hide();
}
}
private FillFlowContainer<ScreenFooterButton> buttons = null!;
private FillFlowContainer<ScreenFooterButton> buttonsFlow = null!;
private Container<ScreenFooterButton> removedButtonsContainer = null!;
public ScreenFooter()
{
RelativeSizeAxes = Axes.X;
Height = height;
Height = HEIGHT;
Anchor = Anchor.BottomLeft;
Origin = Anchor.BottomLeft;
}
@ -64,9 +43,10 @@ namespace osu.Game.Screens.Footer
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background5
},
buttons = new FillFlowContainer<ScreenFooterButton>
buttonsFlow = new FillFlowContainer<ScreenFooterButton>
{
Position = new Vector2(ScreenBackButton.BUTTON_WIDTH + padding, 10),
Margin = new MarginPadding { Left = 12f + ScreenBackButton.BUTTON_WIDTH + padding },
Y = 10f,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Direction = FillDirection.Horizontal,
@ -80,7 +60,125 @@ namespace osu.Game.Screens.Footer
Origin = Anchor.BottomLeft,
Action = () => { },
},
removedButtonsContainer = new Container<ScreenFooterButton>
{
Margin = new MarginPadding { Left = 12f + ScreenBackButton.BUTTON_WIDTH + padding },
Y = 10f,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
AutoSizeAxes = Axes.Both,
},
};
}
protected override void PopIn()
{
this.MoveToY(0, 400, Easing.OutQuint)
.FadeIn(400, Easing.OutQuint);
}
protected override void PopOut()
{
this.MoveToY(HEIGHT, 400, Easing.OutQuint)
.FadeOut(400, Easing.OutQuint);
}
public void SetButtons(IReadOnlyList<ScreenFooterButton> buttons)
{
overlays.Clear();
var oldButtons = buttonsFlow.ToArray();
for (int i = 0; i < oldButtons.Length; i++)
{
var oldButton = oldButtons[i];
buttonsFlow.Remove(oldButton, false);
removedButtonsContainer.Add(oldButton);
if (buttons.Count > 0)
fadeButtonToLeft(oldButton, i, oldButtons.Length);
else
fadeButtonToBottom(oldButton, i, oldButtons.Length);
Scheduler.AddDelayed(() => oldButton.Expire(), oldButton.TopLevelContent.LatestTransformEndTime - Time.Current);
}
for (int i = 0; i < buttons.Count; i++)
{
var newButton = buttons[i];
if (newButton.Overlay != null)
{
newButton.Action = () => showOverlay(newButton.Overlay);
overlays.Add(newButton.Overlay);
}
Debug.Assert(!newButton.IsLoaded);
buttonsFlow.Add(newButton);
int index = i;
// ensure transforms are added after LoadComplete to not be aborted by the FinishTransforms call.
newButton.OnLoadComplete += _ =>
{
if (oldButtons.Length > 0)
fadeButtonFromRight(newButton, index, buttons.Count, 240);
else
fadeButtonFromBottom(newButton, index);
};
}
}
private void fadeButtonFromRight(ScreenFooterButton button, int index, int count, float startDelay)
{
button.TopLevelContent
.MoveToX(-300f)
.FadeOut();
button.TopLevelContent
.Delay(startDelay + (count - index) * delay_per_button)
.MoveToX(0f, 240, Easing.OutCubic)
.FadeIn(240, Easing.OutCubic);
}
private void fadeButtonFromBottom(ScreenFooterButton button, int index)
{
button.TopLevelContent
.MoveToY(100f)
.FadeOut();
button.TopLevelContent
.Delay(index * delay_per_button)
.MoveToY(0f, 240, Easing.OutCubic)
.FadeIn(240, Easing.OutCubic);
}
private void fadeButtonToLeft(ScreenFooterButton button, int index, int count)
{
button.TopLevelContent
.Delay((count - index) * delay_per_button)
.FadeOut(240, Easing.InOutCubic)
.MoveToX(300f, 360, Easing.InOutCubic);
}
private void fadeButtonToBottom(ScreenFooterButton button, int index, int count)
{
button.TopLevelContent
.Delay((count - index) * delay_per_button)
.FadeOut(240, Easing.InOutCubic)
.MoveToY(100f, 240, Easing.InOutCubic);
}
private void showOverlay(OverlayContainer overlay)
{
foreach (var o in overlays)
{
if (o == overlay)
o.ToggleVisibility();
else
o.Hide();
}
}
}
}