Skip to content

Instantly share code, notes, and snippets.

@robby250
Last active February 4, 2025 15:23
Show Gist options
  • Save robby250/fc1a90db6cc4ed5dd9ccb4f592d8bae7 to your computer and use it in GitHub Desktop.
Save robby250/fc1a90db6cc4ed5dd9ccb4f592d8bae7 to your computer and use it in GitHub Desktop.
Convert osu skins to quaver

osu! to Quaver skin conversion

Table of Contents

skin.ini

Not included: any variables for 7k+1 or any variables not in the wiki

For the Quaver variables that don't have an osu! counterpart, a value that resembles osu's UI the most should be used (or just Quaver's default)

General

Quaver osu!
Name Name
Author Author
Version idk (it shouldn't be copied from osu lol)
CenterCursor CursorCentre (0 or 1) (if omitted default to 1)

Keys ([4K] or [7K])

Quaver osu! Comment
AccuracyDisplayPosX None
AccuracyDisplayPosY None
AccuracyDisplayScale None
BattleRoyaleAleretPosX None
BattleRoyaleAlertPosY None
BattleRoyaleAlertScale None
BattleRoyaleEliminatedPosX None
BattleRoyaleEliminatedPosY None
BgMaskAlpha None
BgMaskPadding None
ColorObjectsBySnapDistance None
ColumnAlignment See ColumnAlignment
ColumnColor{1-7} ColourLight{1-7}
ColumnLightingOffsetY See ColumnLightingOffsetY
ColumnLightingScale None
ColumnSize See ColumnSize
ComboDisplayScale None the size in osu is determined by the image resolution
ComboPosX None
ComboPosY ComboPosition
DeadNoteColor None I think default for osu is around 128,128,128?
DrawLongNoteEnd None is true by default in osu
FlipNoteEndImagesOnUpscroll NoteFlipWhenUpsideDown#T 0 or 1
FlipNoteImagesOnUpscroll NoteFlipWhenUpsideDown# 0 or 1
HealthBarKeysAlignment None
HealthBarType None
HitErrorChevronSize None
HitErrorHeight None
HitErrorPosX None
HitErrorPoxY None
HitLightingFps None AnimationFramerate doesn't affect mania lighting
HitLightingHeight None
HitLightingWidth See HitLightingWidth
HitLightingX None
HitLightingY See HitLightingY
HitPosOffsetY See HitPosOffsetY
HoldLightingFps None
JudgementBurstPosY See JudgementBurstPosY
JudgementCounterAlpha None
JudgementCounterFontColor None
JudgementCounterSize None The size in osu is determined by the image resolution
JudgementHitBurstScale None
KpsDisplayPosX None
KpsDisplayPosY None
KpsDisplayScale None
NotePadding None
RatingDisplayPosX None
RatingDisplayPosY None
RatingDisplayScale None
ReceptorPosOffsetY None
ReceptorsOverHitObjects KeysUnderNotes 0 or 1, the Quaver value needs to be the opposite of the osu value
ScoreDisplayPosX None
ScoreDisplayPosY None
ScoreDisplayScale None
SongTimeProgressActiveColor None
SongTimeProgressInactiveColor None
SongTimeProgressScale None
StageReceptorPadding See StageReceptorPadding
TimingLineColor ColourBarline RGB(a)

skin.ini variables in osu! that point to custom names/directories for images (see skin element list for more info):

  • KeyImage#
  • KeyImage#D
  • NoteImage#
  • NoteImage#H
  • NoteImage#L
  • NoteImage#T
  • StageLeft
  • StageRight
  • StageBottom
  • StageHint
  • StageLight
  • LightingN
  • LightingL
  • Hit0
  • Hit50
  • Hit100
  • Hit200
  • Hit300
  • Hit300g

Conversion formulas

1: use closest value for formula if outside range

ColumnAlignment

  • (Quaver) ColumnAlignment min/max:

    • -683 (left), +683 (right)
  • (osu!) ColumnStart min/max1:

    • 0 (left), 853.33 (on 16:9) (right)
  • Since this formula depends on Quaver's ColumnSize, the ColumnSize needs to be converted before this

  • ColumnWidth (osu!) is provided in the skin.ini as one width for each column, so WIDTHS represents the sum of all widths.

  • ColumnSize (Quaver) doesn't support multiple widths, so SIZES represents the ColumnSize * KeyCount (4 or 7)

  • ColumnAlignment = round(((1366 - SIZES) / 2) * ((-2 * ColumnStart)/(WIDTHS - (16/9 * 480)) - 1))

ColumnLightingOffsetY

  • (osu!) LightPosition min/max1:

    • 0 (top), 480 (bottom)
  • ColumnLightingOffsetY = round(768/480 * (480 - LightPosition) - (ColumnSize * {receptor-up-# height} / 100.2))

ColumnSize

  • (osu!) ColumnWidth
  • ColumnSize = round(ColumnWidth * 768/480)

I think Quaver/Quaver#1400 should be implemented first, so the ColumnWidths can be converted for each column.

ComboPosY

  • (osu!) ComboPosition min/max1:
    • 0 (top), 480 (bottom)
  • Quaver default (0) is middle of the screen (768/2)
  • ComboPosY = round(768/480 * (ComboPosition - 480) + 768/2)

HitLightingY

  • (osu!) HitPosition min/max1:
    • 0 (top), 480 (bottom)
  • HitLightingY = round(768/480 * (HitPosition - 480) + (ColumnSize * {receptor-up-# height} / 100.2 / 2))

HitLightingWidth

  • (osu!) LightingNWidth for notes, LightingLWidth for longnotes
  • HitLightingWidth = round(LightingNWidth * 768/480) (untested)

HitLightingY

The hitlighting is centered on the hitposition in osu!.

  • (osu!) HitPosition min/max1:
    • 0 (top), 480 (bottom)
  • HitLightingY = round(768/480 * (HitPosition - 480) + (ColumnSize * {receptor-up-# height} / 100.2 / 2))

HitPosOffsetY

  • (osu!) HitPosition min/max1:
    • 0 (top), 480 (bottom)
  • HitPosOffsetY = round(768/480 * (HitPosition - 480) + (ColumnSize * {receptor-up-# height} / 100.2))

JudgementBurstPosY

  • (osu!) ScorePosition min/max1:
    • 0 (top), 480 (bottom)
  • Quaver default (0) is middle of the screen (768/2)
  • ComboPosY = round(768/480 * (ScorePosition - 480) + 384)

StageReceptorPadding

  • (osu!) ColumnSpacing
  • StageReceptorPadding = round(ColumnSpacing * 768/480) (untested)

Images

If @2x images are found, then take those and scale them if necessary

4K

Section Quaver osu! Value if in skin.ini Comment
HitObjects note-hitobject1.png mania-note1.png NoteImage1
note-hitobject2.png mania-note2.png NoteImage2
note-hitobject3.png mania-note2.png NoteImage3
note-hitobject4.png mania-note1.png NoteImage4
note-holdbody-1.png mania-note1H.png NoteImage1H
note-holdbody-2.png mania-note2H.png NoteImage2H
note-holdbody-3.png mania-note2H.png NoteImage3H
note-holdbody-4.png mania-note1H.png NoteImage4H
note-holdend-1.png mania-note1T.png NoteImage1T
note-holdend-2.png mania-note2T.png NoteImage2T
note-holdend-3.png mania-note2T.png NoteImage3T
note-holdend-4.png mania-note1T.png NoteImage4T
note-holdhitobject-1.png mania-note1L.png NoteImage1L
note-holdhitobject-2.png mania-note2L.png NoteImage2L
note-holdhitobject-3.png mania-note2L.png NoteImage3L
note-holdhitobject-4.png mania-note1L.png NoteImage4L
Lighting column-lighting.png mania-stage-light.png StageLight
hitlighting@{rows}x{columns}.png LightingN-#.png (multiple images need to be merged into one)
holdlighting@{rows}x{columns}.png LightingL-#.png (multiple images need to be merged into one)
Receptors receptor-down-1.png mania-key1D.png KeyImage1D
receptor-down-2.png mania-key2D.png KeyImage2D
receptor-down-3.png mania-key2D.png KeyImage3D
receptor-down-4.png mania-key1D.png KeyImage4D
receptor-up-1.png mania-key1.png KeyImage1
receptor-up-2.png mania-key2.png KeyImage2
receptor-up-3.png mania-key2.png KeyImage3
receptor-up-4.png mania-key1.png KeyImage4
Stage stage-bgmask.png None not sure
stage-distant-overlay.png None not sure
stage-left-border.png mania-stage-left.png StageLeft
stage-right-border.png mania-stage-right.png StageRight
stage-hitposition-overlay.png mania-stage-hint.png needs scaling
Editor note-hitobject-{1-4}.png None
note-holdbody-{1-4}.png None
note-holdend-{1-4}.png None

7K

Section Quaver osu! skin.ini value Comment
HitObjects note-hitobject-1.png mania-note1.png NoteImage1
note-hitobject-2.png mania-note2.png NoteImage2
note-hitobject-3.png mania-note1.png NoteImage3
note-hitobject-4.png mania-noteS.png NoteImage4 if 8K then mania-note2.png
note-hitobject-5.png mania-note1.png NoteImage5
note-hitobject-6.png mania-note2.png NoteImage6
note-hitobject-7.png mania-note1.png NoteImage7
*note-hitobject-8.png mania-noteS.png not sure of the skin.ini variable
note-holdbody-1.png mania-note1H.png NoteImage1H
note-holdbody-2.png mania-note2H.png NoteImage2H
note-holdbody-3.png mania-note1H.png NoteImage3H
note-holdbody-4.png mania-noteSH.png NoteImage4H if 8K then mania-note2H.png
note-holdbody-5.png mania-note1H.png NoteImage5H
note-holdbody-6.png mania-note2H.png NoteImage6H
note-holdbody-7.png mania-note1H.png NoteImage7H
*note-holdbody-8.png mania-noteSH.png not sure of the skin.ini variable
note-holdend-1.png mania-note1T.png NoteImage1T
note-holdend-2.png mania-note2T.png NoteImage2T
note-holdend-3.png mania-note1T.png NoteImage3T
note-holdend-4.png mania-noteST.png NoteImage4T if 8K then mania-note2T.png
note-holdend-5.png mania-note1T.png NoteImage5T
note-holdend-6.png mania-note2T.png NoteImage6T
note-holdend-7.png mania-note1T.png NoteImage7T
*note-holdend-8.png mania-noteST.png not sure of the skin.ini variable
note-holdhitobject-1.png mania-note1L.png NoteImage1L
note-holdhitobject-2.png mania-note2L.png NoteImage2L
note-holdhitobject-3.png mania-note1L.png NoteImage3L
note-holdhitobject-4.png mania-noteSL.png NoteImage4L if 8K then mania-note2L.png
note-holdhitobject-5.png mania-note1L.png NoteImage5L
note-holdhitobject-6.png mania-note2L.png NoteImage6L
note-holdhitobject-7.png mania-note1L.png NoteImage7L
*note-holdhitobject-8.png mania-noteSL.png not sure of the skin.ini variable
Lighting column-lighting.png mania-stage-light.png StageLight
hitlighting@{rows}x{columns}.png LightingN-#.png multiple images need to be merged into one
holdlighting@{rows}x{columns}.png LightingL-#.png multiple images need to be merged into one
Receptors receptor-down-1.png mania-key1D.png KeyImage1D
receptor-down-2.png mania-key2D.png KeyImage2D
receptor-down-3.png mania-key1D.png KeyImage3D
receptor-down-4.png mania-keySD.png KeyImage4D if 8K then mania-key2D.png
receptor-down-5.png mania-key1D.png KeyImage5D
receptor-down-6.png mania-key2D.png KeyImage6D
receptor-down-7.png mania-key1D.png KeyImage7D
*receptor-down-8.png mania-keySD.png not sure of the skin.ini variable
receptor-up-1.png mania-key1.png KeyImage1
receptor-up-2.png mania-key2.png KeyImage2
receptor-up-3.png mania-key1.png KeyImage3
receptor-up-4.png mania-keyS.png KeyImage4 if 8K then mania-key2.png
receptor-up-5.png mania-key1.png KeyImage5
receptor-up-6.png mania-key2.png KeyImage6
receptor-up-7.png mania-key1.png KeyImage7
*receptor-up-8.png mania-keyS.png not sure of the skin.ini variable
Stage stage-bgmask.png None not sure, but should probably be black
stage-distant-overlay.png None not sure
stage-left-border.png mania-stage-left.png StageLeft
stage-right-border.png mania-stage-right.png StageRight
stage-hitposition-overlay.png mania-stage-hint.png needs scaling
Editor note-hitobject-{1-7}.png None
note-holdbody-{1-7}.png None
note-holdend-{1-7}.png None

Cursor

main-cursor.png -> cursor.png

Grades

not needed for conversion

Health

Quaver osu!
health-background.png scorebar-bg.png (needs to be rotated)
health-foreground.png scorebar-colour.png (needs to be rotated)

Judgements

Quaver osu! If animated If in skin.ini
judgement-overlay.png None
judge-marv.png mania-hit300g.png mania-hit300g-0.png Hit300g
judge-perf.png mania-hit300.png mania-hit300-0.png Hit300
judge-great.png mania-hit200.png mania-hit200-0.png Hit200
judge-good.png mania-hit100.png mania-hit100-0.png Hit100
judge-okay.png mania-hit50.png mania-hit50-0.png Hit50
judge-miss.png mania-hit0.png mania-hit0-0.png Hit0

Numbers

Quaver osu! If in skin.ini under [Fonts]
combo-{0-9}.png score-{0-9}.png ComboPrefix
score-{0-9}.png score-{0-9}.png ScorePrefix
score-percent.png score-percent.png ScorePrefix
score-decimal.png score-dot.png ScorePrefix
song-time-{0-9}.png None
song-time-colon.png None
song-time-minus.png None

Pause

Quaver osu!
pause-continue.png pause-continue.png
pause-retry.png pause-retry.png
pause-back.png pause-back.png
pause-background.png pause-overlay.png

Scoreboard

not needed for conversion

SFX (sounds can also be .mp3 but .wav has priority)

Quaver osu!
sound-click.wav click-short-confirm.wav (?)
sound-back.wav menuback.wav
sound-hover.wav click-short.wav (?)
sound-applause.wav applause.mp3
sound-hit.wav normal-hitnormal.wav
sound-hitclap.wav normal-hitclap.wav
sound-hitwhistle.wav normal-hitwhistle.wav
sound-hitfinish.wav normal-hitfinish.wav
sound-combobreak.wav combobreak.wav
sound-failure.wav failsound.mp3
sound-retry.wav pause-retry-click.wav
sound-combo-alert-1.wav comboburst(-n).wav

More information

@Janko5
Copy link

Janko5 commented Jul 19, 2020

here should be JudgementBurstPosY =

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment