Selaa lähdekoodia

Add support for particleSystem.spriteCellChangeSpeed = 0

David Catuhe 7 vuotta sitten
vanhempi
commit
56eaccc2d8

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7542 - 7499
Playground/babylon.d.txt


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7549 - 7506
dist/preview release/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/babylon.js


+ 122 - 44
dist/preview release/babylon.max.js

@@ -23739,6 +23739,7 @@ var BABYLON;
         SceneComponentConstants.NAME_PROCEDURALTEXTURE = "ProceduralTexture";
         SceneComponentConstants.NAME_PROCEDURALTEXTURE = "ProceduralTexture";
         SceneComponentConstants.NAME_SHADOWGENERATOR = "ShadowGenerator";
         SceneComponentConstants.NAME_SHADOWGENERATOR = "ShadowGenerator";
         SceneComponentConstants.NAME_OCTREE = "Octree";
         SceneComponentConstants.NAME_OCTREE = "Octree";
+        SceneComponentConstants.NAME_PHYSICSENGINE = "PhysicsEngine";
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
@@ -24039,7 +24040,7 @@ var BABYLON;
          */
          */
         function Scene(engine) {
         function Scene(engine) {
             var _this = _super.call(this) || this;
             var _this = _super.call(this) || this;
-            // Members
+            // Members   
             /**
             /**
              * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
              * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
              */
              */
@@ -24127,14 +24128,6 @@ var BABYLON;
             */
             */
             _this.onAfterDrawPhaseObservable = new BABYLON.Observable();
             _this.onAfterDrawPhaseObservable = new BABYLON.Observable();
             /**
             /**
-            * An event triggered when physic simulation is about to be run
-            */
-            _this.onBeforePhysicsObservable = new BABYLON.Observable();
-            /**
-            * An event triggered when physic simulation has been done
-            */
-            _this.onAfterPhysicsObservable = new BABYLON.Observable();
-            /**
             * An event triggered when the scene is ready
             * An event triggered when the scene is ready
             */
             */
             _this.onReadyObservable = new BABYLON.Observable();
             _this.onReadyObservable = new BABYLON.Observable();
@@ -24552,6 +24545,12 @@ var BABYLON;
             _this._activeMeshesFrozen = false;
             _this._activeMeshesFrozen = false;
             /** @hidden */
             /** @hidden */
             _this._allowPostProcessClearColor = true;
             _this._allowPostProcessClearColor = true;
+            /**
+             * User updatable function that will return a deterministic frame time when engine is in deterministic lock step mode
+             */
+            _this.getDeterministicFrameTime = function () {
+                return 1000.0 / 60.0; // frame time in ms
+            };
             _this._tempPickingRay = BABYLON.Ray ? BABYLON.Ray.Zero() : null;
             _this._tempPickingRay = BABYLON.Ray ? BABYLON.Ray.Zero() : null;
             /** Gets or sets a boolean blocking all the calls to markAllMaterialsAsDirty (ie. the materials won't be updated if they are out of sync) */
             /** Gets or sets a boolean blocking all the calls to markAllMaterialsAsDirty (ie. the materials won't be updated if they are out of sync) */
             _this.blockMaterialDirtyMechanism = false;
             _this.blockMaterialDirtyMechanism = false;
@@ -27761,6 +27760,10 @@ var BABYLON;
                 }
                 }
             }
             }
         };
         };
+        /** @hidden */
+        Scene.prototype._advancePhysicsEngineStep = function (step) {
+            // Do nothing. Code will be replaced if physics engine component is referenced
+        };
         /**
         /**
          * Render the scene
          * Render the scene
          * @param updateCameras defines a boolean indicating if cameras must update according to their inputs (true by default)
          * @param updateCameras defines a boolean indicating if cameras must update according to their inputs (true by default)
@@ -27787,10 +27790,7 @@ var BABYLON;
             if (this._engine.isDeterministicLockStep()) {
             if (this._engine.isDeterministicLockStep()) {
                 var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) + this._timeAccumulator;
                 var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) + this._timeAccumulator;
                 var defaultFPS = (60.0 / 1000.0);
                 var defaultFPS = (60.0 / 1000.0);
-                var defaultFrameTime = 1000 / 60; // frame time in MS
-                if (this._physicsEngine) {
-                    defaultFrameTime = this._physicsEngine.getTimeStep() * 1000;
-                }
+                var defaultFrameTime = this.getDeterministicFrameTime();
                 var stepsTaken = 0;
                 var stepsTaken = 0;
                 var maxSubSteps = this._engine.getLockstepMaxSteps();
                 var maxSubSteps = this._engine.getLockstepMaxSteps();
                 var internalSteps = Math.floor(deltaTime / (1000 * defaultFPS));
                 var internalSteps = Math.floor(deltaTime / (1000 * defaultFPS));
@@ -27802,11 +27802,7 @@ var BABYLON;
                     this._animate();
                     this._animate();
                     this.onAfterAnimationsObservable.notifyObservers(this);
                     this.onAfterAnimationsObservable.notifyObservers(this);
                     // Physics
                     // Physics
-                    if (this._physicsEngine) {
-                        this.onBeforePhysicsObservable.notifyObservers(this);
-                        this._physicsEngine.step(defaultFrameTime / 1000);
-                        this.onAfterPhysicsObservable.notifyObservers(this);
-                    }
+                    this._advancePhysicsEngineStep(defaultFrameTime);
                     this.onAfterStepObservable.notifyObservers(this);
                     this.onAfterStepObservable.notifyObservers(this);
                     this._currentStepId++;
                     this._currentStepId++;
                     stepsTaken++;
                     stepsTaken++;
@@ -27821,11 +27817,7 @@ var BABYLON;
                 this._animate();
                 this._animate();
                 this.onAfterAnimationsObservable.notifyObservers(this);
                 this.onAfterAnimationsObservable.notifyObservers(this);
                 // Physics
                 // Physics
-                if (this._physicsEngine) {
-                    this.onBeforePhysicsObservable.notifyObservers(this);
-                    this._physicsEngine.step(deltaTime / 1000.0);
-                    this.onAfterPhysicsObservable.notifyObservers(this);
-                }
+                this._advancePhysicsEngineStep(deltaTime);
             }
             }
             // Before camera update steps
             // Before camera update steps
             for (var _i = 0, _a = this._beforeCameraUpdateStage; _i < _a.length; _i++) {
             for (var _i = 0, _a = this._beforeCameraUpdateStage; _i < _a.length; _i++) {
@@ -28155,8 +28147,6 @@ var BABYLON;
             this.onAfterParticlesRenderingObservable.clear();
             this.onAfterParticlesRenderingObservable.clear();
             this.onBeforeDrawPhaseObservable.clear();
             this.onBeforeDrawPhaseObservable.clear();
             this.onAfterDrawPhaseObservable.clear();
             this.onAfterDrawPhaseObservable.clear();
-            this.onBeforePhysicsObservable.clear();
-            this.onAfterPhysicsObservable.clear();
             this.onBeforeAnimationsObservable.clear();
             this.onBeforeAnimationsObservable.clear();
             this.onAfterAnimationsObservable.clear();
             this.onAfterAnimationsObservable.clear();
             this.onDataLoadedObservable.clear();
             this.onDataLoadedObservable.clear();
@@ -28224,10 +28214,6 @@ var BABYLON;
             }
             }
             // Post-processes
             // Post-processes
             this.postProcessManager.dispose();
             this.postProcessManager.dispose();
-            // Physics
-            if (this._physicsEngine) {
-                this.disablePhysicsEngine();
-            }
             // Remove from engine
             // Remove from engine
             index = this._engine.scenes.indexOf(this);
             index = this._engine.scenes.indexOf(this);
             if (index > -1) {
             if (index > -1) {
@@ -28551,7 +28537,6 @@ var BABYLON;
         Scene.prototype.getPointerOverMesh = function () {
         Scene.prototype.getPointerOverMesh = function () {
             return this._pointerOverMesh;
             return this._pointerOverMesh;
         };
         };
-        // Physics
         // Misc.
         // Misc.
         /** @hidden */
         /** @hidden */
         Scene.prototype._rebuildGeometries = function () {
         Scene.prototype._rebuildGeometries = function () {
@@ -55782,14 +55767,21 @@ var BABYLON;
          */
          */
         Particle.prototype.updateCellIndex = function () {
         Particle.prototype.updateCellIndex = function () {
             var offsetAge = this.age;
             var offsetAge = this.age;
+            var changeSpeed = this.particleSystem.spriteCellChangeSpeed;
             if (this.particleSystem.spriteRandomStartCell) {
             if (this.particleSystem.spriteRandomStartCell) {
                 if (this._randomCellOffset === undefined) {
                 if (this._randomCellOffset === undefined) {
                     this._randomCellOffset = Math.random() * this.lifeTime;
                     this._randomCellOffset = Math.random() * this.lifeTime;
                 }
                 }
-                offsetAge += this._randomCellOffset;
+                if (changeSpeed === 0) { // Special case when speed = 0 meaning we want to stay on initial cell
+                    changeSpeed = 1;
+                    offsetAge = this._randomCellOffset;
+                }
+                else {
+                    offsetAge += this._randomCellOffset;
+                }
             }
             }
             var dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
             var dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
-            var ratio = BABYLON.Scalar.Clamp(((offsetAge * this.particleSystem.spriteCellChangeSpeed) % this.lifeTime) / this.lifeTime);
+            var ratio = BABYLON.Scalar.Clamp(((offsetAge * changeSpeed) % this.lifeTime) / this.lifeTime);
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
         };
         };
         /** @hidden */
         /** @hidden */
@@ -56059,6 +56051,10 @@ var BABYLON;
             this._rampGradients = null;
             this._rampGradients = null;
             this._colorRemapGradients = null;
             this._colorRemapGradients = null;
             this._alphaRemapGradients = null;
             this._alphaRemapGradients = null;
+            /**
+             * Defines the delay in milliseconds before starting the system (0 by default)
+             */
+            this.startDelay = 0;
             /** Gets or sets a value indicating the damping to apply if the limit velocity factor is reached */
             /** Gets or sets a value indicating the damping to apply if the limit velocity factor is reached */
             this.limitVelocityDamping = 0.4;
             this.limitVelocityDamping = 0.4;
             /**
             /**
@@ -56114,6 +56110,11 @@ var BABYLON;
         BaseParticleSystem.prototype.getScene = function () {
         BaseParticleSystem.prototype.getScene = function () {
             return this._scene;
             return this._scene;
         };
         };
+        BaseParticleSystem.prototype._hasTargetStopDurationDependantGradient = function () {
+            return (this._startSizeGradients && this._startSizeGradients.length > 0)
+                || (this._emitRateGradients && this._emitRateGradients.length > 0)
+                || (this._lifeTimeGradients && this._lifeTimeGradients.length > 0);
+        };
         /**
         /**
          * Gets the current list of drag gradients.
          * Gets the current list of drag gradients.
          * You must use addDragGradient and removeDragGradient to udpate this list
          * You must use addDragGradient and removeDragGradient to udpate this list
@@ -57359,11 +57360,14 @@ var BABYLON;
         };
         };
         /**
         /**
          * Starts the particle system and begins to emit
          * Starts the particle system and begins to emit
-         * @param delay defines the delay in milliseconds before starting the system (0 by default)
+         * @param delay defines the delay in milliseconds before starting the system (this.startDelay by default)
          */
          */
         ParticleSystem.prototype.start = function (delay) {
         ParticleSystem.prototype.start = function (delay) {
             var _this = this;
             var _this = this;
-            if (delay === void 0) { delay = 0; }
+            if (delay === void 0) { delay = this.startDelay; }
+            if (!this.targetStopDuration && this._hasTargetStopDurationDependantGradient()) {
+                throw "Particle system started with a targetStopDuration dependant gradient (eg. startSizeGradients) but no targetStopDuration set";
+            }
             if (delay) {
             if (delay) {
                 setTimeout(function () {
                 setTimeout(function () {
                     _this.start(0);
                     _this.start(0);
@@ -57571,7 +57575,7 @@ var BABYLON;
                 // Size and scale
                 // Size and scale
                 particle.scale.copyFromFloats(BABYLON.Scalar.RandomRange(this_1.minScaleX, this_1.maxScaleX), BABYLON.Scalar.RandomRange(this_1.minScaleY, this_1.maxScaleY));
                 particle.scale.copyFromFloats(BABYLON.Scalar.RandomRange(this_1.minScaleX, this_1.maxScaleX), BABYLON.Scalar.RandomRange(this_1.minScaleY, this_1.maxScaleY));
                 // Adjust scale by start size
                 // Adjust scale by start size
-                if (this_1._startSizeGradients && this_1._startSizeGradients[0]) {
+                if (this_1._startSizeGradients && this_1._startSizeGradients[0] && this_1.targetStopDuration) {
                     var ratio = this_1._actualFrame / this_1.targetStopDuration;
                     var ratio = this_1._actualFrame / this_1.targetStopDuration;
                     BABYLON.Tools.GetCurrentGradient(ratio, this_1._startSizeGradients, function (currentGradient, nextGradient, scale) {
                     BABYLON.Tools.GetCurrentGradient(ratio, this_1._startSizeGradients, function (currentGradient, nextGradient, scale) {
                         if (currentGradient !== _this._currentStartSizeGradient) {
                         if (currentGradient !== _this._currentStartSizeGradient) {
@@ -62162,11 +62166,14 @@ var BABYLON;
         };
         };
         /**
         /**
          * Starts the particle system and begins to emit
          * Starts the particle system and begins to emit
-         * @param delay defines the delay in milliseconds before starting the system (0 by default)
+         * @param delay defines the delay in milliseconds before starting the system (this.startDelay by default)
          */
          */
         GPUParticleSystem.prototype.start = function (delay) {
         GPUParticleSystem.prototype.start = function (delay) {
             var _this = this;
             var _this = this;
-            if (delay === void 0) { delay = 0; }
+            if (delay === void 0) { delay = this.startDelay; }
+            if (!this.targetStopDuration && this._hasTargetStopDurationDependantGradient()) {
+                throw "Particle system started with a targetStopDuration dependant gradient (eg. startSizeGradients) but no targetStopDuration set";
+            }
             if (delay) {
             if (delay) {
                 setTimeout(function () {
                 setTimeout(function () {
                     _this.start(0);
                     _this.start(0);
@@ -78755,7 +78762,7 @@ var BABYLON;
         this._geometryBufferRenderer = null;
         this._geometryBufferRenderer = null;
     };
     };
     /**
     /**
-     * Defines the Geometry Buffer scene component responsible to manage a G-Buffer usefull
+     * Defines the Geometry Buffer scene component responsible to manage a G-Buffer useful
      * in several rendering techniques.
      * in several rendering techniques.
      */
      */
     var GeometryBufferRendererSceneComponent = /** @class */ (function () {
     var GeometryBufferRendererSceneComponent = /** @class */ (function () {
@@ -78765,7 +78772,7 @@ var BABYLON;
          */
          */
         function GeometryBufferRendererSceneComponent(scene) {
         function GeometryBufferRendererSceneComponent(scene) {
             /**
             /**
-             * The component name helpfull to identify the component in the list of scene components.
+             * The component name helpful to identify the component in the list of scene components.
              */
              */
             this.name = BABYLON.SceneComponentConstants.NAME_GEOMETRYBUFFERRENDERER;
             this.name = BABYLON.SceneComponentConstants.NAME_GEOMETRYBUFFERRENDERER;
             this.scene = scene;
             this.scene = scene;
@@ -89760,7 +89767,7 @@ var BABYLON;
          * Called by the scene. No need to call it.
          * Called by the scene. No need to call it.
          * @param delta defines the timespam between frames
          * @param delta defines the timespam between frames
          */
          */
-        PhysicsEngine.prototype.step = function (delta) {
+        PhysicsEngine.prototype._step = function (delta) {
             var _this = this;
             var _this = this;
             //check if any mesh has no body / requires an update
             //check if any mesh has no body / requires an update
             this._impostors.forEach(function (impostor) {
             this._impostors.forEach(function (impostor) {
@@ -91362,6 +91369,12 @@ var BABYLON;
         if (this._physicsEngine) {
         if (this._physicsEngine) {
             return true;
             return true;
         }
         }
+        // Register the component to the scene
+        var component = this._getComponent(BABYLON.SceneComponentConstants.NAME_PHYSICSENGINE);
+        if (!component) {
+            component = new PhysicsEngineSceneComponent(this);
+            this._addComponent(component);
+        }
         try {
         try {
             this._physicsEngine = new BABYLON.PhysicsEngine(gravity, plugin);
             this._physicsEngine = new BABYLON.PhysicsEngine(gravity, plugin);
             return true;
             return true;
@@ -91399,6 +91412,64 @@ var BABYLON;
             mesh.physicsImpostor = null;
             mesh.physicsImpostor = null;
         }
         }
     };
     };
+    /** @hidden */
+    BABYLON.Scene.prototype._advancePhysicsEngineStep = function (step) {
+        if (this._physicsEngine) {
+            this.onBeforePhysicsObservable.notifyObservers(this);
+            this._physicsEngine._step(step / 1000);
+            this.onAfterPhysicsObservable.notifyObservers(this);
+        }
+    };
+    /**
+     * Defines the physics engine scene component responsible to manage a physics engine
+     */
+    var PhysicsEngineSceneComponent = /** @class */ (function () {
+        /**
+         * Creates a new instance of the component for the given scene
+         * @param scene Defines the scene to register the component in
+         */
+        function PhysicsEngineSceneComponent(scene) {
+            var _this = this;
+            /**
+             * The component name helpful to identify the component in the list of scene components.
+             */
+            this.name = BABYLON.SceneComponentConstants.NAME_PHYSICSENGINE;
+            this.scene = scene;
+            this.scene.onBeforePhysicsObservable = new BABYLON.Observable();
+            this.scene.onAfterPhysicsObservable = new BABYLON.Observable();
+            // Replace the function used to get the deterministic frame time
+            this.scene.getDeterministicFrameTime = function () {
+                if (_this.scene._physicsEngine) {
+                    return _this.scene._physicsEngine.getTimeStep() * 1000;
+                }
+                return 1000.0 / 60.0;
+            };
+        }
+        /**
+         * Registers the component in a given scene
+         */
+        PhysicsEngineSceneComponent.prototype.register = function () {
+        };
+        /**
+         * Rebuilds the elements related to this component in case of
+         * context lost for instance.
+         */
+        PhysicsEngineSceneComponent.prototype.rebuild = function () {
+            // Nothing to do for this component
+        };
+        /**
+         * Disposes the component and the associated ressources
+         */
+        PhysicsEngineSceneComponent.prototype.dispose = function () {
+            this.scene.onBeforePhysicsObservable.clear();
+            this.scene.onAfterPhysicsObservable.clear();
+            if (this.scene._physicsEngine) {
+                this.scene.disablePhysicsEngine();
+            }
+        };
+        return PhysicsEngineSceneComponent;
+    }());
+    BABYLON.PhysicsEngineSceneComponent = PhysicsEngineSceneComponent;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
 
 
 //# sourceMappingURL=babylon.physicsEngineComponent.js.map
 //# sourceMappingURL=babylon.physicsEngineComponent.js.map
@@ -107486,6 +107557,9 @@ var BABYLON;
                 if (value === this._capturePhysicsTime) {
                 if (value === this._capturePhysicsTime) {
                     return;
                     return;
                 }
                 }
+                if (!this.scene.onBeforePhysicsObservable) {
+                    return;
+                }
                 this._capturePhysicsTime = value;
                 this._capturePhysicsTime = value;
                 if (value) {
                 if (value) {
                     this._onBeforePhysicsObserver = this.scene.onBeforePhysicsObservable.add(function () {
                     this._onBeforePhysicsObserver = this.scene.onBeforePhysicsObservable.add(function () {
@@ -107739,10 +107813,14 @@ var BABYLON;
             this._onBeforeDrawPhaseObserver = null;
             this._onBeforeDrawPhaseObserver = null;
             this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
             this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
             this._onAfterDrawPhaseObserver = null;
             this._onAfterDrawPhaseObserver = null;
-            this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
-            this._onBeforePhysicsObserver = null;
-            this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
-            this._onAfterPhysicsObserver = null;
+            if (this._onBeforePhysicsObserver) {
+                this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
+                this._onBeforePhysicsObserver = null;
+            }
+            if (this._onAfterPhysicsObserver) {
+                this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
+                this._onAfterPhysicsObserver = null;
+            }
             this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
             this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
             this._onAfterAnimationsObserver = null;
             this._onAfterAnimationsObserver = null;
             this.scene.onBeforeCameraRenderObservable.remove(this._onBeforeCameraRenderObserver);
             this.scene.onBeforeCameraRenderObservable.remove(this._onBeforeCameraRenderObserver);

+ 122 - 44
dist/preview release/babylon.no-module.max.js

@@ -23706,6 +23706,7 @@ var BABYLON;
         SceneComponentConstants.NAME_PROCEDURALTEXTURE = "ProceduralTexture";
         SceneComponentConstants.NAME_PROCEDURALTEXTURE = "ProceduralTexture";
         SceneComponentConstants.NAME_SHADOWGENERATOR = "ShadowGenerator";
         SceneComponentConstants.NAME_SHADOWGENERATOR = "ShadowGenerator";
         SceneComponentConstants.NAME_OCTREE = "Octree";
         SceneComponentConstants.NAME_OCTREE = "Octree";
+        SceneComponentConstants.NAME_PHYSICSENGINE = "PhysicsEngine";
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
@@ -24006,7 +24007,7 @@ var BABYLON;
          */
          */
         function Scene(engine) {
         function Scene(engine) {
             var _this = _super.call(this) || this;
             var _this = _super.call(this) || this;
-            // Members
+            // Members   
             /**
             /**
              * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
              * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
              */
              */
@@ -24094,14 +24095,6 @@ var BABYLON;
             */
             */
             _this.onAfterDrawPhaseObservable = new BABYLON.Observable();
             _this.onAfterDrawPhaseObservable = new BABYLON.Observable();
             /**
             /**
-            * An event triggered when physic simulation is about to be run
-            */
-            _this.onBeforePhysicsObservable = new BABYLON.Observable();
-            /**
-            * An event triggered when physic simulation has been done
-            */
-            _this.onAfterPhysicsObservable = new BABYLON.Observable();
-            /**
             * An event triggered when the scene is ready
             * An event triggered when the scene is ready
             */
             */
             _this.onReadyObservable = new BABYLON.Observable();
             _this.onReadyObservable = new BABYLON.Observable();
@@ -24519,6 +24512,12 @@ var BABYLON;
             _this._activeMeshesFrozen = false;
             _this._activeMeshesFrozen = false;
             /** @hidden */
             /** @hidden */
             _this._allowPostProcessClearColor = true;
             _this._allowPostProcessClearColor = true;
+            /**
+             * User updatable function that will return a deterministic frame time when engine is in deterministic lock step mode
+             */
+            _this.getDeterministicFrameTime = function () {
+                return 1000.0 / 60.0; // frame time in ms
+            };
             _this._tempPickingRay = BABYLON.Ray ? BABYLON.Ray.Zero() : null;
             _this._tempPickingRay = BABYLON.Ray ? BABYLON.Ray.Zero() : null;
             /** Gets or sets a boolean blocking all the calls to markAllMaterialsAsDirty (ie. the materials won't be updated if they are out of sync) */
             /** Gets or sets a boolean blocking all the calls to markAllMaterialsAsDirty (ie. the materials won't be updated if they are out of sync) */
             _this.blockMaterialDirtyMechanism = false;
             _this.blockMaterialDirtyMechanism = false;
@@ -27728,6 +27727,10 @@ var BABYLON;
                 }
                 }
             }
             }
         };
         };
+        /** @hidden */
+        Scene.prototype._advancePhysicsEngineStep = function (step) {
+            // Do nothing. Code will be replaced if physics engine component is referenced
+        };
         /**
         /**
          * Render the scene
          * Render the scene
          * @param updateCameras defines a boolean indicating if cameras must update according to their inputs (true by default)
          * @param updateCameras defines a boolean indicating if cameras must update according to their inputs (true by default)
@@ -27754,10 +27757,7 @@ var BABYLON;
             if (this._engine.isDeterministicLockStep()) {
             if (this._engine.isDeterministicLockStep()) {
                 var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) + this._timeAccumulator;
                 var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) + this._timeAccumulator;
                 var defaultFPS = (60.0 / 1000.0);
                 var defaultFPS = (60.0 / 1000.0);
-                var defaultFrameTime = 1000 / 60; // frame time in MS
-                if (this._physicsEngine) {
-                    defaultFrameTime = this._physicsEngine.getTimeStep() * 1000;
-                }
+                var defaultFrameTime = this.getDeterministicFrameTime();
                 var stepsTaken = 0;
                 var stepsTaken = 0;
                 var maxSubSteps = this._engine.getLockstepMaxSteps();
                 var maxSubSteps = this._engine.getLockstepMaxSteps();
                 var internalSteps = Math.floor(deltaTime / (1000 * defaultFPS));
                 var internalSteps = Math.floor(deltaTime / (1000 * defaultFPS));
@@ -27769,11 +27769,7 @@ var BABYLON;
                     this._animate();
                     this._animate();
                     this.onAfterAnimationsObservable.notifyObservers(this);
                     this.onAfterAnimationsObservable.notifyObservers(this);
                     // Physics
                     // Physics
-                    if (this._physicsEngine) {
-                        this.onBeforePhysicsObservable.notifyObservers(this);
-                        this._physicsEngine.step(defaultFrameTime / 1000);
-                        this.onAfterPhysicsObservable.notifyObservers(this);
-                    }
+                    this._advancePhysicsEngineStep(defaultFrameTime);
                     this.onAfterStepObservable.notifyObservers(this);
                     this.onAfterStepObservable.notifyObservers(this);
                     this._currentStepId++;
                     this._currentStepId++;
                     stepsTaken++;
                     stepsTaken++;
@@ -27788,11 +27784,7 @@ var BABYLON;
                 this._animate();
                 this._animate();
                 this.onAfterAnimationsObservable.notifyObservers(this);
                 this.onAfterAnimationsObservable.notifyObservers(this);
                 // Physics
                 // Physics
-                if (this._physicsEngine) {
-                    this.onBeforePhysicsObservable.notifyObservers(this);
-                    this._physicsEngine.step(deltaTime / 1000.0);
-                    this.onAfterPhysicsObservable.notifyObservers(this);
-                }
+                this._advancePhysicsEngineStep(deltaTime);
             }
             }
             // Before camera update steps
             // Before camera update steps
             for (var _i = 0, _a = this._beforeCameraUpdateStage; _i < _a.length; _i++) {
             for (var _i = 0, _a = this._beforeCameraUpdateStage; _i < _a.length; _i++) {
@@ -28122,8 +28114,6 @@ var BABYLON;
             this.onAfterParticlesRenderingObservable.clear();
             this.onAfterParticlesRenderingObservable.clear();
             this.onBeforeDrawPhaseObservable.clear();
             this.onBeforeDrawPhaseObservable.clear();
             this.onAfterDrawPhaseObservable.clear();
             this.onAfterDrawPhaseObservable.clear();
-            this.onBeforePhysicsObservable.clear();
-            this.onAfterPhysicsObservable.clear();
             this.onBeforeAnimationsObservable.clear();
             this.onBeforeAnimationsObservable.clear();
             this.onAfterAnimationsObservable.clear();
             this.onAfterAnimationsObservable.clear();
             this.onDataLoadedObservable.clear();
             this.onDataLoadedObservable.clear();
@@ -28191,10 +28181,6 @@ var BABYLON;
             }
             }
             // Post-processes
             // Post-processes
             this.postProcessManager.dispose();
             this.postProcessManager.dispose();
-            // Physics
-            if (this._physicsEngine) {
-                this.disablePhysicsEngine();
-            }
             // Remove from engine
             // Remove from engine
             index = this._engine.scenes.indexOf(this);
             index = this._engine.scenes.indexOf(this);
             if (index > -1) {
             if (index > -1) {
@@ -28518,7 +28504,6 @@ var BABYLON;
         Scene.prototype.getPointerOverMesh = function () {
         Scene.prototype.getPointerOverMesh = function () {
             return this._pointerOverMesh;
             return this._pointerOverMesh;
         };
         };
-        // Physics
         // Misc.
         // Misc.
         /** @hidden */
         /** @hidden */
         Scene.prototype._rebuildGeometries = function () {
         Scene.prototype._rebuildGeometries = function () {
@@ -55749,14 +55734,21 @@ var BABYLON;
          */
          */
         Particle.prototype.updateCellIndex = function () {
         Particle.prototype.updateCellIndex = function () {
             var offsetAge = this.age;
             var offsetAge = this.age;
+            var changeSpeed = this.particleSystem.spriteCellChangeSpeed;
             if (this.particleSystem.spriteRandomStartCell) {
             if (this.particleSystem.spriteRandomStartCell) {
                 if (this._randomCellOffset === undefined) {
                 if (this._randomCellOffset === undefined) {
                     this._randomCellOffset = Math.random() * this.lifeTime;
                     this._randomCellOffset = Math.random() * this.lifeTime;
                 }
                 }
-                offsetAge += this._randomCellOffset;
+                if (changeSpeed === 0) { // Special case when speed = 0 meaning we want to stay on initial cell
+                    changeSpeed = 1;
+                    offsetAge = this._randomCellOffset;
+                }
+                else {
+                    offsetAge += this._randomCellOffset;
+                }
             }
             }
             var dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
             var dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
-            var ratio = BABYLON.Scalar.Clamp(((offsetAge * this.particleSystem.spriteCellChangeSpeed) % this.lifeTime) / this.lifeTime);
+            var ratio = BABYLON.Scalar.Clamp(((offsetAge * changeSpeed) % this.lifeTime) / this.lifeTime);
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
         };
         };
         /** @hidden */
         /** @hidden */
@@ -56026,6 +56018,10 @@ var BABYLON;
             this._rampGradients = null;
             this._rampGradients = null;
             this._colorRemapGradients = null;
             this._colorRemapGradients = null;
             this._alphaRemapGradients = null;
             this._alphaRemapGradients = null;
+            /**
+             * Defines the delay in milliseconds before starting the system (0 by default)
+             */
+            this.startDelay = 0;
             /** Gets or sets a value indicating the damping to apply if the limit velocity factor is reached */
             /** Gets or sets a value indicating the damping to apply if the limit velocity factor is reached */
             this.limitVelocityDamping = 0.4;
             this.limitVelocityDamping = 0.4;
             /**
             /**
@@ -56081,6 +56077,11 @@ var BABYLON;
         BaseParticleSystem.prototype.getScene = function () {
         BaseParticleSystem.prototype.getScene = function () {
             return this._scene;
             return this._scene;
         };
         };
+        BaseParticleSystem.prototype._hasTargetStopDurationDependantGradient = function () {
+            return (this._startSizeGradients && this._startSizeGradients.length > 0)
+                || (this._emitRateGradients && this._emitRateGradients.length > 0)
+                || (this._lifeTimeGradients && this._lifeTimeGradients.length > 0);
+        };
         /**
         /**
          * Gets the current list of drag gradients.
          * Gets the current list of drag gradients.
          * You must use addDragGradient and removeDragGradient to udpate this list
          * You must use addDragGradient and removeDragGradient to udpate this list
@@ -57326,11 +57327,14 @@ var BABYLON;
         };
         };
         /**
         /**
          * Starts the particle system and begins to emit
          * Starts the particle system and begins to emit
-         * @param delay defines the delay in milliseconds before starting the system (0 by default)
+         * @param delay defines the delay in milliseconds before starting the system (this.startDelay by default)
          */
          */
         ParticleSystem.prototype.start = function (delay) {
         ParticleSystem.prototype.start = function (delay) {
             var _this = this;
             var _this = this;
-            if (delay === void 0) { delay = 0; }
+            if (delay === void 0) { delay = this.startDelay; }
+            if (!this.targetStopDuration && this._hasTargetStopDurationDependantGradient()) {
+                throw "Particle system started with a targetStopDuration dependant gradient (eg. startSizeGradients) but no targetStopDuration set";
+            }
             if (delay) {
             if (delay) {
                 setTimeout(function () {
                 setTimeout(function () {
                     _this.start(0);
                     _this.start(0);
@@ -57538,7 +57542,7 @@ var BABYLON;
                 // Size and scale
                 // Size and scale
                 particle.scale.copyFromFloats(BABYLON.Scalar.RandomRange(this_1.minScaleX, this_1.maxScaleX), BABYLON.Scalar.RandomRange(this_1.minScaleY, this_1.maxScaleY));
                 particle.scale.copyFromFloats(BABYLON.Scalar.RandomRange(this_1.minScaleX, this_1.maxScaleX), BABYLON.Scalar.RandomRange(this_1.minScaleY, this_1.maxScaleY));
                 // Adjust scale by start size
                 // Adjust scale by start size
-                if (this_1._startSizeGradients && this_1._startSizeGradients[0]) {
+                if (this_1._startSizeGradients && this_1._startSizeGradients[0] && this_1.targetStopDuration) {
                     var ratio = this_1._actualFrame / this_1.targetStopDuration;
                     var ratio = this_1._actualFrame / this_1.targetStopDuration;
                     BABYLON.Tools.GetCurrentGradient(ratio, this_1._startSizeGradients, function (currentGradient, nextGradient, scale) {
                     BABYLON.Tools.GetCurrentGradient(ratio, this_1._startSizeGradients, function (currentGradient, nextGradient, scale) {
                         if (currentGradient !== _this._currentStartSizeGradient) {
                         if (currentGradient !== _this._currentStartSizeGradient) {
@@ -62129,11 +62133,14 @@ var BABYLON;
         };
         };
         /**
         /**
          * Starts the particle system and begins to emit
          * Starts the particle system and begins to emit
-         * @param delay defines the delay in milliseconds before starting the system (0 by default)
+         * @param delay defines the delay in milliseconds before starting the system (this.startDelay by default)
          */
          */
         GPUParticleSystem.prototype.start = function (delay) {
         GPUParticleSystem.prototype.start = function (delay) {
             var _this = this;
             var _this = this;
-            if (delay === void 0) { delay = 0; }
+            if (delay === void 0) { delay = this.startDelay; }
+            if (!this.targetStopDuration && this._hasTargetStopDurationDependantGradient()) {
+                throw "Particle system started with a targetStopDuration dependant gradient (eg. startSizeGradients) but no targetStopDuration set";
+            }
             if (delay) {
             if (delay) {
                 setTimeout(function () {
                 setTimeout(function () {
                     _this.start(0);
                     _this.start(0);
@@ -78722,7 +78729,7 @@ var BABYLON;
         this._geometryBufferRenderer = null;
         this._geometryBufferRenderer = null;
     };
     };
     /**
     /**
-     * Defines the Geometry Buffer scene component responsible to manage a G-Buffer usefull
+     * Defines the Geometry Buffer scene component responsible to manage a G-Buffer useful
      * in several rendering techniques.
      * in several rendering techniques.
      */
      */
     var GeometryBufferRendererSceneComponent = /** @class */ (function () {
     var GeometryBufferRendererSceneComponent = /** @class */ (function () {
@@ -78732,7 +78739,7 @@ var BABYLON;
          */
          */
         function GeometryBufferRendererSceneComponent(scene) {
         function GeometryBufferRendererSceneComponent(scene) {
             /**
             /**
-             * The component name helpfull to identify the component in the list of scene components.
+             * The component name helpful to identify the component in the list of scene components.
              */
              */
             this.name = BABYLON.SceneComponentConstants.NAME_GEOMETRYBUFFERRENDERER;
             this.name = BABYLON.SceneComponentConstants.NAME_GEOMETRYBUFFERRENDERER;
             this.scene = scene;
             this.scene = scene;
@@ -89727,7 +89734,7 @@ var BABYLON;
          * Called by the scene. No need to call it.
          * Called by the scene. No need to call it.
          * @param delta defines the timespam between frames
          * @param delta defines the timespam between frames
          */
          */
-        PhysicsEngine.prototype.step = function (delta) {
+        PhysicsEngine.prototype._step = function (delta) {
             var _this = this;
             var _this = this;
             //check if any mesh has no body / requires an update
             //check if any mesh has no body / requires an update
             this._impostors.forEach(function (impostor) {
             this._impostors.forEach(function (impostor) {
@@ -91329,6 +91336,12 @@ var BABYLON;
         if (this._physicsEngine) {
         if (this._physicsEngine) {
             return true;
             return true;
         }
         }
+        // Register the component to the scene
+        var component = this._getComponent(BABYLON.SceneComponentConstants.NAME_PHYSICSENGINE);
+        if (!component) {
+            component = new PhysicsEngineSceneComponent(this);
+            this._addComponent(component);
+        }
         try {
         try {
             this._physicsEngine = new BABYLON.PhysicsEngine(gravity, plugin);
             this._physicsEngine = new BABYLON.PhysicsEngine(gravity, plugin);
             return true;
             return true;
@@ -91366,6 +91379,64 @@ var BABYLON;
             mesh.physicsImpostor = null;
             mesh.physicsImpostor = null;
         }
         }
     };
     };
+    /** @hidden */
+    BABYLON.Scene.prototype._advancePhysicsEngineStep = function (step) {
+        if (this._physicsEngine) {
+            this.onBeforePhysicsObservable.notifyObservers(this);
+            this._physicsEngine._step(step / 1000);
+            this.onAfterPhysicsObservable.notifyObservers(this);
+        }
+    };
+    /**
+     * Defines the physics engine scene component responsible to manage a physics engine
+     */
+    var PhysicsEngineSceneComponent = /** @class */ (function () {
+        /**
+         * Creates a new instance of the component for the given scene
+         * @param scene Defines the scene to register the component in
+         */
+        function PhysicsEngineSceneComponent(scene) {
+            var _this = this;
+            /**
+             * The component name helpful to identify the component in the list of scene components.
+             */
+            this.name = BABYLON.SceneComponentConstants.NAME_PHYSICSENGINE;
+            this.scene = scene;
+            this.scene.onBeforePhysicsObservable = new BABYLON.Observable();
+            this.scene.onAfterPhysicsObservable = new BABYLON.Observable();
+            // Replace the function used to get the deterministic frame time
+            this.scene.getDeterministicFrameTime = function () {
+                if (_this.scene._physicsEngine) {
+                    return _this.scene._physicsEngine.getTimeStep() * 1000;
+                }
+                return 1000.0 / 60.0;
+            };
+        }
+        /**
+         * Registers the component in a given scene
+         */
+        PhysicsEngineSceneComponent.prototype.register = function () {
+        };
+        /**
+         * Rebuilds the elements related to this component in case of
+         * context lost for instance.
+         */
+        PhysicsEngineSceneComponent.prototype.rebuild = function () {
+            // Nothing to do for this component
+        };
+        /**
+         * Disposes the component and the associated ressources
+         */
+        PhysicsEngineSceneComponent.prototype.dispose = function () {
+            this.scene.onBeforePhysicsObservable.clear();
+            this.scene.onAfterPhysicsObservable.clear();
+            if (this.scene._physicsEngine) {
+                this.scene.disablePhysicsEngine();
+            }
+        };
+        return PhysicsEngineSceneComponent;
+    }());
+    BABYLON.PhysicsEngineSceneComponent = PhysicsEngineSceneComponent;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
 
 
 //# sourceMappingURL=babylon.physicsEngineComponent.js.map
 //# sourceMappingURL=babylon.physicsEngineComponent.js.map
@@ -107453,6 +107524,9 @@ var BABYLON;
                 if (value === this._capturePhysicsTime) {
                 if (value === this._capturePhysicsTime) {
                     return;
                     return;
                 }
                 }
+                if (!this.scene.onBeforePhysicsObservable) {
+                    return;
+                }
                 this._capturePhysicsTime = value;
                 this._capturePhysicsTime = value;
                 if (value) {
                 if (value) {
                     this._onBeforePhysicsObserver = this.scene.onBeforePhysicsObservable.add(function () {
                     this._onBeforePhysicsObserver = this.scene.onBeforePhysicsObservable.add(function () {
@@ -107706,10 +107780,14 @@ var BABYLON;
             this._onBeforeDrawPhaseObserver = null;
             this._onBeforeDrawPhaseObserver = null;
             this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
             this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
             this._onAfterDrawPhaseObserver = null;
             this._onAfterDrawPhaseObserver = null;
-            this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
-            this._onBeforePhysicsObserver = null;
-            this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
-            this._onAfterPhysicsObserver = null;
+            if (this._onBeforePhysicsObserver) {
+                this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
+                this._onBeforePhysicsObserver = null;
+            }
+            if (this._onAfterPhysicsObserver) {
+                this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
+                this._onAfterPhysicsObserver = null;
+            }
             this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
             this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
             this._onAfterAnimationsObserver = null;
             this._onAfterAnimationsObserver = null;
             this.scene.onBeforeCameraRenderObservable.remove(this._onBeforeCameraRenderObserver);
             this.scene.onBeforeCameraRenderObservable.remove(this._onBeforeCameraRenderObserver);

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/babylon.worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 124 - 46
dist/preview release/es6.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 9 - 2
src/Particles/babylon.particle.ts

@@ -152,16 +152,23 @@
          */
          */
         public updateCellIndex(): void {
         public updateCellIndex(): void {
             let offsetAge = this.age;
             let offsetAge = this.age;
+            let changeSpeed = this.particleSystem.spriteCellChangeSpeed;
 
 
             if (this.particleSystem.spriteRandomStartCell) {
             if (this.particleSystem.spriteRandomStartCell) {
                 if (this._randomCellOffset === undefined) {         
                 if (this._randomCellOffset === undefined) {         
                     this._randomCellOffset = Math.random() * this.lifeTime;
                     this._randomCellOffset = Math.random() * this.lifeTime;
                 }
                 }
-                offsetAge += this._randomCellOffset;
+
+                if (changeSpeed === 0) { // Special case when speed = 0 meaning we want to stay on initial cell
+                    changeSpeed = 1;
+                    offsetAge = this._randomCellOffset;
+                } else {
+                    offsetAge += this._randomCellOffset;
+                }
             }
             }
 
 
             let dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
             let dist = (this._initialEndSpriteCellID - this._initialStartSpriteCellID);
-            let ratio = Scalar.Clamp(((offsetAge * this.particleSystem.spriteCellChangeSpeed) % this.lifeTime) / this.lifeTime);
+            let ratio = Scalar.Clamp(((offsetAge * changeSpeed) % this.lifeTime) / this.lifeTime);
 
 
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
             this.cellIndex = this._initialStartSpriteCellID + (ratio * dist) | 0;
         }
         }