From 51bd6cec6317027ede416740db9db8950c6d4680 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Tue, 31 Mar 2020 15:50:27 +0300 Subject: [PATCH] Support importing lyrics - Use inline "#LYRIC" lines in tja files - "LYRICS:" in tja metadata can point to a vtt file, this overrides "#LYRIC" --- public/src/css/game.css | 3 ++- public/src/js/controller.js | 28 ++++++++++++++++++++-------- public/src/js/importsongs.js | 9 +++++++++ public/src/js/loadsong.js | 7 +++++++ public/src/js/lyrics.js | 4 ++-- public/src/js/parsetja.js | 18 ++++++++++++++++++ 6 files changed, 58 insertions(+), 11 deletions(-) diff --git a/public/src/css/game.css b/public/src/css/game.css index 290c1eb..7918ce1 100644 --- a/public/src/css/game.css +++ b/public/src/css/game.css @@ -99,8 +99,9 @@ font-weight: bold; font-size: calc(45px * var(--scale)); line-height: 1.2; + white-space: pre-wrap; } -#game.portrait{ +#game.portrait #song-lyrics{ right: calc(20px * var(--scale)); left: calc(20px * var(--scale)); } diff --git a/public/src/js/controller.js b/public/src/js/controller.js index 0447daf..af8e9a3 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -57,9 +57,14 @@ class Controller{ if(song.id == this.selectedSong.folder){ this.mainAsset = song.sound this.volume = song.volume || 1 - if(song.lyricsData && !multiplayer && (!this.touchEnabled || this.autoPlayEnabled)){ - var lyricsDiv = document.getElementById("song-lyrics") - this.lyrics = new Lyrics(song.lyricsData, selectedSong.offset, lyricsDiv) + if(!multiplayer && (!this.touchEnabled || this.autoPlayEnabled)){ + if(song.lyricsData){ + var lyricsDiv = document.getElementById("song-lyrics") + this.lyrics = new Lyrics(song.lyricsData, selectedSong.offset, lyricsDiv) + }else if(this.parsedSongData.lyrics){ + var lyricsDiv = document.getElementById("song-lyrics") + this.lyrics = new Lyrics(this.parsedSongData.lyrics, selectedSong.offset, lyricsDiv, true) + } } } }) @@ -231,20 +236,27 @@ class Controller{ resolve() }else{ var songObj = assets.songs.find(song => song.id === this.selectedSong.folder) + var promises = [] if(songObj.chart && songObj.chart !== "blank"){ var reader = new FileReader() - var promise = pageEvents.load(reader).then(event => { + promises.push(pageEvents.load(reader).then(event => { this.songData = event.target.result.replace(/\0/g, "").split("\n") - resolve() - }) + return Promise.resolve() + })) if(this.selectedSong.type === "tja"){ reader.readAsText(songObj.chart, "sjis") }else{ reader.readAsText(songObj.chart) } - }else{ - resolve() } + if(songObj.lyricsFile){ + var reader = new FileReader() + promises.push(pageEvents.load(reader).then(event => { + songObj.lyricsData = event.target.result + }), songObj.lyricsFile.webkitRelativePath) + reader.readAsText(songObj.lyricsFile) + } + Promise.all(promises).then(resolve) } }).then(() => { var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled, false, this.touchEnabled) diff --git a/public/src/js/importsongs.js b/public/src/js/importsongs.js index 375c32b..87d63df 100644 --- a/public/src/js/importsongs.js +++ b/public/src/js/importsongs.js @@ -260,6 +260,15 @@ id: 1 } } + if(meta.lyrics){ + var lyricsFile = this.normPath(this.joinPath(dir, meta.lyrics)) + if(lyricsFile in this.otherFiles){ + songObj.lyrics = true + songObj.lyricsFile = this.otherFiles[lyricsFile] + } + }else if(meta.inlineLyrics){ + songObj.lyrics = true + } for(var id in allStrings){ var songTitle = songObj.title var ura = "" diff --git a/public/src/js/loadsong.js b/public/src/js/loadsong.js index a3e2485..28285dc 100644 --- a/public/src/js/loadsong.js +++ b/public/src/js/loadsong.js @@ -137,6 +137,13 @@ class LoadSong{ reader.readAsText(songObj.chart) } } + if(songObj.lyricsFile){ + var reader = new FileReader() + this.addPromise(pageEvents.load(reader).then(event => { + songObj.lyricsData = event.target.result + }), songObj.lyricsFile.webkitRelativePath) + reader.readAsText(songObj.lyricsFile) + } }else{ var url = this.getSongPath(song) this.addPromise(loader.ajax(url).then(data => { diff --git a/public/src/js/lyrics.js b/public/src/js/lyrics.js index f2708a2..d4974b3 100644 --- a/public/src/js/lyrics.js +++ b/public/src/js/lyrics.js @@ -1,5 +1,5 @@ class Lyrics{ - constructor(file, songOffset, div){ + constructor(file, songOffset, div, parsed){ this.div = div this.stroke = document.createElement("div") this.stroke.classList.add("stroke") @@ -12,7 +12,7 @@ class Lyrics{ this.songOffset = songOffset || 0 this.vttOffset = 0 this.rLinebreak = /\n|\r\n/ - this.lines = this.parseFile(file) + this.lines = parsed ? file : this.parseFile(file) this.length = this.lines.length } parseFile(file){ diff --git a/public/src/js/parsetja.js b/public/src/js/parsetja.js index 6c51ef1..2296dbc 100644 --- a/public/src/js/parsetja.js +++ b/public/src/js/parsetja.js @@ -84,6 +84,8 @@ } }else if(name.startsWith("branchstart") && inSong){ courses[courseName].branch = true + }else if(name.startsWith("lyric") && inSong){ + courses[courseName].inlineLyrics = true } }else if(!inSong){ @@ -411,6 +413,18 @@ } branchObj[branchName] = currentBranch break + case "lyric": + if(!this.lyrics){ + this.lyrics = [] + } + if(this.lyrics.length !== 0){ + this.lyrics[this.lyrics.length - 1].end = ms + } + this.lyrics.push({ + start: ms, + text: value.trim() + }) + break } }else{ @@ -545,6 +559,10 @@ this.scoreinit = autoscore.ScoreInit; this.scorediff = autoscore.ScoreDiff; } + if(this.lyrics){ + var line = this.lyrics[this.lyrics.length - 1] + line.end = Math.max(ms, line.start) + 5000 + } return circles } }