Fix a cosmetic UI issue where -0.0 is displayed when clicking the Calibrate using last play button.
Removed changes to AudioOffsetAdjustControl and added check to ToStandardFormattedString for if floatValue is 0
This change pulls back a significant degree of overspecialisation and
rigidity in the class structure of `HitWindows` to make subsequent
changes to hit windows, whose purpose is to improve replay playback
accuracy, possible to do cleanly.
Notably:
- `HitWindows` is full abstract now. In a few use cases, and as a
reference for ruleset implementors, `DefaultHitWindows` is provided as
a separate class instead.
This fixes the weirdness wherein `HitWindows` always declared 6 fields
for result types but some of them would never be set to a non-zero
value or read.
- `HitWindow.GetRanges()` is deleted because it is overspecialised and
prevents being able to adjust hitwindows by ±0.5ms cleanly which will
be required later.
The fallout of this is that the assertion that used `GetRanges()` in
the `HitWindows` ctor must use something else now, and the closest
thing to it was `GetAllAvailableWindows()`, which didn't return
the miss window - so I made it return the miss window and fixed the
one consumer that didn't want it (bar hit error meter) to skip it.
- Diff also contains some clean-up around `DifficultyRange` to unify
handling of it.
As proposed in https://github.com/ppy/osu/discussions/33572.
Note that this won't work if you leave to song select. We could make
that work but it would require further global faffing and I don't think
it's worth the effort.
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.
Closes https://github.com/ppy/osu/issues/33455.
The fundamental misunderstanding and source of confusion in
https://github.com/ppy/osu/pull/33062 is that solo wants to show
*maximum combo*, and multiplayer wants to show *current combo*, for
their own, valid reasons. Which is spelled out explicitly in this
change.
Closes https://github.com/ppy/osu/issues/33465 probably.
This reverts the replay frame de-duplication logic to what it was before
https://github.com/ppy/osu/pull/33148#discussion_r2091549388.
I don't have good reproduction steps. I tried to write a test case for
this that isn't just "press and release a key in the same frame",
thinking that maybe there was some loophole in the osu! touch input
mapper that may produce this situation artificially, but I could not in
many configurations. So I have to assume that this just *can happen*
organically.
This fell out of my work on hit window-related replay issues. In my WIP
branch (that is probably going to get PR'd as draft soon) I refactored
`HitWindows` and found a few straggling test failures due to some places
reading hit windows for results that were not actually supported by the
underlying `HitWindows` implementations, leading to returning garbage
(mostly zeroes).
Importantly, there is one actual usage in game code with impact here -
`TaikoModSingleTap` was attempting to read the hit window for MEH, when
MEH was never actually a valid hit result in taiko (OK is). This was a
result of a copy-paste oversight from osu!, specifically from
https://github.com/ppy/osu/blob/51cf835fb6300aca53b5b98143d606f64d7a4d49/osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs#L58
I'd have preferred a `get; init;` property but tests were also attached
at the hip to the public bindable. Without some extra composition this
is the best that I can do.
The sorting logic is now exercised in
`TestSceneSoloGameplayLeaderboardProvider`. Trying to work around
it with local test classes would mean that the test would be covering
test code, i.e. complete nonsense and having a green test for the sake
of having a green test.
Intends to close https://github.com/ppy/osu/issues/32859.
The difference between this and https://github.com/ppy/osu/pull/32942 is
that this PR takes the approach of completely moving the score sorting
behaviour to `IGameplayLeaderboardProvider` implementations.
This is going to be helpful for further work - to be precise, I am
looking to add a leaderboard position indicator in the bottom right of
multiplayer player to match stable, and having the position in the
provider will make the implementation of that *much* easier.
This PR converts the leaderboard into a full-fledged skinnable component
that can be manipulated by users at will.
Notably, this finally allows https://github.com/ppy/osu/issues/20422 to
be fixed - although it's a very mixed bag, for several reasons:
- Because of taiko players' refusal to see reason^W^W^W^Winsistence on
keeping stable behaviours related to aspect ratio treatment, I have to
assume the worst case scenario, which means than on typical
resolutions like 16:9 (or even worse, 4:3), the leaderboard will
likely not occupy as much vertical space as it probably could.
- Additionally, there's the problem of where to put the spectator list.
I settled on putting it to the right of the leaderboard, but that's
kind of janky, because the leaderboard sometimes collapses and
sometimes fully hides, leading to a very awkward space left behind. If
we had the capability to anchor elements to other elements, maybe this
could be resolved, but for now, I'm not sure what to do. I think if
some users are bothered by it they can move it where they want it. Or
delete it.
As time goes on, default skin layouts are getting more and more
complicated because of per-ruleset overrides. This was already sort of
apparent in https://github.com/ppy/osu/pull/31527, and I'm about to make
it worse, so before I do, this is a test scene that is supposed to make
it easier to check all possible combinations at a glance.
This is a prerequisite for supporting skinning of leaderboards.
- New `IGameplayLeaderboardProvider` and `IGameplayLeaderboardScore`
interfaces are introduced. They are strictly concerned with supplying
leaderboard data.
- Logic of managing display, which was previously jammed into the
inheritance hierarchy of `GameplayLeaderboard`, is now moved into
`IGameplayLeaderboardProvider` implementations. Solo play,
multiplayer, and multiplayer spectator get their own implementation of
the interface.
- The inheritance hierarchy of `GameplayLeaderboard` and per-player
overriding of the implementation of the gameplay leaderboard is gone.
Only one drawable class (renamed to `DrawableGameplayLeaderboard`) is
allowed to display the leaderboards, across all modes of play.
It's all a bit weird so let's just disable it for now. For instance,
this is exposed as "text" font / colour but only affects the header.
Also, no other headers are cusotmisable in similar components.