require('common') local Easing = require('common.easings'); local defaultFolderBgImage = gfx.CreateSkinImage('song_select/filter_wheel/bg.png', 0) local cursorImage = gfx.CreateSkinImage('song_select/cursor.png', 0) local ITEM_HEIGHT = 172; local specialFolders = { { keys = { 'SOUND VOLTEX BOOTH', 'SDVX BOOTH', 'SOUND VOLTEX I', 'SDVX I', 'SOUND VOLTEX 1', 'SDVX 1' }, folderBg = gfx.CreateSkinImage('song_select/filter_wheel/special_folder_bgs/Booth.png', 0) }, { keys = { 'SOUND VOLTEX INFINITE INFECTION', 'SDVX INFINITE INFECTION', 'SOUND VOLTEX II', 'SDVX II', 'SOUND VOLTEX 2', 'SDVX 2' }, folderBg = gfx.CreateSkinImage('song_select/filter_wheel/special_folder_bgs/Infinite Infection.png', 0) }, -- { -- keys = { -- 'SOUND VOLTEX GRAVITY WARS', -- 'SDVX GRAVITY WARS', -- 'SOUND VOLTEX III', -- 'SDVX III', -- 'SOUND VOLTEX 3', -- 'SDVX 3' -- }, -- folderBg = gfx.CreateSkinImage('song_select/filter_wheel/special_folder_bgs/Infinite Infection.png', 0) -- }, { keys = { 'SOUND VOLTEX HEAVENLY HAVEN', 'SDVX HEAVENLY HAVEN', 'SOUND VOLTEX IV', 'SDVX IV', 'SOUND VOLTEX 4', 'SDVX 4' }, folderBg = gfx.CreateSkinImage('song_select/filter_wheel/special_folder_bgs/Heavenly Haven.png', 0) }, { keys = { 'SOUND VOLTEX VIVID WAVE', 'SDVX VIVID WAVE', 'SOUND VOLTEX V', 'SDVX V', 'SOUND VOLTEX 5', 'SDVX 5' }, folderBg = gfx.CreateSkinImage('song_select/filter_wheel/special_folder_bgs/Vivid Wave.png', 0) }, { keys = { 'SOUND VOLTEX EXCEED GEAR', 'SDVX EXCEED GEAR', 'SOUND VOLTEX VI', 'SDVX VI', 'SOUND VOLTEX 6', 'SDVX 6' }, folderBg = gfx.CreateSkinImage('song_select/filter_wheel/special_folder_bgs/Exceed Gear.png', 0) }, } -- AUDIO game.LoadSkinSample('song_wheel/cursor_change.wav'); local resx, resy = game.GetResolution() local desw, desh = 1080, 1920 local scale = 1; local selectionMode = 'folders'; local selectedFolder = 1; local selectedLevel = 1; local transitionScrollScale = 0; local transitionScrollOffsetY = 0; local scrollingUp = false; function resetLayoutInformation() resx, resy = game.GetResolution() scale = resx / desw end function getCorrectedIndex(from, offset) local total = 1; if selectionMode == 'folders' then total = #filters.folder; else total = #filters.level; end 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 getFolderData(folderLabel) local folderType = 'unknown'; if (string.find(folderLabel, 'Folder: ')) then folderType = 'folder'; folderLabel = folderLabel:gsub('Folder: ', '') -- Delete the useless info end local labelMatcherString = string.upper(folderLabel) local folderBgImage = defaultFolderBgImage; local isSpecial = false; for i,specialFolder in ipairs(specialFolders) do for i,specialFolderKey in ipairs(specialFolder.keys) do if (specialFolderKey == labelMatcherString) then folderBgImage = specialFolder.folderBg; isSpecial = true; end end end return { type = folderType, label = folderLabel, bgImage = folderBgImage, isSpecial = isSpecial, } end function drawFolder(label, y) if (not label) then return end local x = desw / 2 + 0 local folderData = getFolderData(label) -- Draw the bg gfx.BeginPath() gfx.ImageRect(x, y, 630*0.86, 200*0.86, folderData.bgImage, 1, 0) -- Draw the folder label, but only if the folder is not special if (not folderData.isSpecial) then gfx.BeginPath(); gfx.FontSize(38) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) gfx.FillColor(255, 255, 255, 255); gfx.Text(folderData.label, x+18, y+72); end end function drawFolderList() local numOfItemsAround = 7; local selectedIndex = 1; if selectionMode == 'folders' then selectedIndex = selectedFolder else selectedIndex = selectedLevel end local i = 1; while (i <= numOfItemsAround) do local index = getCorrectedIndex(selectedIndex, -i) drawFolder(filters.folder[index], desh / 2 - ITEM_HEIGHT / 2 - ITEM_HEIGHT * i + transitionScrollOffsetY) i = i + 1; end -- Draw the selected song drawFolder(filters.folder[selectedIndex], desh / 2 - ITEM_HEIGHT / 2 + transitionScrollOffsetY) i = 1; while (i <= numOfItemsAround) do local index = getCorrectedIndex(selectedIndex, i) drawFolder(filters.folder[index], desh / 2 - ITEM_HEIGHT / 2 + ITEM_HEIGHT * i + transitionScrollOffsetY) i = i + 1; end end function drawCursor() gfx.BeginPath() gfx.ImageRect(desw/2-14, desh/2-213/2, 555, 213, cursorImage, 1, 0) end 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 scrollingUp then transitionScrollOffsetY = Easing.inQuad(1-transitionScrollScale) * ITEM_HEIGHT; else transitionScrollOffsetY = Easing.inQuad(1-transitionScrollScale) * -ITEM_HEIGHT; end end render = function(deltaTime, shown) if not shown then return end gfx.ResetTransform() resetLayoutInformation() tickTransitions(deltaTime); gfx.Scale(scale,scale); drawFolderList() drawCursor() -- Debug text gfx.BeginPath(); gfx.FontSize(18) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) gfx.FillColor(255, 255, 255, 255); gfx.Text('S_M: ' .. selectionMode .. ' // S_F: ' .. selectedFolder .. ' // S_L: ' .. selectedLevel .. ' // T_S_S: ' .. transitionScrollScale, 8, 1900); end set_selection = function(newIndex, isFolder) local oldIndex = 1; local total = 1; if isFolder then oldIndex = selectedFolder selectedFolder = newIndex total = #filters.folder; else oldIndex = selectedLevel selectedLevel = newIndex total = #filters.level; end transitionScrollScale = 0; scrollingUp = false; if ((newIndex > oldIndex and not (newIndex == total and oldIndex == 1)) or (newIndex == 1 and oldIndex == total)) then scrollingUp = true; end; game.PlaySample('song_wheel/cursor_change.wav'); end set_mode = function(isFolder) if isFolder then selectionMode = 'folders' else selectionMode = 'levels' end end