{"version":3,"file":"Assets.mjs","sources":["../src/Assets.ts"],"sourcesContent":["import { extensions, ExtensionType, utils } from '@pixi/core';\nimport { BackgroundLoader } from './BackgroundLoader';\nimport { Cache } from './cache/Cache';\nimport { Loader } from './loader/Loader';\nimport { loadTextures } from './loader/parsers';\nimport { Resolver } from './resolver/Resolver';\nimport { convertToList } from './utils/convertToList';\nimport { isSingleItem } from './utils/isSingleItem';\n\nimport type { FormatDetectionParser } from './detections';\nimport type { LoadTextureConfig } from './loader/parsers';\nimport type { BundleIdentifierOptions } from './resolver/Resolver';\nimport type {\n ArrayOr,\n AssetsBundle,\n AssetsManifest,\n AssetSrc,\n LoadParserName,\n ResolvedAsset,\n UnresolvedAsset\n} from './types';\n\nexport type ProgressCallback = (progress: number) => void;\n\n/**\n * Extensible preferences that can be used, for instance, when configuring loaders.\n * @since 7.2.0\n * @memberof PIXI\n */\nexport interface AssetsPreferences extends LoadTextureConfig, GlobalMixins.AssetsPreferences {}\n\n/**\n * Initialization options object for Asset Class.\n * @memberof PIXI\n */\nexport interface AssetInitOptions\n{\n // basic...\n /** a base path for any assets loaded */\n basePath?: string;\n\n /** a default URL parameter string to append to all assets loaded */\n defaultSearchParams?: string | Record;\n\n /**\n * a manifest to tell the asset loader upfront what all your assets are\n * this can be the manifest object itself, or a URL to the manifest.\n */\n manifest?: string | AssetsManifest;\n /**\n * optional preferences for which textures preferences you have when resolving assets\n * for example you might set the resolution to 0.5 if the user is on a rubbish old phone\n * or you might set the resolution to 2 if the user is on a retina display\n */\n texturePreference?: {\n /** the resolution order you prefer, can be an array (priority order - first is prefered) or a single resolutions */\n resolution?: number | number[];\n /**\n * the formats you prefer, by default this will be:\n * ['avif', 'webp', 'png', 'jpg', 'jpeg', 'webm', 'mp4', 'm4v', 'ogv']\n */\n format?: ArrayOr;\n };\n\n /**\n * If true, don't attempt to detect whether browser has preferred formats available.\n * May result in increased performance as it skips detection step.\n */\n skipDetections?: boolean;\n\n /** advanced - override how bundlesIds are generated */\n bundleIdentifier?: BundleIdentifierOptions;\n\n /** Optional loader preferences */\n preferences?: Partial;\n}\n\n/**\n * A one stop shop for all Pixi resource management!\n * Super modern and easy to use, with enough flexibility to customize and do what you need!\n * @memberof PIXI\n * @namespace Assets\n *\n * Only one Asset Class exists accessed via the Global Asset object.\n *\n * It has four main responsibilities:\n * 1. Allows users to map URLs to keys and resolve them according to the user's browser capabilities\n * 2. Loads the resources and transforms them into assets that developers understand.\n * 3. Caches the assets and provides a way to access them.\n * 4. Allow developers to unload assets and clear the cache.\n *\n * It also has a few advanced features:\n * 1. Allows developers to provide a manifest upfront of all assets and help manage them via 'bundles'.\n * 2. Allows users to background load assets. Shortening (or eliminating) load times and improving UX. With this feature,\n * in-game loading bars can be a thing of the past!\n *\n * ### Assets Loading\n *\n * Do not be afraid to load things multiple times - under the hood, it will NEVER load anything more than once.\n *\n * For example:\n *\n * ```js\n * import { Assets } from 'pixi.js';\n *\n * promise1 = Assets.load('bunny.png')\n * promise2 = Assets.load('bunny.png')\n *\n * // promise1 === promise2\n * ```\n *\n * Here both promises will be the same. Once resolved... Forever resolved! It makes for really easy resource management!\n *\n * Out of the box it supports the following files:\n * - textures (avif, webp, png, jpg, gif, svg)\n * - sprite sheets (json)\n * - bitmap fonts (xml, fnt, txt)\n * - web fonts (ttf, woff, woff2)\n * - json files (json)\n * - text files (txt)\n *\n * More types can be added fairly easily by creating additional loader parsers.\n *\n * ### Textures\n * - Textures are loaded as ImageBitmap on a worker thread where possible.\n * Leading to much less janky load + parse times.\n * - By default, we will prefer to load AVIF and WebP image files if you specify them.\n * But if the browser doesn't support AVIF or WebP we will fall back to png and jpg.\n * - Textures can also be accessed via Texture.from(...) and now use this asset manager under the hood!\n * - Don't worry if you set preferences for textures that don't exist (for example you prefer 2x resolutions images\n * but only 1x is available for that texture, the Asset manager will pick that up as a fallback automatically)\n *\n * #### Sprite sheets\n * - It's hard to know what resolution a sprite sheet is without loading it first, to address this\n * there is a naming convention we have added that will let Pixi understand the image format and resolution\n * of the spritesheet via its file name:\n *\n * `my-spritesheet{resolution}.{imageFormat}.json`\n *\n * For example:\n *\n * `my-spritesheet@2x.webp.json` // 2x resolution, WebP sprite sheet\n * `my-spritesheet@0.5x.png.json` // 0.5x resolution, png sprite sheet\n *\n * This is optional! You can just load a sprite sheet as normal.\n * This is only useful if you have a bunch of different res / formatted spritesheets.\n *\n * ### Fonts\n * Web fonts will be loaded with all weights.\n * It is possible to load only specific weights by doing the following:\n *\n * ```js\n * import { Assets } from 'pixi.js';\n *\n * // Load specific weights..\n * await Assets.load({\n * data: {\n * weights: ['normal'], // Only loads the weight\n * },\n * src: `outfit.woff2`,\n * });\n *\n * // Load everything...\n * await Assets.load(`outfit.woff2`);\n * ```\n *\n * ### Background Loading\n * Background loading will load stuff for you passively behind the scenes. To minimize jank,\n * it will only load one asset at a time. As soon as a developer calls `Assets.load(...)` the\n * background loader is paused and requested assets are loaded as a priority.\n * Don't worry if something is in there that's already loaded, it will just get skipped!\n *\n * You still need to call `Assets.load(...)` to get an asset that has been loaded in the background.\n * It's just that this promise will resolve instantly if the asset\n * has already been loaded.\n *\n * ### Manifest and Bundles\n * - Manifest is a JSON file that contains a list of all assets and their properties.\n * - Bundles are a way to group assets together.\n *\n * ```js\n * import { Assets } from 'pixi.js';\n *\n * // Manifest Example\n * const manifest = {\n * bundles: [\n * {\n * name: 'load-screen',\n * assets: [\n * {\n * alias: 'background',\n * src: 'sunset.png',\n * },\n * {\n * alias: 'bar',\n * src: 'load-bar.{png,webp}',\n * },\n * ],\n * },\n * {\n * name: 'game-screen',\n * assets: [\n * {\n * alias: 'character',\n * src: 'robot.png',\n * },\n * {\n * alias: 'enemy',\n * src: 'bad-guy.png',\n * },\n * ],\n * },\n * ]\n * };\n *\n * await Assets.init({ manifest });\n *\n * // Load a bundle...\n * loadScreenAssets = await Assets.loadBundle('load-screen');\n * // Load another bundle...\n * gameScreenAssets = await Assets.loadBundle('game-screen');\n * ```\n * @example\n * import { Assets } from 'pixi.js';\n *\n * const bunny = await Assets.load('bunny.png');\n */\nexport class AssetsClass\n{\n /** the resolver to map various urls */\n public resolver: Resolver;\n /**\n * The loader, loads stuff!\n * @type {PIXI.AssetLoader}\n */\n public loader: Loader;\n /**\n * The global cache of all assets within PixiJS\n * @type {PIXI.Cache}\n */\n public cache: typeof Cache;\n\n /** takes care of loading assets in the background */\n private readonly _backgroundLoader: BackgroundLoader;\n\n private _detections: FormatDetectionParser[] = [];\n\n private _initialized = false;\n\n constructor()\n {\n this.resolver = new Resolver();\n this.loader = new Loader();\n this.cache = Cache;\n\n this._backgroundLoader = new BackgroundLoader(this.loader);\n this._backgroundLoader.active = true;\n\n this.reset();\n }\n\n /**\n * Best practice is to call this function before any loading commences\n * Initiating is the best time to add any customization to the way things are loaded.\n *\n * you do not need to call this for the Asset class to work, only if you want to set any initial properties\n * @param options - options to initialize the Asset manager with\n */\n public async init(options: AssetInitOptions = {}): Promise\n {\n if (this._initialized)\n {\n if (process.env.DEBUG)\n {\n console.warn('[Assets]AssetManager already initialized, did you load before calling this Assets.init()?');\n }\n\n return;\n }\n\n this._initialized = true;\n\n if (options.defaultSearchParams)\n {\n this.resolver.setDefaultSearchParams(options.defaultSearchParams);\n }\n\n if (options.basePath)\n {\n this.resolver.basePath = options.basePath;\n }\n\n if (options.bundleIdentifier)\n {\n this.resolver.setBundleIdentifier(options.bundleIdentifier);\n }\n\n if (options.manifest)\n {\n let manifest = options.manifest;\n\n if (typeof manifest === 'string')\n {\n manifest = await this.load(manifest);\n }\n\n this.resolver.addManifest(manifest);\n }\n\n const resolutionPref = options.texturePreference?.resolution ?? 1;\n const resolution = (typeof resolutionPref === 'number') ? [resolutionPref] : resolutionPref;\n\n const formats = await this._detectFormats({\n preferredFormats: options.texturePreference?.format,\n skipDetections: options.skipDetections,\n detections: this._detections\n });\n\n this.resolver.prefer({\n params: {\n format: formats,\n resolution,\n },\n });\n\n if (options.preferences)\n {\n this.setPreferences(options.preferences);\n }\n }\n\n /** @deprecated */\n public add(a: ArrayOr, s?: string | string[], d?: unknown, f?: string, lp?: LoadParserName): void;\n /**\n * Allows you to specify how to resolve any assets load requests.\n * There are a few ways to add things here as shown below:\n * @example\n * import { Assets } from 'pixi.js';\n *\n * // Simple\n * Assets.add({alias: 'bunnyBooBoo', src: 'bunny.png'});\n * const bunny = await Assets.load('bunnyBooBoo');\n *\n * // Multiple keys:\n * Assets.add({alias: ['burger', 'chicken'], src: 'bunny.png'});\n *\n * const bunny = await Assets.load('burger');\n * const bunny2 = await Assets.load('chicken');\n *\n * // passing options to to the object\n * Assets.add({\n * alias: 'bunnyBooBooSmooth',\n * src: 'bunny{png,webp}',\n * data: { scaleMode: SCALE_MODES.NEAREST }, // Base texture options\n * });\n *\n * // Multiple assets\n *\n * // The following all do the same thing:\n *\n * Assets.add({alias: 'bunnyBooBoo', src: 'bunny{png,webp}'});\n *\n * Assets.add({\n * alias: 'bunnyBooBoo',\n * src: [\n * 'bunny.png',\n * 'bunny.webp',\n * ],\n * });\n *\n * const bunny = await Assets.load('bunnyBooBoo'); // Will try to load WebP if available\n * @param data - the data to add\n * @param data.aliases - the key or keys that you will reference when loading this asset\n * @param data.srcs - the asset or assets that will be chosen from when loading via the specified key\n * @param data.data - asset-specific data that will be passed to the loaders\n * - Useful if you want to initiate loaded objects with specific data\n * @param data.format - the format of the asset\n * @param data.loadParser - the name of the load parser to use\n */\n public add(data:(ArrayOr)): void;\n public add(\n aliases: ArrayOr | ArrayOr,\n srcs?: AssetSrc,\n data?: unknown,\n format?: string,\n loadParser?: LoadParserName\n ): void\n {\n this.resolver.add(aliases as ArrayOr, srcs, data, format, loadParser);\n }\n\n /**\n * Loads your assets! You pass in a key or URL and it will return a promise that\n * resolves to the loaded asset. If multiple assets a requested, it will return a hash of assets.\n *\n * Don't worry about loading things multiple times, behind the scenes assets are only ever loaded\n * once and the same promise reused behind the scenes so you can safely call this function multiple\n * times with the same key and it will always return the same asset.\n * @example\n * import { Assets } from 'pixi.js';\n *\n * // Load a URL:\n * const myImageTexture = await Assets.load('http://some.url.com/image.png'); // => returns a texture\n *\n * Assets.add('thumper', 'bunny.png');\n * Assets.add('chicko', 'chicken.png');\n *\n * // Load multiple assets:\n * const textures = await Assets.load(['thumper', 'chicko']); // => {thumper: Texture, chicko: Texture}\n * @param urls - the urls to load\n * @param onProgress - optional function that is called when progress on asset loading is made.\n * The function is passed a single parameter, `progress`, which represents the percentage\n * (0.0 - 1.0) of the assets loaded.\n * @returns - the assets that were loaded, either a single asset or a hash of assets\n */\n public async load(\n urls: string | UnresolvedAsset,\n onProgress?: ProgressCallback,\n ): Promise;\n public async load(\n urls: string[] | UnresolvedAsset[],\n onProgress?: ProgressCallback,\n ): Promise>;\n public async load(\n urls: ArrayOr | ArrayOr,\n onProgress?: ProgressCallback\n ): Promise>\n {\n if (!this._initialized)\n {\n await this.init();\n }\n\n const singleAsset = isSingleItem(urls);\n\n const urlArray: string[] = convertToList(urls)\n .map((url) =>\n {\n if (typeof url !== 'string')\n {\n const aliases = this.resolver.getAlias(url);\n\n if (aliases.some((alias) => !this.resolver.hasKey(alias)))\n {\n this.add(url);\n }\n\n return Array.isArray(aliases) ? aliases[0] : aliases;\n }\n\n // if it hasn't been added, add it now\n if (!this.resolver.hasKey(url)) this.add({ alias: url, src: url });\n\n return url;\n }) as string[];\n\n // check cache first...\n const resolveResults = this.resolver.resolve(urlArray);\n\n // remap to the keys used..\n const out: Record = await this._mapLoadToResolve(resolveResults, onProgress);\n\n return singleAsset ? out[urlArray[0] as string] : out;\n }\n\n /**\n * This adds a bundle of assets in one go so that you can load them as a group.\n * For example you could add a bundle for each screen in you pixi app\n * @example\n * import { Assets } from 'pixi.js';\n *\n * Assets.addBundle('animals', {\n * bunny: 'bunny.png',\n * chicken: 'chicken.png',\n * thumper: 'thumper.png',\n * });\n *\n * const assets = await Assets.loadBundle('animals');\n * @param bundleId - the id of the bundle to add\n * @param assets - a record of the asset or assets that will be chosen from when loading via the specified key\n */\n public addBundle(bundleId: string, assets: AssetsBundle['assets']): void\n {\n this.resolver.addBundle(bundleId, assets);\n }\n\n /**\n * Bundles are a way to load multiple assets at once.\n * If a manifest has been provided to the init function then you can load a bundle, or bundles.\n * you can also add bundles via `addBundle`\n * @example\n * import { Assets } from 'pixi.js';\n *\n * // Manifest Example\n * const manifest = {\n * bundles: [\n * {\n * name: 'load-screen',\n * assets: [\n * {\n * alias: 'background',\n * src: 'sunset.png',\n * },\n * {\n * alias: 'bar',\n * src: 'load-bar.{png,webp}',\n * },\n * ],\n * },\n * {\n * name: 'game-screen',\n * assets: [\n * {\n * alias: 'character',\n * src: 'robot.png',\n * },\n * {\n * alias: 'enemy',\n * src: 'bad-guy.png',\n * },\n * ],\n * },\n * ]\n * };\n *\n * await Assets.init({ manifest });\n *\n * // Load a bundle...\n * loadScreenAssets = await Assets.loadBundle('load-screen');\n * // Load another bundle...\n * gameScreenAssets = await Assets.loadBundle('game-screen');\n * @param bundleIds - the bundle id or ids to load\n * @param onProgress - Optional function that is called when progress on asset loading is made.\n * The function is passed a single parameter, `progress`, which represents the percentage (0.0 - 1.0)\n * of the assets loaded. Do not use this function to detect when assets are complete and available,\n * instead use the Promise returned by this function.\n * @returns all the bundles assets or a hash of assets for each bundle specified\n */\n public async loadBundle(bundleIds: ArrayOr, onProgress?: ProgressCallback): Promise\n {\n if (!this._initialized)\n {\n await this.init();\n }\n\n let singleAsset = false;\n\n if (typeof bundleIds === 'string')\n {\n singleAsset = true;\n bundleIds = [bundleIds];\n }\n\n const resolveResults = this.resolver.resolveBundle(bundleIds);\n\n const out: Record> = {};\n\n const keys = Object.keys(resolveResults);\n let count = 0;\n let total = 0;\n const _onProgress = () =>\n {\n onProgress?.(++count / total);\n };\n const promises = keys.map((bundleId) =>\n {\n const resolveResult = resolveResults[bundleId];\n\n total += Object.keys(resolveResult).length;\n\n return this._mapLoadToResolve(resolveResult, _onProgress)\n .then((resolveResult) =>\n {\n out[bundleId] = resolveResult;\n });\n });\n\n await Promise.all(promises);\n\n return singleAsset ? out[bundleIds[0]] : out;\n }\n\n /**\n * Initiate a background load of some assets. It will passively begin to load these assets in the background.\n * So when you actually come to loading them you will get a promise that resolves to the loaded assets immediately\n *\n * An example of this might be that you would background load game assets after your inital load.\n * then when you got to actually load your game screen assets when a player goes to the game - the loading\n * would already have stared or may even be complete, saving you having to show an interim load bar.\n * @example\n * import { Assets } from 'pixi.js';\n *\n * Assets.backgroundLoad('bunny.png');\n *\n * // later on in your app...\n * await Assets.loadBundle('bunny.png'); // Will resolve quicker as loading may have completed!\n * @param urls - the url / urls you want to background load\n */\n public async backgroundLoad(urls: ArrayOr): Promise\n {\n if (!this._initialized)\n {\n await this.init();\n }\n\n if (typeof urls === 'string')\n {\n urls = [urls];\n }\n\n const resolveResults = this.resolver.resolve(urls);\n\n this._backgroundLoader.add(Object.values(resolveResults));\n }\n\n /**\n * Initiate a background of a bundle, works exactly like backgroundLoad but for bundles.\n * this can only be used if the loader has been initiated with a manifest\n * @example\n * import { Assets } from 'pixi.js';\n *\n * await Assets.init({\n * manifest: {\n * bundles: [\n * {\n * name: 'load-screen',\n * assets: [...],\n * },\n * ...\n * ],\n * },\n * });\n *\n * Assets.backgroundLoadBundle('load-screen');\n *\n * // Later on in your app...\n * await Assets.loadBundle('load-screen'); // Will resolve quicker as loading may have completed!\n * @param bundleIds - the bundleId / bundleIds you want to background load\n */\n public async backgroundLoadBundle(bundleIds: ArrayOr): Promise\n {\n if (!this._initialized)\n {\n await this.init();\n }\n\n if (typeof bundleIds === 'string')\n {\n bundleIds = [bundleIds];\n }\n\n const resolveResults = this.resolver.resolveBundle(bundleIds);\n\n Object.values(resolveResults).forEach((resolveResult) =>\n {\n this._backgroundLoader.add(Object.values(resolveResult));\n });\n }\n\n /**\n * Only intended for development purposes.\n * This will wipe the resolver and caches.\n * You will need to reinitialize the Asset\n */\n public reset(): void\n {\n this.resolver.reset();\n this.loader.reset();\n this.cache.reset();\n\n this._initialized = false;\n }\n\n /**\n * Instantly gets an asset already loaded from the cache. If the asset has not yet been loaded,\n * it will return undefined. So it's on you! When in doubt just use `Assets.load` instead.\n * (Remember, the loader will never load things more than once!)\n * @param keys - The key or keys for the assets that you want to access\n * @returns - The assets or hash of assets requested\n */\n public get(keys: string): T;\n public get(keys: string[]): Record;\n public get(keys: ArrayOr): T | Record\n {\n if (typeof keys === 'string')\n {\n return Cache.get(keys);\n }\n\n const assets: Record = {};\n\n for (let i = 0; i < keys.length; i++)\n {\n assets[i] = Cache.get(keys[i]);\n }\n\n return assets;\n }\n\n /**\n * helper function to map resolved assets back to loaded assets\n * @param resolveResults - the resolve results from the resolver\n * @param onProgress - the progress callback\n */\n private async _mapLoadToResolve(\n resolveResults: ResolvedAsset | Record,\n onProgress?: ProgressCallback\n ): Promise>\n {\n const resolveArray = Object.values(resolveResults) as ResolvedAsset[];\n const resolveKeys = Object.keys(resolveResults);\n\n // pause background loader...\n this._backgroundLoader.active = false;\n\n const loadedAssets = await this.loader.load(resolveArray, onProgress);\n\n // resume background loader...\n this._backgroundLoader.active = true;\n\n // remap to the keys used..\n\n const out: Record = {};\n\n resolveArray.forEach((resolveResult, i) =>\n {\n const asset = loadedAssets[resolveResult.src];\n\n const keys = [resolveResult.src];\n\n if (resolveResult.alias)\n {\n keys.push(...resolveResult.alias);\n }\n\n out[resolveKeys[i]] = asset;\n\n Cache.set(keys, asset);\n });\n\n return out;\n }\n\n /**\n * Unload an asset or assets. As the Assets class is responsible for creating the assets via the `load` function\n * this will make sure to destroy any assets and release them from memory.\n * Once unloaded, you will need to load the asset again.\n *\n * Use this to help manage assets if you find that you have a large app and you want to free up memory.\n *\n * - it's up to you as the developer to make sure that textures are not actively being used when you unload them,\n * Pixi won't break but you will end up with missing assets. Not a good look for the user!\n * @example\n * import { Assets } from 'pixi.js';\n *\n * // Load a URL:\n * const myImageTexture = await Assets.load('http://some.url.com/image.png'); // => returns a texture\n *\n * await Assets.unload('http://some.url.com/image.png')\n *\n * // myImageTexture will be destroyed now.\n *\n * // Unload multiple assets:\n * const textures = await Assets.unload(['thumper', 'chicko']);\n * @param urls - the urls to unload\n */\n public async unload(\n urls: ArrayOr | ResolvedAsset | ResolvedAsset[]\n ): Promise\n {\n if (!this._initialized)\n {\n await this.init();\n }\n\n const urlArray = convertToList(urls)\n .map((url) =>\n ((typeof url !== 'string') ? url.src : url));\n\n // check cache first...\n const resolveResults = this.resolver.resolve(urlArray);\n\n await this._unloadFromResolved(resolveResults);\n }\n\n /**\n * Bundles are a way to manage multiple assets at once.\n * this will unload all files in a bundle.\n *\n * once a bundle has been unloaded, you need to load it again to have access to the assets.\n * @example\n * import { Assets } from 'pixi.js';\n *\n * Assets.addBundle({\n * 'thumper': 'http://some.url.com/thumper.png',\n * })\n *\n * const assets = await Assets.loadBundle('thumper');\n *\n * // Now to unload...\n *\n * await Assets.unloadBundle('thumper');\n *\n * // All assets in the assets object will now have been destroyed and purged from the cache\n * @param bundleIds - the bundle id or ids to unload\n */\n public async unloadBundle(bundleIds: ArrayOr): Promise\n {\n if (!this._initialized)\n {\n await this.init();\n }\n\n bundleIds = convertToList(bundleIds);\n\n const resolveResults = this.resolver.resolveBundle(bundleIds);\n\n const promises = Object.keys(resolveResults).map((bundleId) =>\n this._unloadFromResolved(resolveResults[bundleId]));\n\n await Promise.all(promises);\n }\n\n private async _unloadFromResolved(resolveResult: ResolvedAsset | Record)\n {\n const resolveArray = Object.values(resolveResult);\n\n resolveArray.forEach((resolveResult) =>\n {\n Cache.remove(resolveResult.src);\n });\n\n await this.loader.unload(resolveArray);\n }\n\n /**\n * Detects the supported formats for the browser, and returns an array of supported formats, respecting\n * the users preferred formats order.\n * @param options - the options to use when detecting formats\n * @param options.preferredFormats - the preferred formats to use\n * @param options.skipDetections - if we should skip the detections altogether\n * @param options.detections - the detections to use\n * @returns - the detected formats\n */\n private async _detectFormats(options: {\n preferredFormats: string | string[],\n skipDetections: boolean,\n detections: FormatDetectionParser[]\n }): Promise\n {\n let formats: string[] = [];\n\n // set preferred formats\n if (options.preferredFormats)\n {\n formats = Array.isArray(options.preferredFormats)\n ? options.preferredFormats : [options.preferredFormats];\n }\n\n // we should add any formats that are supported by the browser\n for (const detection of options.detections)\n {\n if (options.skipDetections || await detection.test())\n {\n formats = await detection.add(formats);\n }\n else if (!options.skipDetections)\n {\n formats = await detection.remove(formats);\n }\n }\n\n // remove any duplicates\n formats = formats.filter((format, index) => formats.indexOf(format) === index);\n\n return formats;\n }\n\n /** All the detection parsers currently added to the Assets class. */\n public get detections(): FormatDetectionParser[]\n {\n return this._detections;\n }\n\n /**\n * @deprecated since 7.2.0\n * @see {@link Assets.setPreferences}\n */\n public get preferWorkers(): boolean\n {\n return loadTextures.config.preferWorkers;\n }\n public set preferWorkers(value: boolean)\n {\n if (process.env.DEBUG)\n {\n utils.deprecation('7.2.0', 'Assets.prefersWorkers is deprecated, '\n + 'use Assets.setPreferences({ preferWorkers: true }) instead.');\n }\n this.setPreferences({ preferWorkers: value });\n }\n\n /**\n * General setter for preferences. This is a helper function to set preferences on all parsers.\n * @param preferences - the preferences to set\n */\n public setPreferences(preferences: Partial): void\n {\n // Find matching config keys in loaders with preferences\n // and set the values\n this.loader.parsers.forEach((parser) =>\n {\n if (!parser.config) return;\n\n (Object.keys(parser.config) as (keyof AssetsPreferences)[])\n .filter((key) => key in preferences)\n .forEach((key) =>\n {\n parser.config[key] = preferences[key];\n });\n });\n }\n}\n\nexport const Assets = new AssetsClass();\n\n// Handle registration of extensions\nextensions\n .handleByList(ExtensionType.LoadParser, Assets.loader.parsers)\n .handleByList(ExtensionType.ResolveParser, Assets.resolver.parsers)\n .handleByList(ExtensionType.CacheParser, Assets.cache.parsers)\n .handleByList(ExtensionType.DetectionParser, Assets.detections);\n"],"names":["resolveResult"],"mappings":"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"}