Skip to content

Commit

Permalink
feat(gui):update sprite costume toggle in stage viewer demo
Browse files Browse the repository at this point in the history
  • Loading branch information
luoliwoshang committed Feb 19, 2024
1 parent 871e8ba commit b4630d3
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 78 deletions.
10 changes: 7 additions & 3 deletions spx-gui/src/class/asset-base.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/*
* @Author: TuGitee [email protected]
* @Date: 2024-01-22 10:28:03
* @LastEditors: xuning [email protected]
* @LastEditTime: 2024-02-06 12:53:58
* @FilePath: \builder\spx-gui\src\class\asset-base.ts
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-19 11:58:52
* @FilePath: /spx-gui/src/class/asset-base.ts
* @Description: The abstract class of an asset.
*/
import type { AssetBaseInterface } from "@/interface/file";
Expand Down Expand Up @@ -35,6 +35,10 @@ export abstract class AssetBase implements AssetBaseInterface {
get files(): FileWithUrl[] {
return this._files
}

set files(files: FileWithUrl[]){
this._files = files;
}

/**
* Add file to Asset.
Expand Down
112 changes: 65 additions & 47 deletions spx-gui/src/components/stage-viewer-demo/StageViewerDemo.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:18:34
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-18 17:36:46
* @LastEditTime: 2024-02-19 14:53:44
* @FilePath: /spx-gui/src/components/stage-viewer-demo/StageViewerDemo.vue
* @Description:
-->
Expand All @@ -11,18 +11,49 @@
<div>
<input type="file" @change="add" accept=".zip">
<p>show in stage viewer</p>
<template v-for="sprite in sprites" :key="sprite.name">
<template v-for="sprite in project.sprite.list" :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 style="display: flex;">
<div style="display: flex;flex-direction: column;justify-content: flex-end;"
v-for="sprite in project.sprite.list" :key="sprite.name">
<template v-if="currentSprite?.name === sprite.name">
<button v-for="(costume, costumeIndex) in sprite.config.costumes" :key="costume.name"
:style="sprite.config.costumeIndex === costumeIndex ? { color: 'red' } : {}"
@click="() => sprite.config.costumeIndex = costumeIndex">{{ costume.name }} </button>
</template>
<button @click="currentSprite = sprite"
:style="currentSprite?.name === sprite.name ? { color: 'red' } : {}">
{{ sprite.name }}
</button>
</div>
</div>
</div>
<div>
<h4>backdrop</h4>
<div v-if="backdropConfig.scenes.length > 0">
<p>scene</p>
<!-- in the scene config,the first scene determine the stage size -->
<button v-for="(scene, index) in backdropConfig.scenes" :key="scene.name"
:style="index === 0 ? { color: 'blue' } : {}" @click="() => moveToTopScene(index)">
{{ scene.name }}
</button>
</div>
<div v-if="backdropConfig.costumes.length > 0">
<p>costume</p>
<button v-for="(costume, index) in backdropConfig.costumes" :key="costume.name"
:style="index === backdropConfig.currentCostumeIndex ? { color: 'blue' } : {}"
@click="() => backdropConfig.currentCostumeIndex = index">
{{ costume.name }}
</button>
</div>
</div>
</div>
<div style="display: flex;flex-direction: column;">
Expand Down Expand Up @@ -55,6 +86,7 @@ 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 type { Scene } from "@/interface/file"
import { storeToRefs } from "pinia";
import { ref, computed, watch } from "vue";
Expand All @@ -80,61 +112,47 @@ const toggleShowInStage = (name: string) => {
: [...currentSpriteNames.value, name]
}
const currentSprite = ref<Sprite | null>(null);
const currentSpriteNames = ref<string[]>([])
const sprites: ComputedRef<StageSprite[]> = computed(() => {
const list = project.value.sprite.list.map(sprite => {
console.log(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) => {
return {
name: costume.name as string,
url: sprite.files[index].url as string,
x: costume.x,
y: costume.y,
}
}),
costumeIndex: sprite.config.costumeIndex,
}
})
return list as StageSprite[];
})
// TODO: Temporarily use title of project as id
watch(() => project.value.title, () => {
currentSpriteNames.value = sprites.value.map(sprite => sprite.name)
currentSpriteNames.value = project.value.sprite.list.map(sprite => sprite.name)
})
const onDragEnd = (e: SpriteDragEndEvent) => {
currentSprite.value = project.value.sprite.list.find(sprite => sprite.name === e.targets[0].sprite.name) as Sprite
currentSprite.value?.setSx(e.targets[0].position.x)
currentSprite.value?.setSy(e.targets[0].position.y)
}
// 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
// }
// })
const backdropConfig = computed(() => {
return {
scenes: project.value.backdrop.config?.scenes || [],
costumes: project.value.backdrop.config.costumes || [],
currentCostumeIndex: project.value.backdrop.config.currentCostumeIndex
}
})
console.log(backdropConfig)
// set scene to top
const moveToTopScene = (index: number) => {
if (project.value.backdrop.config.scenes) {
const scenes = [...project.value.backdrop.config.scenes]
const item = scenes.splice(index, 1)[0]
scenes.unshift(item)
project.value.backdrop.config.scenes = scenes
const files = project.value.backdrop.files
if (files) {
const items = [...files]
const item = items.splice(index, 1)[0]
items.unshift(item)
project.value.backdrop.files = items
}
}
}
Expand Down
26 changes: 13 additions & 13 deletions spx-gui/src/components/stage-viewer/BackdropLayer.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 16:33:54
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-18 15:58:57
* @LastEditTime: 2024-02-19 17:06:05
* @FilePath: /spx-gui/src/components/stage-viewer/BackdropLayer.vue
* @Description
-->
Expand All @@ -11,7 +11,14 @@
x: props.offsetConfig.offsetX,
y: props.offsetConfig.offsetY,
}">
<v-rect :config="{
width: props.mapConfig.width,
height: props.mapConfig.height,
stroke: 'pink',
strokeWidth: 1,
}">

</v-rect>
<v-line :config="{
points: [props.mapConfig.width / 2, 0, props.mapConfig.width / 2, props.mapConfig.height],
stroke: 'pink',
Expand Down Expand Up @@ -49,23 +56,16 @@ const image = ref<HTMLImageElement>()
watch(() => props.backdropConfig, (new_config, old_config) => {
if (new_config) {
// In the scene config‘s project, you only need to get the first scene as the backdrop
const _image = new window.Image();
if (new_config.scenes.length != 0) {
const _image = new window.Image();
_image.src = new_config.scenes[0].url
_image.onload = () => {
image.value = _image;
emits('onSceneLoadend', { imageEl: _image })
};
} else if (new_config.costumes.length != 0) {
console.log(new_config)
const _image = new window.Image();
_image.src = new_config.costumes[new_config.currentCostumeIndex].url
console.log(_image)
_image.onload = () => {
image.value = _image;
emits('onSceneLoadend', { imageEl: _image })
};
}
_image.onload = () => {
image.value = _image;
emits('onSceneLoadend', { imageEl: _image })
};
}
else {
image.value?.remove();
Expand Down
5 changes: 2 additions & 3 deletions spx-gui/src/components/stage-viewer/SpriteLayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: Zhang Zhi Yang
* @Date: 2024-01-25 16:13:37
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-07 16:40:01
* @LastEditTime: 2024-02-19 17:09:00
* @FilePath: /spx-gui/src/components/stage-viewer/SpriteLayer.vue
* @Description:
-->
Expand All @@ -11,7 +11,7 @@
x: props.offsetConfig.offsetX,
y: props.offsetConfig.offsetY
}">
<template v-if="!props.loading">
<template >
<template v-for="sprite in props.sprites">
<Sprite @onDragEnd="onSpriteDragEnd" v-if="isVisibleInStage(sprite)" :mapConfig="props.mapConfig"
:key="sprite.name" :spriteConfig="sprite" />
Expand All @@ -26,7 +26,6 @@ import Sprite from "./Sprite.vue"
import { computed } from "vue";
const props = defineProps<{
loading: boolean,
offsetConfig: { offsetX: number, offsetY: number },
mapConfig: MapConfig
sprites: StageSprite[]
Expand Down
17 changes: 5 additions & 12 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-18 17:37:59
* @LastEditTime: 2024-02-19 17:10:29
* @FilePath: /spx-gui/src/components/stage-viewer/StageViewer.vue
* @Description:
-->
Expand All @@ -14,11 +14,11 @@
scaleX: scale,
scaleY: scale,
}">
<BackdropLayer @onSceneLoadend="onSceneLoadend" :loading="loading" :backdropConfig="backdrop" :offsetConfig="{
<BackdropLayer @onSceneLoadend="onSceneLoadend" :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="{
<SpriteLayer @onSpritesDragEnd="onSpritesDragEnd" :offsetConfig="{
offsetX: (props.width / scale - spxMapConfig.width) / 2,
offsetY: (props.height / scale - spxMapConfig.height) / 2
}" :sprites="sprites" :mapConfig="spxMapConfig" :currentSpriteNames="props.currentSpriteNames" />
Expand All @@ -37,7 +37,6 @@ const props = withDefaults(defineProps<StageViewerProps>(), {
width: 400// container width
});
const emits = defineEmits<StageViewerEmits>();
const loading = ref(true);
// get the scale of stage viewer
const scale = computed(() => {
Expand All @@ -58,23 +57,18 @@ const spxMapConfig = ref<MapConfig>({
height: 400
});
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
}
}
}, {
Expand Down Expand Up @@ -122,19 +116,18 @@ const sprites: ComputedRef<StageSprite[]> = computed(() => {
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 }) => {
if (loading.value) {
if (!props.project.backdrop.config.map) {
const { imageEl } = event;
spxMapConfig.value = {
width: imageEl.width,
height: imageEl.height
};
loading.value = false;
// loading.value = false;
}
};
Expand Down

0 comments on commit b4630d3

Please sign in to comment.