mirror of
https://github.com/ppy/osu.git
synced 2026-05-17 01:43:01 +08:00
126 lines
3.7 KiB
C#
126 lines
3.7 KiB
C#
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
using System;
|
|
using osu.Framework.Allocation;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osuTK;
|
|
|
|
namespace osu.Game.Overlays
|
|
{
|
|
public partial class MarqueeContainer : CompositeDrawable
|
|
{
|
|
/// <summary>
|
|
/// Whether the marquee should be allowed to scroll the content if it overflows.
|
|
/// Note that upon changing the value of this, any existing scrolls will be terminated instantly.
|
|
/// </summary>
|
|
public bool AllowScrolling
|
|
{
|
|
get => allowScrolling;
|
|
set
|
|
{
|
|
allowScrolling = value;
|
|
ScheduleAfterChildren(updateScrolling);
|
|
}
|
|
}
|
|
|
|
private bool allowScrolling = true;
|
|
|
|
/// <summary>
|
|
/// Time in milliseconds before scrolling begins.
|
|
/// </summary>
|
|
public double InitialMoveDelay { get; set; } = 1000;
|
|
|
|
/// <summary>
|
|
/// The <see cref="Anchor"/> to anchor the content to if it does not overflow.
|
|
/// </summary>
|
|
public Anchor NonOverflowingContentAnchor { get; init; } = Anchor.TopLeft;
|
|
|
|
public Func<Drawable>? CreateContent
|
|
{
|
|
set
|
|
{
|
|
createContent = value;
|
|
if (IsLoaded)
|
|
updateContent();
|
|
}
|
|
}
|
|
|
|
private Func<Drawable>? createContent;
|
|
|
|
private const float pixels_per_second = 50;
|
|
private const float padding = 15;
|
|
|
|
private Drawable mainContent = null!;
|
|
private Drawable fillerContent = null!;
|
|
private FillFlowContainer flow = null!;
|
|
|
|
public MarqueeContainer()
|
|
{
|
|
RelativeSizeAxes = Axes.X;
|
|
AutoSizeAxes = Axes.Y;
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load()
|
|
{
|
|
InternalChild = flow = new FillFlowContainer
|
|
{
|
|
AutoSizeAxes = Axes.Both,
|
|
Direction = FillDirection.Horizontal,
|
|
Anchor = NonOverflowingContentAnchor,
|
|
Origin = NonOverflowingContentAnchor,
|
|
Spacing = new Vector2(padding),
|
|
Padding = new MarginPadding { Horizontal = padding },
|
|
};
|
|
}
|
|
|
|
protected override void LoadComplete()
|
|
{
|
|
base.LoadComplete();
|
|
|
|
updateContent();
|
|
}
|
|
|
|
private void updateContent()
|
|
{
|
|
flow.Clear();
|
|
|
|
if (createContent == null)
|
|
return;
|
|
|
|
flow.Add(mainContent = createContent());
|
|
flow.Add(fillerContent = createContent().With(d => d.Alpha = 0));
|
|
ScheduleAfterChildren(updateScrolling);
|
|
}
|
|
|
|
private void updateScrolling()
|
|
{
|
|
float overflowWidth = mainContent.DrawWidth + padding - DrawWidth;
|
|
|
|
if (overflowWidth > 0 && AllowScrolling)
|
|
{
|
|
fillerContent.Alpha = 1;
|
|
flow.Anchor = Anchor.TopLeft;
|
|
flow.Origin = Anchor.TopLeft;
|
|
|
|
float targetX = mainContent.DrawWidth + padding;
|
|
|
|
flow.MoveToX(0)
|
|
.Delay(InitialMoveDelay)
|
|
.MoveToX(-targetX, targetX * 1000 / pixels_per_second)
|
|
.Loop();
|
|
}
|
|
else
|
|
{
|
|
fillerContent.Alpha = 0;
|
|
flow.ClearTransforms();
|
|
flow.MoveToX(0, 300, Easing.OutQuint);
|
|
flow.Anchor = NonOverflowingContentAnchor;
|
|
flow.Origin = NonOverflowingContentAnchor;
|
|
}
|
|
}
|
|
}
|
|
}
|