Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add alias for loading resource #1786

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/core/src/asset/LoadItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ type PickOnlyOne<T extends {}, Keys extends keyof T = keyof T> = Keys extends un
* Used to describe loading asset.
*/
export type LoadItem = {
/**
* Resource's alias.
*/
name?: string;
/**
* Asset Type.
*/
Expand Down
52 changes: 40 additions & 12 deletions packages/core/src/asset/ResourceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export class ResourceManager {
private _assetPool: Record<number, string> = Object.create(null);
/** Asset url pool, key is the asset path and the value is the asset. */
private _assetUrlPool: Record<string, Object> = Object.create(null);
/** Asset alias pool, key is the asset name and the value is the asset. */
private _assetAliasPool: Record<string, Object> = Object.create(null);

/** Referable resource pool, key is the `instanceID` of resource. */
private _referResourcePool: Record<number, ReferResource> = Object.create(null);
Expand Down Expand Up @@ -68,7 +70,7 @@ export class ResourceManager {
* @param paths - Path collections
* @returns Asset Promise
*/
load(paths: string[]): AssetPromise<Object[]>;
load(paths: string[]): AssetPromise<EngineObject[]>;

/**
* Load the asset asynchronously by asset item information.
Expand All @@ -82,9 +84,11 @@ export class ResourceManager {
* @param assetItems - Asset collection
* @returns AssetPromise
*/
load(assetItems: LoadItem[]): AssetPromise<Object[]>;
load(assetItems: LoadItem[]): AssetPromise<EngineObject[]>;

load<T>(assetInfo: string | LoadItem | (LoadItem | string)[]): AssetPromise<T | Object[]> {
load<T extends EngineObject>(
assetInfo: string | LoadItem | (LoadItem | string)[]
): AssetPromise<EngineObject | EngineObject[]> {
// single item
if (!Array.isArray(assetInfo)) {
return this._loadSingleItem(assetInfo);
Expand All @@ -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<T>(url: string): T {
return (this._assetUrlPool[url] as T) ?? null;
getFromCache<T extends EngineObject>(aliasOrUrl: string): T {
return (this._assetAliasPool[aliasOrUrl] as T) ?? (this._assetUrlPool[aliasOrUrl] as T) ?? null;
}

/**
Expand Down Expand Up @@ -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);
}
}

/**
Expand Down Expand Up @@ -308,7 +315,27 @@ export class ResourceManager {
return assetInfo;
}

private _loadSingleItem<T>(itemOrURL: LoadItem | string): AssetPromise<T> {
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<T extends EngineObject>(itemOrURL: LoadItem | string): AssetPromise<EngineObject> {
const item = this._assignDefaultOptions(typeof itemOrURL === "string" ? { url: itemOrURL } : itemOrURL);

// Check url mapping
Expand All @@ -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);
});
Expand Down Expand Up @@ -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];
},
Expand Down