Closes https://github.com/ppy/osu/issues/33542.
For a diff this simple this took much more hemming and hawing because
things are a bit annoying here from a few angles:
- The only way that is considered idiomatic right now for a skin
component to not be applicable to a screen is to require a dependency
from DI that is only provided by applicable screens.
`DrawableGameplayLeaderboard` has a few of those dependencies, but the
scope of all the usages makes it so that the only really viable one to
use here is `IGameplayLeaderboardProvider` itself (see: visual tests,
and also the usage of multiplayer spectator, where the leaderboard is
*not* under a player instance).
- The smelly part of this is that the `Player` inheritance hierarchy
must ensure that *every* non-abstract class has an
`IGameplayLeaderboardProvider` cached. It is not trivial - if not
straight up impossible - to force this via some `Player` level
abstract method, because such a method would need to somehow
accommodate all possible leaderboard providers. That however also
means that every possible future `Player` implementor *must inherently
know* to also cache a leaderboard provider lest it die at runtime. I
don't love that, but I also don't see better alternatives.
- Speaking of which, I also noticed that solo spectator and playlists
don't have gameplay leaderboards. At all. Which I don't believe to be
something that I broke with the leaderboard work - I'm pretty sure
that was the pre-existing state - however I don't see any reason why
they *couldn't* receive gameplay leaderboards. I'm not doing that
here, though, just leaving TODOs for later.
These are tested framework-side to throw exceptions, but the
test is ignored for the source generated version because it quietly
allows this scenario.
The source gen project should eventually have an analyser for these
unsupported cases, or we could consider relaxing this particular case.
I also took the freedom to add type checking, as we can't limit the
usage of `Add()` since it's a Container. The exception thrown also
advises of using the suggested `AddTrigger()` instead.
This allows for different layouts of display. Idk, maybe someone would
want to mix both variants? (don't do this please). This commit is mostly
prep for further changes.
All other similar UI components have required dependencies, so this is
mainly to bring things in line with expectations. I am using this fact
in the skin editor to only show components which can be used in the
current editor context (by `try-catch`ing their
`Activator.CreateInstance`).
This is kind of how I see things working going forward, where the editor
can be applied to anything in the game which supports it (ie. a results
screen, gameplay screen, etc.) and it will immediately allow changing
the interface.
This adds a test scene which shows this working with gameplay.