1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-19 04:32:54 +08:00
osu-lazer/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs
Dean Herbert f58c69e639 Fix potential startup crash due to early application of animations
This was always haphazard code, but by luck it never triggered before
drawable load until now. With the recently nullability changes, this
would be triggered when `flash` is not yet constructed.

Switching to `AddOnce` seems safer to avoid multiple applications,
regardless.
2023-07-28 17:17:15 +09:00

196 lines
7.1 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 System.Collections.Specialized;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics;
using osu.Game.Tournament.Models;
using osuTK.Graphics;
namespace osu.Game.Tournament.Components
{
public partial class TournamentBeatmapPanel : CompositeDrawable
{
public readonly TournamentBeatmap? Beatmap;
private readonly string mod;
public const float HEIGHT = 50;
private readonly Bindable<TournamentMatch?> currentMatch = new Bindable<TournamentMatch?>();
private Box flash = null!;
public TournamentBeatmapPanel(TournamentBeatmap? beatmap, string mod = "")
{
Beatmap = beatmap;
this.mod = mod;
Width = 400;
Height = HEIGHT;
}
[BackgroundDependencyLoader]
private void load(LadderInfo ladder)
{
currentMatch.BindValueChanged(matchChanged);
currentMatch.BindTo(ladder.CurrentMatch);
Masking = true;
AddRangeInternal(new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
},
new NoUnloadBeatmapSetCover
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(0.5f),
OnlineInfo = Beatmap,
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Padding = new MarginPadding(15),
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new TournamentSpriteText
{
Text = Beatmap?.GetDisplayTitleRomanisable(false, false) ?? (LocalisableString)@"unknown",
Font = OsuFont.Torus.With(weight: FontWeight.Bold),
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
new TournamentSpriteText
{
Text = "mapper",
Padding = new MarginPadding { Right = 5 },
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 14)
},
new TournamentSpriteText
{
Text = Beatmap?.Metadata.Author.Username ?? "unknown",
Padding = new MarginPadding { Right = 20 },
Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14)
},
new TournamentSpriteText
{
Text = "difficulty",
Padding = new MarginPadding { Right = 5 },
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 14)
},
new TournamentSpriteText
{
Text = Beatmap?.DifficultyName ?? "unknown",
Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14)
},
}
}
},
},
flash = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Gray,
Blending = BlendingParameters.Additive,
Alpha = 0,
},
});
if (!string.IsNullOrEmpty(mod))
{
AddInternal(new TournamentModIcon(mod)
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding(10),
Width = 60,
RelativeSizeAxes = Axes.Y,
});
}
}
private void matchChanged(ValueChangedEvent<TournamentMatch?> match)
{
if (match.OldValue != null)
match.OldValue.PicksBans.CollectionChanged -= picksBansOnCollectionChanged;
if (match.NewValue != null)
match.NewValue.PicksBans.CollectionChanged += picksBansOnCollectionChanged;
Scheduler.AddOnce(updateState);
}
private void picksBansOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
=> Scheduler.AddOnce(updateState);
private BeatmapChoice? choice;
private void updateState()
{
var newChoice = currentMatch.Value?.PicksBans.FirstOrDefault(p => p.BeatmapID == Beatmap?.OnlineID);
bool shouldFlash = newChoice != choice;
if (newChoice != null)
{
if (shouldFlash)
flash.FadeOutFromOne(500).Loop(0, 10);
BorderThickness = 6;
BorderColour = TournamentGame.GetTeamColour(newChoice.Team);
switch (newChoice.Type)
{
case ChoiceType.Pick:
Colour = Color4.White;
Alpha = 1;
break;
case ChoiceType.Ban:
Colour = Color4.Gray;
Alpha = 0.5f;
break;
}
}
else
{
Colour = Color4.White;
BorderThickness = 0;
Alpha = 1;
}
choice = newChoice;
}
private partial class NoUnloadBeatmapSetCover : UpdateableOnlineBeatmapSetCover
{
// As covers are displayed on stream, we want them to load as soon as possible.
protected override double LoadDelay => 0;
// Use DelayedLoadWrapper to avoid content unloading when switching away to another screen.
protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func<Drawable> createContentFunc, double timeBeforeLoad)
=> new DelayedLoadWrapper(createContentFunc, timeBeforeLoad);
}
}
}