/*! * @pixi/basis - v7.4.2 * Compiled Wed, 20 Mar 2024 19:55:28 UTC * * @pixi/basis is licensed under the MIT License. * http://www.opensource.org/licenses/mit-license */ this.PIXI = this.PIXI || {}; var _pixi_basis = function(exports, compressedTextures, core, assets) { "use strict"; var BASIS_FORMATS = /* @__PURE__ */ ((BASIS_FORMATS2) => (BASIS_FORMATS2[BASIS_FORMATS2.cTFETC1 = 0] = "cTFETC1", BASIS_FORMATS2[BASIS_FORMATS2.cTFETC2 = 1] = "cTFETC2", BASIS_FORMATS2[BASIS_FORMATS2.cTFBC1 = 2] = "cTFBC1", BASIS_FORMATS2[BASIS_FORMATS2.cTFBC3 = 3] = "cTFBC3", BASIS_FORMATS2[BASIS_FORMATS2.cTFBC4 = 4] = "cTFBC4", BASIS_FORMATS2[BASIS_FORMATS2.cTFBC5 = 5] = "cTFBC5", BASIS_FORMATS2[BASIS_FORMATS2.cTFBC7 = 6] = "cTFBC7", BASIS_FORMATS2[BASIS_FORMATS2.cTFPVRTC1_4_RGB = 8] = "cTFPVRTC1_4_RGB", BASIS_FORMATS2[BASIS_FORMATS2.cTFPVRTC1_4_RGBA = 9] = "cTFPVRTC1_4_RGBA", BASIS_FORMATS2[BASIS_FORMATS2.cTFASTC_4x4 = 10] = "cTFASTC_4x4", BASIS_FORMATS2[BASIS_FORMATS2.cTFATC_RGB = 11] = "cTFATC_RGB", BASIS_FORMATS2[BASIS_FORMATS2.cTFATC_RGBA_INTERPOLATED_ALPHA = 12] = "cTFATC_RGBA_INTERPOLATED_ALPHA", BASIS_FORMATS2[BASIS_FORMATS2.cTFRGBA32 = 13] = "cTFRGBA32", BASIS_FORMATS2[BASIS_FORMATS2.cTFRGB565 = 14] = "cTFRGB565", BASIS_FORMATS2[BASIS_FORMATS2.cTFBGR565 = 15] = "cTFBGR565", BASIS_FORMATS2[BASIS_FORMATS2.cTFRGBA4444 = 16] = "cTFRGBA4444", BASIS_FORMATS2))(BASIS_FORMATS || {}); const BASIS_FORMAT_TO_INTERNAL_FORMAT = { 0: compressedTextures.INTERNAL_FORMATS.COMPRESSED_RGB_ETC1_WEBGL, 2: compressedTextures.INTERNAL_FORMATS.COMPRESSED_RGB_S3TC_DXT1_EXT, 3: compressedTextures.INTERNAL_FORMATS.COMPRESSED_RGBA_S3TC_DXT5_EXT, 8: compressedTextures.INTERNAL_FORMATS.COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 9: compressedTextures.INTERNAL_FORMATS.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 11: compressedTextures.INTERNAL_FORMATS.COMPRESSED_RGB_ATC_WEBGL, 10: compressedTextures.INTERNAL_FORMATS.COMPRESSED_RGBA_ASTC_4x4_KHR, 6: compressedTextures.INTERNAL_FORMATS.COMPRESSED_RGBA_BPTC_UNORM_EXT }, BASIS_FORMAT_TO_TYPE = { 13: core.TYPES.UNSIGNED_BYTE, 14: core.TYPES.UNSIGNED_SHORT_5_6_5, 16: core.TYPES.UNSIGNED_SHORT_4_4_4_4 }, INTERNAL_FORMAT_TO_BASIS_FORMAT = Object.keys(BASIS_FORMAT_TO_INTERNAL_FORMAT).map((key) => Number(key)).reduce((reverseMap, basisFormat) => (reverseMap[BASIS_FORMAT_TO_INTERNAL_FORMAT[basisFormat]] = basisFormat, reverseMap), {}), BASIS_FORMATS_ALPHA = { 3: !0, 9: !0, 10: !0, 6: !0 }; function TranscoderWorkerWrapper() { let basisBinding; const messageHandlers = { init: (message) => self.BASIS ? (self.BASIS({ wasmBinary: message.wasmSource }).then((basisLibrary) => { basisLibrary.initializeBasis(), basisBinding = basisLibrary, self.postMessage({ type: "init", success: !0 }); }), null) : (console.warn("jsSource was not prepended?"), { type: "init", success: !1 }), transcode(message) { const basisData = message.basisData, BASIS = basisBinding, data = basisData, basisFile = new BASIS.BasisFile(data), imageCount = basisFile.getNumImages(), basisFormat = basisFile.getHasAlpha() ? message.rgbaFormat : message.rgbFormat, basisFallbackFormat = 14, imageArray = new Array(imageCount); let fallbackMode = !1; if (!basisFile.startTranscoding()) return basisFile.close(), basisFile.delete(), { type: "transcode", requestID: message.requestID, success: !1, imageArray: null }; for (let i = 0; i < imageCount; i++) { const levels = basisFile.getNumLevels(i), imageResource = { imageID: i, levelArray: new Array(), width: null, height: null }; for (let j = 0; j < levels; j++) { const format = fallbackMode ? basisFallbackFormat : basisFormat, width = basisFile.getImageWidth(i, j), height = basisFile.getImageHeight(i, j), byteSize = basisFile.getImageTranscodedSizeInBytes(i, j, format), alignedWidth = width + 3 & -4, alignedHeight = height + 3 & -4; j === 0 && (imageResource.width = alignedWidth, imageResource.height = alignedHeight); const imageBuffer = new Uint8Array(byteSize); if (!basisFile.transcodeImage(imageBuffer, i, j, format, !1, !1)) { if (fallbackMode) return console.error(`Basis failed to transcode image ${i}, level ${j}!`), { type: "transcode", requestID: message.requestID, success: !1 }; console.warn(`Basis failed to transcode image ${i}, level ${j}! Retrying to an uncompressed texture format!`), i = -1, fallbackMode = !0; break; } imageResource.levelArray.push({ levelID: j, levelWidth: width, levelHeight: height, levelBuffer: imageBuffer }); } imageArray[i] = imageResource; } return basisFile.close(), basisFile.delete(), { type: "transcode", requestID: message.requestID, success: !0, basisFormat: fallbackMode ? basisFallbackFormat : basisFormat, imageArray }; } }; self.onmessage = (e) => { const msg = e.data, response = messageHandlers[msg.type](msg); response && self.postMessage(response); }; } const _TranscoderWorker = class _TranscoderWorker2 { constructor() { this.requests = {}, this.onMessage = (e) => { const data = e.data; if (data.type === "init") { if (!data.success) throw new Error("BasisResource.TranscoderWorker failed to initialize."); this.isInit = !0, this.onInit(); } else if (data.type === "transcode") { --this.load; const requestID = data.requestID; data.success ? this.requests[requestID].resolve(data) : this.requests[requestID].reject(), delete this.requests[requestID]; } }, this.isInit = !1, this.load = 0, this.initPromise = new Promise((resolve) => { this.onInit = resolve; }), _TranscoderWorker2.wasmSource || console.warn("resources.BasisResource.TranscoderWorker has not been given the transcoder WASM binary!"), this.worker = new Worker(_TranscoderWorker2.workerURL), this.worker.onmessage = this.onMessage, this.worker.postMessage({ type: "init", jsSource: _TranscoderWorker2.jsSource, wasmSource: _TranscoderWorker2.wasmSource }); } /** Generated URL for the transcoder worker script. */ static get workerURL() { if (!_TranscoderWorker2._workerURL) { let workerSource = TranscoderWorkerWrapper.toString(); const beginIndex = workerSource.indexOf("{"), endIndex = workerSource.lastIndexOf("}"); workerSource = workerSource.slice(beginIndex + 1, endIndex), _TranscoderWorker2.jsSource && (workerSource = `${_TranscoderWorker2.jsSource} ${workerSource}`), _TranscoderWorker2._workerURL = URL.createObjectURL(new Blob([workerSource])); } return _TranscoderWorker2._workerURL; } /** @returns a promise that is resolved when the web-worker is initialized */ initAsync() { return this.initPromise; } /** * Creates a promise that will resolve when the transcoding of a *.basis file is complete. * @param basisData - *.basis file contents * @param rgbaFormat - transcoding format for RGBA files * @param rgbFormat - transcoding format for RGB files * @returns a promise that is resolved with the transcoding response of the web-worker */ async transcodeAsync(basisData, rgbaFormat, rgbFormat) { ++this.load; const requestID = _TranscoderWorker2._tempID++, requestPromise = new Promise((resolve, reject) => { this.requests[requestID] = { resolve, reject }; }); return this.worker.postMessage({ requestID, basisData, rgbaFormat, rgbFormat, type: "transcode" }), requestPromise; } /** * Loads the transcoder source code * @param jsURL - URL to the javascript basis transcoder * @param wasmURL - URL to the wasm basis transcoder * @returns A promise that resolves when both the js and wasm transcoders have been loaded. */ static loadTranscoder(jsURL, wasmURL) { const jsPromise = fetch(jsURL).then((res) => res.text()).then((text) => { _TranscoderWorker2.jsSource = text; }), wasmPromise = fetch(wasmURL).then((res) => res.arrayBuffer()).then((arrayBuffer) => { _TranscoderWorker2.wasmSource = arrayBuffer; }); return Promise.all([jsPromise, wasmPromise]).then((data) => (this._onTranscoderInitializedResolve(), data)); } /** * Set the transcoder source code directly * @param jsSource - source for the javascript basis transcoder * @param wasmSource - source for the wasm basis transcoder */ static setTranscoder(jsSource, wasmSource) { _TranscoderWorker2.jsSource = jsSource, _TranscoderWorker2.wasmSource = wasmSource; } }; _TranscoderWorker.onTranscoderInitialized = new Promise((resolve) => { _TranscoderWorker._onTranscoderInitializedResolve = resolve; }), _TranscoderWorker._tempID = 0; let TranscoderWorker = _TranscoderWorker; const _BasisParser = class _BasisParser2 { /** * Runs transcoding and populates imageArray. It will run the transcoding in a web worker * if they are available. * @private */ static async transcode(arrayBuffer) { let resources; return typeof Worker != "undefined" && _BasisParser2.TranscoderWorker.wasmSource ? resources = await _BasisParser2.transcodeAsync(arrayBuffer) : resources = _BasisParser2.transcodeSync(arrayBuffer), resources; } /** * Finds a suitable worker for transcoding and sends a transcoding request * @private * @async */ static async transcodeAsync(arrayBuffer) { !_BasisParser2.defaultRGBAFormat && !_BasisParser2.defaultRGBFormat && _BasisParser2.autoDetectFormats(); const workerPool = _BasisParser2.workerPool; let leastLoad = 268435456, worker = null; for (let i = 0, j = workerPool.length; i < j; i++) workerPool[i].load < leastLoad && (worker = workerPool[i], leastLoad = worker.load); worker || (worker = new TranscoderWorker(), workerPool.push(worker)), await worker.initAsync(); const response = await worker.transcodeAsync( new Uint8Array(arrayBuffer), _BasisParser2.defaultRGBAFormat.basisFormat, _BasisParser2.defaultRGBFormat.basisFormat ), basisFormat = response.basisFormat, imageArray = response.imageArray, fallbackMode = basisFormat > 12; let imageResources; if (fallbackMode) imageResources = imageArray.map( (image) => new core.BufferResource( new Uint16Array(image.levelArray[0].levelBuffer.buffer), { width: image.width, height: image.height } ) ); else { const format = BASIS_FORMAT_TO_INTERNAL_FORMAT[response.basisFormat]; imageResources = new Array(imageArray.length); for (let i = 0, j = imageArray.length; i < j; i++) imageResources[i] = new compressedTextures.CompressedTextureResource(null, { format, width: imageArray[i].width, height: imageArray[i].height, levelBuffers: imageArray[i].levelArray, levels: imageArray[i].levelArray.length }); } return imageResources.basisFormat = basisFormat, imageResources; } /** * Runs transcoding on the main thread. * @private */ static transcodeSync(arrayBuffer) { !_BasisParser2.defaultRGBAFormat && !_BasisParser2.defaultRGBFormat && _BasisParser2.autoDetectFormats(); const BASIS = _BasisParser2.basisBinding, data = new Uint8Array(arrayBuffer), basisFile = new BASIS.BasisFile(data), imageCount = basisFile.getNumImages(), basisFormat = basisFile.getHasAlpha() ? _BasisParser2.defaultRGBAFormat.basisFormat : _BasisParser2.defaultRGBFormat.basisFormat, basisFallbackFormat = BASIS_FORMATS.cTFRGB565, imageResources = new Array(imageCount); let fallbackMode = _BasisParser2.fallbackMode; if (!basisFile.startTranscoding()) return console.error("Basis failed to start transcoding!"), basisFile.close(), basisFile.delete(), null; for (let i = 0; i < imageCount; i++) { const levels = fallbackMode ? 1 : basisFile.getNumLevels(i), width = basisFile.getImageWidth(i, 0), height = basisFile.getImageHeight(i, 0), alignedWidth = width + 3 & -4, alignedHeight = height + 3 & -4, imageLevels = new Array(levels); for (let j = 0; j < levels; j++) { const levelWidth = basisFile.getImageWidth(i, j), levelHeight = basisFile.getImageHeight(i, j), byteSize = basisFile.getImageTranscodedSizeInBytes( i, 0, fallbackMode ? basisFallbackFormat : basisFormat ); if (imageLevels[j] = { levelID: j, levelBuffer: new Uint8Array(byteSize), levelWidth, levelHeight }, !basisFile.transcodeImage( imageLevels[j].levelBuffer, i, 0, fallbackMode ? basisFallbackFormat : basisFormat, !1, !1 )) if (fallbackMode) { console.error(`Basis failed to transcode image ${i}, level 0!`); break; } else { i = -1, fallbackMode = !0, console.warn(`Basis failed to transcode image ${i}, level 0 to a compressed texture format. Retrying to an uncompressed fallback format!`); continue; } } let imageResource; fallbackMode ? imageResource = new core.BufferResource( new Uint16Array(imageLevels[0].levelBuffer.buffer), { width, height } ) : imageResource = new compressedTextures.CompressedTextureResource(null, { format: BASIS_FORMAT_TO_INTERNAL_FORMAT[basisFormat], width: alignedWidth, height: alignedHeight, levelBuffers: imageLevels, levels }), imageResources[i] = imageResource; } basisFile.close(), basisFile.delete(); const transcodedResources = imageResources; return transcodedResources.basisFormat = fallbackMode ? basisFallbackFormat : basisFormat, transcodedResources; } /** * Detects the available compressed texture formats on the device. * @param extensions - extensions provided by a WebGL context * @ignore */ static autoDetectFormats(extensions) { if (!extensions) { const gl = core.settings.ADAPTER.createCanvas().getContext("webgl"); if (!gl) { console.error("WebGL not available for BASIS transcoding. Silently failing."); return; } extensions = { bptc: gl.getExtension("EXT_texture_compression_bptc"), astc: gl.getExtension("WEBGL_compressed_texture_astc"), etc: gl.getExtension("WEBGL_compressed_texture_etc"), s3tc: gl.getExtension("WEBGL_compressed_texture_s3tc"), s3tc_sRGB: gl.getExtension("WEBGL_compressed_texture_s3tc_srgb"), /* eslint-disable-line camelcase */ pvrtc: gl.getExtension("WEBGL_compressed_texture_pvrtc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc"), etc1: gl.getExtension("WEBGL_compressed_texture_etc1"), atc: gl.getExtension("WEBGL_compressed_texture_atc") }; } const supportedFormats = {}; for (const key in extensions) { const extension = extensions[key]; extension && Object.assign(supportedFormats, Object.getPrototypeOf(extension)); } for (let i = 0; i < 2; i++) { const detectWithAlpha = !!i; let internalFormat, basisFormat; for (const id in supportedFormats) if (internalFormat = supportedFormats[id], basisFormat = INTERNAL_FORMAT_TO_BASIS_FORMAT[internalFormat], basisFormat !== void 0 && (detectWithAlpha && BASIS_FORMATS_ALPHA[basisFormat] || !detectWithAlpha && !BASIS_FORMATS_ALPHA[basisFormat])) break; internalFormat ? _BasisParser2[detectWithAlpha ? "defaultRGBAFormat" : "defaultRGBFormat"] = { textureFormat: internalFormat, basisFormat } : (_BasisParser2[detectWithAlpha ? "defaultRGBAFormat" : "defaultRGBFormat"] = { textureFormat: core.TYPES.UNSIGNED_SHORT_5_6_5, basisFormat: BASIS_FORMATS.cTFRGB565 }, _BasisParser2.fallbackMode = !0); } } /** * Binds the basis_universal transcoder to decompress *.basis files. You must initialize the transcoder library yourself. * @example * import { BasisParser } from '@pixi/basis'; * * // BASIS() returns a Promise-like object * globalThis.BASIS().then((basisLibrary) => * { * // Initialize basis-library; otherwise, transcoded results maybe corrupt! * basisLibrary.initializeBasis(); * * // Bind BasisParser to the transcoder * BasisParser.bindTranscoder(basisLibrary); * }); * @param basisLibrary - the initialized transcoder library * @private */ static bindTranscoder(basisLibrary) { _BasisParser2.basisBinding = basisLibrary; } /** * Loads the transcoder source code for use in {@link PIXI.BasisParser.TranscoderWorker}. * @private * @param jsURL - URL to the javascript basis transcoder * @param wasmURL - URL to the wasm basis transcoder */ static loadTranscoder(jsURL, wasmURL) { return _BasisParser2.TranscoderWorker.loadTranscoder(jsURL, wasmURL); } /** * Set the transcoder source code directly * @private * @param jsSource - source for the javascript basis transcoder * @param wasmSource - source for the wasm basis transcoder */ static setTranscoder(jsSource, wasmSource) { _BasisParser2.TranscoderWorker.setTranscoder(jsSource, wasmSource); } static get TRANSCODER_WORKER_POOL_LIMIT() { return this.workerPool.length || 1; } static set TRANSCODER_WORKER_POOL_LIMIT(limit) { for (let i = this.workerPool.length; i < limit; i++) this.workerPool[i] = new TranscoderWorker(), this.workerPool[i].initAsync(); } }; _BasisParser.fallbackMode = !1, _BasisParser.workerPool = [], _BasisParser.TranscoderWorker = TranscoderWorker; let BasisParser = _BasisParser; const detectBasis = { extension: { type: core.ExtensionType.DetectionParser, priority: 3 }, test: async () => !!(BasisParser.basisBinding && BasisParser.TranscoderWorker.wasmSource), add: async (formats) => [...formats, "basis"], remove: async (formats) => formats.filter((f) => f !== "basis") }; core.extensions.add(detectBasis); var __defProp = Object.defineProperty, __getOwnPropSymbols = Object.getOwnPropertySymbols, __hasOwnProp = Object.prototype.hasOwnProperty, __propIsEnum = Object.prototype.propertyIsEnumerable, __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues = (a, b) => { for (var prop in b || (b = {})) __hasOwnProp.call(b, prop) && __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) __propIsEnum.call(b, prop) && __defNormalProp(a, prop, b[prop]); return a; }; const loadBasis = { extension: { type: core.ExtensionType.LoadParser, priority: assets.LoaderParserPriority.High }, name: "loadBasis", test(url) { return assets.checkExtension(url, ".basis"); }, async load(url, asset, loader) { await TranscoderWorker.onTranscoderInitialized; const arrayBuffer = await (await core.settings.ADAPTER.fetch(url)).arrayBuffer(), resources = await BasisParser.transcode(arrayBuffer), type = BASIS_FORMAT_TO_TYPE[resources.basisFormat], format = resources.basisFormat !== BASIS_FORMATS.cTFRGBA32 ? core.FORMATS.RGB : core.FORMATS.RGBA, textures = resources.map((resource) => { const base = new core.BaseTexture(resource, __spreadValues({ mipmap: resource instanceof compressedTextures.CompressedTextureResource && resource.levels > 1 ? core.MIPMAP_MODES.ON_MANUAL : core.MIPMAP_MODES.OFF, alphaMode: core.ALPHA_MODES.NO_PREMULTIPLIED_ALPHA, type, format }, asset.data)); return assets.createTexture(base, loader, url); }); return textures.length === 1 ? textures[0] : textures; }, unload(texture) { Array.isArray(texture) ? texture.forEach((t) => t.destroy(!0)) : texture.destroy(!0); } }; return core.extensions.add(loadBasis), exports.BASIS_FORMATS = BASIS_FORMATS, exports.BASIS_FORMATS_ALPHA = BASIS_FORMATS_ALPHA, exports.BASIS_FORMAT_TO_INTERNAL_FORMAT = BASIS_FORMAT_TO_INTERNAL_FORMAT, exports.BASIS_FORMAT_TO_TYPE = BASIS_FORMAT_TO_TYPE, exports.BasisParser = BasisParser, exports.INTERNAL_FORMAT_TO_BASIS_FORMAT = INTERNAL_FORMAT_TO_BASIS_FORMAT, exports.TranscoderWorker = TranscoderWorker, exports.detectBasis = detectBasis, exports.loadBasis = loadBasis, exports; }({}, PIXI, PIXI, PIXI); Object.assign(this.PIXI, _pixi_basis); //# sourceMappingURL=basis.js.map