2022-04-10 02:58:33 -04:00
|
|
|
import { BaseTexture, Resource, Texture } from '@pixi/core';
|
2021-08-02 23:48:00 -04:00
|
|
|
import { Loader, LoaderResource } from '@pixi/loaders';
|
|
|
|
import { Spritesheet } from '@pixi/spritesheet';
|
2022-11-08 16:44:41 -05:00
|
|
|
import { IAssetData, IAssetManager, IGraphicAsset, IGraphicAssetCollection, NitroLogger } from '../../api';
|
|
|
|
import { Disposable } from '../common';
|
2022-04-11 02:17:08 -04:00
|
|
|
import { ArrayBufferToBase64 } from '../utils';
|
2022-10-30 00:02:19 -04:00
|
|
|
import { GraphicAssetCollection } from './GraphicAssetCollection';
|
2021-03-16 22:02:09 -04:00
|
|
|
import { NitroBundle } from './NitroBundle';
|
|
|
|
|
|
|
|
export class AssetManager extends Disposable implements IAssetManager
|
|
|
|
{
|
2021-07-14 03:10:54 -04:00
|
|
|
private _textures: Map<string, Texture<Resource>>;
|
2021-07-13 16:34:41 -04:00
|
|
|
private _collections: Map<string, IGraphicAssetCollection>;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
constructor()
|
|
|
|
{
|
|
|
|
super();
|
|
|
|
|
2022-03-02 19:21:30 -05:00
|
|
|
this._textures = new Map();
|
|
|
|
this._collections = new Map();
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
|
|
|
|
2021-07-14 03:10:54 -04:00
|
|
|
public getTexture(name: string): Texture<Resource>
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!name) return null;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
const existing = this._textures.get(name);
|
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!existing) return null;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
return existing;
|
|
|
|
}
|
|
|
|
|
2021-07-14 03:10:54 -04:00
|
|
|
public setTexture(name: string, texture: Texture<Resource>): void
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!name || !texture) return;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
this._textures.set(name, texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
public getAsset(name: string): IGraphicAsset
|
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!name) return null;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
for (const collection of this._collections.values())
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!collection) continue;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
const existing = collection.getAsset(name);
|
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!existing) continue;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
return existing;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public getCollection(name: string): IGraphicAssetCollection
|
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!name) return null;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
const existing = this._collections.get(name);
|
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!existing) return null;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
return existing;
|
|
|
|
}
|
|
|
|
|
|
|
|
public createCollection(data: IAssetData, spritesheet: Spritesheet): IGraphicAssetCollection
|
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!data) return null;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
const collection = new GraphicAssetCollection(data, spritesheet);
|
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (collection)
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
for (const [name, texture] of collection.textures.entries()) this.setTexture(name, texture);
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
this._collections.set(collection.name, collection);
|
|
|
|
}
|
2021-07-13 16:34:41 -04:00
|
|
|
|
|
|
|
return collection;
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
public downloadAsset(assetUrl: string, cb: (status: boolean) => void): void
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-07-18 21:51:53 -04:00
|
|
|
this.downloadAssets([assetUrl], cb);
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
public downloadAssets(assetUrls: string[], cb: (status: boolean) => void): void
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!assetUrls || !assetUrls.length)
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
|
|
|
cb(true);
|
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
return;
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
const loader = new Loader();
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
for (const url of assetUrls)
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!url) continue;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
loader
|
2021-07-13 16:34:41 -04:00
|
|
|
.add({
|
|
|
|
url,
|
|
|
|
crossOrigin: 'anonymous',
|
2022-04-11 02:17:08 -04:00
|
|
|
loadType: LoaderResource.LOAD_TYPE.XHR,
|
|
|
|
xhrType: LoaderResource.XHR_RESPONSE_TYPE.BUFFER
|
2022-04-10 02:58:33 -04:00
|
|
|
});
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
let remaining = assetUrls.length;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
const onDownloaded = (status: boolean, url: string) =>
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!status)
|
2022-04-10 02:58:33 -04:00
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
NitroLogger.error('Failed to download asset', url);
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
loader.destroy();
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
cb(false);
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
return;
|
|
|
|
}
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
remaining--;
|
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!remaining)
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-04-10 02:58:33 -04:00
|
|
|
loader.destroy();
|
|
|
|
|
|
|
|
cb(true);
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2022-04-10 02:58:33 -04:00
|
|
|
};
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
loader.load((loader, resources) =>
|
|
|
|
{
|
2022-11-08 16:44:41 -05:00
|
|
|
for (const key in resources)
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-04-10 02:58:33 -04:00
|
|
|
const resource = resources[key];
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!resource || resource.error || !resource.xhr)
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-04-10 02:58:33 -04:00
|
|
|
onDownloaded(false, resource.url);
|
2021-03-16 22:02:09 -04:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-11 12:38:25 -04:00
|
|
|
const resourceType = (resource.xhr.getResponseHeader('Content-Type') || 'application/octet-stream');
|
2022-04-11 02:17:08 -04:00
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (resourceType === 'application/octet-stream')
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-04-10 02:58:33 -04:00
|
|
|
const nitroBundle = new NitroBundle(resource.data);
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
this.processAsset(nitroBundle.baseTexture, (nitroBundle.jsonFile as IAssetData), status =>
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-04-11 12:19:38 -04:00
|
|
|
onDownloaded(status, resource.url);
|
2021-03-16 22:02:09 -04:00
|
|
|
});
|
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
continue;
|
|
|
|
}
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if ((resourceType === 'image/png') || (resourceType === 'image/jpeg') || (resourceType === 'image/gif'))
|
2022-04-10 02:58:33 -04:00
|
|
|
{
|
2022-04-11 02:17:08 -04:00
|
|
|
const base64 = ArrayBufferToBase64(resource.data);
|
2022-07-18 21:51:53 -04:00
|
|
|
const baseTexture = new BaseTexture(`data:${resourceType};base64,${base64}`);
|
2022-04-11 12:19:38 -04:00
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (baseTexture.valid)
|
2022-04-11 12:19:38 -04:00
|
|
|
{
|
|
|
|
const texture = new Texture(baseTexture);
|
|
|
|
|
|
|
|
this.setTexture(resource.name, texture);
|
|
|
|
|
|
|
|
onDownloaded(true, resource.url);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
baseTexture.once('update', () =>
|
|
|
|
{
|
|
|
|
const texture = new Texture(baseTexture);
|
2022-04-11 02:17:08 -04:00
|
|
|
|
2022-04-11 12:19:38 -04:00
|
|
|
this.setTexture(resource.name, texture);
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-11 12:19:38 -04:00
|
|
|
onDownloaded(true, resource.url);
|
|
|
|
});
|
|
|
|
}
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
continue;
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
2022-04-11 02:17:08 -04:00
|
|
|
|
|
|
|
onDownloaded(false, resource.url);
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
2022-04-10 02:58:33 -04:00
|
|
|
});
|
|
|
|
}
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
private processAsset(baseTexture: BaseTexture, data: IAssetData, onDownloaded: (status: boolean) => void): void
|
|
|
|
{
|
|
|
|
const spritesheetData = data.spritesheet;
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (!baseTexture || !spritesheetData || !Object.keys(spritesheetData).length)
|
2022-04-11 12:19:38 -04:00
|
|
|
{
|
|
|
|
this.createCollection(data, null);
|
|
|
|
|
|
|
|
onDownloaded(true);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const createAsset = () =>
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-04-10 02:58:33 -04:00
|
|
|
const spritesheet = new Spritesheet(baseTexture, spritesheetData);
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-04-10 02:58:33 -04:00
|
|
|
spritesheet.parse(() =>
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
2022-04-10 02:58:33 -04:00
|
|
|
this.createCollection(data, spritesheet);
|
|
|
|
|
|
|
|
onDownloaded(true);
|
|
|
|
});
|
2022-04-11 12:19:38 -04:00
|
|
|
};
|
2021-03-16 22:02:09 -04:00
|
|
|
|
2022-11-08 16:44:41 -05:00
|
|
|
if (baseTexture.valid)
|
2022-04-11 12:19:38 -04:00
|
|
|
{
|
|
|
|
createAsset();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
baseTexture.once('update', () => createAsset());
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-13 16:34:41 -04:00
|
|
|
public get collections(): Map<string, IGraphicAssetCollection>
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
|
|
|
return this._collections;
|
|
|
|
}
|
|
|
|
}
|