Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix breaks not showing unless already ordered in the beatmap file #28771

Merged
merged 4 commits into from
Jul 8, 2024

Conversation

frenzibyte
Copy link
Member

@frenzibyte frenzibyte commented Jul 8, 2024

BreakOverlay shows and hides by populating transforms at the designated periods using BeginAbsoluteSequence. The logic expects the breaks list to be ordered chronologically, otherwise the transforms of the earlier break periods will overwrite any transforms made later (and therefore make later break periods not have the overlay visible as seen in #28717).

This can be solved locally in BreakOverlay by reordering the break periods before applying the transforms, but I feel it's generally natural to expect such lists to be ordered beforehand, so I solved this differently by changing IBeatmap.Breaks to be a SortedList instead (similar to ControlPointInfo etc.).

Before:

CleanShot.2024-07-08.at.15.49.48-converted.mp4

After:

CleanShot.2024-07-08.at.14.30.25-converted.mp4

@bdach
Copy link
Collaborator

bdach commented Jul 8, 2024

Did you look into whether this can be tested (the part where breaks do not display, specifically)? I'd like it to be tested if at all possible.

@smoogipoo
Copy link
Contributor

I have slight concerns about the amount of extra stuff we're doing every beatmap conversion. This is effectively doing an O(n log n) operation every convert, on top of what I'd already consider to be wasteful.

As I've mentioned previously, I'd like Beatmap to be treated as a plain old data model, whereas this is adding (albeit hidden) logic to it. The same is done at parse time for HitObjects.

Maybe it's not an issue here since it's breaks so N is expected to be very low, though.

I'll hand this off to another reviewer to evaluate whether my concerns are worthwhile at this point.

@bdach
Copy link
Collaborator

bdach commented Jul 8, 2024

This is effectively doing an O(n log n) operation every convert

Given I'd realistically expect n<10 in this case then I see this as a moot concern. I'll profile if you're concerned but I'm 99% sure this won't even show up.

A local sort could work but I think this is a good invariant to put down. We already enforce start time ordering on hitobjects and control points.

@frenzibyte
Copy link
Member Author

Did you look into whether this can be tested (the part where breaks do not display, specifically)? I'd like it to be tested if at all possible.

The problem with them not displaying is due to BreakOverlay taking an unordered list of break periods, i.e. due to unexpected behaviour. I'm not sure how I can write a test case for that. The best I can do is to write a test case that does all of the steps in #28717 (comment) and then check if the break periods are ordered or not, but I felt that would be too much.

I meant to add some videos showcasing the issue and compare between master & PR, but I had to leave desk abruptly. It's attached now.

As I've mentioned previously, I'd like Beatmap to be treated as a plain old data model, whereas this is adding (albeit hidden) logic to it. The same is done at parse time for HitObjects.

I wouldn't mind following the path of simplicity myself. At first, I've had some concerns about using SortedList, but as mentioned above, it doesn't really matter since it can't be that large. I think SortedList just makes it more convenient to expose the data in an ordered fashion, and simplify code in many places. It doesn't include logic that could end up backfiring like bindables would.

Not using SortedList is also possible. Break periods are mutated in limited places, and we can make such places responsible for reordering the breaks.

@bdach
Copy link
Collaborator

bdach commented Jul 8, 2024

I'm not sure how I can write a test case for that

Surely you can imagine a way? Something like a player instance, with a manual backing clock and 2 breaks specified out of order? Seek to the middle of first break, assert that the overlay is showing?

To me this is very close to "basic correctness" so to not have a test for this sort of core behaviour is hard to swallow.

@frenzibyte
Copy link
Member Author

frenzibyte commented Jul 8, 2024

A realistic test case is what I mean, but I guess intentionally adding break periods out of order is technically possible to do in game (as one could do so in the .osu file), so sure, can do that.

@bdach
Copy link
Collaborator

bdach commented Jul 8, 2024

Profiling (release build, captured using tracing configuration)

On https://osu.ppy.sh/beatmapsets/972#osu/9007 (55 breaks, which I consider to be close to, if not the peak of sane edge cases):

image

On user's beatmap from the issue thread (3 breaks):

image

Based on these results I personally conclude that performance worries here are, as I suspected, unsubstantiated and not worthy of further scrutiny.

@bdach bdach enabled auto-merge July 8, 2024 14:03
@bdach bdach changed the title Enforce sorting order of IBeatmap.Breaks Fix breaks not showing unless already ordered in the beatmap file Jul 8, 2024
@bdach bdach added the area:beatmap-parsing .osu file format parsing label Jul 8, 2024
@bdach bdach disabled auto-merge July 8, 2024 14:46
@bdach bdach merged commit 4dd20cc into ppy:master Jul 8, 2024
11 of 17 checks passed
@frenzibyte frenzibyte deleted the sorted-breaks branch July 8, 2024 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Break not showing in lazer
3 participants