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-04-11 02:17:08 -04:00
|
|
|
import { IGraphicAsset } from '../../room/object/visualization/utils';
|
2021-03-16 22:02:09 -04:00
|
|
|
import { GraphicAssetCollection } from '../../room/object/visualization/utils/GraphicAssetCollection';
|
|
|
|
import { IGraphicAssetCollection } from '../../room/object/visualization/utils/IGraphicAssetCollection';
|
|
|
|
import { Disposable } from '../common/disposable/Disposable';
|
|
|
|
import { INitroLogger } from '../common/logger/INitroLogger';
|
|
|
|
import { NitroLogger } from '../common/logger/NitroLogger';
|
2022-04-11 02:17:08 -04:00
|
|
|
import { ArrayBufferToBase64 } from '../utils';
|
2021-03-16 22:02:09 -04:00
|
|
|
import { IAssetManager } from './IAssetManager';
|
|
|
|
import { IAssetData } from './interfaces';
|
|
|
|
import { NitroBundle } from './NitroBundle';
|
|
|
|
|
|
|
|
export class AssetManager extends Disposable implements IAssetManager
|
|
|
|
{
|
|
|
|
private _logger: INitroLogger;
|
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._logger = new NitroLogger(this.constructor.name);
|
|
|
|
this._textures = new Map();
|
|
|
|
this._collections = new Map();
|
2021-03-16 22:02:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public static removeFileExtension(name: string): string
|
|
|
|
{
|
|
|
|
return (name.substring(0, name.lastIndexOf('.')) || name);
|
|
|
|
}
|
|
|
|
|
2021-07-14 03:10:54 -04:00
|
|
|
public getTexture(name: string): Texture<Resource>
|
2021-03-16 22:02:09 -04:00
|
|
|
{
|
|
|
|
if(!name) return null;
|
|
|
|
|
|
|
|
const existing = this._textures.get(name);
|
|
|
|
|
|
|
|
if(!existing) return null;
|
|
|
|
|
|
|
|
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
|
|
|
{
|
|
|
|
if(!name || !texture) return;
|
|
|
|
|
|
|
|
this._textures.set(name, texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
public getAsset(name: string): IGraphicAsset
|
|
|
|
{
|
|
|
|
if(!name) return null;
|
|
|
|
|
|
|
|
for(const collection of this._collections.values())
|
|
|
|
{
|
|
|
|
if(!collection) continue;
|
|
|
|
|
|
|
|
const existing = collection.getAsset(name);
|
|
|
|
|
|
|
|
if(!existing) continue;
|
|
|
|
|
|
|
|
return existing;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public getCollection(name: string): IGraphicAssetCollection
|
|
|
|
{
|
|
|
|
if(!name) return null;
|
|
|
|
|
|
|
|
const existing = this._collections.get(name);
|
|
|
|
|
|
|
|
if(!existing) return null;
|
|
|
|
|
|
|
|
return existing;
|
|
|
|
}
|
|
|
|
|
|
|
|
public createCollection(data: IAssetData, spritesheet: Spritesheet): IGraphicAssetCollection
|
|
|
|
{
|
|
|
|
if(!data) return null;
|
|
|
|
|
|
|
|
const collection = new GraphicAssetCollection(data, spritesheet);
|
|
|
|
|
|
|
|
if(collection)
|
|
|
|
{
|
|
|
|
for(const [ name, texture ] of collection.textures.entries()) this.setTexture(name, texture);
|
|
|
|
|
|
|
|
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-04-10 02:58:33 -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
|
|
|
{
|
|
|
|
if(!assetUrls || !assetUrls.length)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
|
|
|
for(const url of assetUrls)
|
|
|
|
{
|
|
|
|
if(!url) continue;
|
|
|
|
|
|
|
|
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-04-10 02:58:33 -04:00
|
|
|
if(!status)
|
|
|
|
{
|
|
|
|
this._logger.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--;
|
|
|
|
|
|
|
|
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) =>
|
|
|
|
{
|
|
|
|
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-04-11 02:17:08 -04: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
|
|
|
|
|
|
|
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-06-27 00:19:54 +00: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-04-11 12:19:38 -04:00
|
|
|
const baseTexture = new BaseTexture(`data:${ resourceType };base64,${ base64 }`);
|
|
|
|
|
|
|
|
if(baseTexture.valid)
|
|
|
|
{
|
|
|
|
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-04-11 12:19:38 -04:00
|
|
|
if(!baseTexture || !spritesheetData || !Object.keys(spritesheetData).length)
|
|
|
|
{
|
|
|
|
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-04-11 12:19:38 -04:00
|
|
|
if(baseTexture.valid)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|