Closes https://github.com/ppy/osu/issues/29793.
I believe that the sequence of events that makes this happens is as
follows:
- User selects a range of objects. Some of those objects are off-screen,
and thus would be presumed to be not alive - except the blueprint
container forces them to remain alive, because they're part of the
selection.
- User moves the selection to another column, which is implemented by
temporarily removing the objects from the playfield, changing their
column, and re-adding them.
This sort of pattern is supposed to kick off the
`HitObjectUsageTransferred` flow in `HitObjectUsageEventBuffer` - and
it does... for objects that are *currently visible on screen* and thus
would be alive regardless of `SetKeepAlive()`. However, this does not
hold for objects that are off-screen - nothing ensures they are kept
alive again after re-adding, and thus they inadvertently become dead.
- Thus, this doesn't kick off the `BlueprintContainer` flows associated
with transferring objects to another column, and instead fires the
removal flows, which ensure that the off-screen objects that were
being moved are instead deselected.
I tried a few other options but found no better resolution than this -
calling `SetKeepAlive()` directly would require making it public, which
seems like a bad idea. There's really no good way to generically handle
this either, because it is the ruleset that decides that its way of
implementing this operation will be a removal and re-add of objects,
so...
Before I go with a hammer to redesign these, I want to remove stuff that
does nothing first.
Hard-breaks API to allow rulesets to specify an enumerable of custom
sections rather than two specific weird ones.
For specific rulesets:
- osu!:
- Stack leniency slider merged into difficulty section.
- osu!taiko:
- Approach rate and circle size sliders removed.
- Colours section removed.
- osu!catch:
- No functional changes.
- osu!mania:
- Special style toggle merged into difficulty section.
- Colours section removed.
I'm not sure what the cause of the issue is, but I'm also not sure why
it wasn't using `DrawablePool` (was it not around back then?).
Either way, switching to a proper pool fixes things just fine.
Resolves https://github.com/ppy/osu/issues/25009.
Until now, these were haphazardly enforce inline in blueprint
implementations. The only thing stopping complete breakage is that
`EndPlacement` wasn't called (too much) from outside the blueprint,
leaving them responsible for their own placement.
By moving this conditional out of the provided paramters to
`EndPlacement`, it allows more flexible usage of that method externally.
Coming in a future PR.