nitro-renderer/src/core/asset/AssetManager.ts

254 lines
6.8 KiB
TypeScript
Raw Normal View History

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
{
2022-07-24 23:17:40 -04:00
if(!name) return null;
2021-03-16 22:02:09 -04:00
const existing = this._textures.get(name);
2022-07-24 23:17:40 -04: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-07-24 23:17:40 -04:00
if(!name || !texture) return;
2021-03-16 22:02:09 -04:00
this._textures.set(name, texture);
}
public getAsset(name: string): IGraphicAsset
{
2022-07-24 23:17:40 -04:00
if(!name) return null;
2021-03-16 22:02:09 -04:00
2022-07-24 23:17:40 -04:00
for(const collection of this._collections.values())
2021-03-16 22:02:09 -04:00
{
2022-07-24 23:17:40 -04:00
if(!collection) continue;
2021-03-16 22:02:09 -04:00
const existing = collection.getAsset(name);
2022-07-24 23:17:40 -04:00
if(!existing) continue;
2021-03-16 22:02:09 -04:00
return existing;
}
return null;
}
public getCollection(name: string): IGraphicAssetCollection
{
2022-07-24 23:17:40 -04:00
if(!name) return null;
2021-03-16 22:02:09 -04:00
const existing = this._collections.get(name);
2022-07-24 23:17:40 -04:00
if(!existing) return null;
2021-03-16 22:02:09 -04:00
return existing;
}
public createCollection(data: IAssetData, spritesheet: Spritesheet): IGraphicAssetCollection
{
2022-07-24 23:17:40 -04:00
if(!data) return null;
2021-03-16 22:02:09 -04:00
const collection = new GraphicAssetCollection(data, spritesheet);
2022-07-24 23:17:40 -04:00
if(collection)
2021-03-16 22:02:09 -04:00
{
2022-07-24 23:17:40 -04: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-07-24 23:17:40 -04: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-07-24 23:17:40 -04:00
for(const url of assetUrls)
2021-03-16 22:02:09 -04:00
{
2022-07-24 23:17:40 -04: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-07-24 23:17:40 -04:00
if(!status)
2022-04-10 02:58:33 -04:00
{
2022-07-18 21:51:53 -04:00
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--;
2022-07-24 23:17:40 -04: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-07-24 23:17:40 -04: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-07-24 23:17:40 -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
2022-07-24 23:17:40 -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-07-24 23:17:40 -04: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-07-24 23:17:40 -04: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-07-24 23:17:40 -04: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-07-24 23:17:40 -04: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;
}
}