🆙 foto's 100% in renderer as in habbo

This commit is contained in:
DuckieTM
2026-02-01 15:13:30 +01:00
parent 1fe48bcda7
commit bd059d739d
2 changed files with 42 additions and 19 deletions
@@ -54,12 +54,12 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali
{ {
super.update(geometry, time, update, skipUpdate); 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) if(this._animatedSprite && this._frameTextures && this._frameTextures.length > 1)
{ {
const currentFrameIndex = this._animatedSprite.currentFrame; const currentFrameIndex = this._animatedSprite.currentFrame;
// Only update if frame has changed
if(currentFrameIndex !== this._lastFrameIndex) if(currentFrameIndex !== this._lastFrameIndex)
{ {
this._lastFrameIndex = currentFrameIndex; this._lastFrameIndex = currentFrameIndex;
@@ -73,14 +73,17 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali
const currentFrameTexture = this._frameTextures[currentFrameIndex]; const currentFrameTexture = this._frameTextures[currentFrameIndex];
if(!currentFrameTexture) return; if(!currentFrameTexture) return;
// Update the badge canvas with the current frame
const badgeCanvas = (tex.source as any).resource as HTMLCanvasElement; const badgeCanvas = (tex.source as any).resource as HTMLCanvasElement;
const ctx = badgeCanvas.getContext('2d', { willReadFrequently: true }); const ctx = badgeCanvas.getContext('2d', { willReadFrequently: true });
// Create a temporary canvas to extract the frame texture data
const frameCanvas = document.createElement('canvas'); const frameCanvas = document.createElement('canvas');
frameCanvas.width = currentFrameTexture.width; frameCanvas.width = currentFrameTexture.width;
frameCanvas.height = currentFrameTexture.height; frameCanvas.height = currentFrameTexture.height;
const frameCtx = frameCanvas.getContext('2d'); const frameCtx = frameCanvas.getContext('2d');
// Get the source from the texture
const frameSource = (currentFrameTexture.source as any).resource; const frameSource = (currentFrameTexture.source as any).resource;
if(frameSource instanceof HTMLCanvasElement || frameSource instanceof HTMLImageElement) 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); 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'); const frameCanvas = document.createElement('canvas');
frameCanvas.width = gif.lsd.width; frameCanvas.width = gif.lsd.width;
frameCanvas.height = gif.lsd.height; frameCanvas.height = gif.lsd.height;
const frameCtx = frameCanvas.getContext('2d'); const frameCtx = frameCanvas.getContext('2d');
frameCtx.drawImage(accCanvas, 0, 0); frameCtx.drawImage(accCanvas, 0, 0);
// Create texture from canvas
const frameTexture = Texture.from(frameCanvas); const frameTexture = Texture.from(frameCanvas);
this._frameTextures.push(frameTexture); this._frameTextures.push(frameTexture);
// GIF delays are in centiseconds (1/100th of a second)
frameDelays.push(frame.delay || 10); frameDelays.push(frame.delay || 10);
} }
// Create AnimatedSprite with frame textures
if(this._frameTextures.length > 1) if(this._frameTextures.length > 1)
{ {
this._animatedSprite = new AnimatedSprite(this._frameTextures); this._animatedSprite = new AnimatedSprite(this._frameTextures);
// Calculate average delay and set animation speed
const avgDelay = frameDelays.reduce((a, b) => a + b, 0) / frameDelays.length; 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 delayMs = (avgDelay > 50 ? 10 : avgDelay) * 10;
const framesPerTick = 16.67 / delayMs; const framesPerTick = 16.67 / delayMs;
this._animatedSprite.animationSpeed = framesPerTick; this._animatedSprite.animationSpeed = framesPerTick;
@@ -307,6 +319,7 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali
this._lastFrameIndex = -1; this._lastFrameIndex = -1;
} }
// Draw first frame to the badge canvas
const firstFrameSource = (this._frameTextures[0].source as any).resource; const firstFrameSource = (this._frameTextures[0].source as any).resource;
if(firstFrameSource instanceof HTMLCanvasElement) if(firstFrameSource instanceof HTMLCanvasElement)
{ {
@@ -1,6 +1,6 @@
import { IGraphicAsset } from '@nitrots/api'; import { IGraphicAsset } from '@nitrots/api';
import { GetRenderer, TextureUtils } from '@nitrots/utils'; 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'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization';
export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualization { export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualization {
@@ -80,12 +80,10 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
const asset = this.getAsset(assetName, layerId); const asset = this.getAsset(assetName, layerId);
const thumbnailAssetName = `${this.getThumbnailAssetName(scale)}-${this._uniqueId}`; const thumbnailAssetName = `${this.getThumbnailAssetName(scale)}-${this._uniqueId}`;
const transformedTexture = this.generateTransformedThumbnail(k, asset || { width: 64, height: 64 }); const transformedTexture = this.generateTransformedThumbnail(k, asset || { width: 64, height: 64 });
// Calculate dynamic offsets based on transformed bounds
const sprite = new Sprite(transformedTexture); const sprite = new Sprite(transformedTexture);
const bounds = sprite.getLocalBounds(); const bounds = sprite.getLocalBounds();
const offsetX = -Math.floor(bounds.width / 2); // Center horizontally const offsetX = -Math.floor(bounds.width / 2);
const offsetY = -Math.floor(bounds.height / 2); // Center vertically const offsetY = -Math.floor(bounds.height / 2);
this.asset.addAsset(thumbnailAssetName, transformedTexture, true, offsetX, offsetY, false, false); 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 { protected generateTransformedThumbnail(texture: Texture, asset: IGraphicAsset): Texture {
const sprite = new Sprite(texture);
const scaleFactor = (asset?.width || 64) / texture.width; const scaleFactor = (asset?.width || 64) / texture.width;
const verticalScale = 1.0265;
const matrix = new Matrix(); const matrix = new Matrix();
const frameThickness = 20;
const frameColor = 0x000000;
switch (this.direction) { switch (this.direction) {
case 2: case 2:
matrix.a = scaleFactor; matrix.a = scaleFactor;
matrix.b = (-0.5 * scaleFactor); matrix.b = (-0.5 * scaleFactor);
matrix.c = 0; matrix.c = 0;
matrix.d = scaleFactor; matrix.d = (scaleFactor * verticalScale);
matrix.tx = 0; matrix.tx = 0;
matrix.ty = (0.5 * scaleFactor * texture.width); matrix.ty = (0.5 * scaleFactor * texture.width);
break; break;
@@ -120,7 +120,7 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
matrix.a = scaleFactor; matrix.a = scaleFactor;
matrix.b = (0.5 * scaleFactor); matrix.b = (0.5 * scaleFactor);
matrix.c = 0; matrix.c = 0;
matrix.d = scaleFactor; matrix.d = (scaleFactor * verticalScale);
matrix.tx = 0; matrix.tx = 0;
matrix.ty = 0; matrix.ty = 0;
break; break;
@@ -133,17 +133,27 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
matrix.ty = 0; matrix.ty = 0;
} }
sprite.setFromMatrix(matrix); const imgWidth = texture.width;
const imgHeight = texture.height;
const width = 64; const flatWidth = imgWidth + frameThickness * 2;
const height = 64; const flatHeight = imgHeight + frameThickness * 2;
const flatRenderTexture = TextureUtils.createAndFillRenderTexture(flatWidth, flatHeight, frameColor);
const container = new Container(); const imageSprite = new Sprite(texture);
sprite.position.set((width - sprite.width) / 2, (height - sprite.height) / 2); imageSprite.position.set(frameThickness, frameThickness);
container.addChild(sprite); 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 }); 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; return renderTexture;
} }