Update asset loader to async

This commit is contained in:
Bill 2022-11-14 00:22:26 -05:00
parent 206c5eaa1c
commit c21eb0e699
8 changed files with 177 additions and 234 deletions

View File

@ -1,7 +1,5 @@
import { BaseTexture, Resource, Texture } from '@pixi/core';
import { Loader, LoaderResource } from '@pixi/loaders';
import { Spritesheet } from '@pixi/spritesheet';
import { NitroLogger } from '../common';
import { ArrayBufferToBase64, NitroBundle } from '../utils';
import { GraphicAssetCollection } from './GraphicAssetCollection';
import { IAssetData } from './IAssetData';
@ -79,123 +77,77 @@ export class AssetManager implements IAssetManager
return collection;
}
public downloadAsset(assetUrl: string, cb: (status: boolean) => void): void
public async downloadAsset(url: string): Promise<boolean>
{
this.downloadAssets([assetUrl], cb);
return await this.downloadAssets([url]);
}
public downloadAssets(assetUrls: string[], cb: (status: boolean) => void): void
public async downloadAssets(urls: string[]): Promise<boolean>
{
if(!assetUrls || !assetUrls.length)
{
cb(true);
if(!urls || !urls.length) return true;
return;
const responses = await Promise.all(urls.map(url => fetch(url)));
if(!responses || !responses.length) return false;
try
{
for(const response of responses)
{
const contentType = response.headers.get('Content-Type');
switch(contentType)
{
case 'application/octet-stream': {
const nitroBundle = new NitroBundle(await response.arrayBuffer());
await this.processAsset(nitroBundle.baseTexture, (nitroBundle.jsonFile as IAssetData));
break;
}
case 'image/png':
case 'image/jpeg':
case 'image/gif': {
const base64 = ArrayBufferToBase64(await response.arrayBuffer());
const baseTexture = BaseTexture.from(`data:${contentType};base64,${base64}`);
const loader = new Loader();
for(const url of assetUrls)
const createAsset = async () =>
{
if(!url) continue;
const texture = new Texture(baseTexture);
loader
.add({
url,
crossOrigin: 'anonymous',
loadType: LoaderResource.LOAD_TYPE.XHR,
xhrType: LoaderResource.XHR_RESPONSE_TYPE.BUFFER
});
}
let remaining = assetUrls.length;
const onDownloaded = (status: boolean, url: string) =>
{
if(!status)
{
NitroLogger.error('Failed to download asset', url);
loader.destroy();
cb(false);
return;
}
remaining--;
if(!remaining)
{
loader.destroy();
cb(true);
return;
}
this.setTexture(response.url, texture);
};
loader.load((loader, resources) =>
{
for(const key in resources)
{
const resource = resources[key];
if(!resource || resource.error || !resource.xhr)
{
onDownloaded(false, resource.url);
return;
}
const resourceType = (resource.xhr.getResponseHeader('Content-Type') || 'application/octet-stream');
if(resourceType === 'application/octet-stream')
{
const nitroBundle = new NitroBundle(resource.data);
this.processAsset(nitroBundle.baseTexture, (nitroBundle.jsonFile as IAssetData), status =>
{
onDownloaded(status, resource.url);
});
continue;
}
if((resourceType === 'image/png') || (resourceType === 'image/jpeg') || (resourceType === 'image/gif'))
{
const base64 = ArrayBufferToBase64(resource.data);
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);
await createAsset();
}
else
{
baseTexture.once('update', () =>
await new Promise<void>((resolve, reject) =>
{
const texture = new Texture(baseTexture);
baseTexture.once('update', async () =>
{
await createAsset();
this.setTexture(resource.name, texture);
onDownloaded(true, resource.url);
return resolve();
});
});
}
continue;
break;
}
}
}
}
onDownloaded(false, resource.url);
}
});
catch (err)
{
console.error(err);
}
private processAsset(baseTexture: BaseTexture, data: IAssetData, onDownloaded: (status: boolean) => void): void
return true;
}
private async processAsset(baseTexture: BaseTexture, data: IAssetData): Promise<void>
{
const spritesheetData = data.spritesheet;
@ -203,30 +155,39 @@ export class AssetManager implements IAssetManager
{
this.createCollection(data, null);
onDownloaded(true);
return;
}
const createAsset = () =>
const createAsset = async () =>
{
const spritesheet = new Spritesheet(baseTexture, spritesheetData);
return new Promise<void>((resolve, reject) =>
{
spritesheet.parse(() =>
{
this.createCollection(data, spritesheet);
onDownloaded(true);
return resolve();
});
});
};
if(baseTexture.valid)
{
createAsset();
await createAsset();
}
else
{
baseTexture.once('update', () => createAsset());
await new Promise<void>((resolve, reject) =>
{
baseTexture.once('update', async () =>
{
await createAsset();
return resolve();
});
});
}
}

View File

@ -12,7 +12,7 @@ export interface IAssetManager
getAsset(name: string): IGraphicAsset;
getCollection(name: string): IGraphicAssetCollection;
createCollection(data: IAssetData, spritesheet: Spritesheet): IGraphicAssetCollection;
downloadAssets(urls: string[], cb: Function): void;
downloadAsset(url: string, cb: Function): void;
downloadAssets(urls: string[]): Promise<boolean>;
downloadAsset(url: string): Promise<boolean>;
collections: Map<string, IGraphicAssetCollection>;
}

View File

@ -34,7 +34,7 @@ export class AvatarAssetDownloadLibrary extends EventDispatcher implements IAvat
if(asset) this._state = AvatarAssetDownloadLibrary.LOADED;
}
public downloadAsset(): void
public async downloadAsset(): Promise<void>
{
if(!this._assets || (this._state === AvatarAssetDownloadLibrary.LOADING) || (this._state === AvatarAssetDownloadLibrary.LOADED)) return;
@ -51,16 +51,14 @@ export class AvatarAssetDownloadLibrary extends EventDispatcher implements IAvat
this._state = AvatarAssetDownloadLibrary.LOADING;
this._assets.downloadAsset(this._downloadUrl, (flag: boolean) =>
{
if(flag)
{
const status = await this._assets.downloadAsset(this._downloadUrl);
if(!status) return;
this._state = AvatarAssetDownloadLibrary.LOADED;
this.dispatchEvent(new AvatarRenderLibraryEvent(AvatarRenderLibraryEvent.DOWNLOAD_COMPLETE, this));
}
});
}
public get libraryName(): string
{

View File

@ -36,7 +36,7 @@ export class EffectAssetDownloadLibrary extends EventDispatcher implements IEffe
if(asset) this._state = EffectAssetDownloadLibrary.LOADED;
}
public downloadAsset(): void
public async downloadAsset(): Promise<void>
{
if(!this._assets || (this._state === EffectAssetDownloadLibrary.LOADING) || (this._state === EffectAssetDownloadLibrary.LOADED)) return;
@ -53,10 +53,10 @@ export class EffectAssetDownloadLibrary extends EventDispatcher implements IEffe
this._state = EffectAssetDownloadLibrary.LOADING;
this._assets.downloadAsset(this._downloadUrl, (flag: boolean) =>
{
if(flag)
{
const status = await this._assets.downloadAsset(this._downloadUrl);
if(!status) return;
this._state = EffectAssetDownloadLibrary.LOADED;
const collection = this._assets.getCollection(this._libraryName);
@ -65,8 +65,6 @@ export class EffectAssetDownloadLibrary extends EventDispatcher implements IEffe
this.dispatchEvent(new AvatarRenderEffectLibraryEvent(AvatarRenderEffectLibraryEvent.DOWNLOAD_COMPLETE, this));
}
});
}
public get libraryName(): string
{

View File

@ -1,5 +1,4 @@
import { BaseTexture, Resource, Texture } from '@pixi/core';
import { Loader, LoaderResource } from '@pixi/loaders';
import { Spritesheet } from '@pixi/spritesheet';
import { FurnitureType, GetAssetManager, GraphicAssetCollection, GraphicAssetGifCollection, IAssetData, IEventDispatcher, IFurnitureData, IFurnitureDataListener, IGraphicAssetCollection, IGraphicAssetGifCollection, IPetColorResult, IRoomContentListener, IRoomContentLoader, IRoomObject, ISessionDataManager, NitroBundle, NitroConfiguration, NitroLogger, RoomObjectCategory, RoomObjectUserType, RoomObjectVariable, RoomObjectVisualizationType } from '../../api';
import { NitroEvent } from '../../events';
@ -481,94 +480,48 @@ export class RoomContentLoader implements IFurnitureDataListener, IRoomContentLo
return false;
}
public downloadAsset(type: string, events: IEventDispatcher): void
public async downloadAsset(type: string, events: IEventDispatcher): Promise<void>
{
const assetUrls: string[] = this.getAssetUrls(type);
const assetUrl: string = this.getAssetUrls(type)?.[0];
if(!assetUrls || !assetUrls.length) return;
if(!assetUrl || !assetUrl.length) return;
if((this._pendingContentTypes.indexOf(type) >= 0) || this.getOrRemoveEventDispatcher(type)) return;
this._pendingContentTypes.push(type);
this._events.set(type, events);
const loader = new Loader();
for(const url of assetUrls)
try
{
if(!url || !url.length) continue;
const response = await fetch(assetUrl);
const contentType = response.headers.get('Content-Type');
loader
.add({
url,
crossOrigin: 'anonymous',
loadType: LoaderResource.LOAD_TYPE.XHR,
xhrType: LoaderResource.XHR_RESPONSE_TYPE.BUFFER
});
}
let remaining = assetUrls.length;
const onDownloaded = (status: boolean, url: string) =>
switch(contentType)
{
if(!status)
{
NitroLogger.error('Failed to download asset', url);
case 'application/octet-stream': {
const nitroBundle = new NitroBundle(await response.arrayBuffer());
loader.destroy();
events.dispatchEvent(new RoomContentLoadedEvent(RoomContentLoadedEvent.RCLE_FAILURE, type));
return;
}
remaining--;
if(!remaining)
{
loader.destroy();
await this.processAsset(nitroBundle.baseTexture, (nitroBundle.jsonFile as IAssetData));
const events = this._events.get(type);
if(!events) return;
events.dispatchEvent(new RoomContentLoadedEvent(RoomContentLoadedEvent.RCLE_SUCCESS, type));
return;
break;
}
};
loader.load((loader, resources) =>
{
for(const key in resources)
{
const resource = resources[key];
if(!resource || resource.error || !resource.xhr)
{
onDownloaded(false, resource.url);
return;
}
const resourceType = (resource.xhr.getResponseHeader('Content-Type') || 'application/octet-stream');
if(resourceType === 'application/octet-stream')
{
const nitroBundle = new NitroBundle(resource.data);
this.processAsset(nitroBundle.baseTexture, (nitroBundle.jsonFile as IAssetData), status =>
{
onDownloaded(status, resource.url);
});
continue;
default:
throw new Error();
}
}
});
catch (err)
{
events.dispatchEvent(new RoomContentLoadedEvent(RoomContentLoadedEvent.RCLE_FAILURE, type));
}
}
private processAsset(baseTexture: BaseTexture, data: IAssetData, onDownloaded: (status: boolean) => void): void
private async processAsset(baseTexture: BaseTexture, data: IAssetData): Promise<void>
{
const spritesheetData = data.spritesheet;
@ -576,30 +529,39 @@ export class RoomContentLoader implements IFurnitureDataListener, IRoomContentLo
{
this.createCollection(data, null);
onDownloaded(true);
return;
}
const createAsset = () =>
const createAsset = async () =>
{
const spritesheet = new Spritesheet(baseTexture, spritesheetData);
return new Promise<void>((resolve, reject) =>
{
spritesheet.parse(() =>
{
this.createCollection(data, spritesheet);
onDownloaded(true);
return resolve();
});
});
};
if(baseTexture.valid)
{
createAsset();
await createAsset();
}
else
{
baseTexture.once('update', () => createAsset());
await new Promise<void>((resolve, reject) =>
{
baseTexture.once('update', async () =>
{
await createAsset();
return resolve();
});
});
}
}

View File

@ -134,7 +134,7 @@ export class FurnitureRoomBrandingLogic extends FurnitureLogic
super.mouseEvent(event, geometry);
}
private downloadBackground(): void
private async downloadBackground(): Promise<void>
{
const model = this.object && this.object.model;
@ -216,17 +216,16 @@ export class FurnitureRoomBrandingLogic extends FurnitureLogic
if(!texture)
{
asset.downloadAsset(imageUrl, (flag: boolean) =>
{
if(flag)
{
this.processUpdateMessage(new ObjectAdUpdateMessage(ObjectAdUpdateMessage.IMAGE_LOADED));
}
else
const status = await asset.downloadAsset(imageUrl);
if(!status)
{
this.processUpdateMessage(new ObjectAdUpdateMessage(ObjectAdUpdateMessage.IMAGE_LOADING_FAILED));
}
});
else
{
this.processUpdateMessage(new ObjectAdUpdateMessage(ObjectAdUpdateMessage.IMAGE_LOADED));
}
return;
}

View File

@ -1,7 +1,7 @@
import { RenderTexture, Resource, Texture } from '@pixi/core';
import { Resource, Texture } from '@pixi/core';
import { Matrix } from '@pixi/math';
import { IGraphicAsset, IRoomObjectSprite, RoomObjectVariable } from '../../../../../api';
import { NitroSprite, PixiApplicationProxy } from '../../../../../pixi-proxy';
import { NitroSprite, TextureUtils } from '../../../../../pixi-proxy';
import { IsometricImageFurniVisualization } from './IsometricImageFurniVisualization';
export class FurnitureGuildIsometricBadgeVisualization extends IsometricImageFurniVisualization
@ -42,8 +42,6 @@ export class FurnitureGuildIsometricBadgeVisualization extends IsometricImageFur
const matrix = new Matrix();
const difference = (asset.width / texture.width);
console.log(((0.5 * difference) * texture.width));
switch(this.direction)
{
case 2:
@ -52,7 +50,7 @@ export class FurnitureGuildIsometricBadgeVisualization extends IsometricImageFur
matrix.c = 0;
matrix.d = (difference * scale);
matrix.tx = 0;
matrix.ty = 20;
matrix.ty = ((0.5 * difference) * texture.width);
break;
case 0:
case 4:
@ -74,18 +72,40 @@ export class FurnitureGuildIsometricBadgeVisualization extends IsometricImageFur
const sprite = new NitroSprite(texture);
sprite.transform.setFromMatrix(matrix);
sprite.position.set(0);
return TextureUtils.generateTexture(sprite);
/* const renderTexture = RenderTexture.create({
width: asset.width,
height: asset.height
});
PixiApplicationProxy.instance.renderer.render(sprite, {
renderTexture,
clear: true,
});
return renderTexture; */
/* const sprite = new NitroSprite(texture);
const renderTexture = RenderTexture.create({
width: (asset.width + matrix.tx),
height: (asset.height + matrix.ty)
});
sprite.position.set(0)
PixiApplicationProxy.instance.renderer.render(sprite, {
renderTexture,
clear: true,
transform: matrix
});
return renderTexture;
return renderTexture; */
}
protected getLayerColor(scale: number, layerId: number, colorId: number): number

View File

@ -106,16 +106,21 @@ export class BadgeImageManager implements IDisposable
this._requestedBadges.set(badgeName, true);
this._assets.downloadAsset(url, (flag: boolean) =>
{
if(flag)
this._assets
.downloadAsset(url)
.then(status =>
{
if(!status) return;
this._requestedBadges.delete(badgeName);
const texture = this._assets.getTexture(url);
if(texture && this._sessionDataManager) this._sessionDataManager.events.dispatchEvent(new BadgeImageReadyEvent(badgeName, texture.clone()));
}
})
.catch(err =>
{
});
}