🆙 Update Deps. + WiP

This commit is contained in:
DuckieTM
2025-03-15 14:54:10 +01:00
parent c6ccfab5f5
commit d864fe3018
17 changed files with 215 additions and 262 deletions
+3 -4
View File
@@ -31,20 +31,19 @@
"howler": "^2.2.4", "howler": "^2.2.4",
"pako": "^2.1.0", "pako": "^2.1.0",
"pixi-filters": "^6.0.5", "pixi-filters": "^6.0.5",
"pixi.js": "^8.5.1", "pixi.js": "^8.8.1",
"clientjs": "^0.2.1" "clientjs": "^0.2.1"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.13.0", "@eslint/js": "^9.13.0",
"@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-typescript": "^11.1.6",
"@types/eslint__js": "^8.42.3",
"@types/howler": "^2.2.11", "@types/howler": "^2.2.11",
"@types/node": "^20.14.12", "@types/node": "^20.14.12",
"@types/pako": "^2.0.3", "@types/pako": "^2.0.3",
"eslint": "^9.8.0", "eslint": "^9.8.0",
"tslib": "^2.6.3", "tslib": "^2.6.3",
"typescript": "~5.5.4", "typescript": "~5.8.2",
"typescript-eslint": "^7.17.0", "typescript-eslint": "^8.26.1",
"vite": "^5.4.9" "vite": "^5.4.9"
} }
} }
+2 -2
View File
@@ -12,9 +12,9 @@
}, },
"main": "./index", "main": "./index",
"dependencies": { "dependencies": {
"pixi.js": "^8.5.1" "pixi.js": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+2 -2
View File
@@ -15,9 +15,9 @@
"@nitrots/api": "1.0.0", "@nitrots/api": "1.0.0",
"@nitrots/utils": "1.0.0", "@nitrots/utils": "1.0.0",
"@pixi/gif": "^3.0.1", "@pixi/gif": "^3.0.1",
"pixi.js": "^8.5.1" "pixi.js": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+1 -1
View File
@@ -15,6 +15,6 @@
"@nitrots/utils": "1.0.0" "@nitrots/utils": "1.0.0"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+2 -2
View File
@@ -14,9 +14,9 @@
"@nitrots/configuration": "1.0.0", "@nitrots/configuration": "1.0.0",
"@nitrots/events": "1.0.0", "@nitrots/events": "1.0.0",
"@nitrots/utils": "1.0.0", "@nitrots/utils": "1.0.0",
"pixi.js": "^8.5.1" "pixi.js": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+1 -1
View File
@@ -14,6 +14,6 @@
"@nitrots/utils": "1.0.0" "@nitrots/utils": "1.0.0"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+1 -1
View File
@@ -13,6 +13,6 @@
"@nitrots/utils": "1.0.0" "@nitrots/utils": "1.0.0"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+1 -1
View File
@@ -13,6 +13,6 @@
"@nitrots/utils": "1.0.0" "@nitrots/utils": "1.0.0"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+2 -2
View File
@@ -13,9 +13,9 @@
"@nitrots/communication": "1.0.0", "@nitrots/communication": "1.0.0",
"@nitrots/configuration": "1.0.0", "@nitrots/configuration": "1.0.0",
"@nitrots/events": "1.0.0", "@nitrots/events": "1.0.0",
"pixi.js": "^8.5.1" "pixi.js": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+2 -2
View File
@@ -16,9 +16,9 @@
"@nitrots/configuration": "1.0.0", "@nitrots/configuration": "1.0.0",
"@nitrots/events": "1.0.0", "@nitrots/events": "1.0.0",
"@nitrots/session": "1.0.0", "@nitrots/session": "1.0.0",
"pixi.js": "^8.5.1" "pixi.js": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
@@ -1,104 +1,40 @@
import { Texture, Graphics } from 'pixi.js'; import { Texture } from 'pixi.js';
import { IsometricImageFurniVisualization } from './IsometricImageFurniVisualization'; import { IsometricImageFurniVisualization } from './IsometricImageFurniVisualization';
export class FurnitureDynamicThumbnailVisualization extends IsometricImageFurniVisualization { export class FurnitureDynamicThumbnailVisualization extends IsometricImageFurniVisualization {
private _cachedUrl: string | null; private _cachedUrl: string;
constructor() { constructor() {
super(); super();
this._cachedUrl = null; this._cachedUrl = null;
this._hasOutline = false; // Disable outline to avoid borders this._hasOutline = true;
} }
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 !== '') {
const image = new Image();
if (this._cachedUrl && this._cachedUrl !== '') { image.crossOrigin = '*';
const image = new Image(); image.onload = this.onImageLoad.bind(this, image);
image.crossOrigin = 'anonymous'; image.src = thumbnailUrl;
} else {
image.onload = () => { this.setThumbnailImages(null);
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const targetWidth = 32;
const targetHeight = 32;
canvas.width = targetWidth;
canvas.height = targetHeight;
context!.fillStyle = '#b0b0b0';
context!.fillRect(0, 0, canvas.width, canvas.height);
const aspectRatio = image.width / image.height;
let drawWidth = targetWidth;
let drawHeight = targetHeight;
if (aspectRatio > 1) {
drawHeight = targetWidth / aspectRatio;
} else {
drawWidth = targetHeight * aspectRatio;
}
const offsetX = (targetWidth - drawWidth) / 2;
const offsetY = (targetHeight - drawHeight) / 2;
context!.drawImage(image, offsetX, offsetY, drawWidth, drawHeight);
const texture = Texture.from(canvas);
texture.source.scaleMode = 'linear';
this.setThumbnailImages(texture, scale);
};
image.onerror = () => {
console.error('Image load failed:', thumbnailUrl);
};
image.src = thumbnailUrl;
} else {
this.setThumbnailImages(null);
}
}
} }
return super.updateModel(scale); }
} }
return super.updateModel(scale);
}
protected getThumbnailURL(): string { private onImageLoad(image: HTMLImageElement): void {
return const texture = Texture.from(image);
} texture.source.scaleMode = 'linear';
this.setThumbnailImages(texture);
}
protected setThumbnailImages(texture: Texture | null, scale: number = 1): void { protected getThumbnailURL(): string {
super.setThumbnailImages(texture); throw new Error('This method must be overridden!');
}
if (texture && this.sprite) {
this.sprite.texture = texture;
this.sprite.width = texture.width * scale;
this.sprite.height = texture.height * scale;
this.sprite.anchor.set(0.5, 0.5);
if (this.sprite.mask) {
this.sprite.mask.destroy();
this.sprite.mask = null;
}
const mask = new Graphics()
.beginFill(0xffffff)
.drawRect(-texture.width / 2, -texture.height / 2, texture.width, texture.height)
.endFill();
this.sprite.addChild(mask);
this.sprite.mask = mask;
console.log('Sprite updated:', this.sprite.width, 'x', this.sprite.height);
} else if (!texture) {
if (this.sprite && this.sprite.mask) {
this.sprite.mask.destroy();
this.sprite.mask = null;
}
console.log('Thumbnail cleared');
}
}
} }
@@ -48,4 +48,4 @@ export class FurnitureExternalImageVisualization extends FurnitureDynamicThumbna
return url; return url;
} }
} }
@@ -1,173 +1,193 @@
import { IGraphicAsset } from '@nitrots/api'; import { IGraphicAsset } from '@nitrots/api';
import { TextureUtils } from '@nitrots/utils'; import { TextureUtils } from '@nitrots/utils';
import { Matrix, Sprite, Texture } from 'pixi.js'; import { Container, Matrix, Sprite, Texture } from 'pixi.js';
import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization'; import { FurnitureAnimatedVisualization } from './FurnitureAnimatedVisualization';
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: Texture; private _thumbnailImageNormal: Texture;
private _thumbnailDirection: number; private _thumbnailDirection: number;
private _thumbnailChanged: boolean; private _thumbnailChanged: boolean;
protected _hasOutline: boolean; protected _hasOutline: boolean;
constructor() constructor() {
{ super();
super();
this._thumbnailAssetNameNormal = null; this._thumbnailAssetNameNormal = null;
this._thumbnailImageNormal = null; this._thumbnailImageNormal = null;
this._thumbnailDirection = -1; this._thumbnailDirection = -1;
this._thumbnailChanged = false; this._thumbnailChanged = false;
this._hasOutline = false; this._hasOutline = false;
}
public get hasThumbnailImage(): boolean {
return !!this._thumbnailImageNormal;
}
public setThumbnailImages(k: Texture): void {
this._thumbnailImageNormal = k;
this._thumbnailChanged = true;
}
protected updateModel(scale: number): boolean {
const flag = super.updateModel(scale);
// Example: apply color tint for testing.
if (this.object && this.object.model) {
if (this.direction === 2) this.object.model.setValue('furniture_color', 0xFF0000);
else if (this.direction === 4) this.object.model.setValue('furniture_color', 0x0000FF);
} }
public get hasThumbnailImage(): boolean // Only refresh thumbnail if something changed or the direction changed.
{ if (!this._thumbnailChanged && (this._thumbnailDirection === this.direction))
return !(this._thumbnailImageNormal == null); return flag;
this.refreshThumbnail();
return true;
}
private refreshThumbnail(): void {
if (!this.asset) return;
if (this._thumbnailImageNormal) {
this.addThumbnailAsset(this._thumbnailImageNormal, 64);
} else {
this.asset.disposeAsset(this.getThumbnailAssetName(64));
} }
public setThumbnailImages(k: Texture): void this._thumbnailChanged = false;
{ this._thumbnailDirection = this.direction;
this._thumbnailImageNormal = k; }
this._thumbnailChanged = true;
private addThumbnailAsset(k: Texture, scale: number): void {
if (!k) {
console.warn('addThumbnailAsset called with null/undefined texture. Skipping.');
return;
} }
protected updateModel(scale: number): boolean let layerId = 0;
{ while (layerId < this.totalSprites) {
const flag = super.updateModel(scale); if (
this.getLayerTag(scale, this.direction, layerId) ===
IsometricImageFurniVisualization.THUMBNAIL
) {
const assetName =
this.cacheSpriteAssetName(scale, layerId, false) + this.getFrameNumber(scale, layerId);
const asset = this.getAsset(assetName, layerId);
if(!this._thumbnailChanged && (this._thumbnailDirection === this.direction)) return flag; if (asset) {
const transformed = this.generateTransformedThumbnail(k, asset);
if (!transformed) return;
this.refreshThumbnail(); const thumbAssetName = this.getThumbnailAssetName(scale);
return true; this.asset.disposeAsset(thumbAssetName);
} this.asset.addAsset(
thumbAssetName,
private refreshThumbnail(): void transformed,
{ true,
if(this.asset == null) return; asset.offsetX,
asset.offsetY,
if(this._thumbnailImageNormal) false,
{ false
this.addThumbnailAsset(this._thumbnailImageNormal, 64); );
}
else
{
this.asset.disposeAsset(this.getThumbnailAssetName(64));
} }
return;
}
layerId++;
}
}
this._thumbnailChanged = false; protected generateTransformedThumbnail(texture: Texture, asset: IGraphicAsset): Texture {
this._thumbnailDirection = this.direction; // 1) If an outline is needed, generate it.
if (this._hasOutline) {
const outlineContainer = new Container();
const background = new Sprite(Texture.WHITE);
background.tint = 0x000000;
background.width = texture.width + 40;
background.height = texture.height + 40;
const sprite = new Sprite(texture);
sprite.x = (background.width - sprite.width) / 2;
sprite.y = (background.height - sprite.height) / 2;
outlineContainer.addChild(background, sprite);
// Generate a new texture that includes the outline.
texture = TextureUtils.generateTexture(outlineContainer);
} }
private addThumbnailAsset(k: Texture, scale: number): void // 2) Set the texture's intended dimensions.
{ texture.orig.width = asset.width;
let layerId = 0; texture.orig.height = asset.height;
while(layerId < this.totalSprites) // 3) Build the matrix (same as your original logic).
{ // Default matrix: (a=1, b=0, c=0, d=1, tx=0, ty=0)
if(this.getLayerTag(scale, this.direction, layerId) === IsometricImageFurniVisualization.THUMBNAIL) const matrix = new Matrix();
{ switch (this.direction) {
const assetName = (this.cacheSpriteAssetName(scale, layerId, false) + this.getFrameNumber(scale, layerId)); case 2:
const asset = this.getAsset(assetName, layerId); matrix.b = -0.5; // negative skew
matrix.d /= 1.6; // flatten vertically
if(asset) matrix.ty = 0.5 * texture.width; // shift downward
{ break;
const _local_6 = this.generateTransformedThumbnail(k, asset); case 0:
const _local_7 = this.getThumbnailAssetName(scale); case 4:
matrix.b = 0.5; // positive skew
this.asset.disposeAsset(_local_7); matrix.d /= 1.6;
this.asset.addAsset(_local_7, _local_6, true, asset.offsetX, asset.offsetY, false, false); matrix.tx = -0.5; // shift left
} break;
return;
}
layerId++;
}
} }
protected generateTransformedThumbnail(texture: Texture, asset: IGraphicAsset): Texture // 4) Decompose the matrix.
{ const rotation = Math.atan2(matrix.b, matrix.a);
if(this._hasOutline) const scaleX = Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b);
{ const scaleY = matrix.d;
const container = new Sprite(); const tx = matrix.tx;
const background = new Sprite(Texture.WHITE); const ty = matrix.ty;
background.tint = 0x000000; // 5) Create a sprite from the texture.
background.width = (texture.width + 40); const finalSprite = new Sprite(texture);
background.height = (texture.height + 40); // Set the anchor to center to ease flipping.
finalSprite.anchor.set(0.5, 0.5);
const sprite = new Sprite(texture); // 6) Apply the decomposed transform.
const offsetX = ((background.width - sprite.width) / 2); // Since our anchor is center, add half of the texture's width/height.
const offsetY = ((background.height - sprite.height) / 2); finalSprite.x = tx + texture.width / 2;
finalSprite.y = ty + texture.height / 2;
finalSprite.rotation = rotation;
finalSprite.scale.set(scaleX, scaleY);
sprite.x = Math.floor(offsetX); console.log(
sprite.y = Math.floor(offsetY); 'Manual override: direction', this.direction,
'rotation =', finalSprite.rotation,
'scale =', finalSprite.scale.x, finalSprite.scale.y,
'position =', finalSprite.x, finalSprite.y
);
container.addChild(background, sprite); // 8) Wrap the sprite in a container and generate the final texture.
const container = new Container();
container.addChild(finalSprite);
return TextureUtils.generateTexture(container);
}
texture = TextureUtils.generateTexture(container); protected getSpriteAssetName(scale: number, layerId: number): string {
} if (
this._thumbnailImageNormal &&
const scale = 1.1; this.getLayerTag(scale, this.direction, layerId) === IsometricImageFurniVisualization.THUMBNAIL
const matrix = new Matrix(); ) {
const difference = (asset.width / texture.width); return this.getThumbnailAssetName(scale);
switch(this.direction)
{
case 2:
matrix.a = difference;
matrix.b = (-0.5 * difference);
matrix.c = 0;
matrix.d = (difference * scale);
matrix.tx = 0;
matrix.ty = ((0.5 * difference) * texture.width);
break;
case 0:
case 4:
matrix.a = difference;
matrix.b = (0.5 * difference);
matrix.c = 0;
matrix.d = (difference * scale);
matrix.tx = 0;
matrix.ty = 0;
break;
default:
matrix.a = difference;
matrix.b = 0;
matrix.c = 0;
matrix.d = difference;
matrix.tx = 0;
matrix.ty = 0;
}
const sprite = new Sprite(texture);
sprite.setFromMatrix(matrix);
return TextureUtils.generateTexture(sprite);
} }
return super.getSpriteAssetName(scale, layerId);
}
protected getSpriteAssetName(scale: number, layerId: number): string protected getThumbnailAssetName(scale: number): string {
{ this._thumbnailAssetNameNormal = [this._type, this.object.id, 'thumb', 64, this.direction].join('_');
if(this._thumbnailImageNormal && (this.getLayerTag(scale, this.direction, layerId) === IsometricImageFurniVisualization.THUMBNAIL)) return this.getThumbnailAssetName(scale); return this._thumbnailAssetNameNormal;
}
return super.getSpriteAssetName(scale, layerId); protected getFullThumbnailAssetName(k: number, _arg_2: number): string {
} return [this._type, k, 'thumb', _arg_2, this.direction].join('_');
}
protected getThumbnailAssetName(scale: number): string }
{
this._thumbnailAssetNameNormal = this.getFullThumbnailAssetName(this.object.id, 64);
return this._thumbnailAssetNameNormal;
}
protected getFullThumbnailAssetName(k: number, _arg_2: number): string
{
return [this._type, k, 'thumb', _arg_2].join('_');
}
}
+2 -2
View File
@@ -15,9 +15,9 @@
"@nitrots/configuration": "1.0.0", "@nitrots/configuration": "1.0.0",
"@nitrots/events": "1.0.0", "@nitrots/events": "1.0.0",
"@nitrots/localization": "1.0.0", "@nitrots/localization": "1.0.0",
"pixi.js": "^8.5.1" "pixi.js": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.8.2"
} }
} }
+1 -1
View File
@@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@nitrots/api": "1.0.0", "@nitrots/api": "1.0.0",
"@nitrots/communication": "1.0.0", "@nitrots/communication": "1.0.0",
"pixi.js": "^8.5.1" "pixi.js": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~5.5.4" "typescript": "~5.5.4"
+1 -1
View File
@@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@nitrots/api": "1.0.0", "@nitrots/api": "1.0.0",
"pako": "^2.1.0", "pako": "^2.1.0",
"pixi.js": "^8.5.1" "pixi.js": "^8.8.1"
}, },
"devDependencies": { "devDependencies": {
"@types/pako": "^2.0.3", "@types/pako": "^2.0.3",
+1 -3
View File
@@ -89,9 +89,7 @@ export class TexturePool
this._textures[texture.width][texture.height].splice(i, 1); this._textures[texture.width][texture.height].splice(i, 1);
this._totalTextures--; this._totalTextures--;
NitroLogger.log(`[TexturePool] Texture disposed: ${texture.width}x${texture.height}`);
} }
} }
} }