Преглед изворни кода

Merge remote-tracking branch 'upstream/master'

sebastien пре 7 година
родитељ
комит
f4260ca6d8
35 измењених фајлова са 12413 додато и 11339 уклоњено
  1. 924 915
      Playground/babylon.d.txt
  2. 10302 10161
      dist/preview release/babylon.d.ts
  3. 1 1
      dist/preview release/babylon.js
  4. 254 53
      dist/preview release/babylon.max.js
  5. 254 53
      dist/preview release/babylon.no-module.max.js
  6. 1 1
      dist/preview release/babylon.worker.js
  7. 254 53
      dist/preview release/es6.js
  8. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  9. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js
  10. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js.map
  11. 2 0
      dist/preview release/inspector/babylon.inspector.d.ts
  12. 4 0
      dist/preview release/inspector/babylon.inspector.module.d.ts
  13. 8 5
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  14. 9 6
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  15. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  16. 11 7
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  17. 14 9
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  18. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  19. 11 7
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  20. 14 9
      dist/preview release/loaders/babylon.glTFFileLoader.js
  21. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  22. 31 3
      dist/preview release/loaders/babylon.objFileLoader.d.ts
  23. 31 3
      dist/preview release/loaders/babylon.objFileLoader.js
  24. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  25. 42 10
      dist/preview release/loaders/babylonjs.loaders.d.ts
  26. 45 12
      dist/preview release/loaders/babylonjs.loaders.js
  27. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  28. 42 10
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  29. 1 1
      dist/preview release/viewer/babylon.viewer.js
  30. 4 4
      dist/preview release/viewer/babylon.viewer.max.js
  31. 2 1
      dist/preview release/what's new.md
  32. 23 2
      src/Particles/babylon.IParticleSystem.ts
  33. 11 1
      src/Particles/babylon.baseParticleSystem.ts
  34. 22 0
      src/Particles/babylon.gpuParticleSystem.ts
  35. 88 4
      src/Particles/babylon.particleSystem.ts

Разлика између датотеке није приказан због своје велике величине
+ 924 - 915
Playground/babylon.d.txt


Разлика између датотеке није приказан због своје велике величине
+ 10302 - 10161
dist/preview release/babylon.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/babylon.js


+ 254 - 53
dist/preview release/babylon.max.js

@@ -19647,20 +19647,10 @@ var BABYLON;
              */
             _this.renderingGroupId = 0;
             _this._receiveShadows = false;
-            /**
-             * Gets or sets a boolean indicating if the outline must be rendered as well
-             * @see https://www.babylonjs-playground.com/#10WJ5S#3
-             */
-            _this.renderOutline = false;
             /** Defines color to use when rendering outline */
             _this.outlineColor = BABYLON.Color3.Red();
             /** Define width to use when rendering outline */
             _this.outlineWidth = 0.02;
-            /**
-             * Gets or sets a boolean indicating if the overlay must be rendered as well
-             * @see https://www.babylonjs-playground.com/#10WJ5S#2
-             */
-            _this.renderOverlay = false;
             /** Defines color to use when rendering overlay */
             _this.overlayColor = BABYLON.Color3.Red();
             /** Defines alpha to use when rendering overlay */
@@ -23736,6 +23726,7 @@ var BABYLON;
         SceneComponentConstants.NAME_DEPTHRENDERER = "DepthRenderer";
         SceneComponentConstants.NAME_POSTPROCESSRENDERPIPELINEMANAGER = "PostProcessRenderPipelineManager";
         SceneComponentConstants.NAME_SPRITE = "Sprite";
+        SceneComponentConstants.NAME_OUTLINERENDERER = "Outline";
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
@@ -23743,6 +23734,8 @@ var BABYLON;
         SceneComponentConstants.STEP_CAMERADRAWRENDERTARGET_EFFECTLAYER = 1;
         SceneComponentConstants.STEP_BEFORECAMERADRAW_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFORECAMERADRAW_LAYER = 1;
+        SceneComponentConstants.STEP_BEFORERENDERINGMESH_OUTLINE = 0;
+        SceneComponentConstants.STEP_AFTERRENDERINGMESH_OUTLINE = 0;
         SceneComponentConstants.STEP_AFTERRENDERINGGROUPDRAW_EFFECTLAYER_DRAW = 0;
         SceneComponentConstants.STEP_BEFORECAMERAUPDATE_SIMPLIFICATIONQUEUE = 0;
         SceneComponentConstants.STEP_BEFORECAMERAUPDATE_GAMEPAD = 1;
@@ -24486,11 +24479,22 @@ var BABYLON;
              */
             _this._beforeCameraDrawStage = BABYLON.Stage.Create();
             /**
+             * @hidden
              * Defines the actions happening just before a rendering group is drawing.
              */
             _this._beforeRenderingGroupDrawStage = BABYLON.Stage.Create();
             /**
              * @hidden
+             * Defines the actions happening just before a mesh is drawing.
+             */
+            _this._beforeRenderingMeshStage = BABYLON.Stage.Create();
+            /**
+             * @hidden
+             * Defines the actions happening just after a mesh has been drawn.
+             */
+            _this._afterRenderingMeshStage = BABYLON.Stage.Create();
+            /**
+             * @hidden
              * Defines the actions happening just after a rendering group has been drawn.
              */
             _this._afterRenderingGroupDrawStage = BABYLON.Stage.Create();
@@ -24532,9 +24536,6 @@ var BABYLON;
             if (BABYLON.PostProcessManager) {
                 _this.postProcessManager = new BABYLON.PostProcessManager(_this);
             }
-            if (BABYLON.OutlineRenderer) {
-                _this._outlineRenderer = new BABYLON.OutlineRenderer(_this);
-            }
             if (BABYLON.Tools.IsWindowObjectExist()) {
                 _this.attachControl();
             }
@@ -25051,13 +25052,6 @@ var BABYLON;
             return this._cachedEffect !== effect || this._cachedMaterial !== material || this._cachedVisibility !== visibility;
         };
         /**
-         * Gets the outline renderer associated with the scene
-         * @returns a OutlineRenderer
-         */
-        Scene.prototype.getOutlineRenderer = function () {
-            return this._outlineRenderer;
-        };
-        /**
          * Gets the engine associated with the scene
          * @returns an Engine
          */
@@ -28125,6 +28119,8 @@ var BABYLON;
             this._cameraDrawRenderTargetStage.clear();
             this._beforeCameraDrawStage.clear();
             this._beforeRenderingGroupDrawStage.clear();
+            this._beforeRenderingMeshStage.clear();
+            this._afterRenderingMeshStage.clear();
             this._afterRenderingGroupDrawStage.clear();
             this._afterCameraDrawStage.clear();
             this._beforeCameraUpdateStage.clear();
@@ -32391,12 +32387,9 @@ var BABYLON;
             if (enableAlphaMode) {
                 engine.setAlphaMode(this._effectiveMaterial.alphaMode);
             }
-            // Outline - step 1
-            var savedDepthWrite = engine.getDepthWrite();
-            if (this.renderOutline) {
-                engine.setDepthWrite(false);
-                scene.getOutlineRenderer().render(subMesh, batch);
-                engine.setDepthWrite(savedDepthWrite);
+            for (var _i = 0, _a = scene._beforeRenderingMeshStage; _i < _a.length; _i++) {
+                var step = _a[_i];
+                step.action(this, subMesh, batch);
             }
             var effect;
             if (this._effectiveMaterial.storeEffectOnSubMeshes) {
@@ -32440,19 +32433,9 @@ var BABYLON;
             this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, this._effectiveMaterial);
             // Unbind
             this._effectiveMaterial.unbind();
-            // Outline - step 2
-            if (this.renderOutline && savedDepthWrite) {
-                engine.setDepthWrite(true);
-                engine.setColorWrite(false);
-                scene.getOutlineRenderer().render(subMesh, batch);
-                engine.setColorWrite(true);
-            }
-            // Overlay
-            if (this.renderOverlay) {
-                var currentMode = engine.getAlphaMode();
-                engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
-                scene.getOutlineRenderer().render(subMesh, batch, true);
-                engine.setAlphaMode(currentMode);
+            for (var _b = 0, _c = scene._afterRenderingMeshStage; _b < _c.length; _b++) {
+                var step = _c[_b];
+                step.action(this, subMesh, batch);
             }
             if (this._onAfterRenderObservable) {
                 this._onAfterRenderObservable.notifyObservers(this);
@@ -56167,6 +56150,7 @@ var BABYLON;
             this._limitVelocityGradients = null;
             this._dragGradients = null;
             this._emitRateGradients = null;
+            this._startSizeGradients = null;
             /** Gets or sets a value indicating the damping to apply if the limit velocity factor is reached */
             this.limitVelocityDamping = 0.4;
             /**
@@ -56279,6 +56263,14 @@ var BABYLON;
             return this._velocityGradients;
         };
         /**
+         * Gets the current list of start size gradients.
+         * You must use addStartSizeGradient and removeStartSizeGradient to udpate this list
+         * @returns the list of start size gradients
+         */
+        BaseParticleSystem.prototype.getStartSizeGradients = function () {
+            return this._startSizeGradients;
+        };
+        /**
          * Gets the current list of emit rate gradients.
          * You must use addEmitRateGradient and removeEmitRateGradient to udpate this list
          * @returns the list of emit rate gradients
@@ -56587,6 +56579,10 @@ var BABYLON;
             _this._currentEmitRate1 = 0;
             /** @hidden */
             _this._currentEmitRate2 = 0;
+            /** @hidden */
+            _this._currentStartSize1 = 0;
+            /** @hidden */
+            _this._currentStartSize2 = 0;
             // start of sub system methods
             /**
              * "Recycles" one of the particle by copying it back to the "stock" of particles and removing it from the active list.
@@ -56997,6 +56993,37 @@ var BABYLON;
             return this;
         };
         /**
+         * Adds a new start size gradient (please note that this will only work if you set the targetStopDuration property)
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size value to affect to the specified gradient
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        ParticleSystem.prototype.addStartSizeGradient = function (gradient, factor, factor2) {
+            if (!this._startSizeGradients) {
+                this._startSizeGradients = [];
+            }
+            this._addFactorGradient(this._startSizeGradients, gradient, factor, factor2);
+            if (!this._currentStartSizeGradient) {
+                this._currentStartSizeGradient = this._startSizeGradients[0];
+                this._currentStartSize1 = this._currentStartSizeGradient.getFactor();
+                this._currentStartSize2 = this._currentStartSize1;
+            }
+            if (this._startSizeGradients.length === 2) {
+                this._currentStartSize2 = this._startSizeGradients[1].getFactor();
+            }
+            return this;
+        };
+        /**
+         * Remove a specific start size gradient
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        ParticleSystem.prototype.removeStartSizeGradient = function (gradient) {
+            this._removeFactorGradient(this._emitRateGradients, gradient);
+            return this;
+        };
+        /**
          * Adds a new color gradient
          * @param gradient defines the gradient to use (between 0 and 1)
          * @param color defines the color to affect to the specified gradient
@@ -57256,6 +57283,7 @@ var BABYLON;
         };
         // End of sub system methods
         ParticleSystem.prototype._update = function (newParticles) {
+            var _this = this;
             // Update current
             this._alive = this._particles.length > 0;
             if (this.emitter.position) {
@@ -57333,6 +57361,19 @@ var BABYLON;
                 }
                 // Size and scale
                 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
+                if (this_1._startSizeGradients && this_1._startSizeGradients[0]) {
+                    var ratio = this_1._actualFrame / this_1.targetStopDuration;
+                    BABYLON.Tools.GetCurrentGradient(ratio, this_1._startSizeGradients, function (currentGradient, nextGradient, scale) {
+                        if (currentGradient !== _this._currentStartSizeGradient) {
+                            _this._currentStartSize1 = _this._currentStartSize2;
+                            _this._currentStartSize2 = nextGradient.getFactor();
+                            _this._currentStartSizeGradient = currentGradient;
+                        }
+                        var value = BABYLON.Scalar.Lerp(_this._currentStartSize1, _this._currentStartSize2, scale);
+                        particle.scale.scaleInPlace(value);
+                    });
+                }
                 // Angle
                 if (!this_1._angularSpeedGradients || this_1._angularSpeedGradients.length === 0) {
                     particle.angularSpeed = BABYLON.Scalar.RandomRange(this_1.minAngularSpeed, this_1.maxAngularSpeed);
@@ -57896,11 +57937,26 @@ var BABYLON;
                     serializationObject.emitRateGradients.push(serializedGradient);
                 }
             }
+            var startSizeGradients = particleSystem.getStartSizeGradients();
+            if (startSizeGradients) {
+                serializationObject.startSizeGradients = [];
+                for (var _f = 0, startSizeGradients_1 = startSizeGradients; _f < startSizeGradients_1.length; _f++) {
+                    var startSizeGradient = startSizeGradients_1[_f];
+                    var serializedGradient = {
+                        gradient: startSizeGradient.gradient,
+                        factor1: startSizeGradient.factor1
+                    };
+                    if (startSizeGradient.factor2 !== undefined) {
+                        serializedGradient.factor2 = startSizeGradient.factor2;
+                    }
+                    serializationObject.startSizeGradients.push(serializedGradient);
+                }
+            }
             var limitVelocityGradients = particleSystem.getLimitVelocityGradients();
             if (limitVelocityGradients) {
                 serializationObject.limitVelocityGradients = [];
-                for (var _f = 0, limitVelocityGradients_1 = limitVelocityGradients; _f < limitVelocityGradients_1.length; _f++) {
-                    var limitVelocityGradient = limitVelocityGradients_1[_f];
+                for (var _g = 0, limitVelocityGradients_1 = limitVelocityGradients; _g < limitVelocityGradients_1.length; _g++) {
+                    var limitVelocityGradient = limitVelocityGradients_1[_g];
                     var serializedGradient = {
                         gradient: limitVelocityGradient.gradient,
                         factor1: limitVelocityGradient.factor1
@@ -58021,9 +58077,15 @@ var BABYLON;
                     particleSystem.addEmitRateGradient(emitRateGradient.gradient, emitRateGradient.factor1 !== undefined ? emitRateGradient.factor1 : emitRateGradient.factor, emitRateGradient.factor2);
                 }
             }
+            if (parsedParticleSystem.startSizeGradients) {
+                for (var _m = 0, _o = parsedParticleSystem.startSizeGradients; _m < _o.length; _m++) {
+                    var startSizeGradient = _o[_m];
+                    particleSystem.addStartSizeGradient(startSizeGradient.gradient, startSizeGradient.factor1 !== undefined ? startSizeGradient.factor1 : startSizeGradient.factor, startSizeGradient.factor2);
+                }
+            }
             if (parsedParticleSystem.limitVelocityGradients) {
-                for (var _m = 0, _o = parsedParticleSystem.limitVelocityGradients; _m < _o.length; _m++) {
-                    var limitVelocityGradient = _o[_m];
+                for (var _p = 0, _q = parsedParticleSystem.limitVelocityGradients; _p < _q.length; _p++) {
+                    var limitVelocityGradient = _q[_p];
                     particleSystem.addLimitVelocityGradient(limitVelocityGradient.gradient, limitVelocityGradient.factor1 !== undefined ? limitVelocityGradient.factor1 : limitVelocityGradient.factor, limitVelocityGradient.factor2);
                 }
                 particleSystem.limitVelocityDamping = parsedParticleSystem.limitVelocityDamping;
@@ -61803,6 +61865,26 @@ var BABYLON;
             // Do nothing as emit rate is not supported by GPUParticleSystem
             return this;
         };
+        /**
+         * Not supported by GPUParticleSystem
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size value to affect to the specified gradient
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        GPUParticleSystem.prototype.addStartSizeGradient = function (gradient, factor, factor2) {
+            // Do nothing as start size is not supported by GPUParticleSystem
+            return this;
+        };
+        /**
+         * Not supported by GPUParticleSystem
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        GPUParticleSystem.prototype.removeStartSizeGradient = function (gradient) {
+            // Do nothing as start size is not supported by GPUParticleSystem
+            return this;
+        };
         GPUParticleSystem.prototype._reset = function () {
             this._releaseBuffers();
         };
@@ -71324,7 +71406,7 @@ var BABYLON;
                 }
                 else {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.importMeshAsync(meshNames, scene, data, rootUrl, progressHandler).then(function (result) {
+                    asyncedPlugin.importMeshAsync(meshNames, scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function (result) {
                         scene.loadingPluginName = plugin.name;
                         successHandler(result.meshes, result.particleSystems, result.skeletons, result.animationGroups);
                     }).catch(function (error) {
@@ -71482,7 +71564,7 @@ var BABYLON;
                 }
                 else {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.loadAsync(scene, data, rootUrl, progressHandler).then(function () {
+                    asyncedPlugin.loadAsync(scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function () {
                         scene.loadingPluginName = plugin.name;
                         successHandler();
                     }).catch(function (error) {
@@ -71595,7 +71677,7 @@ var BABYLON;
                 }
                 else if (plugin.loadAssetContainerAsync) {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.loadAssetContainerAsync(scene, data, rootUrl, progressHandler).then(function (assetContainer) {
+                    asyncedPlugin.loadAssetContainerAsync(scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function (assetContainer) {
                         scene.loadingPluginName = plugin.name;
                         successHandler(assetContainer);
                     }).catch(function (error) {
@@ -89337,13 +89419,19 @@ var BABYLON;
                 this.world.addConstraint(constraint);
             }
             else {
-                impostorJoint.mainImpostor.registerAfterPhysicsStep(function () {
+                impostorJoint.joint.jointData.forceApplicationCallback = impostorJoint.joint.jointData.forceApplicationCallback || function () {
                     constraint.applyForce();
-                });
+                };
+                impostorJoint.mainImpostor.registerAfterPhysicsStep(impostorJoint.joint.jointData.forceApplicationCallback);
             }
         };
         CannonJSPlugin.prototype.removeJoint = function (impostorJoint) {
-            this.world.removeConstraint(impostorJoint.joint.physicsJoint);
+            if (impostorJoint.joint.type !== BABYLON.PhysicsJoint.SpringJoint) {
+                this.world.removeConstraint(impostorJoint.joint.physicsJoint);
+            }
+            else {
+                impostorJoint.mainImpostor.unregisterAfterPhysicsStep(impostorJoint.joint.jointData.forceApplicationCallback);
+            }
         };
         CannonJSPlugin.prototype._addMaterial = function (name, friction, restitution) {
             var index;
@@ -100318,16 +100406,97 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * Gets the outline renderer associated with the scene
+     * @returns a OutlineRenderer
+     */
+    BABYLON.Scene.prototype.getOutlineRenderer = function () {
+        if (!this._outlineRenderer) {
+            this._outlineRenderer = new OutlineRenderer(this);
+        }
+        return this._outlineRenderer;
+    };
+    Object.defineProperty(BABYLON.AbstractMesh.prototype, "renderOutline", {
+        get: function () {
+            return this._renderOutline;
+        },
+        set: function (value) {
+            if (value) {
+                // Lazy Load the component.
+                this.getScene().getOutlineRenderer();
+            }
+            this._renderOutline = value;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(BABYLON.AbstractMesh.prototype, "renderOverlay", {
+        get: function () {
+            return this._renderOverlay;
+        },
+        set: function (value) {
+            if (value) {
+                // Lazy Load the component.
+                this.getScene().getOutlineRenderer();
+            }
+            this._renderOverlay = value;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    /**
+     * This class is responsible to draw bothe outline/overlay of meshes.
+     * It should not be used directly but through the available method on mesh.
+     */
     var OutlineRenderer = /** @class */ (function () {
+        /**
+         * Instantiates a new outline renderer. (There could be only one per scene).
+         * @param scene Defines the scene it belongs to
+         */
         function OutlineRenderer(scene) {
+            /**
+             * The name of the component. Each component must have a unique name.
+             */
+            this.name = BABYLON.SceneComponentConstants.NAME_OUTLINERENDERER;
+            /**
+             * Defines a zOffset to prevent zFighting between the overlay and the mesh.
+             */
             this.zOffset = 1;
-            this._scene = scene;
+            this.scene = scene;
+            this._engine = scene.getEngine();
+            this.scene._addComponent(this);
         }
+        /**
+         * Register the component to one instance of a scene.
+         */
+        OutlineRenderer.prototype.register = function () {
+            this.scene._beforeRenderingMeshStage.registerStep(BABYLON.SceneComponentConstants.STEP_BEFORERENDERINGMESH_OUTLINE, this, this._beforeRenderingMesh);
+            this.scene._afterRenderingMeshStage.registerStep(BABYLON.SceneComponentConstants.STEP_AFTERRENDERINGMESH_OUTLINE, this, this._afterRenderingMesh);
+        };
+        /**
+         * Rebuilds the elements related to this component in case of
+         * context lost for instance.
+         */
+        OutlineRenderer.prototype.rebuild = function () {
+            // Nothing to do here.
+        };
+        /**
+         * Disposes the component and the associated ressources.
+         */
+        OutlineRenderer.prototype.dispose = function () {
+            // Nothing to do here.
+        };
+        /**
+         * Renders the outline in the canvas.
+         * @param subMesh Defines the sumesh to render
+         * @param batch Defines the batch of meshes in case of instances
+         * @param useOverlay Defines if the rendering is for the overlay or the outline
+         */
         OutlineRenderer.prototype.render = function (subMesh, batch, useOverlay) {
             var _this = this;
             if (useOverlay === void 0) { useOverlay = false; }
-            var scene = this._scene;
-            var engine = this._scene.getEngine();
+            var scene = this.scene;
+            var engine = scene.getEngine();
             var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
             if (!this.isReady(subMesh, hardwareInstancedRendering)) {
                 return;
@@ -100362,6 +100531,13 @@ var BABYLON;
             mesh._processRendering(subMesh, this._effect, BABYLON.Material.TriangleFillMode, batch, hardwareInstancedRendering, function (isInstance, world) { _this._effect.setMatrix("world", world); });
             engine.setZOffset(0);
         };
+        /**
+         * Returns whether or not the outline renderer is ready for a given submesh.
+         * All the dependencies e.g. submeshes, texture, effect... mus be ready
+         * @param subMesh Defines the submesh to check readyness for
+         * @param useInstances Defines wheter wee are trying to render instances or not
+         * @returns true if ready otherwise false
+         */
         OutlineRenderer.prototype.isReady = function (subMesh, useInstances) {
             var defines = [];
             var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
@@ -100411,10 +100587,35 @@ var BABYLON;
             var join = defines.join("\n");
             if (this._cachedDefines !== join) {
                 this._cachedDefines = join;
-                this._effect = this._scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"], ["diffuseSampler"], join);
+                this._effect = this.scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"], ["diffuseSampler"], join);
             }
             return this._effect.isReady();
         };
+        OutlineRenderer.prototype._beforeRenderingMesh = function (mesh, subMesh, batch) {
+            // Outline - step 1
+            this._savedDepthWrite = this._engine.getDepthWrite();
+            if (mesh.renderOutline) {
+                this._engine.setDepthWrite(false);
+                this.render(subMesh, batch);
+                this._engine.setDepthWrite(this._savedDepthWrite);
+            }
+        };
+        OutlineRenderer.prototype._afterRenderingMesh = function (mesh, subMesh, batch) {
+            // Outline - step 2
+            if (mesh.renderOutline && this._savedDepthWrite) {
+                this._engine.setDepthWrite(true);
+                this._engine.setColorWrite(false);
+                this.render(subMesh, batch);
+                this._engine.setColorWrite(true);
+            }
+            // Overlay
+            if (mesh.renderOverlay) {
+                var currentMode = this._engine.getAlphaMode();
+                this._engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
+                this.render(subMesh, batch, true);
+                this._engine.setAlphaMode(currentMode);
+            }
+        };
         return OutlineRenderer;
     }());
     BABYLON.OutlineRenderer = OutlineRenderer;

+ 254 - 53
dist/preview release/babylon.no-module.max.js

@@ -19614,20 +19614,10 @@ var BABYLON;
              */
             _this.renderingGroupId = 0;
             _this._receiveShadows = false;
-            /**
-             * Gets or sets a boolean indicating if the outline must be rendered as well
-             * @see https://www.babylonjs-playground.com/#10WJ5S#3
-             */
-            _this.renderOutline = false;
             /** Defines color to use when rendering outline */
             _this.outlineColor = BABYLON.Color3.Red();
             /** Define width to use when rendering outline */
             _this.outlineWidth = 0.02;
-            /**
-             * Gets or sets a boolean indicating if the overlay must be rendered as well
-             * @see https://www.babylonjs-playground.com/#10WJ5S#2
-             */
-            _this.renderOverlay = false;
             /** Defines color to use when rendering overlay */
             _this.overlayColor = BABYLON.Color3.Red();
             /** Defines alpha to use when rendering overlay */
@@ -23703,6 +23693,7 @@ var BABYLON;
         SceneComponentConstants.NAME_DEPTHRENDERER = "DepthRenderer";
         SceneComponentConstants.NAME_POSTPROCESSRENDERPIPELINEMANAGER = "PostProcessRenderPipelineManager";
         SceneComponentConstants.NAME_SPRITE = "Sprite";
+        SceneComponentConstants.NAME_OUTLINERENDERER = "Outline";
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
@@ -23710,6 +23701,8 @@ var BABYLON;
         SceneComponentConstants.STEP_CAMERADRAWRENDERTARGET_EFFECTLAYER = 1;
         SceneComponentConstants.STEP_BEFORECAMERADRAW_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFORECAMERADRAW_LAYER = 1;
+        SceneComponentConstants.STEP_BEFORERENDERINGMESH_OUTLINE = 0;
+        SceneComponentConstants.STEP_AFTERRENDERINGMESH_OUTLINE = 0;
         SceneComponentConstants.STEP_AFTERRENDERINGGROUPDRAW_EFFECTLAYER_DRAW = 0;
         SceneComponentConstants.STEP_BEFORECAMERAUPDATE_SIMPLIFICATIONQUEUE = 0;
         SceneComponentConstants.STEP_BEFORECAMERAUPDATE_GAMEPAD = 1;
@@ -24453,11 +24446,22 @@ var BABYLON;
              */
             _this._beforeCameraDrawStage = BABYLON.Stage.Create();
             /**
+             * @hidden
              * Defines the actions happening just before a rendering group is drawing.
              */
             _this._beforeRenderingGroupDrawStage = BABYLON.Stage.Create();
             /**
              * @hidden
+             * Defines the actions happening just before a mesh is drawing.
+             */
+            _this._beforeRenderingMeshStage = BABYLON.Stage.Create();
+            /**
+             * @hidden
+             * Defines the actions happening just after a mesh has been drawn.
+             */
+            _this._afterRenderingMeshStage = BABYLON.Stage.Create();
+            /**
+             * @hidden
              * Defines the actions happening just after a rendering group has been drawn.
              */
             _this._afterRenderingGroupDrawStage = BABYLON.Stage.Create();
@@ -24499,9 +24503,6 @@ var BABYLON;
             if (BABYLON.PostProcessManager) {
                 _this.postProcessManager = new BABYLON.PostProcessManager(_this);
             }
-            if (BABYLON.OutlineRenderer) {
-                _this._outlineRenderer = new BABYLON.OutlineRenderer(_this);
-            }
             if (BABYLON.Tools.IsWindowObjectExist()) {
                 _this.attachControl();
             }
@@ -25018,13 +25019,6 @@ var BABYLON;
             return this._cachedEffect !== effect || this._cachedMaterial !== material || this._cachedVisibility !== visibility;
         };
         /**
-         * Gets the outline renderer associated with the scene
-         * @returns a OutlineRenderer
-         */
-        Scene.prototype.getOutlineRenderer = function () {
-            return this._outlineRenderer;
-        };
-        /**
          * Gets the engine associated with the scene
          * @returns an Engine
          */
@@ -28092,6 +28086,8 @@ var BABYLON;
             this._cameraDrawRenderTargetStage.clear();
             this._beforeCameraDrawStage.clear();
             this._beforeRenderingGroupDrawStage.clear();
+            this._beforeRenderingMeshStage.clear();
+            this._afterRenderingMeshStage.clear();
             this._afterRenderingGroupDrawStage.clear();
             this._afterCameraDrawStage.clear();
             this._beforeCameraUpdateStage.clear();
@@ -32358,12 +32354,9 @@ var BABYLON;
             if (enableAlphaMode) {
                 engine.setAlphaMode(this._effectiveMaterial.alphaMode);
             }
-            // Outline - step 1
-            var savedDepthWrite = engine.getDepthWrite();
-            if (this.renderOutline) {
-                engine.setDepthWrite(false);
-                scene.getOutlineRenderer().render(subMesh, batch);
-                engine.setDepthWrite(savedDepthWrite);
+            for (var _i = 0, _a = scene._beforeRenderingMeshStage; _i < _a.length; _i++) {
+                var step = _a[_i];
+                step.action(this, subMesh, batch);
             }
             var effect;
             if (this._effectiveMaterial.storeEffectOnSubMeshes) {
@@ -32407,19 +32400,9 @@ var BABYLON;
             this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, this._effectiveMaterial);
             // Unbind
             this._effectiveMaterial.unbind();
-            // Outline - step 2
-            if (this.renderOutline && savedDepthWrite) {
-                engine.setDepthWrite(true);
-                engine.setColorWrite(false);
-                scene.getOutlineRenderer().render(subMesh, batch);
-                engine.setColorWrite(true);
-            }
-            // Overlay
-            if (this.renderOverlay) {
-                var currentMode = engine.getAlphaMode();
-                engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
-                scene.getOutlineRenderer().render(subMesh, batch, true);
-                engine.setAlphaMode(currentMode);
+            for (var _b = 0, _c = scene._afterRenderingMeshStage; _b < _c.length; _b++) {
+                var step = _c[_b];
+                step.action(this, subMesh, batch);
             }
             if (this._onAfterRenderObservable) {
                 this._onAfterRenderObservable.notifyObservers(this);
@@ -56134,6 +56117,7 @@ var BABYLON;
             this._limitVelocityGradients = null;
             this._dragGradients = null;
             this._emitRateGradients = null;
+            this._startSizeGradients = null;
             /** Gets or sets a value indicating the damping to apply if the limit velocity factor is reached */
             this.limitVelocityDamping = 0.4;
             /**
@@ -56246,6 +56230,14 @@ var BABYLON;
             return this._velocityGradients;
         };
         /**
+         * Gets the current list of start size gradients.
+         * You must use addStartSizeGradient and removeStartSizeGradient to udpate this list
+         * @returns the list of start size gradients
+         */
+        BaseParticleSystem.prototype.getStartSizeGradients = function () {
+            return this._startSizeGradients;
+        };
+        /**
          * Gets the current list of emit rate gradients.
          * You must use addEmitRateGradient and removeEmitRateGradient to udpate this list
          * @returns the list of emit rate gradients
@@ -56554,6 +56546,10 @@ var BABYLON;
             _this._currentEmitRate1 = 0;
             /** @hidden */
             _this._currentEmitRate2 = 0;
+            /** @hidden */
+            _this._currentStartSize1 = 0;
+            /** @hidden */
+            _this._currentStartSize2 = 0;
             // start of sub system methods
             /**
              * "Recycles" one of the particle by copying it back to the "stock" of particles and removing it from the active list.
@@ -56964,6 +56960,37 @@ var BABYLON;
             return this;
         };
         /**
+         * Adds a new start size gradient (please note that this will only work if you set the targetStopDuration property)
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size value to affect to the specified gradient
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        ParticleSystem.prototype.addStartSizeGradient = function (gradient, factor, factor2) {
+            if (!this._startSizeGradients) {
+                this._startSizeGradients = [];
+            }
+            this._addFactorGradient(this._startSizeGradients, gradient, factor, factor2);
+            if (!this._currentStartSizeGradient) {
+                this._currentStartSizeGradient = this._startSizeGradients[0];
+                this._currentStartSize1 = this._currentStartSizeGradient.getFactor();
+                this._currentStartSize2 = this._currentStartSize1;
+            }
+            if (this._startSizeGradients.length === 2) {
+                this._currentStartSize2 = this._startSizeGradients[1].getFactor();
+            }
+            return this;
+        };
+        /**
+         * Remove a specific start size gradient
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        ParticleSystem.prototype.removeStartSizeGradient = function (gradient) {
+            this._removeFactorGradient(this._emitRateGradients, gradient);
+            return this;
+        };
+        /**
          * Adds a new color gradient
          * @param gradient defines the gradient to use (between 0 and 1)
          * @param color defines the color to affect to the specified gradient
@@ -57223,6 +57250,7 @@ var BABYLON;
         };
         // End of sub system methods
         ParticleSystem.prototype._update = function (newParticles) {
+            var _this = this;
             // Update current
             this._alive = this._particles.length > 0;
             if (this.emitter.position) {
@@ -57300,6 +57328,19 @@ var BABYLON;
                 }
                 // Size and scale
                 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
+                if (this_1._startSizeGradients && this_1._startSizeGradients[0]) {
+                    var ratio = this_1._actualFrame / this_1.targetStopDuration;
+                    BABYLON.Tools.GetCurrentGradient(ratio, this_1._startSizeGradients, function (currentGradient, nextGradient, scale) {
+                        if (currentGradient !== _this._currentStartSizeGradient) {
+                            _this._currentStartSize1 = _this._currentStartSize2;
+                            _this._currentStartSize2 = nextGradient.getFactor();
+                            _this._currentStartSizeGradient = currentGradient;
+                        }
+                        var value = BABYLON.Scalar.Lerp(_this._currentStartSize1, _this._currentStartSize2, scale);
+                        particle.scale.scaleInPlace(value);
+                    });
+                }
                 // Angle
                 if (!this_1._angularSpeedGradients || this_1._angularSpeedGradients.length === 0) {
                     particle.angularSpeed = BABYLON.Scalar.RandomRange(this_1.minAngularSpeed, this_1.maxAngularSpeed);
@@ -57863,11 +57904,26 @@ var BABYLON;
                     serializationObject.emitRateGradients.push(serializedGradient);
                 }
             }
+            var startSizeGradients = particleSystem.getStartSizeGradients();
+            if (startSizeGradients) {
+                serializationObject.startSizeGradients = [];
+                for (var _f = 0, startSizeGradients_1 = startSizeGradients; _f < startSizeGradients_1.length; _f++) {
+                    var startSizeGradient = startSizeGradients_1[_f];
+                    var serializedGradient = {
+                        gradient: startSizeGradient.gradient,
+                        factor1: startSizeGradient.factor1
+                    };
+                    if (startSizeGradient.factor2 !== undefined) {
+                        serializedGradient.factor2 = startSizeGradient.factor2;
+                    }
+                    serializationObject.startSizeGradients.push(serializedGradient);
+                }
+            }
             var limitVelocityGradients = particleSystem.getLimitVelocityGradients();
             if (limitVelocityGradients) {
                 serializationObject.limitVelocityGradients = [];
-                for (var _f = 0, limitVelocityGradients_1 = limitVelocityGradients; _f < limitVelocityGradients_1.length; _f++) {
-                    var limitVelocityGradient = limitVelocityGradients_1[_f];
+                for (var _g = 0, limitVelocityGradients_1 = limitVelocityGradients; _g < limitVelocityGradients_1.length; _g++) {
+                    var limitVelocityGradient = limitVelocityGradients_1[_g];
                     var serializedGradient = {
                         gradient: limitVelocityGradient.gradient,
                         factor1: limitVelocityGradient.factor1
@@ -57988,9 +58044,15 @@ var BABYLON;
                     particleSystem.addEmitRateGradient(emitRateGradient.gradient, emitRateGradient.factor1 !== undefined ? emitRateGradient.factor1 : emitRateGradient.factor, emitRateGradient.factor2);
                 }
             }
+            if (parsedParticleSystem.startSizeGradients) {
+                for (var _m = 0, _o = parsedParticleSystem.startSizeGradients; _m < _o.length; _m++) {
+                    var startSizeGradient = _o[_m];
+                    particleSystem.addStartSizeGradient(startSizeGradient.gradient, startSizeGradient.factor1 !== undefined ? startSizeGradient.factor1 : startSizeGradient.factor, startSizeGradient.factor2);
+                }
+            }
             if (parsedParticleSystem.limitVelocityGradients) {
-                for (var _m = 0, _o = parsedParticleSystem.limitVelocityGradients; _m < _o.length; _m++) {
-                    var limitVelocityGradient = _o[_m];
+                for (var _p = 0, _q = parsedParticleSystem.limitVelocityGradients; _p < _q.length; _p++) {
+                    var limitVelocityGradient = _q[_p];
                     particleSystem.addLimitVelocityGradient(limitVelocityGradient.gradient, limitVelocityGradient.factor1 !== undefined ? limitVelocityGradient.factor1 : limitVelocityGradient.factor, limitVelocityGradient.factor2);
                 }
                 particleSystem.limitVelocityDamping = parsedParticleSystem.limitVelocityDamping;
@@ -61770,6 +61832,26 @@ var BABYLON;
             // Do nothing as emit rate is not supported by GPUParticleSystem
             return this;
         };
+        /**
+         * Not supported by GPUParticleSystem
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size value to affect to the specified gradient
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        GPUParticleSystem.prototype.addStartSizeGradient = function (gradient, factor, factor2) {
+            // Do nothing as start size is not supported by GPUParticleSystem
+            return this;
+        };
+        /**
+         * Not supported by GPUParticleSystem
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        GPUParticleSystem.prototype.removeStartSizeGradient = function (gradient) {
+            // Do nothing as start size is not supported by GPUParticleSystem
+            return this;
+        };
         GPUParticleSystem.prototype._reset = function () {
             this._releaseBuffers();
         };
@@ -71291,7 +71373,7 @@ var BABYLON;
                 }
                 else {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.importMeshAsync(meshNames, scene, data, rootUrl, progressHandler).then(function (result) {
+                    asyncedPlugin.importMeshAsync(meshNames, scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function (result) {
                         scene.loadingPluginName = plugin.name;
                         successHandler(result.meshes, result.particleSystems, result.skeletons, result.animationGroups);
                     }).catch(function (error) {
@@ -71449,7 +71531,7 @@ var BABYLON;
                 }
                 else {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.loadAsync(scene, data, rootUrl, progressHandler).then(function () {
+                    asyncedPlugin.loadAsync(scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function () {
                         scene.loadingPluginName = plugin.name;
                         successHandler();
                     }).catch(function (error) {
@@ -71562,7 +71644,7 @@ var BABYLON;
                 }
                 else if (plugin.loadAssetContainerAsync) {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.loadAssetContainerAsync(scene, data, rootUrl, progressHandler).then(function (assetContainer) {
+                    asyncedPlugin.loadAssetContainerAsync(scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function (assetContainer) {
                         scene.loadingPluginName = plugin.name;
                         successHandler(assetContainer);
                     }).catch(function (error) {
@@ -89304,13 +89386,19 @@ var BABYLON;
                 this.world.addConstraint(constraint);
             }
             else {
-                impostorJoint.mainImpostor.registerAfterPhysicsStep(function () {
+                impostorJoint.joint.jointData.forceApplicationCallback = impostorJoint.joint.jointData.forceApplicationCallback || function () {
                     constraint.applyForce();
-                });
+                };
+                impostorJoint.mainImpostor.registerAfterPhysicsStep(impostorJoint.joint.jointData.forceApplicationCallback);
             }
         };
         CannonJSPlugin.prototype.removeJoint = function (impostorJoint) {
-            this.world.removeConstraint(impostorJoint.joint.physicsJoint);
+            if (impostorJoint.joint.type !== BABYLON.PhysicsJoint.SpringJoint) {
+                this.world.removeConstraint(impostorJoint.joint.physicsJoint);
+            }
+            else {
+                impostorJoint.mainImpostor.unregisterAfterPhysicsStep(impostorJoint.joint.jointData.forceApplicationCallback);
+            }
         };
         CannonJSPlugin.prototype._addMaterial = function (name, friction, restitution) {
             var index;
@@ -100285,16 +100373,97 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * Gets the outline renderer associated with the scene
+     * @returns a OutlineRenderer
+     */
+    BABYLON.Scene.prototype.getOutlineRenderer = function () {
+        if (!this._outlineRenderer) {
+            this._outlineRenderer = new OutlineRenderer(this);
+        }
+        return this._outlineRenderer;
+    };
+    Object.defineProperty(BABYLON.AbstractMesh.prototype, "renderOutline", {
+        get: function () {
+            return this._renderOutline;
+        },
+        set: function (value) {
+            if (value) {
+                // Lazy Load the component.
+                this.getScene().getOutlineRenderer();
+            }
+            this._renderOutline = value;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(BABYLON.AbstractMesh.prototype, "renderOverlay", {
+        get: function () {
+            return this._renderOverlay;
+        },
+        set: function (value) {
+            if (value) {
+                // Lazy Load the component.
+                this.getScene().getOutlineRenderer();
+            }
+            this._renderOverlay = value;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    /**
+     * This class is responsible to draw bothe outline/overlay of meshes.
+     * It should not be used directly but through the available method on mesh.
+     */
     var OutlineRenderer = /** @class */ (function () {
+        /**
+         * Instantiates a new outline renderer. (There could be only one per scene).
+         * @param scene Defines the scene it belongs to
+         */
         function OutlineRenderer(scene) {
+            /**
+             * The name of the component. Each component must have a unique name.
+             */
+            this.name = BABYLON.SceneComponentConstants.NAME_OUTLINERENDERER;
+            /**
+             * Defines a zOffset to prevent zFighting between the overlay and the mesh.
+             */
             this.zOffset = 1;
-            this._scene = scene;
+            this.scene = scene;
+            this._engine = scene.getEngine();
+            this.scene._addComponent(this);
         }
+        /**
+         * Register the component to one instance of a scene.
+         */
+        OutlineRenderer.prototype.register = function () {
+            this.scene._beforeRenderingMeshStage.registerStep(BABYLON.SceneComponentConstants.STEP_BEFORERENDERINGMESH_OUTLINE, this, this._beforeRenderingMesh);
+            this.scene._afterRenderingMeshStage.registerStep(BABYLON.SceneComponentConstants.STEP_AFTERRENDERINGMESH_OUTLINE, this, this._afterRenderingMesh);
+        };
+        /**
+         * Rebuilds the elements related to this component in case of
+         * context lost for instance.
+         */
+        OutlineRenderer.prototype.rebuild = function () {
+            // Nothing to do here.
+        };
+        /**
+         * Disposes the component and the associated ressources.
+         */
+        OutlineRenderer.prototype.dispose = function () {
+            // Nothing to do here.
+        };
+        /**
+         * Renders the outline in the canvas.
+         * @param subMesh Defines the sumesh to render
+         * @param batch Defines the batch of meshes in case of instances
+         * @param useOverlay Defines if the rendering is for the overlay or the outline
+         */
         OutlineRenderer.prototype.render = function (subMesh, batch, useOverlay) {
             var _this = this;
             if (useOverlay === void 0) { useOverlay = false; }
-            var scene = this._scene;
-            var engine = this._scene.getEngine();
+            var scene = this.scene;
+            var engine = scene.getEngine();
             var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
             if (!this.isReady(subMesh, hardwareInstancedRendering)) {
                 return;
@@ -100329,6 +100498,13 @@ var BABYLON;
             mesh._processRendering(subMesh, this._effect, BABYLON.Material.TriangleFillMode, batch, hardwareInstancedRendering, function (isInstance, world) { _this._effect.setMatrix("world", world); });
             engine.setZOffset(0);
         };
+        /**
+         * Returns whether or not the outline renderer is ready for a given submesh.
+         * All the dependencies e.g. submeshes, texture, effect... mus be ready
+         * @param subMesh Defines the submesh to check readyness for
+         * @param useInstances Defines wheter wee are trying to render instances or not
+         * @returns true if ready otherwise false
+         */
         OutlineRenderer.prototype.isReady = function (subMesh, useInstances) {
             var defines = [];
             var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
@@ -100378,10 +100554,35 @@ var BABYLON;
             var join = defines.join("\n");
             if (this._cachedDefines !== join) {
                 this._cachedDefines = join;
-                this._effect = this._scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"], ["diffuseSampler"], join);
+                this._effect = this.scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"], ["diffuseSampler"], join);
             }
             return this._effect.isReady();
         };
+        OutlineRenderer.prototype._beforeRenderingMesh = function (mesh, subMesh, batch) {
+            // Outline - step 1
+            this._savedDepthWrite = this._engine.getDepthWrite();
+            if (mesh.renderOutline) {
+                this._engine.setDepthWrite(false);
+                this.render(subMesh, batch);
+                this._engine.setDepthWrite(this._savedDepthWrite);
+            }
+        };
+        OutlineRenderer.prototype._afterRenderingMesh = function (mesh, subMesh, batch) {
+            // Outline - step 2
+            if (mesh.renderOutline && this._savedDepthWrite) {
+                this._engine.setDepthWrite(true);
+                this._engine.setColorWrite(false);
+                this.render(subMesh, batch);
+                this._engine.setColorWrite(true);
+            }
+            // Overlay
+            if (mesh.renderOverlay) {
+                var currentMode = this._engine.getAlphaMode();
+                this._engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
+                this.render(subMesh, batch, true);
+                this._engine.setAlphaMode(currentMode);
+            }
+        };
         return OutlineRenderer;
     }());
     BABYLON.OutlineRenderer = OutlineRenderer;

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/babylon.worker.js


+ 254 - 53
dist/preview release/es6.js

@@ -19614,20 +19614,10 @@ var BABYLON;
              */
             _this.renderingGroupId = 0;
             _this._receiveShadows = false;
-            /**
-             * Gets or sets a boolean indicating if the outline must be rendered as well
-             * @see https://www.babylonjs-playground.com/#10WJ5S#3
-             */
-            _this.renderOutline = false;
             /** Defines color to use when rendering outline */
             _this.outlineColor = BABYLON.Color3.Red();
             /** Define width to use when rendering outline */
             _this.outlineWidth = 0.02;
-            /**
-             * Gets or sets a boolean indicating if the overlay must be rendered as well
-             * @see https://www.babylonjs-playground.com/#10WJ5S#2
-             */
-            _this.renderOverlay = false;
             /** Defines color to use when rendering overlay */
             _this.overlayColor = BABYLON.Color3.Red();
             /** Defines alpha to use when rendering overlay */
@@ -23703,6 +23693,7 @@ var BABYLON;
         SceneComponentConstants.NAME_DEPTHRENDERER = "DepthRenderer";
         SceneComponentConstants.NAME_POSTPROCESSRENDERPIPELINEMANAGER = "PostProcessRenderPipelineManager";
         SceneComponentConstants.NAME_SPRITE = "Sprite";
+        SceneComponentConstants.NAME_OUTLINERENDERER = "Outline";
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
@@ -23710,6 +23701,8 @@ var BABYLON;
         SceneComponentConstants.STEP_CAMERADRAWRENDERTARGET_EFFECTLAYER = 1;
         SceneComponentConstants.STEP_BEFORECAMERADRAW_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFORECAMERADRAW_LAYER = 1;
+        SceneComponentConstants.STEP_BEFORERENDERINGMESH_OUTLINE = 0;
+        SceneComponentConstants.STEP_AFTERRENDERINGMESH_OUTLINE = 0;
         SceneComponentConstants.STEP_AFTERRENDERINGGROUPDRAW_EFFECTLAYER_DRAW = 0;
         SceneComponentConstants.STEP_BEFORECAMERAUPDATE_SIMPLIFICATIONQUEUE = 0;
         SceneComponentConstants.STEP_BEFORECAMERAUPDATE_GAMEPAD = 1;
@@ -24453,11 +24446,22 @@ var BABYLON;
              */
             _this._beforeCameraDrawStage = BABYLON.Stage.Create();
             /**
+             * @hidden
              * Defines the actions happening just before a rendering group is drawing.
              */
             _this._beforeRenderingGroupDrawStage = BABYLON.Stage.Create();
             /**
              * @hidden
+             * Defines the actions happening just before a mesh is drawing.
+             */
+            _this._beforeRenderingMeshStage = BABYLON.Stage.Create();
+            /**
+             * @hidden
+             * Defines the actions happening just after a mesh has been drawn.
+             */
+            _this._afterRenderingMeshStage = BABYLON.Stage.Create();
+            /**
+             * @hidden
              * Defines the actions happening just after a rendering group has been drawn.
              */
             _this._afterRenderingGroupDrawStage = BABYLON.Stage.Create();
@@ -24499,9 +24503,6 @@ var BABYLON;
             if (BABYLON.PostProcessManager) {
                 _this.postProcessManager = new BABYLON.PostProcessManager(_this);
             }
-            if (BABYLON.OutlineRenderer) {
-                _this._outlineRenderer = new BABYLON.OutlineRenderer(_this);
-            }
             if (BABYLON.Tools.IsWindowObjectExist()) {
                 _this.attachControl();
             }
@@ -25018,13 +25019,6 @@ var BABYLON;
             return this._cachedEffect !== effect || this._cachedMaterial !== material || this._cachedVisibility !== visibility;
         };
         /**
-         * Gets the outline renderer associated with the scene
-         * @returns a OutlineRenderer
-         */
-        Scene.prototype.getOutlineRenderer = function () {
-            return this._outlineRenderer;
-        };
-        /**
          * Gets the engine associated with the scene
          * @returns an Engine
          */
@@ -28092,6 +28086,8 @@ var BABYLON;
             this._cameraDrawRenderTargetStage.clear();
             this._beforeCameraDrawStage.clear();
             this._beforeRenderingGroupDrawStage.clear();
+            this._beforeRenderingMeshStage.clear();
+            this._afterRenderingMeshStage.clear();
             this._afterRenderingGroupDrawStage.clear();
             this._afterCameraDrawStage.clear();
             this._beforeCameraUpdateStage.clear();
@@ -32358,12 +32354,9 @@ var BABYLON;
             if (enableAlphaMode) {
                 engine.setAlphaMode(this._effectiveMaterial.alphaMode);
             }
-            // Outline - step 1
-            var savedDepthWrite = engine.getDepthWrite();
-            if (this.renderOutline) {
-                engine.setDepthWrite(false);
-                scene.getOutlineRenderer().render(subMesh, batch);
-                engine.setDepthWrite(savedDepthWrite);
+            for (var _i = 0, _a = scene._beforeRenderingMeshStage; _i < _a.length; _i++) {
+                var step = _a[_i];
+                step.action(this, subMesh, batch);
             }
             var effect;
             if (this._effectiveMaterial.storeEffectOnSubMeshes) {
@@ -32407,19 +32400,9 @@ var BABYLON;
             this._processRendering(subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, this._effectiveMaterial);
             // Unbind
             this._effectiveMaterial.unbind();
-            // Outline - step 2
-            if (this.renderOutline && savedDepthWrite) {
-                engine.setDepthWrite(true);
-                engine.setColorWrite(false);
-                scene.getOutlineRenderer().render(subMesh, batch);
-                engine.setColorWrite(true);
-            }
-            // Overlay
-            if (this.renderOverlay) {
-                var currentMode = engine.getAlphaMode();
-                engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
-                scene.getOutlineRenderer().render(subMesh, batch, true);
-                engine.setAlphaMode(currentMode);
+            for (var _b = 0, _c = scene._afterRenderingMeshStage; _b < _c.length; _b++) {
+                var step = _c[_b];
+                step.action(this, subMesh, batch);
             }
             if (this._onAfterRenderObservable) {
                 this._onAfterRenderObservable.notifyObservers(this);
@@ -56134,6 +56117,7 @@ var BABYLON;
             this._limitVelocityGradients = null;
             this._dragGradients = null;
             this._emitRateGradients = null;
+            this._startSizeGradients = null;
             /** Gets or sets a value indicating the damping to apply if the limit velocity factor is reached */
             this.limitVelocityDamping = 0.4;
             /**
@@ -56246,6 +56230,14 @@ var BABYLON;
             return this._velocityGradients;
         };
         /**
+         * Gets the current list of start size gradients.
+         * You must use addStartSizeGradient and removeStartSizeGradient to udpate this list
+         * @returns the list of start size gradients
+         */
+        BaseParticleSystem.prototype.getStartSizeGradients = function () {
+            return this._startSizeGradients;
+        };
+        /**
          * Gets the current list of emit rate gradients.
          * You must use addEmitRateGradient and removeEmitRateGradient to udpate this list
          * @returns the list of emit rate gradients
@@ -56554,6 +56546,10 @@ var BABYLON;
             _this._currentEmitRate1 = 0;
             /** @hidden */
             _this._currentEmitRate2 = 0;
+            /** @hidden */
+            _this._currentStartSize1 = 0;
+            /** @hidden */
+            _this._currentStartSize2 = 0;
             // start of sub system methods
             /**
              * "Recycles" one of the particle by copying it back to the "stock" of particles and removing it from the active list.
@@ -56964,6 +56960,37 @@ var BABYLON;
             return this;
         };
         /**
+         * Adds a new start size gradient (please note that this will only work if you set the targetStopDuration property)
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size value to affect to the specified gradient
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        ParticleSystem.prototype.addStartSizeGradient = function (gradient, factor, factor2) {
+            if (!this._startSizeGradients) {
+                this._startSizeGradients = [];
+            }
+            this._addFactorGradient(this._startSizeGradients, gradient, factor, factor2);
+            if (!this._currentStartSizeGradient) {
+                this._currentStartSizeGradient = this._startSizeGradients[0];
+                this._currentStartSize1 = this._currentStartSizeGradient.getFactor();
+                this._currentStartSize2 = this._currentStartSize1;
+            }
+            if (this._startSizeGradients.length === 2) {
+                this._currentStartSize2 = this._startSizeGradients[1].getFactor();
+            }
+            return this;
+        };
+        /**
+         * Remove a specific start size gradient
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        ParticleSystem.prototype.removeStartSizeGradient = function (gradient) {
+            this._removeFactorGradient(this._emitRateGradients, gradient);
+            return this;
+        };
+        /**
          * Adds a new color gradient
          * @param gradient defines the gradient to use (between 0 and 1)
          * @param color defines the color to affect to the specified gradient
@@ -57223,6 +57250,7 @@ var BABYLON;
         };
         // End of sub system methods
         ParticleSystem.prototype._update = function (newParticles) {
+            var _this = this;
             // Update current
             this._alive = this._particles.length > 0;
             if (this.emitter.position) {
@@ -57300,6 +57328,19 @@ var BABYLON;
                 }
                 // Size and scale
                 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
+                if (this_1._startSizeGradients && this_1._startSizeGradients[0]) {
+                    var ratio = this_1._actualFrame / this_1.targetStopDuration;
+                    BABYLON.Tools.GetCurrentGradient(ratio, this_1._startSizeGradients, function (currentGradient, nextGradient, scale) {
+                        if (currentGradient !== _this._currentStartSizeGradient) {
+                            _this._currentStartSize1 = _this._currentStartSize2;
+                            _this._currentStartSize2 = nextGradient.getFactor();
+                            _this._currentStartSizeGradient = currentGradient;
+                        }
+                        var value = BABYLON.Scalar.Lerp(_this._currentStartSize1, _this._currentStartSize2, scale);
+                        particle.scale.scaleInPlace(value);
+                    });
+                }
                 // Angle
                 if (!this_1._angularSpeedGradients || this_1._angularSpeedGradients.length === 0) {
                     particle.angularSpeed = BABYLON.Scalar.RandomRange(this_1.minAngularSpeed, this_1.maxAngularSpeed);
@@ -57863,11 +57904,26 @@ var BABYLON;
                     serializationObject.emitRateGradients.push(serializedGradient);
                 }
             }
+            var startSizeGradients = particleSystem.getStartSizeGradients();
+            if (startSizeGradients) {
+                serializationObject.startSizeGradients = [];
+                for (var _f = 0, startSizeGradients_1 = startSizeGradients; _f < startSizeGradients_1.length; _f++) {
+                    var startSizeGradient = startSizeGradients_1[_f];
+                    var serializedGradient = {
+                        gradient: startSizeGradient.gradient,
+                        factor1: startSizeGradient.factor1
+                    };
+                    if (startSizeGradient.factor2 !== undefined) {
+                        serializedGradient.factor2 = startSizeGradient.factor2;
+                    }
+                    serializationObject.startSizeGradients.push(serializedGradient);
+                }
+            }
             var limitVelocityGradients = particleSystem.getLimitVelocityGradients();
             if (limitVelocityGradients) {
                 serializationObject.limitVelocityGradients = [];
-                for (var _f = 0, limitVelocityGradients_1 = limitVelocityGradients; _f < limitVelocityGradients_1.length; _f++) {
-                    var limitVelocityGradient = limitVelocityGradients_1[_f];
+                for (var _g = 0, limitVelocityGradients_1 = limitVelocityGradients; _g < limitVelocityGradients_1.length; _g++) {
+                    var limitVelocityGradient = limitVelocityGradients_1[_g];
                     var serializedGradient = {
                         gradient: limitVelocityGradient.gradient,
                         factor1: limitVelocityGradient.factor1
@@ -57988,9 +58044,15 @@ var BABYLON;
                     particleSystem.addEmitRateGradient(emitRateGradient.gradient, emitRateGradient.factor1 !== undefined ? emitRateGradient.factor1 : emitRateGradient.factor, emitRateGradient.factor2);
                 }
             }
+            if (parsedParticleSystem.startSizeGradients) {
+                for (var _m = 0, _o = parsedParticleSystem.startSizeGradients; _m < _o.length; _m++) {
+                    var startSizeGradient = _o[_m];
+                    particleSystem.addStartSizeGradient(startSizeGradient.gradient, startSizeGradient.factor1 !== undefined ? startSizeGradient.factor1 : startSizeGradient.factor, startSizeGradient.factor2);
+                }
+            }
             if (parsedParticleSystem.limitVelocityGradients) {
-                for (var _m = 0, _o = parsedParticleSystem.limitVelocityGradients; _m < _o.length; _m++) {
-                    var limitVelocityGradient = _o[_m];
+                for (var _p = 0, _q = parsedParticleSystem.limitVelocityGradients; _p < _q.length; _p++) {
+                    var limitVelocityGradient = _q[_p];
                     particleSystem.addLimitVelocityGradient(limitVelocityGradient.gradient, limitVelocityGradient.factor1 !== undefined ? limitVelocityGradient.factor1 : limitVelocityGradient.factor, limitVelocityGradient.factor2);
                 }
                 particleSystem.limitVelocityDamping = parsedParticleSystem.limitVelocityDamping;
@@ -61770,6 +61832,26 @@ var BABYLON;
             // Do nothing as emit rate is not supported by GPUParticleSystem
             return this;
         };
+        /**
+         * Not supported by GPUParticleSystem
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size value to affect to the specified gradient
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        GPUParticleSystem.prototype.addStartSizeGradient = function (gradient, factor, factor2) {
+            // Do nothing as start size is not supported by GPUParticleSystem
+            return this;
+        };
+        /**
+         * Not supported by GPUParticleSystem
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        GPUParticleSystem.prototype.removeStartSizeGradient = function (gradient) {
+            // Do nothing as start size is not supported by GPUParticleSystem
+            return this;
+        };
         GPUParticleSystem.prototype._reset = function () {
             this._releaseBuffers();
         };
@@ -71291,7 +71373,7 @@ var BABYLON;
                 }
                 else {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.importMeshAsync(meshNames, scene, data, rootUrl, progressHandler).then(function (result) {
+                    asyncedPlugin.importMeshAsync(meshNames, scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function (result) {
                         scene.loadingPluginName = plugin.name;
                         successHandler(result.meshes, result.particleSystems, result.skeletons, result.animationGroups);
                     }).catch(function (error) {
@@ -71449,7 +71531,7 @@ var BABYLON;
                 }
                 else {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.loadAsync(scene, data, rootUrl, progressHandler).then(function () {
+                    asyncedPlugin.loadAsync(scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function () {
                         scene.loadingPluginName = plugin.name;
                         successHandler();
                     }).catch(function (error) {
@@ -71562,7 +71644,7 @@ var BABYLON;
                 }
                 else if (plugin.loadAssetContainerAsync) {
                     var asyncedPlugin = plugin;
-                    asyncedPlugin.loadAssetContainerAsync(scene, data, rootUrl, progressHandler).then(function (assetContainer) {
+                    asyncedPlugin.loadAssetContainerAsync(scene, data, rootUrl, progressHandler, rootUrl + sceneFilename).then(function (assetContainer) {
                         scene.loadingPluginName = plugin.name;
                         successHandler(assetContainer);
                     }).catch(function (error) {
@@ -89304,13 +89386,19 @@ var BABYLON;
                 this.world.addConstraint(constraint);
             }
             else {
-                impostorJoint.mainImpostor.registerAfterPhysicsStep(function () {
+                impostorJoint.joint.jointData.forceApplicationCallback = impostorJoint.joint.jointData.forceApplicationCallback || function () {
                     constraint.applyForce();
-                });
+                };
+                impostorJoint.mainImpostor.registerAfterPhysicsStep(impostorJoint.joint.jointData.forceApplicationCallback);
             }
         };
         CannonJSPlugin.prototype.removeJoint = function (impostorJoint) {
-            this.world.removeConstraint(impostorJoint.joint.physicsJoint);
+            if (impostorJoint.joint.type !== BABYLON.PhysicsJoint.SpringJoint) {
+                this.world.removeConstraint(impostorJoint.joint.physicsJoint);
+            }
+            else {
+                impostorJoint.mainImpostor.unregisterAfterPhysicsStep(impostorJoint.joint.jointData.forceApplicationCallback);
+            }
         };
         CannonJSPlugin.prototype._addMaterial = function (name, friction, restitution) {
             var index;
@@ -100285,16 +100373,97 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    /**
+     * Gets the outline renderer associated with the scene
+     * @returns a OutlineRenderer
+     */
+    BABYLON.Scene.prototype.getOutlineRenderer = function () {
+        if (!this._outlineRenderer) {
+            this._outlineRenderer = new OutlineRenderer(this);
+        }
+        return this._outlineRenderer;
+    };
+    Object.defineProperty(BABYLON.AbstractMesh.prototype, "renderOutline", {
+        get: function () {
+            return this._renderOutline;
+        },
+        set: function (value) {
+            if (value) {
+                // Lazy Load the component.
+                this.getScene().getOutlineRenderer();
+            }
+            this._renderOutline = value;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(BABYLON.AbstractMesh.prototype, "renderOverlay", {
+        get: function () {
+            return this._renderOverlay;
+        },
+        set: function (value) {
+            if (value) {
+                // Lazy Load the component.
+                this.getScene().getOutlineRenderer();
+            }
+            this._renderOverlay = value;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    /**
+     * This class is responsible to draw bothe outline/overlay of meshes.
+     * It should not be used directly but through the available method on mesh.
+     */
     var OutlineRenderer = /** @class */ (function () {
+        /**
+         * Instantiates a new outline renderer. (There could be only one per scene).
+         * @param scene Defines the scene it belongs to
+         */
         function OutlineRenderer(scene) {
+            /**
+             * The name of the component. Each component must have a unique name.
+             */
+            this.name = BABYLON.SceneComponentConstants.NAME_OUTLINERENDERER;
+            /**
+             * Defines a zOffset to prevent zFighting between the overlay and the mesh.
+             */
             this.zOffset = 1;
-            this._scene = scene;
+            this.scene = scene;
+            this._engine = scene.getEngine();
+            this.scene._addComponent(this);
         }
+        /**
+         * Register the component to one instance of a scene.
+         */
+        OutlineRenderer.prototype.register = function () {
+            this.scene._beforeRenderingMeshStage.registerStep(BABYLON.SceneComponentConstants.STEP_BEFORERENDERINGMESH_OUTLINE, this, this._beforeRenderingMesh);
+            this.scene._afterRenderingMeshStage.registerStep(BABYLON.SceneComponentConstants.STEP_AFTERRENDERINGMESH_OUTLINE, this, this._afterRenderingMesh);
+        };
+        /**
+         * Rebuilds the elements related to this component in case of
+         * context lost for instance.
+         */
+        OutlineRenderer.prototype.rebuild = function () {
+            // Nothing to do here.
+        };
+        /**
+         * Disposes the component and the associated ressources.
+         */
+        OutlineRenderer.prototype.dispose = function () {
+            // Nothing to do here.
+        };
+        /**
+         * Renders the outline in the canvas.
+         * @param subMesh Defines the sumesh to render
+         * @param batch Defines the batch of meshes in case of instances
+         * @param useOverlay Defines if the rendering is for the overlay or the outline
+         */
         OutlineRenderer.prototype.render = function (subMesh, batch, useOverlay) {
             var _this = this;
             if (useOverlay === void 0) { useOverlay = false; }
-            var scene = this._scene;
-            var engine = this._scene.getEngine();
+            var scene = this.scene;
+            var engine = scene.getEngine();
             var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
             if (!this.isReady(subMesh, hardwareInstancedRendering)) {
                 return;
@@ -100329,6 +100498,13 @@ var BABYLON;
             mesh._processRendering(subMesh, this._effect, BABYLON.Material.TriangleFillMode, batch, hardwareInstancedRendering, function (isInstance, world) { _this._effect.setMatrix("world", world); });
             engine.setZOffset(0);
         };
+        /**
+         * Returns whether or not the outline renderer is ready for a given submesh.
+         * All the dependencies e.g. submeshes, texture, effect... mus be ready
+         * @param subMesh Defines the submesh to check readyness for
+         * @param useInstances Defines wheter wee are trying to render instances or not
+         * @returns true if ready otherwise false
+         */
         OutlineRenderer.prototype.isReady = function (subMesh, useInstances) {
             var defines = [];
             var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
@@ -100378,10 +100554,35 @@ var BABYLON;
             var join = defines.join("\n");
             if (this._cachedDefines !== join) {
                 this._cachedDefines = join;
-                this._effect = this._scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"], ["diffuseSampler"], join);
+                this._effect = this.scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"], ["diffuseSampler"], join);
             }
             return this._effect.isReady();
         };
+        OutlineRenderer.prototype._beforeRenderingMesh = function (mesh, subMesh, batch) {
+            // Outline - step 1
+            this._savedDepthWrite = this._engine.getDepthWrite();
+            if (mesh.renderOutline) {
+                this._engine.setDepthWrite(false);
+                this.render(subMesh, batch);
+                this._engine.setDepthWrite(this._savedDepthWrite);
+            }
+        };
+        OutlineRenderer.prototype._afterRenderingMesh = function (mesh, subMesh, batch) {
+            // Outline - step 2
+            if (mesh.renderOutline && this._savedDepthWrite) {
+                this._engine.setDepthWrite(true);
+                this._engine.setColorWrite(false);
+                this.render(subMesh, batch);
+                this._engine.setColorWrite(true);
+            }
+            // Overlay
+            if (mesh.renderOverlay) {
+                var currentMode = this._engine.getAlphaMode();
+                this._engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
+                this.render(subMesh, batch, true);
+                this._engine.setAlphaMode(currentMode);
+            }
+        };
         return OutlineRenderer;
     }());
     BABYLON.OutlineRenderer = OutlineRenderer;

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js.map


+ 2 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -819,8 +819,10 @@ declare module INSPECTOR {
         activateNode(item: TreeItem): void;
     }
     class DDSPreview {
+        canvas: HTMLCanvasElement | null;
         constructor(AdapterItem: TextureAdapter);
         insertPreview(AdapterItem: TextureAdapter): void;
+        dispose(): void;
     }
 }
 declare module INSPECTOR {

+ 4 - 0
dist/preview release/inspector/babylon.inspector.module.d.ts

@@ -1061,8 +1061,10 @@ declare module 'babylonjs-inspector/tabs/TextureTab' {
         activateNode(item: TreeItem): void;
     }
     class DDSPreview {
+        canvas: HTMLCanvasElement | null;
         constructor(AdapterItem: TextureAdapter);
         insertPreview(AdapterItem: TextureAdapter): void;
+        dispose(): void;
     }
     export {};
 }
@@ -2157,8 +2159,10 @@ declare module INSPECTOR {
         activateNode(item: TreeItem): void;
     }
     class DDSPreview {
+        canvas: HTMLCanvasElement | null;
         constructor(AdapterItem: TextureAdapter);
         insertPreview(AdapterItem: TextureAdapter): void;
+        dispose(): void;
     }
 }
 declare module INSPECTOR {

+ 8 - 5
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -76,13 +76,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -262,9 +262,10 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -276,18 +277,20 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         /**
          * Load into an asset container.
          * @param scene The scene to load into
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data

+ 9 - 6
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -372,14 +372,15 @@ var BABYLON;
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress);
+                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress, fullName);
             });
         };
         /**
@@ -388,14 +389,15 @@ var BABYLON;
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress);
+                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress, fullName);
             });
         };
         /**
@@ -404,14 +406,15 @@ var BABYLON;
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress).then(function (result) {
+                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress, fullName).then(function (result) {
                     var container = new BABYLON.AssetContainer(scene);
                     Array.prototype.push.apply(container.meshes, result.meshes);
                     Array.prototype.push.apply(container.particleSystems, result.particleSystems);

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 11 - 7
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -76,13 +76,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -262,9 +262,10 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -276,18 +277,20 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         /**
          * Load into an asset container.
          * @param scene The scene to load into
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -568,6 +571,7 @@ declare module BABYLON.GLTF2 {
         private _state;
         private _extensions;
         private _rootUrl;
+        private _fullName;
         private _rootBabylonMesh;
         private _defaultBabylonMaterialData;
         private _progressCallback?;
@@ -596,14 +600,14 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
         /** @hidden */
-        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         private _loadAsync;
         private _loadData;
         private _setupData;

+ 14 - 9
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -372,14 +372,15 @@ var BABYLON;
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress);
+                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress, fullName);
             });
         };
         /**
@@ -388,14 +389,15 @@ var BABYLON;
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress);
+                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress, fullName);
             });
         };
         /**
@@ -404,14 +406,15 @@ var BABYLON;
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress).then(function (result) {
+                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress, fullName).then(function (result) {
                     var container = new BABYLON.AssetContainer(scene);
                     Array.prototype.push.apply(container.meshes, result.meshes);
                     Array.prototype.push.apply(container.particleSystems, result.particleSystems);
@@ -812,11 +815,12 @@ var BABYLON;
                 this._parent._clear();
             };
             /** @hidden */
-            GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+            GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
                 var _this = this;
                 return Promise.resolve().then(function () {
                     _this.babylonScene = scene;
                     _this._rootUrl = rootUrl;
+                    _this._fullName = fullName || "" + Date.now();
                     _this._progressCallback = onProgress;
                     _this._loadData(data);
                     var nodes = null;
@@ -850,11 +854,12 @@ var BABYLON;
                 });
             };
             /** @hidden */
-            GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+            GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
                 var _this = this;
                 return Promise.resolve().then(function () {
                     _this.babylonScene = scene;
                     _this._rootUrl = rootUrl;
+                    _this._fullName = fullName || "" + Date.now();
                     _this._progressCallback = onProgress;
                     _this._loadData(data);
                     return _this._loadAsync(null, function () { return undefined; });
@@ -2106,7 +2111,7 @@ var BABYLON;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
                 promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
-                    var dataUrl = "data:" + _this._rootUrl + (image.uri || "image" + image.index);
+                    var dataUrl = "data:" + _this._fullName + (image.uri || "image" + image.index);
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 11 - 7
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -76,13 +76,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -262,9 +262,10 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -276,18 +277,20 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         /**
          * Load into an asset container.
          * @param scene The scene to load into
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -1130,6 +1133,7 @@ declare module BABYLON.GLTF2 {
         private _state;
         private _extensions;
         private _rootUrl;
+        private _fullName;
         private _rootBabylonMesh;
         private _defaultBabylonMaterialData;
         private _progressCallback?;
@@ -1158,14 +1162,14 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
         /** @hidden */
-        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         private _loadAsync;
         private _loadData;
         private _setupData;

+ 14 - 9
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -372,14 +372,15 @@ var BABYLON;
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress);
+                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress, fullName);
             });
         };
         /**
@@ -388,14 +389,15 @@ var BABYLON;
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress);
+                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress, fullName);
             });
         };
         /**
@@ -404,14 +406,15 @@ var BABYLON;
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress).then(function (result) {
+                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress, fullName).then(function (result) {
                     var container = new BABYLON.AssetContainer(scene);
                     Array.prototype.push.apply(container.meshes, result.meshes);
                     Array.prototype.push.apply(container.particleSystems, result.particleSystems);
@@ -3019,11 +3022,12 @@ var BABYLON;
                 this._parent._clear();
             };
             /** @hidden */
-            GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+            GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
                 var _this = this;
                 return Promise.resolve().then(function () {
                     _this.babylonScene = scene;
                     _this._rootUrl = rootUrl;
+                    _this._fullName = fullName || "" + Date.now();
                     _this._progressCallback = onProgress;
                     _this._loadData(data);
                     var nodes = null;
@@ -3057,11 +3061,12 @@ var BABYLON;
                 });
             };
             /** @hidden */
-            GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+            GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
                 var _this = this;
                 return Promise.resolve().then(function () {
                     _this.babylonScene = scene;
                     _this._rootUrl = rootUrl;
+                    _this._fullName = fullName || "" + Date.now();
                     _this._progressCallback = onProgress;
                     _this._loadData(data);
                     return _this._loadAsync(null, function () { return undefined; });
@@ -4313,7 +4318,7 @@ var BABYLON;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
                 promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
-                    var dataUrl = "data:" + _this._rootUrl + (image.uri || "image" + image.index);
+                    var dataUrl = "data:" + _this._fullName + (image.uri || "image" + image.index);
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 31 - 3
dist/preview release/loaders/babylon.objFileLoader.d.ts

@@ -58,14 +58,42 @@ declare module BABYLON {
          * @private
          */
         private _loadMTL;
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        /**
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
-        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
+        /**
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        /**
+         * Load into an asset container.
+         * @param scene The scene to load into
+         * @param data The data to import
+         * @param rootUrl The root url for scene and resources
+         * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
+         * @returns The loaded asset container
+         */
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.

+ 31 - 3
dist/preview release/loaders/babylon.objFileLoader.js

@@ -251,7 +251,17 @@ var BABYLON;
             // Loads through the babylon tools to allow fileInput search.
             BABYLON.Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, false, function () { console.warn("Error - Unable to load " + pathOfFile); });
         };
-        OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+        /**
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
+        OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
             //get the meshes from OBJ file
             return this._parseSolid(meshesNames, scene, data, rootUrl).then(function (meshes) {
                 return {
@@ -262,13 +272,31 @@ var BABYLON;
                 };
             });
         };
-        OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+        /**
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
+        OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
             //Get the 3D model
             return this.importMeshAsync(null, scene, data, rootUrl, onProgress).then(function () {
                 // return void
             });
         };
-        OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
+        /**
+         * Load into an asset container.
+         * @param scene The scene to load into
+         * @param data The data to import
+         * @param rootUrl The root url for scene and resources
+         * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
+         * @returns The loaded asset container
+         */
+        OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fullName) {
             return this.importMeshAsync(null, scene, data, rootUrl).then(function (result) {
                 var container = new BABYLON.AssetContainer(scene);
                 result.meshes.forEach(function (mesh) { return container.meshes.push(mesh); });

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 42 - 10
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -76,14 +76,42 @@ declare module BABYLON {
          * @private
          */
         private _loadMTL;
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        /**
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
-        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
+        /**
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        /**
+         * Load into an asset container.
+         * @param scene The scene to load into
+         * @param data The data to import
+         * @param rootUrl The root url for scene and resources
+         * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
+         * @returns The loaded asset container
+         */
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.
@@ -178,13 +206,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -364,9 +392,10 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -378,18 +407,20 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         /**
          * Load into an asset container.
          * @param scene The scene to load into
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -1232,6 +1263,7 @@ declare module BABYLON.GLTF2 {
         private _state;
         private _extensions;
         private _rootUrl;
+        private _fullName;
         private _rootBabylonMesh;
         private _defaultBabylonMaterialData;
         private _progressCallback?;
@@ -1260,14 +1292,14 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
         /** @hidden */
-        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         private _loadAsync;
         private _loadData;
         private _setupData;

+ 45 - 12
dist/preview release/loaders/babylonjs.loaders.js

@@ -450,7 +450,17 @@ var BABYLON;
             // Loads through the babylon tools to allow fileInput search.
             BABYLON.Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, false, function () { console.warn("Error - Unable to load " + pathOfFile); });
         };
-        OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+        /**
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
+        OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
             //get the meshes from OBJ file
             return this._parseSolid(meshesNames, scene, data, rootUrl).then(function (meshes) {
                 return {
@@ -461,13 +471,31 @@ var BABYLON;
                 };
             });
         };
-        OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+        /**
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
+        OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
             //Get the 3D model
             return this.importMeshAsync(null, scene, data, rootUrl, onProgress).then(function () {
                 // return void
             });
         };
-        OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
+        /**
+         * Load into an asset container.
+         * @param scene The scene to load into
+         * @param data The data to import
+         * @param rootUrl The root url for scene and resources
+         * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
+         * @returns The loaded asset container
+         */
+        OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fullName) {
             return this.importMeshAsync(null, scene, data, rootUrl).then(function (result) {
                 var container = new BABYLON.AssetContainer(scene);
                 result.meshes.forEach(function (mesh) { return container.meshes.push(mesh); });
@@ -1427,14 +1455,15 @@ var BABYLON;
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress);
+                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress, fullName);
             });
         };
         /**
@@ -1443,14 +1472,15 @@ var BABYLON;
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress);
+                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress, fullName);
             });
         };
         /**
@@ -1459,14 +1489,15 @@ var BABYLON;
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
+        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fullName) {
             var _this = this;
             return Promise.resolve().then(function () {
                 var loaderData = _this._parse(data);
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress).then(function (result) {
+                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress, fullName).then(function (result) {
                     var container = new BABYLON.AssetContainer(scene);
                     Array.prototype.push.apply(container.meshes, result.meshes);
                     Array.prototype.push.apply(container.particleSystems, result.particleSystems);
@@ -4050,11 +4081,12 @@ var BABYLON;
                 this._parent._clear();
             };
             /** @hidden */
-            GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
+            GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
                 var _this = this;
                 return Promise.resolve().then(function () {
                     _this.babylonScene = scene;
                     _this._rootUrl = rootUrl;
+                    _this._fullName = fullName || "" + Date.now();
                     _this._progressCallback = onProgress;
                     _this._loadData(data);
                     var nodes = null;
@@ -4088,11 +4120,12 @@ var BABYLON;
                 });
             };
             /** @hidden */
-            GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
+            GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
                 var _this = this;
                 return Promise.resolve().then(function () {
                     _this.babylonScene = scene;
                     _this._rootUrl = rootUrl;
+                    _this._fullName = fullName || "" + Date.now();
                     _this._progressCallback = onProgress;
                     _this._loadData(data);
                     return _this._loadAsync(null, function () { return undefined; });
@@ -5344,7 +5377,7 @@ var BABYLON;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
                 promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
-                    var dataUrl = "data:" + _this._rootUrl + (image.uri || "image" + image.index);
+                    var dataUrl = "data:" + _this._fullName + (image.uri || "image" + image.index);
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


+ 42 - 10
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -83,14 +83,42 @@ declare module BABYLON {
          * @private
          */
         private _loadMTL;
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        /**
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
-        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
+        /**
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        /**
+         * Load into an asset container.
+         * @param scene The scene to load into
+         * @param data The data to import
+         * @param rootUrl The root url for scene and resources
+         * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
+         * @returns The loaded asset container
+         */
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.
@@ -185,13 +213,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -371,9 +399,10 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -385,18 +414,20 @@ declare module BABYLON {
          * @param data the glTF data to load
          * @param rootUrl root url to load from
          * @param onProgress event that fires when loading progress has occured
+         * @param fullName Defines the FQDN of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         /**
          * Load into an asset container.
          * @param scene The scene to load into
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
+         * @param fullName Defines the FQDN of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -1239,6 +1270,7 @@ declare module BABYLON.GLTF2 {
         private _state;
         private _extensions;
         private _rootUrl;
+        private _fullName;
         private _rootBabylonMesh;
         private _defaultBabylonMaterialData;
         private _progressCallback?;
@@ -1267,14 +1299,14 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
         /** @hidden */
-        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
         private _loadAsync;
         private _loadData;
         private _setupData;

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


Разлика између датотеке није приказан због своје велике величине
+ 4 - 4
dist/preview release/viewer/babylon.viewer.max.js


+ 2 - 1
dist/preview release/what's new.md

@@ -36,6 +36,8 @@
   - Added support for limit velocty gradients. [Doc](https://doc.babylonjs.com/babylon101/particles#limit-velocity-over-time)
   - Added support for noise textures. [Doc](http://doc.babylonjs.com/babylon101/particles#noise-texture)
   - Added support for emit rate gradients. [Doc](http://doc.babylonjs.com/babylon101/particles#emit-rate-over-time)
+  - Start size gradient support for particles [Doc](http://doc.babylonjs.com/babylon101/particles#start-size-over-time) ([TrevorDev](https://github.com/TrevorDev))
+  - Cylinder particle emitter and constructor in baseParticle [Doc](https://doc.babylonjs.com/babylon101/particles#cylinder-emitter) ([TrevorDev](https://github.com/TrevorDev))
 - Added SceneComponent to help decoupling Scene from its components. ([sebavan](http://www.github.com/sebavan))
 - Added [Environment Texture Tools](https://doc.babylonjs.com/how_to/physically_based_rendering#creating-a-compressed-environment-texture) to reduce the size of the usual .DDS file ([sebavan](http://www.github.com/sebavan))
 - Playground can now be used with TypeScript directly!. [Demo](https://www.babylonjs-playground.com/ts.html) ([Deltakosh](https://github.com/deltakosh), [NasimiAsl](https://github.com/NasimiAsl))
@@ -109,7 +111,6 @@
 - Added EdgesLineRenderer to address [#4919](https://github.com/BabylonJS/Babylon.js/pull/4919) ([barteq100](https://github.com/barteq100))
 - Added ```ambientTextureImpactOnAnalyticalLights``` in PBRMaterial to allow fine grained control of the AmbientTexture on the analytical diffuse light ([sebavan](http://www.github.com/sebavan))
 - BoundingBoxGizmo scalePivot field that can be used to always scale objects from the bottom ([TrevorDev](https://github.com/TrevorDev))
-- Cylinder particle emitter and constructor in baseParticle ([TrevorDev](https://github.com/TrevorDev))
 - Improved _isSyncronized performance and reduced GC in TransformNode.computeWorldMatrix by directly reading property. ([Bolloxim](https://github.com/Bolloxim))
 - Added supports for reflectionMatrix in Skybox Mode Cube Texture allowing offsetting the world center or rotating the matrix ([sebavan](http://www.github.com/sebavan))
 

+ 23 - 2
src/Particles/babylon.IParticleSystem.ts

@@ -107,7 +107,7 @@ module BABYLON {
         /**
          * The maximum number of particles to emit per frame until we reach the activeParticleCount value
          */
-        emitRate: number; 
+        emitRate: number;
         
         /**
          * You can use gravity if you want to give an orientation to your particles.
@@ -396,7 +396,28 @@ module BABYLON {
          * You must use addEmitRateGradient and removeEmitRateGradient to udpate this list
          * @returns the list of emit rate gradients
          */
-        getEmitRateGradients(): Nullable<Array<FactorGradient>>;                    
+        getEmitRateGradients(): Nullable<Array<FactorGradient>>;   
+        
+        /**
+         * Adds a new start size gradient (please note that this will only work if you set the targetStopDuration property)
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size to affect to the specified gradient         
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        addStartSizeGradient(gradient: number, factor: number, factor2?: number): IParticleSystem;
+        /**
+         * Remove a specific start size gradient
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        removeStartSizeGradient(gradient: number): IParticleSystem;    
+        /**
+         * Gets the current list of start size gradients.
+         * You must use addStartSizeGradient and removeStartSizeGradient to udpate this list
+         * @returns the list of start size gradients
+         */
+        getStartSizeGradients(): Nullable<Array<FactorGradient>>;  
         
 
         /**

+ 11 - 1
src/Particles/babylon.baseParticleSystem.ts

@@ -253,6 +253,7 @@ module BABYLON {
         protected _limitVelocityGradients: Nullable<Array<FactorGradient>> = null;
         protected _dragGradients: Nullable<Array<FactorGradient>> = null;
         protected _emitRateGradients: Nullable<Array<FactorGradient>> = null;
+        protected _startSizeGradients: Nullable<Array<FactorGradient>> = null;
 
         /**
          * Gets the current list of drag gradients.
@@ -321,13 +322,22 @@ module BABYLON {
         }         
 
         /**
+         * Gets the current list of start size gradients.
+         * You must use addStartSizeGradient and removeStartSizeGradient to udpate this list
+         * @returns the list of start size gradients
+         */
+        public getStartSizeGradients(): Nullable<Array<FactorGradient>> {
+            return this._startSizeGradients;
+        }
+        
+        /**
          * Gets the current list of emit rate gradients.
          * You must use addEmitRateGradient and removeEmitRateGradient to udpate this list
          * @returns the list of emit rate gradients
          */
         public getEmitRateGradients(): Nullable<Array<FactorGradient>> {
             return this._emitRateGradients;
-        }             
+        }      
 
         /**
          * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.

+ 22 - 0
src/Particles/babylon.gpuParticleSystem.ts

@@ -453,6 +453,28 @@
         } 
 
         /**
+         * Not supported by GPUParticleSystem
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size value to affect to the specified gradient         
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        public addStartSizeGradient(gradient: number, factor: number, factor2?: number): IParticleSystem {
+            // Do nothing as start size is not supported by GPUParticleSystem
+            return this;
+        }
+
+        /**
+         * Not supported by GPUParticleSystem
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        public removeStartSizeGradient(gradient: number): IParticleSystem {
+            // Do nothing as start size is not supported by GPUParticleSystem
+            return this;
+        } 
+
+        /**
          * Instantiates a GPU particle system.
          * Particles are often small sprites used to simulate hard-to-reproduce phenomena like fire, smoke, water, or abstract visual effects like magic glitter and faery dust.
          * @param name The name of the particle system

+ 88 - 4
src/Particles/babylon.particleSystem.ts

@@ -75,7 +75,14 @@
         /** @hidden */
         public _currentEmitRate1 = 0;
         /** @hidden */
-        public _currentEmitRate2 = 0;              
+        public _currentEmitRate2 = 0;   
+        
+        /** @hidden */
+        public _currentStartSizeGradient: Nullable<FactorGradient>;
+        /** @hidden */
+        public _currentStartSize1 = 0;
+        /** @hidden */
+        public _currentStartSize2 = 0;   
 
         // end of sheet animation
 
@@ -532,7 +539,45 @@
             this._removeFactorGradient(this._emitRateGradients, gradient);
 
             return this;
-        }           
+        }    
+        
+        /**
+         * Adds a new start size gradient (please note that this will only work if you set the targetStopDuration property)
+         * @param gradient defines the gradient to use (between 0 and 1)
+         * @param factor defines the start size value to affect to the specified gradient         
+         * @param factor2 defines an additional factor used to define a range ([factor, factor2]) with main value to pick the final value from
+         * @returns the current particle system
+         */
+        public addStartSizeGradient(gradient: number, factor: number, factor2?: number): IParticleSystem {
+            if (!this._startSizeGradients) {
+                this._startSizeGradients = [];
+            }
+
+            this._addFactorGradient(this._startSizeGradients, gradient, factor, factor2);
+
+            if (!this._currentStartSizeGradient) {
+                this._currentStartSizeGradient = this._startSizeGradients[0];
+                this._currentStartSize1 = this._currentStartSizeGradient.getFactor();
+                this._currentStartSize2 = this._currentStartSize1;
+            }
+
+            if (this._startSizeGradients.length === 2) {
+                this._currentStartSize2 = this._startSizeGradients[1].getFactor();
+            }
+
+            return this;
+        }
+
+        /**
+         * Remove a specific start size gradient
+         * @param gradient defines the gradient to remove
+         * @returns the current particle system
+         */
+        public removeStartSizeGradient(gradient: number): IParticleSystem {
+            this._removeFactorGradient(this._emitRateGradients, gradient);
+
+            return this;
+        } 
 
         /**
          * Adds a new color gradient
@@ -961,6 +1006,21 @@
                 }
                 // Size and scale
                 particle.scale.copyFromFloats(Scalar.RandomRange(this.minScaleX, this.maxScaleX), Scalar.RandomRange(this.minScaleY, this.maxScaleY));
+                
+                // Adjust scale by start size
+                if(this._startSizeGradients && this._startSizeGradients[0]){
+                    const ratio = this._actualFrame / this.targetStopDuration;            
+                    Tools.GetCurrentGradient(ratio, this._startSizeGradients, (currentGradient, nextGradient, scale) => {
+                        if (currentGradient !== this._currentStartSizeGradient) {
+                            this._currentStartSize1 = this._currentStartSize2;
+                            this._currentStartSize2 = (<FactorGradient>nextGradient).getFactor();    
+                            this._currentStartSizeGradient = (<FactorGradient>currentGradient);
+                        }                                
+                        
+                        var value = Scalar.Lerp(this._currentStartSize1, this._currentStartSize2, scale);
+                        particle.scale.scaleInPlace(value);
+                    });
+                }
 
                 // Angle
                 if (!this._angularSpeedGradients || this._angularSpeedGradients.length === 0) {
@@ -1621,7 +1681,25 @@
 
                     serializationObject.emitRateGradients.push(serializedGradient);
                 }
-            }                
+            } 
+            
+            let startSizeGradients = particleSystem.getStartSizeGradients();
+            if (startSizeGradients) {
+                serializationObject.startSizeGradients = [];
+                for (var startSizeGradient of startSizeGradients) {
+
+                    var serializedGradient: any = {
+                        gradient: startSizeGradient.gradient,
+                        factor1: startSizeGradient.factor1
+                    };
+
+                    if (startSizeGradient.factor2 !== undefined) {
+                        serializedGradient.factor2 = startSizeGradient.factor2;
+                    }
+
+                    serializationObject.startSizeGradients.push(serializedGradient);
+                }
+            } 
 
             let limitVelocityGradients = particleSystem.getLimitVelocityGradients();
             if (limitVelocityGradients) {
@@ -1762,7 +1840,13 @@
                 for (var emitRateGradient of parsedParticleSystem.emitRateGradients) {
                     particleSystem.addEmitRateGradient(emitRateGradient.gradient, emitRateGradient.factor1 !== undefined ?  emitRateGradient.factor1 : emitRateGradient.factor, emitRateGradient.factor2);
                 }
-            }               
+            } 
+            
+            if (parsedParticleSystem.startSizeGradients) {
+                for (var startSizeGradient of parsedParticleSystem.startSizeGradients) {
+                    particleSystem.addStartSizeGradient(startSizeGradient.gradient, startSizeGradient.factor1 !== undefined ?  startSizeGradient.factor1 : startSizeGradient.factor, startSizeGradient.factor2);
+                }
+            }
 
             if (parsedParticleSystem.limitVelocityGradients) {
                 for (var limitVelocityGradient of parsedParticleSystem.limitVelocityGradients) {