2021-08-07 20:35:00 +02:00
require ( ' common ' )
2021-08-21 13:52:40 +02:00
local Easing = require ( ' common.easings ' )
local Background = require ( ' components.background ' ) ;
2021-08-09 20:48:31 +02:00
2021-08-12 21:21:42 +02:00
local VolforceCalc = require ( ' components.volforceCalc ' ) ;
2021-07-30 16:37:01 +02:00
local backgroundImage = gfx.CreateSkinImage ( " song_select/bg.png " , 1 )
2021-08-01 20:00:45 +02:00
local dataPanelImage = gfx.CreateSkinImage ( " song_select/data_bg_overlay.png " , 1 )
local dataGlowOverlayImage = gfx.CreateSkinImage ( " song_select/data_panel/data_glow_overlay.png " , 1 )
local gradeBgImage = gfx.CreateSkinImage ( " song_select/data_panel/grade_bg.png " , 1 )
local badgeBgImage = gfx.CreateSkinImage ( " song_select/data_panel/clear_badge_bg.png " , 1 )
local effectedBgImage = gfx.CreateSkinImage ( " song_select/data_panel/effected_bg.png " , 1 )
local illustratedBgImage = gfx.CreateSkinImage ( " song_select/data_panel/illust_bg.png " , 1 )
2021-07-30 16:37:01 +02:00
local songPlateBg = gfx.CreateSkinImage ( " song_select/plate/bg.png " , 1 )
local songPlateBottomBarOverlayImage = gfx.CreateSkinImage ( " song_select/plate/bottom_bar_overlay.png " , 1 )
2021-08-16 15:58:28 +02:00
2021-08-16 16:29:21 +02:00
local laserAnimBaseImage = gfx.CreateSkinImage ( " song_select/laser_anim.png " , 1 )
2021-08-16 15:50:53 +02:00
local top50OverlayImage = gfx.CreateSkinImage ( " song_select/top50.png " , 1 )
2021-08-16 15:58:28 +02:00
local top50JacketOverlayImage = gfx.CreateSkinImage ( " song_select/top50_jacket.png " , 1 )
2021-07-30 16:37:01 +02:00
2021-08-12 15:33:47 +02:00
local cursorImages = {
gfx.CreateSkinImage ( " song_select/cursor.png " , 1 ) , -- Effective rate or fallback
gfx.CreateSkinImage ( " song_select/cursor_exc.png " , 1 ) , -- Excessive rate
2021-08-12 17:18:35 +02:00
gfx.CreateSkinImage ( " song_select/cursor_perm.png " , 1 ) , -- Premissive rate
gfx.CreateSkinImage ( " song_select/cursor_blast.png " , 1 ) , -- Blastive rate
2021-08-12 15:33:47 +02:00
}
2021-07-31 22:53:05 +02:00
local diffCursorImage = gfx.CreateSkinImage ( " song_select/level_cursor.png " , 1 )
2021-07-30 18:27:43 +02:00
2021-08-13 17:35:26 +02:00
local filterInfoBgImage = gfx.CreateSkinImage ( " song_select/filter_info_bg.png " , 1 )
2021-08-14 17:49:12 +02:00
local sortInfoBgImage = gfx.CreateSkinImage ( " song_select/sort_info_bg.png " , 1 )
2021-08-13 17:35:26 +02:00
2021-08-05 22:01:17 +02:00
local searchBgImage = gfx.CreateSkinImage ( " song_select/search_bg.png " , 1 )
2021-07-30 18:40:49 +02:00
local defaultJacketImage = gfx.CreateSkinImage ( " song_select/loading.png " , 0 )
2021-07-30 16:37:01 +02:00
local difficultyLabelImages = {
gfx.CreateSkinImage ( " song_select/plate/difficulty_labels/novice.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/plate/difficulty_labels/advanced.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/plate/difficulty_labels/exhaust.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/plate/difficulty_labels/maximum.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/plate/difficulty_labels/infinite.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/plate/difficulty_labels/gravity.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/plate/difficulty_labels/heavenly.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/plate/difficulty_labels/vivid.png " , 1 ) ,
2021-07-25 20:10:06 +02:00
}
2021-07-30 18:27:43 +02:00
local badgeImages = {
gfx.CreateSkinImage ( " song_select/medal/nomedal.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/medal/played.png " , 1 ) ,
2021-07-30 18:40:49 +02:00
gfx.CreateSkinImage ( " song_select/medal/clear.png " , 1 ) ,
2021-07-30 18:27:43 +02:00
gfx.CreateSkinImage ( " song_select/medal/hard.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/medal/uc.png " , 1 ) ,
gfx.CreateSkinImage ( " song_select/medal/puc.png " , 1 ) ,
}
2021-07-31 18:43:17 +02:00
local gradeCutoffs = {
D = 0000000 ,
C = 7000000 ,
B = 8000000 ,
A = 8700000 ,
A_P = 9000000 ,
AA = 9300000 ,
AA_P = 9500000 ,
AAA = 9700000 ,
AAA_P = 9800000 ,
S = 9900000 ,
}
local gradeImages = {
S = gfx.CreateSkinImage ( " common/grades/S.png " , 0 ) ,
AAA_P = gfx.CreateSkinImage ( " common/grades/AAA+.png " , 0 ) ,
AAA = gfx.CreateSkinImage ( " common/grades/AAA.png " , 0 ) ,
AA_P = gfx.CreateSkinImage ( " common/grades/AA+.png " , 0 ) ,
AA = gfx.CreateSkinImage ( " common/grades/AA.png " , 0 ) ,
A_P = gfx.CreateSkinImage ( " common/grades/A+.png " , 0 ) ,
A = gfx.CreateSkinImage ( " common/grades/A.png " , 0 ) ,
B = gfx.CreateSkinImage ( " common/grades/B.png " , 0 ) ,
C = gfx.CreateSkinImage ( " common/grades/C.png " , 0 ) ,
D = gfx.CreateSkinImage ( " common/grades/D.png " , 0 ) ,
none = gfx.CreateSkinImage ( " common/grades/none.png " , 0 ) ,
}
2021-07-31 22:53:05 +02:00
local difficultyLabelUnderImages = {
gfx.CreateSkinImage ( " songtransition/difficulty_labels/nov.png " , 0 ) ,
gfx.CreateSkinImage ( " songtransition/difficulty_labels/adv.png " , 0 ) ,
gfx.CreateSkinImage ( " songtransition/difficulty_labels/exh.png " , 0 ) ,
gfx.CreateSkinImage ( " songtransition/difficulty_labels/mxm.png " , 0 ) ,
gfx.CreateSkinImage ( " songtransition/difficulty_labels/inf.png " , 0 ) ,
gfx.CreateSkinImage ( " songtransition/difficulty_labels/grv.png " , 0 ) ,
gfx.CreateSkinImage ( " songtransition/difficulty_labels/hvn.png " , 0 ) ,
gfx.CreateSkinImage ( " songtransition/difficulty_labels/vvd.png " , 0 ) ,
}
2021-07-30 22:06:08 +02:00
game.LoadSkinSample ( ' song_wheel/cursor_change.wav ' ) ;
2021-08-12 14:29:55 +02:00
game.LoadSkinSample ( ' song_wheel/diff_change.wav ' ) ;
2021-07-30 22:06:08 +02:00
2021-07-30 16:37:01 +02:00
local difficultyNumbers ;
2021-07-31 20:36:05 +02:00
local scoreNumbers ;
2021-07-25 20:10:06 +02:00
2021-07-30 16:37:01 +02:00
local resx , resy = game.GetResolution ( )
local desw , desh ;
local scale ;
2021-07-25 20:10:06 +02:00
2021-07-30 21:34:36 +02:00
local songPlateHeight = 172 ;
2021-07-30 16:37:01 +02:00
local selectedIndex = 1 ;
local selectedDifficulty = 1 ;
2021-07-25 20:10:06 +02:00
2021-07-30 16:37:01 +02:00
local jacketCache = { }
2021-07-25 20:10:06 +02:00
2021-08-16 15:50:53 +02:00
local top50diffs = { }
2021-07-30 21:34:36 +02:00
local transitionScrollScale = 0 ;
local transitionScrollOffsetY = 0 ;
local scrollingUp = false ;
2021-07-31 22:14:34 +02:00
local transitionAfterscrollScale = 0 ;
local transitionAfterscrollDataOverlayAlpha = 0 ;
local transitionAfterscrollGradeAlpha = 0 ;
local transitionAfterscrollBadgeAlpha = 0 ;
2021-08-01 18:08:52 +02:00
local transitionAfterscrollTextSongTitle = 0 ;
local transitionAfterscrollTextSongArtist = 0 ;
2021-07-31 23:00:32 +02:00
local transitionAfterscrollDifficultiesAlpha = 0 ;
2021-08-01 18:08:52 +02:00
local transitionAfterscrollJacketBgAlpha = 0 ;
2021-07-31 22:14:34 +02:00
2021-08-16 16:29:21 +02:00
local transitionLaserScale = 0 ;
local transitionLaserY = 0 ;
2021-08-12 17:18:35 +02:00
local transitionLeaveReverse = false ;
2021-08-12 16:55:10 +02:00
local transitionLeaveScale = 0 ;
local transitionLeaveOffsetY = 0 ;
2021-08-09 20:48:31 +02:00
2021-07-30 16:37:01 +02:00
function resetLayoutInformation ( )
resx , resy = game.GetResolution ( )
desw = 1080
desh = 1920
scale = resx / desw
2021-07-25 20:10:06 +02:00
end
2021-07-30 16:37:01 +02:00
function load_number_image ( path )
local images = { }
for i = 0 , 9 do
images [ i + 1 ] = gfx.CreateSkinImage ( string.format ( " %s/%d.png " , path , i ) , 0 )
2021-07-25 20:10:06 +02:00
end
2021-07-30 16:37:01 +02:00
return images
2021-07-25 20:10:06 +02:00
end
2021-07-30 16:37:01 +02:00
function draw_number ( x , y , alpha , num , digits , images , is_dim , scale , kern )
scale = scale or 1 ;
kern = kern or 1 ;
local tw , th = gfx.ImageSize ( images [ 1 ] )
tw = tw * scale ;
th = th * scale ;
x = x + ( tw * ( digits - 1 ) ) / 2
y = y - th / 2
for i = 1 , digits do
local mul = 10 ^ ( i - 1 )
local digit = math.floor ( num / mul ) % 10
local a = alpha
if is_dim and num < mul then
a = 0.4
2021-07-25 20:10:06 +02:00
end
gfx.BeginPath ( )
2021-07-30 16:37:01 +02:00
gfx.ImageRect ( x , y , tw , th , images [ digit + 1 ] , a , 0 )
x = x - ( tw * kern )
2021-07-25 20:10:06 +02:00
end
end
2021-07-30 20:18:03 +02:00
function getCorrectedIndex ( from , offset )
total = # songwheel.songs ;
2021-08-12 22:34:38 +02:00
if ( math.abs ( offset ) > total ) then
if ( offset < 0 ) then
offset = offset + total * math.floor ( math.abs ( offset ) / total ) ;
else
offset = offset - total * math.floor ( math.abs ( offset ) / total ) ;
end
end
2021-07-30 20:18:03 +02:00
index = from + offset ;
if index < 1 then
index = total + ( from + offset ) -- this only happens if the offset is negative
end ;
if index > total then
indexesUntilEnd = total - from ;
index = offset - indexesUntilEnd -- this only happens if the offset is positive
end ;
return index ;
end ;
2021-07-30 16:37:01 +02:00
function getJacketImage ( song )
2021-07-31 19:36:47 +02:00
if not jacketCache [ song.id ] or jacketCache [ song.id ] == defaultJacketImage then
2021-08-13 22:36:21 +02:00
jacketCache [ song.id ] = gfx.LoadImageJob ( song.difficulties [
math.min ( selectedDifficulty , # song.difficulties )
] . jacketPath , defaultJacketImage , 500 , 500 ) ;
2021-07-25 20:10:06 +02:00
end
2021-07-30 16:37:01 +02:00
return jacketCache [ song.id ] ;
2021-07-25 20:10:06 +02:00
end
2021-07-31 18:43:17 +02:00
function getGradeImageForScore ( score )
local gradeImage = gradeImages.none ;
local bestGradeCutoff = 0 ;
for gradeName , scoreCutoff in pairs ( gradeCutoffs ) do
if scoreCutoff <= score then
if scoreCutoff > bestGradeCutoff then
gradeImage = gradeImages [ gradeName ] ;
bestGradeCutoff = scoreCutoff ;
end
end
end
return gradeImage ;
end
2021-08-16 16:29:21 +02:00
function drawLaserAnim ( )
gfx.BeginPath ( )
gfx.Scissor ( 0 , transitionLaserY , desw , 100 ) ;
gfx.ImageRect ( 0 , 0 , desw , desh , laserAnimBaseImage , 1 , 0 )
gfx.ResetScissor ( ) ;
end
2021-08-02 19:55:17 +02:00
function drawBackground ( deltaTime )
2021-08-21 13:52:40 +02:00
Background.draw ( deltaTime )
2021-08-11 20:00:35 +02:00
2021-07-31 20:36:05 +02:00
-- If the score for song exists
local song = songwheel.songs [ selectedIndex ] ;
2021-08-12 11:52:37 +02:00
local diff = song and song.difficulties [ selectedDifficulty ] or false ;
2021-08-01 20:00:45 +02:00
if song and diff then
2021-08-01 18:08:52 +02:00
local jacketImage = getJacketImage ( song ) ;
2021-07-31 20:36:05 +02:00
gfx.BeginPath ( )
2021-08-06 20:04:34 +02:00
gfx.ImageRect ( 0 + transitionAfterscrollScale *- 300 , 0 , 900 , 900 , jacketImage or defaultJacketImage , transitionAfterscrollJacketBgAlpha , 0 )
gfx.BeginPath ( ) ;
gfx.FillColor ( 0 , 0 , 0 , math.floor ( transitionAfterscrollJacketBgAlpha * 64 ) ) ;
gfx.Rect ( 0 , 0 , 900 , 900 ) ;
gfx.Fill ( ) ;
gfx.ClosePath ( ) ;
gfx.BeginPath ( ) ;
2021-08-01 20:00:45 +02:00
end
2021-08-11 20:00:35 +02:00
2021-08-01 20:00:45 +02:00
gfx.ImageRect ( 0 , 0 , desw , desh , dataPanelImage , 1 , 0 )
2021-08-16 16:29:21 +02:00
drawLaserAnim ( )
2021-08-11 20:00:35 +02:00
2021-08-01 20:00:45 +02:00
if song and diff then
gfx.BeginPath ( )
gfx.ImageRect ( 0 , 0 , desw , desh , dataGlowOverlayImage , transitionAfterscrollDataOverlayAlpha , 0 )
gfx.BeginPath ( )
gfx.ImageRect ( 341 , 754 , 85 , 85 , gradeBgImage , transitionAfterscrollDataOverlayAlpha , 0 )
gfx.BeginPath ( )
gfx.ImageRect ( 391 , 687 , 180 * 0.85 , 226 * 0.85 , badgeBgImage , transitionAfterscrollDataOverlayAlpha , 0 )
gfx.BeginPath ( )
gfx.ImageRect ( 95 , 1165 , 433 , 30 , effectedBgImage , transitionAfterscrollDataOverlayAlpha , 0 )
gfx.BeginPath ( )
gfx.ImageRect ( 95 , 1195 , 433 , 30 , illustratedBgImage , transitionAfterscrollDataOverlayAlpha , 0 )
2021-07-31 20:36:05 +02:00
end
2021-08-02 19:55:17 +02:00
2021-07-25 20:10:06 +02:00
end
2021-07-30 16:37:01 +02:00
function drawSong ( song , y )
2021-07-31 20:36:05 +02:00
if ( not song ) then return end ;
2021-07-30 16:37:01 +02:00
local songX = desw / 2 + 28
2021-08-12 21:47:16 +02:00
local selectedSongDifficulty = song.difficulties [ math.min ( selectedDifficulty , # song.difficulties ) ] -- Limit selecting difficulty that is above the number that the song has
2021-07-31 18:43:17 +02:00
if not selectedSongDifficulty then
return ;
end
local bestScore ;
if selectedSongDifficulty.scores then
bestScore = selectedSongDifficulty.scores [ 1 ] ;
end
2021-07-25 20:10:06 +02:00
2021-07-30 16:37:01 +02:00
-- Draw the bg for the song plate
gfx.BeginPath ( )
2021-07-30 16:42:01 +02:00
gfx.ImageRect ( songX , y , 515 , 172 , songPlateBg , 1 , 0 )
2021-07-30 16:37:01 +02:00
-- Draw jacket
local jacketImage = getJacketImage ( song ) ;
gfx.BeginPath ( )
2021-07-30 18:40:49 +02:00
gfx.ImageRect ( songX + 4 , y + 4 , 163 , 163 , jacketImage or defaultJacketImage , 1 , 0 )
2021-07-25 20:10:06 +02:00
2021-07-30 16:37:01 +02:00
-- Draw the overlay for the song plate (that bottom black bar)
gfx.BeginPath ( )
2021-07-30 16:42:01 +02:00
gfx.ImageRect ( songX , y , 515 , 172 , songPlateBottomBarOverlayImage , 1 , 0 )
2021-07-30 16:37:01 +02:00
-- Draw the difficulty notch background
2021-07-25 20:10:06 +02:00
gfx.BeginPath ( )
2021-08-07 20:35:00 +02:00
local diffIndex = GetDisplayDifficulty ( selectedSongDifficulty.jacketPath , selectedSongDifficulty.difficulty )
gfx.ImageRect ( songX , y + 95 , 83 , 74 , difficultyLabelImages [ diffIndex ] , 1 , 0 )
2021-07-25 20:10:06 +02:00
2021-07-30 16:37:01 +02:00
-- Draw the difficulty level number
gfx.BeginPath ( )
2021-07-30 18:27:43 +02:00
draw_number ( songX + 30 , y + 125 , 1.0 , selectedSongDifficulty.level , 2 , difficultyNumbers , false , 0.65 , 1 )
2021-07-30 22:10:04 +02:00
-- Draw song title
gfx.FontSize ( 24 )
gfx.TextAlign ( gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE )
gfx.Text ( song.title , songX + 90 , y + 155 ) ;
2021-07-30 18:27:43 +02:00
-- Draw score badge
local badgeImage = badgeImages [ 1 ] ;
2021-08-12 18:08:27 +02:00
if selectedSongDifficulty.topBadge then
badgeImage = badgeImages [ selectedSongDifficulty.topBadge + 1 ] ;
2021-07-30 18:27:43 +02:00
end
gfx.BeginPath ( )
gfx.ImageRect ( songX + 282 , y + 44 , 79 , 69 , badgeImage , 1 , 0 )
2021-07-31 18:43:17 +02:00
-- Draw grade
local gradeImage = gradeImages.none ;
if bestScore then
gradeImage = getGradeImageForScore ( bestScore.score )
end
gfx.BeginPath ( ) ;
2021-08-12 22:39:03 +02:00
gfx.ImageRect ( songX + 391 , y + 47 , 60 , 60 , gradeImage , 1 , 0 ) ;
2021-07-31 18:43:17 +02:00
2021-08-16 15:50:53 +02:00
-- Draw top 50 label if applicable
if ( top50diffs [ selectedSongDifficulty.id ] ) then
gfx.BeginPath ( ) ;
gfx.ImageRect ( songX + 82 , y + 109 , 506 * 0.85 , 26 * 0.85 , top50OverlayImage , 1 , 0 ) ;
end
2021-07-25 20:10:06 +02:00
end
2021-07-30 16:37:01 +02:00
function drawSongList ( )
2021-07-30 21:34:36 +02:00
local numOfSongsAround = 7 ; -- How many songs should be up and how many should be down of the selected one
2021-08-12 16:55:10 +02:00
local yOffset = transitionLeaveOffsetY + transitionScrollOffsetY ;
2021-07-30 20:07:04 +02:00
local i = 1 ;
while ( i <= numOfSongsAround ) do
2021-07-30 20:18:03 +02:00
local songIndex = getCorrectedIndex ( selectedIndex , - i )
2021-08-12 16:55:10 +02:00
drawSong ( songwheel.songs [ songIndex ] , desh / 2 - songPlateHeight / 2 - songPlateHeight * i + yOffset )
2021-07-30 20:07:04 +02:00
i = i + 1 ;
end ;
-- Draw the selected song
2021-08-12 16:55:10 +02:00
drawSong ( songwheel.songs [ selectedIndex ] , desh / 2 - songPlateHeight / 2 + yOffset )
2021-07-30 20:07:04 +02:00
i = 1 ;
while ( i <= numOfSongsAround ) do
2021-07-30 20:18:03 +02:00
local songIndex = getCorrectedIndex ( selectedIndex , i )
2021-08-12 16:55:10 +02:00
drawSong ( songwheel.songs [ songIndex ] , desh / 2 - songPlateHeight / 2 + songPlateHeight * i + yOffset )
2021-07-30 20:07:04 +02:00
i = i + 1 ;
end ;
2021-07-25 20:10:06 +02:00
end
2021-07-30 18:27:43 +02:00
function drawCursor ( )
gfx.BeginPath ( )
2021-08-12 15:33:47 +02:00
local cursorImageIndex = game.GetSkinSetting ( ' _gaugeType ' )
local cursorImage = cursorImages [ cursorImageIndex or 1 ] ;
2021-07-30 18:27:43 +02:00
gfx.ImageRect ( desw / 2 - 14 , desh / 2 - 213 / 2 , 555 , 213 , cursorImage , 1 , 0 )
end
2021-07-31 20:36:05 +02:00
local scoreNumbers = load_number_image ( " score_num " ) ;
function drawData ( ) -- Draws the song data on the left panel
local song = songwheel.songs [ selectedIndex ] ;
2021-08-12 11:52:37 +02:00
local diff = song and song.difficulties [ selectedDifficulty ] or false ;
local bestScore = diff and diff.scores [ 1 ] ;
if not song then return false end
2021-07-31 20:36:05 +02:00
local jacketImage = getJacketImage ( song ) ;
gfx.BeginPath ( )
gfx.ImageRect ( 96 , 324 , 348 , 348 , jacketImage or defaultJacketImage , 1 , 0 )
2021-08-16 15:58:28 +02:00
if ( top50diffs [ diff.id ] ) then
gfx.BeginPath ( )
gfx.ImageRect ( 96 , 529 , 410 * 0.85 , 168 * 0.85 , top50JacketOverlayImage , 1 , 0 )
end
2021-07-31 20:36:05 +02:00
2021-07-31 22:14:34 +02:00
gfx.Save ( )
2021-07-31 20:36:05 +02:00
if bestScore then
-- Draw best score
gfx.BeginPath ( )
draw_number ( 100 , 793 , 1.0 , math.floor ( bestScore.score / 10000 ) , 4 , scoreNumbers , true , 0.3 , 1.12 )
2021-08-14 12:03:46 +02:00
draw_number ( 253 , 798 , 1.0 , bestScore.score , 4 , scoreNumbers , true , 0.22 , 1.12 )
2021-07-31 20:36:05 +02:00
-- Draw grade
local gradeImage = gradeImages.none ;
if bestScore then
gradeImage = getGradeImageForScore ( bestScore.score )
end
gfx.BeginPath ( ) ;
2021-07-31 22:14:34 +02:00
gfx.ImageRect ( 360 , 773 , 45 , 45 , gradeImage , transitionAfterscrollGradeAlpha , 0 ) ;
2021-07-31 20:36:05 +02:00
-- Draw badge
2021-08-12 18:08:27 +02:00
badgeImage = badgeImages [ diff.topBadge + 1 ] ;
2021-07-31 20:36:05 +02:00
gfx.BeginPath ( )
2021-07-31 22:14:34 +02:00
gfx.ImageRect ( 425 , 724 , 93 / 1.1 , 81 / 1.1 , badgeImage , transitionAfterscrollBadgeAlpha , 0 )
2021-07-31 20:36:05 +02:00
end
2021-07-31 22:14:34 +02:00
gfx.Restore ( )
2021-07-31 20:36:05 +02:00
-- Draw BPM
2021-07-31 22:14:34 +02:00
gfx.BeginPath ( ) ;
2021-07-31 20:36:05 +02:00
gfx.FontSize ( 24 )
gfx.TextAlign ( gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE )
gfx.Save ( )
gfx.LoadSkinFont ( ' Digital-Serial-Bold.ttf ' )
2021-08-01 18:08:52 +02:00
gfx.GlobalAlpha ( transitionAfterscrollDataOverlayAlpha ) -- TODO: split this out
2021-07-31 20:36:05 +02:00
gfx.Text ( song.bpm , 85 , 920 ) ;
gfx.Restore ( )
-- Draw song title
gfx.FontSize ( 28 )
2021-08-01 18:08:52 +02:00
gfx.GlobalAlpha ( transitionAfterscrollTextSongTitle ) ;
gfx.Text ( song.title , 30 + ( 1 - transitionAfterscrollTextSongTitle ) * 20 , 955 ) ;
2021-07-31 20:36:05 +02:00
-- Draw artist
2021-08-01 18:08:52 +02:00
gfx.GlobalAlpha ( transitionAfterscrollTextSongArtist ) ;
2021-08-06 20:06:35 +02:00
gfx.Text ( song.artist , 30 + ( 1 - transitionAfterscrollTextSongArtist ) * 30 , 997 ) ;
2021-08-01 18:08:52 +02:00
gfx.GlobalAlpha ( 1 ) ;
2021-07-31 22:53:05 +02:00
-- Draw difficulties
local DIFF_X_START = 98.5
local DIFF_GAP = 114.8 ;
2021-07-31 23:00:32 +02:00
gfx.GlobalAlpha ( transitionAfterscrollDifficultiesAlpha ) ;
2021-08-12 15:53:29 +02:00
for i , diff in ipairs ( song.difficulties ) do
2021-07-31 22:53:05 +02:00
gfx.BeginPath ( )
2021-08-12 15:53:29 +02:00
local index = diff.difficulty + 1
if i == selectedDifficulty then
2021-07-31 22:53:05 +02:00
gfx.ImageRect ( DIFF_X_START + ( index - 1 ) * DIFF_GAP - ( 163 * 0.8 ) / 2 , 1028 , 163 * 0.8 , 163 * 0.8 , diffCursorImage , 1 , 0 )
end
draw_number ( 85 + ( index - 1 ) * DIFF_GAP , 1085 , 1.0 , diff.level , 2 , difficultyNumbers , false , 0.8 , 1 )
2021-08-07 20:35:00 +02:00
local diffLabelImage = difficultyLabelUnderImages [
GetDisplayDifficulty ( diff.jacketPath , diff.difficulty )
] ;
2021-07-31 22:53:05 +02:00
local tw , th = gfx.ImageSize ( diffLabelImage )
tw = tw * 0.9
th = th * 0.9
gfx.BeginPath ( )
gfx.ImageRect ( DIFF_X_START + ( index - 1 ) * DIFF_GAP - tw / 2 , 1050 , tw , th , diffLabelImage , 1 , 0 )
end
2021-07-31 23:00:32 +02:00
gfx.GlobalAlpha ( 1 ) ;
2021-08-01 20:07:48 +02:00
gfx.FontSize ( 22 )
gfx.GlobalAlpha ( transitionAfterscrollDataOverlayAlpha ) ;
gfx.Text ( diff.effector , 270 , 1180 ) ;
gfx.Text ( diff.illustrator , 270 , 1210 ) ;
gfx.GlobalAlpha ( 1 ) ;
2021-07-31 20:36:05 +02:00
end
2021-08-13 17:35:26 +02:00
function drawFilterInfo ( deltatime )
gfx.BeginPath ( )
gfx.ImageRect ( 5 , 95 , 417 * 0.85 , 163 * 0.85 , filterInfoBgImage , 1 , 0 )
local folderLabel = game.GetSkinSetting ( ' _songWheelActiveFolderLabel ' )
local subFolderLabel = game.GetSkinSetting ( ' _songWheelActiveSubFolderLabel ' )
2021-08-14 17:49:12 +02:00
local sortOptionLabel = game.GetSkinSetting ( ' _songWheelActiveSortOptionLabel ' )
2021-08-13 17:35:26 +02:00
gfx.FontSize ( 24 )
gfx.TextAlign ( gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE )
2021-08-14 17:49:12 +02:00
2021-08-13 17:35:26 +02:00
gfx.BeginPath ( )
2021-08-13 22:36:21 +02:00
gfx.Text ( folderLabel or ' ' , 167 , 131 ) ;
2021-08-14 17:49:12 +02:00
2021-08-13 17:35:26 +02:00
gfx.BeginPath ( )
2021-08-13 22:36:21 +02:00
gfx.Text ( subFolderLabel or ' ' , 195 , 166 ) ;
2021-08-14 17:49:12 +02:00
gfx.BeginPath ( )
gfx.ImageRect ( desw - 310 - 5 , 108 , 310 , 75 , sortInfoBgImage , 1 , 0 )
gfx.BeginPath ( )
2021-08-14 17:52:04 +02:00
gfx.Text ( sortOptionLabel or ' ' , desw - 150 , 130 ) ;
2021-08-13 17:35:26 +02:00
end
2021-08-05 22:01:17 +02:00
function drawSearch ( )
if ( not songwheel.searchInputActive ) then
return ;
end
gfx.BeginPath ( ) ;
local tw , th = gfx.ImageSize ( searchBgImage )
gfx.ImageRect ( desw - tw / 2 , 0 , tw / 2 , th / 2 , searchBgImage , 1 , 0 )
gfx.FontSize ( 28 ) ;
gfx.Text ( songwheel.searchText , desw - 200 , 30 ) ;
end
2021-07-30 21:34:36 +02:00
function tickTransitions ( deltaTime )
if transitionScrollScale < 1 then
transitionScrollScale = transitionScrollScale + deltaTime / 0.1 -- transition should last for that time in seconds
else
transitionScrollScale = 1
end
2021-07-31 22:14:34 +02:00
if transitionAfterscrollScale < 1 then
if transitionScrollScale == 1 then
-- Only start the after scroll transition when the scroll transition is finished
2021-08-01 18:08:52 +02:00
transitionAfterscrollScale = transitionAfterscrollScale + deltaTime / 15
2021-07-31 22:14:34 +02:00
end
else
transitionAfterscrollScale = 1 ;
end
2021-07-30 21:34:36 +02:00
if scrollingUp then
transitionScrollOffsetY = Easing.inQuad ( 1 - transitionScrollScale ) * songPlateHeight ;
else
transitionScrollOffsetY = Easing.inQuad ( 1 - transitionScrollScale ) * - songPlateHeight ;
end
2021-07-31 22:14:34 +02:00
2021-08-01 18:08:52 +02:00
if transitionAfterscrollScale < 0.02 then
transitionAfterscrollDataOverlayAlpha = math.min ( 1 , transitionAfterscrollScale / 0.02 )
2021-07-31 22:14:34 +02:00
else
transitionAfterscrollDataOverlayAlpha = 1 ;
end
-- Grade alpha
2021-08-01 18:08:52 +02:00
if transitionAfterscrollScale >= 0.03 and transitionAfterscrollScale < 0.033 then
2021-07-31 22:14:34 +02:00
transitionAfterscrollGradeAlpha = 0.5 ;
2021-08-01 18:08:52 +02:00
elseif transitionAfterscrollScale >= 0.04 then
2021-07-31 22:14:34 +02:00
transitionAfterscrollGradeAlpha = 1 ;
else
transitionAfterscrollGradeAlpha = 0 ;
end
-- Badge alpha
2021-08-01 18:08:52 +02:00
if transitionAfterscrollScale >= 0.032 and transitionAfterscrollScale < 0.035 then
2021-07-31 22:14:34 +02:00
transitionAfterscrollBadgeAlpha = 0.5 ;
2021-08-01 18:08:52 +02:00
elseif transitionAfterscrollScale >= 0.042 then
2021-07-31 22:14:34 +02:00
transitionAfterscrollBadgeAlpha = 1 ;
else
transitionAfterscrollBadgeAlpha = 0 ;
end
2021-08-01 18:08:52 +02:00
-- Song title alpha and pos
2021-08-06 20:06:35 +02:00
if transitionAfterscrollScale < 0.025 then
transitionAfterscrollTextSongTitle = Easing.outQuad ( math.min ( 1 , ( transitionAfterscrollScale ) / 0.025 ) ) ;
2021-08-01 18:08:52 +02:00
else
transitionAfterscrollTextSongTitle = 1
end
-- Song artist alpha and pos
2021-08-06 20:06:35 +02:00
if transitionAfterscrollScale < 0.025 then
transitionAfterscrollTextSongArtist = Easing.outQuad ( math.min ( 1 , ( transitionAfterscrollScale ) / 0.025 ) ) ;
2021-08-01 18:08:52 +02:00
else
transitionAfterscrollTextSongArtist = 1
end
2021-07-31 23:00:32 +02:00
-- Difficulties alpha
2021-08-01 18:08:52 +02:00
if transitionAfterscrollScale < 0.025 then
transitionAfterscrollDifficultiesAlpha = math.min ( 1 , transitionAfterscrollScale / 0.025 )
2021-07-31 23:00:32 +02:00
else
transitionAfterscrollDifficultiesAlpha = 1 ;
end
2021-08-01 18:08:52 +02:00
-- Jacket background alpha
if transitionAfterscrollScale < 0.05 or transitionAfterscrollScale >= 1 then
transitionAfterscrollJacketBgAlpha = 0 ;
elseif transitionAfterscrollScale >= 0.05 and transitionAfterscrollScale < 0.1 then
transitionAfterscrollJacketBgAlpha = math.min ( 1 , ( transitionAfterscrollScale - 0.05 ) / 0.05 ) ;
elseif transitionAfterscrollScale >= 0.95 and transitionAfterscrollScale < 1 then
transitionAfterscrollJacketBgAlpha = math.min ( 1 , 1 - ( ( transitionAfterscrollScale - 0.95 ) / 0.05 ) ) ;
else
transitionAfterscrollJacketBgAlpha = 1 ;
end
2021-08-12 16:55:10 +02:00
2021-08-16 16:29:21 +02:00
-- Laser anim
if transitionLaserScale < 1 then
2021-08-18 18:41:33 +02:00
transitionLaserScale = transitionLaserScale + deltaTime / 2 -- transition should last for that time in seconds
2021-08-16 16:29:21 +02:00
else
transitionLaserScale = 0
end
transitionLaserY = desh - math.min ( transitionLaserScale * 2 * desh , desh ) ;
2021-08-12 16:55:10 +02:00
-- Leave transition
2021-08-12 17:18:35 +02:00
if ( transitionLeaveReverse ) then
if transitionLeaveScale > 0 then
2021-08-12 17:25:24 +02:00
transitionLeaveScale = transitionLeaveScale - deltaTime / 0.5 -- transition should last for that time in seconds
2021-08-12 17:18:35 +02:00
else
transitionLeaveScale = 0
end
2021-08-12 16:55:10 +02:00
else
2021-08-12 17:18:35 +02:00
if transitionLeaveScale < 1 then
2021-08-12 17:25:24 +02:00
transitionLeaveScale = transitionLeaveScale + deltaTime / 0.5 -- transition should last for that time in seconds
2021-08-12 17:18:35 +02:00
else
transitionLeaveScale = 1
end
2021-08-12 16:55:10 +02:00
end
2021-08-12 17:18:35 +02:00
transitionLeaveOffsetY = Easing.inOutQuad ( transitionLeaveScale ) * ( desh + songPlateHeight * 2 + 145 ) ;
2021-07-30 21:34:36 +02:00
end
2021-07-31 20:36:05 +02:00
2021-07-30 16:37:01 +02:00
render = function ( deltaTime )
resetLayoutInformation ( ) ;
2021-07-30 21:34:36 +02:00
tickTransitions ( deltaTime ) ;
2021-07-30 16:37:01 +02:00
gfx.Scale ( scale , scale ) ;
2021-07-25 20:10:06 +02:00
2021-07-30 16:37:01 +02:00
if not difficultyNumbers then
difficultyNumbers = load_number_image ( ' diff_num ' )
end
2021-07-25 20:10:06 +02:00
2021-08-02 19:55:17 +02:00
drawBackground ( deltaTime ) ;
2021-07-25 20:10:06 +02:00
2021-07-30 16:37:01 +02:00
drawSongList ( )
2021-07-30 18:27:43 +02:00
drawCursor ( )
2021-07-25 20:10:06 +02:00
2021-07-31 20:36:05 +02:00
drawData ( )
2021-08-13 17:35:26 +02:00
drawFilterInfo ( deltaTime )
2021-08-05 22:01:17 +02:00
drawSearch ( ) ;
2021-08-12 17:18:35 +02:00
if ( game.GetSkinSetting ( ' _songWheelOverlayActive ' ) ~= 1 ) then
transitionLeaveReverse = true ;
2021-08-12 16:55:10 +02:00
else
2021-08-12 17:18:35 +02:00
transitionLeaveReverse = false ;
2021-08-12 16:55:10 +02:00
end
2021-07-30 21:34:36 +02:00
2021-07-25 20:10:06 +02:00
gfx.BeginPath ( ) ;
2021-07-30 16:37:01 +02:00
gfx.FontSize ( 18 )
gfx.TextAlign ( gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP )
2021-07-30 21:34:36 +02:00
local debugScrollingUp = " FALSE "
if scrollingUp then debugScrollingUp = " TRUE " end ;
2021-08-06 20:18:18 +02:00
gfx.Text ( ' S_I: ' .. selectedIndex .. ' // S_D: ' .. selectedDifficulty .. ' // S_UP: ' .. debugScrollingUp .. ' // AC_TS: ' .. transitionAfterscrollScale , 8 , 8 ) ;
2021-07-25 20:10:06 +02:00
end
2021-08-12 21:21:42 +02:00
songs_changed = function ( withAll )
if not withAll then return end
local diffs = { }
for i = 1 , # songwheel.allSongs do
local song = songwheel.allSongs [ i ]
for j = 1 , # song.difficulties do
local diff = song.difficulties [ j ]
diff.force = VolforceCalc.calc ( diff )
table.insert ( diffs , diff )
end
end
table.sort ( diffs , function ( l , r )
return l.force > r.force
end )
totalForce = 0
for i = 1 , 50 do
if diffs [ i ] then
2021-08-16 15:50:53 +02:00
top50diffs [ diffs [ i ] . id ] = true ;
2021-08-12 21:21:42 +02:00
totalForce = totalForce + diffs [ i ] . force
end
end
game.SetSkinSetting ( ' _volforce ' , totalForce )
end
2021-07-25 20:10:06 +02:00
set_index = function ( newIndex )
2021-07-30 21:34:36 +02:00
transitionScrollScale = 0 ;
2021-07-31 22:14:34 +02:00
transitionAfterscrollScale = 0 ;
2021-07-30 21:34:36 +02:00
scrollingUp = false ;
if ( ( newIndex > selectedIndex and not ( newIndex == # songwheel.songs and selectedIndex == 1 ) ) or ( newIndex == 1 and selectedIndex == # songwheel.songs ) ) then
scrollingUp = true ;
end ;
2021-07-30 22:06:08 +02:00
game.PlaySample ( ' song_wheel/cursor_change.wav ' ) ;
2021-07-30 21:34:36 +02:00
2021-07-30 16:37:01 +02:00
selectedIndex = newIndex ;
2021-07-25 20:10:06 +02:00
end ;
set_diff = function ( newDiff )
2021-08-12 14:29:55 +02:00
if newDiff ~= selectedDifficulty then
2021-08-13 22:36:21 +02:00
jacketCache = { } ; -- Clear the jacket cache for the new diff jackets
2021-08-12 14:29:55 +02:00
game.PlaySample ( ' song_wheel/diff_change.wav ' ) ;
end
2021-07-30 16:37:01 +02:00
selectedDifficulty = newDiff ;
end ;