diff --git a/audio/filter_wheel/open_close.wav b/audio/filter_wheel/open_close.wav new file mode 100644 index 0000000..e4e7bfb Binary files /dev/null and b/audio/filter_wheel/open_close.wav differ diff --git a/scripts/songselect/filterwheel.lua b/scripts/songselect/filterwheel.lua index 32823fa..03208f3 100644 --- a/scripts/songselect/filterwheel.lua +++ b/scripts/songselect/filterwheel.lua @@ -86,11 +86,15 @@ local specialFolders = { -- AUDIO game.LoadSkinSample('song_wheel/cursor_change.wav'); +game.LoadSkinSample('filter_wheel/open_close.wav'); local resx, resy = game.GetResolution() local desw, desh = 1080, 1920 local scale = 1; +local isFilterWheelActive = false; +local previousActiveState = false; -- for open/close sounds + local selectionMode = 'folders'; local selectedFolder = 1; local selectedLevel = 1; @@ -99,9 +103,9 @@ local transitionScrollScale = 0; local transitionScrollOffsetY = 0; local scrollingUp = false; -local transitionEnterReverse = false; -local transitionEnterScale = 0; -local transitionEnterOffsetY = 0; +local transitionLeaveScale = 1; +local transitionLeaveReappearTimer = 0; +local TRANSITION_LEAVE_DURATION = 0.1; function resetLayoutInformation() resx, resy = game.GetResolution() @@ -185,6 +189,8 @@ end function drawFolder(label, y) if (not label) then return end + gfx.LoadSkinFont('NotoSans-Regular.ttf') + local x = desw / 2 + 0 local folderData = getFolderData(label) @@ -204,6 +210,8 @@ function drawFolder(label, y) end function drawFolderList() + gfx.GlobalAlpha(1-transitionLeaveScale) + local numOfItemsAround = 7; local selectedIndex = 1; local folderList = filters.folder; @@ -216,7 +224,7 @@ function drawFolderList() folderList = filters.level; end - yOffset = transitionEnterOffsetY + transitionScrollOffsetY; + local yOffset = transitionScrollOffsetY; local i = 1; while (i <= numOfItemsAround) do @@ -236,9 +244,13 @@ function drawFolderList() desh / 2 - ITEM_HEIGHT / 2 + ITEM_HEIGHT * i + yOffset) i = i + 1; end + + gfx.GlobalAlpha(1); end function drawCursor() + if not isFilterWheelActive or transitionLeaveScale ~= 0 then return end + gfx.BeginPath() local cursorImageIndex = game.GetSkinSetting('_gaugeType') @@ -285,24 +297,26 @@ function tickTransitions(deltaTime) -ITEM_HEIGHT; end - -- ENTRY TRANSITION - if transitionEnterReverse then - if transitionEnterScale > 0 then - transitionEnterScale = transitionEnterScale - deltaTime / 0.5 -- transition should last for that time in seconds + -- LEAVE TRANSITION + if (not isFilterWheelActive) then + if transitionLeaveScale < 1 then + transitionLeaveScale = transitionLeaveScale + deltaTime / TRANSITION_LEAVE_DURATION -- transition should last for that time in seconds else - transitionEnterScale = 0 + transitionLeaveScale = 1 end + transitionLeaveReappearTimer = 1; else - if transitionEnterScale < 1 then - transitionEnterScale = transitionEnterScale + deltaTime / 0.5 -- transition should last for that time in seconds - else - transitionEnterScale = 1 + if (transitionLeaveReappearTimer == 1) then + -- This stuff happens right after filterwheel is deactivated + end + + transitionLeaveReappearTimer = transitionLeaveReappearTimer - deltaTime / (TRANSITION_LEAVE_DURATION + 0.05) -- same reasoning as in the songwheel + + if (transitionLeaveReappearTimer <= 0) then + transitionLeaveScale = 0; + transitionLeaveReappearTimer = 0; end end - - transitionEnterOffsetY = -Easing.inOutQuad(1 - transitionEnterScale) * - (desh + ITEM_HEIGHT * 2 + 145 + - (transitionEnterReverse and -4 or 0)); end function drawFilterWheel(deltatime) @@ -315,39 +329,38 @@ function drawFilterWheel(deltatime) end render = function(deltatime, shown) + isFilterWheelActive = shown; + drawFilterWheel(deltatime) + if not shown then game.SetSkinSetting('_songWheelOverlayActive', 0); - transitionEnterReverse = true - - if (transitionEnterScale > 0) then - drawFilterWheel(deltatime) - else - game.SetSkinSetting('_songWheelDespawnSelectorElements', 0); - end else - transitionEnterReverse = false game.SetSkinSetting('_songWheelOverlayActive', 1); - game.SetSkinSetting('_songWheelDespawnSelectorElements', 1); - drawFilterWheel(deltatime) end game.SetSkinSetting('_songWheelActiveFolderLabel', getFolderData(filters.folder[selectedFolder]).label); game.SetSkinSetting('_songWheelActiveSubFolderLabel', getFolderData(filters.level[selectedLevel]).label); - + drawCursor() drawScrollbar() SongSelectHeader.draw(deltatime); Footer.draw(deltatime); + + if (isFilterWheelActive ~= previousActiveState) then + game.PlaySample('filter_wheel/open_close.wav'); + previousActiveState = isFilterWheelActive; + end + -- 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_E_S: ' .. - -- transitionEnterScale, 8, 1870); + -- ' // S_L: ' .. selectedLevel .. ' // L_TS: ' .. + -- transitionLeaveScale .. ' // L_TRT: ' .. transitionLeaveReappearTimer, 8, 1870); end set_selection = function(newIndex, isFolder) diff --git a/scripts/songselect/songwheel.lua b/scripts/songselect/songwheel.lua index ce75bc7..3888ea0 100644 --- a/scripts/songselect/songwheel.lua +++ b/scripts/songselect/songwheel.lua @@ -49,6 +49,12 @@ local badgeImages = { gfx.CreateSkinImage("song_select/medal/puc.png", 1), } +local cursorImages = { + gfx.CreateSkinImage("song_select/cursor.png", 1), -- Effective rate or fallback + gfx.CreateSkinImage("song_select/cursor_exc.png", 1), -- Excessive rate + gfx.CreateSkinImage("song_select/cursor_perm.png", 1), -- Premissive rate + gfx.CreateSkinImage("song_select/cursor_blast.png", 1), -- Blastive rate +} local gradeCutoffs = { D = 0000000, C = 7000000, @@ -131,9 +137,10 @@ local transitionLaserY = 0; local transitionFlashScale = 0; local transitionFlashAlpha = 1; -local transitionLeaveReverse = false; +local isFilterWheelActive = false; local transitionLeaveScale = 0; -local transitionLeaveOffsetY = 0; +local transitionLeaveReappearTimer = 0; +local TRANSITION_LEAVE_DURATION = 0.1; function resetLayoutInformation() resx, resy = game.GetResolution() @@ -233,29 +240,32 @@ end function drawBackground(deltaTime) Background.draw(deltaTime) - - -- 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); - 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(); + if (not isFilterWheelActive and transitionLeaveReappearTimer == 0) then + -- If the score for song exists + if song and diff then + local jacketImage = getJacketImage(song); + 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(); + end end + gfx.BeginPath(); gfx.ImageRect(0, 0, desw, desh, dataPanelImage, 1, 0) drawLaserAnim() - if song and diff then + if song and diff and (not isFilterWheelActive and transitionLeaveReappearTimer == 0) then gfx.BeginPath() gfx.ImageRect(0, 0, desw, desh, dataGlowOverlayImage, transitionAfterscrollDataOverlayAlpha, 0) gfx.BeginPath() @@ -351,9 +361,11 @@ function drawSong(song, y) end function drawSongList() + gfx.GlobalAlpha(1-transitionLeaveScale); + local numOfSongsAround = 7; -- How many songs should be up and how many should be down of the selected one - local yOffset = transitionLeaveOffsetY + transitionScrollOffsetY; + local yOffset = transitionScrollOffsetY; local i=1; while (i <= numOfSongsAround) do @@ -371,10 +383,15 @@ function drawSongList() drawSong(songwheel.songs[songIndex], desh/2-songPlateHeight/2+songPlateHeight*i + yOffset) i=i+1; end; + + gfx.GlobalAlpha(1); end local scoreNumbers = load_number_image("score_num"); function drawData() -- Draws the song data on the left panel + + if isFilterWheelActive or transitionLeaveReappearTimer ~= 0 then return false end; + local song = songwheel.songs[selectedIndex]; local diff = song and song.difficulties[selectedDifficulty] or false; local bestScore = diff and diff.scores[1]; @@ -524,6 +541,8 @@ function drawData() -- Draws the song data on the left panel end function drawFilterInfo(deltatime) + gfx.LoadSkinFont('NotoSans-Regular.ttf') + gfx.BeginPath() gfx.ImageRect(5, 95, 417*0.85, 163*0.85, filterInfoBgImage, 1, 0) @@ -547,6 +566,17 @@ function drawFilterInfo(deltatime) gfx.Text(sortOptionLabel or '', desw-150, 130); end +function drawCursor() + if isFilterWheelActive or transitionLeaveScale ~= 0 then return false end + + gfx.BeginPath() + + local cursorImageIndex = game.GetSkinSetting('_gaugeType') + local cursorImage = cursorImages[cursorImageIndex or 1]; + + gfx.ImageRect(desw / 2 - 14, desh / 2 - 213 / 2, 555, 213, cursorImage, 1, 0) +end + function drawSearch() if (not songwheel.searchInputActive) then return; @@ -689,21 +719,28 @@ function tickTransitions(deltaTime) transitionFlashAlpha = 1+transitionFlashAlpha*0.5 -- 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 - else + if (isFilterWheelActive) then if transitionLeaveScale < 1 then - transitionLeaveScale = transitionLeaveScale + deltaTime / 0.5 -- transition should last for that time in seconds + transitionLeaveScale = transitionLeaveScale + deltaTime / TRANSITION_LEAVE_DURATION -- transition should last for that time in seconds else transitionLeaveScale = 1 end - end + transitionLeaveReappearTimer = 1; + transitionAfterscrollScale = 0; -- Keep songwheel in the "afterscroll" state while the filterwheel is active + transitionJacketBgScrollScale = 0; -- Same thing here, just with the jacket bg + else + if (transitionLeaveReappearTimer ~= 0) then + transitionAfterscrollScale = 0; -- Keep songwheel in the "afterscroll" state while we're waiting on filter wheel to fade out + transitionJacketBgScrollScale = 0; -- Same thing here, just with the jacket bg + end - transitionLeaveOffsetY = Easing.inOutQuad(transitionLeaveScale) * (desh+songPlateHeight*2+145); + transitionLeaveReappearTimer = transitionLeaveReappearTimer - deltaTime / (TRANSITION_LEAVE_DURATION + 0.05) -- 0.05s is a few frames between the completetion of the fade out and songs reappearing in the AC + + if (transitionLeaveReappearTimer <= 0) then + transitionLeaveScale = 0; + transitionLeaveReappearTimer = 0; + end + end end @@ -720,24 +757,21 @@ render = function (deltaTime) drawSongList() + isFilterWheelActive = game.GetSkinSetting('_songWheelOverlayActive') == 1; + drawData() + drawCursor() drawFilterInfo(deltaTime) drawSearch(); - if (game.GetSkinSetting('_songWheelOverlayActive') ~= 1) then - transitionLeaveReverse = true; - else - transitionLeaveReverse = false; - end - gfx.BeginPath(); gfx.FontSize(18) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) local debugScrollingUp= "FALSE" if scrollingUp then debugScrollingUp = "TRUE" end; - -- gfx.Text('S_I: ' .. selectedIndex .. ' // S_D: ' .. selectedDifficulty .. ' // S_UP: ' .. debugScrollingUp .. ' // AC_TS: ' .. transitionAfterscrollScale, 8, 8); + -- gfx.Text('S_I: ' .. selectedIndex .. ' // S_D: ' .. selectedDifficulty .. ' // S_UP: ' .. debugScrollingUp .. ' // AC_TS: ' .. transitionAfterscrollScale .. ' // L_TS: ' .. transitionLeaveScale, 8, 8); end songs_changed = function (withAll)