Gary Hsu před 7 roky
rodič
revize
0180e5b519

+ 31 - 14
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -68,10 +68,10 @@ module BABYLON.GLTF2 {
 
             this._disposed = true;
 
-            this._abortRequests();
-            this._releaseResources();
-
             this.onDisposeObservable.notifyObservers(this);
+            this.onDisposeObservable.clear();
+
+            this._clear();
         }
 
         public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[] }> {
@@ -115,11 +115,7 @@ module BABYLON.GLTF2 {
 
         private _loadAsync(nodes: Nullable<Array<ILoaderNode>>, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
             return Promise.resolve().then(() => {
-                for (const name of GLTFLoader._Names) {
-                    const extension = GLTFLoader._Factories[name](this);
-                    this._extensions[name] = extension;
-                    this.onExtensionLoadedObservable.notifyObservers(extension);
-                }
+                this._loadExtensions();
 
                 this._babylonScene = scene;
                 this._rootUrl = rootUrl;
@@ -153,23 +149,35 @@ module BABYLON.GLTF2 {
                     Tools.SetImmediate(() => {
                         if (!this._disposed) {
                             Promise.all(this._completePromises).then(() => {
-                                this._releaseResources();
                                 this._state = GLTFLoaderState.Complete;
                                 this.onCompleteObservable.notifyObservers(this);
+                                this.onCompleteObservable.clear();
+                                this._clear();
                             }).catch(error => {
                                 Tools.Error("glTF Loader: " + error.message);
-                                this.dispose();
+                                this._clear();
                             });
                         }
                     });
                 });
             }).catch(error => {
                 Tools.Error("glTF Loader: " + error.message);
-                this.dispose();
+                this._clear();
                 throw error;
             });
         }
 
+        private _loadExtensions(): void {
+            for (const name of GLTFLoader._Names) {
+                const extension = GLTFLoader._Factories[name](this);
+                this._extensions[name] = extension;
+
+                this.onExtensionLoadedObservable.notifyObservers(extension);
+            }
+
+            this.onExtensionLoadedObservable.clear();
+        }
+
         private _loadData(data: IGLTFLoaderData): void {
             this._gltf = data.json as ILoaderGLTF;
             this._setupData();
@@ -1513,15 +1521,13 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
         }
 
-        private _abortRequests(): void {
+        private _clear(): void {
             for (const request of this._requests) {
                 request.abort();
             }
 
             this._requests.length = 0;
-        }
 
-        private _releaseResources(): void {
             if (this._gltf.images) {
                 for (const image of this._gltf.images) {
                     if (image._objectURL) {
@@ -1533,6 +1539,17 @@ module BABYLON.GLTF2 {
                     }
                 }
             }
+
+            delete this._gltf;
+            delete this._babylonScene;
+            this._completePromises.length = 0;
+            this._extensions = {};
+            delete this._rootBabylonMesh;
+            delete this._progressCallback;
+
+            this.onMeshLoadedObservable.clear();
+            this.onTextureLoadedObservable.clear();
+            this.onMaterialLoadedObservable.clear();
         }
 
         public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>) {

+ 1 - 2
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -3,6 +3,7 @@
 module BABYLON.GLTF2 {
     export abstract class GLTFLoaderExtension implements IGLTFLoaderExtension {
         public enabled = true;
+        public abstract readonly name: string;
 
         protected _loader: GLTFLoader;
 
@@ -10,8 +11,6 @@ module BABYLON.GLTF2 {
             this._loader = loader;
         }
 
-        public abstract readonly name: string;
-
         // #region Overridable Methods
 
         /** Override this method to modify the default behavior for loading scenes. */

+ 12 - 3
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -239,11 +239,9 @@ module BABYLON {
                 this._loader = null;
             }
 
-            this.onParsedObservable.clear();
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
-            this.onCompleteObservable.clear();
 
             this.onDisposeObservable.notifyObservers(this);
             this.onDisposeObservable.clear();
@@ -303,6 +301,8 @@ module BABYLON {
             }
 
             this.onParsedObservable.notifyObservers(parsedData);
+            this.onParsedObservable.clear();
+
             return parsedData;
         }
 
@@ -346,8 +346,17 @@ module BABYLON {
             loader.onMeshLoadedObservable.add(mesh => this.onMeshLoadedObservable.notifyObservers(mesh));
             loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
             loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));
-            loader.onCompleteObservable.add(() => this.onCompleteObservable.notifyObservers(this));
             loader.onExtensionLoadedObservable.add(extension => this.onExtensionLoadedObservable.notifyObservers(extension));
+
+            loader.onCompleteObservable.add(() => {
+                this.onMeshLoadedObservable.clear();
+                this.onTextureLoadedObservable.clear();
+                this.onMaterialLoadedObservable.clear();
+
+                this.onCompleteObservable.notifyObservers(this);
+                this.onCompleteObservable.clear();
+            });
+
             return loader;
         }
 

+ 8 - 10
src/Materials/Textures/babylon.texture.ts

@@ -182,7 +182,7 @@
             if (!scene) {
                 return;
             }
-            
+
             this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
             this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
 
@@ -192,19 +192,17 @@
                     delete this._buffer;
                 }
             } else {
-                if (this._texture.isReady) {
-                    Tools.SetImmediate(() => {
-                        if (!this._delayedOnLoad) {
-                            return;
-                        }
-                        this._delayedOnLoad();
-                    });
-                } else {
-                    if (this._delayedOnLoad) {
+                if (this._delayedOnLoad) {
+                    if (this._texture.isReady) {
+                        Tools.SetImmediate(this._delayedOnLoad);
+                    } else {
                         this._texture.onLoadedObservable.add(this._delayedOnLoad);
                     }
                 }
             }
+
+            this._delayedOnLoad = null;
+            this._delayedOnError = null;
         }
 
         public updateSamplingMode(samplingMode: number): void {

+ 11 - 33
src/Tools/babylon.promise.ts

@@ -22,36 +22,6 @@ module BABYLON {
         private _onRejected?: (reason: any) => void;
         private _rejectWasConsumed = false;
 
-        public get state(): PromiseStates {
-            return this._state;
-        }
-
-        public get isFulfilled(): boolean {
-            return this._state === PromiseStates.Fulfilled;
-        }
-
-        public get isRejected(): boolean {
-            return this._state === PromiseStates.Rejected;
-        }
-
-        public get isPending(): boolean {
-            return this._state === PromiseStates.Pending;
-        }
-
-        public value(): Nullable<T> | undefined {
-            if (!this.isFulfilled) {
-                throw new Error("Promise is not fulfilled");
-            }
-            return this._result;
-        }
-
-        public reason(): any {
-            if (!this.isRejected) {
-                throw new Error("Promise is not rejected");
-            }
-            return this._reason;
-        }
-
         public constructor(resolver?: (
             resolve: (value?: Nullable<T>) => void,
             reject: (reason: any) => void
@@ -108,11 +78,11 @@ module BABYLON {
         private _moveChildren(children: InternalPromise<T>[]): void {
             this._children.push(...children.splice(0, children.length));
 
-            if (this.isFulfilled) {
+            if (this._state === PromiseStates.Fulfilled) {
                 for (var child of this._children) {
                     child._resolve(this._result);
                 }
-            } else if (this.isRejected) {
+            } else if (this._state === PromiseStates.Rejected) {
                 for (var child of this._children) {
                     child._reject(this._reason);
                 }
@@ -144,6 +114,10 @@ module BABYLON {
                     child._resolve(value);
                 }
 
+                this._children.length = 0;
+                delete this._onFulfilled;
+                delete this._onRejected;
+
                 return returnedValue;
             } catch (e) {
                 this._reject(e);
@@ -168,6 +142,10 @@ module BABYLON {
                     child._reject(reason);
                 }
             }
+
+            this._children.length = 0;
+            delete this._onFulfilled;
+            delete this._onRejected;
         }
 
         public static resolve<T>(value: T): InternalPromise<T> {
@@ -188,7 +166,7 @@ module BABYLON {
                 }
                 return null;
             }, (reason: any) => {
-                if (!agregator.rootPromise.isRejected) {
+                if (agregator.rootPromise._state !== PromiseStates.Rejected) {
                     agregator.rootPromise._reject(reason);
                 }
             })

+ 12 - 2
src/Tools/babylon.tools.ts

@@ -494,11 +494,16 @@
             var img = new Image();
             Tools.SetCorsBehavior(url, img);
 
-            img.onload = () => {
+            const loadHandler = () => {
+                img.removeEventListener("load", loadHandler);
+                img.removeEventListener("error", errorHandler);
                 onLoad(img);
             };
 
-            img.onerror = err => {
+            const errorHandler = (err: any) => {
+                img.removeEventListener("load", loadHandler);
+                img.removeEventListener("error", errorHandler);
+
                 Tools.Error("Error while trying to load image: " + url);
 
                 if (onError) {
@@ -506,6 +511,9 @@
                 }
             };
 
+            img.addEventListener("load", loadHandler);
+            img.addEventListener("error", errorHandler);
+
             var noIndexedDB = () => {
                 img.src = url;
             };
@@ -599,7 +607,9 @@
                     }
 
                     const onLoadEnd = () => {
+                        request.removeEventListener("loadend", onLoadEnd);
                         fileRequest.onCompleteObservable.notifyObservers(fileRequest);
+                        fileRequest.onCompleteObservable.clear();
                     };
 
                     request.addEventListener("loadend", onLoadEnd);