From 190beb224dc424e8583698c632355f6b8ef1cfad Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Tue, 9 Oct 2018 16:07:53 +0300 Subject: [PATCH] Songselect: Add cache for shadows --- public/index.html | 1 + public/src/css/titlescreen.css | 4 +- public/src/js/canvascache.js | 67 +++++++++ public/src/js/canvasdraw.js | 153 +++++++++++-------- public/src/js/canvastest.js | 3 + public/src/js/loader.js | 1 - public/src/js/scoresheet.js | 77 ++++++---- public/src/js/songselect.js | 260 +++++++++++++++++++++++---------- 8 files changed, 391 insertions(+), 175 deletions(-) create mode 100644 public/src/js/canvascache.js diff --git a/public/index.html b/public/index.html index e40cd8e..a9062d4 100644 --- a/public/index.html +++ b/public/index.html @@ -50,6 +50,7 @@ + diff --git a/public/src/css/titlescreen.css b/public/src/css/titlescreen.css index 2d8efbb..eacadc0 100644 --- a/public/src/css/titlescreen.css +++ b/public/src/css/titlescreen.css @@ -34,8 +34,6 @@ } .click-to-continue::before{ -webkit-text-stroke: 0.25em #f00; + filter: blur(0.3vmin); left: auto; } -#screen:not(.disable-blur) .click-to-continue::before{ - filter: blur(0.3vmin); -} diff --git a/public/src/js/canvascache.js b/public/src/js/canvascache.js new file mode 100644 index 0000000..4ebae13 --- /dev/null +++ b/public/src/js/canvascache.js @@ -0,0 +1,67 @@ +class CanvasCache{ + constructor(w, h, scale){ + this.canvas = document.createElement("canvas") + this.ctx = this.canvas.getContext("2d") + this.map = new Map() + if(w){ + this.resize(w, h, scale) + } + } + resize(w, h, scale){ + this.map.clear() + this.scale = scale + this.x = 0 + this.y = 0 + this.w = w + this.h = h + this.lastW = 0 + this.lastH = 0 + this.canvas.width = this.w * this.scale + this.canvas.height = this.h * this.scale + this.ctx.scale(this.scale, this.scale) + } + get(config, callback){ + var img = this.map.get(config.id) + var saved = false + if(!img){ + var w = config.w + var h = config.h + this.x += this.lastW + 1 + if(this.x + w > this.w){ + this.x = 0 + this.y += this.lastH + 1 + } + this.lastW = w + this.lastH = Math.max(this.lastH, h) + img = { + x: this.x, + y: this.y, + w: w, + h: h + } + this.map.set(config.id, img) + + saved = true + this.ctx.save() + this.ctx.translate(img.x |0, img.y |0) + this.ctx.beginPath() + this.ctx.rect(0, 0, img.w |0, img.h |0) + this.ctx.clip() + + callback(this.ctx) + } + var z = this.scale + config.ctx.drawImage(this.canvas, + img.x * z |0, img.y * z |0, img.w * z |0, img.h * z |0, + config.x |0, config.y |0, config.w |0, config.h |0 + ) + if(saved){ + this.ctx.restore() + } + } + clean(){ + delete this.map + delete this.ctx + delete this.canvas + } +} diff --git a/public/src/js/canvasdraw.js b/public/src/js/canvasdraw.js index 7786cb7..d899003 100644 --- a/public/src/js/canvasdraw.js +++ b/public/src/js/canvasdraw.js @@ -60,6 +60,10 @@ uppercaseDigit: /[A-ZA-Z0-90-9]/ } + this.songFrameCache = new CanvasCache() + this.diffStarCache = new CanvasCache() + this.crownCache = new CanvasCache() + this.tmpCanvas = document.createElement("canvas") this.tmpCtx = this.tmpCanvas.getContext("2d") } @@ -95,15 +99,34 @@ ctx.save() - this.shadow({ - ctx: ctx, - fill: "rgba(0, 0, 0, 0.5)", - blur: 10, - x: 5, - y: 5 - }) - ctx.fillStyle = "#000" - ctx.fillRect(x, y, w, h) + var shadowBg = (ctx, noForce) => { + this.shadow({ + ctx: ctx, + fill: "rgba(0, 0, 0, 0.5)", + blur: 10, + x: 5, + y: 5, + force: !noForce + }) + ctx.fillStyle = "#000" + ctx.fillRect(0, 0, w, h) + } + if(config.cached){ + if(this.songFrameCache.w !== config.frameCache.w){ + this.songFrameCache.resize(config.frameCache.w, config.frameCache.h, config.frameCache.ratio) + } + this.songFrameCache.get({ + ctx: ctx, + x: x, + y: y, + w: w + 15, + h: h + 15, + id: "shadow" + config.cached + }, shadowBg) + }else{ + ctx.translate(x, y) + shadowBg(ctx, true) + } ctx.restore() ctx.save() @@ -211,15 +234,7 @@ var ctx = config.ctx var inputText = config.text var mul = config.fontSize / 40 - var ura = false - if(inputText.endsWith(" (裏)")){ - inputText = inputText.slice(0, -4) - ura = true - }else if(inputText.endsWith("(裏)")){ - inputText = inputText.slice(0, -3) - ura = true - } var string = inputText.split("") var drawn = [] @@ -246,7 +261,7 @@ }else if(r.tilde.test(symbol)){ // Rotated hyphen, tilde if(symbol === "~"){ - symbol = "~" + symbol = "~" } drawn.push({text: symbol, x: 0, y: 2, h: 35, rotate: true}) }else if(r.tall.test(symbol)){ @@ -281,18 +296,8 @@ ctx.save() ctx.translate(config.x, config.y) - var scale = 1 - if(config.height){ - var height = config.height - (ura ? 52 * mul : 0) - if(drawnHeight > height){ - scale = height / drawnHeight - ctx.scale(1, scale) - } - } - - if(ura){ - // Circled ura - drawn.push({text: "裏", x: 0, y: 18, h: 52, ura: true, scale: [1, 1 / scale]}) + if(config.height && drawnHeight > config.height){ + ctx.scale(1, config.height / drawnHeight) } var actions = [] @@ -322,7 +327,7 @@ currentX += 20 * mul } var currentY = offsetY + symbol.y * mul - if(symbol.rotate || symbol.scale || symbol.svg || symbol.ura){ + if(symbol.rotate || symbol.scale || symbol.svg){ saved = true ctx.save() @@ -347,23 +352,7 @@ }else{ ctx.textAlign = "center" } - if(symbol.ura){ - ctx.font = (30 * mul) + "px Meiryo" - 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) } offsetY += symbol.h * mul if(saved){ @@ -463,7 +452,8 @@ fill: "rgba(0, 0, 0, " + (1 / (layer.shadow[3] || 2)) + ")", blur: layer.shadow[2], x: layer.shadow[0], - y: layer.shadow[1] + y: layer.shadow[1], + force: config.forceShadow }) } var offsetX = 0 @@ -629,19 +619,35 @@ diffStar(config){ var ctx = config.ctx ctx.save() - ctx.fillStyle = config.songSel ? "#fff" : "#f72568" if(config.songSel){ - this.shadow({ + if(this.diffStarCache.scale !== config.ratio){ + this.diffStarCache.resize(30, 30, config.ratio) + } + var offset = 30 / 2 - 18 / 2 + this.diffStarCache.get({ ctx: ctx, - fill: "#fff", - blur: 10 + x: config.x - 9 - offset, + y: config.y - 9 - offset, + w: 30, + h: 30, + id: "star" + }, ctx => { + ctx.fillStyle = "#fff" + this.shadow({ + ctx: ctx, + fill: "#fff", + blur: 10, + force: true + }) + ctx.translate(offset, offset) + ctx.fill(this.diffStarPath) }) - ctx.translate(config.x - 9, config.y - 9) }else{ + ctx.fillStyle = "#f72568" ctx.translate(config.x - 10.5, config.y - 9.5) ctx.scale(1.1, 1.1) + ctx.fill(this.diffStarPath) } - ctx.fill(this.diffStarPath) ctx.restore() } @@ -708,14 +714,27 @@ ctx.translate(-47, -39) ctx.miterLimit = 1.7 - ctx.save() - ctx.strokeStyle = "#fff" - ctx.lineWidth = 35 - if(!disableBlur){ - ctx.filter = "blur(1.5px)" + if(!this.crownCache.w){ + this.crownCache.resize(140, 140, config.ratio) } - ctx.stroke(this.crownPath) - ctx.restore() + var offset = 140 / 2 - 94 / 2 + this.crownCache.get({ + ctx: ctx, + x: -offset, + y: -offset, + w: 140, + h: 140, + id: "crown" + }, ctx => { + ctx.save() + ctx.translate(offset, offset) + ctx.strokeStyle = "#fff" + ctx.lineWidth = 35 + ctx.miterLimit = 1.7 + ctx.filter = "blur(1.5px)" + ctx.stroke(this.crownPath) + ctx.restore() + }) if(config.shine){ ctx.strokeStyle = "#fff" @@ -770,7 +789,7 @@ } shadow(config){ - if(!disableBlur){ + if(!disableBlur || config.force){ var ctx = config.ctx if(config.fill){ ctx.shadowColor = config.fill @@ -790,4 +809,12 @@ getMS(){ return +new Date } + + clean(){ + this.songFrameCache.clean() + this.diffStarCache.clean() + this.crownCache.clean() + delete this.tmpCtx + delete this.tmpCanvas + } } diff --git a/public/src/js/canvastest.js b/public/src/js/canvastest.js index f9f3580..5a5e92b 100644 --- a/public/src/js/canvastest.js +++ b/public/src/js/canvastest.js @@ -8,6 +8,7 @@ class CanvasTest{ this.canvas.height = height this.ctx = this.canvas.getContext("2d") this.ctx.scale(pixelRatio, pixelRatio) + this.ratio = pixelRatio this.draw = new CanvasDraw() this.font = "serif" @@ -60,6 +61,7 @@ class CanvasTest{ innerBorder: this.songAsset.innerBorder, background: "#efb058", borderStyle: ["#ffe7bd", "#c68229"], + ratio: this.ratio, innerContent: () => {} }) } @@ -138,6 +140,7 @@ class CanvasTest{ this.ctx.fillText(text, x, y) } clean(){ + this.draw.clean() delete this.ctx delete this.canvas } diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 2b6307b..62dce66 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -88,7 +88,6 @@ class Loader{ if(result > 1000 / 50){ // Less than 50 fps with blur enabled disableBlur = true - this.screen.classList.add("disable-blur") } })) diff --git a/public/src/js/scoresheet.js b/public/src/js/scoresheet.js index 67b540f..3556cfe 100644 --- a/public/src/js/scoresheet.js +++ b/public/src/js/scoresheet.js @@ -21,6 +21,7 @@ class Scoresheet{ this.numbers = "001122334455667788900112233445".split("") this.draw = new CanvasDraw() + this.canvasCache = new CanvasCache() this.gamepad = new Gamepad({ "13": ["a", "b", "start", "ls", "rs"] @@ -130,6 +131,8 @@ class Scoresheet{ ctx.scale(ratio, ratio) this.canvas.style.width = (winW / this.pixelRatio) + "px" this.canvas.style.height = (winH / this.pixelRatio) + "px" + + this.canvasCache.resize(winW / ratio, 80 + 1, ratio) }else if(!document.hasFocus() && this.state.screen === "scoresShown"){ return }else{ @@ -237,36 +240,47 @@ class Scoresheet{ ctx.scale(ratio, ratio) ctx.translate(frameLeft, frameTop) - this.draw.layeredText({ + this.canvasCache.get({ ctx: ctx, - text: "成績発表", - fontSize: 48, - fontFamily: this.font, - x: 23, - y: 15, - letterSpacing: 3 - }, [ - {x: -2, y: -2, outline: "#000", letterBorder: 22}, - {}, - {x: 2, y: 2, shadow: [2, 2, 7]}, - {x: 2, y: 2, outline: "#ad1516", letterBorder: 10}, - {x: -2, y: -2, outline: "#ff797b"}, - {outline: "#f70808"}, - {fill: "#fff", shadow: [-1, 1, 3, 1.5]} - ]) - - this.draw.layeredText({ - ctx: ctx, - text: this.results.title, - fontSize: 40, - fontFamily: this.font, - x: 1257, - y: 20, - align: "right" - }, [ - {outline: "#000", letterBorder: 10, shadow: [1, 1, 3]}, - {fill: "#fff"} - ]) + x: 0, + y: 0, + w: winW, + h: 80, + id: "results" + }, ctx => { + this.draw.layeredText({ + ctx: ctx, + text: "成績発表", + fontSize: 48, + fontFamily: this.font, + x: 23, + y: 15, + letterSpacing: 3, + forceShadow: true + }, [ + {x: -2, y: -2, outline: "#000", letterBorder: 22}, + {}, + {x: 2, y: 2, shadow: [2, 2, 7]}, + {x: 2, y: 2, outline: "#ad1516", letterBorder: 10}, + {x: -2, y: -2, outline: "#ff797b"}, + {outline: "#f70808"}, + {fill: "#fff", shadow: [-1, 1, 3, 1.5]} + ]) + + this.draw.layeredText({ + ctx: ctx, + text: this.results.title, + fontSize: 40, + fontFamily: this.font, + x: 1257, + y: 20, + align: "right", + forceShadow: true + }, [ + {outline: "#000", letterBorder: 10, shadow: [1, 1, 3]}, + {fill: "#fff"} + ]) + }) ctx.save() for(var p = 0; p < players; p++){ @@ -470,7 +484,8 @@ class Scoresheet{ x: 395, y: 218, scale: crownScale, - shine: shine + shine: shine, + ratio: ratio }) ctx.restore() @@ -649,6 +664,8 @@ class Scoresheet{ } clean(){ + this.draw.clean() + this.canvasCache.clean() assets.sounds["bgm_result"].stop() snd.musicGain.fadeIn() this.redrawRunning = false diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index dfd5538..ddf6a0c 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -132,13 +132,19 @@ class SongSelect{ marginLeft: 18, width: 82, selectedWidth: 382, + fullWidth: 912, height: 452, + fullHeight: 502, border: 6, innerBorder: 8, letterBorder: 12 } this.draw = new CanvasDraw() + this.songTitleCache = new CanvasCache() + this.selectTextCache = new CanvasCache() + this.categoryCache = new CanvasCache() + this.difficultyCache = new CanvasCache() this.difficulty = ["かんたん", "ふつう", "むずかしい", "おに"] this.difficultyId = ["easy", "normal", "hard", "oni"] @@ -530,6 +536,24 @@ class SongSelect{ ctx.scale(ratio, ratio) this.canvas.style.width = (winW / this.pixelRatio) + "px" this.canvas.style.height = (winH / this.pixelRatio) + "px" + + var borders = (this.songAsset.border + this.songAsset.innerBorder) * 2 + this.songTitleCache.resize((this.songAsset.width - borders + 1) * this.songs.length, (this.songAsset.height - borders + 1) * 2, ratio + 0.5) + + this.selectTextCache.resize((280 + 53 + 60 + 1) * 2, this.songAsset.marginTop + 15, ratio + 0.5) + + 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) * categories , ratio + 0.5) + + this.difficultyCache.resize((44 + 56 + 2) * 4, 135 + 10, ratio + 0.5) }else if(!document.hasFocus()){ this.pointer(false) return @@ -567,39 +591,60 @@ class SongSelect{ } if(screen === "title" || screen === "titleFadeIn" || screen === "song"){ - this.draw.layeredText({ + this.selectTextCache.get({ ctx: ctx, - text: "曲をえらぶ", - fontSize: 48, - fontFamily: this.font, - x: frameLeft + 53, - y: frameTop + 30, - letterSpacing: 2 - }, [ - {x: -2, y: -2, outline: "#000", letterBorder: 22}, - {}, - {x: 2, y: 2, shadow: [3, 3, 3]}, - {x: 2, y: 2, outline: "#ad1516", letterBorder: 10}, - {x: -2, y: -2, outline: "#ff797b"}, - {outline: "#f70808"}, - {fill: "#fff", shadow: [-1, 1, 3, 1.5]} - ]) + x: frameLeft, + y: frameTop, + w: 280 + 53 + 60, + h: this.songAsset.marginTop + 15, + id: "song" + }, ctx => { + this.draw.layeredText({ + ctx: ctx, + text: "曲をえらぶ", + fontSize: 48, + fontFamily: this.font, + x: 53, + y: 30, + letterSpacing: 2, + forceShadow: true + }, [ + {x: -2, y: -2, outline: "#000", letterBorder: 22}, + {}, + {x: 2, y: 2, shadow: [3, 3, 3]}, + {x: 2, y: 2, outline: "#ad1516", letterBorder: 10}, + {x: -2, y: -2, outline: "#ff797b"}, + {outline: "#f70808"}, + {fill: "#fff", shadow: [-1, 1, 3, 1.5]} + ]) + }) var category = this.songs[this.selectedSong].category if(category){ - this.draw.layeredText({ + var selectedSong = this.songs[this.selectedSong] + this.categoryCache.get({ ctx: ctx, - text: category, - fontSize: 40, - fontFamily: this.font, - x: winW / 2, - y: frameTop + 38, - width: 255, - align: "center" - }, [ - {outline: this.songs[this.selectedSong].skin.outline, letterBorder: 12, shadow: [3, 3, 3]}, - {fill: "#fff"} - ]) + x: winW / 2 - 280 / 2, + y: frameTop, + w: 280, + h: this.songAsset.marginTop, + id: category + selectedSong.skin.outline + }, ctx => { + this.draw.layeredText({ + ctx: ctx, + text: category, + fontSize: 40, + fontFamily: this.font, + x: 280 / 2, + y: 38, + width: 255, + align: "center", + forceShadow: true + }, [ + {outline: selectedSong.skin.outline, letterBorder: 12, shadow: [3, 3, 3]}, + {fill: "#fff"} + ]) + }) } } @@ -668,6 +713,12 @@ class SongSelect{ } } + this.songFrameCache = { + w: this.songAsset.width + this.songAsset.selectedWidth + this.songAsset.fullWidth + (15 + 1) * 3, + h: this.songAsset.fullHeight + 16, + ratio: ratio + } + if(screen === "title" || screen === "titleFadeIn" || screen === "song"){ for(var i = this.selectedSong - 1; ; i--){ var highlight = 0 @@ -726,8 +777,8 @@ class SongSelect{ } var selectedHeight = this.songAsset.height if(screen === "difficulty"){ - selectedWidth = 912 - selectedHeight = 502 + selectedWidth = this.songAsset.fullWidth + selectedHeight = this.songAsset.fullHeight highlight = 0 } @@ -744,29 +795,41 @@ class SongSelect{ highlight: highlight, noCrop: screen === "difficulty", animateMS: this.state.moveMS, + cached: selectedWidth === this.songAsset.fullWidth ? 3 : (selectedWidth === this.songAsset.selectedWidth ? 2 : (selectedWidth === this.songAsset.width ? 1 : 0)), + frameCache: this.songFrameCache, innerContent: (x, y, w, h) => { ctx.strokeStyle = "#000" if(screen === "title" || screen === "titleFadeIn" || screen === "song"){ var opened = ((selectedWidth - this.songAsset.width) / (this.songAsset.selectedWidth - this.songAsset.width)) var songSel = true }else{ - this.draw.layeredText({ + this.selectTextCache.get({ ctx: ctx, - text: "むずかしさをえらぶ", - fontSize: 46, - fontFamily: this.font, - x: x - 144, - y: y - 24, - width: 280 - }, [ - {x: -2, y: -2, outline: "#000", letterBorder: 23}, - {shadow: [3, 3, 3]}, - {x: 2, y: 2}, - {x: 2, y: 2, outline: "#ad1516", letterBorder: 10}, - {x: -2, y: -2, outline: "#ff797b"}, - {outline: "#f70808"}, - {fill: "#fff", shadow: [-1, 1, 3, 1.5]} - ]) + x: x - 144 - 53, + y: y - 24 - 30, + w: 280 + 53 + 60, + h: this.songAsset.marginTop + 15, + id: "difficulty" + }, ctx => { + this.draw.layeredText({ + ctx: ctx, + text: "むずかしさをえらぶ", + fontSize: 46, + fontFamily: this.font, + x: 53, + y: 30, + width: 280, + forceShadow: true + }, [ + {x: -2, y: -2, outline: "#000", letterBorder: 23}, + {}, + {x: 2, y: 2, shadow: [3, 3, 3]}, + {x: 2, y: 2, outline: "#ad1516", letterBorder: 10}, + {x: -2, y: -2, outline: "#ff797b"}, + {outline: "#f70808"}, + {fill: "#fff", shadow: [-1, 1, 3, 1.5]} + ]) + }) var opened = 1 var songSel = false var _x = x + 62 @@ -883,16 +946,26 @@ class SongSelect{ border: 4.5 }) } - this.draw.verticalText({ + var offset = (songSel ? 44 : 56) / 2 + this.difficultyCache.get({ ctx: ctx, - text: this.difficulty[i], - x: _x, + x: _x - offset, y: songSel ? _y + 10 : _y + 23, - width: songSel ? 44 : 56, - height: songSel ? (i === 1 ? 66 : 88) : (i === 0 ? 130 : i === 1 ? 110 : 135), - fill: "#000", - fontSize: songSel ? 25 : (i === 2 ? 45 : 40), - fontFamily: this.font + w: songSel ? 44 : 56, + h: (songSel ? 88 : 135) + 10, + id: this.difficulty[i] + (songSel ? "1" : "0") + }, ctx => { + this.draw.verticalText({ + ctx: ctx, + text: this.difficulty[i], + x: offset, + y: 0, + width: songSel ? 44 : 56, + height: songSel ? (i === 1 ? 66 : 88) : (i === 0 ? 130 : (i === 1 ? 110 : 135)), + fill: "#000", + fontSize: songSel ? 25 : (i === 2 ? 45 : 40), + fontFamily: this.font + }) }) for(var j = 0; j < 10; j++){ if(songSel){ @@ -910,7 +983,8 @@ class SongSelect{ ctx: ctx, songSel: songSel, x: _x, - y: yPos + y: yPos, + ratio: ratio }) } } @@ -959,23 +1033,37 @@ class SongSelect{ } ctx.globalAlpha = 1 - Math.max(0, opened - 0.5) * 2 ctx.fillStyle = selectedSkin.background - ctx.fillRect(x,y,w,h) + ctx.fillRect(x, y, w, h) ctx.globalAlpha = 1 - var textX = Math.max(w - 37, w / 2) + var borders = (this.songAsset.border + this.songAsset.innerBorder) * 2 + var textW = this.songAsset.width - borders + var textH = this.songAsset.height - borders + var textX = Math.max(w - 37 - textW / 2, w / 2 - textW / 2) var textY = opened * 12 + (1 - opened) * 7 - this.draw.verticalText({ + this.songTitleCache.get({ ctx: ctx, - text: currentSong.title, x: x + textX, - y: y + textY, - width: w, - height: h - 35, - fill: "#fff", - outline: selectedSkin.outline, - outlineSize: this.songAsset.letterBorder, - fontSize: 40, - fontFamily: this.font + y: y + textY - 7, + w: textW, + h: textH, + id: currentSong.title + selectedSkin.outline, + }, ctx => { + this.draw.verticalText({ + ctx: ctx, + text: currentSong.title, + x: textW / 2, + y: 7, + width: textW, + height: textH - 35, + fill: "#fff", + outline: selectedSkin.outline, + outlineSize: this.songAsset.letterBorder, + fontSize: 40, + fontFamily: this.font + }) }) + //ctx.fillStyle="#f00" + //ctx.fillRect(textX,textY,textW,textH) } }) @@ -1014,19 +1102,30 @@ class SongSelect{ config.outline = config.song.skin.outline config.text = config.song.title config.animateMS = this.state.moveMS + config.cached = 1 + config.frameCache = this.songFrameCache config.innerContent = (x, y, w, h) => { - this.draw.verticalText({ + this.songTitleCache.get({ ctx: ctx, - text: config.text, - x: x + w / 2, - y: y + 7, - width: w, - height: h - 35, - fill: "#fff", - outline: config.outline, - outlineSize: this.songAsset.letterBorder, - fontSize: 40, - fontFamily: this.font + x: x, + y: y, + w: w, + h: h, + id: config.text + config.outline, + }, ctx => { + this.draw.verticalText({ + ctx: ctx, + text: config.text, + x: w / 2, + y: 7, + width: w, + height: h - 35, + fill: "#fff", + outline: config.outline, + outlineSize: this.songAsset.letterBorder, + fontSize: 40, + fontFamily: this.font + }) }) } this.draw.songFrame(config) @@ -1137,6 +1236,11 @@ class SongSelect{ } clean(){ + this.draw.clean() + this.songTitleCache.clean() + this.selectTextCache.clean() + this.categoryCache.clean() + this.difficultyCache.clean() assets.sounds["bgm_songsel"].stop() if(!this.bgmEnabled){ snd.musicGain.fadeIn()