UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

167 lines (165 loc) 6.2 kB
/** * @import { Asset } from './asset.js' * @import { AssetRegistry } from './asset-registry.js' * @import { EventHandle } from '../../core/event-handle.js' */ /** * An object that manages the case where an object holds a reference to an asset and needs to be * notified when changes occur in the asset. e.g. notifications include load, add and remove * events. * * @category Asset */ class AssetReference { /** * Create a new AssetReference instance. * * @param {string} propertyName - The name of the property that the asset is stored under, * passed into callbacks to enable updating. * @param {Asset|object} parent - The parent object that contains the asset reference, passed * into callbacks to enable updating. Currently an asset, but could be component or other. * @param {AssetRegistry} registry - The asset registry that stores all assets. * @param {object} callbacks - A set of functions called when the asset state changes: load, * add, remove. * @param {object} [callbacks.load] - The function called when the asset loads * load(propertyName, parent, asset). * @param {object} [callbacks.add] - The function called when the asset is added to the * registry add(propertyName, parent, asset). * @param {object} [callbacks.remove] - The function called when the asset is remove from the * registry remove(propertyName, parent, asset). * @param {object} [callbacks.unload] - The function called when the asset is unloaded * unload(propertyName, parent, asset). * @param {object} [scope] - The scope to call the callbacks in. * @example * const reference = new pc.AssetReference('textureAsset', this, this.app.assets, { * load: this.onTextureAssetLoad, * add: this.onTextureAssetAdd, * remove: this.onTextureAssetRemove * }, this); * reference.id = this.textureAsset.id; */ constructor(propertyName, parent, registry, callbacks, scope){ /** * @type {EventHandle|null} * @private */ this._evtLoadById = null; /** * @type {EventHandle|null} * @private */ this._evtUnloadById = null; /** * @type {EventHandle|null} * @private */ this._evtAddById = null; /** * @type {EventHandle|null} * @private */ this._evtRemoveById = null; /** * @type {EventHandle|null} * @private */ this._evtLoadByUrl = null; /** * @type {EventHandle|null} * @private */ this._evtAddByUrl = null; /** * @type {EventHandle|null} * @private */ this._evtRemoveByUrl = null; this.propertyName = propertyName; this.parent = parent; this._scope = scope; this._registry = registry; this.id = null; this.url = null; this.asset = null; this._onAssetLoad = callbacks.load; this._onAssetAdd = callbacks.add; this._onAssetRemove = callbacks.remove; this._onAssetUnload = callbacks.unload; } /** * Sets the asset id which this references. One of either id or url must be set to * initialize an asset reference. * * @type {number} */ set id(value) { if (this.url) throw Error('Can\'t set id and url'); this._unbind(); this._id = value; this.asset = this._registry.get(this._id); this._bind(); } /** * Gets the asset id which this references. * * @type {number} */ get id() { return this._id; } /** * Sets the asset url which this references. One of either id or url must be called to * initialize an asset reference. * * @type {string|null} */ set url(value) { if (this.id) throw Error('Can\'t set id and url'); this._unbind(); this._url = value; this.asset = this._registry.getByUrl(this._url); this._bind(); } /** * Gets the asset url which this references. * * @type {string|null} */ get url() { return this._url; } _bind() { if (this.id) { if (this._onAssetLoad) this._evtLoadById = this._registry.on(`load:${this.id}`, this._onLoad, this); if (this._onAssetAdd) this._evtAddById = this._registry.once(`add:${this.id}`, this._onAdd, this); if (this._onAssetRemove) this._evtRemoveById = this._registry.on(`remove:${this.id}`, this._onRemove, this); if (this._onAssetUnload) this._evtUnloadById = this._registry.on(`unload:${this.id}`, this._onUnload, this); } if (this.url) { if (this._onAssetLoad) this._evtLoadByUrl = this._registry.on(`load:url:${this.url}`, this._onLoad, this); if (this._onAssetAdd) this._evtAddByUrl = this._registry.once(`add:url:${this.url}`, this._onAdd, this); if (this._onAssetRemove) this._evtRemoveByUrl = this._registry.on(`remove:url:${this.url}`, this._onRemove, this); } } _unbind() { if (this.id) { this._evtLoadById?.off(); this._evtLoadById = null; this._evtAddById?.off(); this._evtAddById = null; this._evtRemoveById?.off(); this._evtRemoveById = null; this._evtUnloadById?.off(); this._evtUnloadById = null; } if (this.url) { this._evtLoadByUrl?.off(); this._evtLoadByUrl = null; this._evtAddByUrl?.off(); this._evtAddByUrl = null; this._evtRemoveByUrl?.off(); this._evtRemoveByUrl = null; } } _onLoad(asset) { this._onAssetLoad.call(this._scope, this.propertyName, this.parent, asset); } _onAdd(asset) { this.asset = asset; this._onAssetAdd.call(this._scope, this.propertyName, this.parent, asset); } _onRemove(asset) { this._onAssetRemove.call(this._scope, this.propertyName, this.parent, asset); this.asset = null; } _onUnload(asset) { this._onAssetUnload.call(this._scope, this.propertyName, this.parent, asset); } } export { AssetReference };