From 85d6e70ff691c70ec2aa29a3d0848d0af6b93a9d Mon Sep 17 00:00:00 2001 From: mnvdk Date: Tue, 14 Apr 2020 23:01:47 +0200 Subject: [PATCH 01/17] Dynamic songskin loading for categories --- app.py | 10 +++++-- public/assets/img/bg_genre_def.png | Bin 0 -> 16418 bytes public/src/js/assets.js | 4 ++- public/src/js/loader.js | 4 +++ public/src/js/songselect.js | 45 ++++++++++++++++++++++++----- 5 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 public/assets/img/bg_genre_def.png diff --git a/app.py b/app.py index b167014..3641875 100644 --- a/app.py +++ b/app.py @@ -188,8 +188,9 @@ def route_admin(): @admin_required(level=50) def route_admin_songs(): songs = db.songs.find({}) + categories = db.categories.find({}) user = db.users.find_one({'username': session['username']}) - return render_template('admin_songs.html', songs=list(songs), admin=user) + return render_template('admin_songs.html', songs=list(songs), admin=user, categories=list(categories)) @app.route('/admin/songs/') @@ -358,7 +359,7 @@ def route_api_songs(): song['category'] = db.categories.find_one({'id': song['category_id']})['title'] else: song['category'] = None - del song['category_id'] + #del song['category_id'] if song['skin_id']: song['song_skin'] = db.song_skins.find_one({'id': song['skin_id']}, {'_id': False, 'id': False}) @@ -368,6 +369,11 @@ def route_api_songs(): return jsonify(songs) +@app.route('/api/categories') +@app.cache.cached(timeout=15) +def route_api_categories(): + categories = list(db.categories.find({},{'_id': False})) + return jsonify(categories) @app.route('/api/config') @app.cache.cached(timeout=15) diff --git a/public/assets/img/bg_genre_def.png b/public/assets/img/bg_genre_def.png new file mode 100644 index 0000000000000000000000000000000000000000..37be238ffeb2fb9bddf271d26a0b32415620a0e3 GIT binary patch literal 16418 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 B`H%nr literal 0 HcmV?d00001 diff --git a/public/src/js/assets.js b/public/src/js/assets.js index 919b5f3..9616776 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -83,6 +83,7 @@ var assets = { "bg_genre_5.png", "bg_genre_6.png", "bg_genre_7.png", + "bg_genre_def.png", "bg_score_p1.png", "bg_score_p2.png", "bg_settings.png", @@ -157,7 +158,8 @@ var assets = { "songs": [], "sounds": {}, "image": {}, - "pages": {} + "pages": {}, + "categories": {} } var gameConfig = {} diff --git a/public/src/js/loader.js b/public/src/js/loader.js index e574b00..96b332b 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -104,6 +104,10 @@ class Loader{ assets.pages[id] = page }), url) }) + + this.addPromise(this.ajax("/api/categories").then(categories => { + assets.categories = JSON.parse(categories) + }), "/api/categories") this.addPromise(this.ajax("/api/songs").then(songs => { assets.songsDefault = JSON.parse(songs) diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 4532057..d319afb 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -96,14 +96,29 @@ class SongSelect{ background: "#ff5716", border: ["#ffa66b", "#b53000"], outline: "#9c2000" - }, - "default": { - sort: 7, - background: "#ececec", - border: ["#fbfbfb", "#8b8b8b"], - outline: "#656565" } } + + let sortCount = 7; + + for(let category of assets.categories){ + if(!this.songSkin[category.title] && category.songSkin){ + if(!category.songSkin.sort){ + category.songSkin.sort = sortCount + sortCount += 1 + } + + this.songSkin[category.title] = category.songSkin + } + } + + this.songSkin.default = { + sort: Object.keys(this.songSkin).length + 1, + background: "#ececec", + border: ["#fbfbfb", "#8b8b8b"], + outline: "#656565" + } + this.font = strings.font this.songs = [] @@ -118,6 +133,7 @@ class SongSelect{ skin: song.category in this.songSkin ? this.songSkin[song.category] : this.songSkin.default, courses: song.courses, category: song.category, + category_id: song.category_id, preview: song.preview || 0, type: song.type, offset: song.offset, @@ -292,7 +308,7 @@ class SongSelect{ this.songSelect = document.getElementById("song-select") var cat = this.songs[this.selectedSong].category var sort = cat in this.songSkin ? this.songSkin[cat].sort : 7 - this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_" + sort].src + "')" + this.drawBackground(cat, sort) this.previewId = 0 this.previewList = Array(5) @@ -1201,7 +1217,8 @@ class SongSelect{ if(this.songs[this.selectedSong].action !== "back"){ var cat = this.songs[this.selectedSong].category var sort = cat in this.songSkin ? this.songSkin[cat].sort : 7 - this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_" + sort].src + "')" + + this.drawBackground(cat, sort) } } if(this.state.moveMS && ms < this.state.moveMS + changeSpeed){ @@ -2306,6 +2323,18 @@ class SongSelect{ scoreStorage.eventLoop() } } + + drawBackground(cat, sort){ + if(this.songSkin[cat] && this.songSkin[cat].bg_img){ + this.songSelect.style.backgroundImage = "url('assets/img/" + this.songSkin[cat].bg_img + "')" + }else{ + if(assets.image["bg_genre_" + sort]){ + this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_" + sort].src + "')" + }else{ + this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_def"].src + "')" + } + } + } drawClosedSong(config){ var ctx = config.ctx From e1411bcd0d7758f76b0b76f95098c67cf98b9215 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Wed, 15 Apr 2020 22:33:49 +0200 Subject: [PATCH 02/17] preload all category images in loader.js --- public/src/js/loader.js | 16 +++++++++++++++- public/src/js/songselect.js | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 96b332b..6603c6a 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -86,7 +86,7 @@ class Loader{ }), url) } - assets.img.forEach(name => { + assets.img.forEach(name=>{ var id = this.getFilename(name) var image = document.createElement("img") var url = gameConfig.assets_baseurl + "img/" + name @@ -132,6 +132,20 @@ class Loader{ return } + assets.categories //load category backgrounds to DOM + .filter(cat=>cat.songSkin && cat.songSkin.bg_img) + .forEach(cat=>{ + let name = cat.songSkin.bg_img + var id = this.getFilename(name) + var image = document.createElement("img") + var url = gameConfig.assets_baseurl + "img/" + name + this.addPromise(pageEvents.load(image), url) + image.id = name + image.src = url + this.assetsDiv.appendChild(image) + assets.image[id] = image + }) + snd.buffer = new SoundBuffer() snd.musicGain = snd.buffer.createGain() snd.sfxGain = snd.buffer.createGain() diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index d319afb..6075c5a 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -107,7 +107,6 @@ class SongSelect{ category.songSkin.sort = sortCount sortCount += 1 } - this.songSkin[category.title] = category.songSkin } } @@ -2326,7 +2325,8 @@ class SongSelect{ drawBackground(cat, sort){ if(this.songSkin[cat] && this.songSkin[cat].bg_img){ - this.songSelect.style.backgroundImage = "url('assets/img/" + this.songSkin[cat].bg_img + "')" + let filename = this.songSkin[cat].bg_img.slice(0, this.songSkin[cat].bg_img.lastIndexOf(".")) + this.songSelect.style.backgroundImage = "url('" + assets.image[filename].src + "')" }else{ if(assets.image["bg_genre_" + sort]){ this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_" + sort].src + "')" From 988c4cc734b3b8c5cf8dfb35346e5de755d38fb1 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Thu, 16 Apr 2020 00:40:13 +0200 Subject: [PATCH 03/17] Removed more hardcoded instances of categories --- public/src/js/loader.js | 8 +++++ public/src/js/songselect.js | 66 +++++-------------------------------- public/src/js/view.js | 46 ++------------------------ 3 files changed, 19 insertions(+), 101 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 6603c6a..08d767d 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -107,6 +107,14 @@ class Loader{ this.addPromise(this.ajax("/api/categories").then(categories => { assets.categories = JSON.parse(categories) + assets.categories.push({ + title: "default", + songSkin: { + background: "#ececec", + border: ["#fbfbfb", "#8b8b8b"], + outline: "#656565" + } + }) }), "/api/categories") this.addPromise(this.ajax("/api/songs").then(songs => { diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 6075c5a..504ead6 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -26,97 +26,47 @@ class SongSelect{ outline: "#ad7723" }, "random": { - sort: 7, + sort: 0, background: "#fa91ff", border: ["#ffdfff", "#b068b2"], outline: "#b221bb" }, "tutorial": { - sort: 7, + sort: 0, background: "#29e8aa", border: ["#86ffbd", "#009a8c"], outline: "#08a28c" }, "about": { - sort: 7, + sort: 0, background: "#a2d0e7", border: ["#c6dfff", "#4485d9"], outline: "#2390d9" }, "settings": { - sort: 7, + sort: 0, background: "#ce93fa", border: ["#dec4fd", "#a543ef"], outline: "#a741ef" }, "browse": { - sort: 7, + sort: 0, background: "#fab5d3", border: ["#ffe7ef", "#d36aa2"], outline: "#d36aa2" - }, - "J-POP": { - sort: 0, - background: "#219fbb", - border: ["#7ec3d3", "#0b6773"], - outline: "#005058" - }, - "アニメ": { - sort: 1, - background: "#ff9700", - border: ["#ffdb8c", "#e75500"], - outline: "#9c4100" - }, - "ボーカロイド™曲": { - sort: 2, - background: "#def2ef", - border: ["#f7fbff", "#79919f"], - outline: "#5a6584" - }, - "バラエティ": { - sort: 3, - background: "#8fd321", - border: ["#f7fbff", "#587d0b"], - outline: "#374c00" - }, - "クラシック": { - sort: 4, - background: "#d1a016", - border: ["#e7cf6b", "#9a6b00"], - outline: "#734d00" - }, - "ゲームミュージック": { - sort: 5, - background: "#9c72c0", - border: ["#bda2ce", "#63407e"], - outline: "#4b1c74" - }, - "ナムコオリジナル": { - sort: 6, - background: "#ff5716", - border: ["#ffa66b", "#b53000"], - outline: "#9c2000" } } - let sortCount = 7; - for(let category of assets.categories){ if(!this.songSkin[category.title] && category.songSkin){ - if(!category.songSkin.sort){ - category.songSkin.sort = sortCount - sortCount += 1 + if(!category.songSkin.sort == null){ + category.songSkin.sort = Object.keys(this.songSkin).length + 1 } this.songSkin[category.title] = category.songSkin } } - this.songSkin.default = { - sort: Object.keys(this.songSkin).length + 1, - background: "#ececec", - border: ["#fbfbfb", "#8b8b8b"], - outline: "#656565" - } + this.songSkin['default'].sort= Object.keys(this.songSkin).length + 1 this.font = strings.font diff --git a/public/src/js/view.js b/public/src/js/view.js index 4326379..5c32505 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -23,40 +23,6 @@ this.darkDonBg = false this.pauseOptions = strings.pauseOptions - this.categories = { - "J-POP": { - sort: 0, - infoFill: "#004d68" - }, - "アニメ": { - sort: 1, - infoFill: "#9c4002" - }, - "ボーカロイド™曲": { - sort: 2, - infoFill: "#546184" - }, - "バラエティ": { - sort: 3, - infoFill: "#3c6800" - }, - "クラシック": { - sort: 4, - infoFill: "#865800" - }, - "ゲームミュージック": { - sort: 5, - infoFill: "#4f2886" - }, - "ナムコオリジナル": { - sort: 6, - infoFill: "#961e00" - }, - "default": { - sort: 7, - infoFill: "#656565" - } - } this.difficulty = { "easy": 0, "normal": 1, @@ -329,10 +295,10 @@ var _h = 22 var _x = 628 - _w var _y = 88 - _h - if(selectedSong.category in this.categories){ - ctx.fillStyle = this.categories[selectedSong.category].infoFill + if(assets.categories.find(cat=>cat.title == selectedSong.category)){ + ctx.fillStyle = assets.categories.find(cat=>cat.title == selectedSong.category).songSkin.outline }else{ - ctx.fillStyle = this.categories.default.infoFill + ctx.fillStyle = assets.categories.find(cat=>cat.title == 'default').songSkin.outline } this.draw.roundedRect({ ctx: ctx, @@ -1425,12 +1391,6 @@ var songLayers = [document.getElementById("layer1"), document.getElementById("layer2")] var prefix = "" - if(selectedSong.category in this.categories){ - var catId = this.categories[selectedSong.category].sort - }else{ - var catId = this.categories.default.sort - } - if(!selectedSong.songSkin.song){ var id = selectedSong.songBg this.songBg.classList.add("songbg-" + id) From 7d810a27cec4d90634e420efb52f4d49318b414c Mon Sep 17 00:00:00 2001 From: mnvdk Date: Thu, 16 Apr 2020 00:51:24 +0200 Subject: [PATCH 04/17] bg_genre_def made bg_genre_7 obsolete --- public/assets/img/bg_genre_7.png | Bin 16418 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 public/assets/img/bg_genre_7.png diff --git a/public/assets/img/bg_genre_7.png b/public/assets/img/bg_genre_7.png deleted file mode 100644 index 37be238ffeb2fb9bddf271d26a0b32415620a0e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16418 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 B`H%nr From 2c4fdab4f9b50c9666efe43d3cc6d996e79e4815 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Thu, 16 Apr 2020 21:39:23 +0200 Subject: [PATCH 05/17] removed hardcoded categories from stringsjs and moved the language block to mongo --- public/src/js/loader.js | 8 ++++++ public/src/js/songselect.js | 15 +++--------- public/src/js/strings.js | 49 ++----------------------------------- 3 files changed, 14 insertions(+), 58 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 08d767d..6889a00 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -107,6 +107,14 @@ class Loader{ this.addPromise(this.ajax("/api/categories").then(categories => { assets.categories = JSON.parse(categories) + assets.categories.forEach(cat => { + let title = cat.title + // if(cat.title_lang){ + translations.categories[title] = cat.title_lang + // } + + }); + separateStrings() assets.categories.push({ title: "default", songSkin: { diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 504ead6..31f57c4 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -256,8 +256,7 @@ class SongSelect{ this.songSelect = document.getElementById("song-select") var cat = this.songs[this.selectedSong].category - var sort = cat in this.songSkin ? this.songSkin[cat].sort : 7 - this.drawBackground(cat, sort) + this.drawBackground(cat) this.previewId = 0 this.previewList = Array(5) @@ -1165,9 +1164,7 @@ class SongSelect{ if(this.songs[this.selectedSong].action !== "back"){ var cat = this.songs[this.selectedSong].category - var sort = cat in this.songSkin ? this.songSkin[cat].sort : 7 - - this.drawBackground(cat, sort) + this.drawBackground(cat) } } if(this.state.moveMS && ms < this.state.moveMS + changeSpeed){ @@ -2273,18 +2270,14 @@ class SongSelect{ } } - drawBackground(cat, sort){ + drawBackground(cat){ if(this.songSkin[cat] && this.songSkin[cat].bg_img){ let filename = this.songSkin[cat].bg_img.slice(0, this.songSkin[cat].bg_img.lastIndexOf(".")) this.songSelect.style.backgroundImage = "url('" + assets.image[filename].src + "')" }else{ - if(assets.image["bg_genre_" + sort]){ - this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_" + sort].src + "')" - }else{ - this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_def"].src + "')" + this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_def"].src + "')" } } - } drawClosedSong(config){ var ctx = config.ctx diff --git a/public/src/js/strings.js b/public/src/js/strings.js index 9d99ff2..975ad44 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -47,52 +47,7 @@ var translations = { en: "Taiko no Tatsujin ©&™ 2011 BANDAI NAMCO Entertainment Inc." }, categories: { - "J-POP": { - ja: "J-POP", - en: "Pop", - cn: "流行音乐", - tw: "流行音樂", - ko: "POP" - }, - "アニメ": { - ja: "アニメ", - en: "Anime", - cn: "卡通动画音乐", - tw: "卡通動畫音樂", - ko: "애니메이션" - }, - "ボーカロイド™曲": { - ja: "ボーカロイド™曲", - en: "VOCALOID™ Music" - }, - "バラエティ": { - ja: "バラエティ", - en: "Variety", - cn: "综合音乐", - tw: "綜合音樂", - ko: "버라이어티" - }, - "クラシック": { - ja: "クラシック", - en: "Classical", - cn: "古典音乐", - tw: "古典音樂", - ko: "클래식" - }, - "ゲームミュージック": { - ja: "ゲームミュージック", - en: "Game Music", - cn: "游戏音乐", - tw: "遊戲音樂", - ko: "게임" - }, - "ナムコオリジナル": { - ja: "ナムコオリジナル", - en: "NAMCO Original", - cn: "NAMCO原创音乐", - tw: "NAMCO原創音樂", - ko: "남코 오리지널" - } + }, selectSong: { ja: "曲をえらぶ", @@ -1130,7 +1085,7 @@ function separateStrings(){ } var str = allStrings[lang] var translateObj = function(obj, name, str){ - if("en" in obj){ + if(obj != null && "en" in obj && obj["en"] != null){ for(var i in obj){ str[name] = obj[lang] || obj.en } From 84d5edbbd0ffb9a7b1c27bfff96a2618b4287229 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Thu, 16 Apr 2020 21:50:17 +0200 Subject: [PATCH 06/17] removed backgrounds from assets.js --- public/src/js/assets.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/public/src/js/assets.js b/public/src/js/assets.js index 9616776..da923b9 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -75,14 +75,6 @@ var assets = { "don_anim_clear_b2.png", "fire_anim.png", "fireworks_anim.png", - "bg_genre_0.png", - "bg_genre_1.png", - "bg_genre_2.png", - "bg_genre_3.png", - "bg_genre_4.png", - "bg_genre_5.png", - "bg_genre_6.png", - "bg_genre_7.png", "bg_genre_def.png", "bg_score_p1.png", "bg_score_p2.png", From d02bfa8426108a2860217f2068397470a0677fc8 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Thu, 16 Apr 2020 21:55:55 +0200 Subject: [PATCH 07/17] tiny bit of cleanup --- public/src/js/loader.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 6889a00..4ff9173 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -109,12 +109,9 @@ class Loader{ assets.categories = JSON.parse(categories) assets.categories.forEach(cat => { let title = cat.title - // if(cat.title_lang){ - translations.categories[title] = cat.title_lang - // } - + translations.categories[title] = cat.title_lang }); - separateStrings() + separateStrings() //load categories into strings.js to handle multi language assets.categories.push({ title: "default", songSkin: { @@ -298,11 +295,8 @@ class Loader{ this.callback(songId) pageEvents.send("ready", readyEvent) }) - }, this.errorMsg.bind(this)) - - - }) - + }, this.errorMsg.bind(this)) + }) } addPromise(promise, url){ this.promises.push(promise) From dca4948548a0287eb44f7ea82eb7e1b75dc5b9b5 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Fri, 17 Apr 2020 18:35:39 +0200 Subject: [PATCH 08/17] reintroduced infoFill, moved infoFill to mongo --- public/src/js/loader.js | 5 +++-- public/src/js/view.js | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 4ff9173..7df3928 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -109,7 +109,7 @@ class Loader{ assets.categories = JSON.parse(categories) assets.categories.forEach(cat => { let title = cat.title - translations.categories[title] = cat.title_lang + translations.categories[title] = cat.title_lang }); separateStrings() //load categories into strings.js to handle multi language assets.categories.push({ @@ -117,7 +117,8 @@ class Loader{ songSkin: { background: "#ececec", border: ["#fbfbfb", "#8b8b8b"], - outline: "#656565" + outline: "#656565", + infoFill: "#656565" } }) }), "/api/categories") diff --git a/public/src/js/view.js b/public/src/js/view.js index 5c32505..0da8b18 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -295,10 +295,12 @@ var _h = 22 var _x = 628 - _w var _y = 88 - _h - if(assets.categories.find(cat=>cat.title == selectedSong.category)){ - ctx.fillStyle = assets.categories.find(cat=>cat.title == selectedSong.category).songSkin.outline + + let category = assets.categories.find(cat=>cat.title == selectedSong.category) + if(category != null && category.songSkin != null && category.songSkin.infoFill != null){ + ctx.fillStyle = assets.categories.find(cat=>cat.title == selectedSong.category).songSkin.infoFill }else{ - ctx.fillStyle = assets.categories.find(cat=>cat.title == 'default').songSkin.outline + ctx.fillStyle = assets.categories.find(cat=>cat.title == 'default').songSkin.infoFill } this.draw.roundedRect({ ctx: ctx, From f66ef6417f9a66a0cd06b3b34983ff6fe3375843 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Sun, 26 Apr 2020 16:48:18 +0200 Subject: [PATCH 09/17] Moved categories to its own object instead of allstrings and adjusted code in the other files in order to maintain multilangual support --- public/src/js/assets.js | 2 +- public/src/js/loader.js | 18 ++++++++++++------ public/src/js/settings.js | 9 +++------ public/src/js/songselect.js | 8 ++++++-- public/src/js/strings.js | 21 +++++++++++++++++---- public/src/js/titlescreen.js | 19 ++++++++++++++++--- 6 files changed, 55 insertions(+), 22 deletions(-) diff --git a/public/src/js/assets.js b/public/src/js/assets.js index da923b9..dd9830c 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -151,7 +151,7 @@ var assets = { "sounds": {}, "image": {}, "pages": {}, - "categories": {} + "categories": [] } var gameConfig = {} diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 7df3928..62ddb61 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -105,13 +105,18 @@ class Loader{ }), url) }) - this.addPromise(this.ajax("/api/categories").then(categories => { - assets.categories = JSON.parse(categories) - assets.categories.forEach(cat => { + this.addPromise(this.ajax("/api/categories").then(cats => { + let jsonCategories = JSON.parse(cats) + + for (var i in jsonCategories) { //rename the song_skin property and add category title to categories array + let cat = jsonCategories[i] + cat.songSkin = cat.song_Skin + delete cat.song_Skin + assets.categories.push(cat) let title = cat.title - translations.categories[title] = cat.title_lang - }); - separateStrings() //load categories into strings.js to handle multi language + categories[title] = cat.title_lang + } + assets.categories.push({ title: "default", songSkin: { @@ -145,6 +150,7 @@ class Loader{ if(this.error){ return } + separateStrings() //iterate over strings and apply translations where required assets.categories //load category backgrounds to DOM .filter(cat=>cat.songSkin && cat.songSkin.bg_img) diff --git a/public/src/js/settings.js b/public/src/js/settings.js index 1f7a9bb..c64ab8f 100644 --- a/public/src/js/settings.js +++ b/public/src/js/settings.js @@ -145,12 +145,9 @@ class Settings{ } return this.allLanguages[0] } - setLang(lang, noEvent){ - strings = lang - var boldFonts = strings.font === "Microsoft YaHei, sans-serif" - loader.screen.style.fontFamily = strings.font - loader.screen.style.fontWeight = boldFonts ? "bold" : "" - loader.screen.classList[boldFonts ? "add" : "remove"]("bold-fonts") + setLang(lang, noEvent, stringRepo){ + stringRepo = lang + if(!noEvent){ pageEvents.send("language-change", lang.id) } diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 31f57c4..bb438fa 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -54,6 +54,12 @@ class SongSelect{ background: "#fab5d3", border: ["#ffe7ef", "#d36aa2"], outline: "#d36aa2" + }, + "default": { + background: "#ececec", + border: ["#fbfbfb", "#8b8b8b"], + outline: "#656565", + infoFill: "#656565" } } @@ -917,13 +923,11 @@ class SongSelect{ this.nameplateCache.resize(274, 134, ratio + 0.2) - var categories = 0 var lastCategory this.songs.forEach(song => { var cat = (song.category || "") + song.skin.outline if(lastCategory !== cat){ lastCategory = cat - categories++ } }) this.categoryCache.resize(280, this.songAsset.marginTop + 1 , ratio + 0.5) diff --git a/public/src/js/strings.js b/public/src/js/strings.js index 975ad44..cb51297 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -45,9 +45,6 @@ var translations = { }, titleCopyright: { en: "Taiko no Tatsujin ©&™ 2011 BANDAI NAMCO Entertainment Inc." - }, - categories: { - }, selectSong: { ja: "曲をえらぶ", @@ -1076,14 +1073,20 @@ var translations = { ko: "가사가있는" } } +var categories = {} var allStrings = {} + function separateStrings(){ + let categoriesTemp = Object.assign({}, categories); + categories = {} + for(var j in languageList){ var lang = languageList[j] allStrings[lang] = { id: lang } var str = allStrings[lang] + var translateObj = function(obj, name, str){ if(obj != null && "en" in obj && obj["en"] != null){ for(var i in obj){ @@ -1094,11 +1097,21 @@ function separateStrings(){ for(var i in obj){ translateObj(obj[i], i, str[name]) } + }else{ //key appears in string obj but has no language values, so just apply the key name to each language for consistency and as fallback + str[name] = name } } + for(var i in translations){ translateObj(translations[i], i, str) } + + categories[lang] = { + id: lang + } + var str = categories[lang] + for(var i in categoriesTemp){ + translateObj(categoriesTemp[i], i, str) + } } } -separateStrings() diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index aa98e4d..da73ac9 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -11,7 +11,7 @@ class Titlescreen{ this.disclaimerCopyright = document.getElementById("title-disclaimer-copyright") this.logo = new Logo() } - this.setLang(allStrings[settings.getItem("language")]) + this.setLang() if(songId){ if(localStorage.getItem("tutorial") === "true"){ @@ -76,8 +76,21 @@ class Titlescreen{ }, 500) } } - setLang(lang, noEvent){ - settings.setLang(lang, true) + setLang(){ + let stringLang = allStrings[settings.getItem("language")] + let categoryLang = categories[settings.getItem("language")] + + strings = stringLang + strings.categories = categoryLang + + settings.setLang(stringLang, true, allStrings) + settings.setLang(categoryLang, true, categories) + + let boldFonts = strings.font === "Microsoft YaHei, sans-serif" + loader.screen.style.fontFamily = strings.font + loader.screen.style.fontWeight = boldFonts ? "bold" : "" + loader.screen.classList[boldFonts ? "add" : "remove"]("bold-fonts") + if(this.songId){ return } From 41ddbb66a9f7fb6a2f062d86ab2fe5993b610b36 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Sun, 26 Apr 2020 18:13:59 +0200 Subject: [PATCH 10/17] load category strings in its own object instead of just overwriting everything --- public/src/js/strings.js | 15 +++++++-------- public/src/js/titlescreen.js | 6 +++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/public/src/js/strings.js b/public/src/js/strings.js index cb51297..3a5d63e 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -1074,11 +1074,11 @@ var translations = { } } var categories = {} + var allStrings = {} +var categoryStrings = {} function separateStrings(){ - let categoriesTemp = Object.assign({}, categories); - categories = {} for(var j in languageList){ var lang = languageList[j] @@ -1106,12 +1106,11 @@ function separateStrings(){ translateObj(translations[i], i, str) } - categories[lang] = { - id: lang - } - var str = categories[lang] - for(var i in categoriesTemp){ - translateObj(categoriesTemp[i], i, str) + categoryStrings[lang] = {} + var str = categoryStrings[lang] + + for(var i in categories){ + translateObj(categories[i], i, str) } } } diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index da73ac9..b818725 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -78,13 +78,13 @@ class Titlescreen{ } setLang(){ let stringLang = allStrings[settings.getItem("language")] - let categoryLang = categories[settings.getItem("language")] - + let categoryLang = categoryStrings[settings.getItem("language")] + strings = stringLang strings.categories = categoryLang settings.setLang(stringLang, true, allStrings) - settings.setLang(categoryLang, true, categories) + settings.setLang(categoryLang, true, categoryStrings) let boldFonts = strings.font === "Microsoft YaHei, sans-serif" loader.screen.style.fontFamily = strings.font From 387d1268fdcb7af82bbc7400f9bcc0c662ffc334 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Sun, 26 Apr 2020 22:56:31 +0200 Subject: [PATCH 11/17] importsongs no longer has a static category list --- public/src/js/importsongs.js | 44 +++++++++++++++--------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/public/src/js/importsongs.js b/public/src/js/importsongs.js index 87d63df..f999439 100644 --- a/public/src/js/importsongs.js +++ b/public/src/js/importsongs.js @@ -38,25 +38,18 @@ "oni": 3, "ura": 4 } - this.categories = { - "ボーカロイド曲": "ボーカロイド™曲", - "ボーカロイド": "ボーカロイド™曲", - "vocaloid music": "ボーカロイド™曲", - "vocaloid": "ボーカロイド™曲", - "バラエティー": "バラエティ", - "どうよう": "バラエティ", - "童謡・民謡": "バラエティ", - "children": "バラエティ", - "children/folk": "バラエティ", - "children-folk": "バラエティ", - "クラッシック": "クラシック", - "classic": "クラシック" - } - for(var i in allStrings){ - for(var ja in allStrings[i].categories){ - this.categories[allStrings[i].categories[ja].toLowerCase()] = ja + + this.categoryAliases = {} + + assets.categories.forEach(cat => { + this.categoryAliases[cat.title.toLowerCase()] = cat.title.toLowerCase() + if(cat.aliases != null){ + cat.aliases.forEach(alias => { + this.categoryAliases[alias.toLowerCase()] = cat.title.toLowerCase() + }); } - } + }); + this.assetSelectors = { "bg-pattern-1": ".pattern-bg", "bg_genre_0": "#song-select", @@ -137,7 +130,7 @@ 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() + category = this.categoryAliases[value] || data[i].trim().slice(equalsPos + 1).trim() break } } @@ -147,12 +140,12 @@ 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] + if(value in this.categoryAliases){ + category = this.categoryAliases[value] } }else if(line.startsWith("#genre:")){ var value = line.slice(7).trim() - category = this.categories[value] || data[i].trim().slice(7).trim() + category = this.categoryAliases[value] || data[i].trim().slice(7).trim() break } } @@ -215,7 +208,6 @@ var subtitleLang = {} 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 = meta.title || file.name.slice(0, file.name.lastIndexOf(".")) @@ -234,7 +226,7 @@ songObj.music = this.otherFiles[dir + meta.wave.toLowerCase()] || songObj.music } if(meta.genre){ - songObj.category = this.categories[meta.genre.toLowerCase()] || meta.genre + songObj.category = this.categoryAliases[meta.genre.toLowerCase()] || meta.genre } if(meta.taikowebskin){ songObj.song_skin = this.getSkin(dir, meta.taikowebskin) @@ -445,9 +437,9 @@ } } if(!hasTitle){ - for(var cat in this.categories){ + for(var cat in this.categoryAliases){ if(path[i].indexOf(cat) !== -1){ - return this.categories[cat] + return this.categoryAliases[cat] } } } From 14629ad12a1139e9fa8475a0125071d0467c06d0 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Sun, 26 Apr 2020 23:14:16 +0200 Subject: [PATCH 12/17] Don't lowercase the assigned value --- public/src/js/importsongs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/js/importsongs.js b/public/src/js/importsongs.js index f999439..c65549d 100644 --- a/public/src/js/importsongs.js +++ b/public/src/js/importsongs.js @@ -42,10 +42,10 @@ this.categoryAliases = {} assets.categories.forEach(cat => { - this.categoryAliases[cat.title.toLowerCase()] = cat.title.toLowerCase() + this.categoryAliases[cat.title.toLowerCase()] = cat.title if(cat.aliases != null){ cat.aliases.forEach(alias => { - this.categoryAliases[alias.toLowerCase()] = cat.title.toLowerCase() + this.categoryAliases[alias.toLowerCase()] = cat.title }); } }); From 800e136f919e88cdb737b7cd4229c55c6ec5119b Mon Sep 17 00:00:00 2001 From: mnvdk Date: Mon, 27 Apr 2020 02:12:09 +0200 Subject: [PATCH 13/17] Undid storing categories in strings.js, instead using the localization method in songselect.js. category info gets passed down to view.js. --- public/src/js/loader.js | 16 +++++----------- public/src/js/settings.js | 9 +++++++-- public/src/js/songselect.js | 21 +++++++++++++-------- public/src/js/strings.js | 14 ++------------ public/src/js/titlescreen.js | 18 +++--------------- public/src/js/view.js | 15 +++++---------- 6 files changed, 35 insertions(+), 58 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 62ddb61..8b2f90d 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -106,16 +106,11 @@ class Loader{ }) this.addPromise(this.ajax("/api/categories").then(cats => { - let jsonCategories = JSON.parse(cats) - - for (var i in jsonCategories) { //rename the song_skin property and add category title to categories array - let cat = jsonCategories[i] - cat.songSkin = cat.song_Skin + assets.categories = JSON.parse(cats) + assets.categories.forEach(cat => { + cat.songSkin = cat.song_Skin //rename the song_skin property and add category title to categories array delete cat.song_Skin - assets.categories.push(cat) - let title = cat.title - categories[title] = cat.title_lang - } + }); assets.categories.push({ title: "default", @@ -150,8 +145,7 @@ class Loader{ if(this.error){ return } - separateStrings() //iterate over strings and apply translations where required - + assets.categories //load category backgrounds to DOM .filter(cat=>cat.songSkin && cat.songSkin.bg_img) .forEach(cat=>{ diff --git a/public/src/js/settings.js b/public/src/js/settings.js index c64ab8f..d5b7ce6 100644 --- a/public/src/js/settings.js +++ b/public/src/js/settings.js @@ -145,8 +145,13 @@ class Settings{ } return this.allLanguages[0] } - setLang(lang, noEvent, stringRepo){ - stringRepo = lang + setLang(lang, noEvent){ + strings = lang + + var boldFonts = strings.font === "Microsoft YaHei, sans-serif" + loader.screen.style.fontFamily = strings.font + loader.screen.style.fontWeight = boldFonts ? "bold" : "" + loader.screen.classList[boldFonts ? "add" : "remove"]("bold-fonts") if(!noEvent){ pageEvents.send("language-change", lang.id) diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index bb438fa..69d35ae 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -80,6 +80,8 @@ class SongSelect{ for(let song of assets.songs){ var title = this.getLocalTitle(song.title, song.title_lang) var subtitle = this.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang) + let category = assets.categories.find(cat=>cat.id == song.category_id) + var categoryName = this.getLocalTitle(category.title, category.title_lang) this.songs.push({ id: song.id, title: title, @@ -87,7 +89,8 @@ class SongSelect{ subtitle: subtitle, skin: song.category in this.songSkin ? this.songSkin[song.category] : this.songSkin.default, courses: song.courses, - category: song.category, + originalCategory: song.category, + category: categoryName, category_id: song.category_id, preview: song.preview || 0, type: song.type, @@ -103,8 +106,8 @@ class SongSelect{ }) } this.songs.sort((a, b) => { - var catA = a.category in this.songSkin ? this.songSkin[a.category] : this.songSkin.default - var catB = b.category in this.songSkin ? this.songSkin[b.category] : this.songSkin.default + var catA = a.originalCategory in this.songSkin ? this.songSkin[a.originalCategory] : this.songSkin.default + var catB = b.originalCategory in this.songSkin ? this.songSkin[b.originalCategory] : this.songSkin.default if(catA.sort === catB.sort){ if(a.order === b.order){ return a.id > b.id ? 1 : -1 @@ -261,7 +264,7 @@ class SongSelect{ } this.songSelect = document.getElementById("song-select") - var cat = this.songs[this.selectedSong].category + var cat = this.songs[this.selectedSong].originalCategory this.drawBackground(cat) this.previewId = 0 @@ -769,6 +772,7 @@ class SongSelect{ "folder": selectedSong.id, "difficulty": diff, "category": selectedSong.category, + "category_id":selectedSong.category_id, "type": selectedSong.type, "offset": selectedSong.offset, "songSkin": selectedSong.songSkin, @@ -1043,8 +1047,8 @@ class SongSelect{ ]) }) - var category = this.songs[this.selectedSong].category var selectedSong = this.songs[this.selectedSong] + var category = selectedSong.category this.draw.category({ ctx: ctx, x: winW / 2 - 280 / 2 - 30, @@ -1069,8 +1073,9 @@ class SongSelect{ id: category + selectedSong.skin.outline }, ctx => { if(category){ - if(category in strings.categories){ - var categoryName = strings.categories[category] + let cat = assets.categories.find(cat=>cat.title === category) + if(cat){ + var categoryName = this.getLocalTitle(cat.title, cat.title_lang) }else{ var categoryName = category } @@ -1167,7 +1172,7 @@ class SongSelect{ } if(this.songs[this.selectedSong].action !== "back"){ - var cat = this.songs[this.selectedSong].category + var cat = this.songs[this.selectedSong].originalCategory this.drawBackground(cat) } } diff --git a/public/src/js/strings.js b/public/src/js/strings.js index 3a5d63e..c4fa550 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -1073,13 +1073,10 @@ var translations = { ko: "가사가있는" } } -var categories = {} var allStrings = {} -var categoryStrings = {} function separateStrings(){ - for(var j in languageList){ var lang = languageList[j] allStrings[lang] = { @@ -1097,20 +1094,13 @@ function separateStrings(){ for(var i in obj){ translateObj(obj[i], i, str[name]) } - }else{ //key appears in string obj but has no language values, so just apply the key name to each language for consistency and as fallback - str[name] = name } } for(var i in translations){ translateObj(translations[i], i, str) } - - categoryStrings[lang] = {} - var str = categoryStrings[lang] - - for(var i in categories){ - translateObj(categories[i], i, str) - } } } + +separateStrings() diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index b818725..ca700c7 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -11,7 +11,7 @@ class Titlescreen{ this.disclaimerCopyright = document.getElementById("title-disclaimer-copyright") this.logo = new Logo() } - this.setLang() + this.setLang(allStrings[settings.getItem("language")]) if(songId){ if(localStorage.getItem("tutorial") === "true"){ @@ -76,20 +76,8 @@ class Titlescreen{ }, 500) } } - setLang(){ - let stringLang = allStrings[settings.getItem("language")] - let categoryLang = categoryStrings[settings.getItem("language")] - - strings = stringLang - strings.categories = categoryLang - - settings.setLang(stringLang, true, allStrings) - settings.setLang(categoryLang, true, categoryStrings) - - let boldFonts = strings.font === "Microsoft YaHei, sans-serif" - loader.screen.style.fontFamily = strings.font - loader.screen.style.fontWeight = boldFonts ? "bold" : "" - loader.screen.classList[boldFonts ? "add" : "remove"]("bold-fonts") + setLang(lang, noEvent){ + settings.setLang(lang, true) if(this.songId){ return diff --git a/public/src/js/view.js b/public/src/js/view.js index 0da8b18..9c74fdf 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -296,9 +296,9 @@ var _x = 628 - _w var _y = 88 - _h - let category = assets.categories.find(cat=>cat.title == selectedSong.category) + let category = assets.categories.find(cat=>cat.id == selectedSong.category_id) if(category != null && category.songSkin != null && category.songSkin.infoFill != null){ - ctx.fillStyle = assets.categories.find(cat=>cat.title == selectedSong.category).songSkin.infoFill + ctx.fillStyle = category.songSkin.infoFill }else{ ctx.fillStyle = assets.categories.find(cat=>cat.title == 'default').songSkin.infoFill } @@ -308,16 +308,11 @@ w: _w, h: _h, radius: 11 }) - ctx.fill() - - if(selectedSong.category in strings.categories){ - var categoryName = strings.categories[selectedSong.category] - }else{ - var categoryName = selectedSong.category - } + ctx.fill() + this.draw.layeredText({ ctx: ctx, - text: categoryName, + text: selectedSong.category, fontSize: 15, fontFamily: this.font, align: "center", From 8fe06bfb9de822251cea84fe00d475b568fe2b77 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Mon, 27 Apr 2020 02:22:18 +0200 Subject: [PATCH 14/17] renamed infoFill to info_Fill on in the database --- public/src/js/loader.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 8b2f90d..1b5bc26 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -108,8 +108,12 @@ class Loader{ this.addPromise(this.ajax("/api/categories").then(cats => { assets.categories = JSON.parse(cats) assets.categories.forEach(cat => { - cat.songSkin = cat.song_Skin //rename the song_skin property and add category title to categories array - delete cat.song_Skin + if(cat.song_Skin){ + cat.songSkin = cat.song_Skin //rename the song_skin property and add category title to categories array + delete cat.song_Skin + cat.songSkin.infoFill = cat.songSkin.info_Fill + delete cat.songSkin.info_Fill + } }); assets.categories.push({ From 962adb1dc7ddd3ace7dee3852d3bc81364268ff3 Mon Sep 17 00:00:00 2001 From: mnvdk Date: Mon, 27 Apr 2020 02:33:14 +0200 Subject: [PATCH 15/17] song_Skin should be song_skin, info_Fill should be info_fill --- public/src/js/loader.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 1b5bc26..60b7b6f 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -108,11 +108,11 @@ class Loader{ this.addPromise(this.ajax("/api/categories").then(cats => { assets.categories = JSON.parse(cats) assets.categories.forEach(cat => { - if(cat.song_Skin){ - cat.songSkin = cat.song_Skin //rename the song_skin property and add category title to categories array - delete cat.song_Skin - cat.songSkin.infoFill = cat.songSkin.info_Fill - delete cat.songSkin.info_Fill + if(cat.song_skin){ + cat.songSkin = cat.song_skin //rename the song_skin property and add category title to categories array + delete cat.song_skin + cat.songSkin.infoFill = cat.songSkin.info_fill + delete cat.songSkin.info_fill } }); From 6d0d5e1632b402282bed5baf81aba3ef4a88a11b Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Mon, 27 Apr 2020 18:47:55 +0300 Subject: [PATCH 16/17] Fix categories for imported songs --- public/src/js/importsongs.js | 70 +++++++++++++++++++++++++++--------- public/src/js/songselect.js | 48 +++++++++++++++---------- 2 files changed, 83 insertions(+), 35 deletions(-) diff --git a/public/src/js/importsongs.js b/public/src/js/importsongs.js index c65549d..1687e0b 100644 --- a/public/src/js/importsongs.js +++ b/public/src/js/importsongs.js @@ -38,18 +38,22 @@ "oni": 3, "ura": 4 } - + this.categoryAliases = {} - assets.categories.forEach(cat => { - this.categoryAliases[cat.title.toLowerCase()] = cat.title - if(cat.aliases != null){ + this.categoryAliases[cat.title.toLowerCase()] = cat.id + if(cat.aliases){ cat.aliases.forEach(alias => { - this.categoryAliases[alias.toLowerCase()] = cat.title - }); + this.categoryAliases[alias.toLowerCase()] = cat.id + }) } - }); - + if(cat.title_lang){ + for(var i in cat.title_lang){ + this.categoryAliases[cat.title_lang[i].toLowerCase()] = cat.id + } + } + }) + this.assetSelectors = { "bg-pattern-1": ".pattern-bg", "bg_genre_0": "#song-select", @@ -130,7 +134,11 @@ var equalsPos = line.indexOf("=") if(equalsPos !== -1 && line.slice(0, equalsPos).trim() === "genrename"){ var value = line.slice(equalsPos + 1).trim() - category = this.categoryAliases[value] || data[i].trim().slice(equalsPos + 1).trim() + if(value.toLowerCase() in this.categoryAliases){ + category = value + }else{ + category = data[i].trim().slice(equalsPos + 1).trim() + } break } } @@ -140,12 +148,16 @@ var line = data[i].trim().toLowerCase() if(line.startsWith("#title:")){ var value = line.slice(7).trim() - if(value in this.categoryAliases){ - category = this.categoryAliases[value] + if(value.toLowerCase() in this.categoryAliases){ + category = value } }else if(line.startsWith("#genre:")){ var value = line.slice(7).trim() - category = this.categoryAliases[value] || data[i].trim().slice(7).trim() + if(value.toLowerCase() in this.categoryAliases){ + category = value + }else{ + category = data[i].trim().slice(7).trim() + } break } } @@ -169,7 +181,11 @@ var filesLoop = fileObj => { 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 + if(category.toLowerCase() in this.categoryAliases){ + fileObj.category_id = this.categoryAliases[category.toLowerCase()] + }else{ + fileObj.category = category + } fileObj.categoryLevel = level } } @@ -189,6 +205,7 @@ var file = fileObj.file var index = fileObj.index var category = fileObj.category + var category_id = fileObj.category_id var reader = new FileReader() var promise = pageEvents.load(reader).then(event => { var data = event.target.result.replace(/\0/g, "").split("\n") @@ -226,7 +243,11 @@ songObj.music = this.otherFiles[dir + meta.wave.toLowerCase()] || songObj.music } if(meta.genre){ - songObj.category = this.categoryAliases[meta.genre.toLowerCase()] || meta.genre + if(meta.genre.toLowerCase() in this.categoryAliases){ + songObj.category_id = this.categoryAliases[meta.genre.toLowerCase()] + }else{ + songObj.category = meta.genre + } } if(meta.taikowebskin){ songObj.song_skin = this.getSkin(dir, meta.taikowebskin) @@ -290,8 +311,15 @@ if(subtitleLangAdded){ songObj.subtitle_lang = subtitleLang } - if(!songObj.category){ - songObj.category = category || this.getCategory(file, [songTitle || songObj.title, file.name.slice(0, file.name.lastIndexOf("."))]) + if(!songObj.category_id && !songObj.category){ + if(!category && category_id === undefined){ + songObj.category_id = this.getCategory(file, [songTitle || songObj.title, file.name.slice(0, file.name.lastIndexOf("."))]) + }else if(category){ + songObj.category = category + songObj.orginalCategory = category + }else{ + songObj.category_id = category_id + } } if(coursesAdded){ this.songs[index] = songObj @@ -312,6 +340,7 @@ var file = fileObj.file var index = fileObj.index var category = fileObj.category + var category_id = fileObj.category_id var reader = new FileReader() var promise = pageEvents.load(reader).then(event => { var data = event.target.result.replace(/\0/g, "").split("\n") @@ -352,7 +381,14 @@ songObj.title = filename } this.songs[index] = songObj - songObj.category = category || this.getCategory(file, [osu.metadata.TitleUnicode, osu.metadata.Title, file.name.slice(0, file.name.lastIndexOf("."))]) + if(!category && category_id === undefined){ + songObj.category_id = this.getCategory(file, [osu.metadata.TitleUnicode, osu.metadata.Title, file.name.slice(0, file.name.lastIndexOf("."))]) + }else if(category){ + songObj.category = category + songObj.orginalCategory = category + }else{ + songObj.category_id = category_id + } var hash = md5.base64(event.target.result).slice(0, -2) songObj.hash = hash scoreStorage.songTitles[songObj.title] = hash diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 69d35ae..2f95327 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -56,40 +56,52 @@ class SongSelect{ outline: "#d36aa2" }, "default": { + sort: null, background: "#ececec", border: ["#fbfbfb", "#8b8b8b"], outline: "#656565", infoFill: "#656565" } } - - for(let category of assets.categories){ + + var songSkinLength = Object.keys(this.songSkin).length + for(var i in assets.categories){ + var category = assets.categories[i] if(!this.songSkin[category.title] && category.songSkin){ - if(!category.songSkin.sort == null){ - category.songSkin.sort = Object.keys(this.songSkin).length + 1 + if(category.songSkin.sort === null){ + category.songSkin.sort = songSkinLength + 1 } this.songSkin[category.title] = category.songSkin } } - - this.songSkin['default'].sort= Object.keys(this.songSkin).length + 1 - + this.songSkin["default"].sort = songSkinLength + 1 + this.font = strings.font this.songs = [] for(let song of assets.songs){ var title = this.getLocalTitle(song.title, song.title_lang) var subtitle = this.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang) - let category = assets.categories.find(cat=>cat.id == song.category_id) - var categoryName = this.getLocalTitle(category.title, category.title_lang) + var skin = null + var categoryName = "" + var originalCategory = "" + if(song.category_id !== null && song.category_id !== undefined){ + var category = assets.categories.find(cat => cat.id === song.category_id) + var categoryName = this.getLocalTitle(category.title, category.title_lang) + var originalCategory = category.title + var skin = this.songSkin[category.title] + }else if(song.category){ + var categoryName = song.category + var originalCategory = song.category + } this.songs.push({ id: song.id, title: title, originalTitle: song.title, subtitle: subtitle, - skin: song.category in this.songSkin ? this.songSkin[song.category] : this.songSkin.default, + skin: skin || this.songSkin.default, courses: song.courses, - originalCategory: song.category, + originalCategory: originalCategory, category: categoryName, category_id: song.category_id, preview: song.preview || 0, @@ -108,14 +120,14 @@ class SongSelect{ this.songs.sort((a, b) => { var catA = a.originalCategory in this.songSkin ? this.songSkin[a.originalCategory] : this.songSkin.default var catB = b.originalCategory in this.songSkin ? this.songSkin[b.originalCategory] : this.songSkin.default - if(catA.sort === catB.sort){ - if(a.order === b.order){ - return a.id > b.id ? 1 : -1 - }else{ - return a.order > b.order ? 1 : -1 - } - }else{ + if(catA.sort !== catB.sort){ return catA.sort > catB.sort ? 1 : -1 + }else if(a.originalCategory !== b.originalCategory){ + return a.originalCategory > b.originalCategory ? 1 : -1 + }else if(a.order !== b.order){ + return a.order > b.order ? 1 : -1 + }else{ + return a.id > b.id ? 1 : -1 } }) this.songs.push({ From db5e76880b75c42f3e392ca9bbc26d6cbb0694cd Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Mon, 27 Apr 2020 20:07:43 +0300 Subject: [PATCH 17/17] Revert some whitespace changes --- public/src/js/settings.js | 6 ++---- public/src/js/strings.js | 7 +------ public/src/js/titlescreen.js | 3 +-- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/public/src/js/settings.js b/public/src/js/settings.js index d5b7ce6..1f7a9bb 100644 --- a/public/src/js/settings.js +++ b/public/src/js/settings.js @@ -147,12 +147,10 @@ class Settings{ } setLang(lang, noEvent){ strings = lang - var boldFonts = strings.font === "Microsoft YaHei, sans-serif" - loader.screen.style.fontFamily = strings.font - loader.screen.style.fontWeight = boldFonts ? "bold" : "" + loader.screen.style.fontFamily = strings.font + loader.screen.style.fontWeight = boldFonts ? "bold" : "" loader.screen.classList[boldFonts ? "add" : "remove"]("bold-fonts") - if(!noEvent){ pageEvents.send("language-change", lang.id) } diff --git a/public/src/js/strings.js b/public/src/js/strings.js index c4fa550..cca613e 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -1073,9 +1073,7 @@ var translations = { ko: "가사가있는" } } - var allStrings = {} - function separateStrings(){ for(var j in languageList){ var lang = languageList[j] @@ -1083,9 +1081,8 @@ function separateStrings(){ id: lang } var str = allStrings[lang] - var translateObj = function(obj, name, str){ - if(obj != null && "en" in obj && obj["en"] != null){ + if("en" in obj){ for(var i in obj){ str[name] = obj[lang] || obj.en } @@ -1096,11 +1093,9 @@ function separateStrings(){ } } } - for(var i in translations){ translateObj(translations[i], i, str) } } } - separateStrings() diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index ca700c7..aa98e4d 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -77,8 +77,7 @@ class Titlescreen{ } } setLang(lang, noEvent){ - settings.setLang(lang, true) - + settings.setLang(lang, true) if(this.songId){ return }