Sfoglia il codice sorgente

Reduce dependency on window object + nightly + fix #5423

David Catuhe 6 anni fa
parent
commit
561a6ab5e7

File diff suppressed because it is too large
+ 6593 - 6578
Playground/babylon.d.txt


File diff suppressed because it is too large
+ 1 - 12317
dist/preview release/Oimo.js


File diff suppressed because it is too large
+ 6611 - 6596
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.js


+ 40 - 17
dist/preview release/babylon.max.js

@@ -12666,8 +12666,10 @@ var BABYLON;
                 this._onCanvasPointerOut = function (ev) {
                     _this.onCanvasPointerOutObservable.notifyObservers(ev);
                 };
-                window.addEventListener("blur", this._onBlur);
-                window.addEventListener("focus", this._onFocus);
+                if (BABYLON.Tools.IsWindowObjectExist()) {
+                    window.addEventListener("blur", this._onBlur);
+                    window.addEventListener("focus", this._onFocus);
+                }
                 canvas.addEventListener("pointerout", this._onCanvasPointerOut);
                 // Context lost
                 if (!this._doNotHandleContextLost) {
@@ -12711,8 +12713,9 @@ var BABYLON;
                 }
             }
             // Viewport
-            var limitDeviceRatio = options.limitDeviceRatio || window.devicePixelRatio || 1.0;
-            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, window.devicePixelRatio || 1.0) : 1.0;
+            var devicePixelRatio = BABYLON.Tools.IsWindowObjectExist() ? (window.devicePixelRatio || 1.0) : 1.0;
+            var limitDeviceRatio = options.limitDeviceRatio || devicePixelRatio;
+            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, devicePixelRatio) : 1.0;
             this.resize();
             this._isStencilEnable = options.stencil ? true : false;
             this._initGLContext();
@@ -12765,8 +12768,10 @@ var BABYLON;
                 this._onVRDisplayPointerUnrestricted = function () {
                     document.exitPointerLock();
                 };
-                window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
-                window.addEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted, false);
+                if (BABYLON.Tools.IsWindowObjectExist()) {
+                    window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
+                    window.addEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted, false);
+                }
             }
             // Create Audio Engine if needed.
             if (!Engine.audioEngine && options.audioEngine && Engine.AudioEngineFactory) {
@@ -27665,6 +27670,32 @@ var BABYLON;
             return animatable;
         };
         /**
+         * Will start the animation sequence of a given target and its hierarchy
+         * @param target defines the target
+         * @param directDescendantsOnly if true only direct descendants will be used, if false direct and also indirect (children of children, an so on in a recursive manner) descendants will be used.
+         * @param from defines from which frame should animation start
+         * @param to defines until which frame should animation run.
+         * @param loop defines if the animation loops
+         * @param speedRatio defines the speed in which to run the animation (1.0 by default)
+         * @param onAnimationEnd defines the function to be executed when the animation ends
+         * @param animatable defines an animatable object. If not provided a new one will be created from the given params
+         * @param stopCurrent defines if the current animations must be stopped first (true by default)
+         * @param targetMask defines if the target should be animated if animations are present (this is called recursively on descendant animatables regardless of return value)
+         * @returns the animatable object created for this animation
+         */
+        Scene.prototype.beginHierarchyAnimation = function (target, directDescendantsOnly, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask) {
+            if (speedRatio === void 0) { speedRatio = 1.0; }
+            if (stopCurrent === void 0) { stopCurrent = true; }
+            var children = target.getDescendants(directDescendantsOnly);
+            var result = [];
+            result.push(this.beginAnimation(target, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask));
+            for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
+                var child = children_1[_i];
+                result.push(this.beginAnimation(child, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask));
+            }
+            return result;
+        };
+        /**
          * Begin a new animation on a given node
          * @param target defines the target where the animation will take place
          * @param animations defines the list of animations to start
@@ -27698,8 +27729,8 @@ var BABYLON;
             var children = target.getDescendants(directDescendantsOnly);
             var result = [];
             result.push(this.beginDirectAnimation(target, animations, from, to, loop, speedRatio, onAnimationEnd));
-            for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
-                var child = children_1[_i];
+            for (var _i = 0, children_2 = children; _i < children_2.length; _i++) {
+                var child = children_2[_i];
                 result.push(this.beginDirectAnimation(child, animations, from, to, loop, speedRatio, onAnimationEnd));
             }
             return result;
@@ -97067,7 +97098,7 @@ var BABYLON;
                 BABYLON.Tools.Error("No object was provided. A physics object is obligatory");
                 return;
             }
-            //legacy support for old syntax.
+            // Legacy support for old syntax.
             if (!this._scene && object.getScene) {
                 this._scene = object.getScene();
             }
@@ -99260,10 +99291,6 @@ var BABYLON;
                         bodyConfig.pos.push(center.y);
                         bodyConfig.pos.push(center.z);
                         bodyConfig.posShape.push(0, 0, 0);
-                        //tmp solution
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
                         bodyConfig.rotShape.push(0, 0, 0);
                     }
                     else {
@@ -99272,10 +99299,6 @@ var BABYLON;
                         bodyConfig.posShape.push(localPosition.y);
                         bodyConfig.posShape.push(localPosition.z);
                         bodyConfig.pos.push(0, 0, 0);
-                        //tmp solution until https://github.com/lo-th/OIMO.js/pull/37 is merged
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
                         bodyConfig.rotShape.push(rot.x * radToDeg);
                         bodyConfig.rotShape.push(rot.y * radToDeg);
                         bodyConfig.rotShape.push(rot.z * radToDeg);

+ 40 - 17
dist/preview release/babylon.no-module.max.js

@@ -12633,8 +12633,10 @@ var BABYLON;
                 this._onCanvasPointerOut = function (ev) {
                     _this.onCanvasPointerOutObservable.notifyObservers(ev);
                 };
-                window.addEventListener("blur", this._onBlur);
-                window.addEventListener("focus", this._onFocus);
+                if (BABYLON.Tools.IsWindowObjectExist()) {
+                    window.addEventListener("blur", this._onBlur);
+                    window.addEventListener("focus", this._onFocus);
+                }
                 canvas.addEventListener("pointerout", this._onCanvasPointerOut);
                 // Context lost
                 if (!this._doNotHandleContextLost) {
@@ -12678,8 +12680,9 @@ var BABYLON;
                 }
             }
             // Viewport
-            var limitDeviceRatio = options.limitDeviceRatio || window.devicePixelRatio || 1.0;
-            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, window.devicePixelRatio || 1.0) : 1.0;
+            var devicePixelRatio = BABYLON.Tools.IsWindowObjectExist() ? (window.devicePixelRatio || 1.0) : 1.0;
+            var limitDeviceRatio = options.limitDeviceRatio || devicePixelRatio;
+            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, devicePixelRatio) : 1.0;
             this.resize();
             this._isStencilEnable = options.stencil ? true : false;
             this._initGLContext();
@@ -12732,8 +12735,10 @@ var BABYLON;
                 this._onVRDisplayPointerUnrestricted = function () {
                     document.exitPointerLock();
                 };
-                window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
-                window.addEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted, false);
+                if (BABYLON.Tools.IsWindowObjectExist()) {
+                    window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
+                    window.addEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted, false);
+                }
             }
             // Create Audio Engine if needed.
             if (!Engine.audioEngine && options.audioEngine && Engine.AudioEngineFactory) {
@@ -27632,6 +27637,32 @@ var BABYLON;
             return animatable;
         };
         /**
+         * Will start the animation sequence of a given target and its hierarchy
+         * @param target defines the target
+         * @param directDescendantsOnly if true only direct descendants will be used, if false direct and also indirect (children of children, an so on in a recursive manner) descendants will be used.
+         * @param from defines from which frame should animation start
+         * @param to defines until which frame should animation run.
+         * @param loop defines if the animation loops
+         * @param speedRatio defines the speed in which to run the animation (1.0 by default)
+         * @param onAnimationEnd defines the function to be executed when the animation ends
+         * @param animatable defines an animatable object. If not provided a new one will be created from the given params
+         * @param stopCurrent defines if the current animations must be stopped first (true by default)
+         * @param targetMask defines if the target should be animated if animations are present (this is called recursively on descendant animatables regardless of return value)
+         * @returns the animatable object created for this animation
+         */
+        Scene.prototype.beginHierarchyAnimation = function (target, directDescendantsOnly, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask) {
+            if (speedRatio === void 0) { speedRatio = 1.0; }
+            if (stopCurrent === void 0) { stopCurrent = true; }
+            var children = target.getDescendants(directDescendantsOnly);
+            var result = [];
+            result.push(this.beginAnimation(target, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask));
+            for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
+                var child = children_1[_i];
+                result.push(this.beginAnimation(child, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask));
+            }
+            return result;
+        };
+        /**
          * Begin a new animation on a given node
          * @param target defines the target where the animation will take place
          * @param animations defines the list of animations to start
@@ -27665,8 +27696,8 @@ var BABYLON;
             var children = target.getDescendants(directDescendantsOnly);
             var result = [];
             result.push(this.beginDirectAnimation(target, animations, from, to, loop, speedRatio, onAnimationEnd));
-            for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
-                var child = children_1[_i];
+            for (var _i = 0, children_2 = children; _i < children_2.length; _i++) {
+                var child = children_2[_i];
                 result.push(this.beginDirectAnimation(child, animations, from, to, loop, speedRatio, onAnimationEnd));
             }
             return result;
@@ -97034,7 +97065,7 @@ var BABYLON;
                 BABYLON.Tools.Error("No object was provided. A physics object is obligatory");
                 return;
             }
-            //legacy support for old syntax.
+            // Legacy support for old syntax.
             if (!this._scene && object.getScene) {
                 this._scene = object.getScene();
             }
@@ -99227,10 +99258,6 @@ var BABYLON;
                         bodyConfig.pos.push(center.y);
                         bodyConfig.pos.push(center.z);
                         bodyConfig.posShape.push(0, 0, 0);
-                        //tmp solution
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
                         bodyConfig.rotShape.push(0, 0, 0);
                     }
                     else {
@@ -99239,10 +99266,6 @@ var BABYLON;
                         bodyConfig.posShape.push(localPosition.y);
                         bodyConfig.posShape.push(localPosition.z);
                         bodyConfig.pos.push(0, 0, 0);
-                        //tmp solution until https://github.com/lo-th/OIMO.js/pull/37 is merged
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
                         bodyConfig.rotShape.push(rot.x * radToDeg);
                         bodyConfig.rotShape.push(rot.y * radToDeg);
                         bodyConfig.rotShape.push(rot.z * radToDeg);

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.worker.js


+ 40 - 17
dist/preview release/es6.js

@@ -12633,8 +12633,10 @@ var BABYLON;
                 this._onCanvasPointerOut = function (ev) {
                     _this.onCanvasPointerOutObservable.notifyObservers(ev);
                 };
-                window.addEventListener("blur", this._onBlur);
-                window.addEventListener("focus", this._onFocus);
+                if (BABYLON.Tools.IsWindowObjectExist()) {
+                    window.addEventListener("blur", this._onBlur);
+                    window.addEventListener("focus", this._onFocus);
+                }
                 canvas.addEventListener("pointerout", this._onCanvasPointerOut);
                 // Context lost
                 if (!this._doNotHandleContextLost) {
@@ -12678,8 +12680,9 @@ var BABYLON;
                 }
             }
             // Viewport
-            var limitDeviceRatio = options.limitDeviceRatio || window.devicePixelRatio || 1.0;
-            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, window.devicePixelRatio || 1.0) : 1.0;
+            var devicePixelRatio = BABYLON.Tools.IsWindowObjectExist() ? (window.devicePixelRatio || 1.0) : 1.0;
+            var limitDeviceRatio = options.limitDeviceRatio || devicePixelRatio;
+            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, devicePixelRatio) : 1.0;
             this.resize();
             this._isStencilEnable = options.stencil ? true : false;
             this._initGLContext();
@@ -12732,8 +12735,10 @@ var BABYLON;
                 this._onVRDisplayPointerUnrestricted = function () {
                     document.exitPointerLock();
                 };
-                window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
-                window.addEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted, false);
+                if (BABYLON.Tools.IsWindowObjectExist()) {
+                    window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
+                    window.addEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted, false);
+                }
             }
             // Create Audio Engine if needed.
             if (!Engine.audioEngine && options.audioEngine && Engine.AudioEngineFactory) {
@@ -27632,6 +27637,32 @@ var BABYLON;
             return animatable;
         };
         /**
+         * Will start the animation sequence of a given target and its hierarchy
+         * @param target defines the target
+         * @param directDescendantsOnly if true only direct descendants will be used, if false direct and also indirect (children of children, an so on in a recursive manner) descendants will be used.
+         * @param from defines from which frame should animation start
+         * @param to defines until which frame should animation run.
+         * @param loop defines if the animation loops
+         * @param speedRatio defines the speed in which to run the animation (1.0 by default)
+         * @param onAnimationEnd defines the function to be executed when the animation ends
+         * @param animatable defines an animatable object. If not provided a new one will be created from the given params
+         * @param stopCurrent defines if the current animations must be stopped first (true by default)
+         * @param targetMask defines if the target should be animated if animations are present (this is called recursively on descendant animatables regardless of return value)
+         * @returns the animatable object created for this animation
+         */
+        Scene.prototype.beginHierarchyAnimation = function (target, directDescendantsOnly, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask) {
+            if (speedRatio === void 0) { speedRatio = 1.0; }
+            if (stopCurrent === void 0) { stopCurrent = true; }
+            var children = target.getDescendants(directDescendantsOnly);
+            var result = [];
+            result.push(this.beginAnimation(target, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask));
+            for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
+                var child = children_1[_i];
+                result.push(this.beginAnimation(child, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask));
+            }
+            return result;
+        };
+        /**
          * Begin a new animation on a given node
          * @param target defines the target where the animation will take place
          * @param animations defines the list of animations to start
@@ -27665,8 +27696,8 @@ var BABYLON;
             var children = target.getDescendants(directDescendantsOnly);
             var result = [];
             result.push(this.beginDirectAnimation(target, animations, from, to, loop, speedRatio, onAnimationEnd));
-            for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
-                var child = children_1[_i];
+            for (var _i = 0, children_2 = children; _i < children_2.length; _i++) {
+                var child = children_2[_i];
                 result.push(this.beginDirectAnimation(child, animations, from, to, loop, speedRatio, onAnimationEnd));
             }
             return result;
@@ -97034,7 +97065,7 @@ var BABYLON;
                 BABYLON.Tools.Error("No object was provided. A physics object is obligatory");
                 return;
             }
-            //legacy support for old syntax.
+            // Legacy support for old syntax.
             if (!this._scene && object.getScene) {
                 this._scene = object.getScene();
             }
@@ -99227,10 +99258,6 @@ var BABYLON;
                         bodyConfig.pos.push(center.y);
                         bodyConfig.pos.push(center.z);
                         bodyConfig.posShape.push(0, 0, 0);
-                        //tmp solution
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
                         bodyConfig.rotShape.push(0, 0, 0);
                     }
                     else {
@@ -99239,10 +99266,6 @@ var BABYLON;
                         bodyConfig.posShape.push(localPosition.y);
                         bodyConfig.posShape.push(localPosition.z);
                         bodyConfig.pos.push(0, 0, 0);
-                        //tmp solution until https://github.com/lo-th/OIMO.js/pull/37 is merged
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
                         bodyConfig.rotShape.push(rot.x * radToDeg);
                         bodyConfig.rotShape.push(rot.y * radToDeg);
                         bodyConfig.rotShape.push(rot.z * radToDeg);

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


+ 45 - 5
dist/preview release/viewer/babylon.viewer.d.ts

@@ -168,11 +168,11 @@ declare module BabylonViewer {
                 * Mainly used for help and errors
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 */
-            showOverlayScreen(subScreen: string): Promise<string> | Promise<Template>;
+            showOverlayScreen(subScreen: string): Promise<Template> | Promise<string>;
             /**
                 * Hide the overlay screen.
                 */
-            hideOverlayScreen(): Promise<string> | Promise<Template>;
+            hideOverlayScreen(): Promise<Template> | Promise<string>;
             /**
                 * show the viewer (in case it was hidden)
                 *
@@ -189,11 +189,11 @@ declare module BabylonViewer {
                 * Show the loading screen.
                 * The loading screen can be configured using the configuration object
                 */
-            showLoadingScreen(): Promise<string> | Promise<Template>;
+            showLoadingScreen(): Promise<Template> | Promise<string>;
             /**
                 * Hide the loading screen
                 */
-            hideLoadingScreen(): Promise<string> | Promise<Template>;
+            hideLoadingScreen(): Promise<Template> | Promise<string>;
             dispose(): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
     }
@@ -924,7 +924,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1558,6 +1558,20 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
+    /**
+        * A custom upgrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedUpgrade(sceneManager: SceneManager): boolean;
+    /**
+        * A custom degrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedDegrade(sceneManager: SceneManager): boolean;
+}
+declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {
@@ -1665,6 +1679,32 @@ declare module BabylonViewer {
     }
 }
 declare module BabylonViewer {
+    /**
+        * Defines an animation to be applied to a model (translation, scale or rotation).
+        */
+    export interface IModelAnimationConfiguration {
+            /**
+                * Time of animation, in seconds
+                */
+            time?: number;
+            /**
+                * Scale to apply
+                */
+            scaling?: {
+                    x: number;
+                    y: number;
+                    z: number;
+            };
+            /**
+                * Easing function to apply
+                */
+            easingFunction?: number;
+            /**
+                * An Easing mode to apply to the easing function
+                * See BABYLON.EasingFunction
+                */
+            easingMode?: number;
+    }
 }
 declare module BabylonViewer {
     export class TelemetryLoaderPlugin implements ILoaderPlugin {

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 48 - 6
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -200,11 +200,11 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * Mainly used for help and errors
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 */
-            showOverlayScreen(subScreen: string): Promise<string> | Promise<Template>;
+            showOverlayScreen(subScreen: string): Promise<Template> | Promise<string>;
             /**
                 * Hide the overlay screen.
                 */
-            hideOverlayScreen(): Promise<string> | Promise<Template>;
+            hideOverlayScreen(): Promise<Template> | Promise<string>;
             /**
                 * show the viewer (in case it was hidden)
                 *
@@ -221,11 +221,11 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * Show the loading screen.
                 * The loading screen can be configured using the configuration object
                 */
-            showLoadingScreen(): Promise<string> | Promise<Template>;
+            showLoadingScreen(): Promise<Template> | Promise<string>;
             /**
                 * Hide the loading screen
                 */
-            hideLoadingScreen(): Promise<string> | Promise<Template>;
+            hideLoadingScreen(): Promise<Template> | Promise<string>;
             dispose(): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
     }
@@ -985,13 +985,14 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
+    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1662,6 +1663,22 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
+declare module 'babylonjs-viewer/optimizer/custom/extended' {
+    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
+    /**
+        * A custom upgrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedUpgrade(sceneManager: SceneManager): boolean;
+    /**
+        * A custom degrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedDegrade(sceneManager: SceneManager): boolean;
+}
+
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';
@@ -1792,7 +1809,32 @@ declare module 'babylonjs-viewer/labs/viewerLabs' {
 }
 
 declare module 'babylonjs-viewer/configuration/interfaces/modelAnimationConfiguration' {
-    
+    /**
+        * Defines an animation to be applied to a model (translation, scale or rotation).
+        */
+    export interface IModelAnimationConfiguration {
+            /**
+                * Time of animation, in seconds
+                */
+            time?: number;
+            /**
+                * Scale to apply
+                */
+            scaling?: {
+                    x: number;
+                    y: number;
+                    z: number;
+            };
+            /**
+                * Easing function to apply
+                */
+            easingFunction?: number;
+            /**
+                * An Easing mode to apply to the easing function
+                * See BABYLON.EasingFunction
+                */
+            easingMode?: number;
+    }
 }
 
 declare module 'babylonjs-viewer/loader/plugins/telemetryLoaderPlugin' {

+ 9 - 3
gui/src/2D/controls/control.ts

@@ -1269,12 +1269,18 @@ export class Control {
 
     /** @hidden */
     public _onPointerOut(target: Control): void {
-        if (!this._isEnabled) {
+        if (!this._isEnabled || target === this) {
             return;
         }
         this._enterCount = 0;
 
-        this.onPointerOutObservable.notifyObservers(this, -1, target, this);
+        var canNotify: boolean = true;
+
+        if (!target.isAscendant(this)) {
+            canNotify = this.onPointerOutObservable.notifyObservers(this, -1, target, this);
+        }
+
+        if (canNotify && this.parent != null) { this.parent._onPointerOut(target); }
     }
 
     /** @hidden */
@@ -1337,7 +1343,7 @@ export class Control {
             this._onPointerMove(this, this._dummyVector2);
 
             var previousControlOver = this._host._lastControlOver[pointerId];
-            if (previousControlOver && previousControlOver !== this && !this.isAscendant(previousControlOver)) {
+            if (previousControlOver && previousControlOver !== this) {
                 previousControlOver._onPointerOut(this);
             }
 

+ 12 - 6
src/Engine/babylon.engine.ts

@@ -1096,8 +1096,10 @@ module BABYLON {
                     this.onCanvasPointerOutObservable.notifyObservers(ev);
                 };
 
-                window.addEventListener("blur", this._onBlur);
-                window.addEventListener("focus", this._onFocus);
+                if (Tools.IsWindowObjectExist()) {
+                    window.addEventListener("blur", this._onBlur);
+                    window.addEventListener("focus", this._onFocus);
+                }
 
                 canvas.addEventListener("pointerout", this._onCanvasPointerOut);
 
@@ -1155,8 +1157,10 @@ module BABYLON {
             }
 
             // Viewport
-            var limitDeviceRatio = options.limitDeviceRatio || window.devicePixelRatio || 1.0;
-            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, window.devicePixelRatio || 1.0) : 1.0;
+            const devicePixelRatio = Tools.IsWindowObjectExist() ? (window.devicePixelRatio || 1.0) : 1.0;
+
+            var limitDeviceRatio = options.limitDeviceRatio || devicePixelRatio;
+            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, devicePixelRatio) : 1.0;
             this.resize();
 
             this._isStencilEnable = options.stencil ? true : false;
@@ -1217,8 +1221,10 @@ module BABYLON {
                     document.exitPointerLock();
                 };
 
-                window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
-                window.addEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted, false);
+                if (Tools.IsWindowObjectExist()) {
+                    window.addEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted, false);
+                    window.addEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted, false);
+                }
             }
 
             // Create Audio Engine if needed.

+ 0 - 8
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -149,10 +149,6 @@ module BABYLON {
                         bodyConfig.pos.push(center.z);
                         bodyConfig.posShape.push(0, 0, 0);
 
-                        //tmp solution
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
                         bodyConfig.rotShape.push(0, 0, 0);
                     } else {
                         let localPosition = i.object.getAbsolutePosition().subtract(impostor.object.getAbsolutePosition());
@@ -161,10 +157,6 @@ module BABYLON {
                         bodyConfig.posShape.push(localPosition.z);
                         bodyConfig.pos.push(0, 0, 0);
 
-                        //tmp solution until https://github.com/lo-th/OIMO.js/pull/37 is merged
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
-                        bodyConfig.rot.push(0);
                         bodyConfig.rotShape.push(rot.x * radToDeg);
                         bodyConfig.rotShape.push(rot.y * radToDeg);
                         bodyConfig.rotShape.push(rot.z * radToDeg);

+ 1 - 1
src/Physics/babylon.physicsImpostor.ts

@@ -256,7 +256,7 @@ module BABYLON {
                 return;
             }
 
-            //legacy support for old syntax.
+            // Legacy support for old syntax.
             if (!this._scene && object.getScene) {
                 this._scene = object.getScene();
             }

+ 26 - 0
src/babylon.scene.ts

@@ -2486,6 +2486,32 @@ module BABYLON {
         }
 
         /**
+         * Will start the animation sequence of a given target and its hierarchy
+         * @param target defines the target
+         * @param directDescendantsOnly if true only direct descendants will be used, if false direct and also indirect (children of children, an so on in a recursive manner) descendants will be used.
+         * @param from defines from which frame should animation start
+         * @param to defines until which frame should animation run.
+         * @param loop defines if the animation loops
+         * @param speedRatio defines the speed in which to run the animation (1.0 by default)
+         * @param onAnimationEnd defines the function to be executed when the animation ends
+         * @param animatable defines an animatable object. If not provided a new one will be created from the given params
+         * @param stopCurrent defines if the current animations must be stopped first (true by default)
+         * @param targetMask defines if the target should be animated if animations are present (this is called recursively on descendant animatables regardless of return value)
+         * @returns the list of created animatables
+         */
+        public beginHierarchyAnimation(target: any, directDescendantsOnly: boolean, from: number, to: number, loop?: boolean, speedRatio: number = 1.0, onAnimationEnd?: () => void, animatable?: Animatable, stopCurrent = true, targetMask?: (target: any) => boolean): Animatable[] {
+            let children = target.getDescendants(directDescendantsOnly);
+
+            let result = [];
+            result.push(this.beginAnimation(target, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask));
+            for (var child of children) {
+                result.push(this.beginAnimation(child, from, to, loop, speedRatio, onAnimationEnd, animatable, stopCurrent, targetMask));
+            }
+
+            return result;
+        }
+
+        /**
          * Begin a new animation on a given node
          * @param target defines the target where the animation will take place
          * @param animations defines the list of animations to start