2019-03-04 12:24:19 +08:00
|
|
|
// 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-11-16 19:14:34 +08:00
|
|
|
|
2020-02-17 14:06:14 +08:00
|
|
|
using System.Collections.Specialized;
|
2022-12-16 19:18:02 +08:00
|
|
|
using System.Diagnostics;
|
2018-11-16 19:14:34 +08:00
|
|
|
using System.Linq;
|
|
|
|
using osu.Framework.Allocation;
|
|
|
|
using osu.Framework.Caching;
|
|
|
|
using osu.Framework.Extensions.Color4Extensions;
|
|
|
|
using osu.Framework.Graphics;
|
|
|
|
using osu.Framework.Graphics.Containers;
|
|
|
|
using osu.Framework.Graphics.Lines;
|
2019-06-17 20:07:30 +08:00
|
|
|
using osu.Game.Tournament.Components;
|
2019-06-18 13:51:48 +08:00
|
|
|
using osu.Game.Tournament.Models;
|
|
|
|
using osu.Game.Tournament.Screens.Editors;
|
2018-11-16 19:14:34 +08:00
|
|
|
using osu.Game.Tournament.Screens.Ladder.Components;
|
2018-11-22 09:25:30 +08:00
|
|
|
using osuTK.Graphics;
|
2018-11-16 19:14:34 +08:00
|
|
|
|
|
|
|
namespace osu.Game.Tournament.Screens.Ladder
|
|
|
|
{
|
2022-07-11 19:42:04 +08:00
|
|
|
public partial class LadderScreen : TournamentScreen
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2023-07-25 19:50:55 +08:00
|
|
|
protected Container<DrawableTournamentMatch> MatchesContainer = null!;
|
|
|
|
private Container<Path> paths = null!;
|
|
|
|
private Container headings = null!;
|
2018-11-16 19:14:34 +08:00
|
|
|
|
2023-07-25 19:50:55 +08:00
|
|
|
protected LadderDragContainer ScrollContent = null!;
|
2018-11-16 19:14:34 +08:00
|
|
|
|
2023-07-25 19:50:55 +08:00
|
|
|
protected Container Content = null!;
|
2019-06-13 16:04:57 +08:00
|
|
|
|
2018-11-16 19:14:34 +08:00
|
|
|
[BackgroundDependencyLoader]
|
2022-01-15 08:06:39 +08:00
|
|
|
private void load()
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2020-03-11 09:18:41 +08:00
|
|
|
normalPathColour = Color4Extensions.FromHex("#66D1FF");
|
|
|
|
losersPathColour = Color4Extensions.FromHex("#FFC700");
|
2018-11-16 19:14:34 +08:00
|
|
|
|
|
|
|
RelativeSizeAxes = Axes.Both;
|
|
|
|
|
2019-06-13 16:04:57 +08:00
|
|
|
InternalChild = Content = new Container
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
|
|
|
RelativeSizeAxes = Axes.Both,
|
2023-07-20 17:31:13 +08:00
|
|
|
Masking = true,
|
2018-11-16 19:14:34 +08:00
|
|
|
Children = new Drawable[]
|
|
|
|
{
|
2020-03-06 17:38:29 +08:00
|
|
|
new TourneyVideo("ladder")
|
2018-11-17 13:59:37 +08:00
|
|
|
{
|
|
|
|
RelativeSizeAxes = Axes.Both,
|
|
|
|
Loop = true,
|
|
|
|
},
|
2020-03-12 12:29:09 +08:00
|
|
|
new DrawableTournamentHeaderText
|
2020-03-07 00:37:15 +08:00
|
|
|
{
|
|
|
|
Y = 100,
|
|
|
|
Anchor = Anchor.TopCentre,
|
|
|
|
Origin = Anchor.TopCentre,
|
|
|
|
},
|
2019-06-13 15:11:15 +08:00
|
|
|
ScrollContent = new LadderDragContainer
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2023-07-28 15:25:52 +08:00
|
|
|
AutoSizeAxes = Axes.Both,
|
2018-11-16 19:14:34 +08:00
|
|
|
Children = new Drawable[]
|
|
|
|
{
|
|
|
|
paths = new Container<Path> { RelativeSizeAxes = Axes.Both },
|
|
|
|
headings = new Container { RelativeSizeAxes = Axes.Both },
|
2023-07-28 15:25:52 +08:00
|
|
|
MatchesContainer = new Container<DrawableTournamentMatch>
|
|
|
|
{
|
|
|
|
AutoSizeAxes = Axes.Both
|
|
|
|
},
|
2018-11-16 19:14:34 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-06-18 13:57:05 +08:00
|
|
|
void addMatch(TournamentMatch match) =>
|
|
|
|
MatchesContainer.Add(new DrawableTournamentMatch(match, this is LadderEditorScreen)
|
2019-06-14 18:16:20 +08:00
|
|
|
{
|
|
|
|
Changed = () => layout.Invalidate()
|
|
|
|
});
|
|
|
|
|
2019-06-18 13:57:05 +08:00
|
|
|
foreach (var match in LadderInfo.Matches)
|
|
|
|
addMatch(match);
|
2018-11-16 19:14:34 +08:00
|
|
|
|
2022-06-24 20:25:23 +08:00
|
|
|
LadderInfo.Rounds.CollectionChanged += (_, _) => layout.Invalidate();
|
2020-02-17 14:06:14 +08:00
|
|
|
LadderInfo.Matches.CollectionChanged += (_, args) =>
|
2019-06-14 18:16:20 +08:00
|
|
|
{
|
2020-02-17 14:06:14 +08:00
|
|
|
switch (args.Action)
|
2019-11-11 19:53:22 +08:00
|
|
|
{
|
2020-02-17 14:06:14 +08:00
|
|
|
case NotifyCollectionChangedAction.Add:
|
2022-12-16 19:18:02 +08:00
|
|
|
Debug.Assert(args.NewItems != null);
|
|
|
|
|
2020-02-17 14:06:14 +08:00
|
|
|
foreach (var p in args.NewItems.Cast<TournamentMatch>())
|
|
|
|
addMatch(p);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NotifyCollectionChangedAction.Remove:
|
2022-12-16 19:18:02 +08:00
|
|
|
Debug.Assert(args.OldItems != null);
|
|
|
|
|
2020-03-04 11:37:42 +08:00
|
|
|
foreach (var p in args.OldItems.Cast<TournamentMatch>())
|
2020-02-17 14:06:14 +08:00
|
|
|
{
|
|
|
|
foreach (var d in MatchesContainer.Where(d => d.Match == p))
|
|
|
|
d.Expire();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2019-11-11 19:53:22 +08:00
|
|
|
}
|
2019-06-14 18:16:20 +08:00
|
|
|
|
|
|
|
layout.Invalidate();
|
|
|
|
};
|
2018-11-16 19:14:34 +08:00
|
|
|
}
|
|
|
|
|
2019-08-09 18:12:29 +08:00
|
|
|
private readonly Cached layout = new Cached();
|
2018-11-16 19:14:34 +08:00
|
|
|
|
|
|
|
protected override void Update()
|
|
|
|
{
|
|
|
|
base.Update();
|
|
|
|
|
|
|
|
if (!layout.IsValid)
|
|
|
|
UpdateLayout();
|
|
|
|
}
|
|
|
|
|
|
|
|
private Color4 normalPathColour;
|
|
|
|
private Color4 losersPathColour;
|
|
|
|
|
2019-06-14 18:16:20 +08:00
|
|
|
protected virtual bool DrawLoserPaths => false;
|
|
|
|
|
2018-11-16 19:14:34 +08:00
|
|
|
protected virtual void UpdateLayout()
|
|
|
|
{
|
|
|
|
paths.Clear();
|
|
|
|
headings.Clear();
|
|
|
|
|
|
|
|
int id = 1;
|
2019-05-15 11:08:23 +08:00
|
|
|
|
2019-06-18 13:57:05 +08:00
|
|
|
foreach (var match in MatchesContainer.OrderBy(d => d.Y).ThenBy(d => d.X))
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2019-06-18 13:57:05 +08:00
|
|
|
match.Match.ID = id++;
|
2018-11-16 19:14:34 +08:00
|
|
|
|
2019-06-18 13:57:05 +08:00
|
|
|
if (match.Match.Progression.Value != null)
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2019-06-18 13:57:05 +08:00
|
|
|
var dest = MatchesContainer.FirstOrDefault(p => p.Match == match.Match.Progression.Value);
|
2018-11-16 19:14:34 +08:00
|
|
|
|
|
|
|
if (dest == null)
|
|
|
|
// clean up outdated progressions.
|
2019-06-18 13:57:05 +08:00
|
|
|
match.Match.Progression.Value = null;
|
2018-11-16 19:14:34 +08:00
|
|
|
else
|
2019-06-18 13:57:05 +08:00
|
|
|
paths.Add(new ProgressionPath(match, dest) { Colour = match.Match.Losers.Value ? losersPathColour : normalPathColour });
|
2018-11-16 19:14:34 +08:00
|
|
|
}
|
2019-06-14 18:16:20 +08:00
|
|
|
|
|
|
|
if (DrawLoserPaths)
|
|
|
|
{
|
2019-06-18 13:57:05 +08:00
|
|
|
if (match.Match.LosersProgression.Value != null)
|
2019-06-14 18:16:20 +08:00
|
|
|
{
|
2019-06-18 13:57:05 +08:00
|
|
|
var dest = MatchesContainer.FirstOrDefault(p => p.Match == match.Match.LosersProgression.Value);
|
2019-06-14 18:16:20 +08:00
|
|
|
|
|
|
|
if (dest == null)
|
|
|
|
// clean up outdated progressions.
|
2019-06-18 13:57:05 +08:00
|
|
|
match.Match.LosersProgression.Value = null;
|
2019-06-14 18:16:20 +08:00
|
|
|
else
|
2019-06-18 13:57:05 +08:00
|
|
|
paths.Add(new ProgressionPath(match, dest) { Colour = losersPathColour.Opacity(0.1f) });
|
2019-06-14 18:16:20 +08:00
|
|
|
}
|
|
|
|
}
|
2018-11-16 19:14:34 +08:00
|
|
|
}
|
|
|
|
|
2019-06-18 13:44:15 +08:00
|
|
|
foreach (var round in LadderInfo.Rounds)
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2022-12-19 15:42:21 +08:00
|
|
|
var topMatch = MatchesContainer.Where(p => !p.Match.Losers.Value && p.Match.Round.Value == round).MinBy(p => p.Y);
|
2018-11-16 19:14:34 +08:00
|
|
|
|
2019-06-18 13:57:05 +08:00
|
|
|
if (topMatch == null) continue;
|
2018-11-16 19:14:34 +08:00
|
|
|
|
2019-06-18 13:44:15 +08:00
|
|
|
headings.Add(new DrawableTournamentRound(round)
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2019-06-18 13:57:05 +08:00
|
|
|
Position = headings.ToLocalSpace((topMatch.ScreenSpaceDrawQuad.TopLeft + topMatch.ScreenSpaceDrawQuad.TopRight) / 2),
|
2018-11-16 19:14:34 +08:00
|
|
|
Margin = new MarginPadding { Bottom = 10 },
|
|
|
|
Origin = Anchor.BottomCentre,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-06-18 13:44:15 +08:00
|
|
|
foreach (var round in LadderInfo.Rounds)
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2022-12-19 15:42:21 +08:00
|
|
|
var topMatch = MatchesContainer.Where(p => p.Match.Losers.Value && p.Match.Round.Value == round).MinBy(p => p.Y);
|
2018-11-16 19:14:34 +08:00
|
|
|
|
2019-06-18 13:57:05 +08:00
|
|
|
if (topMatch == null) continue;
|
2018-11-16 19:14:34 +08:00
|
|
|
|
2019-06-18 13:44:15 +08:00
|
|
|
headings.Add(new DrawableTournamentRound(round, true)
|
2018-11-16 19:14:34 +08:00
|
|
|
{
|
2019-06-18 13:57:05 +08:00
|
|
|
Position = headings.ToLocalSpace((topMatch.ScreenSpaceDrawQuad.TopLeft + topMatch.ScreenSpaceDrawQuad.TopRight) / 2),
|
2018-11-16 19:14:34 +08:00
|
|
|
Margin = new MarginPadding { Bottom = 10 },
|
|
|
|
Origin = Anchor.BottomCentre,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
layout.Validate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|