ExperimentalGear/scripts/songselect/songwheel.lua

759 lines
25 KiB
Lua
Raw Normal View History

2021-08-07 20:35:00 +02:00
require('common')
local Easing = require('common.easings')
local Background = require('components.background');
2021-08-12 21:21:42 +02:00
local VolforceCalc = require('components.volforceCalc');
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)
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
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)
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)
local defaultJacketImage = gfx.CreateSkinImage("song_select/loading.png", 0)
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),
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),
}
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');
game.LoadSkinSample('song_wheel/diff_change.wav');
2021-07-30 22:06:08 +02:00
local difficultyNumbers;
2021-07-31 20:36:05 +02:00
local scoreNumbers;
2021-07-25 20:10:06 +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;
local selectedIndex = 1;
local selectedDifficulty = 1;
2021-07-25 20:10:06 +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;
local transitionAfterscrollScale = 0;
local transitionAfterscrollDataOverlayAlpha = 0;
local transitionAfterscrollGradeAlpha = 0;
local transitionAfterscrollBadgeAlpha = 0;
local transitionAfterscrollTextSongTitle = 0;
local transitionAfterscrollTextSongArtist = 0;
local transitionAfterscrollDifficultiesAlpha = 0;
local transitionJacketBgScrollScale = 0;
local transitionJacketBgScrollAlpha = 0;
local transitionJacketBgScrollPosX = 0;
local transitionLaserScale = 0;
local transitionLaserY = 0;
-- Flash transition (animation)
-- Used for flashing the badges
-- 0 = minimum brightness; 0.5 = maximum brightness; 1 = minimum brightness again
local transitionFlashScale = 0;
local transitionFlashAlpha = 1;
local transitionLeaveReverse = false;
2021-08-12 16:55:10 +02:00
local transitionLeaveScale = 0;
local transitionLeaveOffsetY = 0;
function resetLayoutInformation()
resx, resy = game.GetResolution()
desw = 1080
desh = 1920
scale = resx / desw
2021-07-25 20:10:06 +02:00
end
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
return images
2021-07-25 20:10:06 +02:00
end
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()
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;
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;
function getJacketImage(song)
if not jacketCache[song.id] or jacketCache[song.id]==defaultJacketImage then
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
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
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)
Background.draw(deltaTime)
2021-07-31 20:36:05 +02:00
-- If the score for song exists
local song = songwheel.songs[selectedIndex];
local diff = song and song.difficulties[selectedDifficulty] or false;
if song and diff then
local jacketImage = getJacketImage(song);
2021-07-31 20:36:05 +02:00
gfx.BeginPath()
gfx.ImageRect(transitionJacketBgScrollPosX, 0, 900, 900, jacketImage or defaultJacketImage, transitionJacketBgScrollAlpha, 0)
gfx.BeginPath();
gfx.FillColor(0,0,0,math.floor(transitionJacketBgScrollAlpha*64));
gfx.Rect(0,0,900,900);
gfx.Fill();
gfx.ClosePath();
gfx.BeginPath();
end
gfx.ImageRect(0, 0, desw, desh, dataPanelImage, 1, 0)
drawLaserAnim()
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
function drawSong(song, y)
2021-07-31 20:36:05 +02:00
if (not song) then return end;
local songX = desw/2+28
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
-- 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)
-- Draw jacket
local jacketImage = getJacketImage(song);
gfx.BeginPath()
gfx.ImageRect(songX+4, y+4, 163, 163, jacketImage or defaultJacketImage, 1, 0)
2021-07-25 20:10:06 +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)
-- 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
-- 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];
if selectedSongDifficulty.topBadge then
badgeImage = badgeImages[selectedSongDifficulty.topBadge+1];
2021-07-30 18:27:43 +02:00
end
local badgeAlpha = 1;
if (selectedSongDifficulty.topBadge >= 3) then
badgeAlpha = transitionFlashAlpha; -- If hard clear or above, flash the badge
end
2021-07-30 18:27:43 +02:00
gfx.BeginPath()
gfx.ImageRect(songX+282, y+44, 79, 69, badgeImage, badgeAlpha, 0)
2021-07-31 18:43:17 +02:00
-- Draw grade
local gradeImage = gradeImages.none;
local gradeAlpha = 1;
2021-07-31 18:43:17 +02:00
if bestScore then
gradeImage = getGradeImageForScore(bestScore.score)
if (bestScore.score >= gradeCutoffs.S) then
gradeAlpha = transitionFlashAlpha; -- If S, flash the badge
end
2021-07-31 18:43:17 +02:00
end
gfx.BeginPath();
gfx.ImageRect(songX+391, y+47, 60, 60, gradeImage, gradeAlpha, 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
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;
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)
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)
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)
i=i+1;
end;
2021-07-25 20:10:06 +02:00
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];
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
gfx.Save()
-- Draw best score
gfx.BeginPath()
2021-08-26 15:42:50 +02:00
local scoreNumber = 0;
2021-07-31 20:36:05 +02:00
if bestScore then
2021-08-26 15:42:50 +02:00
scoreNumber = bestScore.score
end
2021-07-31 20:36:05 +02:00
2021-08-26 15:42:50 +02:00
draw_number(100, 793, 1.0, math.floor(scoreNumber / 10000), 4, scoreNumbers, true, 0.3, 1.12)
draw_number(253, 798, 1.0, scoreNumber, 4, scoreNumbers, true, 0.22, 1.12)
-- Draw grade
local gradeImage = gradeImages.none;
local gradeAlpha = transitionAfterscrollGradeAlpha;
if bestScore then
gradeImage = getGradeImageForScore(bestScore.score)
if (transitionAfterscrollGradeAlpha == 1 and bestScore.score >= gradeCutoffs.S) then
gradeAlpha = transitionFlashAlpha; -- If S, flash the badge
2021-07-31 20:36:05 +02:00
end
end
2021-07-31 20:36:05 +02:00
gfx.BeginPath();
gfx.ImageRect(360, 773, 45, 45, gradeImage, gradeAlpha, 0);
-- Draw badge
badgeImage = badgeImages[diff.topBadge+1];
local badgeAlpha = transitionAfterscrollBadgeAlpha;
if (transitionAfterscrollBadgeAlpha == 1 and diff.topBadge >= 3) then
badgeAlpha = transitionFlashAlpha; -- If hard clear or above, flash the badge, but only after the initial transition
2021-07-31 20:36:05 +02:00
end
gfx.BeginPath()
gfx.ImageRect(425, 724, 93/1.1, 81/1.1, badgeImage, badgeAlpha, 0)
gfx.Restore()
2021-07-31 20:36:05 +02:00
-- Draw BPM
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')
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)
gfx.GlobalAlpha(transitionAfterscrollTextSongTitle);
gfx.Text(song.title, 30+(1-transitionAfterscrollTextSongTitle)*20, 955);
2021-07-31 20:36:05 +02:00
-- Draw artist
gfx.GlobalAlpha(transitionAfterscrollTextSongArtist);
gfx.Text(song.artist, 30+(1-transitionAfterscrollTextSongArtist)*30, 997);
gfx.GlobalAlpha(1);
-- Draw difficulties
local DIFF_X_START = 98.5
local DIFF_GAP = 114.8;
gfx.GlobalAlpha(transitionAfterscrollDifficultiesAlpha);
for i, diff in ipairs(song.difficulties) do
gfx.BeginPath()
local index = diff.difficulty+1
if i == selectedDifficulty then
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)
];
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
gfx.GlobalAlpha(1);
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()
gfx.Text(folderLabel or '', 167, 131);
2021-08-14 17:49:12 +02:00
2021-08-13 17:35:26 +02:00
gfx.BeginPath()
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
if transitionAfterscrollScale < 1 then
if transitionScrollScale == 1 then
-- Only start the after scroll transition when the scroll transition is finished
transitionAfterscrollScale = transitionAfterscrollScale + deltaTime / 15
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
if transitionAfterscrollScale < 0.02 then
transitionAfterscrollDataOverlayAlpha = math.min(1, transitionAfterscrollScale / 0.02)
else
transitionAfterscrollDataOverlayAlpha = 1;
end
-- Grade alpha
if transitionAfterscrollScale >= 0.03 and transitionAfterscrollScale < 0.033 then
transitionAfterscrollGradeAlpha = 0.5;
elseif transitionAfterscrollScale >= 0.04 then
transitionAfterscrollGradeAlpha = 1;
else
transitionAfterscrollGradeAlpha = 0;
end
-- Badge alpha
if transitionAfterscrollScale >= 0.032 and transitionAfterscrollScale < 0.035 then
transitionAfterscrollBadgeAlpha = 0.5;
elseif transitionAfterscrollScale >= 0.042 then
transitionAfterscrollBadgeAlpha = 1;
else
transitionAfterscrollBadgeAlpha = 0;
end
-- Song title alpha and pos
if transitionAfterscrollScale < 0.025 then
transitionAfterscrollTextSongTitle = Easing.outQuad(math.min(1, (transitionAfterscrollScale) / 0.025));
else
transitionAfterscrollTextSongTitle = 1
end
-- Song artist alpha and pos
if transitionAfterscrollScale < 0.025 then
transitionAfterscrollTextSongArtist = Easing.outQuad(math.min(1, (transitionAfterscrollScale) / 0.025));
else
transitionAfterscrollTextSongArtist = 1
end
-- Difficulties alpha
if transitionAfterscrollScale < 0.025 then
transitionAfterscrollDifficultiesAlpha = math.min(1, transitionAfterscrollScale / 0.025)
else
transitionAfterscrollDifficultiesAlpha = 1;
end
-- Jacket bg animation
if transitionJacketBgScrollScale < 1 then
transitionJacketBgScrollScale = transitionJacketBgScrollScale + deltaTime / 20 -- transition should last for that time in seconds
else
transitionJacketBgScrollScale = 0
end
2021-08-12 16:55:10 +02:00
if transitionJacketBgScrollScale < 0.05 or transitionJacketBgScrollScale >= 1 then
transitionJacketBgScrollAlpha = 0;
elseif transitionJacketBgScrollScale >= 0.05 and transitionJacketBgScrollScale < 0.1 then
transitionJacketBgScrollAlpha = math.min(1, (transitionJacketBgScrollScale-0.05) / 0.05);
elseif transitionJacketBgScrollScale >= 0.8 and transitionJacketBgScrollScale < 1 then
transitionJacketBgScrollAlpha = math.max(0,
math.min(1, 1-((transitionJacketBgScrollScale-0.8) / 0.05))
);
else
transitionJacketBgScrollAlpha = 1;
end
transitionJacketBgScrollPosX = 0+(transitionJacketBgScrollScale*(0.8/1))*-300;
-- Laser anim
if transitionLaserScale < 1 then
transitionLaserScale = transitionLaserScale + deltaTime / 2 -- transition should last for that time in seconds
else
transitionLaserScale = 0
end
transitionLaserY = desh - math.min(transitionLaserScale * 2 * desh, desh);
-- Flash transition
if transitionFlashScale < 1 then
local songBpm = 120;
if (songwheel.songs[selectedIndex] and game.GetSkinSetting('animations_affectWithBPM')) then
songBpm = songwheel.songs[selectedIndex].bpm;
-- Is a variable BPM
if (type(songBpm) == "string") then
local s = split(songBpm, '-');
songBpm = tonumber(s[1]); -- Lowest bpm value
end
end
-- If the original songBpm is "2021.04.01" for example, the above code can produce `nil` in the songBpm
-- since it cannot parse the number out of that string. Here we implement a fallback, to not crash
-- USC on whacky charts. Whacky charters, quit using batshit insane bpm values. It makes me angery >:(
if (songBpm == nil) then
songBpm = 120;
end
transitionFlashScale = transitionFlashScale + deltaTime / (60/songBpm) -- transition should last for that time in seconds
else
transitionFlashScale = 0
end
if transitionFlashScale < 0.5 then
transitionFlashAlpha = transitionFlashScale * 2;
else
transitionFlashAlpha = 1-((transitionFlashScale-0.5) * 2);
end
transitionFlashAlpha = 1+transitionFlashAlpha*0.5
2021-08-12 16:55:10 +02:00
-- Leave transition
if (transitionLeaveReverse) then
if transitionLeaveScale > 0 then
transitionLeaveScale = transitionLeaveScale - deltaTime / 0.5 -- transition should last for that time in seconds
else
transitionLeaveScale = 0
end
2021-08-12 16:55:10 +02:00
else
if transitionLeaveScale < 1 then
transitionLeaveScale = transitionLeaveScale + deltaTime / 0.5 -- transition should last for that time in seconds
else
transitionLeaveScale = 1
end
2021-08-12 16:55:10 +02:00
end
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
render = function (deltaTime)
resetLayoutInformation();
2021-07-30 21:34:36 +02:00
tickTransitions(deltaTime);
gfx.Scale(scale, scale);
2021-07-25 20:10:06 +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
drawSongList()
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();
if (game.GetSkinSetting('_songWheelOverlayActive') ~= 1) then
transitionLeaveReverse = true;
2021-08-12 16:55:10 +02:00
else
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();
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
game.SetSkinSetting('_songWheelScrollbarTotal', #songwheel.songs)
game.SetSkinSetting('_songWheelScrollbarIndex', selectedIndex)
2021-08-12 21:21:42 +02:00
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;
transitionAfterscrollScale = 0;
transitionJacketBgScrollScale = 0;
2021-07-30 21:34:36 +02:00
game.SetSkinSetting('_songWheelScrollbarTotal', #songwheel.songs)
game.SetSkinSetting('_songWheelScrollbarIndex', newIndex)
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
selectedIndex = newIndex;
2021-07-25 20:10:06 +02:00
end;
set_diff = function(newDiff)
if newDiff ~= selectedDifficulty then
jacketCache = {}; -- Clear the jacket cache for the new diff jackets
game.PlaySample('song_wheel/diff_change.wav');
end
selectedDifficulty = newDiff;
end;