diff --git a/src/framework/asset/asset-registry.js b/src/framework/asset/asset-registry.js index 3d682d53def..9a2cd358884 100644 --- a/src/framework/asset/asset-registry.js +++ b/src/framework/asset/asset-registry.js @@ -179,7 +179,7 @@ class AssetRegistry extends EventHandler { _idToAsset = new Map(); /** - * @type {Map} + * @type {Map>} * @private */ _urlToAsset = new Map(); @@ -264,8 +264,12 @@ class AssetRegistry extends EventHandler { this._idToAsset.set(asset.id, asset); - if (asset.file?.url) { - this._urlToAsset.set(asset.file.url, asset); + const url = asset.file?.url; + if (url) { + if (!this._urlToAsset.has(url)) { + this._urlToAsset.set(url, new Set()); + } + this._urlToAsset.get(url).add(asset); } if (!this._nameToAsset.has(asset.name)) { @@ -310,8 +314,13 @@ class AssetRegistry extends EventHandler { this._idToAsset.delete(asset.id); - if (asset.file?.url) { - this._urlToAsset.delete(asset.file.url); + const url = asset.file?.url; + if (url) { + const assets = this._urlToAsset.get(url); + assets?.delete(asset); + if (assets?.size === 0) { + this._urlToAsset.delete(url); + } } asset.off('name', this._onNameChange, this); @@ -356,12 +365,24 @@ class AssetRegistry extends EventHandler { * Retrieve an asset from the registry by its file's URL field. * * @param {string} url - The url of the asset to get. + * @param {string} [type] - The type of the asset to get. * @returns {Asset|undefined} The asset. * @example * const asset = app.assets.getByUrl("../path/to/image.jpg"); */ - getByUrl(url) { - return this._urlToAsset.get(url); + getByUrl(url, type) { + const assets = this._urlToAsset.get(url); + if (!assets) { + return undefined; + } + + let result; + assets.forEach((asset) => { + if (!type || asset.type === type) { + result = asset; + } + }); + return result; } /** diff --git a/test/framework/asset/asset-registry.test.mjs b/test/framework/asset/asset-registry.test.mjs index 415dc67a218..9bd09414cf3 100644 --- a/test/framework/asset/asset-registry.test.mjs +++ b/test/framework/asset/asset-registry.test.mjs @@ -187,6 +187,48 @@ describe('AssetRegistry', function () { expect(asset).to.equal(assetFromRegistry); }); + it('retrieves an asset by url and type', function () { + const url = 'fake/shared/image.png'; + const cubemapAsset = new Asset('Cubemap Asset', 'cubemap', { + url: url + }); + const textureAsset = new Asset('Texture Asset', 'texture', { + url: url + }); + + app.assets.add(cubemapAsset); + app.assets.add(textureAsset); + + expect(app.assets.getByUrl(url)).to.equal(textureAsset); + expect(app.assets.getByUrl(url, 'cubemap')).to.equal(cubemapAsset); + expect(app.assets.getByUrl(url, 'texture')).to.equal(textureAsset); + expect(app.assets.getByUrl(url, 'model')).to.equal(undefined); + }); + + it('works after removing assets with the same url', function () { + const url = 'fake/shared/image.png'; + const cubemapAsset = new Asset('Cubemap Asset', 'cubemap', { + url: url + }); + const textureAsset = new Asset('Texture Asset', 'texture', { + url: url + }); + + app.assets.add(cubemapAsset); + app.assets.add(textureAsset); + + app.assets.remove(textureAsset); + + expect(app.assets.getByUrl(url)).to.equal(cubemapAsset); + expect(app.assets.getByUrl(url, 'cubemap')).to.equal(cubemapAsset); + expect(app.assets.getByUrl(url, 'texture')).to.equal(undefined); + + app.assets.remove(cubemapAsset); + + expect(app.assets.getByUrl(url)).to.equal(undefined); + expect(app.assets.getByUrl(url, 'cubemap')).to.equal(undefined); + }); + it('works after removing an asset', function () { const asset1 = new Asset('Asset 1', 'text', { url: 'fake/one/file.txt'