This commit is contained in:
duckietm 2025-03-18 10:46:22 +01:00
parent 00790c0789
commit 8acd0c7de4
4 changed files with 187 additions and 213 deletions

View File

@ -37,7 +37,7 @@ export class FurnitureChangeStateWhenStepOnLogic extends FurnitureLogic
let sizeX = this.object.model.getValue<number>(RoomObjectVariable.FURNITURE_SIZE_X); let sizeX = this.object.model.getValue<number>(RoomObjectVariable.FURNITURE_SIZE_X);
let sizeY = this.object.model.getValue<number>(RoomObjectVariable.FURNITURE_SIZE_Y); let sizeY = this.object.model.getValue<number>(RoomObjectVariable.FURNITURE_SIZE_Y);
const direction = (((Math.floor(this.object.getDirection().x) + 45) % 360) / 90); const direction = Math.floor(((this.object.getDirection().x + 45) % 360) / 90);
if((direction === 1) || (direction === 3)) [sizeX, sizeY] = [sizeY, sizeX]; if((direction === 1) || (direction === 3)) [sizeX, sizeY] = [sizeY, sizeX];

View File

@ -6,6 +6,7 @@ export class FurnitureDynamicThumbnailVisualization extends IsometricImageFurniV
constructor() { constructor() {
super(); super();
this._cachedUrl = null; this._cachedUrl = null;
this._hasOutline = true; this._hasOutline = true;
} }
@ -13,25 +14,32 @@ export class FurnitureDynamicThumbnailVisualization extends IsometricImageFurniV
protected updateModel(scale: number): boolean { protected updateModel(scale: number): boolean {
if (this.object) { if (this.object) {
const thumbnailUrl = this.getThumbnailURL(); const thumbnailUrl = this.getThumbnailURL();
if (this._cachedUrl !== thumbnailUrl) { if (this._cachedUrl !== thumbnailUrl) {
this._cachedUrl = thumbnailUrl; this._cachedUrl = thumbnailUrl;
if (this._cachedUrl && this._cachedUrl !== '') { if (this._cachedUrl && this._cachedUrl !== '') {
const image = new Image(); const image = new Image();
image.crossOrigin = '*';
image.onload = this.onImageLoad.bind(this, image);
image.src = thumbnailUrl; image.src = thumbnailUrl;
image.crossOrigin = '*';
image.onload = () => {
if (image.complete && image.width > 0 && image.height > 0) {
const texture = Texture.from(image);
texture.source.scaleMode = 'linear';
this.setThumbnailImages(texture, thumbnailUrl); // Pass URL here
} else {
console.error("Image failed to load properly:", thumbnailUrl);
}
};
} else { } else {
this.setThumbnailImages(null); this.setThumbnailImages(null);
} }
} }
} }
return super.updateModel(scale);
}
private onImageLoad(image: HTMLImageElement): void { return super.updateModel(scale);
const texture = Texture.from(image);
texture.source.scaleMode = 'linear';
this.setThumbnailImages(texture);
} }
protected getThumbnailURL(): string { protected getThumbnailURL(): string {

View File

@ -1,18 +1,17 @@
import { IGraphicAsset } from '@nitrots/api'; import { IGraphicAsset } from '@nitrots/api';
import { TextureUtils } from '@nitrots/utils'; import { GetRenderer, TextureUtils } from '@nitrots/utils';
import * as PIXI from 'pixi.js'; import { Matrix, Sprite, Texture, RenderTexture } from 'pixi.js';
import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization';
console.log('Pixi.js Version at import:', PIXI.VERSION);
export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualization { export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualization {
protected static THUMBNAIL: string = 'THUMBNAIL'; protected static THUMBNAIL: string = 'THUMBNAIL';
private _thumbnailAssetNameNormal: string; private _thumbnailAssetNameNormal: string;
private _thumbnailImageNormal: PIXI.Texture; private _thumbnailImageNormal: Texture;
private _thumbnailDirection: number; private _thumbnailDirection: number;
private _thumbnailChanged: boolean; private _thumbnailChanged: boolean;
protected _hasOutline: boolean; private _uniqueId: string;
private _photoUrl: string; // Store the photo URL or ID
constructor() { constructor() {
super(); super();
@ -21,28 +20,30 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
this._thumbnailImageNormal = null; this._thumbnailImageNormal = null;
this._thumbnailDirection = -1; this._thumbnailDirection = -1;
this._thumbnailChanged = false; this._thumbnailChanged = false;
this._hasOutline = false; // Disable outline for simplicity this._uniqueId = `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
this._photoUrl = null;
} }
public get hasThumbnailImage(): boolean { public get hasThumbnailImage(): boolean {
return !!this._thumbnailImageNormal; return !(this._thumbnailImageNormal == null);
} }
public setThumbnailImages(k: PIXI.Texture): void { public setThumbnailImages(k: Texture, url?: string): void {
this._thumbnailImageNormal = k; this._thumbnailImageNormal = k;
this._photoUrl = url || null; // Store the URL or ID passed with the texture
this._thumbnailChanged = true; this._thumbnailChanged = true;
} }
public getPhotoUrl(): string {
return this._photoUrl; // Expose the URL for the click handler
}
protected updateModel(scale: number): boolean { protected updateModel(scale: number): boolean {
const flag = super.updateModel(scale); const flag = super.updateModel(scale);
if (this.object && this.object.model) { if (!this._thumbnailChanged && (this._thumbnailDirection === this.direction)) {
if (this.direction === 2) this.object.model.setValue('furniture_color', 0xFF0000);
else if (this.direction === 4) this.object.model.setValue('furniture_color', 0x0000FF);
}
if (!this._thumbnailChanged && (this._thumbnailDirection === this.direction))
return flag; return flag;
}
this.refreshThumbnail(); this.refreshThumbnail();
@ -50,157 +51,104 @@ export class IsometricImageFurniVisualization extends FurnitureAnimatedVisualiza
} }
private refreshThumbnail(): void { private refreshThumbnail(): void {
if (!this.asset) return; if (this.asset == null) {
return;
}
const thumbnailAssetName = this.getThumbnailAssetName(64);
if (this._thumbnailImageNormal) { if (this._thumbnailImageNormal) {
this.addThumbnailAsset(this._thumbnailImageNormal, 64); this.addThumbnailAsset(this._thumbnailImageNormal, 64);
} else { } else {
this.asset.disposeAsset(this.getThumbnailAssetName(64)); const layerId = 2;
const sprite = this.getSprite(layerId);
} }
this._thumbnailChanged = false; this._thumbnailChanged = false;
this._thumbnailDirection = this.direction; this._thumbnailDirection = this.direction;
} }
private addThumbnailAsset(k: PIXI.Texture, scale: number): void { private addThumbnailAsset(k: Texture, scale: number): void {
if (!k) {
console.warn('addThumbnailAsset called with null/undefined texture. Skipping.');
return;
}
let layerId = 0; let layerId = 0;
while (layerId < this.totalSprites) { while (layerId < this.totalSprites) {
if ( const layerTag = this.getLayerTag(scale, this.direction, layerId);
this.getLayerTag(scale, this.direction, layerId) ===
IsometricImageFurniVisualization.THUMBNAIL if (layerTag === IsometricImageFurniVisualization.THUMBNAIL) {
) { const assetName = (this.cacheSpriteAssetName(scale, layerId, false) + this.getFrameNumber(scale, layerId));
const assetName =
this.cacheSpriteAssetName(scale, layerId, false) + this.getFrameNumber(scale, layerId);
const asset = this.getAsset(assetName, layerId); const asset = this.getAsset(assetName, layerId);
const thumbnailAssetName = `${this.getThumbnailAssetName(scale)}-${this._uniqueId}`;
const transformedTexture = this.generateTransformedThumbnail(k, asset || { width: 64, height: 64, offsetX: -34, offsetY: -30 });
if (asset) { this.asset.addAsset(thumbnailAssetName, transformedTexture, true, asset?.offsetX || -34, asset?.offsetY || -30, false, false);
const transformed = this.generateTransformedThumbnail(k, asset);
if (!transformed) return;
const thumbAssetName = this.getThumbnailAssetName(scale); const sprite = this.getSprite(layerId);
if (sprite) {
this.asset.disposeAsset(thumbAssetName); sprite.texture = transformedTexture;
this.asset.addAsset(
thumbAssetName,
transformed,
true,
asset.offsetX,
asset.offsetY,
false,
false
);
} }
return; return;
} }
layerId++; layerId++;
} }
} }
protected generateTransformedThumbnail(texture: PIXI.Texture, asset: IGraphicAsset): PIXI.Texture { protected generateTransformedThumbnail(texture: Texture, asset: IGraphicAsset): Texture {
console.log('Entering generateTransformedThumbnail'); const sprite = new Sprite(texture);
console.log('Initial texture dimensions:', texture.width, 'x', texture.height); const scaleFactor = (asset?.width || 64) / texture.width;
console.log('Asset dimensions:', asset.width, 'x', asset.height); const matrix = new Matrix();
// 1) Scale the texture to 320x320, then to 64x64
const targetWidth = 64;
const targetHeight = 64;
let workingTexture = texture;
// Ensure texture is 320x320
if (texture.width !== 320 || texture.height !== 320) {
const scaleContainer = new PIXI.Container();
const scaleSprite = new PIXI.Sprite(texture);
scaleSprite.width = 320;
scaleSprite.height = 320;
scaleContainer.addChild(scaleSprite);
workingTexture = TextureUtils.generateTexture(scaleContainer, 320, 320);
console.log('Scaled texture to 320x320:', workingTexture.width, 'x', workingTexture.height);
}
// Scale to 64x64
const scaleFactor = targetWidth / workingTexture.width; // 64/320 = 0.2
const scaledContainer = new PIXI.Container();
const scaledSprite = new PIXI.Sprite(workingTexture);
scaledSprite.scale.set(scaleFactor, scaleFactor); // Scale to 64x64
scaledContainer.addChild(scaledSprite);
workingTexture = TextureUtils.generateTexture(scaledContainer, targetWidth, targetHeight);
console.log('Scaled texture to 64x64:', workingTexture.width, 'x', workingTexture.height);
// 2) Apply trapezoid transformation: (0,0), (64,30), (64,64), (0,34)
if (this.direction === 4) {
const sprite = new PIXI.Sprite(workingTexture);
const container = new PIXI.Container();
container.addChild(sprite);
// Apply the trapezoid transformation
const points = [
new PIXI.Point(0, 0),
new PIXI.Point(64, 30),
new PIXI.Point(64, 64),
new PIXI.Point(0, 34),
];
const graphics = new PIXI.Graphics();
graphics.beginFill(0xFFFFFF);
graphics.drawPolygon(points);
graphics.endFill();
container.addChild(graphics);
container.mask = graphics;
const bounds = container.getBounds();
console.log('Container bounds before render:', bounds.width, 'x', bounds.height);
const finalTexture = TextureUtils.generateTexture(container, targetWidth, targetHeight);
console.log('Final texture dimensions:', finalTexture.width, 'x', finalTexture.height);
return finalTexture;
} else {
// Original matrix transformation for cases 0 and 2
const matrix = new PIXI.Matrix();
switch (this.direction) { switch (this.direction) {
case 0:
case 2: case 2:
matrix.b = 0.5; // Positive skew matrix.a = scaleFactor;
matrix.d /= 1.6; matrix.b = (-0.5 * scaleFactor);
matrix.tx = -0.5; // Shift left matrix.c = 0;
matrix.d = scaleFactor;
matrix.tx = 0;
matrix.ty = (0.5 * scaleFactor * texture.width);
break;
case 0:
case 4:
matrix.a = scaleFactor;
matrix.b = (0.5 * scaleFactor);
matrix.c = 0;
matrix.d = scaleFactor;
matrix.tx = 0;
matrix.ty = 0;
break; break;
default: default:
break; matrix.a = scaleFactor;
matrix.b = 0;
matrix.c = 0;
matrix.d = scaleFactor;
matrix.tx = 0;
matrix.ty = 0;
} }
const sprite = new PIXI.Sprite(workingTexture); sprite.setFromMatrix(matrix);
sprite.position.set(matrix.tx, matrix.ty);
sprite.scale.set(matrix.a, matrix.d);
sprite.skew.set(matrix.b, matrix.c);
const container = new PIXI.Container(); const width = 64;
container.addChild(sprite); const height = 64;
return TextureUtils.generateTexture(container); const renderTexture = RenderTexture.create({ width, height, resolution: 1 });
} GetRenderer().render({ container: sprite, target: renderTexture });
}
return renderTexture;
}
protected getSpriteAssetName(scale: number, layerId: number): string { protected getSpriteAssetName(scale: number, layerId: number): string {
if ( if (this._thumbnailImageNormal && (this.getLayerTag(scale, this.direction, layerId) === IsometricImageFurniVisualization.THUMBNAIL)) {
this._thumbnailImageNormal && return `${this.getThumbnailAssetName(scale)}-${this._uniqueId}`;
this.getLayerTag(scale, this.direction, layerId) === IsometricImageFurniVisualization.THUMBNAIL
) {
return this.getThumbnailAssetName(scale);
} }
return super.getSpriteAssetName(scale, layerId); return super.getSpriteAssetName(scale, layerId);
} }
protected getThumbnailAssetName(scale: number): string { protected getThumbnailAssetName(scale: number): string {
this._thumbnailAssetNameNormal = [this._type, this.object.id, 'thumb', 64, this.direction].join('_'); return this.cacheSpriteAssetName(scale, 2, false) + this.getFrameNumber(scale, 2);
return this._thumbnailAssetNameNormal;
} }
protected getFullThumbnailAssetName(k: number, _arg_2: number): string { protected getFullThumbnailAssetName(k: number, _arg_2: number): string {
return [this._type, k, 'thumb', _arg_2, this.direction].join('_'); return [this._type, k, 'thumb', _arg_2].join('_');
} }
} }

View File

@ -90,9 +90,22 @@ export class RoomObjectCache
data.type = sprite.sprite.type; data.type = sprite.sprite.type;
data.posture = sprite.sprite.posture; data.posture = sprite.sprite.posture;
console.log("Sprite data before processing:", {
name: data.name,
type: data.type,
tag: sprite.sprite.tag, // Add this line to log the tag
width: data.width,
height: data.height,
frame: data.frame,
color: data.color
});
const isSkewed = this.isSkewedSprite(sprite.sprite); const isSkewed = this.isSkewedSprite(sprite.sprite);
if(isSkewed) data.skew = (((sprite.sprite.direction % 4) === 0) ? -0.5 : 0.5); if(isSkewed)
{
data.skew = (((sprite.sprite.direction % 4) === 0) ? -0.5 : 0.5);
}
if(((((isSkewed || (sprite.name.indexOf('%image.library.url%') >= 0)) || (sprite.name.indexOf('%group.badge.url%') >= 0)) && (data.width <= RoomObjectCache.MAX_SIZE_FOR_AVG_COLOR)) && (data.height <= RoomObjectCache.MAX_SIZE_FOR_AVG_COLOR))) if(((((isSkewed || (sprite.name.indexOf('%image.library.url%') >= 0)) || (sprite.name.indexOf('%group.badge.url%') >= 0)) && (data.width <= RoomObjectCache.MAX_SIZE_FOR_AVG_COLOR)) && (data.height <= RoomObjectCache.MAX_SIZE_FOR_AVG_COLOR)))
{ {
@ -118,6 +131,11 @@ export class RoomObjectCache
{ {
if(!k.type) return false; if(!k.type) return false;
console.log("Checking if sprite is skewed:", {
type: k.type,
tag: k.tag
});
if((k.type.indexOf('external_image_wallitem') === 0) && (k.tag === 'THUMBNAIL')) return true; if((k.type.indexOf('external_image_wallitem') === 0) && (k.tag === 'THUMBNAIL')) return true;
if((k.type.indexOf('guild_forum') === 0) && (k.tag === 'THUMBNAIL')) return true; if((k.type.indexOf('guild_forum') === 0) && (k.tag === 'THUMBNAIL')) return true;