Skip to content

Commit

Permalink
Optimize speed for running project
Browse files Browse the repository at this point in the history
  • Loading branch information
nighca committed Jan 10, 2025
1 parent 700dcad commit 0aead4e
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 33 deletions.
2 changes: 1 addition & 1 deletion spx-gui/src/components/editor/preview/EditorPreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
>
{{ $t({ en: 'Rerun', zh: '重新运行' }) }}
</UIButton>
<UIButton class="button" type="boring" :disabled="running.initializing" @click="handleStop">
<UIButton class="button" type="boring" @click="handleStop">
{{ $t({ en: 'Stop', zh: '停止' }) }}
</UIButton>
</UICardHeader>
Expand Down
4 changes: 2 additions & 2 deletions spx-gui/src/components/project/runner/ProjectRunner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ function handleConsole(type: 'log' | 'warn', args: unknown[]) {
const version = useSpxVersion()
defineExpose({
async run() {
return projectRunnerRef.value?.run()
async run(signal?: AbortSignal) {
return projectRunnerRef.value?.run(signal)
},
async stop() {
return projectRunnerRef.value?.stop()
Expand Down
39 changes: 25 additions & 14 deletions spx-gui/src/components/project/runner/v1/ProjectRunnerV1.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,32 @@
</div>
</template>

<script lang="ts">
const zipEntryCache = new WeakMap<File, Promise<Blob>>()
function getZipEntry(file: File) {
if (zipEntryCache.has(file)) return zipEntryCache.get(file)!
const zipEntry = toNativeFile(file).then((nf) => {
// For svg files, we convert them to png before sending to spx (v1):
// 1. Compatibility: Many SVG features are not supported in spx v1
// 2. Improve performance: SVG rendering is slow in spx v1
if (nf.type === 'image/svg+xml') return toPng(nf)
return nf
})
zipEntryCache.set(file, zipEntry)
zipEntry.catch(() => zipEntryCache.delete(file))
return zipEntry
}
</script>

<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue'
import JSZip from 'jszip'
import { registerPlayer } from '@/utils/player-registry'
import { until } from '@/utils/utils'
import { useFileUrl } from '@/utils/file'
import { toPng } from '@/utils/img'
import { toNativeFile } from '@/models/common/file'
import { File, toNativeFile } from '@/models/common/file'
import { Project } from '@/models/project'
import { UIImg, UILoading } from '@/components/ui'
import IframeDisplay, { preload } from './IframeDisplay.vue'
Expand Down Expand Up @@ -47,30 +65,23 @@ onUnmounted(() => {
registered.onStopped()
})
async function getProjectZipData() {
async function getProjectZipData(signal?: AbortSignal) {
const zip = new JSZip()
const [, files] = await props.project.export()
signal?.throwIfAborted()
Object.entries(files).forEach(([path, file]) => {
if (file == null) return
zip.file(
path,
toNativeFile(file).then((nf) => {
// For svg files, we convert them to png before sending to spx (v1):
// 1. Compatibility: Many SVG features are not supported in spx v1
// 2. Improve performance: SVG rendering is slow in spx v1
if (nf.type === 'image/svg+xml') return toPng(nf)
return nf
})
)
zip.file(path, getZipEntry(file))
})
return zip.generateAsync({ type: 'arraybuffer' })
}
defineExpose({
async run() {
async run(signal?: AbortSignal) {
loading.value = true
registered.onStart()
zipData.value = await getProjectZipData()
zipData.value = await getProjectZipData(signal)
signal?.throwIfAborted()
await until(() => !loading.value)
},
stop() {
Expand Down
5 changes: 4 additions & 1 deletion spx-gui/src/components/project/runner/v2/ProjectRunnerV2.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,15 @@ onMounted(() => {
})
defineExpose({
async run() {
async run(signal?: AbortSignal) {
loading.value = true
registered.onStart()
const iframeWindow = await untilNotNull(iframeWindowRef)
signal?.throwIfAborted()
const projectData = await getProjectData()
signal?.throwIfAborted()
await withLog('startGame', iframeWindow.startGame(projectData, assetURLs))
signal?.throwIfAborted()
loading.value = false
},
async stop() {
Expand Down
21 changes: 6 additions & 15 deletions spx-gui/src/utils/img.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,15 @@ export function convertImg(
return new Promise<Blob>((resolve, reject) => {
const img = new Image()
img.onload = async () => {
const canvas = document.createElement('canvas')
let size = { width: img.naturalWidth, height: img.naturalHeight }
if (input.type === 'image/svg+xml') {
const svgText = await input.text()
const { width, height } = await getSVGSize(svgText)
canvas.width = width
canvas.height = height
} else {
canvas.width = img.naturalWidth
canvas.height = img.naturalHeight
size = await getSVGSize(svgText)
}
canvas.getContext('2d')?.drawImage(img, 0, 0, canvas.width, canvas.height)
canvas.toBlob((newBlob) => {
if (newBlob == null) {
reject(new Error('toBlob failed'))
return
}
resolve(newBlob)
}, type)
const canvas = new OffscreenCanvas(size.width, size.height)
const ctx = canvas.getContext('2d')!
ctx.drawImage(img, 0, 0, size.width, size.height)
resolve(canvas.convertToBlob({ type }))
}
img.onerror = (e) => reject(new Error(`load image failed: ${e.toString()}`))
const url = URL.createObjectURL(input)
Expand Down

0 comments on commit 0aead4e

Please sign in to comment.