Skip to content

feat: osu!mania -> quaver reverse conversion (+ combo/positioning fixes) - #5

Merged
dromzeh merged 4 commits into
mainfrom
marc/feat/reverse-conversion
Jul 24, 2026
Merged

feat: osu!mania -> quaver reverse conversion (+ combo/positioning fixes)#5
dromzeh merged 4 commits into
mainfrom
marc/feat/reverse-conversion

Conversation

@dromzeh

@dromzeh dromzeh commented Jul 24, 2026

Copy link
Copy Markdown
Owner

closes #2, closes #3, closes #4

three for one: both open fixes plus the reverse direction. the fun part - the gist formulas are the osu!->quaver direction already (the existing converters are their inverses), so the reverse coordinate math was basically free and round-trips exactly (there's a test: ComboPosY -> ComboPosition -> ComboPosY is lossless).

the fixes

  • combo colour during LNs (ln combo colour changes instead of static consistent #3) - osu! tints the combo counter with ColourHold (default orange 255,191,51) while a hold is pressed; quaver never touches it. every [Mania] block now writes a white ColourHold so it stays static.
  • perfect/combo positioning (perfect/combo values positioning not exact 1:1 #2) - turned out to be a defaults bug, not a formula bug. checked the math against lazer's ManiaLegacySkinTransformer + LegacyManiaJudgementPiece (both centre-anchored at N*1.6 from screen top) and quaver's GameplayPlayfieldKeysStage (MidCenter + offset) - the existing gist-inverse formulas are already exact. the real issue: a skin.ini that omits ComboPosY/JudgementBurstPosY inherits the default skin's values in quaver (-40 / 108 in bar, arrow and circle alike), and we assumed 0 - judgements ~68px and combo ~25px off in osu! space for those skins.

how the reverse works

  • detection - auto-detected from the input's skin.ini: [Mania] blocks = osu! skin, [4K]/[7K] = quaver. .osk in, .qs out (folder + archive, --open installs in quaver).
  • skin.ini - new osu! parser (Key: Value, repeated [Mania] blocks keyed by Keys, // comments) and a quaver Key = Value writer. [Mania] geometry maps to [4K]/[7K] via the gist's forward formulas.
  • assets - per-column notes/holds/receptors honouring skin.ini overrides, osu!'s default mania-note1/2/S per-column styles, and @2x fallbacks (halved back to @1x metrics). LN tails flip back, health bars rotate back to vertical, lighting animations get recomposed into quaver's @1xN spritesheets, judgements/fonts/grades/hitsounds all map back.
  • receptors - written ColumnSize wide at their osu! pixel height, so quaver's aspect scaling reproduces osu!'s drawn size - which also gives an exact HitPosOffsetY back out of HitPosition.

notes

  • stage hint is copied unchanged: osu! centres it on the hit line, quaver bottom-anchors it, so content below the line can't be represented - flagged in the report instead of silently cropping.
  • animated hold bodies take frame 0, hitsounds are .wav-only - both match what the forward direction already does.
  • osu!-only files (standard mode, menus, ...) are skipped and counted in the report.

test

  • go test ./... - osu! parse test, reverse coordinate goldens + round-trip, and a reverse end-to-end over a synthetic .osk (overrides + default filenames, flipped tail, rotated health, sheet sizes)
  • built the exe and round-tripped a skin both directions: direction auto-detected, ComboPosY -120 / JudgementBurstPosY -85 came back exactly
  • not yet eyeballed in-game (parsec) - worth a look before merge

@dromzeh

dromzeh commented Jul 24, 2026

Copy link
Copy Markdown
Owner Author

so sorry to the people i accidentally @'d my bad guys

@dromzeh
dromzeh marked this pull request as ready for review July 24, 2026 10:05
@dromzeh
dromzeh merged commit 5a9646b into main Jul 24, 2026
1 check passed
@dromzeh
dromzeh deleted the marc/feat/reverse-conversion branch July 24, 2026 10:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vice versa support (osu!mania -> quaver) ln combo colour changes instead of static consistent perfect/combo values positioning not exact 1:1

1 participant