Files
Foundry-VTT-Docker/resources/app/node_modules/@pixi/assets/lib/Assets.js

329 lines
14 KiB
JavaScript
Raw Normal View History

2025-01-04 00:34:03 +01:00
"use strict";
var core = require("@pixi/core"), BackgroundLoader = require("./BackgroundLoader.js"), Cache = require("./cache/Cache.js"), Loader = require("./loader/Loader.js");
require("./loader/parsers/index.js");
var Resolver = require("./resolver/Resolver.js"), convertToList = require("./utils/convertToList.js"), isSingleItem = require("./utils/isSingleItem.js"), loadTextures = require("./loader/parsers/textures/loadTextures.js");
class AssetsClass {
constructor() {
this._detections = [], this._initialized = !1, this.resolver = new Resolver.Resolver(), this.loader = new Loader.Loader(), this.cache = Cache.Cache, this._backgroundLoader = new BackgroundLoader.BackgroundLoader(this.loader), this._backgroundLoader.active = !0, this.reset();
}
/**
* Best practice is to call this function before any loading commences
* Initiating is the best time to add any customization to the way things are loaded.
*
* you do not need to call this for the Asset class to work, only if you want to set any initial properties
* @param options - options to initialize the Asset manager with
*/
async init(options = {}) {
if (this._initialized) {
console.warn("[Assets]AssetManager already initialized, did you load before calling this Assets.init()?");
return;
}
if (this._initialized = !0, options.defaultSearchParams && this.resolver.setDefaultSearchParams(options.defaultSearchParams), options.basePath && (this.resolver.basePath = options.basePath), options.bundleIdentifier && this.resolver.setBundleIdentifier(options.bundleIdentifier), options.manifest) {
let manifest = options.manifest;
typeof manifest == "string" && (manifest = await this.load(manifest)), this.resolver.addManifest(manifest);
}
const resolutionPref = options.texturePreference?.resolution ?? 1, resolution = typeof resolutionPref == "number" ? [resolutionPref] : resolutionPref, formats = await this._detectFormats({
preferredFormats: options.texturePreference?.format,
skipDetections: options.skipDetections,
detections: this._detections
});
this.resolver.prefer({
params: {
format: formats,
resolution
}
}), options.preferences && this.setPreferences(options.preferences);
}
add(aliases, srcs, data, format, loadParser) {
this.resolver.add(aliases, srcs, data, format, loadParser);
}
async load(urls, onProgress) {
this._initialized || await this.init();
const singleAsset = isSingleItem.isSingleItem(urls), urlArray = convertToList.convertToList(urls).map((url) => {
if (typeof url != "string") {
const aliases = this.resolver.getAlias(url);
return aliases.some((alias) => !this.resolver.hasKey(alias)) && this.add(url), Array.isArray(aliases) ? aliases[0] : aliases;
}
return this.resolver.hasKey(url) || this.add({ alias: url, src: url }), url;
}), resolveResults = this.resolver.resolve(urlArray), out = await this._mapLoadToResolve(resolveResults, onProgress);
return singleAsset ? out[urlArray[0]] : out;
}
/**
* This adds a bundle of assets in one go so that you can load them as a group.
* For example you could add a bundle for each screen in you pixi app
* @example
* import { Assets } from 'pixi.js';
*
* Assets.addBundle('animals', {
* bunny: 'bunny.png',
* chicken: 'chicken.png',
* thumper: 'thumper.png',
* });
*
* const assets = await Assets.loadBundle('animals');
* @param bundleId - the id of the bundle to add
* @param assets - a record of the asset or assets that will be chosen from when loading via the specified key
*/
addBundle(bundleId, assets) {
this.resolver.addBundle(bundleId, assets);
}
/**
* Bundles are a way to load multiple assets at once.
* If a manifest has been provided to the init function then you can load a bundle, or bundles.
* you can also add bundles via `addBundle`
* @example
* import { Assets } from 'pixi.js';
*
* // Manifest Example
* const manifest = {
* bundles: [
* {
* name: 'load-screen',
* assets: [
* {
* alias: 'background',
* src: 'sunset.png',
* },
* {
* alias: 'bar',
* src: 'load-bar.{png,webp}',
* },
* ],
* },
* {
* name: 'game-screen',
* assets: [
* {
* alias: 'character',
* src: 'robot.png',
* },
* {
* alias: 'enemy',
* src: 'bad-guy.png',
* },
* ],
* },
* ]
* };
*
* await Assets.init({ manifest });
*
* // Load a bundle...
* loadScreenAssets = await Assets.loadBundle('load-screen');
* // Load another bundle...
* gameScreenAssets = await Assets.loadBundle('game-screen');
* @param bundleIds - the bundle id or ids to load
* @param onProgress - Optional function that is called when progress on asset loading is made.
* The function is passed a single parameter, `progress`, which represents the percentage (0.0 - 1.0)
* of the assets loaded. Do not use this function to detect when assets are complete and available,
* instead use the Promise returned by this function.
* @returns all the bundles assets or a hash of assets for each bundle specified
*/
async loadBundle(bundleIds, onProgress) {
this._initialized || await this.init();
let singleAsset = !1;
typeof bundleIds == "string" && (singleAsset = !0, bundleIds = [bundleIds]);
const resolveResults = this.resolver.resolveBundle(bundleIds), out = {}, keys = Object.keys(resolveResults);
let count = 0, total = 0;
const _onProgress = () => {
onProgress?.(++count / total);
}, promises = keys.map((bundleId) => {
const resolveResult = resolveResults[bundleId];
return total += Object.keys(resolveResult).length, this._mapLoadToResolve(resolveResult, _onProgress).then((resolveResult2) => {
out[bundleId] = resolveResult2;
});
});
return await Promise.all(promises), singleAsset ? out[bundleIds[0]] : out;
}
/**
* Initiate a background load of some assets. It will passively begin to load these assets in the background.
* So when you actually come to loading them you will get a promise that resolves to the loaded assets immediately
*
* An example of this might be that you would background load game assets after your inital load.
* then when you got to actually load your game screen assets when a player goes to the game - the loading
* would already have stared or may even be complete, saving you having to show an interim load bar.
* @example
* import { Assets } from 'pixi.js';
*
* Assets.backgroundLoad('bunny.png');
*
* // later on in your app...
* await Assets.loadBundle('bunny.png'); // Will resolve quicker as loading may have completed!
* @param urls - the url / urls you want to background load
*/
async backgroundLoad(urls) {
this._initialized || await this.init(), typeof urls == "string" && (urls = [urls]);
const resolveResults = this.resolver.resolve(urls);
this._backgroundLoader.add(Object.values(resolveResults));
}
/**
* Initiate a background of a bundle, works exactly like backgroundLoad but for bundles.
* this can only be used if the loader has been initiated with a manifest
* @example
* import { Assets } from 'pixi.js';
*
* await Assets.init({
* manifest: {
* bundles: [
* {
* name: 'load-screen',
* assets: [...],
* },
* ...
* ],
* },
* });
*
* Assets.backgroundLoadBundle('load-screen');
*
* // Later on in your app...
* await Assets.loadBundle('load-screen'); // Will resolve quicker as loading may have completed!
* @param bundleIds - the bundleId / bundleIds you want to background load
*/
async backgroundLoadBundle(bundleIds) {
this._initialized || await this.init(), typeof bundleIds == "string" && (bundleIds = [bundleIds]);
const resolveResults = this.resolver.resolveBundle(bundleIds);
Object.values(resolveResults).forEach((resolveResult) => {
this._backgroundLoader.add(Object.values(resolveResult));
});
}
/**
* Only intended for development purposes.
* This will wipe the resolver and caches.
* You will need to reinitialize the Asset
*/
reset() {
this.resolver.reset(), this.loader.reset(), this.cache.reset(), this._initialized = !1;
}
get(keys) {
if (typeof keys == "string")
return Cache.Cache.get(keys);
const assets = {};
for (let i = 0; i < keys.length; i++)
assets[i] = Cache.Cache.get(keys[i]);
return assets;
}
/**
* helper function to map resolved assets back to loaded assets
* @param resolveResults - the resolve results from the resolver
* @param onProgress - the progress callback
*/
async _mapLoadToResolve(resolveResults, onProgress) {
const resolveArray = Object.values(resolveResults), resolveKeys = Object.keys(resolveResults);
this._backgroundLoader.active = !1;
const loadedAssets = await this.loader.load(resolveArray, onProgress);
this._backgroundLoader.active = !0;
const out = {};
return resolveArray.forEach((resolveResult, i) => {
const asset = loadedAssets[resolveResult.src], keys = [resolveResult.src];
resolveResult.alias && keys.push(...resolveResult.alias), out[resolveKeys[i]] = asset, Cache.Cache.set(keys, asset);
}), out;
}
/**
* Unload an asset or assets. As the Assets class is responsible for creating the assets via the `load` function
* this will make sure to destroy any assets and release them from memory.
* Once unloaded, you will need to load the asset again.
*
* Use this to help manage assets if you find that you have a large app and you want to free up memory.
*
* - it's up to you as the developer to make sure that textures are not actively being used when you unload them,
* Pixi won't break but you will end up with missing assets. Not a good look for the user!
* @example
* import { Assets } from 'pixi.js';
*
* // Load a URL:
* const myImageTexture = await Assets.load('http://some.url.com/image.png'); // => returns a texture
*
* await Assets.unload('http://some.url.com/image.png')
*
* // myImageTexture will be destroyed now.
*
* // Unload multiple assets:
* const textures = await Assets.unload(['thumper', 'chicko']);
* @param urls - the urls to unload
*/
async unload(urls) {
this._initialized || await this.init();
const urlArray = convertToList.convertToList(urls).map((url) => typeof url != "string" ? url.src : url), resolveResults = this.resolver.resolve(urlArray);
await this._unloadFromResolved(resolveResults);
}
/**
* Bundles are a way to manage multiple assets at once.
* this will unload all files in a bundle.
*
* once a bundle has been unloaded, you need to load it again to have access to the assets.
* @example
* import { Assets } from 'pixi.js';
*
* Assets.addBundle({
* 'thumper': 'http://some.url.com/thumper.png',
* })
*
* const assets = await Assets.loadBundle('thumper');
*
* // Now to unload...
*
* await Assets.unloadBundle('thumper');
*
* // All assets in the assets object will now have been destroyed and purged from the cache
* @param bundleIds - the bundle id or ids to unload
*/
async unloadBundle(bundleIds) {
this._initialized || await this.init(), bundleIds = convertToList.convertToList(bundleIds);
const resolveResults = this.resolver.resolveBundle(bundleIds), promises = Object.keys(resolveResults).map((bundleId) => this._unloadFromResolved(resolveResults[bundleId]));
await Promise.all(promises);
}
async _unloadFromResolved(resolveResult) {
const resolveArray = Object.values(resolveResult);
resolveArray.forEach((resolveResult2) => {
Cache.Cache.remove(resolveResult2.src);
}), await this.loader.unload(resolveArray);
}
/**
* Detects the supported formats for the browser, and returns an array of supported formats, respecting
* the users preferred formats order.
* @param options - the options to use when detecting formats
* @param options.preferredFormats - the preferred formats to use
* @param options.skipDetections - if we should skip the detections altogether
* @param options.detections - the detections to use
* @returns - the detected formats
*/
async _detectFormats(options) {
let formats = [];
options.preferredFormats && (formats = Array.isArray(options.preferredFormats) ? options.preferredFormats : [options.preferredFormats]);
for (const detection of options.detections)
options.skipDetections || await detection.test() ? formats = await detection.add(formats) : options.skipDetections || (formats = await detection.remove(formats));
return formats = formats.filter((format, index) => formats.indexOf(format) === index), formats;
}
/** All the detection parsers currently added to the Assets class. */
get detections() {
return this._detections;
}
/**
* @deprecated since 7.2.0
* @see {@link Assets.setPreferences}
*/
get preferWorkers() {
return loadTextures.loadTextures.config.preferWorkers;
}
set preferWorkers(value) {
core.utils.deprecation("7.2.0", "Assets.prefersWorkers is deprecated, use Assets.setPreferences({ preferWorkers: true }) instead."), this.setPreferences({ preferWorkers: value });
}
/**
* General setter for preferences. This is a helper function to set preferences on all parsers.
* @param preferences - the preferences to set
*/
setPreferences(preferences) {
this.loader.parsers.forEach((parser) => {
parser.config && Object.keys(parser.config).filter((key) => key in preferences).forEach((key) => {
parser.config[key] = preferences[key];
});
});
}
}
const Assets = new AssetsClass();
core.extensions.handleByList(core.ExtensionType.LoadParser, Assets.loader.parsers).handleByList(core.ExtensionType.ResolveParser, Assets.resolver.parsers).handleByList(core.ExtensionType.CacheParser, Assets.cache.parsers).handleByList(core.ExtensionType.DetectionParser, Assets.detections);
exports.Assets = Assets;
exports.AssetsClass = AssetsClass;
//# sourceMappingURL=Assets.js.map