1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-27 00:13:00 +08:00
osu-lazer/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

366 lines
10 KiB
C#
Raw Normal View History

// 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.
2018-04-13 17:19:50 +08:00
2022-06-17 15:37:17 +08:00
#nullable disable
2017-03-03 19:08:32 +08:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
2017-03-03 19:08:32 +08:00
using System.Linq;
2017-02-27 14:02:38 +08:00
using osu.Framework.Graphics;
2017-03-03 19:08:32 +08:00
using osu.Framework.Graphics.Colour;
2017-02-27 14:02:38 +08:00
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
2017-02-27 14:02:38 +08:00
using osu.Framework.Threading;
2018-11-04 03:58:35 +08:00
using osu.Game.Graphics;
2018-08-26 00:24:19 +08:00
using osu.Game.Tournament.Components;
2019-06-18 13:51:48 +08:00
using osu.Game.Tournament.Models;
2018-11-20 15:51:59 +08:00
using osuTK;
using osuTK.Graphics;
2018-04-13 17:19:50 +08:00
namespace osu.Game.Tournament.Screens.Drawings.Components
2017-02-27 14:02:38 +08:00
{
public partial class ScrollingTeamContainer : Container
{
public event Action OnScrollStarted;
public event Action<TournamentTeam> OnSelected;
2018-04-13 17:19:50 +08:00
private readonly List<TournamentTeam> availableTeams = new List<TournamentTeam>();
2018-04-13 17:19:50 +08:00
private readonly Container tracker;
2018-04-13 17:19:50 +08:00
#pragma warning disable 649
// set via reflection.
2017-03-03 19:08:32 +08:00
private float speed;
#pragma warning restore 649
2018-04-13 17:19:50 +08:00
2017-03-03 19:08:32 +08:00
private int expiredCount;
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
private float offset;
private float timeOffset;
private float leftPos => offset + timeOffset + expiredCount * ScrollingTeam.WIDTH;
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
private double lastTime;
2018-04-13 17:19:50 +08:00
2017-03-03 12:01:57 +08:00
private ScheduledDelegate delayedStateChangeDelegate;
2018-04-13 17:19:50 +08:00
2017-05-02 13:21:22 +08:00
public ScrollingTeamContainer()
{
AutoSizeAxes = Axes.Y;
2018-04-13 17:19:50 +08:00
Children = new Drawable[]
{
2017-03-03 19:08:32 +08:00
tracker = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
2018-04-13 17:19:50 +08:00
AutoSizeAxes = Axes.Both,
2018-11-04 03:58:35 +08:00
Colour = OsuColour.Gray(0.33f),
2018-04-13 17:19:50 +08:00
Masking = true,
CornerRadius = 10f,
Alpha = 0,
2018-04-13 17:19:50 +08:00
Children = new[]
{
2017-03-03 19:08:32 +08:00
new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.BottomCentre,
Size = new Vector2(2, 55),
2018-04-13 17:19:50 +08:00
2017-07-23 13:30:50 +08:00
Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White)
},
2017-03-03 19:08:32 +08:00
new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.TopCentre,
Size = new Vector2(2, 55),
2018-04-13 17:19:50 +08:00
2017-07-23 13:30:50 +08:00
Colour = ColourInfo.GradientVertical(Color4.White, Color4.Transparent)
}
}
}
};
}
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
private ScrollState scrollState;
private void setScrollState(ScrollState newState)
2017-02-27 14:02:38 +08:00
{
if (scrollState == newState)
2019-12-11 13:10:35 +08:00
return;
delayedStateChangeDelegate?.Cancel();
2018-04-13 17:19:50 +08:00
switch (scrollState = newState)
2017-02-27 14:02:38 +08:00
{
2019-12-11 13:10:35 +08:00
case ScrollState.Scrolling:
resetSelected();
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
OnScrollStarted?.Invoke();
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
speedTo(1000f, 200);
tracker.FadeOut(100);
break;
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
case ScrollState.Stopping:
speedTo(0f, 2000);
tracker.FadeIn(200);
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
delayedStateChangeDelegate = Scheduler.AddDelayed(() => setScrollState(ScrollState.Stopped), 2300);
break;
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
case ScrollState.Stopped:
// Find closest to center
if (!Children.Any())
2017-02-27 14:02:38 +08:00
break;
2019-04-01 11:44:46 +08:00
2019-12-11 13:10:35 +08:00
ScrollingTeam closest = null;
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
foreach (var c in Children)
{
if (!(c is ScrollingTeam stc))
continue;
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
if (closest == null)
2017-02-27 14:02:38 +08:00
{
2019-12-11 13:10:35 +08:00
closest = stc;
continue;
}
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f);
float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f);
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
if (o < lastOffset)
closest = stc;
}
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
Trace.Assert(closest != null, "closest != null");
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
// ReSharper disable once PossibleNullReferenceException
offset += DrawWidth / 2f - (closest.Position.X + closest.DrawWidth / 2f);
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
ScrollingTeam st = closest;
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
availableTeams.RemoveAll(at => at == st.Team);
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
st.Selected = true;
OnSelected?.Invoke(st.Team);
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
delayedStateChangeDelegate = Scheduler.AddDelayed(() => setScrollState(ScrollState.Idle), 10000);
break;
2019-04-01 11:44:46 +08:00
2019-12-11 13:10:35 +08:00
case ScrollState.Idle:
resetSelected();
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
OnScrollStarted?.Invoke();
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
speedTo(40f, 200);
tracker.FadeOut(100);
break;
2017-02-27 14:02:38 +08:00
}
}
2018-04-13 17:19:50 +08:00
public void AddTeam(TournamentTeam team)
2017-02-27 14:02:38 +08:00
{
if (availableTeams.Contains(team))
return;
2018-04-13 17:19:50 +08:00
availableTeams.Add(team);
2018-04-13 17:19:50 +08:00
2022-09-03 20:17:46 +08:00
RemoveAll(c => c is ScrollingTeam, true);
2019-12-11 13:10:35 +08:00
setScrollState(ScrollState.Idle);
}
2018-04-13 17:19:50 +08:00
public void AddTeams(IEnumerable<TournamentTeam> teams)
2017-03-03 14:59:33 +08:00
{
if (teams == null)
return;
2018-04-13 17:19:50 +08:00
foreach (TournamentTeam t in teams)
2017-03-03 14:59:33 +08:00
AddTeam(t);
}
2018-04-13 17:19:50 +08:00
public void ClearTeams()
{
availableTeams.Clear();
RemoveAll(c => c is ScrollingTeam, true);
2019-12-11 13:10:35 +08:00
setScrollState(ScrollState.Idle);
}
2018-04-13 17:19:50 +08:00
public void RemoveTeam(TournamentTeam team)
{
availableTeams.Remove(team);
2018-04-13 17:19:50 +08:00
foreach (var c in Children)
{
2019-11-12 18:16:51 +08:00
if (c is ScrollingTeam st)
{
2019-11-12 18:16:51 +08:00
if (st.Team == team)
{
st.FadeOut(200);
st.Expire();
}
2017-02-27 14:02:38 +08:00
}
}
}
2018-04-13 17:19:50 +08:00
public void StartScrolling()
{
if (availableTeams.Count == 0)
return;
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
setScrollState(ScrollState.Scrolling);
}
2018-04-13 17:19:50 +08:00
public void StopScrolling()
{
if (availableTeams.Count == 0)
return;
2018-04-13 17:19:50 +08:00
switch (scrollState)
{
case ScrollState.Stopped:
case ScrollState.Idle:
return;
}
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
setScrollState(ScrollState.Stopping);
}
2018-04-13 17:19:50 +08:00
protected override void LoadComplete()
{
base.LoadComplete();
2019-12-11 13:10:35 +08:00
setScrollState(ScrollState.Idle);
2017-02-27 14:02:38 +08:00
}
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
protected override void UpdateAfterChildren()
{
timeOffset -= (float)(Time.Current - lastTime) / 1000 * speed;
lastTime = Time.Current;
2018-04-13 17:19:50 +08:00
if (availableTeams.Count > 0)
{
// Fill more than required to account for transformation + scrolling speed
while (Children.Count(c => c is ScrollingTeam) < DrawWidth * 2 / ScrollingTeam.WIDTH)
addFlags();
}
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
float pos = leftPos;
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
foreach (var c in Children)
{
if (!(c is ScrollingTeam))
continue;
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
if (c.Position.X + c.DrawWidth < 0)
{
c.ClearTransforms();
c.Expire();
expiredCount++;
}
else
{
2017-02-27 14:02:38 +08:00
c.MoveToX(pos, 100);
2017-06-07 22:00:14 +08:00
c.FadeTo(1.0f - Math.Abs(pos - DrawWidth / 2f) / (DrawWidth / 2.5f), 100);
}
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
pos += ScrollingTeam.WIDTH;
}
}
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
private void addFlags()
{
foreach (TournamentTeam t in availableTeams)
2017-02-27 14:02:38 +08:00
{
2017-05-02 13:21:22 +08:00
Add(new ScrollingTeam(t)
2017-02-27 14:02:38 +08:00
{
X = leftPos + DrawWidth
});
}
}
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
private void resetSelected()
{
foreach (var c in Children)
{
2019-11-12 18:16:51 +08:00
if (c is ScrollingTeam st)
2017-02-27 14:02:38 +08:00
{
2019-11-12 18:16:51 +08:00
if (st.Selected)
{
st.Selected = false;
RemoveTeam(st.Team);
}
2017-02-27 14:02:38 +08:00
}
}
}
2018-04-13 17:19:50 +08:00
2017-07-23 02:50:25 +08:00
private void speedTo(float value, double duration = 0, Easing easing = Easing.None) =>
2017-07-16 18:59:26 +08:00
this.TransformTo(nameof(speed), value, duration, easing);
2018-04-13 17:19:50 +08:00
2019-12-11 13:10:35 +08:00
protected enum ScrollState
2017-02-27 14:02:38 +08:00
{
None,
2017-02-27 14:02:38 +08:00
Idle,
Stopping,
Stopped,
Scrolling
}
2018-04-13 17:19:50 +08:00
2018-08-26 00:24:19 +08:00
public partial class ScrollingTeam : DrawableTournamentTeam
2017-02-27 14:02:38 +08:00
{
public const float WIDTH = 58;
public const float HEIGHT = 44;
2018-04-13 17:19:50 +08:00
private readonly Box outline;
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
private bool selected;
2017-02-27 14:02:38 +08:00
public bool Selected
{
get => selected;
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
set
{
selected = value;
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
if (selected)
outline.FadeIn(100);
else
outline.FadeOut(100);
}
}
2018-04-13 17:19:50 +08:00
public ScrollingTeam(TournamentTeam team)
2018-08-26 00:24:19 +08:00
: base(team)
2017-02-27 14:02:38 +08:00
{
Anchor = Anchor.CentreLeft;
Origin = Anchor.CentreLeft;
2018-04-13 17:19:50 +08:00
2017-02-27 14:02:38 +08:00
Size = new Vector2(WIDTH, HEIGHT);
Masking = true;
CornerRadius = 8f;
2018-04-13 17:19:50 +08:00
Alpha = 0;
2018-04-13 17:19:50 +08:00
2018-08-26 00:24:19 +08:00
Flag.Anchor = Anchor.Centre;
Flag.Origin = Anchor.Centre;
2021-02-26 16:58:21 +08:00
Flag.Scale = new Vector2(0.7f);
2018-08-26 00:24:19 +08:00
InternalChildren = new Drawable[]
2017-02-27 14:02:38 +08:00
{
2017-03-03 19:08:32 +08:00
outline = new Box
2017-02-27 14:02:38 +08:00
{
RelativeSizeAxes = Axes.Both,
2018-11-04 03:58:35 +08:00
Colour = OsuColour.Gray(0.33f),
2017-02-27 14:02:38 +08:00
Alpha = 0
},
2018-08-26 00:24:19 +08:00
Flag
2017-02-27 14:02:38 +08:00
};
}
}
}
}