2019-01-05 15:44:28 +08:00
|
|
|
|
class ImportSongs{
|
|
|
|
|
constructor(songSelect, event){
|
|
|
|
|
this.songSelect = songSelect
|
|
|
|
|
this.songSelect.redrawRunning = false
|
|
|
|
|
this.songSelect.pointer(false)
|
|
|
|
|
|
|
|
|
|
this.loaderDiv = document.createElement("div")
|
|
|
|
|
this.loaderDiv.innerHTML = assets.pages["loadsong"]
|
|
|
|
|
loader.screen.appendChild(this.loaderDiv)
|
|
|
|
|
var loadingText = document.getElementById("loading-text")
|
|
|
|
|
loadingText.appendChild(document.createTextNode(strings.loading))
|
|
|
|
|
loadingText.setAttribute("alt", strings.loading)
|
|
|
|
|
|
|
|
|
|
var files = []
|
|
|
|
|
for(var i = 0; i < event.target.files.length; i++){
|
|
|
|
|
files.push(event.target.files[i])
|
|
|
|
|
}
|
|
|
|
|
var extensionRegex = /\.[^\/]+$/
|
|
|
|
|
files.sort((a, b) => {
|
|
|
|
|
var path1 = a.webkitRelativePath.replace(extensionRegex, "")
|
|
|
|
|
var path2 = b.webkitRelativePath.replace(extensionRegex, "")
|
|
|
|
|
return path1 > path2 ? 1 : -1
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
this.tjaFiles = []
|
|
|
|
|
this.osuFiles = []
|
2019-02-03 20:04:25 +08:00
|
|
|
|
this.assetFiles = {}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
var metaFiles = []
|
|
|
|
|
this.otherFiles = {}
|
|
|
|
|
this.songs = []
|
2019-02-03 20:04:25 +08:00
|
|
|
|
this.stylesheet = []
|
2019-01-05 15:44:28 +08:00
|
|
|
|
this.courseTypes = {
|
|
|
|
|
"easy": 0,
|
|
|
|
|
"normal": 1,
|
|
|
|
|
"hard": 2,
|
|
|
|
|
"oni": 3,
|
|
|
|
|
"ura": 4
|
|
|
|
|
}
|
|
|
|
|
this.categories = {
|
|
|
|
|
"ボーカロイド曲": "ボーカロイド™曲",
|
|
|
|
|
"ボーカロイド": "ボーカロイド™曲",
|
|
|
|
|
"vocaloid music": "ボーカロイド™曲",
|
|
|
|
|
"vocaloid": "ボーカロイド™曲",
|
|
|
|
|
"バラエティー": "バラエティ",
|
|
|
|
|
"どうよう": "バラエティ",
|
|
|
|
|
"童謡・民謡": "バラエティ",
|
|
|
|
|
"children": "バラエティ",
|
|
|
|
|
"children/folk": "バラエティ",
|
|
|
|
|
"children-folk": "バラエティ",
|
|
|
|
|
"クラッシック": "クラシック",
|
2019-01-25 09:42:05 +08:00
|
|
|
|
"classic": "クラシック"
|
|
|
|
|
}
|
|
|
|
|
for(var i in allStrings){
|
|
|
|
|
for(var ja in allStrings[i].categories){
|
|
|
|
|
this.categories[allStrings[i].categories[ja].toLowerCase()] = ja
|
|
|
|
|
}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
}
|
2019-02-03 20:04:25 +08:00
|
|
|
|
this.assetSelectors = {
|
|
|
|
|
"bg-pattern-1": ".pattern-bg",
|
|
|
|
|
"bg_genre_0": "#song-select",
|
|
|
|
|
"title-screen": "#title-screen",
|
|
|
|
|
"dancing-don": "#loading-don",
|
|
|
|
|
"touch_drum": "#touch-drum-img",
|
|
|
|
|
"touch_fullscreen": "#touch-full-btn",
|
|
|
|
|
"touch_pause": "#touch-pause-btn",
|
|
|
|
|
"bg_stage_1": ".song-stage-1",
|
|
|
|
|
"bg_stage_2": ".song-stage-2",
|
|
|
|
|
"bg_stage_3": ".song-stage-3"
|
|
|
|
|
}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
|
|
|
|
|
for(var i = 0; i < files.length; i++){
|
|
|
|
|
var file = files[i]
|
|
|
|
|
var name = file.name.toLowerCase()
|
|
|
|
|
var path = file.webkitRelativePath.toLowerCase()
|
|
|
|
|
if(name.endsWith(".tja")){
|
|
|
|
|
this.tjaFiles.push({
|
|
|
|
|
file: file,
|
|
|
|
|
index: i
|
|
|
|
|
})
|
|
|
|
|
}else if(name.endsWith(".osu")){
|
|
|
|
|
this.osuFiles.push({
|
|
|
|
|
file: file,
|
|
|
|
|
index: i
|
|
|
|
|
})
|
|
|
|
|
}else if(name === "genre.ini" || name === "box.def"){
|
|
|
|
|
var level = (file.webkitRelativePath.match(/\//g) || []).length
|
|
|
|
|
metaFiles.push({
|
|
|
|
|
file: file,
|
|
|
|
|
level: (level * 2) + (name === "genre.ini" ? 1 : 0)
|
|
|
|
|
})
|
2019-02-03 20:04:25 +08:00
|
|
|
|
}else if(path.indexOf("/taiko-web assets/") !== -1){
|
|
|
|
|
if(!(name in this.assetFiles)){
|
|
|
|
|
this.assetFiles[name] = file
|
|
|
|
|
}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
}else{
|
2019-02-03 20:04:25 +08:00
|
|
|
|
this.otherFiles[path] = file
|
2019-01-05 15:44:28 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var metaPromises = []
|
|
|
|
|
|
|
|
|
|
metaFiles.forEach(fileObj => {
|
|
|
|
|
metaPromises.push(this.addMeta(fileObj))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
Promise.all(metaPromises).then(() => {
|
|
|
|
|
var songPromises = []
|
|
|
|
|
|
|
|
|
|
this.tjaFiles.forEach(fileObj => {
|
|
|
|
|
songPromises.push(this.addTja(fileObj))
|
|
|
|
|
})
|
|
|
|
|
this.osuFiles.forEach(fileObj => {
|
|
|
|
|
songPromises.push(this.addOsu(fileObj))
|
|
|
|
|
})
|
2019-02-03 20:04:25 +08:00
|
|
|
|
songPromises.push(this.addAssets())
|
2019-01-05 15:44:28 +08:00
|
|
|
|
Promise.all(songPromises).then(this.loaded.bind(this))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addMeta(fileObj){
|
|
|
|
|
var file = fileObj.file
|
|
|
|
|
var level = fileObj.level
|
|
|
|
|
var name = file.name.toLowerCase()
|
|
|
|
|
var reader = new FileReader()
|
|
|
|
|
var promise = pageEvents.load(reader).then(event => {
|
|
|
|
|
var data = event.target.result.replace(/\0/g, "").split("\n")
|
|
|
|
|
var category
|
|
|
|
|
if(name === "genre.ini"){
|
|
|
|
|
var key
|
|
|
|
|
for(var i = 0; i < data.length; i++){
|
|
|
|
|
var line = data[i].trim().toLowerCase()
|
|
|
|
|
if(line.startsWith("[") && line.endsWith("]")){
|
|
|
|
|
key = line.slice(1, -1)
|
|
|
|
|
}else if(key === "genre"){
|
|
|
|
|
var equalsPos = line.indexOf("=")
|
|
|
|
|
if(equalsPos !== -1 && line.slice(0, equalsPos).trim() === "genrename"){
|
|
|
|
|
var value = line.slice(equalsPos + 1).trim()
|
|
|
|
|
category = this.categories[value] || data[i].trim().slice(equalsPos + 1).trim()
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}else if(name === "box.def"){
|
|
|
|
|
for(var i = 0; i < data.length; i++){
|
|
|
|
|
var line = data[i].trim().toLowerCase()
|
|
|
|
|
if(line.startsWith("#title:")){
|
|
|
|
|
var value = line.slice(7).trim()
|
|
|
|
|
if(value in this.categories){
|
|
|
|
|
category = this.categories[value]
|
|
|
|
|
}
|
|
|
|
|
}else if(line.startsWith("#genre:")){
|
|
|
|
|
var value = line.slice(7).trim()
|
|
|
|
|
category = this.categories[value] || data[i].trim().slice(7).trim()
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(category){
|
|
|
|
|
var metaPath = file.webkitRelativePath.toLowerCase().slice(0, file.name.length * -1)
|
2019-01-05 20:24:09 +08:00
|
|
|
|
var filesLoop = fileObj => {
|
2019-01-05 15:44:28 +08:00
|
|
|
|
var tjaPath = fileObj.file.webkitRelativePath.toLowerCase().slice(0, fileObj.file.name.length * -1)
|
|
|
|
|
if(tjaPath.startsWith(metaPath) && (!("categoryLevel" in fileObj) || fileObj.categoryLevel < level)){
|
|
|
|
|
fileObj.category = category
|
|
|
|
|
fileObj.categoryLevel = level
|
|
|
|
|
}
|
2019-01-05 20:24:09 +08:00
|
|
|
|
}
|
|
|
|
|
this.tjaFiles.forEach(filesLoop)
|
|
|
|
|
this.osuFiles.forEach(filesLoop)
|
2019-01-05 15:44:28 +08:00
|
|
|
|
}
|
|
|
|
|
}).catch(() => {})
|
|
|
|
|
reader.readAsText(file, "sjis")
|
|
|
|
|
return promise
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addTja(fileObj){
|
|
|
|
|
var file = fileObj.file
|
|
|
|
|
var index = fileObj.index
|
|
|
|
|
var category = fileObj.category
|
|
|
|
|
var reader = new FileReader()
|
|
|
|
|
var promise = pageEvents.load(reader).then(event => {
|
|
|
|
|
var data = event.target.result.replace(/\0/g, "").split("\n")
|
|
|
|
|
var tja = new ParseTja(data, "oni", 0, true)
|
|
|
|
|
var songObj = {
|
|
|
|
|
id: index + 1,
|
|
|
|
|
type: "tja",
|
|
|
|
|
chart: data,
|
|
|
|
|
stars: []
|
|
|
|
|
}
|
|
|
|
|
var dir = file.webkitRelativePath.toLowerCase()
|
|
|
|
|
dir = dir.slice(0, dir.lastIndexOf("/") + 1)
|
|
|
|
|
var hasCategory = false
|
|
|
|
|
for(var diff in tja.metadata){
|
|
|
|
|
var meta = tja.metadata[diff]
|
|
|
|
|
songObj.title = songObj.title_en = meta.title || file.name.slice(0, file.name.lastIndexOf("."))
|
|
|
|
|
var subtitle = meta.subtitle || ""
|
|
|
|
|
if(subtitle.startsWith("--")){
|
|
|
|
|
subtitle = subtitle.slice(2)
|
|
|
|
|
}
|
|
|
|
|
songObj.subtitle = songObj.subtitle_en = subtitle
|
|
|
|
|
songObj.preview = meta.demostart ? Math.floor(meta.demostart * 1000) : 0
|
|
|
|
|
if(meta.level){
|
|
|
|
|
songObj.stars[this.courseTypes[diff]] = meta.level
|
|
|
|
|
}
|
|
|
|
|
if(meta.wave){
|
|
|
|
|
songObj.music = this.otherFiles[dir + meta.wave.toLowerCase()]
|
|
|
|
|
}
|
2019-01-05 20:24:09 +08:00
|
|
|
|
if(meta.genre){
|
|
|
|
|
songObj.category = this.categories[meta.genre.toLowerCase()] || meta.genre
|
2019-01-05 15:44:28 +08:00
|
|
|
|
}
|
2019-02-03 20:04:25 +08:00
|
|
|
|
if(meta.taikowebskin){
|
|
|
|
|
songObj.song_skin = this.getSkin(dir, meta.taikowebskin)
|
|
|
|
|
}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
}
|
|
|
|
|
if(!songObj.category){
|
|
|
|
|
songObj.category = category || this.getCategory(file)
|
|
|
|
|
}
|
|
|
|
|
if(songObj.music && songObj.stars.filter(star => star).length !== 0){
|
|
|
|
|
this.songs[index] = songObj
|
|
|
|
|
}
|
|
|
|
|
}).catch(() => {})
|
|
|
|
|
reader.readAsText(file, "sjis")
|
|
|
|
|
return promise
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addOsu(fileObj){
|
|
|
|
|
var file = fileObj.file
|
|
|
|
|
var index = fileObj.index
|
|
|
|
|
var category = fileObj.category
|
|
|
|
|
var reader = new FileReader()
|
|
|
|
|
var promise = pageEvents.load(reader).then(event => {
|
|
|
|
|
var data = event.target.result.replace(/\0/g, "").split("\n")
|
|
|
|
|
var osu = new ParseOsu(data, 0, true)
|
|
|
|
|
var dir = file.webkitRelativePath.toLowerCase()
|
|
|
|
|
dir = dir.slice(0, dir.lastIndexOf("/") + 1)
|
|
|
|
|
var songObj = {
|
|
|
|
|
id: index + 1,
|
|
|
|
|
type: "osu",
|
|
|
|
|
chart: data,
|
|
|
|
|
subtitle: osu.metadata.ArtistUnicode || osu.metadata.Artist,
|
|
|
|
|
subtitle_en: osu.metadata.Artist || osu.metadata.ArtistUnicode,
|
|
|
|
|
preview: osu.generalInfo.PreviewTime,
|
|
|
|
|
stars: [null, null, null, parseInt(osu.difficulty.overallDifficulty) || 1],
|
|
|
|
|
music: this.otherFiles[dir + osu.generalInfo.AudioFilename.toLowerCase()]
|
|
|
|
|
}
|
|
|
|
|
var filename = file.name.slice(0, file.name.lastIndexOf("."))
|
|
|
|
|
var title = osu.metadata.TitleUnicode || osu.metadata.Title
|
|
|
|
|
if(title){
|
|
|
|
|
var suffix = ""
|
|
|
|
|
var matches = filename.match(/\[.+?\]$/)
|
|
|
|
|
if(matches){
|
|
|
|
|
suffix = " " + matches[0]
|
|
|
|
|
}
|
|
|
|
|
songObj.title = title + suffix
|
|
|
|
|
songObj.title_en = (osu.metadata.Title || osu.metadata.TitleUnicode) + suffix
|
|
|
|
|
}else{
|
|
|
|
|
songObj.title = filename
|
|
|
|
|
}
|
|
|
|
|
if(songObj.music){
|
|
|
|
|
this.songs[index] = songObj
|
|
|
|
|
}
|
|
|
|
|
songObj.category = category || this.getCategory(file)
|
|
|
|
|
}).catch(() => {})
|
|
|
|
|
reader.readAsText(file)
|
|
|
|
|
return promise
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 20:04:25 +08:00
|
|
|
|
addAssets(){
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
var promises = []
|
|
|
|
|
for(let name in this.assetFiles){
|
|
|
|
|
let id = this.getFilename(name)
|
|
|
|
|
var file = this.assetFiles[name]
|
|
|
|
|
if(name === "vectors.json"){
|
|
|
|
|
var reader = new FileReader()
|
|
|
|
|
promises.push(pageEvents.load(reader).then(() => response => {
|
|
|
|
|
vectors = JSON.parse(response)
|
|
|
|
|
}))
|
|
|
|
|
reader.readAsText(file)
|
|
|
|
|
}
|
|
|
|
|
if(assets.img.indexOf(name) !== -1){
|
|
|
|
|
let image = document.createElement("img")
|
|
|
|
|
promises.push(pageEvents.load(image).then(() => {
|
|
|
|
|
if(id in this.assetSelectors){
|
|
|
|
|
var selector = this.assetSelectors[id]
|
|
|
|
|
this.stylesheet.push(selector + '{background-image:url("' + image.src + '")}')
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
image.id = name
|
|
|
|
|
image.src = URL.createObjectURL(file)
|
|
|
|
|
loader.assetsDiv.appendChild(image)
|
|
|
|
|
assets.image[id].parentNode.removeChild(assets.image[id])
|
|
|
|
|
assets.image[id] = image
|
|
|
|
|
}
|
|
|
|
|
if(assets.audioSfx.indexOf(name) !== -1){
|
|
|
|
|
assets.sounds[id].clean()
|
|
|
|
|
promises.push(this.loadSound(file, name, snd.sfxGain))
|
|
|
|
|
}
|
|
|
|
|
if(assets.audioMusic.indexOf(name) !== -1){
|
|
|
|
|
assets.sounds[id].clean()
|
|
|
|
|
promises.push(this.loadSound(file, name, snd.musicGain))
|
|
|
|
|
}
|
|
|
|
|
if(assets.audioSfxLR.indexOf(name) !== -1){
|
|
|
|
|
assets.sounds[id + "_p1"].clean()
|
|
|
|
|
assets.sounds[id + "_p2"].clean()
|
|
|
|
|
promises.push(this.loadSound(file, name, snd.sfxGain).then(sound => {
|
|
|
|
|
assets.sounds[id + "_p1"] = assets.sounds[id].copy(snd.sfxGainL)
|
|
|
|
|
assets.sounds[id + "_p2"] = assets.sounds[id].copy(snd.sfxGainR)
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
if(assets.audioSfxLoud.indexOf(name) !== -1){
|
|
|
|
|
assets.sounds[id].clean()
|
|
|
|
|
promises.push(this.loadSound(file, name, snd.sfxLoudGain))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Promise.all(promises).then(resolve, reject)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
loadSound(file, name, gain){
|
|
|
|
|
var id = this.getFilename(name)
|
|
|
|
|
return gain.load(file, true).then(sound => {
|
|
|
|
|
assets.sounds[id] = sound
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
getFilename(name){
|
|
|
|
|
return name.slice(0, name.lastIndexOf("."))
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-05 15:44:28 +08:00
|
|
|
|
getCategory(file){
|
|
|
|
|
var path = file.webkitRelativePath.toLowerCase().split("/")
|
|
|
|
|
for(var i = path.length - 2; i >= 0; i--){
|
|
|
|
|
for(var cat in this.categories){
|
|
|
|
|
if(path[i].indexOf(cat) !== -1){
|
|
|
|
|
return this.categories[cat]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 20:04:25 +08:00
|
|
|
|
getSkin(dir, config){
|
|
|
|
|
var configArray = config.toLowerCase().split(",")
|
|
|
|
|
var configObj = {}
|
|
|
|
|
for(var i in configArray){
|
|
|
|
|
var string = configArray[i].trim()
|
|
|
|
|
var space = string.indexOf(" ")
|
|
|
|
|
if(space !== -1){
|
|
|
|
|
configObj[string.slice(0, space).trim()] = string.slice(space + 1).trim()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(!configObj.dir){
|
|
|
|
|
configObj.dir = ""
|
|
|
|
|
}
|
|
|
|
|
configObj.prefix = "custom "
|
|
|
|
|
var skinnable = ["song", "stage", "don"]
|
|
|
|
|
for(var i in skinnable){
|
|
|
|
|
var skinName = skinnable[i]
|
|
|
|
|
var skinValue = configObj[skinName]
|
|
|
|
|
if(skinValue && skinValue !== "none"){
|
|
|
|
|
var fileName = "bg_" + skinName + "_" + configObj.name
|
|
|
|
|
var skinPath = this.joinPath(dir, configObj.dir, fileName)
|
|
|
|
|
for(var j = 0; j < 2; j++){
|
|
|
|
|
if(skinValue !== "static"){
|
|
|
|
|
var suffix = (j === 0 ? "_a" : "_b") + ".png"
|
|
|
|
|
}else{
|
|
|
|
|
var suffix = ".png"
|
|
|
|
|
}
|
|
|
|
|
var skinFull = this.normPath(skinPath + suffix)
|
|
|
|
|
if(skinFull in this.otherFiles){
|
|
|
|
|
configObj[fileName + suffix] = this.otherFiles[skinFull]
|
|
|
|
|
}else{
|
|
|
|
|
configObj[skinName] = null
|
|
|
|
|
}
|
|
|
|
|
if(skinValue === "static"){
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return configObj
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-05 15:44:28 +08:00
|
|
|
|
loaded(){
|
|
|
|
|
this.songs = this.songs.filter(song => typeof song !== "undefined")
|
2019-02-03 20:04:25 +08:00
|
|
|
|
if(this.stylesheet.length){
|
|
|
|
|
var style = document.createElement("style")
|
|
|
|
|
style.appendChild(document.createTextNode(this.stylesheet.join("\n")))
|
|
|
|
|
document.head.appendChild(style)
|
|
|
|
|
}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
if(this.songs.length){
|
Custom scripting, #song=, translations
- A song can be linked directly by adding "#song=<id>" to the url, replace `<id>` with the id in the database, after loading it jumps immediately jumps to the difficulty selection
- Added tutorial translations
- Fixed song preview not playing
- Use text fallback for the logo when there are no vectors
- Increased combo cache by 1 pixel
- A custom javascript file can be loaded from config.json by defining "custom_js" value
- Added lots of events to help writing custom js files: `version-link, title-screen, language-change, song-select, song-select-move, song-select-difficulty, song-select-back, about, about-link, tutorial, import-songs, import-songs-default, session, session-start, session-end, debug, load-song, load-song-player2, load-song-unfocused, load-song-cancel, load-song-error, game-start, key-events, p2-game-end, p2-disconnected, p2-abandoned, pause, unpause, pause-restart, pause-song-select, game-lag, scoresheet, scoresheet-player2`
- Event syntax example:
```js
addEventListener("game-start", event => {
console.log("game-start", event.detail)
})
```
2019-02-14 17:32:45 +08:00
|
|
|
|
var length = this.songs.length
|
2019-01-05 15:44:28 +08:00
|
|
|
|
assets.songs = this.songs
|
|
|
|
|
assets.customSongs = true
|
|
|
|
|
assets.customSelected = 0
|
2019-02-04 17:14:42 +08:00
|
|
|
|
assets.sounds["se_don"].play()
|
2019-01-05 15:44:28 +08:00
|
|
|
|
this.songSelect.clean()
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
loader.screen.removeChild(this.loaderDiv)
|
|
|
|
|
this.clean()
|
|
|
|
|
new SongSelect("browse", false, this.songSelect.touchEnabled)
|
Custom scripting, #song=, translations
- A song can be linked directly by adding "#song=<id>" to the url, replace `<id>` with the id in the database, after loading it jumps immediately jumps to the difficulty selection
- Added tutorial translations
- Fixed song preview not playing
- Use text fallback for the logo when there are no vectors
- Increased combo cache by 1 pixel
- A custom javascript file can be loaded from config.json by defining "custom_js" value
- Added lots of events to help writing custom js files: `version-link, title-screen, language-change, song-select, song-select-move, song-select-difficulty, song-select-back, about, about-link, tutorial, import-songs, import-songs-default, session, session-start, session-end, debug, load-song, load-song-player2, load-song-unfocused, load-song-cancel, load-song-error, game-start, key-events, p2-game-end, p2-disconnected, p2-abandoned, pause, unpause, pause-restart, pause-song-select, game-lag, scoresheet, scoresheet-player2`
- Event syntax example:
```js
addEventListener("game-start", event => {
console.log("game-start", event.detail)
})
```
2019-02-14 17:32:45 +08:00
|
|
|
|
pageEvents.send("import-songs", length)
|
2019-01-05 15:44:28 +08:00
|
|
|
|
}, 500)
|
|
|
|
|
}else{
|
|
|
|
|
loader.screen.removeChild(this.loaderDiv)
|
|
|
|
|
this.songSelect.browse.parentNode.reset()
|
|
|
|
|
this.songSelect.redrawRunning = true
|
|
|
|
|
this.clean()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 20:04:25 +08:00
|
|
|
|
joinPath(){
|
|
|
|
|
var resultPath = arguments[0]
|
|
|
|
|
for(var i = 1; i < arguments.length; i++){
|
|
|
|
|
var pPath = arguments[i]
|
|
|
|
|
if(pPath && (pPath[0] === "/" || pPath[0] === "\\")){
|
|
|
|
|
resultPath = pPath
|
|
|
|
|
}else{
|
|
|
|
|
var lastChar = resultPath.slice(-1)
|
|
|
|
|
if(resultPath && (lastChar !== "/" || lastChar !== "\\")){
|
|
|
|
|
resultPath = resultPath + "/"
|
|
|
|
|
}
|
|
|
|
|
resultPath = resultPath + pPath
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return resultPath
|
|
|
|
|
}
|
|
|
|
|
normPath(path){
|
|
|
|
|
path = path.replace(/\\/g, "/").toLowerCase()
|
|
|
|
|
while(path[0] === "/"){
|
|
|
|
|
path = path.slice(1)
|
|
|
|
|
}
|
|
|
|
|
var comps = path.split("/")
|
|
|
|
|
for(var i = 0; i < comps.length; i++){
|
|
|
|
|
if(comps[i] === "." || comps[i] === ""){
|
|
|
|
|
comps.splice(i, 1)
|
|
|
|
|
i--
|
|
|
|
|
}else if(i !== 0 && comps[i] === ".." && comps[i - 1] !== ".."){
|
|
|
|
|
comps.splice(i - 1, 2)
|
|
|
|
|
i -= 2
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return comps.join("/")
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-05 15:44:28 +08:00
|
|
|
|
clean(){
|
|
|
|
|
delete this.loaderDiv
|
|
|
|
|
delete this.songs
|
|
|
|
|
delete this.tjaFiles
|
|
|
|
|
delete this.osuFiles
|
|
|
|
|
delete this.otherFiles
|
|
|
|
|
}
|
|
|
|
|
}
|