UNPKG

stage-js

Version:

2D HTML5 Rendering and Layout

226 lines (188 loc) 5.88 kB
import { isFn, isHash } from "../common/is"; import { Texture } from "./texture"; import { TextureSelection } from "./selection"; import { ImageTexture } from "./image"; import { PipeTexture } from "./pipe"; export interface AtlasTextureDefinition { x: number; y: number; width: number; height: number; left?: number; top?: number; right?: number; bottom?: number; } type MonotypeAtlasTextureDefinition = Record<string, AtlasTextureDefinition | Texture | string>; type AnimAtlasTextureDefinition = (AtlasTextureDefinition | Texture | string)[]; export interface AtlasDefinition { name?: string; image?: | { src: string; ratio?: number; } | { /** @deprecated Use src instead of url */ url: string; ratio?: number; }; ppu?: number; textures?: Record< string, AtlasTextureDefinition | Texture | MonotypeAtlasTextureDefinition | AnimAtlasTextureDefinition >; map?: (texture: AtlasTextureDefinition) => AtlasTextureDefinition; /** @deprecated Use map */ filter?: (texture: AtlasTextureDefinition) => AtlasTextureDefinition; /** @deprecated */ trim?: number; /** @deprecated Use ppu */ ratio?: number; /** @deprecated Use map */ imagePath?: string; /** @deprecated Use map */ imageRatio?: number; } export class Atlas extends ImageTexture { /** @internal */ name: any; /** @internal */ _ppu: any; /** @internal */ _trim: any; /** @internal */ _map: any; /** @internal */ _textures: any; /** @internal */ _imageSrc: string; constructor(def: AtlasDefinition = {}) { super(); this.name = def.name; this._ppu = def.ppu || def.ratio || 1; this._trim = def.trim || 0; this._map = def.map || def.filter; this._textures = def.textures; if (typeof def.image === "object" && isHash(def.image)) { if ("src" in def.image) { this._imageSrc = def.image.src; } else if ("url" in def.image) { this._imageSrc = def.image.url; } if (typeof def.image.ratio === "number") { this._pixelRatio = def.image.ratio; } } else { if (typeof def.imagePath === "string") { this._imageSrc = def.imagePath; } else if (typeof def.image === "string") { this._imageSrc = def.image; } if (typeof def.imageRatio === "number") { this._pixelRatio = def.imageRatio; } } deprecatedWarning(def); } async load() { if (this._imageSrc) { const image = await asyncLoadImage(this._imageSrc); this.setSourceImage(image, this._pixelRatio); } } /** * @internal * Uses the definition to create a texture object from this atlas. */ pipeSpriteTexture = (def: AtlasTextureDefinition): Texture => { const map = this._map; const ppu = this._ppu; const trim = this._trim; if (!def) { return undefined; } def = Object.assign({}, def); if (isFn(map)) { def = map(def); } if (ppu != 1) { def.x *= ppu; def.y *= ppu; def.width *= ppu; def.height *= ppu; def.top *= ppu; def.bottom *= ppu; def.left *= ppu; def.right *= ppu; } if (trim != 0) { def.x += trim; def.y += trim; def.width -= 2 * trim; def.height -= 2 * trim; def.top -= trim; def.bottom -= trim; def.left -= trim; def.right -= trim; } const texture = new PipeTexture(this); texture.top = def.top; texture.bottom = def.bottom; texture.left = def.left; texture.right = def.right; texture.setSourceCoordinate(def.x, def.y); texture.setSourceDimension(def.width, def.height); return texture; }; /** * @internal * Looks up and returns texture definition. */ findSpriteDefinition = (query: string) => { const textures = this._textures; if (textures) { if (isFn(textures)) { return textures(query); } else if (isHash(textures)) { return textures[query]; } } }; // returns Selection, and then selection.one/array returns actual texture/textures select = (query?: string) => { if (!query) { // TODO: if `textures` is texture def, map or fn? return new TextureSelection(new PipeTexture(this)); } const textureDefinition = this.findSpriteDefinition(query); if (textureDefinition) { return new TextureSelection(textureDefinition, this); } }; } /** @internal */ function asyncLoadImage(src: string) { console.debug && console.debug("Loading image: " + src); return new Promise<HTMLImageElement>(function (resolve, reject) { const img = new Image(); img.onload = function () { console.debug && console.debug("Image loaded: " + src); resolve(img); }; img.onerror = function (error) { console.error("Loading failed: " + src); reject(error); }; img.src = src; }); } /** @internal */ function deprecatedWarning(def: AtlasDefinition) { if ("filter" in def) console.warn("'filter' field of atlas definition is deprecated"); // todo: throw error here? if ("cutouts" in def) console.warn("'cutouts' field of atlas definition is deprecated"); // todo: throw error here? if ("sprites" in def) console.warn("'sprites' field of atlas definition is deprecated"); // todo: throw error here? if ("factory" in def) console.warn("'factory' field of atlas definition is deprecated"); if ("ratio" in def) console.warn("'ratio' field of atlas definition is deprecated"); if ("imagePath" in def) console.warn("'imagePath' field of atlas definition is deprecated"); if ("imageRatio" in def) console.warn("'imageRatio' field of atlas definition is deprecated"); if (typeof def.image === "object" && "url" in def.image) console.warn("'image.url' field of atlas definition is deprecated"); }