diff --git a/packages/core/src/asset/LoadItem.ts b/packages/core/src/asset/LoadItem.ts index 7897f2bd61..dc9d5219cb 100644 --- a/packages/core/src/asset/LoadItem.ts +++ b/packages/core/src/asset/LoadItem.ts @@ -6,6 +6,10 @@ type PickOnlyOne = Keys extends un * Used to describe loading asset. */ export type LoadItem = { + /** + * Resource's alias. + */ + name?: string; /** * Asset Type. */ diff --git a/packages/core/src/asset/ResourceManager.ts b/packages/core/src/asset/ResourceManager.ts index 9a05222afa..3aff3509fb 100644 --- a/packages/core/src/asset/ResourceManager.ts +++ b/packages/core/src/asset/ResourceManager.ts @@ -41,6 +41,8 @@ export class ResourceManager { private _assetPool: Record = Object.create(null); /** Asset url pool, key is the asset path and the value is the asset. */ private _assetUrlPool: Record = Object.create(null); + /** Asset alias pool, key is the asset name and the value is the asset. */ + private _assetAliasPool: Record = Object.create(null); /** Referable resource pool, key is the `instanceID` of resource. */ private _referResourcePool: Record = Object.create(null); @@ -68,7 +70,7 @@ export class ResourceManager { * @param paths - Path collections * @returns Asset Promise */ - load(paths: string[]): AssetPromise; + load(paths: string[]): AssetPromise; /** * Load the asset asynchronously by asset item information. @@ -82,9 +84,11 @@ export class ResourceManager { * @param assetItems - Asset collection * @returns AssetPromise */ - load(assetItems: LoadItem[]): AssetPromise; + load(assetItems: LoadItem[]): AssetPromise; - load(assetInfo: string | LoadItem | (LoadItem | string)[]): AssetPromise { + load( + assetInfo: string | LoadItem | (LoadItem | string)[] + ): AssetPromise { // single item if (!Array.isArray(assetInfo)) { return this._loadSingleItem(assetInfo); @@ -95,12 +99,12 @@ export class ResourceManager { } /** - * Get the resource from cache by asset url, return the resource object if it loaded, otherwise return null. - * @param url - Resource url + * Get the resource from cache by asset name or url, return the resource object if it loaded, otherwise return null. + * @param aliasOrUrl - Resource name or url * @returns Resource object */ - getFromCache(url: string): T { - return (this._assetUrlPool[url] as T) ?? null; + getFromCache(aliasOrUrl: string): T { + return (this._assetAliasPool[aliasOrUrl] as T) ?? (this._assetUrlPool[aliasOrUrl] as T) ?? null; } /** @@ -196,9 +200,12 @@ export class ResourceManager { /** * @internal */ - _addAsset(path: string, asset: EngineObject): void { - this._assetPool[asset.instanceId] = path; - this._assetUrlPool[path] = asset; + _addAsset(item: string, asset: EngineObject, name?: string): void { + this._assetPool[asset.instanceId] = item; + this._assetUrlPool[item] = asset; + if (name) { + this._setAssetAlias(asset, name); + } } /** @@ -308,7 +315,27 @@ export class ResourceManager { return assetInfo; } - private _loadSingleItem(itemOrURL: LoadItem | string): AssetPromise { + private _setAssetAlias(obj: Object, name?: string) { + if (!name) { + return; + } + const cache = this._assetAliasPool[name]; + if (cache) { + if (obj !== cache) { + console.warn( + `Cache already has an asset named "${name}", the newest asset will replace the old one if they have same name."`, + obj, + "will replace", + cache + ); + } else { + return; + } + } + this._assetAliasPool[name] = obj; + } + + private _loadSingleItem(itemOrURL: LoadItem | string): AssetPromise { const item = this._assignDefaultOptions(typeof itemOrURL === "string" ? { url: itemOrURL } : itemOrURL); // Check url mapping @@ -322,6 +349,7 @@ export class ResourceManager { // Check cache const cacheObject = this._assetUrlPool[assetBaseURL]; if (cacheObject) { + this._setAssetAlias(cacheObject, item.name); // sometimes user could give one resource different names if used in different scenes return new AssetPromise((resolve) => { resolve(this._getResolveResource(cacheObject, paths) as T); }); @@ -368,7 +396,7 @@ export class ResourceManager { promise.then( (resource: T) => { if (loader.useCache) { - this._addAsset(assetBaseURL, resource as EngineObject); + this._addAsset(assetBaseURL, resource, item.name); } delete loadingPromises[assetBaseURL]; },