SongSel: Add browse for local songs button
This commit is contained in:
parent
7f5b1e97c3
commit
a435ed1a6d
@ -19,7 +19,8 @@ body{
|
|||||||
background-size: 30vh;
|
background-size: 30vh;
|
||||||
font-family: TnT, Meiryo, sans-serif;
|
font-family: TnT, Meiryo, sans-serif;
|
||||||
}
|
}
|
||||||
#assets{
|
#assets,
|
||||||
|
#browse{
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.window{
|
.window{
|
||||||
|
@ -51,8 +51,8 @@
|
|||||||
ideographicComma: /[、。]/,
|
ideographicComma: /[、。]/,
|
||||||
apostrophe: /['']/,
|
apostrophe: /['']/,
|
||||||
degree: /[゚°]/,
|
degree: /[゚°]/,
|
||||||
brackets: /[\((\))「」『』]/,
|
brackets: /[\((\))\[\]「」『』【】]/,
|
||||||
tilde: /[\--~~〜]/,
|
tilde: /[\--~~〜_]/,
|
||||||
tall: /[bbddffgghhj-lj-ltt♪]/,
|
tall: /[bbddffgghhj-lj-ltt♪]/,
|
||||||
i: /[ii]/,
|
i: /[ii]/,
|
||||||
uppercase: /[A-ZA-Z]/,
|
uppercase: /[A-ZA-Z]/,
|
||||||
@ -68,7 +68,8 @@
|
|||||||
em: /[mwmw]/,
|
em: /[mwmw]/,
|
||||||
emCap: /[MWMW]/,
|
emCap: /[MWMW]/,
|
||||||
rWidth: /[abdfIjo-rtvabdfIjo-rtv]/,
|
rWidth: /[abdfIjo-rtvabdfIjo-rtv]/,
|
||||||
lWidth: /[ilil]/
|
lWidth: /[ilil]/,
|
||||||
|
ura: /\s*[\((]裏[\))]$/
|
||||||
}
|
}
|
||||||
|
|
||||||
var numbersFull = "0123456789"
|
var numbersFull = "0123456789"
|
||||||
@ -276,13 +277,18 @@
|
|||||||
var ctx = config.ctx
|
var ctx = config.ctx
|
||||||
var inputText = config.text
|
var inputText = config.text
|
||||||
var mul = config.fontSize / 40
|
var mul = config.fontSize / 40
|
||||||
|
var ura = false
|
||||||
|
var r = this.regex
|
||||||
|
|
||||||
|
var matches = inputText.match(r.ura)
|
||||||
|
if(matches){
|
||||||
|
inputText = inputText.slice(0, matches.index)
|
||||||
|
ura = matches[0]
|
||||||
|
}
|
||||||
|
|
||||||
var string = inputText.split("")
|
var string = inputText.split("")
|
||||||
var drawn = []
|
var drawn = []
|
||||||
|
|
||||||
var r = this.regex
|
|
||||||
var previousSymbol = ""
|
|
||||||
|
|
||||||
for(var i = 0; i < string.length; i++){
|
for(var i = 0; i < string.length; i++){
|
||||||
let symbol = string[i]
|
let symbol = string[i]
|
||||||
if(symbol === " "){
|
if(symbol === " "){
|
||||||
@ -297,6 +303,8 @@
|
|||||||
drawn.push({text: symbol, x: 0, y: 12, h: 45})
|
drawn.push({text: symbol, x: 0, y: 12, h: 45})
|
||||||
}else if(symbol === "."){
|
}else if(symbol === "."){
|
||||||
drawn.push({realText: symbol, text: ".", x: 13, y: -7, h: 15, scale: [1.2, 0.7]})
|
drawn.push({realText: symbol, text: ".", x: 13, y: -7, h: 15, scale: [1.2, 0.7]})
|
||||||
|
}else if(symbol === "…"){
|
||||||
|
drawn.push({text: symbol, x: 0, y: 5, h: 25, rotate: true})
|
||||||
}else if(r.comma.test(symbol)){
|
}else if(r.comma.test(symbol)){
|
||||||
// Comma, full stop
|
// Comma, full stop
|
||||||
drawn.push({text: symbol, x: 13, y: -7, h: 15, scale: [1.2, 0.7]})
|
drawn.push({text: symbol, x: 13, y: -7, h: 15, scale: [1.2, 0.7]})
|
||||||
@ -408,22 +416,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var scaling = 1
|
var scaling = 1
|
||||||
if(config.height && drawnHeight > config.height){
|
var height = config.height - (ura ? 52 * mul : 0)
|
||||||
|
if(height && drawnHeight > height){
|
||||||
if(config.align === "bottom"){
|
if(config.align === "bottom"){
|
||||||
scaling = Math.max(0.6, config.height / drawnHeight)
|
scaling = Math.max(0.6, height / drawnHeight)
|
||||||
ctx.translate(40 * mul, 0)
|
ctx.translate(40 * mul, 0)
|
||||||
ctx.scale(scaling, config.height / drawnHeight)
|
ctx.scale(scaling, height / drawnHeight)
|
||||||
ctx.translate(-40 * mul, 0)
|
ctx.translate(-40 * mul, 0)
|
||||||
}else{
|
}else{
|
||||||
scaling = config.height / drawnHeight
|
scaling = height / drawnHeight
|
||||||
ctx.scale(1, scaling)
|
ctx.scale(1, scaling)
|
||||||
}
|
}
|
||||||
if(config.selectable){
|
if(config.selectable){
|
||||||
style.transform = "scale(1, " + scaling + ")"
|
style.transform = "scale(1, " + scaling + ")"
|
||||||
style.top = (config.y + (config.height - drawnHeight) / 2 - 15 / 2 * scaling) * scale + "px"
|
style.top = (config.y + (height - drawnHeight) / 2 - 15 / 2 * scaling) * scale + "px"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ura){
|
||||||
|
// Circled ura
|
||||||
|
drawn.push({realText: ura, text: "裏", x: 0, y: 18, h: 52, ura: true, scale: [1, 1 / scale]})
|
||||||
|
}
|
||||||
|
|
||||||
var actions = []
|
var actions = []
|
||||||
if(config.outline){
|
if(config.outline){
|
||||||
actions.push("stroke")
|
actions.push("stroke")
|
||||||
@ -492,7 +506,7 @@
|
|||||||
config.selectable.appendChild(div)
|
config.selectable.appendChild(div)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if(symbol.rotate || symbol.scale || symbol.svg){
|
if(symbol.rotate || symbol.scale || symbol.svg || symbol.ura){
|
||||||
saved = true
|
saved = true
|
||||||
ctx.save()
|
ctx.save()
|
||||||
|
|
||||||
@ -517,8 +531,24 @@
|
|||||||
}else{
|
}else{
|
||||||
ctx.textAlign = "center"
|
ctx.textAlign = "center"
|
||||||
}
|
}
|
||||||
|
if(symbol.ura){
|
||||||
|
ctx.font = (30 * mul) + "px Meiryo, sans-serif"
|
||||||
|
ctx.textBaseline = "center"
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.arc(currentX, currentY + (21.5 * mul), (18 * mul), 0, Math.PI * 2)
|
||||||
|
if(action === "stroke"){
|
||||||
|
ctx.fillStyle = config.outline
|
||||||
|
ctx.fill()
|
||||||
|
}else if(action === "fill"){
|
||||||
|
ctx.strokeStyle = config.fill
|
||||||
|
ctx.lineWidth = 2.5 * mul
|
||||||
|
ctx.fillText(symbol.text, currentX, currentY)
|
||||||
|
}
|
||||||
|
ctx.stroke()
|
||||||
|
}else{
|
||||||
ctx[action + "Text"](symbol.text, currentX, currentY)
|
ctx[action + "Text"](symbol.text, currentX, currentY)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(saved){
|
if(saved){
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,8 @@ class Loader{
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.promises.push(this.ajax("/api/songs").then(songs => {
|
this.promises.push(this.ajax("/api/songs").then(songs => {
|
||||||
assets.songs = JSON.parse(songs)
|
assets.songsDefault = JSON.parse(songs)
|
||||||
|
assets.songs = assets.songsDefault
|
||||||
}))
|
}))
|
||||||
|
|
||||||
assets.views.forEach(name => {
|
assets.views.forEach(name => {
|
||||||
|
@ -66,16 +66,17 @@ class loadSong{
|
|||||||
}
|
}
|
||||||
promises.push(this.loadSongBg(id))
|
promises.push(this.loadSongBg(id))
|
||||||
|
|
||||||
|
var songObj = assets.songs.find(song => song.id === id)
|
||||||
|
|
||||||
promises.push(new Promise((resolve, reject) => {
|
promises.push(new Promise((resolve, reject) => {
|
||||||
var songObj
|
|
||||||
assets.songs.forEach(song => {
|
|
||||||
if(song.id == id){
|
|
||||||
songObj = song
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if(songObj.sound){
|
if(songObj.sound){
|
||||||
songObj.sound.gain = snd.musicGain
|
songObj.sound.gain = snd.musicGain
|
||||||
resolve()
|
resolve()
|
||||||
|
}else if(songObj.music){
|
||||||
|
snd.musicGain.load(songObj.music, true).then(sound => {
|
||||||
|
songObj.sound = sound
|
||||||
|
resolve()
|
||||||
|
}, reject)
|
||||||
}else{
|
}else{
|
||||||
snd.musicGain.load(gameConfig.songs_baseurl + id + "/main.mp3").then(sound => {
|
snd.musicGain.load(gameConfig.songs_baseurl + id + "/main.mp3").then(sound => {
|
||||||
songObj.sound = sound
|
songObj.sound = sound
|
||||||
@ -83,9 +84,13 @@ class loadSong{
|
|||||||
}, reject)
|
}, reject)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
if(songObj.chart){
|
||||||
|
this.songData = songObj.chart
|
||||||
|
}else{
|
||||||
promises.push(loader.ajax(this.getSongPath(song)).then(data => {
|
promises.push(loader.ajax(this.getSongPath(song)).then(data => {
|
||||||
this.songData = data.replace(/\0/g, "").split("\n")
|
this.songData = data.replace(/\0/g, "").split("\n")
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
Promise.all(promises).then(() => {
|
Promise.all(promises).then(() => {
|
||||||
this.setupMultiplayer()
|
this.setupMultiplayer()
|
||||||
}, error => {
|
}, error => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
class ParseOsu{
|
class ParseOsu{
|
||||||
constructor(fileContent, offset){
|
constructor(fileContent, offset, metaOnly){
|
||||||
this.osu = {
|
this.osu = {
|
||||||
OFFSET: 0,
|
OFFSET: 0,
|
||||||
MSPERBEAT: 1,
|
MSPERBEAT: 1,
|
||||||
@ -52,10 +52,12 @@ class ParseOsu{
|
|||||||
this.metadata = this.parseMetadata()
|
this.metadata = this.parseMetadata()
|
||||||
this.editor = this.parseEditor()
|
this.editor = this.parseEditor()
|
||||||
this.difficulty = this.parseDifficulty()
|
this.difficulty = this.parseDifficulty()
|
||||||
|
if(!metaOnly){
|
||||||
this.timingPoints = this.parseTiming()
|
this.timingPoints = this.parseTiming()
|
||||||
this.circles = this.parseCircles()
|
this.circles = this.parseCircles()
|
||||||
this.measures = this.parseMeasures()
|
this.measures = this.parseMeasures()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
getStartEndIndexes(type){
|
getStartEndIndexes(type){
|
||||||
var indexes = {
|
var indexes = {
|
||||||
start: 0,
|
start: 0,
|
||||||
@ -186,40 +188,20 @@ class ParseOsu{
|
|||||||
return measures
|
return measures
|
||||||
}
|
}
|
||||||
parseGeneralInfo(){
|
parseGeneralInfo(){
|
||||||
var generalInfo = {
|
var generalInfo = {}
|
||||||
audioFilename: "",
|
|
||||||
audioWait: 0
|
|
||||||
}
|
|
||||||
var indexes = this.getStartEndIndexes("General")
|
var indexes = this.getStartEndIndexes("General")
|
||||||
for(var i = indexes.start; i<= indexes.end; i++){
|
for(var i = indexes.start; i<= indexes.end; i++){
|
||||||
var [item, key] = this.data[i].split(":")
|
var [item, key] = this.data[i].split(":")
|
||||||
switch(item){
|
generalInfo[item] = key.trim()
|
||||||
case "SliderMultiple":
|
|
||||||
generalInfo.audioFilename = key
|
|
||||||
break
|
|
||||||
case "AudioWait":
|
|
||||||
generalInfo.audioWait = parseInt(key)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return generalInfo
|
return generalInfo
|
||||||
}
|
}
|
||||||
parseMetadata(){
|
parseMetadata(){
|
||||||
var metadata = {
|
var metadata = {}
|
||||||
title: "",
|
|
||||||
artist: ""
|
|
||||||
}
|
|
||||||
var indexes = this.getStartEndIndexes("Metadata")
|
var indexes = this.getStartEndIndexes("Metadata")
|
||||||
for(var i = indexes.start; i <= indexes.end; i++){
|
for(var i = indexes.start; i <= indexes.end; i++){
|
||||||
var [item, key] = this.data[i].split(":")
|
var [item, key] = this.data[i].split(":")
|
||||||
switch(item){
|
metadata[item] = key.trim()
|
||||||
case "TitleUnicode":
|
|
||||||
metadata.title = key
|
|
||||||
break
|
|
||||||
case "ArtistUnicode":
|
|
||||||
metadata.artist = key
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return metadata
|
return metadata
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
class ParseTja{
|
class ParseTja{
|
||||||
constructor(file, difficulty, offset){
|
constructor(file, difficulty, offset, metaOnly){
|
||||||
this.data = []
|
this.data = []
|
||||||
for(let line of file){
|
for(let line of file){
|
||||||
line = line.replace(/\/\/.*/, "").trim()
|
line = line.replace(/\/\/.*/, "").trim()
|
||||||
@ -34,10 +34,12 @@
|
|||||||
this.metadata = this.parseMetadata()
|
this.metadata = this.parseMetadata()
|
||||||
this.measures = []
|
this.measures = []
|
||||||
this.beatInfo = {}
|
this.beatInfo = {}
|
||||||
|
if(!metaOnly){
|
||||||
this.circles = this.parseCircles()
|
this.circles = this.parseCircles()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
parseMetadata(){
|
parseMetadata(){
|
||||||
var metaNumbers = ["bpm", "offset"]
|
var metaNumbers = ["bpm", "offset", "demostart", "level"]
|
||||||
var inSong = false
|
var inSong = false
|
||||||
var courses = {}
|
var courses = {}
|
||||||
var currentCourse = {}
|
var currentCourse = {}
|
||||||
|
@ -35,6 +35,12 @@ class SongSelect{
|
|||||||
border: ["#dff0ff", "#6890b2"],
|
border: ["#dff0ff", "#6890b2"],
|
||||||
outline: "#217abb"
|
outline: "#217abb"
|
||||||
},
|
},
|
||||||
|
"browse": {
|
||||||
|
sort: 7,
|
||||||
|
background: "#9791ff",
|
||||||
|
border: ["#e2dfff", "#6d68b2"],
|
||||||
|
outline: "#5350ba"
|
||||||
|
},
|
||||||
"J-POP": {
|
"J-POP": {
|
||||||
sort: 0,
|
sort: 0,
|
||||||
background: "#219fbb",
|
background: "#219fbb",
|
||||||
@ -98,7 +104,8 @@ class SongSelect{
|
|||||||
preview: song.preview || 0,
|
preview: song.preview || 0,
|
||||||
type: song.type,
|
type: song.type,
|
||||||
offset: song.offset,
|
offset: song.offset,
|
||||||
songSkin: song.song_skin || {}
|
songSkin: song.song_skin || {},
|
||||||
|
music: song.music
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.songs.sort((a, b) => {
|
this.songs.sort((a, b) => {
|
||||||
@ -139,6 +146,17 @@ class SongSelect{
|
|||||||
action: "about",
|
action: "about",
|
||||||
category: "ランダム"
|
category: "ランダム"
|
||||||
})
|
})
|
||||||
|
if("webkitdirectory" in HTMLInputElement.prototype && !(/Android|iPhone|iPad/.test(navigator.userAgent))){
|
||||||
|
this.browse = document.getElementById("browse")
|
||||||
|
pageEvents.add(this.browse, "change", this.browseChange.bind(this))
|
||||||
|
|
||||||
|
this.songs.push({
|
||||||
|
title: assets.customSongs ? "デフォルト曲リスト" : "参照する…",
|
||||||
|
skin: this.songSkin.browse,
|
||||||
|
action: "browse",
|
||||||
|
category: "ランダム"
|
||||||
|
})
|
||||||
|
}
|
||||||
this.songs.push({
|
this.songs.push({
|
||||||
title: "もどる",
|
title: "もどる",
|
||||||
skin: this.songSkin.back,
|
skin: this.songSkin.back,
|
||||||
@ -204,8 +222,10 @@ class SongSelect{
|
|||||||
this.selectedSong = this.songs.findIndex(song => song.action === fromTutorial)
|
this.selectedSong = this.songs.findIndex(song => song.action === fromTutorial)
|
||||||
this.playBgm(true)
|
this.playBgm(true)
|
||||||
}else{
|
}else{
|
||||||
if((!p2.session || fadeIn) && "selectedSong" in localStorage){
|
if(assets.customSongs){
|
||||||
this.selectedSong = Math.min(Math.max(0, localStorage["selectedSong"] |0), this.songs.length)
|
this.selectedSong = assets.customSelected
|
||||||
|
}else if((!p2.session || fadeIn) && "selectedSong" in localStorage){
|
||||||
|
this.selectedSong = Math.min(Math.max(0, localStorage["selectedSong"] |0), this.songs.length - 1)
|
||||||
}
|
}
|
||||||
assets.sounds["song-select"].play()
|
assets.sounds["song-select"].play()
|
||||||
snd.musicGain.fadeOut()
|
snd.musicGain.fadeOut()
|
||||||
@ -265,6 +285,7 @@ class SongSelect{
|
|||||||
this.state.moveHover = null
|
this.state.moveHover = null
|
||||||
})
|
})
|
||||||
pageEvents.add(loader.screen, ["mousedown", "touchstart"], this.mouseDown.bind(this))
|
pageEvents.add(loader.screen, ["mousedown", "touchstart"], this.mouseDown.bind(this))
|
||||||
|
pageEvents.add(this.canvas, "touchend", this.touchEnd.bind(this))
|
||||||
if(touchEnabled && fullScreenSupported){
|
if(touchEnabled && fullScreenSupported){
|
||||||
this.touchFullBtn = document.getElementById("touch-full-btn")
|
this.touchFullBtn = document.getElementById("touch-full-btn")
|
||||||
this.touchFullBtn.style.display = "block"
|
this.touchFullBtn.style.display = "block"
|
||||||
@ -404,6 +425,19 @@ class SongSelect{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
touchEnd(event){
|
||||||
|
event.preventDefault()
|
||||||
|
if(this.state.screen === "song"){
|
||||||
|
var currentSong = this.songs[this.selectedSong]
|
||||||
|
if(currentSong.action === "browse"){
|
||||||
|
var mouse = this.mouseOffset(event.changedTouches[0].pageX, event.changedTouches[0].pageY)
|
||||||
|
var moveBy = this.songSelMouse(mouse.x, mouse.y)
|
||||||
|
if(moveBy === 0){
|
||||||
|
this.toBrowse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
mouseMove(event){
|
mouseMove(event){
|
||||||
var mouse = this.mouseOffset(event.offsetX, event.offsetY)
|
var mouse = this.mouseOffset(event.offsetX, event.offsetY)
|
||||||
var moveTo = null
|
var moveTo = null
|
||||||
@ -521,6 +555,119 @@ class SongSelect{
|
|||||||
assets.sounds["ka"].play()
|
assets.sounds["ka"].play()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
browseChange(event){
|
||||||
|
var files = event.target.files
|
||||||
|
var promises = []
|
||||||
|
var tjaFiles = []
|
||||||
|
var osuFiles = []
|
||||||
|
var otherFiles = {}
|
||||||
|
|
||||||
|
for(var i = 0; i < files.length; i++){
|
||||||
|
var file = files[i]
|
||||||
|
var name = file.name.toLowerCase()
|
||||||
|
if(name.endsWith(".tja")){
|
||||||
|
tjaFiles.push([file, i])
|
||||||
|
}else if(name.endsWith(".osu")){
|
||||||
|
osuFiles.push([file, i])
|
||||||
|
}else{
|
||||||
|
otherFiles[file.webkitRelativePath.toLowerCase()] = file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var songs = []
|
||||||
|
var courseTypes = {"easy": 0, "normal": 1, "hard": 2, "oni": 3, "ura": 4}
|
||||||
|
for(var i = 0; i < tjaFiles.length; i++){
|
||||||
|
let file = tjaFiles[i][0]
|
||||||
|
let index = tjaFiles[i][1]
|
||||||
|
var reader = new FileReader()
|
||||||
|
promises.push(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)
|
||||||
|
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[courseTypes[diff]] = meta.level
|
||||||
|
}
|
||||||
|
if(meta.wave){
|
||||||
|
songObj.music = otherFiles[dir + meta.wave.toLowerCase()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(songObj.music && songObj.stars.filter(star => star).length !== 0){
|
||||||
|
songs[index] = songObj
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
reader.readAsText(file, "sjis")
|
||||||
|
}
|
||||||
|
for(var i = 0; i < osuFiles.length; i++){
|
||||||
|
let file = osuFiles[i][0]
|
||||||
|
let index = osuFiles[i][1]
|
||||||
|
var reader = new FileReader()
|
||||||
|
promises.push(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: 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){
|
||||||
|
songs[index] = songObj
|
||||||
|
}
|
||||||
|
}).catch(() => {}))
|
||||||
|
reader.readAsText(file)
|
||||||
|
}
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
songs = songs.filter(song => typeof song !== "undefined")
|
||||||
|
if(songs.length){
|
||||||
|
assets.songs = songs
|
||||||
|
assets.customSongs = true
|
||||||
|
assets.customSelected = 0
|
||||||
|
assets.sounds["don"].play()
|
||||||
|
this.clean()
|
||||||
|
setTimeout(() => {
|
||||||
|
new SongSelect("browse", false, this.touchEnabled)
|
||||||
|
}, 500)
|
||||||
|
}else{
|
||||||
|
this.browse.parentNode.reset()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
toSelectDifficulty(fromP2){
|
toSelectDifficulty(fromP2){
|
||||||
var currentSong = this.songs[this.selectedSong]
|
var currentSong = this.songs[this.selectedSong]
|
||||||
if(p2.session && !fromP2 && currentSong.action !== "random"){
|
if(p2.session && !fromP2 && currentSong.action !== "random"){
|
||||||
@ -564,6 +711,8 @@ class SongSelect{
|
|||||||
this.toTutorial()
|
this.toTutorial()
|
||||||
}else if(currentSong.action === "about"){
|
}else if(currentSong.action === "about"){
|
||||||
this.toAbout()
|
this.toAbout()
|
||||||
|
}else if(currentSong.action === "browse"){
|
||||||
|
this.toBrowse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.pointer(false)
|
this.pointer(false)
|
||||||
@ -593,7 +742,11 @@ class SongSelect{
|
|||||||
assets.sounds["don"].play()
|
assets.sounds["don"].play()
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
if(assets.customSongs){
|
||||||
|
assets.customSelected = this.selectedSong
|
||||||
|
}else{
|
||||||
localStorage["selectedSong"] = this.selectedSong
|
localStorage["selectedSong"] = this.selectedSong
|
||||||
|
}
|
||||||
localStorage["selectedDiff"] = difficulty + this.diffOptions.length
|
localStorage["selectedDiff"] = difficulty + this.diffOptions.length
|
||||||
}catch(e){}
|
}catch(e){}
|
||||||
|
|
||||||
@ -670,6 +823,19 @@ class SongSelect{
|
|||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
toBrowse(){
|
||||||
|
if(assets.customSongs){
|
||||||
|
assets.customSongs = false
|
||||||
|
assets.songs = assets.songsDefault
|
||||||
|
assets.sounds["don"].play()
|
||||||
|
this.clean()
|
||||||
|
setTimeout(() => {
|
||||||
|
new SongSelect("browse", false, this.touchEnabled)
|
||||||
|
}, 500)
|
||||||
|
}else{
|
||||||
|
this.browse.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
redraw(){
|
redraw(){
|
||||||
if(!this.redrawRunning){
|
if(!this.redrawRunning){
|
||||||
@ -1636,10 +1802,16 @@ class SongSelect{
|
|||||||
return snd.previewGain.load(gameConfig.songs_baseurl + id + previewFilename)
|
return snd.previewGain.load(gameConfig.songs_baseurl + id + previewFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
if(currentSong.music){
|
||||||
|
snd.previewGain.load(currentSong.music, true).then(resolve, reject)
|
||||||
|
}else{
|
||||||
songObj.preview_time = 0
|
songObj.preview_time = 0
|
||||||
loadPreview(previewFilename).catch(() => {
|
loadPreview(previewFilename).catch(() => {
|
||||||
songObj.preview_time = prvTime
|
songObj.preview_time = prvTime
|
||||||
return loadPreview("/main.mp3")
|
return loadPreview("/main.mp3")
|
||||||
|
}).then(resolve, reject)
|
||||||
|
}
|
||||||
}).then(sound => {
|
}).then(sound => {
|
||||||
if(currentId === this.previewId){
|
if(currentId === this.previewId){
|
||||||
songObj.preview_sound = sound
|
songObj.preview_sound = sound
|
||||||
@ -1799,11 +1971,14 @@ class SongSelect{
|
|||||||
})
|
})
|
||||||
pageEvents.keyRemove(this, "all")
|
pageEvents.keyRemove(this, "all")
|
||||||
pageEvents.remove(loader.screen, ["mousemove", "mouseleave", "mousedown", "touchstart"])
|
pageEvents.remove(loader.screen, ["mousemove", "mouseleave", "mousedown", "touchstart"])
|
||||||
|
pageEvents.remove(this.canvas, "touchend")
|
||||||
pageEvents.remove(p2, "message")
|
pageEvents.remove(p2, "message")
|
||||||
if(this.touchEnabled && fullScreenSupported){
|
if(this.touchEnabled && fullScreenSupported){
|
||||||
pageEvents.remove(this.touchFullBtn, "click")
|
pageEvents.remove(this.touchFullBtn, "click")
|
||||||
delete this.touchFullBtn
|
delete this.touchFullBtn
|
||||||
}
|
}
|
||||||
|
pageEvents.remove(this.browse, "change")
|
||||||
|
delete this.browse
|
||||||
delete this.selectable
|
delete this.selectable
|
||||||
delete this.ctx
|
delete this.ctx
|
||||||
delete this.canvas
|
delete this.canvas
|
||||||
|
@ -4,10 +4,19 @@
|
|||||||
this.context = new AudioContext()
|
this.context = new AudioContext()
|
||||||
pageEvents.add(window, ["click", "touchend"], this.pageClicked.bind(this))
|
pageEvents.add(window, ["click", "touchend"], this.pageClicked.bind(this))
|
||||||
}
|
}
|
||||||
load(url, gain){
|
load(url, local, gain){
|
||||||
return loader.ajax(url, request => {
|
if(local){
|
||||||
|
var reader = new FileReader()
|
||||||
|
var loadPromise = pageEvents.load(reader).then(event => {
|
||||||
|
return event.target.result
|
||||||
|
})
|
||||||
|
reader.readAsArrayBuffer(url)
|
||||||
|
}else{
|
||||||
|
var loadPromise = loader.ajax(url, request => {
|
||||||
request.responseType = "arraybuffer"
|
request.responseType = "arraybuffer"
|
||||||
}).then(response => {
|
})
|
||||||
|
}
|
||||||
|
return loadPromise.then(response => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
return this.context.decodeAudioData(response, resolve, reject)
|
return this.context.decodeAudioData(response, resolve, reject)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
@ -66,8 +75,8 @@ class SoundGain{
|
|||||||
}
|
}
|
||||||
this.setVolume(1)
|
this.setVolume(1)
|
||||||
}
|
}
|
||||||
load(url){
|
load(url, local){
|
||||||
return this.soundBuffer.load(url, this)
|
return this.soundBuffer.load(url, local, this)
|
||||||
}
|
}
|
||||||
convertTime(time, absolute){
|
convertTime(time, absolute){
|
||||||
return this.soundBuffer.convertTime(time, absolute)
|
return this.soundBuffer.convertTime(time, absolute)
|
||||||
|
@ -2,4 +2,5 @@
|
|||||||
<canvas id="song-sel-canvas"></canvas>
|
<canvas id="song-sel-canvas"></canvas>
|
||||||
<div id="song-sel-selectable" tabindex="1"></div>
|
<div id="song-sel-selectable" tabindex="1"></div>
|
||||||
<div id="touch-full-btn"></div>
|
<div id="touch-full-btn"></div>
|
||||||
|
<form><input id="browse" type="file" webkitdirectory multiple></form>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user