From bd059d739d03e90834a24405de6e96392a3da720 Mon Sep 17 00:00:00 2001 From: DuckieTM Date: Sun, 1 Feb 2026 15:13:30 +0100 Subject: [PATCH] :up: foto's 100% in renderer as in habbo --- .../FurnitureBadgeDisplayVisualization.ts | 17 ++++++- .../IsometricImageFurniVisualization.ts | 44 ++++++++++++------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/packages/room/src/object/visualization/furniture/FurnitureBadgeDisplayVisualization.ts b/packages/room/src/object/visualization/furniture/FurnitureBadgeDisplayVisualization.ts index 4bb1f2b..7caa949 100644 --- a/packages/room/src/object/visualization/furniture/FurnitureBadgeDisplayVisualization.ts +++ b/packages/room/src/object/visualization/furniture/FurnitureBadgeDisplayVisualization.ts @@ -54,12 +54,12 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali { super.update(geometry, time, update, skipUpdate); - // GIF using AnimatedSprite's + // Update animated GIF using AnimatedSprite's current frame if(this._animatedSprite && this._frameTextures && this._frameTextures.length > 1) { const currentFrameIndex = this._animatedSprite.currentFrame; - + // Only update if frame has changed if(currentFrameIndex !== this._lastFrameIndex) { this._lastFrameIndex = currentFrameIndex; @@ -73,14 +73,17 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali const currentFrameTexture = this._frameTextures[currentFrameIndex]; if(!currentFrameTexture) return; + // Update the badge canvas with the current frame const badgeCanvas = (tex.source as any).resource as HTMLCanvasElement; const ctx = badgeCanvas.getContext('2d', { willReadFrequently: true }); + // Create a temporary canvas to extract the frame texture data const frameCanvas = document.createElement('canvas'); frameCanvas.width = currentFrameTexture.width; frameCanvas.height = currentFrameTexture.height; const frameCtx = frameCanvas.getContext('2d'); + // Get the source from the texture const frameSource = (currentFrameTexture.source as any).resource; if(frameSource instanceof HTMLCanvasElement || frameSource instanceof HTMLImageElement) { @@ -281,23 +284,32 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali accCtx.drawImage(tempCanvas, frame.dims.left, frame.dims.top); + // Create a new canvas for this frame and create a texture from it const frameCanvas = document.createElement('canvas'); frameCanvas.width = gif.lsd.width; frameCanvas.height = gif.lsd.height; const frameCtx = frameCanvas.getContext('2d'); frameCtx.drawImage(accCanvas, 0, 0); + // Create texture from canvas const frameTexture = Texture.from(frameCanvas); this._frameTextures.push(frameTexture); + // GIF delays are in centiseconds (1/100th of a second) frameDelays.push(frame.delay || 10); } + // Create AnimatedSprite with frame textures if(this._frameTextures.length > 1) { this._animatedSprite = new AnimatedSprite(this._frameTextures); + // Calculate average delay and set animation speed const avgDelay = frameDelays.reduce((a, b) => a + b, 0) / frameDelays.length; + // Convert centiseconds to seconds, then to animation speed + // AnimatedSprite.animationSpeed is frames per ticker update (60fps default) + // delay in centiseconds * 10 = milliseconds, / 1000 = seconds + // At 60fps, 1 frame = ~16.67ms const delayMs = (avgDelay > 50 ? 10 : avgDelay) * 10; const framesPerTick = 16.67 / delayMs; this._animatedSprite.animationSpeed = framesPerTick; @@ -307,6 +319,7 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali this._lastFrameIndex = -1; } + // Draw first frame to the badge canvas const firstFrameSource = (this._frameTextures[0].source as any).resource; if(firstFrameSource instanceof HTMLCanvasElement) { diff --git a/packages/room/src/object/visualization/furniture/IsometricImageFurniVisualization.ts b/packages/room/src/object/visualization/furniture/IsometricImageFurniVisualization.ts index 485d43c..9f23461 100644 --- a/packages/room/src/object/visualization/furniture/IsometricImageFurniVisualization.ts +++ b/packages/room/src/object/visualization/furniture/IsometricImageFurniVisualization.ts @@ -1,6 +1,6 @@ import { IGraphicAsset } from '@nitrots/api'; import { GetRenderer, TextureUtils } from '@nitrots/utils'; -import { Container, Matrix, Sprite, Texture, RenderTexture } from 'pixi.js'; +import { Container, Graphics, Matrix, Sprite, Texture, RenderTexture } from 'pixi.js'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualization { @@ -80,12 +80,10 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza const asset = this.getAsset(assetName, layerId); const thumbnailAssetName = `${this.getThumbnailAssetName(scale)}-${this._uniqueId}`; const transformedTexture = this.generateTransformedThumbnail(k, asset || { width: 64, height: 64 }); - - // Calculate dynamic offsets based on transformed bounds const sprite = new Sprite(transformedTexture); const bounds = sprite.getLocalBounds(); - const offsetX = -Math.floor(bounds.width / 2); // Center horizontally - const offsetY = -Math.floor(bounds.height / 2); // Center vertically + const offsetX = -Math.floor(bounds.width / 2); + const offsetY = -Math.floor(bounds.height / 2); this.asset.addAsset(thumbnailAssetName, transformedTexture, true, offsetX, offsetY, false, false); @@ -102,16 +100,18 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza } protected generateTransformedThumbnail(texture: Texture, asset: IGraphicAsset): Texture { - const sprite = new Sprite(texture); const scaleFactor = (asset?.width || 64) / texture.width; + const verticalScale = 1.0265; const matrix = new Matrix(); + const frameThickness = 20; + const frameColor = 0x000000; switch (this.direction) { case 2: matrix.a = scaleFactor; matrix.b = (-0.5 * scaleFactor); matrix.c = 0; - matrix.d = scaleFactor; + matrix.d = (scaleFactor * verticalScale); matrix.tx = 0; matrix.ty = (0.5 * scaleFactor * texture.width); break; @@ -120,7 +120,7 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza matrix.a = scaleFactor; matrix.b = (0.5 * scaleFactor); matrix.c = 0; - matrix.d = scaleFactor; + matrix.d = (scaleFactor * verticalScale); matrix.tx = 0; matrix.ty = 0; break; @@ -133,17 +133,27 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza matrix.ty = 0; } - sprite.setFromMatrix(matrix); - - const width = 64; - const height = 64; - - const container = new Container(); - sprite.position.set((width - sprite.width) / 2, (height - sprite.height) / 2); - container.addChild(sprite); + const imgWidth = texture.width; + const imgHeight = texture.height; + const flatWidth = imgWidth + frameThickness * 2; + const flatHeight = imgHeight + frameThickness * 2; + const flatRenderTexture = TextureUtils.createAndFillRenderTexture(flatWidth, flatHeight, frameColor); + const imageSprite = new Sprite(texture); + imageSprite.position.set(frameThickness, frameThickness); + TextureUtils.writeToTexture(imageSprite, flatRenderTexture, false); + const flatTexture = flatRenderTexture; + const transformedSprite = new Sprite(flatTexture); + transformedSprite.setFromMatrix(matrix); + const width = 80; + const height = 80; + const finalContainer = new Container(); + const posX = (width - transformedSprite.width) / 2; + const posY = (height - transformedSprite.height) / 2; + transformedSprite.position.set(posX, posY); + finalContainer.addChild(transformedSprite); const renderTexture = RenderTexture.create({ width, height, resolution: 1 }); - GetRenderer().render({ container, target: renderTexture, clear: true }); + GetRenderer().render({ container: finalContainer, target: renderTexture, clear: true }); return renderTexture; }