- Closes https://github.com/ppy/osu/issues/37757
Commit-by-commit reading is recommended. Commits will be split to PRs on
request but I consider this to be the minimal viable functional
increment.
## Done
- This adds a first version of a full storyboard encoder
(a66dc406f498e35d4e0c8f2a462e946a9a1aeccc). I expect there to be hiccups
due to weird corners of the `.osb` format; this is only intended to be
somewhat correct as a start to build upon. Storyboarders are asked to
file issues as necessary.
- Due to the fact that storyboard definitions can reside both in the
`.osu` and the `.osb`, b60698a95c4de1bfeb36fbb159fd5a6028920832 adds the
required storage to be able to tell which storyboard element lives
where, so that it can be decoded properly later.
- In c9d3e04a4135886b5b0943c85f3cc6f4fe99c84c, the storyboard decoder is
weaved into the beatmap decoder to handle the `.osu` part of the
storyboard, via the
`LegacyStoryboardEncoder.Encode{General,Events}ToBeatmap()` methods. For
`.osb`s, `LegacyStoryboardEncoder.EncodeStandaloneStoryboard()` is
intended, but for now is not used outside tests.
- Because of the above, dd1c4e43dc51154cd67860f096712f8b4f229661 removes
`Beatmap.UnhandledEventLines` as no longer required.
- 26ac417ed98a8937c42e5f52c4e15ef065a48902 adds tests. They are mostly
handwritten to ensure basic encode-decode roundtripping. Using existing
storyboards is difficult, see "Known issues" section as to why.
- 5cc542366db7caac38eb0729260d884905a2c0d5 fixes a bug in the storyboard
decoder where the trigger group number was not properly negated on
decode (see inline comment reference to relevant stable code).
## Known issues
- Any and all variables in the `[Variables]` section are inlined into
their usages by `LegacyStoryboardDecoder`, and as such
`LegacyStoryboardEncoder` will end up inlining them and discarding the
`[Variables]` section. As far as I can tell stable will also do this.
- `LegacyStoryboardDecoder` splits all `M` (move) commands into
`MX`/`MY` commands. Therefore, `LegacyStoryboardEncoder` will write out
things in the same split way. I did not put in effort to attempt to
reconcile this, for reasons of part laziness, part not wanting to bloat
this already-large diff.
- Ordering of storyboard samples on decode may not match the order on
decode. I'm crossing fingers this doesn't matter.
Closes https://github.com/ppy/osu/issues/32420.
The failure cause here is that in editor the beatmap version for the
beatmap affected (or... any beatmap, really), is 0 (ZERO). That is
probably a regression from https://github.com/ppy/osu/pull/32315, but
like... can we universally agree that calling that change "a regression"
in any capacity is dumb? Like what was that code *doing* playing dumb
reference games and copying stuff into an arbitrary instance that could
get or not get used later on? And now you have a 50/50 chance of
accessing the *correct* model's field, depending on whether you go via
`BeatmapInfo` or `Beatmap.BeatmapInfo`?
Moving the field to `IBeatmap`, i.e. what is by now - by consensus,
since https://github.com/ppy/osu/pull/28473 - supposed to be the "decoded
and materialised" beatmap, fixes this issue.
I probably should have done this as part of
https://github.com/ppy/osu/pull/28473 but it slipped my mind. Probably
for the better too because this change has rather large chances of
breaking stuff so maybe better to examine it in isolation (via diffcalc
runs or whatever).
For added humour points, you'd say that the field on `BeatmapInfo` was
not `[Ignore]`d, so this is a realm schema change, right? No. As far as
I can tell, it's not. I opened realm studio and `BeatmapVersion` *is not
a listed column` on `Beatmap` models.
I'm also not gonna get into the fact that I think `EditorBeatmap` doing
dumb games with juggling two `BeatmapInfo` references since
https://github.com/ppy/osu/pull/15075 is bad, because I don't think I
have the mental capacity to hotfix this by going down that train of
thought.
Having these be separate implementations sounded awesome at the time,
but it only ever led to confusion. There's no practical difference if,
for example, catch sees hitobjects with `IHasPosition` instead of
`IHasXPosition`.
Closes https://github.com/ppy/osu/issues/28587.
As outlined in the issue thread, the tail volume wasn't saving because
it wasn't actually attached to a hitobject properly, and as such the
`LegacyBeatmapEncoder` logic, which is based on hitobjects, did not
pick them up on save.
To fix that, switch to using `NodeSamples` for objects that are
`IHasRepeats`. That has one added complication in that having it work
properly requires changes to the decode side too. That is because the
intent is to allow the user to change the sample settings for each node
(which are specified via `NodeSamples`), as well as "the rest of the
object", which generally means ticks or auxiliary samples like
`sliderslide` (which are specified by `Samples`).
However, up until now, `Samples` always queried the control point
which was _active at the end time of the slider_. This obviously can't
work anymore when converting `NodeSamples` to legacy control points,
because the last node's sample is _also_ at the end time of the slider.
To bypass that, add extra sample points after each node (just out of
reach of the 5ms leniency), which are supposed to control volume of
ticks and/or slides.
Upon testing, this *sort of* has the intended effect in stable, with
the exception of `sliderslide`, which seems to either respect or _not_
respect the relevant volume spec dependent on... not sure what, and not
sure I want to be debugging that. It might be frame alignment, or it
might be the phase of the moon.
Was added in cc76c58f5f without any
specific reasoning. Likely not required (and will fix some storyboard
elements inside `.osu` files from not being correctly saved).