Because the online info reset (which includes online ID reset) was
happening after encoding,
`TestSceneBeatmapLeaderboard.TestLocalScoresDisplayOnBeatmapEdit()`
started failing, as the hash no longer matched expectations after the
first save of the map.
This test scene passes at e58e1151f3 and
fails at current master, due to an inadvertent regression caused by
e72f103c17.
As it turns out, the online lookup flow that was causing UI thread
freezes when saving beatmaps in the editor, was also responsible for
resetting the online ID of locally-modified beatmaps if online lookup
failed.
The `SelectedMods.BindValueChanged()` callback in `ModSelectOverlay` can
in some instances run recursively. This is most heavily leaned on in
scenarios where `SelectedMods` is updated by an external component. In
such cases, the mod select overlay needs to replace the mod instances
received externally with mod instances which it owns, so that the changes
made on the overlay can propagate outwards.
This in particular means that prior to this commit, it was possible to
encounter the following scenario:
modSettingChangeTracker?.Dispose();
updateFromExternalSelection(); // mutates SelectedMods to perform the replacement
// therefore causing a recursive call
modSettingChangeTracker?.Dispose();
// inner call continues
modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value);
// outer call continues
modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value);
This leaks one `modSettingChangeTracker` instance from the inner call,
which is never disposed.
To avoid this, move the disposal to the same side of the recursion that
the creation happens on, changing the call pattern to:
updateFromExternalSelection(); // mutates SelectedMods to perform the replacement
// therefore causing a recursive call
modSettingChangeTracker?.Dispose();
// inner call continues
modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value);
modSettingChangeTracker?.Dispose();
// outer call continues
modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value);
which, while slightly wasteful, does not cause any leaks.
The solution is definitely suboptimal, but addressing this properly
would entail a major rewrite of the mod instance management in the mods
overlay, which is probably not the wisest move to make right now.
This avoids the notice showing when running on windows, but using the
newer renderers (where the underlying logic hasn't been tested properly
and can result in false-positives).
Supersedes https://github.com/ppy/osu-framework/pull/5759 as a more
correct implementation.