UNPKG

32.3 kBSource Map (JSON)View Raw
1{"version":3,"file":"Texture.js","sources":["../../src/textures/Texture.ts"],"sourcesContent":["import { Point, Rectangle } from '@pixi/math';\nimport { settings } from '@pixi/settings';\nimport { EventEmitter, getResolutionOfUrl, TextureCache, uid } from '@pixi/utils';\nimport { BaseTexture } from './BaseTexture';\nimport { ImageResource } from './resources/ImageResource';\nimport { TextureUvs } from './TextureUvs';\n\nimport type { IPointData } from '@pixi/math';\nimport type { IBaseTextureOptions, ImageSource } from './BaseTexture';\nimport type { BufferResource, BufferType, IBufferResourceOptions } from './resources/BufferResource';\nimport type { CanvasResource } from './resources/CanvasResource';\nimport type { Resource } from './resources/Resource';\nimport type { TextureMatrix } from './TextureMatrix';\n\nconst DEFAULT_UVS = new TextureUvs();\n\nexport type TextureSource = string | BaseTexture | ImageSource;\n\n/**\n * Stores the width of the non-scalable borders, for example when used with {@link PIXI.NineSlicePlane} texture.\n * @memberof PIXI\n * @since 7.2.0\n */\nexport interface ITextureBorders\n{\n /** left border in pixels */\n left: number;\n /** top border in pixels */\n top: number;\n /** right border in pixels */\n right: number;\n /** bottom border in pixels */\n bottom: number;\n}\n\nexport interface Texture extends GlobalMixins.Texture, EventEmitter {}\n\n/**\n * Used to remove listeners from WHITE and EMPTY Textures\n * @ignore\n */\nfunction removeAllHandlers(tex: any): void\n{\n tex.destroy = function _emptyDestroy(): void { /* empty */ };\n tex.on = function _emptyOn(): void { /* empty */ };\n tex.once = function _emptyOnce(): void { /* empty */ };\n tex.emit = function _emptyEmit(): void { /* empty */ };\n}\n\n/**\n * A texture stores the information that represents an image or part of an image.\n *\n * It cannot be added to the display list directly; instead use it as the texture for a Sprite.\n * If no frame is provided for a texture, then the whole image is used.\n *\n * You can directly create a texture from an image and then reuse it multiple times like this :\n *\n * ```js\n * import { Sprite, Texture } from 'pixi.js';\n *\n * const texture = Texture.from('assets/image.png');\n * const sprite1 = new Sprite(texture);\n * const sprite2 = new Sprite(texture);\n * ```\n *\n * If you didnt pass the texture frame to constructor, it enables `noFrame` mode:\n * it subscribes on baseTexture events, it automatically resizes at the same time as baseTexture.\n *\n * Textures made from SVGs, loaded or not, cannot be used before the file finishes processing.\n * You can check for this by checking the sprite's _textureID property.\n *\n * ```js\n * import { Sprite, Texture } from 'pixi.js';\n *\n * const texture = Texture.from('assets/image.svg');\n * const sprite1 = new Sprite(texture);\n * // sprite1._textureID should not be undefined if the texture has finished processing the SVG file\n * ```\n *\n * You can use a ticker or rAF to ensure your sprites load the finished textures after processing.\n * See issue [#3085]{@link https://github.com/pixijs/pixijs/issues/3085}.\n * @memberof PIXI\n * @typeParam R - The BaseTexture's Resource type.\n */\nexport class Texture<R extends Resource = Resource> extends EventEmitter\n{\n /** The base texture that this texture uses. */\n public baseTexture: BaseTexture<R>;\n\n /** This is the area of original texture, before it was put in atlas. */\n public orig: Rectangle;\n\n /**\n * This is the trimmed area of original texture, before it was put in atlas\n * Please call `updateUvs()` after you change coordinates of `trim` manually.\n */\n public trim: Rectangle;\n\n /** This will let the renderer know if the texture is valid. If it's not then it cannot be rendered. */\n public valid: boolean;\n\n /**\n * Has the texture been destroyed?\n * @readonly\n */\n public destroyed: boolean;\n\n /**\n * Does this Texture have any frame data assigned to it?\n *\n * This mode is enabled automatically if no frame was passed inside constructor.\n *\n * In this mode texture is subscribed to baseTexture events, and fires `update` on any change.\n *\n * Beware, after loading or resize of baseTexture event can fired two times!\n * If you want more control, subscribe on baseTexture itself.\n *\n * Any assignment of `frame` switches off `noFrame` mode.\n * @example\n * texture.on('update', () => {});\n */\n public noFrame: boolean;\n\n /**\n * Anchor point that is used as default if sprite is created with this texture.\n * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.\n * @default {0,0}\n */\n public defaultAnchor: Point;\n\n /**\n * Default width of the non-scalable border that is used if 9-slice plane is created with this texture.\n * @since 7.2.0\n * @see PIXI.NineSlicePlane\n */\n public defaultBorders?: ITextureBorders;\n\n /** Default TextureMatrix instance for this texture. By default, that object is not created because its heavy. */\n public uvMatrix: TextureMatrix;\n protected _rotate: number;\n\n /**\n * Update ID is observed by sprites and TextureMatrix instances.\n * Call updateUvs() to increment it.\n * @protected\n */\n _updateID: number;\n\n /**\n * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,\n * irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)\n */\n _frame: Rectangle;\n\n /**\n * The WebGL UV data cache. Can be used as quad UV.\n * @protected\n */\n _uvs: TextureUvs;\n\n /**\n * The ids under which this Texture has been added to the texture cache. This is\n * automatically set as long as Texture.addToCache is used, but may not be set if a\n * Texture is added directly to the TextureCache array.\n */\n textureCacheIds: Array<string>;\n\n /**\n * @param baseTexture - The base texture source to create the texture from\n * @param frame - The rectangle frame of the texture to show\n * @param orig - The area of original texture\n * @param trim - Trimmed rectangle of original texture\n * @param rotate - indicates how the texture was rotated by texture packer. See {@link PIXI.groupD8}\n * @param anchor - Default anchor point used for sprite placement / rotation\n * @param borders - Default borders used for 9-slice scaling. See {@link PIXI.NineSlicePlane}\n */\n constructor(baseTexture: BaseTexture<R>, frame?: Rectangle,\n orig?: Rectangle, trim?: Rectangle, rotate?: number, anchor?: IPointData, borders?: ITextureBorders)\n {\n super();\n\n this.noFrame = false;\n\n if (!frame)\n {\n this.noFrame = true;\n frame = new Rectangle(0, 0, 1, 1);\n }\n\n if (baseTexture instanceof Texture)\n {\n baseTexture = baseTexture.baseTexture;\n }\n\n this.baseTexture = baseTexture;\n this._frame = frame;\n this.trim = trim;\n this.valid = false;\n this.destroyed = false;\n this._uvs = DEFAULT_UVS;\n this.uvMatrix = null;\n this.orig = orig || frame;// new Rectangle(0, 0, 1, 1);\n\n this._rotate = Number(rotate || 0);\n\n if (rotate as any === true)\n {\n // this is old texturepacker legacy, some games/libraries are passing \"true\" for rotated textures\n this._rotate = 2;\n }\n else if (this._rotate % 2 !== 0)\n {\n throw new Error('attempt to use diamond-shaped UVs. If you are sure, set rotation manually');\n }\n\n this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);\n this.defaultBorders = borders;\n\n this._updateID = 0;\n\n this.textureCacheIds = [];\n\n if (!baseTexture.valid)\n {\n baseTexture.once('loaded', this.onBaseTextureUpdated, this);\n }\n else if (this.noFrame)\n {\n // if there is no frame we should monitor for any base texture changes..\n if (baseTexture.valid)\n {\n this.onBaseTextureUpdated(baseTexture);\n }\n }\n else\n {\n this.frame = frame;\n }\n\n if (this.noFrame)\n {\n baseTexture.on('update', this.onBaseTextureUpdated, this);\n }\n }\n\n /**\n * Updates this texture on the gpu.\n *\n * Calls the TextureResource update.\n *\n * If you adjusted `frame` manually, please call `updateUvs()` instead.\n */\n update(): void\n {\n if (this.baseTexture.resource)\n {\n this.baseTexture.resource.update();\n }\n }\n\n /**\n * Called when the base texture is updated\n * @protected\n * @param baseTexture - The base texture.\n */\n onBaseTextureUpdated(baseTexture: BaseTexture): void\n {\n if (this.noFrame)\n {\n if (!this.baseTexture.valid)\n {\n return;\n }\n\n this._frame.width = baseTexture.width;\n this._frame.height = baseTexture.height;\n this.valid = true;\n this.updateUvs();\n }\n else\n {\n // TODO this code looks confusing.. boo to abusing getters and setters!\n // if user gave us frame that has bigger size than resized texture it can be a problem\n this.frame = this._frame;\n }\n\n this.emit('update', this);\n }\n\n /**\n * Destroys this texture\n * @param [destroyBase=false] - Whether to destroy the base texture as well\n * @fires PIXI.Texture#destroyed\n */\n destroy(destroyBase?: boolean): void\n {\n if (this.baseTexture)\n {\n if (destroyBase)\n {\n const { resource } = this.baseTexture as unknown as BaseTexture<ImageResource>;\n\n // delete the texture if it exists in the texture cache..\n // this only needs to be removed if the base texture is actually destroyed too..\n if (resource?.url && TextureCache[resource.url])\n {\n Texture.removeFromCache(resource.url);\n }\n\n this.baseTexture.destroy();\n }\n\n this.baseTexture.off('loaded', this.onBaseTextureUpdated, this);\n this.baseTexture.off('update', this.onBaseTextureUpdated, this);\n\n this.baseTexture = null;\n }\n\n this._frame = null;\n this._uvs = null;\n this.trim = null;\n this.orig = null;\n\n this.valid = false;\n\n Texture.removeFromCache(this);\n this.textureCacheIds = null;\n\n this.destroyed = true;\n this.emit('destroyed', this);\n this.removeAllListeners();\n }\n\n /**\n * Creates a new texture object that acts the same as this one.\n * @returns - The new texture\n */\n clone(): Texture\n {\n const clonedFrame = this._frame.clone();\n const clonedOrig = this._frame === this.orig ? clonedFrame : this.orig.clone();\n const clonedTexture = new Texture(this.baseTexture,\n !this.noFrame && clonedFrame,\n clonedOrig,\n this.trim?.clone(),\n this.rotate,\n this.defaultAnchor,\n this.defaultBorders\n );\n\n if (this.noFrame)\n {\n clonedTexture._frame = clonedFrame;\n }\n\n return clonedTexture;\n }\n\n /**\n * Updates the internal WebGL UV cache. Use it after you change `frame` or `trim` of the texture.\n * Call it after changing the frame\n */\n updateUvs(): void\n {\n if (this._uvs === DEFAULT_UVS)\n {\n this._uvs = new TextureUvs();\n }\n\n this._uvs.set(this._frame, this.baseTexture, this.rotate);\n\n this._updateID++;\n }\n\n /**\n * Helper function that creates a new Texture based on the source you provide.\n * The source can be - frame id, image url, video url, canvas element, video element, base texture\n * @param {string|PIXI.BaseTexture|HTMLImageElement|HTMLVideoElement|ImageBitmap|PIXI.ICanvas} source -\n * Source or array of sources to create texture from\n * @param options - See {@link PIXI.BaseTexture}'s constructor for options.\n * @param {string} [options.pixiIdPrefix=pixiid] - If a source has no id, this is the prefix of the generated id\n * @param {boolean} [strict] - Enforce strict-mode, see {@link PIXI.settings.STRICT_TEXTURE_CACHE}.\n * @returns {PIXI.Texture} The newly created texture\n */\n static from<R extends Resource = Resource, RO = any>(source: TextureSource | TextureSource[],\n options: IBaseTextureOptions<RO> = {},\n strict = settings.STRICT_TEXTURE_CACHE): Texture<R>\n {\n const isFrame = typeof source === 'string';\n let cacheId = null;\n\n if (isFrame)\n {\n cacheId = source;\n }\n else if (source instanceof BaseTexture)\n {\n if (!source.cacheId)\n {\n const prefix = options?.pixiIdPrefix || 'pixiid';\n\n source.cacheId = `${prefix}-${uid()}`;\n BaseTexture.addToCache(source, source.cacheId);\n }\n\n cacheId = source.cacheId;\n }\n else\n {\n if (!(source as any)._pixiId)\n {\n const prefix = options?.pixiIdPrefix || 'pixiid';\n\n (source as any)._pixiId = `${prefix}_${uid()}`;\n }\n\n cacheId = (source as any)._pixiId;\n }\n\n let texture = TextureCache[cacheId] as Texture<R>;\n\n // Strict-mode rejects invalid cacheIds\n if (isFrame && strict && !texture)\n {\n throw new Error(`The cacheId \"${cacheId}\" does not exist in TextureCache.`);\n }\n\n if (!texture && !(source instanceof BaseTexture))\n {\n if (!options.resolution)\n {\n options.resolution = getResolutionOfUrl(source as string);\n }\n\n texture = new Texture<R>(new BaseTexture<R>(source, options));\n texture.baseTexture.cacheId = cacheId;\n\n BaseTexture.addToCache(texture.baseTexture, cacheId);\n Texture.addToCache(texture, cacheId);\n }\n else if (!texture && (source instanceof BaseTexture))\n {\n texture = new Texture<R>(source as BaseTexture<R>);\n\n Texture.addToCache(texture, cacheId);\n }\n\n // lets assume its a base texture!\n return texture;\n }\n\n /**\n * Useful for loading textures via URLs. Use instead of `Texture.from` because\n * it does a better job of handling failed URLs more effectively. This also ignores\n * `PIXI.settings.STRICT_TEXTURE_CACHE`. Works for Videos, SVGs, Images.\n * @param url - The remote URL or array of URLs to load.\n * @param options - Optional options to include\n * @returns - A Promise that resolves to a Texture.\n */\n static fromURL<R extends Resource = Resource, RO = any>(\n url: string | string[], options?: IBaseTextureOptions<RO>): Promise<Texture<R>>\n {\n const resourceOptions = Object.assign({ autoLoad: false }, options?.resourceOptions);\n const texture = Texture.from<R>(url, Object.assign({ resourceOptions }, options), false);\n const resource = texture.baseTexture.resource;\n\n // The texture was already loaded\n if (texture.baseTexture.valid)\n {\n return Promise.resolve(texture);\n }\n\n // Manually load the texture, this should allow users to handle load errors\n return resource.load().then(() => Promise.resolve(texture));\n }\n\n /**\n * Create a new Texture with a BufferResource from a typed array.\n * @param buffer - The optional array to use. If no data is provided, a new Float32Array is created.\n * @param width - Width of the resource\n * @param height - Height of the resource\n * @param options - See {@link PIXI.BaseTexture}'s constructor for options.\n * Default properties are different from the constructor's defaults.\n * @param {PIXI.FORMATS} [options.format] - The format is not given, the type is inferred from the\n * type of the buffer: `RGBA` if Float32Array, Int8Array, Uint8Array, or Uint8ClampedArray,\n * otherwise `RGBA_INTEGER`.\n * @param {PIXI.TYPES} [options.type] - The type is not given, the type is inferred from the\n * type of the buffer. Maps Float32Array to `FLOAT`, Int32Array to `INT`, Uint32Array to\n * `UNSIGNED_INT`, Int16Array to `SHORT`, Uint16Array to `UNSIGNED_SHORT`, Int8Array to `BYTE`,\n * Uint8Array/Uint8ClampedArray to `UNSIGNED_BYTE`.\n * @param {PIXI.ALPHA_MODES} [options.alphaMode=PIXI.ALPHA_MODES.NPM]\n * @param {PIXI.SCALE_MODES} [options.scaleMode=PIXI.SCALE_MODES.NEAREST]\n * @returns - The resulting new BaseTexture\n */\n static fromBuffer(buffer: BufferType, width: number, height: number,\n options?: IBaseTextureOptions<IBufferResourceOptions>): Texture<BufferResource>\n {\n return new Texture(BaseTexture.fromBuffer(buffer, width, height, options));\n }\n\n /**\n * Create a texture from a source and add to the cache.\n * @param {HTMLImageElement|HTMLVideoElement|ImageBitmap|PIXI.ICanvas|string} source - The input source.\n * @param imageUrl - File name of texture, for cache and resolving resolution.\n * @param name - Human readable name for the texture cache. If no name is\n * specified, only `imageUrl` will be used as the cache ID.\n * @param options\n * @returns - Output texture\n */\n static fromLoader<R extends Resource = Resource>(source: ImageSource | string,\n imageUrl: string, name?: string, options?: IBaseTextureOptions): Promise<Texture<R>>\n {\n const baseTexture = new BaseTexture<R>(source, Object.assign({\n scaleMode: BaseTexture.defaultOptions.scaleMode,\n resolution: getResolutionOfUrl(imageUrl),\n }, options));\n\n const { resource } = baseTexture;\n\n if (resource instanceof ImageResource)\n {\n resource.url = imageUrl;\n }\n\n const texture = new Texture<R>(baseTexture);\n\n // No name, use imageUrl instead\n if (!name)\n {\n name = imageUrl;\n }\n\n // lets also add the frame to pixi's global cache for 'fromLoader' function\n BaseTexture.addToCache(texture.baseTexture, name);\n Texture.addToCache(texture, name);\n\n // also add references by url if they are different.\n if (name !== imageUrl)\n {\n BaseTexture.addToCache(texture.baseTexture, imageUrl);\n Texture.addToCache(texture, imageUrl);\n }\n\n // Generally images are valid right away\n if (texture.baseTexture.valid)\n {\n return Promise.resolve(texture);\n }\n\n // SVG assets need to be parsed async, let's wait\n return new Promise((resolve) =>\n {\n texture.baseTexture.once('loaded', () => resolve(texture));\n });\n }\n\n /**\n * Adds a Texture to the global TextureCache. This cache is shared across the whole PIXI object.\n * @param texture - The Texture to add to the cache.\n * @param id - The id that the Texture will be stored against.\n */\n static addToCache(texture: Texture, id: string): void\n {\n if (id)\n {\n if (!texture.textureCacheIds.includes(id))\n {\n texture.textureCacheIds.push(id);\n }\n\n // only throw a warning if there is a different texture mapped to this id.\n if (TextureCache[id] && TextureCache[id] !== texture)\n {\n // eslint-disable-next-line no-console\n console.warn(`Texture added to the cache with an id [${id}] that already had an entry`);\n }\n\n TextureCache[id] = texture;\n }\n }\n\n /**\n * Remove a Texture from the global TextureCache.\n * @param texture - id of a Texture to be removed, or a Texture instance itself\n * @returns - The Texture that was removed\n */\n static removeFromCache(texture: string | Texture): Texture | null\n {\n if (typeof texture === 'string')\n {\n const textureFromCache = TextureCache[texture];\n\n if (textureFromCache)\n {\n const index = textureFromCache.textureCacheIds.indexOf(texture);\n\n if (index > -1)\n {\n textureFromCache.textureCacheIds.splice(index, 1);\n }\n\n delete TextureCache[texture];\n\n return textureFromCache;\n }\n }\n else if (texture?.textureCacheIds)\n {\n for (let i = 0; i < texture.textureCacheIds.length; ++i)\n {\n // Check that texture matches the one being passed in before deleting it from the cache.\n if (TextureCache[texture.textureCacheIds[i]] === texture)\n {\n delete TextureCache[texture.textureCacheIds[i]];\n }\n }\n\n texture.textureCacheIds.length = 0;\n\n return texture;\n }\n\n return null;\n }\n\n /**\n * Returns resolution of baseTexture\n * @readonly\n */\n get resolution(): number\n {\n return this.baseTexture.resolution;\n }\n\n /**\n * The frame specifies the region of the base texture that this texture uses.\n * Please call `updateUvs()` after you change coordinates of `frame` manually.\n */\n get frame(): Rectangle\n {\n return this._frame;\n }\n\n set frame(frame: Rectangle)\n {\n this._frame = frame;\n\n this.noFrame = false;\n\n const { x, y, width, height } = frame;\n const xNotFit = x + width > this.baseTexture.width;\n const yNotFit = y + height > this.baseTexture.height;\n\n if (xNotFit || yNotFit)\n {\n const relationship = xNotFit && yNotFit ? 'and' : 'or';\n const errorX = `X: ${x} + ${width} = ${x + width} > ${this.baseTexture.width}`;\n const errorY = `Y: ${y} + ${height} = ${y + height} > ${this.baseTexture.height}`;\n\n throw new Error('Texture Error: frame does not fit inside the base Texture dimensions: '\n + `${errorX} ${relationship} ${errorY}`);\n }\n\n this.valid = width && height && this.baseTexture.valid;\n\n if (!this.trim && !this.rotate)\n {\n this.orig = frame;\n }\n\n if (this.valid)\n {\n this.updateUvs();\n }\n }\n\n /**\n * Indicates whether the texture is rotated inside the atlas\n * set to 2 to compensate for texture packer rotation\n * set to 6 to compensate for spine packer rotation\n * can be used to rotate or mirror sprites\n * See {@link PIXI.groupD8} for explanation\n */\n get rotate(): number\n {\n return this._rotate;\n }\n\n set rotate(rotate: number)\n {\n this._rotate = rotate;\n if (this.valid)\n {\n this.updateUvs();\n }\n }\n\n /** The width of the Texture in pixels. */\n get width(): number\n {\n return this.orig.width;\n }\n\n /** The height of the Texture in pixels. */\n get height(): number\n {\n return this.orig.height;\n }\n\n /** Utility function for BaseTexture|Texture cast. */\n castToBaseTexture(): BaseTexture\n {\n return this.baseTexture;\n }\n\n private static _EMPTY: Texture<Resource>;\n private static _WHITE: Texture<CanvasResource>;\n\n /** An empty texture, used often to not have to create multiple empty textures. Can not be destroyed. */\n public static get EMPTY(): Texture<Resource>\n {\n if (!Texture._EMPTY)\n {\n Texture._EMPTY = new Texture(new BaseTexture());\n removeAllHandlers(Texture._EMPTY);\n removeAllHandlers(Texture._EMPTY.baseTexture);\n }\n\n return Texture._EMPTY;\n }\n\n /** A white texture of 16x16 size, used for graphics and other things Can not be destroyed. */\n public static get WHITE(): Texture<CanvasResource>\n {\n if (!Texture._WHITE)\n {\n const canvas = settings.ADAPTER.createCanvas(16, 16);\n const context = canvas.getContext('2d');\n\n canvas.width = 16;\n canvas.height = 16;\n context.fillStyle = 'white';\n context.fillRect(0, 0, 16, 16);\n\n Texture._WHITE = new Texture(BaseTexture.from(canvas));\n removeAllHandlers(Texture._WHITE);\n removeAllHandlers(Texture._WHITE.baseTexture);\n }\n\n return Texture._WHITE;\n }\n}\n\n"],"names":["TextureUvs","EventEmitter","Rectangle","Point","TextureCache","settings","BaseTexture","uid","getResolutionOfUrl","ImageResource"],"mappings":"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"}
\No newline at end of file