This was already being done on the old carousel (see `ApplyState`
methods) but wasn't correctly on new carousel.
Importantly, `FreeAfterUse` alone is not enough due to transitions. We
want to immediately stop calculation as soon as a panel is marked
non-visible.
There's no bindable flow for this so it's performed in `Update`. I don't
see this as an issue.
Closes https://github.com/ppy/osu/issues/22086
While this *is* a case of aspire-tier breakage, I hesitate to dismiss it
as wontfix, because the fix is somewhat easy, and probably results in
better accuracy across the board.
The issue in question here manifests when there is a significant amount
of lead-in time, like what the beatmap linked in the aforementioned
issue (https://osu.ppy.sh/beatmapsets/948643#osu/1981090) does.
Both stable and lazer record replay frames using absolute timestamps,
*but* the legacy replay format after the first frame uses time *deltas*,
i.e. amounts of time elapsed since the previous frame. This means that
the decoding process of the replay has to reconstruct absolute timestamps
by doing cumulative summation starting from the first frame.
When the very first frame has a timestamp that is very large in
magnitude (say, like the negative 2 billion that the beatmap in question
uses), this will lead to error if the cumulative summation is using
floating point numbers, because it will be adding a small magnitude
frame delta to a large magnitude cumulative absolute time. Which means
that sometimes adding the frame delta to the cumulative time *will not
change the cumulative time*, leading to the loss of time and thus replay
de-synchronisation.
Knowing that the legacy replay format only deals in integral time
values, however, this can be circumvented by just using a large enough
integral number type for the cumulative time tracking instead. I think
`long` in this case can be safely used "large enough" for our purposes:
> Console.WriteLine(long.MaxValue);
9223372036854775807
9 223 372 036 854 775 807 ms equals 292 277 024,6269277149 years
Addresses https://github.com/ppy/osu/discussions/28301.
No sound effects on click because right click handling is weird. I would
have liked to call `DeselectAll` on the mod select overlay, but this
doesn't work unless it's displayed due to queued operation.
Previously, carousel panels would appear immediately at their required Y
position. This didn't look great when they appear with other panels
surrounding them.
Now they will spawn in underneath the nearest item before them, making
the animation feel much more correct.
With judgements occurring forcing emission of important frames, there's
the question of emitting redundant frames. In a majority of cases
still, a judgement *will* be tied to a specific user input, which means
that there's a high likelihood of duplicate frames, as one will be
emitted by the input change, and another by the judgement.
To a degree this is a pre-existing issue. The replay recording code
responds to both mouse movement and key presses by recording frames, so
depending on the intrinsic (basically undefined) ordering between
handling mouse move and key presses, it was possible for multiple frames
to be emitted with the same timestamp to the replay, each containing
partial input state changes (e.g. first frame with mouse position
changed, and the second with a key pressed).
The extent to which this increases the frame count will obviously depend
on the beatmap, but in my ballpark testing across all rulesets on a
single "relatively standard" beatmap (think no aspire chicanery), around
4-10% of frames can end up being duplicates / not meaningful. This has
implications both on replay size and on playback performance.
This commit therefore performs de-duplication of the frames based on
timestamp - only the last frame with a given timestamp ends up in the
final replay.
The CPU cost of this is negligible to the point of not being useful to
profile - it's a single condition gated behind a single float comparison