1
0
forked from noxious/client

Sprite gen. work

This commit is contained in:
2025-03-24 15:15:16 +01:00
parent 27c775821a
commit 5392093d71
3 changed files with 196 additions and 138 deletions

View File

@ -36,16 +36,17 @@
</div>
</div>
<SpriteEditor
v-for="[actionId, editorData] in Array.from(openEditors.entries())"
:key="actionId"
:sprite="selectedSprite!"
:sprites="editorData.action.sprites"
:frame-rate="editorData.action.frameRate"
:is-modal-open="editorData.isOpen"
:temp-offset-index="getTempOffsetIndex(editorData.action)"
:temp-offset="getTempOffset(editorData.action)"
@update:frame-rate="(value) => updateFrameRate(editorData.action, value)"
@update:is-modal-open="(value) => handleEditorModalClose(editorData.action, value)"
v-for="[actionId, editorData] in Array.from(openEditors.entries())"
:key="actionId"
:sprite="selectedSprite!"
:sprites="editorData.action.sprites"
:frame-rate="editorData.action.frameRate"
:is-modal-open="editorData.isOpen"
:temp-offset-index="getTempOffsetIndex(editorData.action)"
:temp-offset="getTempOffset(editorData.action)"
@update:frame-rate="(value) => updateFrameRate(editorData.action, value)"
@update:is-modal-open="(value) => handleEditorModalClose(editorData.action, value)"
@update:temp-offset="(index, offset) => handleTempOffsetChange(editorData.action, index, offset)"
/>
</div>
</div>
@ -123,17 +124,17 @@ async function saveSprite() {
id: selectedSprite.value.id,
name: spriteName.value,
spriteActions:
spriteActions.value?.map((action) => {
return {
action: action.action,
sprites: action.sprites,
originX: action.originX,
originY: action.originY,
frameRate: action.frameRate,
frameWidth: action.frameWidth,
frameHeight: action.frameHeight
}
}) ?? []
spriteActions.value?.map((action) => {
return {
action: action.action,
sprites: action.sprites,
originX: action.originX,
originY: action.originY,
frameRate: action.frameRate,
frameWidth: action.frameWidth,
frameHeight: action.frameHeight
}
}) ?? []
}
socketManager.emit(SocketEvent.GM_SPRITE_UPDATE, updatedSprite, async (response: boolean) => {
@ -181,6 +182,7 @@ function openEditorModal(action: SpriteAction) {
}
function updateFrameRate(action: SpriteAction, value: number) {
console.log('update frame rate', action)
action.frameRate = value
}
@ -192,9 +194,15 @@ function handleEditorModalClose(action: SpriteAction, isOpen: boolean) {
}
function handleTempOffsetChange(action: SpriteAction, index: number, offset: { x: number; y: number }) {
// Update the temporary offset data for this action
const newTempOffsetData = new Map(tempOffsetData.value)
newTempOffsetData.set(action.id, { index, offset })
tempOffsetData.value = newTempOffsetData
// Also update the actual sprite data so changes persist
if (action.sprites && action.sprites[index]) {
action.sprites[index].offset = { ...offset };
}
}
function getTempOffsetIndex(action: SpriteAction): number | undefined {
@ -210,6 +218,7 @@ watch(selectedSprite, (sprite: Sprite | null) => {
spriteName.value = sprite.name
spriteActions.value = sortSpriteActions(sprite.spriteActions)
openEditors.value = new Map()
tempOffsetData.value = new Map() // Reset temp offset data when sprite changes
})
interface SpriteImage {
@ -237,4 +246,4 @@ onMounted(() => {
onBeforeUnmount(() => {
assetManagerStore.setSelectedSprite(null)
})
</script>
</script>

View File

@ -56,11 +56,11 @@
</div>
<div class="form-field-half">
<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" v-model.number="offsetXModel" :disabled="isAnimating" />
</div>
<div class="form-field-half">
<label for="offset-y">Offset Y</label>
<input class="input-field" type="number" step="1" :value="currentSprite?.offset?.y || 0" @input="updateOffset($event, 'y')" :disabled="isAnimating" />
<input class="input-field" type="number" step="1" v-model.number="offsetYModel" :disabled="isAnimating" />
</div>
<div class="form-field-full">
<label for="frame-speed">Frame rate</label>
@ -74,12 +74,12 @@
<div class="bg-gray-800 border-solid border-white/10 rounded flex-grow mb-2 relative overflow-hidden" @mousedown="startDrag" @mousemove="onDrag" @mouseup="stopDrag" @mouseleave="stopDrag">
<!-- Background reference sprites (semi-transparent) -->
<img
v-for="(sprite, index) in spritesWithTempOffset"
:key="`bg-${index}`"
:src="sprite.url"
alt="Reference sprite"
v-show="index !== currentFrame && showReferenceSprites"
:style="{
v-for="(sprite, index) in spritesWithTempOffset"
:key="`bg-${index}`"
:src="sprite.url"
alt="Reference sprite"
v-show="index !== currentFrame && showReferenceSprites"
:style="{
position: 'absolute',
left: `${(sprite.offset?.x || 0) * (zoomLevel / 100)}px`,
bottom: `${(sprite.offset?.y || 0) * (zoomLevel / 100)}px`,
@ -91,29 +91,32 @@
/>
<!-- Current sprite (draggable) -->
<img
v-for="(sprite, index) in spritesWithTempOffset"
:key="index"
:src="sprite.url"
alt="Sprite"
:class="{ 'cursor-move': currentFrame === index }"
:style="{
v-for="(sprite, index) in spritesWithTempOffset"
:key="index"
:src="sprite.url"
alt="Sprite"
:class="{ 'cursor-move': currentFrame === index }"
:style="{
position: 'absolute',
left: `${(sprite.offset?.x || 0) * (zoomLevel / 100)}px`,
bottom: `${(sprite.offset?.y || 0) * (zoomLevel / 100)}px`,
display: currentFrame === index ? 'block' : 'none',
transform: `scale(${zoomLevel / 100})`,
transformOrigin: 'bottom left'
transformOrigin: 'bottom left',
userSelect: 'none',
pointerEvents: currentFrame === index ? 'auto' : 'none'
}"
@dragstart.prevent
/>
</div>
<div class="bg-gray-800 p-2 overflow-x-auto border-solid border-white/10 rounded mb-8 h-24 min-h-16">
<div class="flex gap-2">
<div
v-for="(sprite, index) in sprites"
:key="`thumb-${index}`"
class="relative cursor-pointer border-solid transition-all duration-200 rounded flex-shrink-0 p-3 px-12"
:class="currentFrame === index ? 'border-cyan-600 bg-cyan-500/10' : 'border-transparent hover:border-white/30'"
@click="selectFrame(index)"
v-for="(sprite, index) in sprites"
:key="`thumb-${index}`"
class="relative cursor-pointer border-solid transition-all duration-200 rounded flex-shrink-0 p-3 px-12"
:class="currentFrame === index ? 'border-cyan-600 bg-cyan-500/10' : 'border-transparent hover:border-white/30'"
@click="selectFrame(index)"
>
<img :src="sprite.url" alt="Sprite thumbnail" class="h-16 w-auto object-contain rounded" />
<div class="absolute top-0 right-0 bg-gray-400 text-white text-xs font-default px-1 rounded-bl">
@ -178,6 +181,31 @@ const currentSprite = computed(() => {
return null
})
// Create computed properties with getters and setters for two-way binding
const offsetXModel = computed({
get: () => currentSprite.value?.offset?.x || 0,
set: (value) => {
if (isAnimating.value) return
const newOffset = {
x: value,
y: currentSprite.value?.offset?.y || 0
}
emit('update:tempOffset', currentFrame.value, newOffset)
}
})
const offsetYModel = computed({
get: () => currentSprite.value?.offset?.y || 0,
set: (value) => {
if (isAnimating.value) return
const newOffset = {
x: currentSprite.value?.offset?.x || 0,
y: value
}
emit('update:tempOffset', currentFrame.value, newOffset)
}
})
// Toggle for showing reference sprites
const showReferenceSprites = ref(true)
@ -276,6 +304,13 @@ function onDrag(event: MouseEvent) {
}
function stopDrag() {
if (isDragging.value && currentSprite.value?.offset) {
// Ensure the final offset is applied when dragging stops
emit('update:tempOffset', currentFrame.value, {
x: currentSprite.value.offset.x,
y: currentSprite.value.offset.y
})
}
isDragging.value = false
}
@ -297,25 +332,25 @@ function updateOffset(event: Event, axis: 'x' | 'y') {
}
watch(
() => props.frameRate,
(newValue) => {
localFrameRate.value = newValue
updateAnimation()
},
{ immediate: true }
() => props.frameRate,
(newValue) => {
localFrameRate.value = newValue
updateAnimation()
},
{ immediate: true }
)
watch(() => props.sprites, updateAnimation, { immediate: true })
watch(
() => isAnimating.value,
(newValue) => {
if (newValue) {
updateAnimation()
} else {
stopAnimation()
() => isAnimating.value,
(newValue) => {
if (newValue) {
updateAnimation()
} else {
stopAnimation()
}
}
}
)
onMounted(() => {
@ -328,4 +363,4 @@ onMounted(() => {
onUnmounted(() => {
stopAnimation()
})
</script>
</script>