123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- module BABYLON {
- /**
- * Defines the list of states available for a task inside a {BABYLON.AssetsManager}
- */
- export enum AssetTaskState {
- /**
- * Initialization
- */
- INIT,
- /**
- * Running
- */
- RUNNING,
- /**
- * Done
- */
- DONE,
- /**
- * Error
- */
- ERROR
- }
- /**
- * Define an abstract asset task used with a {BABYLON.AssetsManager} class to load assets into a scene
- */
- export abstract class AbstractAssetTask {
- /**
- * Callback called when the task is successful
- * @param task contains the successful task
- */
- public onSuccess: (task: any) => void;
- /**
- * Callback called when the task is successful
- * @param task contains the successful task
- * @param message contains the error message
- * @param exception can contains the inner exception
- */
- public onError: (task: any, message?: string, exception?: any) => void;
- /**
- * Creates a new {BABYLON.AssetsManager}
- * @param name define the name of the task
- */
- constructor(public name: string) {
- }
- private _isCompleted = false;
- private _taskState = AssetTaskState.INIT;
- private _errorObject: { message?: string; exception?: any; };
- /**
- * Get if the task is completed
- */
- public get isCompleted(): boolean {
- return this._isCompleted;
- }
- /**
- * Gets the current state of the task
- */
- public get taskState(): AssetTaskState {
- return this._taskState;
- }
- /**
- * Gets the current error object (if task is in error)
- */
- public get errorObject(): { message?: string; exception?: any; } {
- return this._errorObject;
- }
- /**
- * Internal only
- * @ignore
- */
- public _setErrorObject(message?: string, exception?: any) {
- if (this._errorObject) {
- return;
- }
- this._errorObject = {
- message: message,
- exception: exception
- };
- }
- /**
- * Execute the current task
- * @param scene defines the scene where you want your assets to be loaded
- * @param onSuccess is a callback called when the task is successfully executed
- * @param onError is a callback called if an error occurs
- */
- public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- this._taskState = AssetTaskState.RUNNING;
- this.runTask(scene, () => {
- this.onDoneCallback(onSuccess, onError);
- }, (msg, exception) => {
- this.onErrorCallback(onError, msg, exception);
- });
- }
- /**
- * Execute the current task
- * @param scene defines the scene where you want your assets to be loaded
- * @param onSuccess is a callback called when the task is successfully executed
- * @param onError is a callback called if an error occurs
- */
- public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- throw new Error("runTask is not implemented");
- }
- private onErrorCallback(onError: (message?: string, exception?: any) => void, message?: string, exception?: any) {
- this._taskState = AssetTaskState.ERROR;
- this._errorObject = {
- message: message,
- exception: exception
- }
- if (this.onError) {
- this.onError(this, message, exception);
- }
- onError();
- }
- private onDoneCallback(onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- try {
- this._taskState = AssetTaskState.DONE;
- this._isCompleted = true;
- if (this.onSuccess) {
- this.onSuccess(this);
- }
- onSuccess();
- } catch (e) {
- this.onErrorCallback(onError, "Task is done, error executing success callback(s)", e);
- }
- }
- }
- /**
- * Define the interface used by progress events raised during assets loading
- */
- export interface IAssetsProgressEvent {
- /**
- * Defines the number of remaining tasks to process
- */
- remainingCount: number;
- /**
- * Defines the total number of tasks
- */
- totalCount: number;
- /**
- * Defines the task that was just processed
- */
- task: AbstractAssetTask;
- }
- /**
- * Class used to share progress information about assets loading
- */
- export class AssetsProgressEvent implements IAssetsProgressEvent {
- /**
- * Defines the number of remaining tasks to process
- */
- public remainingCount: number;
- /**
- * Defines the total number of tasks
- */
- public totalCount: number;
- /**
- * Defines the task that was just processed
- */
- public task: AbstractAssetTask;
- /**
- * Creates a {BABYLON.AssetsProgressEvent}
- * @param remainingCount defines the number of remaining tasks to process
- * @param totalCount defines the total number of tasks
- * @param task defines the task that was just processed
- */
- constructor(remainingCount: number, totalCount: number, task: AbstractAssetTask) {
- this.remainingCount = remainingCount;
- this.totalCount = totalCount;
- this.task = task;
- }
- }
- /**
- * Define a task used by {BABYLON.AssetsManager} to load meshes
- */
- export class MeshAssetTask extends AbstractAssetTask {
- public loadedMeshes: Array<AbstractMesh>;
- public loadedParticleSystems: Array<ParticleSystem>;
- public loadedSkeletons: Array<Skeleton>;
- public onSuccess: (task: MeshAssetTask) => void;
- public onError: (task: MeshAssetTask, message?: string, exception?: any) => void;
- /**
- * Creates a new {BABYLON.MeshAssetTask}
- * @param name defines the name of the task
- * @param meshesNames
- * @param rootUrl
- * @param sceneFilename
- */
- constructor(public name: string, public meshesNames: any, public rootUrl: string, public sceneFilename: string) {
- super(name);
- }
- public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- SceneLoader.ImportMesh(this.meshesNames, this.rootUrl, this.sceneFilename, scene,
- (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => {
- this.loadedMeshes = meshes;
- this.loadedParticleSystems = particleSystems;
- this.loadedSkeletons = skeletons;
- onSuccess();
- }, null, (scene, message, exception) => {
- onError(message, exception);
- }
- );
- }
- }
- /**
- * Define a task used by {BABYLON.AssetsManager} to load text content
- */
- export class TextFileAssetTask extends AbstractAssetTask {
- public text: string;
- public onSuccess: (task: TextFileAssetTask) => void;
- public onError: (task: TextFileAssetTask, message?: string, exception?: any) => void;
- constructor(public name: string, public url: string) {
- super(name);
- }
- public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- scene._loadFile(this.url, (data) => {
- this.text = data as string;
- onSuccess();
- }, undefined, false, true, (request, exception) => {
- if (request) {
- onError(request.status + " " + request.statusText, exception);
- }
- });
- }
- }
- /**
- * Define a task used by {BABYLON.AssetsManager} to load binary data
- */
- export class BinaryFileAssetTask extends AbstractAssetTask {
- public data: ArrayBuffer;
- public onSuccess: (task: BinaryFileAssetTask) => void;
- public onError: (task: BinaryFileAssetTask, message?: string, exception?: any) => void;
- constructor(public name: string, public url: string) {
- super(name);
- }
- public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- scene._loadFile(this.url, (data) => {
- this.data = data as ArrayBuffer;
- onSuccess();
- }, undefined, true, true, (request, exception) => {
- if (request) {
- onError(request.status + " " + request.statusText, exception);
- }
- });
- }
- }
- /**
- * Define a task used by {BABYLON.AssetsManager} to load images
- */
- export class ImageAssetTask extends AbstractAssetTask {
- public image: HTMLImageElement;
- public onSuccess: (task: ImageAssetTask) => void;
- public onError: (task: ImageAssetTask, message?: string, exception?: any) => void;
- constructor(public name: string, public url: string) {
- super(name);
- }
- public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- var img = new Image();
- Tools.SetCorsBehavior(this.url, img);
- img.onload = () => {
- this.image = img;
- onSuccess();
- };
- img.onerror = (err: ErrorEvent): any => {
- onError("Error loading image", err);
- };
- img.src = this.url;
- }
- }
- export interface ITextureAssetTask<TEX extends BaseTexture> {
- texture: TEX;
- }
- /**
- * Define a task used by {BABYLON.AssetsManager} to load 2D textures
- */
- export class TextureAssetTask extends AbstractAssetTask implements ITextureAssetTask<Texture> {
- public texture: Texture;
- public onSuccess: (task: TextureAssetTask) => void;
- public onError: (task: TextureAssetTask, message?: string, exception?: any) => void;
- constructor(public name: string, public url: string, public noMipmap?: boolean, public invertY?: boolean, public samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
- super(name);
- }
- public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- var onload = () => {
- onSuccess();
- };
- var onerror = (message?: string, exception?: any) => {
- onError(message, exception);
- };
- this.texture = new Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onerror);
- }
- }
- /**
- * Define a task used by {BABYLON.AssetsManager} to load cube textures
- */
- export class CubeTextureAssetTask extends AbstractAssetTask implements ITextureAssetTask<CubeTexture> {
- public texture: CubeTexture;
- public onSuccess: (task: CubeTextureAssetTask) => void;
- public onError: (task: CubeTextureAssetTask, message?: string, exception?: any) => void;
- constructor(public name: string, public url: string, public extensions?: string[], public noMipmap?: boolean, public files?: string[]) {
- super(name);
- }
- public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- var onload = () => {
- onSuccess();
- };
- var onerror = (message?: string, exception?: any) => {
- onError(message, exception);
- };
- this.texture = new CubeTexture(this.url, scene, this.extensions, this.noMipmap, this.files, onload, onerror);
- }
- }
- /**
- * Define a task used by {BABYLON.AssetsManager} to load HDR cube textures
- */
- export class HDRCubeTextureAssetTask extends AbstractAssetTask implements ITextureAssetTask<HDRCubeTexture> {
- public texture: HDRCubeTexture;
- public onSuccess: (task: HDRCubeTextureAssetTask) => void;
- public onError: (task: HDRCubeTextureAssetTask, message?: string, exception?: any) => void;
- constructor(public name: string, public url: string, public size?: number, public noMipmap = false, public generateHarmonics = true, public useInGammaSpace = false, public usePMREMGenerator = false) {
- super(name);
- }
- public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
- var onload = () => {
- onSuccess();
- };
- var onerror = (message?: string, exception?: any) => {
- onError(message, exception);
- };
- this.texture = new HDRCubeTexture(this.url, scene, this.size, this.noMipmap, this.generateHarmonics, this.useInGammaSpace, this.usePMREMGenerator, onload, onerror);
- }
- }
- /**
- * This class can be used to easily import assets into a scene
- * @see http://doc.babylonjs.com/how_to/how_to_use_assetsmanager
- */
- export class AssetsManager {
- private _scene: Scene;
- private _isLoading = false;
- protected tasks = new Array<AbstractAssetTask>();
- protected waitingTasksCount = 0;
- protected totalTasksCount = 0;
- /**
- * Callback called when all tasks are processed
- * @param tasks will contains all remaining tasks (ie. all tasks which were not successful)
- */
- public onFinish: (tasks: AbstractAssetTask[]) => void;
- /**
- * Callback called when a task is successful
- * @param task defines the loaded task
- */
- public onTaskSuccess: (task: AbstractAssetTask) => void;
- /**
- * Callback called when a task had an error
- * @param task defines failed task
- */
- public onTaskError: (task: AbstractAssetTask) => void;
- /**
- * Callback called when a task is done (whatever the result is)
- * @param remainingCount defines the number of remaining tasks to process
- * @param totalCount defines the total number of tasks
- * @param task defines the task that was just processed
- */
- public onProgress: (remainingCount: number, totalCount: number, task: AbstractAssetTask) => void;
- //Observables
- /**
- * Observable called when all tasks are processed
- */
- public onTaskSuccessObservable = new Observable<AbstractAssetTask>();
- /**
- * Observable called when a task had an error
- */
- public onTaskErrorObservable = new Observable<AbstractAssetTask>();
- /**
- * Observable called when a task is successful
- */
- public onTasksDoneObservable = new Observable<AbstractAssetTask[]>();
- /**
- * Observable called when a task is done (whatever the result is)
- */
- public onProgressObservable = new Observable<IAssetsProgressEvent>();
- /**
- * Gets or sets a boolean defining if the {BABYLON.AssetsManager} should use the default loading screen
- * @see http://doc.babylonjs.com/how_to/creating_a_custom_loading_screen
- */
- public useDefaultLoadingScreen = true;
- constructor(scene: Scene) {
- this._scene = scene;
- }
- /**
- * Add a {BABYLON.MeshAssetTask} to the list of active tasks
- * @param taskName defines the name of the new task
- * @param meshesNames defines the name of meshes to load
- * @param rootUrl defines the root url to use to locate files
- * @param sceneFilename defines the filename of the scene file
- */
- public addMeshTask(taskName: string, meshesNames: any, rootUrl: string, sceneFilename: string): MeshAssetTask {
- var task = new MeshAssetTask(taskName, meshesNames, rootUrl, sceneFilename);
- this.tasks.push(task);
- return task;
- }
- /**
- * Add a {BABYLON.TextFileAssetTask} to the list of active tasks
- * @param taskName defines the name of the new task
- * @param url defines the url of the file to load
- */
- public addTextFileTask(taskName: string, url: string): TextFileAssetTask {
- var task = new TextFileAssetTask(taskName, url);
- this.tasks.push(task);
- return task;
- }
- /**
- * Add a {BABYLON.BinaryFileAssetTask} to the list of active tasks
- * @param taskName defines the name of the new task
- * @param url defines the url of the file to load
- */
- public addBinaryFileTask(taskName: string, url: string): BinaryFileAssetTask {
- var task = new BinaryFileAssetTask(taskName, url);
- this.tasks.push(task);
- return task;
- }
- /**
- * Add a {BABYLON.ImageAssetTask} to the list of active tasks
- * @param taskName defines the name of the new task
- * @param url defines the url of the file to load
- */
- public addImageTask(taskName: string, url: string): ImageAssetTask {
- var task = new ImageAssetTask(taskName, url);
- this.tasks.push(task);
- return task;
- }
- /**
- * Add a {BABYLON.TextureAssetTask} to the list of active tasks
- * @param taskName defines the name of the new task
- * @param url defines the url of the file to load
- * @param noMipmap defines if the texture must not receive mipmaps (false by default)
- * @param invertY defines if you want to invert Y axis of the loaded texture (false by default)
- * @param samplingMode defines the sampling mode to use (BABYLON.Texture.TRILINEAR_SAMPLINGMODE by default)
- */
- public addTextureTask(taskName: string, url: string, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE): TextureAssetTask {
- var task = new TextureAssetTask(taskName, url, noMipmap, invertY, samplingMode);
- this.tasks.push(task);
- return task;
- }
- /**
- * Add a {BABYLON.CubeTextureAssetTask} to the list of active tasks
- * @param taskName defines the name of the new task
- * @param url defines the url of the file to load
- * @param extensions defines the extension to use to load the cube map (can be null)
- * @param noMipmap defines if the texture must not receive mipmaps (false by default)
- * @param files defines the list of files to load (can be null)
- */
- public addCubeTextureTask(taskName: string, url: string, extensions?: string[], noMipmap?: boolean, files?: string[]): CubeTextureAssetTask {
- var task = new CubeTextureAssetTask(taskName, url, extensions, noMipmap, files);
- this.tasks.push(task);
- return task;
- }
- /**
- *
- * Add a {BABYLON.HDRCubeTextureAssetTask} to the list of active tasks
- * @param taskName defines the name of the new task
- * @param url defines the url of the file to load
- * @param size defines the size you want for the cubemap (can be null)
- * @param noMipmap defines if the texture must not receive mipmaps (false by default)
- * @param generateHarmonics defines if you want to automatically generate (true by default)
- * @param useInGammaSpace defines if the texture must be considered in gamma space (false by default)
- * @param usePMREMGenerator is a reserved parameter and must be set to false or ignored
- */
- public addHDRCubeTextureTask(taskName: string, url: string, size?: number, noMipmap = false, generateHarmonics = true, useInGammaSpace = false, usePMREMGenerator = false): HDRCubeTextureAssetTask {
- var task = new HDRCubeTextureAssetTask(taskName, url, size, noMipmap, generateHarmonics, useInGammaSpace, usePMREMGenerator);
- this.tasks.push(task);
- return task;
- }
- private _decreaseWaitingTasksCount(task: AbstractAssetTask): void {
- this.waitingTasksCount--;
- try {
- if (task.taskState === AssetTaskState.DONE) {
- // Let's remove successfull tasks
- Tools.SetImmediate(() => {
- let index = this.tasks.indexOf(task);
- if (index > -1) {
- this.tasks.splice(index, 1);
- }
- });
- }
- if (this.onProgress) {
- this.onProgress(
- this.waitingTasksCount,
- this.totalTasksCount,
- task
- );
- }
- this.onProgressObservable.notifyObservers(
- new AssetsProgressEvent(
- this.waitingTasksCount,
- this.totalTasksCount,
- task
- )
- );
- } catch (e) {
- Tools.Error("Error running progress callbacks.");
- console.log(e);
- }
- if (this.waitingTasksCount === 0) {
- try {
- if (this.onFinish) {
- this.onFinish(this.tasks);
- }
- this.onTasksDoneObservable.notifyObservers(this.tasks);
- } catch (e) {
- Tools.Error("Error running tasks-done callbacks.");
- console.log(e);
- }
- this._isLoading = false;
- this._scene.getEngine().hideLoadingUI();
- }
- }
- private _runTask(task: AbstractAssetTask): void {
- let done = () => {
- try {
- if (this.onTaskSuccess) {
- this.onTaskSuccess(task);
- }
- this.onTaskSuccessObservable.notifyObservers(task);
- this._decreaseWaitingTasksCount(task);
- } catch (e) {
- error("Error executing task success callbacks", e);
- }
- }
- let error = (message?: string, exception?: any) => {
- task._setErrorObject(message, exception);
- if (this.onTaskError) {
- this.onTaskError(task);
- }
- this.onTaskErrorObservable.notifyObservers(task);
- this._decreaseWaitingTasksCount(task);
- }
- task.run(this._scene, done, error);
- }
- /**
- * Reset the {BABYLON.AssetsManager} and remove all tasks
- * @return the current instance of the {BABYLON.AssetsManager}
- */
- public reset(): AssetsManager {
- this._isLoading = false;
- this.tasks = new Array<AbstractAssetTask>();
- return this;
- }
- /**
- * Start the loading process
- * @return the current instance of the {BABYLON.AssetsManager}
- */
- public load(): AssetsManager {
- if (this._isLoading) {
- return this;
- }
- this._isLoading = true;
- this.waitingTasksCount = this.tasks.length;
- this.totalTasksCount = this.tasks.length;
- if (this.waitingTasksCount === 0) {
- if (this.onFinish) {
- this.onFinish(this.tasks);
- }
- this.onTasksDoneObservable.notifyObservers(this.tasks);
- return this;
- }
- if (this.useDefaultLoadingScreen) {
- this._scene.getEngine().displayLoadingUI();
- }
- for (var index = 0; index < this.tasks.length; index++) {
- var task = this.tasks[index];
- this._runTask(task);
- }
- return this;
- }
- }
- }
|