d4b357dfa0 contains a sneaky regression.
The previous code read:
if (CurrentSelection != null && CheckModelEquality(beatmap, CurrentSelection))
RequestSelection(matchingNewBeatmap);
and the new one reads:
if (CurrentSelection is GroupedBeatmap currentBeatmapUnderGrouping)
{
var candidateSelection = currentBeatmapUnderGrouping with { Beatmap = beatmap };
if (CheckModelEquality(candidateSelection, CurrentSelection))
RequestSelection(candidateSelection);
}
The point is that we want to reselect `matchingNewBeatmap` here, not the
old selection. The `CheckModelEquality()` check's purpose is to check
whether *the current selection needs updating*.
I'm not sure why tests just wonderfully passed despite this, but my
suspicion is that it was because of accidental copying of realm guids
that obscured this problem.
This is probably where things get a little controversial.
There are some song select flows wherein song select just wants to
ensure sanity by authoritatively setting the global beatmap. The goal is
to change the beatmap immediately and instantly. Therefore it should
kind of be the carousel's job to figure out its grouping complications.
To that end, `CurrentSelection` is made virtual, and overridden in
`BeatmapCarousel` to perform a sort of reconciliation logic. If an
external component sets `CurrentSelection` to a `BeatmapInfo`, one of
the two following things happen:
- Nothing, if the current `GroupedBeatmap` is already a copy of the
beatmap that needs to be selected, or
- The carousel looks at its items, finds any first copy which matches
the beatmap that the external consumer wanted selected, and changes
selection to that instead.
Basically, `BeatmapCarousel.CurrentSelection`, which is
magic-object-typed, can no longer use `BeatmapInfo` directly, it now
must also use `GroupedBeatmap`.
This spills out all the way into song select because of beatmap
selection flows that require hookup from song select.
This bypasses the immediate first issue of not being able to display
multiple instances of a beatmap on the carousel because of model
equality being baked into the structure. It inevitably poses a bunch of
*other* problems, but it's a start.
Takes changes in https://github.com/ppy/osu/pull/34233 and removes *all*
of the complexity.
Supersedes and closes#34233.
Contains same caveat that we can only display one beatmap once in the
carousel; this will be addressed separately.
The new version wasn't really working as expected, because the Y
position measurement only considered visible panels, while it was being
divided over all panels (including non-expanded groups or sets).
Rather than trying to divide across all panels, just choose a sane
number for the "highest pitch" sound and work with that as a constant.
Previously, random selection would always be done at a *set* level. The
final operation of a random action would be "select the user's
recommended difficulty from this randomly selected set".
This makes no sense when sets are not grouped together at song select.
In fact, it is completely broken with the previous commit which adds
group-isolated random support – if we're grouping by difficulty and the
user's recommendation is not in the current group it would throw the
user into another group unexpectedly.
This fixes the issue by splitting out the random implementation into two
separate pathways depending on the carousel display mode.