Skip to content

Commit

Permalink
feat(gui):Merge the interface of stage viewer accepting SPX project to
Browse files Browse the repository at this point in the history
  • Loading branch information
luoliwoshang committed Feb 18, 2024
1 parent d12c793 commit d7a4a50
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 67 deletions.
68 changes: 31 additions & 37 deletions spx-gui/src/components/stage-viewer-demo/StageViewerDemo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,30 @@
* @Author: Zhang Zhi Yang
* @Date: 2024-02-05 14:18:34
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-07 16:40:21
* @LastEditTime: 2024-02-18 17:36:46
* @FilePath: /spx-gui/src/components/stage-viewer-demo/StageViewerDemo.vue
* @Description:
-->
<template>
<input type="file" @change="add" accept=".zip">


<div style="display: flex;">
<div style="display: flex;flex-direction: column;">
<div>
<p>show in stage viewer</p>
<template v-for="sprite in sprites" :key="sprite.name">
<button :style="currentSpriteNames.includes(sprite.name) ? { color: 'blue' } : {}"
@click="toggleShowInStage(sprite.name)">
{{ sprite.name }}
</button>
</template>
</div>
<div>
<p>show in stage viewer</p>
<template v-for="sprite in sprites" :key="sprite.name">
<button :style="currentSpriteNames.includes(sprite.name) ? { color: 'blue' } : {}"
@click="toggleShowInStage(sprite.name)">
{{ sprite.name }}
</button>
</template>
<div>
<p>active in stage</p>
<button v-for="sprite in project.sprite.list" :key="sprite.name" @click="currentSprite = sprite"
:style="currentSprite?.name === sprite.name ? { color: 'yellow' } : {}">
{{ sprite.name }}
</button>
</div>
</div>
<div style="display: flex;flex-direction: column;">
<p>sprite position</p>
<n-input-number type="number" :value="x"
@update:value="(val) => { currentSprite && currentSprite.setSx(val as number) }"></n-input-number>
Expand All @@ -46,19 +44,17 @@
@update:value="(val) => { currentSprite && currentSprite.setCy(val as number) }"></n-input-number>
<n-switch v-model:value="visible" @update:value="(val) => { currentSprite && currentSprite.setVisible(val) }" />
</div>
<div style="width:400px;height:400px;">
<StageViewer :id="projectId" @onSpritesDragEnd="onDragEnd" :backdrop="backdrop" :sprites="sprites"
:currentSpriteNames="currentSpriteNames" />
</div>
<StageViewer @onSpritesDragEnd="onDragEnd" :currentSpriteNames="currentSpriteNames" :project="(project as Project)" />
</div>
</template>
<script setup lang="ts">
import { NInputNumber, NSwitch } from "naive-ui";
import type { Sprite } from "@/class/sprite";
import StageViewer from "../stage-viewer";
import type { StageSprite, SpriteDragEndEvent, StageBackdrop } from "../stage-viewer"
import { useProjectStore } from "@/store/modules/project";
import type { Project } from "@/store/modules/project";
import { storeToRefs } from "pinia";
import { ref, computed, watch } from "vue";
import type { ComputedRef } from "vue";
Expand All @@ -67,8 +63,6 @@ const { project } = storeToRefs(projectStore);
const add = async (e: any) => {
await projectStore.loadProject(e.target.files[0], e.target.files[0].name.split(".")[0]);
}
const x = computed(() => currentSprite.value ? currentSprite.value.config.x : 0)
const y = computed(() => currentSprite.value ? currentSprite.value.config.y : 0)
const heading = computed(() => currentSprite.value ? currentSprite.value.config.heading : 0)
Expand All @@ -78,8 +72,13 @@ const costumeX = computed(() => currentSprite.value ? currentSprite.value.config
const costumeY = computed(() => currentSprite.value ? currentSprite.value.config.costumes[currentSprite.value.config.costumeIndex].y : 0)
// TODO: Temporarily use title of project as id
const projectId = computed(() => project.value.title)
const toggleShowInStage = (name: string) => {
currentSpriteNames.value =
currentSpriteNames.value.includes(name) ?
currentSpriteNames.value.filter(_name => _name !== name)
: [...currentSpriteNames.value, name]
}
const currentSprite = ref<Sprite | null>(null);
Expand Down Expand Up @@ -111,12 +110,7 @@ const sprites: ComputedRef<StageSprite[]> = computed(() => {
return list as StageSprite[];
})
const toggleShowInStage = (name: string) => {
currentSpriteNames.value =
currentSpriteNames.value.includes(name) ?
currentSpriteNames.value.filter(_name => _name !== name)
: [...currentSpriteNames.value, name]
}
// TODO: Temporarily use title of project as id
watch(() => project.value.title, () => {
Expand All @@ -130,16 +124,16 @@ const onDragEnd = (e: SpriteDragEndEvent) => {
currentSprite.value?.setSy(e.targets[0].position.y)
}
const backdrop: ComputedRef<StageBackdrop> = computed(() => {
// const backdrop: ComputedRef<StageBackdrop> = computed(() => {
return {
scenes: project.value.backdrop.config.scenes.map((scene, index) => ({
name: scene.name as string,
url: project.value.backdrop.files[index].url as string
})),
sceneIndex: project.value.backdrop.currentSceneIndex
}
})
// return {
// scenes: project.value.backdrop.config.scenes.map((scene, index) => ({
// name: scene.name as string,
// url: project.value.backdrop.files[index].url as string
// })),
// sceneIndex: project.value.backdrop.currentSceneIndex
// }
// })
Expand Down
96 changes: 71 additions & 25 deletions spx-gui/src/components/stage-viewer/StageViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: Zhang Zhi Yang
* @Date: 2024-02-05 14:09:40
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-07 17:15:13
* @LastEditTime: 2024-02-18 17:37:59
* @FilePath: /spx-gui/src/components/stage-viewer/StageViewer.vue
* @Description:
-->
Expand All @@ -14,22 +14,21 @@
scaleX: scale,
scaleY: scale,
}">
<BackdropLayer @onSceneLoadend="onSceneLoadend" :loading="loading" :backdropConfig="props.backdrop"
:offsetConfig="{
offsetX: (props.width / scale - spxMapConfig.width) / 2,
offsetY: (props.height / scale - spxMapConfig.height) / 2,
}" :mapConfig="spxMapConfig" />
<BackdropLayer @onSceneLoadend="onSceneLoadend" :loading="loading" :backdropConfig="backdrop" :offsetConfig="{
offsetX: (props.width / scale - spxMapConfig.width) / 2,
offsetY: (props.height / scale - spxMapConfig.height) / 2,
}" :mapConfig="spxMapConfig" />
<SpriteLayer :loading="loading" @onSpritesDragEnd="onSpritesDragEnd" :offsetConfig="{
offsetX: (props.width / scale - spxMapConfig.width) / 2,
offsetY: (props.height / scale - spxMapConfig.height) / 2
}" :sprites="props.sprites" :mapConfig="spxMapConfig" :currentSpriteNames="props.currentSpriteNames" />
}" :sprites="sprites" :mapConfig="spxMapConfig" :currentSpriteNames="props.currentSpriteNames" />
</v-stage>
</div>
</template>
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch, withDefaults, watchEffect } from 'vue';
import type { ComputedRef } from 'vue';
import type { StageViewerEmits, StageViewerProps, MapConfig, SpriteDragEndEvent } from './index';
import type { StageViewerEmits, StageViewerProps, MapConfig, SpriteDragEndEvent, StageBackdrop, StageSprite } from './index';
import SpriteLayer from './SpriteLayer.vue';
import BackdropLayer from './BackdropLayer.vue';
// ----------props & emit------------------------------------
Expand Down Expand Up @@ -59,20 +58,73 @@ const spxMapConfig = ref<MapConfig>({
height: 400
});
watch(() => props.id, () => {
loading.value = true;
checkProps();
})
watchEffect(() => {
// when the stage size is determined by mapConfig,There is no need for the background layer to complete loading
if (props.mapConfig) {
console.log(props.mapConfig)
spxMapConfig.value = props.mapConfig
loading.value = false
watch(() => props.project, (new_project, old_project) => {
console.log(new_project, old_project)
// TODO: temperary use project's title to determine whether to reload
if (new_project.title !== old_project.title) {
loading.value = true;
// witch project have map config,this will confirm the stage size
// When there is no map, it does not end the loading and waits for the background layer to send new loaded content
if (new_project.backdrop.config.map) {
spxMapConfig.value = new_project.backdrop.config.map;
loading.value = false
}
// If there is no map, but there is a backdrop scene or backdrop costume, it will end the loading and wait for the sprite layer to send new loaded content
else if ((!new_project.backdrop.config.scenes || new_project.backdrop.config.scenes.length === 0) && (!new_project.backdrop.config.costumes || new_project.backdrop.config.costumes.length === 0)) {
console.error("Project missing backdrop configuration or map size configuration");
loading.value = false
}
}
}, {
deep: true
})
const backdrop = computed(() => {
const { files, config } = props.project.backdrop;
console.log(files, config)
return props.project.backdrop.config.map ? null : {
scenes: config.scenes?.map((scene, index) => ({
name: scene.name as string,
url: files[index].url as string
})) || [],
costumes: config.costumes?.map((costume, index) => ({
name: costume.name as string,
url: files[index].url as string,
x: costume.x || 0,
y: costume.y || 0
})) || [],
currentCostumeIndex: config.currentCostumeIndex || 0
} as StageBackdrop
})
const sprites: ComputedRef<StageSprite[]> = computed(() => {
const list = props.project.sprite.list.map(sprite => {
return {
name: sprite.name,
x: sprite.config.x,
y: sprite.config.y,
heading: sprite.config.heading,
size: sprite.config.size,
visible: sprite.config.visible, // Visible at run time
zorder: 1,
costumes: sprite.config.costumes.map((costume, index) => {
console.log(costume)
return {
name: costume.name as string,
url: sprite.files[index].url as string,
x: costume.x,
y: costume.y,
}
}),
costumeIndex: sprite.config.costumeIndex,
}
})
console.log(list)
return list as StageSprite[];
})
// When config is not configured, its stage size is determined by the first loaded background image
const onSceneLoadend = (event: { imageEl: HTMLImageElement }) => {
Expand All @@ -86,12 +138,6 @@ const onSceneLoadend = (event: { imageEl: HTMLImageElement }) => {
}
};
const checkProps = () => {
if (!props.mapConfig && !props.backdrop) {
console.error("Mapconfig and backdrop must choose one");
}
}
const onSpritesDragEnd = (e: SpriteDragEndEvent) => {
emits("onSpritesDragEnd", e)
}
Expand All @@ -101,6 +147,6 @@ const onSpritesDragEnd = (e: SpriteDragEndEvent) => {
<style scoped>
#stage-viewer {
height: v-bind("props.height + 'px'");
width: v-bind("props.width+ 'px'");
width: v-bind("props.width + 'px'");
}
</style>
9 changes: 4 additions & 5 deletions spx-gui/src/components/stage-viewer/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import StageViewer from "./StageViewer.vue"
import { Project } from "@/store"
export default StageViewer
/**
* @description: The Stage Position,Relative to the stage center
Expand Down Expand Up @@ -44,7 +45,8 @@ export interface StageScene {
*/
export interface StageBackdrop {
scenes: StageScene[]
sceneIndex: number
costumes: StageCostume[]
currentCostumeIndex: number
}
/**
* @description: Map Config,some spx project havent this config,the stage size will depend on the SceneSize
Expand All @@ -65,12 +67,9 @@ export interface MapConfig {
* @Date: 2024-02-02 17:18:49
*/
export interface StageViewerProps {
id: string
project: Project
height?: number // container height
width?: number // container width
mapConfig?: MapConfig // some spx project havent this config,the stage size will depend on the SceneSize
sprites: StageSprite[] // sprite list
backdrop?: StageBackdrop // backdrop
currentSpriteNames: string[]
}

Expand Down

0 comments on commit d7a4a50

Please sign in to comment.