Align with Pixi v8: Filter[] union, WebGLRenderer narrow, ImageLike

Four sites where Pixi v8's stricter typing tripped tsgo:

- AvatarImage: container.filters is typed as 'readonly Filter[] | null'
  in v8 (no longer a single-Filter union). The old fallback branch
  'else container.filters = [container.filters, …]' tried to treat a
  readonly array as a single Filter; collapsed to the array-spread
  path which now covers both undefined and non-empty cases. Added
  Filter to the pixi.js import.
- FurnitureBadgeDisplayVisualization.updateSprite() had a 4-arg
  override (sprite, asset, scale, layerId) of the parent's 2-arg
  signature (scale, layerId). The sprite/asset were never used from
  the parameters — the body only mutated 'sprite'. Refactored to
  fetch the sprite via this.getSprite(layerId) inside the override
  body so the signature matches the base.
- ExtendedSprite: 'renderer.gl' / 'glRenderTarget.resolveTargetFramebuffer'
  exist only on WebGLRenderer / GlRenderTarget (not the WebGPU
  variants). The runtime check 'renderer.type === RendererType.WEBGL'
  guarantees this; cast at the boundary to satisfy the typechecker.
- TextureUtils.generateImage: Pixi v8's Extractor.image() returns the
  union ImageLike (HTMLCanvasElement | HTMLImageElement); the public
  signature promises HTMLImageElement. Cast at return — the Pixi
  default backend returns HTMLImageElement here.
This commit is contained in:
simoleo89
2026-05-11 21:09:59 +02:00
parent b42f989e28
commit 5ea3201e31
4 changed files with 17 additions and 15 deletions
+5 -8
View File
@@ -1,6 +1,6 @@
import { AvatarAction, AvatarDirectionAngle, AvatarScaleType, AvatarSetType, IActiveActionData, IAnimationLayerData, IAvatarDataContainer, IAvatarEffectListener, IAvatarFigureContainer, IAvatarImage, IPartColor, ISpriteDataContainer } from '@nitrots/api'; import { AvatarAction, AvatarDirectionAngle, AvatarScaleType, AvatarSetType, IActiveActionData, IAnimationLayerData, IAvatarDataContainer, IAvatarEffectListener, IAvatarFigureContainer, IAvatarImage, IGraphicAsset, IPartColor, ISpriteDataContainer } from '@nitrots/api';
import { GetRenderer, GetTexturePool, GetTickerTime, PaletteMapFilter, TextureUtils } from '@nitrots/utils'; import { GetRenderer, GetTexturePool, GetTickerTime, PaletteMapFilter, TextureUtils } from '@nitrots/utils';
import { ColorMatrixFilter, Container, RenderTexture, Sprite, Texture } from 'pixi.js'; import { ColorMatrixFilter, Container, Filter, RenderTexture, Sprite, Texture } from 'pixi.js';
import { AvatarFigureContainer } from './AvatarFigureContainer'; import { AvatarFigureContainer } from './AvatarFigureContainer';
import { AvatarStructure } from './AvatarStructure'; import { AvatarStructure } from './AvatarStructure';
import { EffectAssetDownloadManager } from './EffectAssetDownloadManager'; import { EffectAssetDownloadManager } from './EffectAssetDownloadManager';
@@ -243,8 +243,7 @@ export class AvatarImage implements IAvatarImage, IAvatarEffectListener
if(this._avatarSpriteData.colorTransform) if(this._avatarSpriteData.colorTransform)
{ {
if(container.filters === undefined || container.filters === null) container.filters = [ this._avatarSpriteData.colorTransform ]; if(container.filters === undefined || container.filters === null) container.filters = [ this._avatarSpriteData.colorTransform ];
else if(Array.isArray(container.filters)) container.filters = [ ...container.filters, this._avatarSpriteData.colorTransform ]; else container.filters = [ ...(container.filters as readonly Filter[]), this._avatarSpriteData.colorTransform ];
else container.filters = [ container.filters, this._avatarSpriteData.colorTransform ];
} }
if(this._avatarSpriteData.paletteIsGrayscale) if(this._avatarSpriteData.paletteIsGrayscale)
@@ -257,8 +256,7 @@ export class AvatarImage implements IAvatarImage, IAvatarEffectListener
}); });
if(container.filters === undefined || container.filters === null) container.filters = [ paletteMapFilter ]; if(container.filters === undefined || container.filters === null) container.filters = [ paletteMapFilter ];
else if(Array.isArray(container.filters)) container.filters = [ ...container.filters, paletteMapFilter ]; else container.filters = [ ...(container.filters as readonly Filter[]), paletteMapFilter ];
else container.filters = [ container.filters, paletteMapFilter ];
} }
} }
@@ -766,8 +764,7 @@ export class AvatarImage implements IAvatarImage, IAvatarEffectListener
]; ];
if(container.filters === undefined || container.filters === null) container.filters = [ filter ]; if(container.filters === undefined || container.filters === null) container.filters = [ filter ];
else if(Array.isArray(container.filters)) container.filters = [ ...container.filters, filter ]; else container.filters = [ ...(container.filters as readonly Filter[]), filter ];
else container.filters = [ container.filters, filter ];
return container; return container;
} }
@@ -170,14 +170,18 @@ export class FurnitureBadgeDisplayVisualization extends FurnitureAnimatedVisuali
return assetName; return assetName;
} }
protected updateSprite(sprite: IRoomObjectSprite, asset: IGraphicAsset, scale: number, layerId: number): void protected updateSprite(scale: number, layerId: number): void
{ {
super.updateSprite(sprite, asset, scale, layerId); super.updateSprite(scale, layerId);
const tag = this.getLayerTag(scale, this.direction, layerId); const tag = this.getLayerTag(scale, this.direction, layerId);
if(tag === FurnitureBadgeDisplayVisualization.BADGE_TAG) if(tag === FurnitureBadgeDisplayVisualization.BADGE_TAG)
{ {
const sprite = this.getSprite(layerId);
if(!sprite) return;
sprite.visible = true; sprite.visible = true;
sprite.alpha = 255; sprite.alpha = 255;
sprite.color = 0xFFFFFF; sprite.color = 0xFFFFFF;
@@ -1,6 +1,6 @@
import { AlphaTolerance } from '@nitrots/api'; import { AlphaTolerance } from '@nitrots/api';
import { GetRenderer, TextureUtils } from '@nitrots/utils'; import { GetRenderer, TextureUtils } from '@nitrots/utils';
import { Point, RendererType, Sprite, Texture, TextureSource, WebGPURenderer } from 'pixi.js'; import { GlRenderTarget, Point, RendererType, Sprite, Texture, TextureSource, WebGLRenderer, WebGPURenderer } from 'pixi.js';
const BYTES_PER_PIXEL = 4; const BYTES_PER_PIXEL = 4;
@@ -97,10 +97,11 @@ export class ExtendedSprite extends Sprite
{ {
pixels = new Uint8ClampedArray(BYTES_PER_PIXEL * width * height); pixels = new Uint8ClampedArray(BYTES_PER_PIXEL * width * height);
const renderTarget = renderer.renderTarget.getRenderTarget(textureSource); const webglRenderer = renderer as WebGLRenderer;
const glRenderTarget = renderer.renderTarget.getGpuRenderTarget(renderTarget); const renderTarget = webglRenderer.renderTarget.getRenderTarget(textureSource);
const glRenderTarget = webglRenderer.renderTarget.getGpuRenderTarget(renderTarget) as GlRenderTarget;
const gl = renderer.gl; const gl = webglRenderer.gl;
gl.bindFramebuffer(gl.FRAMEBUFFER, glRenderTarget.resolveTargetFramebuffer); gl.bindFramebuffer(gl.FRAMEBUFFER, glRenderTarget.resolveTargetFramebuffer);
+1 -1
View File
@@ -28,7 +28,7 @@ export class TextureUtils
try try
{ {
return await this.getExtractor().image(options); return await this.getExtractor().image(options) as HTMLImageElement;
} }
catch(e) catch(e)
{ {