Renderer support for the in-client image position editor:
- FurnitureBrandedImageVisualization applies offsetX/Y to the branded image
layer only (offsetZ stays as z-index/depth), so the image can be moved
without shifting the furni frame
- new `scale` branding key + FURNITURE_BRANDING_SCALE: zooms the image via a
real per-sprite scale (RoomObjectSprite.scale, default 1, applied in
RoomSpriteCanvas) — NOT by writing the read-only width/height
- AssetManager loads external raster images (png/jpg/…) via a CORS <img> +
Texture.from instead of Assets.load (which didn't load cross-origin images);
branding image download failures are now surfaced instead of swallowed
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.
Display Container
├── Furniture Container (renders 1st - back)
│ └── All furniture sprites sorted by z-depth
├── Avatar Container (renders 2nd - middle)
│ └── All avatar sprites sorted by z-depth
└── Badge Container (renders 3rd - front)
└── All badge sprites sorted by z-depth
✅ Badges render on top of their furniture
✅ Avatars respect proper 3D depth (in front when in front, behind when behind)
✅ Animated GIFs work beautifully
✅ Clean, maintainable code with just a tiny z-offset