UNPKG

@pixi/core

Version:
318 lines (317 loc) 14.6 kB
import { SCALE_MODES, ALPHA_MODES, FORMATS, TYPES, MIPMAP_MODES, WRAP_MODES, TARGETS } from "@pixi/constants"; import { settings } from "@pixi/settings"; import { EventEmitter, uid, isPow2, BaseTextureCache, TextureCache } from "@pixi/utils"; import { autoDetectResource } from "./resources/autoDetectResource.mjs"; import { BufferResource } from "./resources/BufferResource.mjs"; import { Resource } from "./resources/Resource.mjs"; const defaultBufferOptions = { scaleMode: SCALE_MODES.NEAREST, alphaMode: ALPHA_MODES.NPM }, _BaseTexture = class _BaseTexture2 extends EventEmitter { /** * @param {PIXI.Resource|PIXI.ImageSource|string} [resource=null] - * The current resource to use, for things that aren't Resource objects, will be converted * into a Resource. * @param options - Collection of options, default options inherited from {@link PIXI.BaseTexture.defaultOptions}. * @param {PIXI.MIPMAP_MODES} [options.mipmap] - If mipmapping is enabled for texture * @param {number} [options.anisotropicLevel] - Anisotropic filtering level of texture * @param {PIXI.WRAP_MODES} [options.wrapMode] - Wrap mode for textures * @param {PIXI.SCALE_MODES} [options.scaleMode] - Default scale mode, linear, nearest * @param {PIXI.FORMATS} [options.format] - GL format type * @param {PIXI.TYPES} [options.type] - GL data type * @param {PIXI.TARGETS} [options.target] - GL texture target * @param {PIXI.ALPHA_MODES} [options.alphaMode] - Pre multiply the image alpha * @param {number} [options.width=0] - Width of the texture * @param {number} [options.height=0] - Height of the texture * @param {number} [options.resolution=PIXI.settings.RESOLUTION] - Resolution of the base texture * @param {object} [options.resourceOptions] - Optional resource options, * see {@link PIXI.autoDetectResource autoDetectResource} */ constructor(resource = null, options = null) { super(), options = Object.assign({}, _BaseTexture2.defaultOptions, options); const { alphaMode, mipmap, anisotropicLevel, scaleMode, width, height, wrapMode, format, type, target, resolution, resourceOptions } = options; resource && !(resource instanceof Resource) && (resource = autoDetectResource(resource, resourceOptions), resource.internal = !0), this.resolution = resolution || settings.RESOLUTION, this.width = Math.round((width || 0) * this.resolution) / this.resolution, this.height = Math.round((height || 0) * this.resolution) / this.resolution, this._mipmap = mipmap, this.anisotropicLevel = anisotropicLevel, this._wrapMode = wrapMode, this._scaleMode = scaleMode, this.format = format, this.type = type, this.target = target, this.alphaMode = alphaMode, this.uid = uid(), this.touched = 0, this.isPowerOfTwo = !1, this._refreshPOT(), this._glTextures = {}, this.dirtyId = 0, this.dirtyStyleId = 0, this.cacheId = null, this.valid = width > 0 && height > 0, this.textureCacheIds = [], this.destroyed = !1, this.resource = null, this._batchEnabled = 0, this._batchLocation = 0, this.parentTextureArray = null, this.setResource(resource); } /** * Pixel width of the source of this texture * @readonly */ get realWidth() { return Math.round(this.width * this.resolution); } /** * Pixel height of the source of this texture * @readonly */ get realHeight() { return Math.round(this.height * this.resolution); } /** * Mipmap mode of the texture, affects downscaled images * @default PIXI.MIPMAP_MODES.POW2 */ get mipmap() { return this._mipmap; } set mipmap(value) { this._mipmap !== value && (this._mipmap = value, this.dirtyStyleId++); } /** * The scale mode to apply when scaling this texture * @default PIXI.SCALE_MODES.LINEAR */ get scaleMode() { return this._scaleMode; } set scaleMode(value) { this._scaleMode !== value && (this._scaleMode = value, this.dirtyStyleId++); } /** * How the texture wraps * @default PIXI.WRAP_MODES.CLAMP */ get wrapMode() { return this._wrapMode; } set wrapMode(value) { this._wrapMode !== value && (this._wrapMode = value, this.dirtyStyleId++); } /** * Changes style options of BaseTexture * @param scaleMode - Pixi scalemode * @param mipmap - enable mipmaps * @returns - this */ setStyle(scaleMode, mipmap) { let dirty; return scaleMode !== void 0 && scaleMode !== this.scaleMode && (this.scaleMode = scaleMode, dirty = !0), mipmap !== void 0 && mipmap !== this.mipmap && (this.mipmap = mipmap, dirty = !0), dirty && this.dirtyStyleId++, this; } /** * Changes w/h/resolution. Texture becomes valid if width and height are greater than zero. * @param desiredWidth - Desired visual width * @param desiredHeight - Desired visual height * @param resolution - Optionally set resolution * @returns - this */ setSize(desiredWidth, desiredHeight, resolution) { return resolution = resolution || this.resolution, this.setRealSize(desiredWidth * resolution, desiredHeight * resolution, resolution); } /** * Sets real size of baseTexture, preserves current resolution. * @param realWidth - Full rendered width * @param realHeight - Full rendered height * @param resolution - Optionally set resolution * @returns - this */ setRealSize(realWidth, realHeight, resolution) { return this.resolution = resolution || this.resolution, this.width = Math.round(realWidth) / this.resolution, this.height = Math.round(realHeight) / this.resolution, this._refreshPOT(), this.update(), this; } /** * Refresh check for isPowerOfTwo texture based on size * @private */ _refreshPOT() { this.isPowerOfTwo = isPow2(this.realWidth) && isPow2(this.realHeight); } /** * Changes resolution * @param resolution - res * @returns - this */ setResolution(resolution) { const oldResolution = this.resolution; return oldResolution === resolution ? this : (this.resolution = resolution, this.valid && (this.width = Math.round(this.width * oldResolution) / resolution, this.height = Math.round(this.height * oldResolution) / resolution, this.emit("update", this)), this._refreshPOT(), this); } /** * Sets the resource if it wasn't set. Throws error if resource already present * @param resource - that is managing this BaseTexture * @returns - this */ setResource(resource) { if (this.resource === resource) return this; if (this.resource) throw new Error("Resource can be set only once"); return resource.bind(this), this.resource = resource, this; } /** Invalidates the object. Texture becomes valid if width and height are greater than zero. */ update() { this.valid ? (this.dirtyId++, this.dirtyStyleId++, this.emit("update", this)) : this.width > 0 && this.height > 0 && (this.valid = !0, this.emit("loaded", this), this.emit("update", this)); } /** * Handle errors with resources. * @private * @param event - Error event emitted. */ onError(event) { this.emit("error", this, event); } /** * Destroys this base texture. * The method stops if resource doesn't want this texture to be destroyed. * Removes texture from all caches. * @fires PIXI.BaseTexture#destroyed */ destroy() { this.resource && (this.resource.unbind(this), this.resource.internal && this.resource.destroy(), this.resource = null), this.cacheId && (delete BaseTextureCache[this.cacheId], delete TextureCache[this.cacheId], this.cacheId = null), this.valid = !1, this.dispose(), _BaseTexture2.removeFromCache(this), this.textureCacheIds = null, this.destroyed = !0, this.emit("destroyed", this), this.removeAllListeners(); } /** * Frees the texture from WebGL memory without destroying this texture object. * This means you can still use the texture later which will upload it to GPU * memory again. * @fires PIXI.BaseTexture#dispose */ dispose() { this.emit("dispose", this); } /** Utility function for BaseTexture|Texture cast. */ castToBaseTexture() { return this; } /** * Helper function that creates a base texture based on the source you provide. * The source can be - image url, image element, canvas element. If the * source is an image url or an image element and not in the base texture * cache, it will be created and loaded. * @static * @param {PIXI.ImageSource|string|string[]} source - The * source to create base texture from. * @param options - See {@link PIXI.BaseTexture}'s constructor for options. * @param {string} [options.pixiIdPrefix=pixiid] - If a source has no id, this is the prefix of the generated id * @param {boolean} [strict] - Enforce strict-mode, see {@link PIXI.settings.STRICT_TEXTURE_CACHE}. * @returns {PIXI.BaseTexture} The new base texture. */ static from(source, options, strict = settings.STRICT_TEXTURE_CACHE) { const isFrame = typeof source == "string"; let cacheId = null; if (isFrame) cacheId = source; else { if (!source._pixiId) { const prefix = options?.pixiIdPrefix || "pixiid"; source._pixiId = `${prefix}_${uid()}`; } cacheId = source._pixiId; } let baseTexture = BaseTextureCache[cacheId]; if (isFrame && strict && !baseTexture) throw new Error(`The cacheId "${cacheId}" does not exist in BaseTextureCache.`); return baseTexture || (baseTexture = new _BaseTexture2(source, options), baseTexture.cacheId = cacheId, _BaseTexture2.addToCache(baseTexture, cacheId)), baseTexture; } /** * Create a new Texture with a BufferResource from a typed array. * @param buffer - The optional array to use. If no data is provided, a new Float32Array is created. * @param width - Width of the resource * @param height - Height of the resource * @param options - See {@link PIXI.BaseTexture}'s constructor for options. * Default properties are different from the constructor's defaults. * @param {PIXI.FORMATS} [options.format] - The format is not given, the type is inferred from the * type of the buffer: `RGBA` if Float32Array, Int8Array, Uint8Array, or Uint8ClampedArray, * otherwise `RGBA_INTEGER`. * @param {PIXI.TYPES} [options.type] - The type is not given, the type is inferred from the * type of the buffer. Maps Float32Array to `FLOAT`, Int32Array to `INT`, Uint32Array to * `UNSIGNED_INT`, Int16Array to `SHORT`, Uint16Array to `UNSIGNED_SHORT`, Int8Array to `BYTE`, * Uint8Array/Uint8ClampedArray to `UNSIGNED_BYTE`. * @param {PIXI.ALPHA_MODES} [options.alphaMode=PIXI.ALPHA_MODES.NPM] * @param {PIXI.SCALE_MODES} [options.scaleMode=PIXI.SCALE_MODES.NEAREST] * @returns - The resulting new BaseTexture */ static fromBuffer(buffer, width, height, options) { buffer = buffer || new Float32Array(width * height * 4); const resource = new BufferResource(buffer, { width, height, ...options?.resourceOptions }); let format, type; return buffer instanceof Float32Array ? (format = FORMATS.RGBA, type = TYPES.FLOAT) : buffer instanceof Int32Array ? (format = FORMATS.RGBA_INTEGER, type = TYPES.INT) : buffer instanceof Uint32Array ? (format = FORMATS.RGBA_INTEGER, type = TYPES.UNSIGNED_INT) : buffer instanceof Int16Array ? (format = FORMATS.RGBA_INTEGER, type = TYPES.SHORT) : buffer instanceof Uint16Array ? (format = FORMATS.RGBA_INTEGER, type = TYPES.UNSIGNED_SHORT) : buffer instanceof Int8Array ? (format = FORMATS.RGBA, type = TYPES.BYTE) : (format = FORMATS.RGBA, type = TYPES.UNSIGNED_BYTE), resource.internal = !0, new _BaseTexture2(resource, Object.assign({}, defaultBufferOptions, { type, format }, options)); } /** * Adds a BaseTexture to the global BaseTextureCache. This cache is shared across the whole PIXI object. * @param {PIXI.BaseTexture} baseTexture - The BaseTexture to add to the cache. * @param {string} id - The id that the BaseTexture will be stored against. */ static addToCache(baseTexture, id) { id && (baseTexture.textureCacheIds.includes(id) || baseTexture.textureCacheIds.push(id), BaseTextureCache[id] && BaseTextureCache[id] !== baseTexture && console.warn(`BaseTexture added to the cache with an id [${id}] that already had an entry`), BaseTextureCache[id] = baseTexture); } /** * Remove a BaseTexture from the global BaseTextureCache. * @param {string|PIXI.BaseTexture} baseTexture - id of a BaseTexture to be removed, or a BaseTexture instance itself. * @returns {PIXI.BaseTexture|null} The BaseTexture that was removed. */ static removeFromCache(baseTexture) { if (typeof baseTexture == "string") { const baseTextureFromCache = BaseTextureCache[baseTexture]; if (baseTextureFromCache) { const index = baseTextureFromCache.textureCacheIds.indexOf(baseTexture); return index > -1 && baseTextureFromCache.textureCacheIds.splice(index, 1), delete BaseTextureCache[baseTexture], baseTextureFromCache; } } else if (baseTexture?.textureCacheIds) { for (let i = 0; i < baseTexture.textureCacheIds.length; ++i) delete BaseTextureCache[baseTexture.textureCacheIds[i]]; return baseTexture.textureCacheIds.length = 0, baseTexture; } return null; } }; _BaseTexture.defaultOptions = { /** * If mipmapping is enabled for texture. * @type {PIXI.MIPMAP_MODES} * @default PIXI.MIPMAP_MODES.POW2 */ mipmap: MIPMAP_MODES.POW2, /** Anisotropic filtering level of texture */ anisotropicLevel: 0, /** * Default scale mode, linear, nearest. * @type {PIXI.SCALE_MODES} * @default PIXI.SCALE_MODES.LINEAR */ scaleMode: SCALE_MODES.LINEAR, /** * Wrap mode for textures. * @type {PIXI.WRAP_MODES} * @default PIXI.WRAP_MODES.CLAMP */ wrapMode: WRAP_MODES.CLAMP, /** * Pre multiply the image alpha * @type {PIXI.ALPHA_MODES} * @default PIXI.ALPHA_MODES.UNPACK */ alphaMode: ALPHA_MODES.UNPACK, /** * GL texture target * @type {PIXI.TARGETS} * @default PIXI.TARGETS.TEXTURE_2D */ target: TARGETS.TEXTURE_2D, /** * GL format type * @type {PIXI.FORMATS} * @default PIXI.FORMATS.RGBA */ format: FORMATS.RGBA, /** * GL data type * @type {PIXI.TYPES} * @default PIXI.TYPES.UNSIGNED_BYTE */ type: TYPES.UNSIGNED_BYTE }, /** Global number of the texture batch, used by multi-texture renderers. */ _BaseTexture._globalBatch = 0; let BaseTexture = _BaseTexture; export { BaseTexture }; //# sourceMappingURL=BaseTexture.mjs.map