Something went wrong. Try again.
A Social Deduction / Deception Game
Something went wrong. Try again.
2.0 kB · 52 lines
TypeScript
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253// ---------------------------------------------------------------------------// Atlas texture helpers: decode the baked sheet into a Pixi texture and slice// per-entry sub-textures from it on demand (cached).// ---------------------------------------------------------------------------
import { Rectangle, Texture } from 'pixi.js'import type { AtlasEntry } from './contract'
/** Decode a data URL (or any image URL) into a nearest-neighbour Texture, so the * baked pixel art stays crisp under the renderer's uniform zoom. */export async function loadTexture(url: string): Promise<Texture> { const img = new Image() // Request CORS so a remote atlas (e.g. an atproto PDS blob) can be uploaded to // WebGL without tainting the canvas. Harmless for same-origin `data:`/`blob:` // URLs (the editor's case), required for cross-origin http(s) URLs. img.crossOrigin = 'anonymous' img.src = url await img.decode() const tex = Texture.from(img) tex.source.scaleMode = 'nearest' return tex}
/** A lazily-built, cached lookup from atlas entry id → its sub-texture of the * baked sheet. Returns null when there is no atlas (colour-only / failed bake) * so callers can skip art that isn't available. */export interface AtlasSlicer { texFor: (id: number) => Texture | null /** Destroy every interned sub-texture (NOT the underlying atlas source). */ destroy: () => void}
export function makeAtlasSlicer(atlas: Texture | null, entries: AtlasEntry[]): AtlasSlicer { const cache = new Map<number, Texture>() return { texFor(id) { if (!atlas) return null let t = cache.get(id) if (!t) { const e = entries[id] if (!e) return null t = new Texture({ source: atlas.source, frame: new Rectangle(e.x, e.y, e.w, e.h) }) cache.set(id, t) } return t }, destroy() { for (const t of cache.values()) t.destroy(false) cache.clear() }, }}