This commit is contained in:
Dennis Postma 2025-02-23 01:39:30 +01:00
parent e8adb5c815
commit 12805e571a

View File

@ -31,8 +31,6 @@ interface EffectiveDimensions {
type Payload = { type Payload = {
id: UUID id: UUID
name: string name: string
width: number | null
height: number | null
spriteActions: Array<{ spriteActions: Array<{
action: string action: string
sprites: SpriteImage[] sprites: SpriteImage[]
@ -57,17 +55,12 @@ export default class SpriteUpdateEvent extends BaseEvent {
await spriteRepository.getEntityManager().populate(sprite, ['spriteActions']) await spriteRepository.getEntityManager().populate(sprite, ['spriteActions'])
// Update sprite in database with width/height if provided // Update sprite in database
await sprite await sprite.setName(data.name).setUpdatedAt(new Date()).save()
.setName(data.name)
.setWidth(data.width ?? sprite.getWidth())
.setHeight(data.height ?? sprite.getHeight())
.setUpdatedAt(new Date())
.save()
// First verify all sprite sheets can be generated // First verify all sprite sheets can be generated
for (const actionData of data.spriteActions) { for (const actionData of data.spriteActions) {
if (!(await this.generateSpriteSheet(actionData.sprites, sprite.getId(), actionData.action, data.width ?? 0, data.height ?? 0))) { if (!(await this.generateSpriteSheet(actionData.sprites, sprite.getId(), actionData.action))) {
return callback(false) return callback(false)
} }
} }
@ -85,12 +78,11 @@ export default class SpriteUpdateEvent extends BaseEvent {
const imageData = await Promise.all(actionData.sprites.map((sprite) => this.processImage(sprite))) const imageData = await Promise.all(actionData.sprites.map((sprite) => this.processImage(sprite)))
const effectiveDimensions = imageData.map((dimensions) => this.calculateEffectiveDimensions(dimensions)) const effectiveDimensions = imageData.map((dimensions) => this.calculateEffectiveDimensions(dimensions))
// Calculate maximum dimensions // Calculate total height needed for the sprite sheet
const maxWidth = data.width ?? Math.max(...effectiveDimensions.map((d) => d.width)) const maxHeight = Math.max(...effectiveDimensions.map((d) => d.height))
const maxHeight = data.height ?? Math.max(...effectiveDimensions.map((d) => d.height))
const maxTop = Math.max(...effectiveDimensions.map((d) => d.top)) const maxTop = Math.max(...effectiveDimensions.map((d) => d.top))
const maxBottom = Math.max(...effectiveDimensions.map((d) => d.bottom)) const maxBottom = Math.max(...effectiveDimensions.map((d) => d.bottom))
const totalHeight = data.height ?? maxHeight + maxTop + maxBottom const totalHeight = maxHeight + maxTop + maxBottom
const spriteAction = new SpriteAction() const spriteAction = new SpriteAction()
spriteAction.setSprite(sprite) spriteAction.setSprite(sprite)
@ -101,7 +93,7 @@ export default class SpriteUpdateEvent extends BaseEvent {
.setSprites(actionData.sprites) .setSprites(actionData.sprites)
.setOriginX(actionData.originX) .setOriginX(actionData.originX)
.setOriginY(actionData.originY) .setOriginY(actionData.originY)
.setFrameWidth(maxWidth) .setFrameWidth(await this.calculateMaxWidth(actionData.sprites))
.setFrameHeight(totalHeight) .setFrameHeight(totalHeight)
.setFrameRate(actionData.frameRate) .setFrameRate(actionData.frameRate)
@ -115,7 +107,7 @@ export default class SpriteUpdateEvent extends BaseEvent {
} }
} }
private async generateSpriteSheet(sprites: SpriteImage[], spriteId: string, action: string, containerWidth: number, containerHeight: number): Promise<boolean> { private async generateSpriteSheet(sprites: SpriteImage[], spriteId: string, action: string): Promise<boolean> {
try { try {
if (!sprites.length) return true if (!sprites.length) return true
@ -124,31 +116,25 @@ export default class SpriteUpdateEvent extends BaseEvent {
const effectiveDimensions = imageData.map((dimensions) => this.calculateEffectiveDimensions(dimensions)) const effectiveDimensions = imageData.map((dimensions) => this.calculateEffectiveDimensions(dimensions))
// Calculate maximum dimensions // Calculate maximum dimensions
const maxWidth = containerWidth > 0 ? containerWidth : Math.max(...effectiveDimensions.map((d) => d.width)) const maxWidth = Math.max(...effectiveDimensions.map((d) => d.width))
const maxHeight = containerHeight > 0 ? containerHeight : Math.max(...effectiveDimensions.map((d) => d.height)) const maxHeight = Math.max(...effectiveDimensions.map((d) => d.height))
const maxTop = Math.max(...effectiveDimensions.map((d) => d.top)) const maxTop = Math.max(...effectiveDimensions.map((d) => d.top))
const maxBottom = Math.max(...effectiveDimensions.map((d) => d.bottom)) const maxBottom = Math.max(...effectiveDimensions.map((d) => d.bottom))
// Calculate total height needed // Calculate total height needed
const totalHeight = containerHeight > 0 ? containerHeight : maxHeight + maxTop + maxBottom const totalHeight = maxHeight + maxTop + maxBottom
// Process images and create sprite sheet // Process images and create sprite sheet
const processedImages = await Promise.all( const processedImages = await Promise.all(
sprites.map(async (sprite) => { sprites.map(async (sprite, index) => {
const { width, height, offsetX, offsetY } = await this.processImage(sprite) const { width, height, offsetX, offsetY } = await this.processImage(sprite)
const uri = sprite.url.split(';base64,').pop() const uri = sprite.url.split(';base64,').pop()
if (!uri) throw new Error('Invalid base64 image') if (!uri) throw new Error('Invalid base64 image')
const buffer = Buffer.from(uri, 'base64') const buffer = Buffer.from(uri, 'base64')
// Calculate position based on container or offset // Create individual frame
// If container dimensions are set, position at top center const left = offsetX >= 0 ? offsetX : 0
const left = containerWidth > 0 ? Math.floor((maxWidth - width) / 2) : offsetX >= 0 ? offsetX : 0 const verticalOffset = totalHeight - height - (offsetY >= 0 ? offsetY : 0)
const top =
containerHeight > 0
? 0 // Place at top when container dimensions are set
: totalHeight - height - (offsetY >= 0 ? offsetY : 0)
return sharp({ return sharp({
create: { create: {
width: maxWidth, width: maxWidth,
@ -157,20 +143,7 @@ export default class SpriteUpdateEvent extends BaseEvent {
background: { r: 0, g: 0, b: 0, alpha: 0 } background: { r: 0, g: 0, b: 0, alpha: 0 }
} }
}) })
.composite([ .composite([{ input: buffer, left, top: verticalOffset }])
{
input: buffer,
left,
top,
...(containerWidth > 0 || containerHeight > 0
? {
width: containerWidth || undefined,
height: containerHeight || undefined,
fit: 'contain'
}
: {})
}
])
.png() .png()
.toBuffer() .toBuffer()
}) })