1
0
forked from noxious/client

Sprite editor changes

This commit is contained in:
Dennis Postma 2025-03-21 01:57:37 +01:00
parent 32ca61cc50
commit ba3ed8c099
4 changed files with 45 additions and 75 deletions

View File

@ -17,20 +17,24 @@
<button class="btn-cyan px-4" type="button" @click.prevent="addNewImage">New action</button> <button class="btn-cyan px-4" type="button" @click.prevent="addNewImage">New action</button>
</div> </div>
</div> </div>
<Accordion v-for="action in spriteActions" :key="action.id"> <div v-for="action in spriteActions" :key="action.id">
<template #header> <div class="flex flex-wrap gap-3 mb-3">
<div class="flex items-center"> <div v-for="(image, index) in action.sprites" :key="index" class="h-20 w-20 p-4 bg-gray-300 bg-opacity-50 rounded text-center relative group">
{{ action.action }} <img :src="image.url" class="max-w-full max-h-full object-contain pointer-events-none" alt="Uploaded image" @load="updateImageDimensions($event, index)" />
<div class="ml-auto space-x-2"> <div v-if="imageDimensions[index]" class="absolute bottom-1 right-1 bg-black/50 text-white text-xs px-1 py-0.5 rounded transition-opacity font-default">{{ imageDimensions[index].width }}x{{ imageDimensions[index].height }}</div>
<button class="btn-cyan px-4 py-1.5 min-w-24" type="button" @click.stop.prevent="openEditorModal(action)">Editor</button> </div>
<button class="btn-red px-4 py-1.5 min-w-24" type="button" @click.stop.prevent="() => spriteActions.splice(spriteActions.indexOf(action), 1)">Delete</button> </div>
<div class="flex items-center mb-3 hidden">
<div class="mr-3 space-x-2">
<button class="btn-cyan px-4 py-1.5 min-w-24 text-left" type="button" @click.stop.prevent="openEditorModal(action)">
Editor
<div class="flex">
<small class="text-xs font-default">{{ action.action }}</small>
</div>
</button>
</div> </div>
</div> </div>
</template> </div>
<template #content>
<SpriteImagesPreview :spriteActionImages="action.sprites" @tempOffsetChange="(index, offset) => handleTempOffsetChange(action, index, offset)" />
</template>
</Accordion>
<SpriteEditor <SpriteEditor
v-for="[actionId, editorData] in Array.from(openEditors.entries())" v-for="[actionId, editorData] in Array.from(openEditors.entries())"
:key="actionId" :key="actionId"
@ -52,8 +56,6 @@ import { SocketEvent } from '@/application/enums'
import type { Sprite, SpriteAction } from '@/application/types' import type { Sprite, SpriteAction } from '@/application/types'
import { downloadCache, uuidv4 } from '@/application/utilities' import { downloadCache, uuidv4 } from '@/application/utilities'
import SpriteEditor from '@/components/gameMaster/assetManager/partials/sprite/partials/SpriteEditor.vue' import SpriteEditor from '@/components/gameMaster/assetManager/partials/sprite/partials/SpriteEditor.vue'
import SpriteImagesPreview from '@/components/gameMaster/assetManager/partials/sprite/partials/SpriteImagesPreview.vue'
import Accordion from '@/components/utilities/Accordion.vue'
import { socketManager } from '@/managers/SocketManager' import { socketManager } from '@/managers/SocketManager'
import { SpriteStorage } from '@/storage/storages' import { SpriteStorage } from '@/storage/storages'
import { useAssetManagerStore } from '@/stores/assetManagerStore' import { useAssetManagerStore } from '@/stores/assetManagerStore'
@ -210,6 +212,24 @@ watch(selectedSprite, (sprite: Sprite | null) => {
openEditors.value = new Map() openEditors.value = new Map()
}) })
interface SpriteImage {
url: string
offset: {
x: number
y: number
}
}
const imageDimensions = ref<{ [key: number]: { width: number; height: number } }>({})
const updateImageDimensions = (event: Event, index: number) => {
const img = event.target as HTMLImageElement
imageDimensions.value[index] = {
width: img.naturalWidth,
height: img.naturalHeight
}
}
onMounted(() => { onMounted(() => {
if (!selectedSprite.value) return if (!selectedSprite.value) return
}) })

View File

@ -32,8 +32,13 @@
</div> </div>
<div class="mt-6"> <div class="mt-6">
<form class="flex gap-2.5 flex-wrap" @submit.prevent=""> <form class="flex gap-2.5 flex-wrap" @submit.prevent="">
<div class="relative flex py-5 items-center">
<div class="flex-grow border-t border-gray-400"></div>
<span class="flex-shrink mx-4 text-gray-400">Sprite action</span>
<div class="flex-grow border-solid border-gray-200"></div>
</div>
<div class="form-field-full"> <div class="form-field-full">
<label for="action">Action</label> <label for="action">Name</label>
<input class="input-field" type="text" name="action" placeholder="Action" /> <input class="input-field" type="text" name="action" placeholder="Action" />
</div> </div>
<div class="form-field-half"> <div class="form-field-half">
@ -44,6 +49,11 @@
<label for="origin-y">Origin Y</label> <label for="origin-y">Origin Y</label>
<input class="input-field" type="number" step="any" name="origin-y" placeholder="Origin Y" /> <input class="input-field" type="number" step="any" name="origin-y" placeholder="Origin Y" />
</div> </div>
<div class="relative flex py-5 items-center">
<div class="flex-grow border-t border-gray-400"></div>
<span class="flex-shrink mx-4 text-gray-400">Sprite action image</span>
<div class="flex-grow border-t border-gray-400"></div>
</div>
<div class="form-field-half"> <div class="form-field-half">
<label for="offset-x">Offset X</label> <label for="offset-x">Offset X</label>
<input class="input-field" type="number" step="1" :value="currentSprite?.offset?.x || 0" @input="updateOffset($event, 'x')" :disabled="isAnimating" /> <input class="input-field" type="number" step="1" :value="currentSprite?.offset?.x || 0" @input="updateOffset($event, 'x')" :disabled="isAnimating" />

View File

@ -1,38 +0,0 @@
<template>
<div class="flex flex-wrap gap-3">
<div v-for="(image, index) in spriteActionImages" :key="index" class="h-20 w-20 p-4 bg-gray-300 bg-opacity-50 rounded text-center relative group">
<img :src="image.url" class="max-w-full max-h-full object-contain pointer-events-none" alt="Uploaded image" @load="updateImageDimensions($event, index)" />
<div v-if="imageDimensions[index]" class="absolute bottom-1 right-1 bg-black/50 text-white text-xs px-1 py-0.5 rounded transition-opacity font-default">{{ imageDimensions[index].width }}x{{ imageDimensions[index].height }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
interface SpriteImage {
url: string
offset: {
x: number
y: number
}
}
interface Props {
spriteActionImages: SpriteImage[]
}
const props = withDefaults(defineProps<Props>(), {
spriteActionImages: () => []
})
const imageDimensions = ref<{ [key: number]: { width: number; height: number } }>({})
const updateImageDimensions = (event: Event, index: number) => {
const img = event.target as HTMLImageElement
imageDimensions.value[index] = {
width: img.naturalWidth,
height: img.naturalHeight
}
}
</script>

View File

@ -1,22 +0,0 @@
<template>
<div class="mb-4 flex flex-col gap-3">
<div @click="toggle" class="p-3 bg-gray-300 bg-opacity-50 rounded hover:bg-gray-400 text-white font-default cursor-pointer">
<slot name="header" />
</div>
<transition enter-active-class="transition-all duration-300 ease-in-out" leave-active-class="transition-all duration-300 ease-in-out" enter-from-class="opacity-0 max-h-0" enter-to-class="opacity-100 max-h-96" leave-from-class="opacity-100 max-h-96" leave-to-class="opacity-0 max-h-0">
<div v-if="isOpen" class="overflow-hidden">
<slot name="content" />
</div>
</transition>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const isOpen = ref(false)
const toggle = () => {
isOpen.value = !isOpen.value
}
</script>