Skip to content

Commit

Permalink
feat(gui):modify to edit project object inside the component and modi…
Browse files Browse the repository at this point in the history
…fy the interface selected of sprite
  • Loading branch information
luoliwoshang committed Feb 21, 2024
1 parent 7efa830 commit 3808b9f
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 134 deletions.
57 changes: 25 additions & 32 deletions spx-gui/src/components/stage-viewer-demo/StageViewerDemo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,14 @@
* @Author: Zhang Zhi Yang
* @Date: 2024-02-05 14:18:34
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-20 16:27:48
* @FilePath: /spx-gui/src/components/stage-viewer-demo/StageViewerDemo.vue
* @LastEditTime: 2024-02-21 18:11:56
* @FilePath: /builder/spx-gui/src/components/stage-viewer-demo/StageViewerDemo.vue
* @Description:
-->
<template>
<div style="display: flex;">
<div>
<input type="file" @change="importFile" accept=".zip">
<p>show in stage viewer</p>
<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>
<div style="display: flex;">
Expand All @@ -27,7 +20,7 @@
:style="sprite.config.costumeIndex === costumeIndex ? { color: 'red' } : {}"
@click="() => sprite.config.costumeIndex = costumeIndex">{{ costume.name }} </button>
</template>
<button @click="currentSprite = sprite"
<button @click="() => { currentSprite = sprite; selectedSpriteNames = [sprite.name] }"
:style="currentSprite?.name === sprite.name ? { color: 'red' } : {}">
{{ sprite.name }}
</button>
Expand Down Expand Up @@ -84,15 +77,15 @@
@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>
<StageViewer @onZorderChange="onZorderChange" @onSpritesDragEnd="onDragEnd" :currentSpriteNames="currentSpriteNames"
<StageViewer @onSelectedSpriteChange="onSelectedSpriteChange" :selectedSpriteNames="selectedSpriteNames"
: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, ZorderChangeEvent } from "../stage-viewer"
import type { StageSprite, SpriteDragEndEvent, StageBackdrop, ZorderChangeEvent, SelectedSpriteChangeEvent } from "../stage-viewer"
import { useProjectStore } from "@/store/modules/project";
import type { Project } from "@/class/project";
import { storeToRefs } from "pinia";
Expand All @@ -102,7 +95,7 @@ const projectStore = useProjectStore();
const { project } = storeToRefs(projectStore);
const currentSprite = ref<Sprite | null>(null);
const currentSpriteNames = ref<string[]>([])
const selectedSpriteNames = ref<string[]>([])
// current sprite config
const x = computed(() => currentSprite.value ? currentSprite.value.config.x : 0)
Expand All @@ -128,20 +121,26 @@ const zorderList = computed(() => {
return project.value.backdrop.config.zorder
})
watch(() => project.value.id, () => {
currentSpriteNames.value = project.value.sprite.list.map(sprite => sprite.name)
})
// watch(() => project.value.id, () => {
// currentSpriteNames.value = project.value.sprite.list.map(sprite => sprite.name)
// })
// accept the new sprite position config when dragend from stage viewer
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)
}
// accept the new zorder configuration from stage viewer
const onZorderChange = (e: ZorderChangeEvent) => {
project.value.backdrop.config.zorder = e.zorder
// 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)
// }
// // accept the new zorder configuration from stage viewer
// const onZorderChange = (e: ZorderChangeEvent) => {
// project.value.backdrop.config.zorder = e.zorder
// }
const onSelectedSpriteChange = (e: SelectedSpriteChangeEvent) => {
selectedSpriteNames.value = e.names
console.log(e.names)
currentSprite.value = project.value.sprite.list.find(sprite => sprite.name === e.names[0]) as Sprite
}
// import file
Expand All @@ -157,13 +156,7 @@ const spriteToTop = (index: number) => {
zorderList.value.push(spriteToMove);
}
// choose the sprite to show in stage
const toggleShowInStage = (name: string) => {
currentSpriteNames.value =
currentSpriteNames.value.includes(name) ?
currentSpriteNames.value.filter(_name => _name !== name)
: [...currentSpriteNames.value, name]
}
// choose the scene to show in stage
// in spx project the first scene will be shown in stage
Expand Down
52 changes: 30 additions & 22 deletions spx-gui/src/components/stage-viewer/Costume.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,50 @@
* @Author: Zhang Zhi Yang
* @Date: 2024-01-25 14:19:57
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-20 14:17:43
* @FilePath: /spx-gui/src/components/stage-viewer/Costume.vue
* @LastEditTime: 2024-02-21 17:26:41
* @FilePath: /builder/spx-gui/src/components/stage-viewer/Costume.vue
* @Description:
-->
<template>
<v-image @dragend="handleDragEnd" :config="{
spriteName:props.spriteConfig.name,
spriteName: props.spriteConfig.name,
image: image,
draggable: true,
x: spritePosition.x,
y: spritePosition.y,
rotation: spriteRotation,
offsetX: props.costumeConfig.x,
offsetY: props.costumeConfig.y,
scaleX: props.spriteConfig.size,
scaleY: props.spriteConfig.size
offsetX: currentCostume.x,
offsetY: currentCostume.y,
scaleX: props.spriteConfig.config.size,
scaleY: props.spriteConfig.config.size
}" />
</template>
<script setup lang="ts">
// ----------Import required packages / components-----------
import { defineProps, onMounted, ref, computed, watchEffect, onUnmounted, watch } from "vue"
import type { StageCostume, StageSprite, MapConfig, SpriteDragEndTarget } from "./index";
import type { ComputedRef } from "vue"
import type { StageCostume, MapConfig, SpriteDragEndTarget } from "./index";
import type { Sprite as SpriteConfig } from "@/class/sprite";
import type { Costume as CostumeConfig } from "@/interface/file";
// ----------props & emit------------------------------------
const props = defineProps<{
spriteConfig: StageSprite,
costumeConfig: StageCostume,
spriteConfig: SpriteConfig,
mapConfig: MapConfig
}>()
// define the emits
const emits = defineEmits<{
// when ths costume dragend,emit the sprite position
(e: 'onDragEnd', event: SpriteDragEndTarget): void
(e: 'onDragEnd', event: { sprite: SpriteConfig }): void
}>()
// ----------computed properties-----------------------------
// computed the current costume with current image
const currentCostume: ComputedRef<CostumeConfig> = computed(() => {
console.log(props.spriteConfig.config.costumes)
console.log(props.spriteConfig.config.costumes[props.spriteConfig.config.costumeIndex])
return props.spriteConfig.config.costumes[props.spriteConfig.config.costumeIndex]
})
// ----------data related -----------------------------------
Expand All @@ -48,21 +55,21 @@ const image = ref<HTMLImageElement>()
// Computed spx's sprite position to konva's relative position by about changing sprite postion
const spritePosition = computed(() => {
return getRelativePosition(
props.spriteConfig.x,
props.spriteConfig.y
props.spriteConfig.config.x,
props.spriteConfig.config.y
);
})
// Computed spx's sprite heading to konva's rotation by about changing sprite heading
const spriteRotation = computed(() => {
return getRotation(props.spriteConfig.heading);
return getRotation(props.spriteConfig.config.heading);
})
watch(() => props.costumeConfig.url, (new_url, old_url) => {
console.log(new_url, old_url)
if (new_url) {
watch(() => currentCostume.value, (new_costume, old_costume) => {
console.log(new_costume, old_costume)
if (new_costume != null) {
const _image = new window.Image();
_image.src = props.costumeConfig.url;
_image.src = props.spriteConfig.files[props.spriteConfig.config.costumeIndex].url as string
_image.onload = () => {
image.value = _image;
console.log(_image.width, _image.height)
Expand Down Expand Up @@ -125,10 +132,11 @@ const getSpxPostion = (x: number, y: number): { x: number; y: number; } => {
* @Date: 2024-01-25 15:44:18
*/
const handleDragEnd = (event: { target: { attrs: { x: number, y: number } } }) => {
const position = getSpxPostion(event.target.attrs.x, event.target.attrs.y)
props.spriteConfig.config.x = position.x
props.spriteConfig.config.y = position.y
emits('onDragEnd', {
sprite: props.spriteConfig,
costume: props.costumeConfig,
position: getSpxPostion(event.target.attrs.x, event.target.attrs.y)
})
}
Expand Down
22 changes: 8 additions & 14 deletions spx-gui/src/components/stage-viewer/Sprite.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,41 @@
* @Author: Zhang Zhi Yang
* @Date: 2024-01-24 15:48:38
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-07 12:14:11
* @FilePath: /spx-gui/src/components/stage-viewer/Sprite.vue
* @LastEditTime: 2024-02-21 17:33:10
* @FilePath: /builder/spx-gui/src/components/stage-viewer/Sprite.vue
* @Description:
-->
<template>
<Costume @onDragEnd="onDragEnd" :spriteConfig="spriteConfig" :costumeConfig="currentCostume" :mapConfig="mapConfig">
<Costume @onDragEnd="onDragEnd" :spriteConfig="spriteConfig" :mapConfig="mapConfig">
</Costume>
</template>
<script lang="ts" setup>
import Costume from "./Costume.vue"
import { defineProps, computed, defineEmits, type ComputedRef } from "vue"
import type { StageSprite, StageCostume, MapConfig, SpriteDragEndTarget } from ".";
import type { Sprite as SpriteConfig } from "@/class/sprite"
// ----------props & emit------------------------------------
const props = defineProps<{
spriteConfig: StageSprite
spriteConfig: SpriteConfig
mapConfig: MapConfig
}>();
// when ths costume dragend,emit the sprite position
const emits = defineEmits<{
(e: 'onDragEnd', event: SpriteDragEndTarget): void
(e: 'onDragEnd', event: { sprite: SpriteConfig }): void
}>()
// ----------computed properties-----------------------------
// computed the current costume with current image
const currentCostume: ComputedRef<StageCostume> = computed(() => {
return props.spriteConfig.costumes[props.spriteConfig.costumeIndex]
})
// ----------methods-----------------------------------------
/**
* @description: function about the costume is dragged
* @param {*} e
* @param {*} y
* @return {*}
* @Author: Zhang Zhi Yang
* @Date: 2024-01-25 15:39:27
*/
const onDragEnd = (e: SpriteDragEndTarget) => {
const onDragEnd = (e: { sprite: SpriteConfig }) => {
emits("onDragEnd", e)
}
</script>
70 changes: 57 additions & 13 deletions spx-gui/src/components/stage-viewer/SpriteLayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* @Author: Zhang Zhi Yang
* @Date: 2024-01-25 16:13:37
* @LastEditors: Zhang Zhi Yang
* @LastEditTime: 2024-02-20 15:04:03
* @FilePath: /spx-gui/src/components/stage-viewer/SpriteLayer.vue
* @LastEditTime: 2024-02-21 17:41:06
* @FilePath: /builder/spx-gui/src/components/stage-viewer/SpriteLayer.vue
* @Description:
-->
<template>
Expand All @@ -12,32 +12,76 @@
x: props.offsetConfig.offsetX,
y: props.offsetConfig.offsetY
}">
<template v-for="sprite in props.sprites" :key="sprite.name">
<Sprite @onDragEnd="onSpriteDragEnd" v-if="isVisibleInStage(sprite)" :mapConfig="props.mapConfig"
:spriteConfig="sprite" />
<template v-for="sprite in sortedSprites" :key="sprite.name">
<Sprite v-if="sprite.config.visible" @onDragEnd="onSpriteDragEnd" :mapConfig="props.mapConfig"
:spriteConfig="sprite" />
</template>
</v-layer>
</template>
<script setup lang="ts">
// ----------Import required packages / components-----------
import type { StageSprite, MapConfig, SpriteDragEndTarget, SpriteDragEndEvent } from ".";
import Sprite from "./Sprite.vue"
import type { Sprite as SpriteConfig } from "@/class/sprite"
import { computed } from "vue";
import type { ComputedRef } from "vue"
const props = defineProps<{
offsetConfig: { offsetX: number, offsetY: number },
mapConfig: MapConfig
sprites: StageSprite[]
currentSpriteNames: string[]
spriteList: SpriteConfig[]
zorder: string[]
}>()
const isVisibleInStage = (sprite: StageSprite) => {
return props.currentSpriteNames.includes(sprite.name) && sprite.visible
}
const sortedSprites = computed(() => {
const spriteMap = new Map<string, SpriteConfig>();
props.spriteList.forEach(sprite => {
spriteMap.set(sprite.name, sprite);
})
const list: SpriteConfig[] = []
props.zorder.forEach(name => {
if (spriteMap.has(name)) {
list.push(spriteMap.get(name) as SpriteConfig);
}
})
return list;
})
// get sprites for stage sort by zorder
const sprites: ComputedRef<StageSprite[]> = computed(() => {
const spriteMap = new Map<string, StageSprite>();
props.spriteList.forEach(sprite => {
const stageSprite: StageSprite = {
name: sprite.name,
x: sprite.config.x,
y: sprite.config.y,
heading: sprite.config.heading,
size: sprite.config.size,
visible: sprite.config.visible,
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,
};
spriteMap.set(sprite.name, stageSprite);
});
const list: StageSprite[] = []
props.zorder.forEach(name => {
if (spriteMap.has(name)) {
list.push(spriteMap.get(name) as StageSprite);
}
})
return list;
})
// ----------methods-----------------------------------------
const emits = defineEmits<{
(e: 'onSpritesDragEnd', value: SpriteDragEndEvent): void
(e: 'onSpritesDragEnd', value: { spriteList: SpriteConfig[] }): void
}>()
/**
Expand All @@ -47,9 +91,9 @@ const emits = defineEmits<{
* @Author: Zhang Zhi Yang
* @Date: 2024-01-25 15:47:53
*/
const onSpriteDragEnd = (e: SpriteDragEndTarget) => {
const onSpriteDragEnd = (e: { sprite: SpriteConfig }) => {
emits('onSpritesDragEnd', {
targets: [e]
spriteList: [e.sprite]
})
}
</script>
Loading

0 comments on commit 3808b9f

Please sign in to comment.