Skip to content

Commit

Permalink
details
Browse files Browse the repository at this point in the history
  • Loading branch information
nighca committed Nov 13, 2024
1 parent fd92b6d commit 95a93a1
Show file tree
Hide file tree
Showing 31 changed files with 440 additions and 676 deletions.
13 changes: 13 additions & 0 deletions spx-gui/public/runner/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Files from gdspx/spx output while useless for Go+ Builder
diff.zip
favicon.png
game.zip
index.html
logo.svg
manifest.json
offline.html
service-worker.js

# For now it costs time to build the wasm file, we commit them to simplify the deployment
# TODO: Build wasm files on the fly
!*.wasm
File renamed without changes.
Binary file added spx-gui/public/runner/20241111_1621/gdspx.wasm
Binary file not shown.
Binary file not shown.
13 changes: 13 additions & 0 deletions spx-gui/public/runner/20241111_1621/jszip-3.10.1.min.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
</div>

<script src="godot.editor.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script src="jszip-3.10.1.min.js"></script>
<script src="game.js"></script>
<script>
"use strict";
Expand Down Expand Up @@ -112,6 +112,7 @@
}
await gameApp.StopGame()
}
window.dispatchEvent(new Event('runnerReady'))
</script>
</body>

Expand Down
5 changes: 5 additions & 0 deletions spx-gui/public/runner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Runner Public Files

These files collectively function as the "project runner".

They are expected to be included in the releases of [gdspx](https://github.com/realdream-ai/gdspx) and [spx](https://github.com/goplus/spx/tree/dev). Currently, we manually copy and paste the versioned files from @JiepengTan. TODO: We plan to automate this process in the future.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ const i18n = useI18n()
editorCtx = useEditorCtx()
const loaderConfig = {
// TODO:
// * `cross-origin-resource-policy: cross-origin` for `builder-static.gopluscdn.com`
// * ould not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq
paths: {
vs: 'https://builder-static.gopluscdn.com/libs/monaco-editor/0.45.0/min/vs'
}
Expand Down
42 changes: 19 additions & 23 deletions spx-gui/src/components/editor/preview/EditorPreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,30 @@
<div class="header">
{{ $t({ en: 'Preview', zh: '预览' }) }}
</div>
<UIButton class="run-button" type="primary" icon="play" @click="show = true">
<UIButton class="run-button" type="primary" icon="play" @click="running = true">
{{ $t({ en: 'Run', zh: '运行' }) }}
</UIButton>
</UICardHeader>

<UIFullScreenModal v-model:show="show" class="project-runner-modal">
<RunnerContainer :project="editorCtx.project" @close="show = false" />
</UIFullScreenModal>
<div class="project-runner-modal" :class="{ visible: running }">
<RunnerContainer :project="editorCtx.project" :visible="running" @close="running = false" />
</div>
<div class="stage-viewer-container">
<StageViewer />
</div>
</UICard>
</template>

<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { ref } from 'vue'
import { useEditorCtx } from '@/components/editor/EditorContextProvider.vue'
import { UICard, UICardHeader, UIButton, UIFullScreenModal } from '@/components/ui'
import { UICard, UICardHeader, UIButton } from '@/components/ui'
import StageViewer from './stage-viewer/StageViewer.vue'
import RunnerContainer, { preload as preloadRunner } from './RunnerContainer.vue'
import RunnerContainer from './RunnerContainer.vue'
let show = ref(false)
let running = ref(false)
const editorCtx = useEditorCtx()
onMounted(() => {
preloadRunner()
})
</script>

<style scoped lang="scss">
Expand All @@ -57,17 +53,17 @@ onMounted(() => {
}
.project-runner-modal {
margin-left: 32px;
margin-right: 32px;
height: 80vh;
display: flex;
justify-content: center;
align-items: center;
background: #fff;
border-radius: 20px;
.n-modal-content {
border-radius: 20px;
display: none;
position: fixed;
z-index: 100;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: white;
&.visible {
display: block;
}
padding: 16px;
}
</style>
40 changes: 17 additions & 23 deletions spx-gui/src/components/editor/preview/RunnerContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="header">
<div class="header-left"></div>
<div class="project-name">
{{ project?.name }}
{{ project.name }}
</div>
<div class="header-right">
<UIButton class="button" icon="rotate" @click="handleRerun">
Expand All @@ -19,7 +19,6 @@
<div class="runner-container">
<div class="wrapper" :style="runnerAspectRatio">
<ProjectRunner
v-if="project"
ref="projectRunnerRef"
:project="project"
:style="runnerAspectRatio"
Expand Down Expand Up @@ -47,21 +46,19 @@
</div>
</template>

<script lang="ts">
import ProjectRunner, { preload } from '@/components/project/runner/ProjectRunner.vue'
export { preload }
</script>

<script setup lang="ts">
import { onMounted, ref, type CSSProperties, watch, nextTick } from 'vue'
import { ref, type CSSProperties, watch } from 'vue'
import dayjs from 'dayjs'
import { untilNotNull } from '@/utils/utils'
import { useMessageHandle } from '@/utils/exception'
import type { Project } from '@/models/project'
import { usePublishProject } from '@/components/project'
import { UIButton, UIIcon, UIModalClose } from '@/components/ui'
import { useMessageHandle } from '@/utils/exception'
import { usePublishProject } from '@/components/project'
import ProjectRunner from '@/components/project/runner/ProjectRunner.vue'
const props = defineProps<{
project: Project
visible: boolean
}>()
const emit = defineEmits<{
Expand All @@ -87,18 +84,20 @@ const displayMode = ref<'landscape' | 'portrait'>('landscape')
const expanded = ref(false)
watch(
() => props.project,
async (newProject) => {
const mapSize = newProject.stage.getMapSize()
() => props.visible,
async (visible, _, onCleanup) => {
if (!visible) return
const mapSize = props.project.stage.getMapSize()
runnerAspectRatio.value.aspectRatio = `${mapSize.width}/${mapSize.height}`
displayMode.value = mapSize.width > mapSize.height ? 'landscape' : 'portrait'
consoleMessages.value = []
// Wait for the project to be injected into the component
await nextTick()
handleRerun()
const projectRunner = await untilNotNull(projectRunnerRef)
consoleMessages.value = []
projectRunner.run()
onCleanup(() => {
projectRunner.stop()
})
},
{ immediate: true }
)
Expand All @@ -109,11 +108,6 @@ const handleConsole = (type: 'log' | 'warn', args: any[]) => {
consoleMessages.value.unshift({ id: nextId.value++, time, message, type })
}
onMounted(() => {
if (!projectRunnerRef.value) throw new Error('projectRunnerRef is not ready')
projectRunnerRef.value.run()
})
const handleRerun = () => {
projectRunnerRef.value?.rerun()
consoleMessages.value = []
Expand Down
78 changes: 19 additions & 59 deletions spx-gui/src/components/project/runner/ProjectRunner.vue
Original file line number Diff line number Diff line change
@@ -1,80 +1,40 @@
<template>
<div class="iframe-container">
<IframeDisplay v-if="zipData" :zip-data="zipData" @console="handleConsole" @loaded="loading = false" />
<UIImg v-show="zipData == null || loading" class="thumbnail" :src="thumbnailUrl" :loading="thumbnailUrlLoading" />
<UILoading :visible="loading" cover />
</div>
</template>

<script lang="ts">
import IframeDisplay, { preload } from './IframeDisplay.vue'
export { preload }
</script>

<script lang="ts" setup>
import { onUnmounted, ref } from 'vue'
import { registerPlayer } from '@/utils/player-registry'
import { useFileUrl } from '@/utils/file'
import { Project } from '@/models/project'
import { UIImg, UILoading } from '@/components/ui'
<script setup lang="ts">
import { ref } from 'vue'
import { getSpxVersion, useLocalStorage } from '@/utils/utils'
import type { Project } from '@/models/project'
import ProjectRunnerV1 from './v1/ProjectRunnerV1.vue'
import ProjectRunnerV2 from './v2/ProjectRunnerV2.vue'
const props = defineProps<{ project: Project }>()
const zipData = ref<ArrayBuffer | null>(null)
const loading = ref(false)
const emit = defineEmits<{
console: [type: 'log' | 'warn', args: unknown[]]
}>()
const [thumbnailUrl, thumbnailUrlLoading] = useFileUrl(() => props.project.thumbnail)
const projectRunnerRef = ref<InstanceType<typeof ProjectRunnerV1> | InstanceType<typeof ProjectRunnerV2>>()
const handleConsole = (type: 'log' | 'warn', args: unknown[]) => {
function handleConsole(type: 'log' | 'warn', args: unknown[]) {
emit('console', type, args)
}
const registered = registerPlayer(() => {
// For now we don't need to implement stop handler here because there's no chance for
// the user to activate another audio player when `ProjectRunner` visible.
// If you see this warning in console, you need to think what the proper behavior is.
console.warn('unexpected call')
})
onUnmounted(() => {
registered.onStopped()
})
const version = useLocalStorage('spx-gui-runner', 'v1')
const specifiedVersion = getSpxVersion()
if (specifiedVersion != null) version.value = specifiedVersion
defineExpose({
async run() {
loading.value = true
registered.onStart()
const gbpFile = await props.project.exportGbpFile()
zipData.value = await gbpFile.arrayBuffer()
run() {
projectRunnerRef.value?.run()
},
stop() {
zipData.value = null
registered.onStopped()
projectRunnerRef.value?.stop()
},
rerun() {
this.stop()
return this.run()
projectRunnerRef.value?.rerun()
}
})
</script>
<style scoped lang="scss">
.iframe-container {
position: relative;
aspect-ratio: 4 / 3;
display: flex;
justify-content: center;
align-items: center;
}

.thumbnail {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
</style>
<template>
<ProjectRunnerV2 v-if="version === 'v2'" ref="projectRunnerRef" v-bind="props" @console="handleConsole" />
<ProjectRunnerV1 v-else v-bind="props" ref="projectRunnerRef" @console="handleConsole" />
</template>
80 changes: 80 additions & 0 deletions spx-gui/src/components/project/runner/v1/ProjectRunnerV1.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<template>
<div class="iframe-container">
<IframeDisplay v-if="zipData" :zip-data="zipData" @console="handleConsole" @loaded="loading = false" />
<UIImg v-show="zipData == null || loading" class="thumbnail" :src="thumbnailUrl" :loading="thumbnailUrlLoading" />
<UILoading :visible="loading" cover />
</div>
</template>

<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue'
import { registerPlayer } from '@/utils/player-registry'
import { useFileUrl } from '@/utils/file'
import { Project } from '@/models/project'
import { UIImg, UILoading } from '@/components/ui'
import IframeDisplay, { preload } from './IframeDisplay.vue'
const props = defineProps<{ project: Project }>()
const zipData = ref<ArrayBuffer | null>(null)
const loading = ref(false)
const emit = defineEmits<{
console: [type: 'log' | 'warn', args: unknown[]]
}>()
const [thumbnailUrl, thumbnailUrlLoading] = useFileUrl(() => props.project.thumbnail)
const handleConsole = (type: 'log' | 'warn', args: unknown[]) => {
emit('console', type, args)
}
onMounted(() => {
preload()
})
const registered = registerPlayer(() => {
// For now we don't need to implement stop handler here because there's no chance for
// the user to activate another audio player when `ProjectRunner` visible.
// If you see this warning in console, you need to think what the proper behavior is.
console.warn('unexpected call')
})
onUnmounted(() => {
registered.onStopped()
})
defineExpose({
async run() {
loading.value = true
registered.onStart()
const gbpFile = await props.project.exportGbpFile()
zipData.value = await gbpFile.arrayBuffer()
},
stop() {
zipData.value = null
registered.onStopped()
},
rerun() {
this.stop()
return this.run()
}
})
</script>
<style scoped lang="scss">
.iframe-container {
position: relative;
aspect-ratio: 4 / 3;
display: flex;
justify-content: center;
align-items: center;
}
.thumbnail {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
</style>
Loading

0 comments on commit 95a93a1

Please sign in to comment.