Browse Source

Merge pull request #4655 from BabylonJS/particleAsComponent

Removing dependencies to ParticleSystem
David Catuhe 7 years ago
parent
commit
9448ddaa0e
34 changed files with 791 additions and 527 deletions
  1. 2 2
      Tools/Gulp/config.json
  2. 2 2
      Viewer/src/model/viewerModel.ts
  3. 142 95
      dist/preview release/babylon.max.js
  4. 142 95
      dist/preview release/babylon.no-module.max.js
  5. 142 95
      dist/preview release/es6.js
  6. 3 3
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  7. 3 3
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  8. 4 4
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  9. 1 1
      dist/preview release/loaders/babylon.objFileLoader.d.ts
  10. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.d.ts
  11. 6 6
      dist/preview release/loaders/babylonjs.loaders.d.ts
  12. 6 6
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  13. 1 1
      dist/preview release/viewer/babylon.viewer.d.ts
  14. 143 96
      dist/preview release/viewer/babylon.viewer.max.js
  15. 2 2
      dist/preview release/viewer/babylon.viewer.module.d.ts
  16. 1 1
      loaders/src/OBJ/babylon.objFileLoader.ts
  17. 1 1
      loaders/src/STL/babylon.stlFileLoader.ts
  18. 1 1
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  19. 1 1
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  20. 2 2
      loaders/src/glTF/babylon.glTFFileLoader.ts
  21. 0 36
      src/Engine/babylon.engine.ts
  22. 19 14
      src/Layer/babylon.effectLayerSceneComponent.ts
  23. 13 8
      src/Layer/babylon.layerSceneComponent.ts
  24. 13 11
      src/LensFlare/babylon.lensFlareSystemSceneComponent.ts
  25. 8 20
      src/Loading/Plugins/babylon.babylonFileLoader.ts
  26. 6 6
      src/Loading/babylon.sceneLoader.ts
  27. 2 2
      src/Mesh/babylon.mesh.ts
  28. 1 1
      src/Particles/babylon.IParticleSystem.ts
  29. 1 1
      src/Particles/babylon.particleHelper.ts
  30. 70 0
      src/Particles/babylon.particleSystemComponent.ts
  31. 2 2
      src/Tools/babylon.assetsManager.ts
  32. 49 2
      src/babylon.abstractScene.ts
  33. 0 6
      src/babylon.assetContainer.ts
  34. 1 0
      src/babylon.sceneComponent.ts

+ 2 - 2
Tools/Gulp/config.json

@@ -254,10 +254,10 @@
             "files": [
                 "../../src/Particles/babylon.particle.js",
                 "../../src/Particles/babylon.particleSystem.js",
-                "../../src/Particles/EmitterTypes/babylon.IParticleEmitterType.js",
                 "../../src/Particles/EmitterTypes/babylon.boxParticleEmitter.js",
                 "../../src/Particles/EmitterTypes/babylon.coneParticleEmitter.js",
-                "../../src/Particles/EmitterTypes/babylon.sphereParticleEmitter.js"
+                "../../src/Particles/EmitterTypes/babylon.sphereParticleEmitter.js",
+                "../../src/Particles/babylon.particleSystemComponent.js"
             ],
             "dependUpon": [
                 "core"

+ 2 - 2
Viewer/src/model/viewerModel.ts

@@ -1,4 +1,4 @@
-import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, Animatable, AbstractMesh, Tools, Scene, SceneLoader, Observable, SceneLoaderProgressEvent, Tags, ParticleSystem, Skeleton, IDisposable, Nullable, Animation, Quaternion, Material, Vector3, AnimationPropertiesOverride, QuinticEase, SineEase, CircleEase, BackEase, BounceEase, CubicEase, ElasticEase, ExponentialEase, PowerEase, QuadraticEase, QuarticEase, PBRMaterial, MultiMaterial } from "babylonjs";
+import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, Animatable, AbstractMesh, Tools, Scene, SceneLoader, Observable, SceneLoaderProgressEvent, Tags, IParticleSystem, Skeleton, IDisposable, Nullable, Animation, Quaternion, Material, Vector3, AnimationPropertiesOverride, QuinticEase, SineEase, CircleEase, BackEase, BounceEase, CubicEase, ElasticEase, ExponentialEase, PowerEase, QuadraticEase, QuarticEase, PBRMaterial, MultiMaterial } from "babylonjs";
 import { GLTFFileLoader, GLTF2 } from "babylonjs-loaders";
 import { IModelConfiguration } from "../configuration/interfaces/modelConfiguration";
 import { IModelAnimationConfiguration } from "../configuration/interfaces/modelAnimationConfiguration";
@@ -48,7 +48,7 @@ export class ViewerModel implements IDisposable {
     /**
      * ParticleSystems connected to this model
      */
-    public particleSystems: Array<ParticleSystem> = [];
+    public particleSystems: Array<IParticleSystem> = [];
     /**
      * Skeletons defined in this model
      */

+ 142 - 95
dist/preview release/babylon.max.js

@@ -13741,35 +13741,6 @@ var BABYLON;
             return effect;
         };
         /**
-         * Create an effect to use with particle systems.
-         * Please note that some parameters like animation sheets or not being billboard are not supported in this configuration
-         * @param fragmentName defines the base name of the effect (The name of file without .fragment.fx)
-         * @param uniformsNames defines a list of attribute names
-         * @param samplers defines an array of string used to represent textures
-         * @param defines defines the string containing the defines to use to compile the shaders
-         * @param fallbacks defines the list of potential fallbacks to use if shader conmpilation fails
-         * @param onCompiled defines a function to call when the effect creation is successful
-         * @param onError defines a function to call when the effect creation has failed
-         * @returns the new Effect
-         */
-        Engine.prototype.createEffectForParticles = function (fragmentName, uniformsNames, samplers, defines, fallbacks, onCompiled, onError) {
-            if (uniformsNames === void 0) { uniformsNames = []; }
-            if (samplers === void 0) { samplers = []; }
-            if (defines === void 0) { defines = ""; }
-            var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
-            var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
-            if (defines.indexOf(" BILLBOARD") === -1) {
-                defines += "\n#define BILLBOARD\n";
-            }
-            if (samplers.indexOf("diffuseSampler") === -1) {
-                samplers.push("diffuseSampler");
-            }
-            return this.createEffect({
-                vertex: "particles",
-                fragmentElement: fragmentName
-            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
-        };
-        /**
          * Directly creates a webGL program
          * @param vertexCode defines the vertex shader code to use
          * @param fragmentCode defines the fragment shader code to use
@@ -23717,6 +23688,7 @@ var BABYLON;
         SceneComponentConstants.NAME_LAYER = "Layer";
         SceneComponentConstants.NAME_LENSFLARESYSTEM = "LensFlareSystem";
         SceneComponentConstants.NAME_BOUNDINGBOXRENDERER = "BoundingBoxRenderer";
+        SceneComponentConstants.NAME_PARTICLESYSTEM = "ParticleSystem";
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
@@ -23786,7 +23758,7 @@ var BABYLON;
     /**
      * Base class of the scene acting as a container for the different elements composing a scene.
      * This class is dynamically extended by the different components of the scene increasing
-     * flexibility and reducing coupling.
+     * flexibility and reducing coupling
      */
     var AbstractScene = /** @class */ (function () {
         function AbstractScene() {
@@ -23860,7 +23832,7 @@ var BABYLON;
             this.textures = new Array();
         }
         /**
-         * Adds a parser in the list of availables ones.
+         * Adds a parser in the list of available ones
          * @param name Defines the name of the parser
          * @param parser Defines the parser to add
          */
@@ -23868,6 +23840,36 @@ var BABYLON;
             this._BabylonFileParsers[name] = parser;
         };
         /**
+         * Gets a general parser from the list of avaialble ones
+         * @param name Defines the name of the parser
+         * @returns the requested parser or null
+         */
+        AbstractScene.GetParser = function (name) {
+            if (this._BabylonFileParsers[name]) {
+                return this._BabylonFileParsers[name];
+            }
+            return null;
+        };
+        /**
+         * Adds n individual parser in the list of available ones
+         * @param name Defines the name of the parser
+         * @param parser Defines the parser to add
+         */
+        AbstractScene.AddIndividualParser = function (name, parser) {
+            this._IndividualBabylonFileParsers[name] = parser;
+        };
+        /**
+         * Gets an individual parser from the list of avaialble ones
+         * @param name Defines the name of the parser
+         * @returns the requested parser or null
+         */
+        AbstractScene.GetIndividualParser = function (name) {
+            if (this._IndividualBabylonFileParsers[name]) {
+                return this._IndividualBabylonFileParsers[name];
+            }
+            return null;
+        };
+        /**
          * Parser json data and populate both a scene and its associated container object
          * @param jsonData Defines the data to parse
          * @param scene Defines the scene to parse the data for
@@ -23885,6 +23887,10 @@ var BABYLON;
          * Stores the list of available parsers in the application.
          */
         AbstractScene._BabylonFileParsers = {};
+        /**
+         * Stores the list of available individual parsers in the application.
+         */
+        AbstractScene._IndividualBabylonFileParsers = {};
         return AbstractScene;
     }());
     BABYLON.AbstractScene = AbstractScene;
@@ -29241,9 +29247,6 @@ var BABYLON;
             this.skeletons.forEach(function (o) {
                 _this.scene.addSkeleton(o);
             });
-            this.particleSystems.forEach(function (o) {
-                _this.scene.addParticleSystem(o);
-            });
             this.animations.forEach(function (o) {
                 _this.scene.addAnimation(o);
             });
@@ -29298,9 +29301,6 @@ var BABYLON;
             this.skeletons.forEach(function (o) {
                 _this.scene.removeSkeleton(o);
             });
-            this.particleSystems.forEach(function (o) {
-                _this.scene.removeParticleSystem(o);
-            });
             this.animations.forEach(function (o) {
                 _this.scene.removeAnimation(o);
             });
@@ -32551,7 +32551,7 @@ var BABYLON;
             }
         };
         /**
-         * Returns an array populated with ParticleSystem objects whose the mesh is the emitter.
+         * Returns an array populated with IParticleSystem objects whose the mesh is the emitter.
          */
         Mesh.prototype.getEmittedParticleSystems = function () {
             var results = new Array();
@@ -32564,7 +32564,7 @@ var BABYLON;
             return results;
         };
         /**
-         * Returns an array populated with ParticleSystem objects whose the mesh or its children are the emitter.
+         * Returns an array populated with IParticleSystem objects whose the mesh or its children are the emitter.
          */
         Mesh.prototype.getHierarchyEmittedParticleSystems = function () {
             var results = new Array();
@@ -56716,10 +56716,6 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.particleSystem.js.map
 
-
-
-//# sourceMappingURL=babylon.IParticleEmitterType.js.map
-
 var BABYLON;
 (function (BABYLON) {
     /**
@@ -57225,6 +57221,56 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.sphereParticleEmitter.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    // Adds the parsers to the scene parsers.
+    BABYLON.AbstractScene.AddParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM, function (parsedData, scene, container, rootUrl) {
+        // Particles Systems
+        if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
+            for (var index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
+                var parsedParticleSystem = parsedData.particleSystems[index];
+                if (parsedParticleSystem.activeParticleCount) {
+                    var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+                    container.particleSystems.push(ps);
+                }
+                else {
+                    var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+                    container.particleSystems.push(ps);
+                }
+            }
+        }
+    });
+    BABYLON.AbstractScene.AddIndividualParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM, function (parsedParticleSystem, scene, rootUrl) {
+        if (parsedParticleSystem.activeParticleCount) {
+            var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+            return ps;
+        }
+        else {
+            var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+            return ps;
+        }
+    });
+    BABYLON.Engine.prototype.createEffectForParticles = function (fragmentName, uniformsNames, samplers, defines, fallbacks, onCompiled, onError) {
+        if (uniformsNames === void 0) { uniformsNames = []; }
+        if (samplers === void 0) { samplers = []; }
+        if (defines === void 0) { defines = ""; }
+        var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
+        var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
+        if (defines.indexOf(" BILLBOARD") === -1) {
+            defines += "\n#define BILLBOARD\n";
+        }
+        if (samplers.indexOf("diffuseSampler") === -1) {
+            samplers.push("diffuseSampler");
+        }
+        return this.createEffect({
+            vertex: "particles",
+            fragmentElement: fragmentName
+        }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
+    };
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.particleSystemComponent.js.map
+
 var __assign = (this && this.__assign) || Object.assign || function(t) {
     for (var s, i = 1, n = arguments.length; i < n; i++) {
         s = arguments[i];
@@ -68782,20 +68828,6 @@ var BABYLON;
                     currentMesh.computeWorldMatrix(true);
                 }
             }
-            // Particles Systems
-            if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
-                for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
-                    var parsedParticleSystem = parsedData.particleSystems[index];
-                    if (parsedParticleSystem.activeParticleCount) {
-                        var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
-                        container.particleSystems.push(ps);
-                    }
-                    else {
-                        var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
-                        container.particleSystems.push(ps);
-                    }
-                }
-            }
             // Shadows
             if (parsedData.shadowGenerators !== undefined && parsedData.shadowGenerators !== null) {
                 for (index = 0, cache = parsedData.shadowGenerators.length; index < cache; index++) {
@@ -69027,10 +69059,13 @@ var BABYLON;
                 }
                 // Particles
                 if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
-                    for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
-                        var parsedParticleSystem = parsedData.particleSystems[index];
-                        if (hierarchyIds.indexOf(parsedParticleSystem.emitterId) !== -1) {
-                            particleSystems.push(BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl));
+                    var parser = BABYLON.AbstractScene.GetIndividualParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM);
+                    if (parser) {
+                        for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
+                            var parsedParticleSystem = parsedData.particleSystems[index];
+                            if (hierarchyIds.indexOf(parsedParticleSystem.emitterId) !== -1) {
+                                particleSystems.push(parser(parsedParticleSystem, scene, rootUrl));
+                            }
                         }
                     }
                 }
@@ -84657,7 +84692,7 @@ var BABYLON;
         this.lensFlareSystems.push(newLensFlareSystem);
     };
     /**
-     * Defines the layer scene component responsible to manage any layers
+     * Defines the lens flare scene component responsible to manage any lens flares
      * in a given scene.
      */
     var LensFlareSystemSceneComponent = /** @class */ (function () {
@@ -84671,7 +84706,7 @@ var BABYLON;
              */
             this.name = BABYLON.SceneComponentConstants.NAME_LENSFLARESYSTEM;
             this.scene = scene;
-            this._lensFlareSystems = scene.lensFlareSystems = new Array();
+            scene.lensFlareSystems = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -84719,8 +84754,9 @@ var BABYLON;
         LensFlareSystemSceneComponent.prototype.serialize = function (serializationObject) {
             // Lens flares
             serializationObject.lensFlareSystems = [];
-            for (var _i = 0, _a = this._lensFlareSystems; _i < _a.length; _i++) {
-                var lensFlareSystem = _a[_i];
+            var lensFlareSystems = this.scene.lensFlareSystems;
+            for (var _i = 0, lensFlareSystems_1 = lensFlareSystems; _i < lensFlareSystems_1.length; _i++) {
+                var lensFlareSystem = lensFlareSystems_1[_i];
                 serializationObject.lensFlareSystems.push(lensFlareSystem.serialize());
             }
         };
@@ -84728,21 +84764,23 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         LensFlareSystemSceneComponent.prototype.dispose = function () {
-            while (this._lensFlareSystems.length) {
-                this._lensFlareSystems[0].dispose();
+            var lensFlareSystems = this.scene.lensFlareSystems;
+            while (lensFlareSystems.length) {
+                lensFlareSystems[0].dispose();
             }
         };
         LensFlareSystemSceneComponent.prototype._draw = function (camera) {
             // Lens flares
             if (this.scene.lensFlaresEnabled) {
-                BABYLON.Tools.StartPerformanceCounter("Lens flares", this._lensFlareSystems.length > 0);
-                for (var _i = 0, _a = this._lensFlareSystems; _i < _a.length; _i++) {
-                    var lensFlareSystem = _a[_i];
+                var lensFlareSystems = this.scene.lensFlareSystems;
+                BABYLON.Tools.StartPerformanceCounter("Lens flares", lensFlareSystems.length > 0);
+                for (var _i = 0, lensFlareSystems_2 = lensFlareSystems; _i < lensFlareSystems_2.length; _i++) {
+                    var lensFlareSystem = lensFlareSystems_2[_i];
                     if ((camera.layerMask & lensFlareSystem.layerMask) !== 0) {
                         lensFlareSystem.render();
                     }
                 }
-                BABYLON.Tools.EndPerformanceCounter("Lens flares", this._lensFlareSystems.length > 0);
+                BABYLON.Tools.EndPerformanceCounter("Lens flares", lensFlareSystems.length > 0);
             }
         };
         return LensFlareSystemSceneComponent;
@@ -96836,7 +96874,7 @@ var BABYLON;
             this._previousStencilState = false;
             this.scene = scene;
             this._engine = scene.getEngine();
-            this._effectLayers = scene.effectLayers = new Array();
+            scene.effectLayers = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -96854,8 +96892,9 @@ var BABYLON;
          * context lost for instance.
          */
         EffectLayerSceneComponent.prototype.rebuild = function () {
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var effectLayer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_1 = layers; _i < layers_1.length; _i++) {
+                var effectLayer = layers_1[_i];
                 effectLayer._rebuild();
             }
         };
@@ -96866,8 +96905,9 @@ var BABYLON;
         EffectLayerSceneComponent.prototype.serialize = function (serializationObject) {
             // Effect layers
             serializationObject.effectLayers = [];
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var effectLayer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_2 = layers; _i < layers_2.length; _i++) {
+                var effectLayer = layers_2[_i];
                 if (effectLayer.serialize) {
                     serializationObject.effectLayers.push(effectLayer.serialize());
                 }
@@ -96903,18 +96943,20 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         EffectLayerSceneComponent.prototype.dispose = function () {
-            while (this._effectLayers.length) {
-                this._effectLayers[0].dispose();
+            var layers = this.scene.effectLayers;
+            while (layers.length) {
+                layers[0].dispose();
             }
         };
         EffectLayerSceneComponent.prototype._isReadyForMesh = function (mesh, hardwareInstancedRendering) {
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var layer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_3 = layers; _i < layers_3.length; _i++) {
+                var layer = layers_3[_i];
                 if (!layer.hasMesh(mesh)) {
                     continue;
                 }
-                for (var _b = 0, _c = mesh.subMeshes; _b < _c.length; _b++) {
-                    var subMesh = _c[_b];
+                for (var _a = 0, _b = mesh.subMeshes; _a < _b.length; _a++) {
+                    var subMesh = _b[_a];
                     if (!layer.isReady(subMesh, hardwareInstancedRendering)) {
                         return false;
                     }
@@ -96925,10 +96967,11 @@ var BABYLON;
         EffectLayerSceneComponent.prototype._renderMainTexture = function (camera) {
             this._renderEffects = false;
             this._needStencil = false;
-            if (this._effectLayers && this._effectLayers.length > 0) {
+            var layers = this.scene.effectLayers;
+            if (layers && layers.length > 0) {
                 this._previousStencilState = this._engine.getStencilBuffer();
-                for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                    var effectLayer = _a[_i];
+                for (var _i = 0, layers_4 = layers; _i < layers_4.length; _i++) {
+                    var effectLayer = layers_4[_i];
                     if (effectLayer.shouldRender() &&
                         (!effectLayer.camera ||
                             (effectLayer.camera.cameraRigMode === BABYLON.Camera.RIG_MODE_NONE && camera === effectLayer.camera) ||
@@ -96960,8 +97003,9 @@ var BABYLON;
         EffectLayerSceneComponent.prototype._draw = function (renderingGroupId) {
             if (this._renderEffects) {
                 this._engine.setDepthBuffer(false);
-                for (var i = 0; i < this._effectLayers.length; i++) {
-                    var effectLayer = this._effectLayers[i];
+                var layers = this.scene.effectLayers;
+                for (var i = 0; i < layers.length; i++) {
+                    var effectLayer = layers[i];
                     if (effectLayer.renderingGroupId === renderingGroupId) {
                         if (effectLayer.shouldRender()) {
                             effectLayer.render();
@@ -99771,7 +99815,7 @@ var BABYLON;
             this.name = BABYLON.SceneComponentConstants.NAME_LAYER;
             this.scene = scene;
             this._engine = scene.getEngine();
-            this._layers = scene.layers = new Array();
+            scene.layers = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -99785,8 +99829,9 @@ var BABYLON;
          * context lost for instance.
          */
         LayerSceneComponent.prototype.rebuild = function () {
-            for (var _i = 0, _a = this._layers; _i < _a.length; _i++) {
-                var layer = _a[_i];
+            var layers = this.scene.layers;
+            for (var _i = 0, layers_1 = layers; _i < layers_1.length; _i++) {
+                var layer = layers_1[_i];
                 layer._rebuild();
             }
         };
@@ -99794,16 +99839,18 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         LayerSceneComponent.prototype.dispose = function () {
-            while (this._layers.length) {
-                this._layers[0].dispose();
+            var layers = this.scene.layers;
+            while (layers.length) {
+                layers[0].dispose();
             }
         };
         LayerSceneComponent.prototype._draw = function (camera, isBackground) {
-            if (this._layers.length) {
+            var layers = this.scene.layers;
+            if (layers.length) {
                 this._engine.setDepthBuffer(false);
                 var cameraLayerMask = camera.layerMask;
-                for (var _i = 0, _a = this._layers; _i < _a.length; _i++) {
-                    var layer = _a[_i];
+                for (var _i = 0, layers_2 = layers; _i < layers_2.length; _i++) {
+                    var layer = layers_2[_i];
                     if (layer.isBackground === isBackground && ((layer.layerMask & cameraLayerMask) !== 0)) {
                         layer.render();
                     }

+ 142 - 95
dist/preview release/babylon.no-module.max.js

@@ -13708,35 +13708,6 @@ var BABYLON;
             return effect;
         };
         /**
-         * Create an effect to use with particle systems.
-         * Please note that some parameters like animation sheets or not being billboard are not supported in this configuration
-         * @param fragmentName defines the base name of the effect (The name of file without .fragment.fx)
-         * @param uniformsNames defines a list of attribute names
-         * @param samplers defines an array of string used to represent textures
-         * @param defines defines the string containing the defines to use to compile the shaders
-         * @param fallbacks defines the list of potential fallbacks to use if shader conmpilation fails
-         * @param onCompiled defines a function to call when the effect creation is successful
-         * @param onError defines a function to call when the effect creation has failed
-         * @returns the new Effect
-         */
-        Engine.prototype.createEffectForParticles = function (fragmentName, uniformsNames, samplers, defines, fallbacks, onCompiled, onError) {
-            if (uniformsNames === void 0) { uniformsNames = []; }
-            if (samplers === void 0) { samplers = []; }
-            if (defines === void 0) { defines = ""; }
-            var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
-            var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
-            if (defines.indexOf(" BILLBOARD") === -1) {
-                defines += "\n#define BILLBOARD\n";
-            }
-            if (samplers.indexOf("diffuseSampler") === -1) {
-                samplers.push("diffuseSampler");
-            }
-            return this.createEffect({
-                vertex: "particles",
-                fragmentElement: fragmentName
-            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
-        };
-        /**
          * Directly creates a webGL program
          * @param vertexCode defines the vertex shader code to use
          * @param fragmentCode defines the fragment shader code to use
@@ -23684,6 +23655,7 @@ var BABYLON;
         SceneComponentConstants.NAME_LAYER = "Layer";
         SceneComponentConstants.NAME_LENSFLARESYSTEM = "LensFlareSystem";
         SceneComponentConstants.NAME_BOUNDINGBOXRENDERER = "BoundingBoxRenderer";
+        SceneComponentConstants.NAME_PARTICLESYSTEM = "ParticleSystem";
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
@@ -23753,7 +23725,7 @@ var BABYLON;
     /**
      * Base class of the scene acting as a container for the different elements composing a scene.
      * This class is dynamically extended by the different components of the scene increasing
-     * flexibility and reducing coupling.
+     * flexibility and reducing coupling
      */
     var AbstractScene = /** @class */ (function () {
         function AbstractScene() {
@@ -23827,7 +23799,7 @@ var BABYLON;
             this.textures = new Array();
         }
         /**
-         * Adds a parser in the list of availables ones.
+         * Adds a parser in the list of available ones
          * @param name Defines the name of the parser
          * @param parser Defines the parser to add
          */
@@ -23835,6 +23807,36 @@ var BABYLON;
             this._BabylonFileParsers[name] = parser;
         };
         /**
+         * Gets a general parser from the list of avaialble ones
+         * @param name Defines the name of the parser
+         * @returns the requested parser or null
+         */
+        AbstractScene.GetParser = function (name) {
+            if (this._BabylonFileParsers[name]) {
+                return this._BabylonFileParsers[name];
+            }
+            return null;
+        };
+        /**
+         * Adds n individual parser in the list of available ones
+         * @param name Defines the name of the parser
+         * @param parser Defines the parser to add
+         */
+        AbstractScene.AddIndividualParser = function (name, parser) {
+            this._IndividualBabylonFileParsers[name] = parser;
+        };
+        /**
+         * Gets an individual parser from the list of avaialble ones
+         * @param name Defines the name of the parser
+         * @returns the requested parser or null
+         */
+        AbstractScene.GetIndividualParser = function (name) {
+            if (this._IndividualBabylonFileParsers[name]) {
+                return this._IndividualBabylonFileParsers[name];
+            }
+            return null;
+        };
+        /**
          * Parser json data and populate both a scene and its associated container object
          * @param jsonData Defines the data to parse
          * @param scene Defines the scene to parse the data for
@@ -23852,6 +23854,10 @@ var BABYLON;
          * Stores the list of available parsers in the application.
          */
         AbstractScene._BabylonFileParsers = {};
+        /**
+         * Stores the list of available individual parsers in the application.
+         */
+        AbstractScene._IndividualBabylonFileParsers = {};
         return AbstractScene;
     }());
     BABYLON.AbstractScene = AbstractScene;
@@ -29208,9 +29214,6 @@ var BABYLON;
             this.skeletons.forEach(function (o) {
                 _this.scene.addSkeleton(o);
             });
-            this.particleSystems.forEach(function (o) {
-                _this.scene.addParticleSystem(o);
-            });
             this.animations.forEach(function (o) {
                 _this.scene.addAnimation(o);
             });
@@ -29265,9 +29268,6 @@ var BABYLON;
             this.skeletons.forEach(function (o) {
                 _this.scene.removeSkeleton(o);
             });
-            this.particleSystems.forEach(function (o) {
-                _this.scene.removeParticleSystem(o);
-            });
             this.animations.forEach(function (o) {
                 _this.scene.removeAnimation(o);
             });
@@ -32518,7 +32518,7 @@ var BABYLON;
             }
         };
         /**
-         * Returns an array populated with ParticleSystem objects whose the mesh is the emitter.
+         * Returns an array populated with IParticleSystem objects whose the mesh is the emitter.
          */
         Mesh.prototype.getEmittedParticleSystems = function () {
             var results = new Array();
@@ -32531,7 +32531,7 @@ var BABYLON;
             return results;
         };
         /**
-         * Returns an array populated with ParticleSystem objects whose the mesh or its children are the emitter.
+         * Returns an array populated with IParticleSystem objects whose the mesh or its children are the emitter.
          */
         Mesh.prototype.getHierarchyEmittedParticleSystems = function () {
             var results = new Array();
@@ -56683,10 +56683,6 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.particleSystem.js.map
 
-
-
-//# sourceMappingURL=babylon.IParticleEmitterType.js.map
-
 var BABYLON;
 (function (BABYLON) {
     /**
@@ -57192,6 +57188,56 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.sphereParticleEmitter.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    // Adds the parsers to the scene parsers.
+    BABYLON.AbstractScene.AddParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM, function (parsedData, scene, container, rootUrl) {
+        // Particles Systems
+        if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
+            for (var index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
+                var parsedParticleSystem = parsedData.particleSystems[index];
+                if (parsedParticleSystem.activeParticleCount) {
+                    var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+                    container.particleSystems.push(ps);
+                }
+                else {
+                    var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+                    container.particleSystems.push(ps);
+                }
+            }
+        }
+    });
+    BABYLON.AbstractScene.AddIndividualParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM, function (parsedParticleSystem, scene, rootUrl) {
+        if (parsedParticleSystem.activeParticleCount) {
+            var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+            return ps;
+        }
+        else {
+            var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+            return ps;
+        }
+    });
+    BABYLON.Engine.prototype.createEffectForParticles = function (fragmentName, uniformsNames, samplers, defines, fallbacks, onCompiled, onError) {
+        if (uniformsNames === void 0) { uniformsNames = []; }
+        if (samplers === void 0) { samplers = []; }
+        if (defines === void 0) { defines = ""; }
+        var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
+        var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
+        if (defines.indexOf(" BILLBOARD") === -1) {
+            defines += "\n#define BILLBOARD\n";
+        }
+        if (samplers.indexOf("diffuseSampler") === -1) {
+            samplers.push("diffuseSampler");
+        }
+        return this.createEffect({
+            vertex: "particles",
+            fragmentElement: fragmentName
+        }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
+    };
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.particleSystemComponent.js.map
+
 var __assign = (this && this.__assign) || Object.assign || function(t) {
     for (var s, i = 1, n = arguments.length; i < n; i++) {
         s = arguments[i];
@@ -68749,20 +68795,6 @@ var BABYLON;
                     currentMesh.computeWorldMatrix(true);
                 }
             }
-            // Particles Systems
-            if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
-                for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
-                    var parsedParticleSystem = parsedData.particleSystems[index];
-                    if (parsedParticleSystem.activeParticleCount) {
-                        var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
-                        container.particleSystems.push(ps);
-                    }
-                    else {
-                        var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
-                        container.particleSystems.push(ps);
-                    }
-                }
-            }
             // Shadows
             if (parsedData.shadowGenerators !== undefined && parsedData.shadowGenerators !== null) {
                 for (index = 0, cache = parsedData.shadowGenerators.length; index < cache; index++) {
@@ -68994,10 +69026,13 @@ var BABYLON;
                 }
                 // Particles
                 if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
-                    for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
-                        var parsedParticleSystem = parsedData.particleSystems[index];
-                        if (hierarchyIds.indexOf(parsedParticleSystem.emitterId) !== -1) {
-                            particleSystems.push(BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl));
+                    var parser = BABYLON.AbstractScene.GetIndividualParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM);
+                    if (parser) {
+                        for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
+                            var parsedParticleSystem = parsedData.particleSystems[index];
+                            if (hierarchyIds.indexOf(parsedParticleSystem.emitterId) !== -1) {
+                                particleSystems.push(parser(parsedParticleSystem, scene, rootUrl));
+                            }
                         }
                     }
                 }
@@ -84624,7 +84659,7 @@ var BABYLON;
         this.lensFlareSystems.push(newLensFlareSystem);
     };
     /**
-     * Defines the layer scene component responsible to manage any layers
+     * Defines the lens flare scene component responsible to manage any lens flares
      * in a given scene.
      */
     var LensFlareSystemSceneComponent = /** @class */ (function () {
@@ -84638,7 +84673,7 @@ var BABYLON;
              */
             this.name = BABYLON.SceneComponentConstants.NAME_LENSFLARESYSTEM;
             this.scene = scene;
-            this._lensFlareSystems = scene.lensFlareSystems = new Array();
+            scene.lensFlareSystems = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -84686,8 +84721,9 @@ var BABYLON;
         LensFlareSystemSceneComponent.prototype.serialize = function (serializationObject) {
             // Lens flares
             serializationObject.lensFlareSystems = [];
-            for (var _i = 0, _a = this._lensFlareSystems; _i < _a.length; _i++) {
-                var lensFlareSystem = _a[_i];
+            var lensFlareSystems = this.scene.lensFlareSystems;
+            for (var _i = 0, lensFlareSystems_1 = lensFlareSystems; _i < lensFlareSystems_1.length; _i++) {
+                var lensFlareSystem = lensFlareSystems_1[_i];
                 serializationObject.lensFlareSystems.push(lensFlareSystem.serialize());
             }
         };
@@ -84695,21 +84731,23 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         LensFlareSystemSceneComponent.prototype.dispose = function () {
-            while (this._lensFlareSystems.length) {
-                this._lensFlareSystems[0].dispose();
+            var lensFlareSystems = this.scene.lensFlareSystems;
+            while (lensFlareSystems.length) {
+                lensFlareSystems[0].dispose();
             }
         };
         LensFlareSystemSceneComponent.prototype._draw = function (camera) {
             // Lens flares
             if (this.scene.lensFlaresEnabled) {
-                BABYLON.Tools.StartPerformanceCounter("Lens flares", this._lensFlareSystems.length > 0);
-                for (var _i = 0, _a = this._lensFlareSystems; _i < _a.length; _i++) {
-                    var lensFlareSystem = _a[_i];
+                var lensFlareSystems = this.scene.lensFlareSystems;
+                BABYLON.Tools.StartPerformanceCounter("Lens flares", lensFlareSystems.length > 0);
+                for (var _i = 0, lensFlareSystems_2 = lensFlareSystems; _i < lensFlareSystems_2.length; _i++) {
+                    var lensFlareSystem = lensFlareSystems_2[_i];
                     if ((camera.layerMask & lensFlareSystem.layerMask) !== 0) {
                         lensFlareSystem.render();
                     }
                 }
-                BABYLON.Tools.EndPerformanceCounter("Lens flares", this._lensFlareSystems.length > 0);
+                BABYLON.Tools.EndPerformanceCounter("Lens flares", lensFlareSystems.length > 0);
             }
         };
         return LensFlareSystemSceneComponent;
@@ -96803,7 +96841,7 @@ var BABYLON;
             this._previousStencilState = false;
             this.scene = scene;
             this._engine = scene.getEngine();
-            this._effectLayers = scene.effectLayers = new Array();
+            scene.effectLayers = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -96821,8 +96859,9 @@ var BABYLON;
          * context lost for instance.
          */
         EffectLayerSceneComponent.prototype.rebuild = function () {
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var effectLayer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_1 = layers; _i < layers_1.length; _i++) {
+                var effectLayer = layers_1[_i];
                 effectLayer._rebuild();
             }
         };
@@ -96833,8 +96872,9 @@ var BABYLON;
         EffectLayerSceneComponent.prototype.serialize = function (serializationObject) {
             // Effect layers
             serializationObject.effectLayers = [];
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var effectLayer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_2 = layers; _i < layers_2.length; _i++) {
+                var effectLayer = layers_2[_i];
                 if (effectLayer.serialize) {
                     serializationObject.effectLayers.push(effectLayer.serialize());
                 }
@@ -96870,18 +96910,20 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         EffectLayerSceneComponent.prototype.dispose = function () {
-            while (this._effectLayers.length) {
-                this._effectLayers[0].dispose();
+            var layers = this.scene.effectLayers;
+            while (layers.length) {
+                layers[0].dispose();
             }
         };
         EffectLayerSceneComponent.prototype._isReadyForMesh = function (mesh, hardwareInstancedRendering) {
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var layer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_3 = layers; _i < layers_3.length; _i++) {
+                var layer = layers_3[_i];
                 if (!layer.hasMesh(mesh)) {
                     continue;
                 }
-                for (var _b = 0, _c = mesh.subMeshes; _b < _c.length; _b++) {
-                    var subMesh = _c[_b];
+                for (var _a = 0, _b = mesh.subMeshes; _a < _b.length; _a++) {
+                    var subMesh = _b[_a];
                     if (!layer.isReady(subMesh, hardwareInstancedRendering)) {
                         return false;
                     }
@@ -96892,10 +96934,11 @@ var BABYLON;
         EffectLayerSceneComponent.prototype._renderMainTexture = function (camera) {
             this._renderEffects = false;
             this._needStencil = false;
-            if (this._effectLayers && this._effectLayers.length > 0) {
+            var layers = this.scene.effectLayers;
+            if (layers && layers.length > 0) {
                 this._previousStencilState = this._engine.getStencilBuffer();
-                for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                    var effectLayer = _a[_i];
+                for (var _i = 0, layers_4 = layers; _i < layers_4.length; _i++) {
+                    var effectLayer = layers_4[_i];
                     if (effectLayer.shouldRender() &&
                         (!effectLayer.camera ||
                             (effectLayer.camera.cameraRigMode === BABYLON.Camera.RIG_MODE_NONE && camera === effectLayer.camera) ||
@@ -96927,8 +96970,9 @@ var BABYLON;
         EffectLayerSceneComponent.prototype._draw = function (renderingGroupId) {
             if (this._renderEffects) {
                 this._engine.setDepthBuffer(false);
-                for (var i = 0; i < this._effectLayers.length; i++) {
-                    var effectLayer = this._effectLayers[i];
+                var layers = this.scene.effectLayers;
+                for (var i = 0; i < layers.length; i++) {
+                    var effectLayer = layers[i];
                     if (effectLayer.renderingGroupId === renderingGroupId) {
                         if (effectLayer.shouldRender()) {
                             effectLayer.render();
@@ -99738,7 +99782,7 @@ var BABYLON;
             this.name = BABYLON.SceneComponentConstants.NAME_LAYER;
             this.scene = scene;
             this._engine = scene.getEngine();
-            this._layers = scene.layers = new Array();
+            scene.layers = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -99752,8 +99796,9 @@ var BABYLON;
          * context lost for instance.
          */
         LayerSceneComponent.prototype.rebuild = function () {
-            for (var _i = 0, _a = this._layers; _i < _a.length; _i++) {
-                var layer = _a[_i];
+            var layers = this.scene.layers;
+            for (var _i = 0, layers_1 = layers; _i < layers_1.length; _i++) {
+                var layer = layers_1[_i];
                 layer._rebuild();
             }
         };
@@ -99761,16 +99806,18 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         LayerSceneComponent.prototype.dispose = function () {
-            while (this._layers.length) {
-                this._layers[0].dispose();
+            var layers = this.scene.layers;
+            while (layers.length) {
+                layers[0].dispose();
             }
         };
         LayerSceneComponent.prototype._draw = function (camera, isBackground) {
-            if (this._layers.length) {
+            var layers = this.scene.layers;
+            if (layers.length) {
                 this._engine.setDepthBuffer(false);
                 var cameraLayerMask = camera.layerMask;
-                for (var _i = 0, _a = this._layers; _i < _a.length; _i++) {
-                    var layer = _a[_i];
+                for (var _i = 0, layers_2 = layers; _i < layers_2.length; _i++) {
+                    var layer = layers_2[_i];
                     if (layer.isBackground === isBackground && ((layer.layerMask & cameraLayerMask) !== 0)) {
                         layer.render();
                     }

+ 142 - 95
dist/preview release/es6.js

@@ -13708,35 +13708,6 @@ var BABYLON;
             return effect;
         };
         /**
-         * Create an effect to use with particle systems.
-         * Please note that some parameters like animation sheets or not being billboard are not supported in this configuration
-         * @param fragmentName defines the base name of the effect (The name of file without .fragment.fx)
-         * @param uniformsNames defines a list of attribute names
-         * @param samplers defines an array of string used to represent textures
-         * @param defines defines the string containing the defines to use to compile the shaders
-         * @param fallbacks defines the list of potential fallbacks to use if shader conmpilation fails
-         * @param onCompiled defines a function to call when the effect creation is successful
-         * @param onError defines a function to call when the effect creation has failed
-         * @returns the new Effect
-         */
-        Engine.prototype.createEffectForParticles = function (fragmentName, uniformsNames, samplers, defines, fallbacks, onCompiled, onError) {
-            if (uniformsNames === void 0) { uniformsNames = []; }
-            if (samplers === void 0) { samplers = []; }
-            if (defines === void 0) { defines = ""; }
-            var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
-            var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
-            if (defines.indexOf(" BILLBOARD") === -1) {
-                defines += "\n#define BILLBOARD\n";
-            }
-            if (samplers.indexOf("diffuseSampler") === -1) {
-                samplers.push("diffuseSampler");
-            }
-            return this.createEffect({
-                vertex: "particles",
-                fragmentElement: fragmentName
-            }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
-        };
-        /**
          * Directly creates a webGL program
          * @param vertexCode defines the vertex shader code to use
          * @param fragmentCode defines the fragment shader code to use
@@ -23684,6 +23655,7 @@ var BABYLON;
         SceneComponentConstants.NAME_LAYER = "Layer";
         SceneComponentConstants.NAME_LENSFLARESYSTEM = "LensFlareSystem";
         SceneComponentConstants.NAME_BOUNDINGBOXRENDERER = "BoundingBoxRenderer";
+        SceneComponentConstants.NAME_PARTICLESYSTEM = "ParticleSystem";
         SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER = 0;
         SceneComponentConstants.STEP_BEFOREEVALUATEACTIVEMESH_BOUNDINGBOXRENDERER = 0;
         SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER = 0;
@@ -23753,7 +23725,7 @@ var BABYLON;
     /**
      * Base class of the scene acting as a container for the different elements composing a scene.
      * This class is dynamically extended by the different components of the scene increasing
-     * flexibility and reducing coupling.
+     * flexibility and reducing coupling
      */
     var AbstractScene = /** @class */ (function () {
         function AbstractScene() {
@@ -23827,7 +23799,7 @@ var BABYLON;
             this.textures = new Array();
         }
         /**
-         * Adds a parser in the list of availables ones.
+         * Adds a parser in the list of available ones
          * @param name Defines the name of the parser
          * @param parser Defines the parser to add
          */
@@ -23835,6 +23807,36 @@ var BABYLON;
             this._BabylonFileParsers[name] = parser;
         };
         /**
+         * Gets a general parser from the list of avaialble ones
+         * @param name Defines the name of the parser
+         * @returns the requested parser or null
+         */
+        AbstractScene.GetParser = function (name) {
+            if (this._BabylonFileParsers[name]) {
+                return this._BabylonFileParsers[name];
+            }
+            return null;
+        };
+        /**
+         * Adds n individual parser in the list of available ones
+         * @param name Defines the name of the parser
+         * @param parser Defines the parser to add
+         */
+        AbstractScene.AddIndividualParser = function (name, parser) {
+            this._IndividualBabylonFileParsers[name] = parser;
+        };
+        /**
+         * Gets an individual parser from the list of avaialble ones
+         * @param name Defines the name of the parser
+         * @returns the requested parser or null
+         */
+        AbstractScene.GetIndividualParser = function (name) {
+            if (this._IndividualBabylonFileParsers[name]) {
+                return this._IndividualBabylonFileParsers[name];
+            }
+            return null;
+        };
+        /**
          * Parser json data and populate both a scene and its associated container object
          * @param jsonData Defines the data to parse
          * @param scene Defines the scene to parse the data for
@@ -23852,6 +23854,10 @@ var BABYLON;
          * Stores the list of available parsers in the application.
          */
         AbstractScene._BabylonFileParsers = {};
+        /**
+         * Stores the list of available individual parsers in the application.
+         */
+        AbstractScene._IndividualBabylonFileParsers = {};
         return AbstractScene;
     }());
     BABYLON.AbstractScene = AbstractScene;
@@ -29208,9 +29214,6 @@ var BABYLON;
             this.skeletons.forEach(function (o) {
                 _this.scene.addSkeleton(o);
             });
-            this.particleSystems.forEach(function (o) {
-                _this.scene.addParticleSystem(o);
-            });
             this.animations.forEach(function (o) {
                 _this.scene.addAnimation(o);
             });
@@ -29265,9 +29268,6 @@ var BABYLON;
             this.skeletons.forEach(function (o) {
                 _this.scene.removeSkeleton(o);
             });
-            this.particleSystems.forEach(function (o) {
-                _this.scene.removeParticleSystem(o);
-            });
             this.animations.forEach(function (o) {
                 _this.scene.removeAnimation(o);
             });
@@ -32518,7 +32518,7 @@ var BABYLON;
             }
         };
         /**
-         * Returns an array populated with ParticleSystem objects whose the mesh is the emitter.
+         * Returns an array populated with IParticleSystem objects whose the mesh is the emitter.
          */
         Mesh.prototype.getEmittedParticleSystems = function () {
             var results = new Array();
@@ -32531,7 +32531,7 @@ var BABYLON;
             return results;
         };
         /**
-         * Returns an array populated with ParticleSystem objects whose the mesh or its children are the emitter.
+         * Returns an array populated with IParticleSystem objects whose the mesh or its children are the emitter.
          */
         Mesh.prototype.getHierarchyEmittedParticleSystems = function () {
             var results = new Array();
@@ -56683,10 +56683,6 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.particleSystem.js.map
 
-
-
-//# sourceMappingURL=babylon.IParticleEmitterType.js.map
-
 var BABYLON;
 (function (BABYLON) {
     /**
@@ -57192,6 +57188,56 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.sphereParticleEmitter.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    // Adds the parsers to the scene parsers.
+    BABYLON.AbstractScene.AddParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM, function (parsedData, scene, container, rootUrl) {
+        // Particles Systems
+        if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
+            for (var index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
+                var parsedParticleSystem = parsedData.particleSystems[index];
+                if (parsedParticleSystem.activeParticleCount) {
+                    var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+                    container.particleSystems.push(ps);
+                }
+                else {
+                    var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+                    container.particleSystems.push(ps);
+                }
+            }
+        }
+    });
+    BABYLON.AbstractScene.AddIndividualParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM, function (parsedParticleSystem, scene, rootUrl) {
+        if (parsedParticleSystem.activeParticleCount) {
+            var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+            return ps;
+        }
+        else {
+            var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+            return ps;
+        }
+    });
+    BABYLON.Engine.prototype.createEffectForParticles = function (fragmentName, uniformsNames, samplers, defines, fallbacks, onCompiled, onError) {
+        if (uniformsNames === void 0) { uniformsNames = []; }
+        if (samplers === void 0) { samplers = []; }
+        if (defines === void 0) { defines = ""; }
+        var attributesNamesOrOptions = BABYLON.ParticleSystem._GetAttributeNamesOrOptions();
+        var effectCreationOption = BABYLON.ParticleSystem._GetEffectCreationOptions();
+        if (defines.indexOf(" BILLBOARD") === -1) {
+            defines += "\n#define BILLBOARD\n";
+        }
+        if (samplers.indexOf("diffuseSampler") === -1) {
+            samplers.push("diffuseSampler");
+        }
+        return this.createEffect({
+            vertex: "particles",
+            fragmentElement: fragmentName
+        }, attributesNamesOrOptions, effectCreationOption.concat(uniformsNames), samplers, defines, fallbacks, onCompiled, onError);
+    };
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.particleSystemComponent.js.map
+
 var __assign = (this && this.__assign) || Object.assign || function(t) {
     for (var s, i = 1, n = arguments.length; i < n; i++) {
         s = arguments[i];
@@ -68749,20 +68795,6 @@ var BABYLON;
                     currentMesh.computeWorldMatrix(true);
                 }
             }
-            // Particles Systems
-            if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
-                for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
-                    var parsedParticleSystem = parsedData.particleSystems[index];
-                    if (parsedParticleSystem.activeParticleCount) {
-                        var ps = BABYLON.GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
-                        container.particleSystems.push(ps);
-                    }
-                    else {
-                        var ps = BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
-                        container.particleSystems.push(ps);
-                    }
-                }
-            }
             // Shadows
             if (parsedData.shadowGenerators !== undefined && parsedData.shadowGenerators !== null) {
                 for (index = 0, cache = parsedData.shadowGenerators.length; index < cache; index++) {
@@ -68994,10 +69026,13 @@ var BABYLON;
                 }
                 // Particles
                 if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
-                    for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
-                        var parsedParticleSystem = parsedData.particleSystems[index];
-                        if (hierarchyIds.indexOf(parsedParticleSystem.emitterId) !== -1) {
-                            particleSystems.push(BABYLON.ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl));
+                    var parser = BABYLON.AbstractScene.GetIndividualParser(BABYLON.SceneComponentConstants.NAME_PARTICLESYSTEM);
+                    if (parser) {
+                        for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
+                            var parsedParticleSystem = parsedData.particleSystems[index];
+                            if (hierarchyIds.indexOf(parsedParticleSystem.emitterId) !== -1) {
+                                particleSystems.push(parser(parsedParticleSystem, scene, rootUrl));
+                            }
                         }
                     }
                 }
@@ -84624,7 +84659,7 @@ var BABYLON;
         this.lensFlareSystems.push(newLensFlareSystem);
     };
     /**
-     * Defines the layer scene component responsible to manage any layers
+     * Defines the lens flare scene component responsible to manage any lens flares
      * in a given scene.
      */
     var LensFlareSystemSceneComponent = /** @class */ (function () {
@@ -84638,7 +84673,7 @@ var BABYLON;
              */
             this.name = BABYLON.SceneComponentConstants.NAME_LENSFLARESYSTEM;
             this.scene = scene;
-            this._lensFlareSystems = scene.lensFlareSystems = new Array();
+            scene.lensFlareSystems = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -84686,8 +84721,9 @@ var BABYLON;
         LensFlareSystemSceneComponent.prototype.serialize = function (serializationObject) {
             // Lens flares
             serializationObject.lensFlareSystems = [];
-            for (var _i = 0, _a = this._lensFlareSystems; _i < _a.length; _i++) {
-                var lensFlareSystem = _a[_i];
+            var lensFlareSystems = this.scene.lensFlareSystems;
+            for (var _i = 0, lensFlareSystems_1 = lensFlareSystems; _i < lensFlareSystems_1.length; _i++) {
+                var lensFlareSystem = lensFlareSystems_1[_i];
                 serializationObject.lensFlareSystems.push(lensFlareSystem.serialize());
             }
         };
@@ -84695,21 +84731,23 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         LensFlareSystemSceneComponent.prototype.dispose = function () {
-            while (this._lensFlareSystems.length) {
-                this._lensFlareSystems[0].dispose();
+            var lensFlareSystems = this.scene.lensFlareSystems;
+            while (lensFlareSystems.length) {
+                lensFlareSystems[0].dispose();
             }
         };
         LensFlareSystemSceneComponent.prototype._draw = function (camera) {
             // Lens flares
             if (this.scene.lensFlaresEnabled) {
-                BABYLON.Tools.StartPerformanceCounter("Lens flares", this._lensFlareSystems.length > 0);
-                for (var _i = 0, _a = this._lensFlareSystems; _i < _a.length; _i++) {
-                    var lensFlareSystem = _a[_i];
+                var lensFlareSystems = this.scene.lensFlareSystems;
+                BABYLON.Tools.StartPerformanceCounter("Lens flares", lensFlareSystems.length > 0);
+                for (var _i = 0, lensFlareSystems_2 = lensFlareSystems; _i < lensFlareSystems_2.length; _i++) {
+                    var lensFlareSystem = lensFlareSystems_2[_i];
                     if ((camera.layerMask & lensFlareSystem.layerMask) !== 0) {
                         lensFlareSystem.render();
                     }
                 }
-                BABYLON.Tools.EndPerformanceCounter("Lens flares", this._lensFlareSystems.length > 0);
+                BABYLON.Tools.EndPerformanceCounter("Lens flares", lensFlareSystems.length > 0);
             }
         };
         return LensFlareSystemSceneComponent;
@@ -96803,7 +96841,7 @@ var BABYLON;
             this._previousStencilState = false;
             this.scene = scene;
             this._engine = scene.getEngine();
-            this._effectLayers = scene.effectLayers = new Array();
+            scene.effectLayers = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -96821,8 +96859,9 @@ var BABYLON;
          * context lost for instance.
          */
         EffectLayerSceneComponent.prototype.rebuild = function () {
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var effectLayer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_1 = layers; _i < layers_1.length; _i++) {
+                var effectLayer = layers_1[_i];
                 effectLayer._rebuild();
             }
         };
@@ -96833,8 +96872,9 @@ var BABYLON;
         EffectLayerSceneComponent.prototype.serialize = function (serializationObject) {
             // Effect layers
             serializationObject.effectLayers = [];
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var effectLayer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_2 = layers; _i < layers_2.length; _i++) {
+                var effectLayer = layers_2[_i];
                 if (effectLayer.serialize) {
                     serializationObject.effectLayers.push(effectLayer.serialize());
                 }
@@ -96870,18 +96910,20 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         EffectLayerSceneComponent.prototype.dispose = function () {
-            while (this._effectLayers.length) {
-                this._effectLayers[0].dispose();
+            var layers = this.scene.effectLayers;
+            while (layers.length) {
+                layers[0].dispose();
             }
         };
         EffectLayerSceneComponent.prototype._isReadyForMesh = function (mesh, hardwareInstancedRendering) {
-            for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                var layer = _a[_i];
+            var layers = this.scene.effectLayers;
+            for (var _i = 0, layers_3 = layers; _i < layers_3.length; _i++) {
+                var layer = layers_3[_i];
                 if (!layer.hasMesh(mesh)) {
                     continue;
                 }
-                for (var _b = 0, _c = mesh.subMeshes; _b < _c.length; _b++) {
-                    var subMesh = _c[_b];
+                for (var _a = 0, _b = mesh.subMeshes; _a < _b.length; _a++) {
+                    var subMesh = _b[_a];
                     if (!layer.isReady(subMesh, hardwareInstancedRendering)) {
                         return false;
                     }
@@ -96892,10 +96934,11 @@ var BABYLON;
         EffectLayerSceneComponent.prototype._renderMainTexture = function (camera) {
             this._renderEffects = false;
             this._needStencil = false;
-            if (this._effectLayers && this._effectLayers.length > 0) {
+            var layers = this.scene.effectLayers;
+            if (layers && layers.length > 0) {
                 this._previousStencilState = this._engine.getStencilBuffer();
-                for (var _i = 0, _a = this._effectLayers; _i < _a.length; _i++) {
-                    var effectLayer = _a[_i];
+                for (var _i = 0, layers_4 = layers; _i < layers_4.length; _i++) {
+                    var effectLayer = layers_4[_i];
                     if (effectLayer.shouldRender() &&
                         (!effectLayer.camera ||
                             (effectLayer.camera.cameraRigMode === BABYLON.Camera.RIG_MODE_NONE && camera === effectLayer.camera) ||
@@ -96927,8 +96970,9 @@ var BABYLON;
         EffectLayerSceneComponent.prototype._draw = function (renderingGroupId) {
             if (this._renderEffects) {
                 this._engine.setDepthBuffer(false);
-                for (var i = 0; i < this._effectLayers.length; i++) {
-                    var effectLayer = this._effectLayers[i];
+                var layers = this.scene.effectLayers;
+                for (var i = 0; i < layers.length; i++) {
+                    var effectLayer = layers[i];
                     if (effectLayer.renderingGroupId === renderingGroupId) {
                         if (effectLayer.shouldRender()) {
                             effectLayer.render();
@@ -99738,7 +99782,7 @@ var BABYLON;
             this.name = BABYLON.SceneComponentConstants.NAME_LAYER;
             this.scene = scene;
             this._engine = scene.getEngine();
-            this._layers = scene.layers = new Array();
+            scene.layers = new Array();
         }
         /**
          * Registers the component in a given scene
@@ -99752,8 +99796,9 @@ var BABYLON;
          * context lost for instance.
          */
         LayerSceneComponent.prototype.rebuild = function () {
-            for (var _i = 0, _a = this._layers; _i < _a.length; _i++) {
-                var layer = _a[_i];
+            var layers = this.scene.layers;
+            for (var _i = 0, layers_1 = layers; _i < layers_1.length; _i++) {
+                var layer = layers_1[_i];
                 layer._rebuild();
             }
         };
@@ -99761,16 +99806,18 @@ var BABYLON;
          * Disposes the component and the associated ressources.
          */
         LayerSceneComponent.prototype.dispose = function () {
-            while (this._layers.length) {
-                this._layers[0].dispose();
+            var layers = this.scene.layers;
+            while (layers.length) {
+                layers[0].dispose();
             }
         };
         LayerSceneComponent.prototype._draw = function (camera, isBackground) {
-            if (this._layers.length) {
+            var layers = this.scene.layers;
+            if (layers.length) {
                 this._engine.setDepthBuffer(false);
                 var cameraLayerMask = camera.layerMask;
-                for (var _i = 0, _a = this._layers; _i < _a.length; _i++) {
-                    var layer = _a[_i];
+                for (var _i = 0, layers_2 = layers; _i < layers_2.length; _i++) {
+                    var layer = layers_2[_i];
                     if (layer.isBackground === isBackground && ((layer.layerMask & cameraLayerMask) !== 0)) {
                         layer.render();
                     }

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

@@ -78,7 +78,7 @@ declare module BABYLON {
         readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -255,7 +255,7 @@ declare module BABYLON {
          */
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -730,7 +730,7 @@ declare module BABYLON.GLTF1 {
         */
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;

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

@@ -78,7 +78,7 @@ declare module BABYLON {
         readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -255,7 +255,7 @@ declare module BABYLON {
          */
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -471,7 +471,7 @@ declare module BABYLON.GLTF2 {
         dispose(): void;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;

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

@@ -78,7 +78,7 @@ declare module BABYLON {
         readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -255,7 +255,7 @@ declare module BABYLON {
          */
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -730,7 +730,7 @@ declare module BABYLON.GLTF1 {
         */
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -1033,7 +1033,7 @@ declare module BABYLON.GLTF2 {
         dispose(): void;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;

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

@@ -59,7 +59,7 @@ declare module BABYLON {
         private _loadMTL(url, rootUrl, onSuccess);
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;

+ 1 - 1
dist/preview release/loaders/babylon.stlFileLoader.d.ts

@@ -7,7 +7,7 @@ declare module BABYLON {
         vertexPattern: RegExp;
         name: string;
         extensions: ISceneLoaderPluginExtensions;
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
+        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<IParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
         load(scene: Scene, data: any, rootUrl: string): boolean;
         loadAssetContainer(scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void): AssetContainer;
         private isBinary(data);

+ 6 - 6
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -7,7 +7,7 @@ declare module BABYLON {
         vertexPattern: RegExp;
         name: string;
         extensions: ISceneLoaderPluginExtensions;
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
+        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<IParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
         load(scene: Scene, data: any, rootUrl: string): boolean;
         loadAssetContainer(scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void): AssetContainer;
         private isBinary(data);
@@ -77,7 +77,7 @@ declare module BABYLON {
         private _loadMTL(url, rootUrl, onSuccess);
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -179,7 +179,7 @@ declare module BABYLON {
         readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -356,7 +356,7 @@ declare module BABYLON {
          */
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -831,7 +831,7 @@ declare module BABYLON.GLTF1 {
         */
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -1134,7 +1134,7 @@ declare module BABYLON.GLTF2 {
         dispose(): void;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;

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

@@ -14,7 +14,7 @@ declare module BABYLON {
         vertexPattern: RegExp;
         name: string;
         extensions: ISceneLoaderPluginExtensions;
-        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
+        importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<IParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean;
         load(scene: Scene, data: any, rootUrl: string): boolean;
         loadAssetContainer(scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void): AssetContainer;
         private isBinary(data);
@@ -84,7 +84,7 @@ declare module BABYLON {
         private _loadMTL(url, rootUrl, onSuccess);
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -186,7 +186,7 @@ declare module BABYLON {
         readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -363,7 +363,7 @@ declare module BABYLON {
          */
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -838,7 +838,7 @@ declare module BABYLON.GLTF1 {
         */
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
@@ -1141,7 +1141,7 @@ declare module BABYLON.GLTF2 {
         dispose(): void;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
-            particleSystems: ParticleSystem[];
+            particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;

+ 1 - 1
dist/preview release/viewer/babylon.viewer.d.ts

@@ -590,7 +590,7 @@ declare module BabylonViewer {
             /**
                 * ParticleSystems connected to this model
                 */
-            particleSystems: Array<BABYLON.ParticleSystem>;
+            particleSystems: Array<BABYLON.IParticleSystem>;
             /**
                 * Skeletons defined in this model
                 */

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


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

@@ -555,7 +555,7 @@ declare module 'babylonjs-viewer/loader/modelLoader' {
 }
 
 declare module 'babylonjs-viewer/model/viewerModel' {
-    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, AbstractMesh, Observable, SceneLoaderProgressEvent, ParticleSystem, Skeleton, IDisposable, Nullable, Animation, Material } from "babylonjs";
+    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, AbstractMesh, Observable, SceneLoaderProgressEvent, IParticleSystem, Skeleton, IDisposable, Nullable, Animation, Material } from "babylonjs";
     import { GLTF2 } from "babylonjs-loaders";
     import { IModelConfiguration } from "babylonjs-viewer/configuration/interfaces/modelConfiguration";
     import { IModelAnimation } from "babylonjs-viewer/model/modelAnimation";
@@ -590,7 +590,7 @@ declare module 'babylonjs-viewer/model/viewerModel' {
             /**
                 * ParticleSystems connected to this model
                 */
-            particleSystems: Array<ParticleSystem>;
+            particleSystems: Array<IParticleSystem>;
             /**
                 * Skeletons defined in this model
                 */

+ 1 - 1
loaders/src/OBJ/babylon.objFileLoader.ts

@@ -252,7 +252,7 @@ module BABYLON {
                 () => { console.warn("Error - Unable to load " + pathOfFile); });
         }
 
-        public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             //get the meshes from OBJ file
             return this._parseSolid(meshesNames, scene, data, rootUrl).then(meshes => {
                 return {

+ 1 - 1
loaders/src/STL/babylon.stlFileLoader.ts

@@ -18,7 +18,7 @@ module BABYLON {
             ".stl": { isBinary: true },
         };
 
-        public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean {
+        public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<IParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean {
             var matches;
 
             if (typeof data !== "string") {

+ 1 - 1
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1640,7 +1640,7 @@ module BABYLON.GLTF1 {
         * @param onProgress event that fires when loading progress has occured
         * @returns a promise containg the loaded meshes, particles, skeletons and animations
         */
-        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             return new Promise((resolve, reject) => {
                 this._importMeshAsync(meshesNames, scene, data, rootUrl, (meshes, skeletons) => {
                     resolve({

+ 1 - 1
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -95,7 +95,7 @@ module BABYLON.GLTF2 {
             this._parent._clear();
         }
 
-        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             return Promise.resolve().then(() => {
                 this._babylonScene = scene;
                 this._rootUrl = rootUrl;

+ 2 - 2
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -89,7 +89,7 @@ module BABYLON {
     /** @hidden */
     export interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
 
@@ -425,7 +425,7 @@ module BABYLON {
          * @param onProgress event that fires when loading progress has occured
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             return Promise.resolve().then(() => {
                 const loaderData = this._parse(data);
                 this._loader = this._getLoader(loaderData);

+ 0 - 36
src/Engine/babylon.engine.ts

@@ -3315,42 +3315,6 @@
         }
 
         /**
-         * Create an effect to use with particle systems.
-         * Please note that some parameters like animation sheets or not being billboard are not supported in this configuration
-         * @param fragmentName defines the base name of the effect (The name of file without .fragment.fx)
-         * @param uniformsNames defines a list of attribute names 
-         * @param samplers defines an array of string used to represent textures
-         * @param defines defines the string containing the defines to use to compile the shaders
-         * @param fallbacks defines the list of potential fallbacks to use if shader conmpilation fails
-         * @param onCompiled defines a function to call when the effect creation is successful
-         * @param onError defines a function to call when the effect creation has failed
-         * @returns the new Effect
-         */
-        public createEffectForParticles(fragmentName: string, uniformsNames: string[] = [], samplers: string[] = [], defines = "", fallbacks?: EffectFallbacks,
-            onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void): Effect {
-
-            var attributesNamesOrOptions = ParticleSystem._GetAttributeNamesOrOptions();
-            var effectCreationOption = ParticleSystem._GetEffectCreationOptions();
-
-            if (defines.indexOf(" BILLBOARD") === -1) {
-                defines += "\n#define BILLBOARD\n";
-            }
-
-            if (samplers.indexOf("diffuseSampler") === -1) {
-                samplers.push("diffuseSampler");
-            }
-
-            return this.createEffect(
-                {
-                    vertex: "particles",
-                    fragmentElement: fragmentName
-                },
-                attributesNamesOrOptions,
-                effectCreationOption.concat(uniformsNames),
-                samplers, defines, fallbacks, onCompiled, onError);
-        }
-
-        /**
          * Directly creates a webGL program
          * @param vertexCode defines the vertex shader code to use
          * @param fragmentCode defines the fragment shader code to use

+ 19 - 14
src/Layer/babylon.effectLayerSceneComponent.ts

@@ -60,8 +60,6 @@
         public scene: Scene
 
         private _engine: Engine;
-        private _effectLayers: Array<EffectLayer>;
-
         private _renderEffects = false;
         private _needStencil = false;
         private _previousStencilState = false;
@@ -73,7 +71,7 @@
         constructor(scene: Scene) {
             this.scene = scene;
             this._engine = scene.getEngine();
-            this._effectLayers = scene.effectLayers = new Array<EffectLayer>();
+            scene.effectLayers = new Array<EffectLayer>();
         }
 
         /**
@@ -97,7 +95,8 @@
          * context lost for instance.
          */
         public rebuild(): void {
-            for (let effectLayer of this._effectLayers) {
+            let layers = this.scene.effectLayers;
+            for (let effectLayer of layers) {
                 effectLayer._rebuild();
             }
         }
@@ -110,7 +109,8 @@
             // Effect layers
             serializationObject.effectLayers = [];
 
-            for (let effectLayer of this._effectLayers) {
+            let layers = this.scene.effectLayers;
+            for (let effectLayer of layers) {
                 if (effectLayer.serialize) {
                     serializationObject.effectLayers.push(effectLayer.serialize());
                 }
@@ -146,14 +146,16 @@
         /**
          * Disposes the component and the associated ressources.
          */
-        public dispose(): void {
-            while (this._effectLayers.length) {
-                this._effectLayers[0].dispose();
+        public dispose(): void {            
+            let layers = this.scene.effectLayers;
+            while (layers.length) {
+                layers[0].dispose();
             }
         }
 
-        private _isReadyForMesh(mesh: AbstractMesh, hardwareInstancedRendering: boolean): boolean {
-            for (let layer of this._effectLayers) {
+        private _isReadyForMesh(mesh: AbstractMesh, hardwareInstancedRendering: boolean): boolean {            
+            let layers = this.scene.effectLayers;
+            for (let layer of layers) {
                 if (!layer.hasMesh(mesh)) {
                     continue;
                 }
@@ -171,9 +173,10 @@
             this._renderEffects = false;
             this._needStencil = false;
 
-            if (this._effectLayers && this._effectLayers.length > 0) {
+            let layers = this.scene.effectLayers;
+            if (layers && layers.length > 0) {
                 this._previousStencilState = this._engine.getStencilBuffer();
-                for (let effectLayer of this._effectLayers) {
+                for (let effectLayer of layers) {
                     if (effectLayer.shouldRender() &&
                         (!effectLayer.camera ||
                             (effectLayer.camera.cameraRigMode === Camera.RIG_MODE_NONE && camera === effectLayer.camera) ||
@@ -211,8 +214,10 @@
         private _draw(renderingGroupId: number): void {
             if (this._renderEffects) {
                 this._engine.setDepthBuffer(false);
-                for (let i = 0; i < this._effectLayers.length; i++) {
-                    const effectLayer = this._effectLayers[i];
+                
+                let layers = this.scene.effectLayers;
+                for (let i = 0; i < layers.length; i++) {
+                    const effectLayer = layers[i];
                     if (effectLayer.renderingGroupId === renderingGroupId) {
                         if (effectLayer.shouldRender()) {
                             effectLayer.render();

+ 13 - 8
src/Layer/babylon.layerSceneComponent.ts

@@ -22,7 +22,6 @@
         public scene: Scene;
 
         private _engine: Engine;
-        private _layers: Array<Layer>;
 
         /**
          * Creates a new instance of the component for the given scene
@@ -31,7 +30,7 @@
         constructor(scene: Scene) {
             this.scene = scene;
             this._engine = scene.getEngine();
-            this._layers = scene.layers = new Array<Layer>();
+            scene.layers = new Array<Layer>();
         }
 
         /**
@@ -47,7 +46,9 @@
          * context lost for instance.
          */
         public rebuild(): void {
-            for (let layer of this._layers) {
+            let layers = this.scene.layers;
+
+            for (let layer of layers) {
                 layer._rebuild();
             }
         }
@@ -56,16 +57,20 @@
          * Disposes the component and the associated ressources.
          */
         public dispose(): void {
-            while (this._layers.length) {
-                this._layers[0].dispose();
+            let layers = this.scene.layers;
+
+            while (layers.length) {
+                layers[0].dispose();
             }
         }
 
-        private _draw(camera: Camera, isBackground: boolean): void {
-            if (this._layers.length) {
+        private _draw(camera: Camera, isBackground: boolean): void {            
+            let layers = this.scene.layers;
+
+            if (layers.length) {
                 this._engine.setDepthBuffer(false);
                 const cameraLayerMask = camera.layerMask;
-                for (let layer of this._layers) {
+                for (let layer of layers) {
                     if (layer.isBackground === isBackground && ((layer.layerMask & cameraLayerMask) !== 0)) {
                         layer.render();
                     }

+ 13 - 11
src/LensFlare/babylon.lensFlareSystemSceneComponent.ts

@@ -17,6 +17,7 @@
          * @see http://doc.babylonjs.com/how_to/how_to_use_lens_flares
          */         
         lensFlareSystems: Array<LensFlareSystem>;
+
         /**
          * Removes the given lens flare system from this scene.
          * @param toRemove The lens flare system to remove
@@ -78,7 +79,7 @@
     }
 
     /**
-     * Defines the layer scene component responsible to manage any layers
+     * Defines the lens flare scene component responsible to manage any lens flares
      * in a given scene.
      */
     export class LensFlareSystemSceneComponent implements ISceneSerializableComponent {
@@ -92,8 +93,6 @@
          */
         public scene: Scene;
 
-        private _lensFlareSystems: Array<LensFlareSystem>;
-
         /**
          * Creates a new instance of the component for the given scene
          * @param scene Defines the scene to register the component in
@@ -101,7 +100,7 @@
         constructor(scene: Scene) {
             this.scene = scene;
 
-            this._lensFlareSystems = scene.lensFlareSystems = new Array<LensFlareSystem>();
+            scene.lensFlareSystems = new Array<LensFlareSystem>();
         }
 
         /**
@@ -152,7 +151,8 @@
         public serialize(serializationObject: any): void {
             // Lens flares
             serializationObject.lensFlareSystems = [];
-            for (let lensFlareSystem of this._lensFlareSystems) {
+            let lensFlareSystems = this.scene.lensFlareSystems;
+            for (let lensFlareSystem of lensFlareSystems) {
                 serializationObject.lensFlareSystems.push(lensFlareSystem.serialize());
             }
         }
@@ -161,21 +161,23 @@
          * Disposes the component and the associated ressources.
          */
         public dispose(): void {
-            while (this._lensFlareSystems.length) {
-                this._lensFlareSystems[0].dispose();
+            let lensFlareSystems = this.scene.lensFlareSystems;
+            while (lensFlareSystems.length) {
+                lensFlareSystems[0].dispose();
             }
         }
 
         private _draw(camera: Camera): void {
             // Lens flares
-            if (this.scene.lensFlaresEnabled) {
-                Tools.StartPerformanceCounter("Lens flares", this._lensFlareSystems.length > 0);
-                for (let lensFlareSystem of this._lensFlareSystems) {
+            if (this.scene.lensFlaresEnabled) {                
+                let lensFlareSystems = this.scene.lensFlareSystems;
+                Tools.StartPerformanceCounter("Lens flares", lensFlareSystems.length > 0);
+                for (let lensFlareSystem of lensFlareSystems) {
                     if ((camera.layerMask & lensFlareSystem.layerMask) !== 0) {
                         lensFlareSystem.render();
                     }
                 }
-                Tools.EndPerformanceCounter("Lens flares", this._lensFlareSystems.length > 0);
+                Tools.EndPerformanceCounter("Lens flares", lensFlareSystems.length > 0);
             }
         }
     }

+ 8 - 20
src/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -293,21 +293,6 @@
                 }
             }
 
-            // Particles Systems
-            if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
-                for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
-                    var parsedParticleSystem = parsedData.particleSystems[index];
-
-                    if (parsedParticleSystem.activeParticleCount) {
-                        let ps = GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
-                        container.particleSystems.push(ps);
-                    } else {
-                        let ps = ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
-                        container.particleSystems.push(ps);
-                    }
-                }
-            }
-
             // Shadows
             if (parsedData.shadowGenerators !== undefined && parsedData.shadowGenerators !== null) {
                 for (index = 0, cache = parsedData.shadowGenerators.length; index < cache; index++) {
@@ -384,7 +369,7 @@
 
             return false;
         },
-        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], onError?: (message: string, exception?: any) => void): boolean => {
+        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], onError?: (message: string, exception?: any) => void): boolean => {
             // Entire method running in try block, so ALWAYS logs as far as it got, only actually writes details
             // when SceneLoader.debugLogging = true (default), or exception encountered.
             // Everything stored in var log instead of writing separate lines to support only writing in exception,
@@ -555,10 +540,13 @@
 
                 // Particles
                 if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
-                    for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
-                        var parsedParticleSystem = parsedData.particleSystems[index];
-                        if (hierarchyIds.indexOf(parsedParticleSystem.emitterId) !== -1) {
-                            particleSystems.push(ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl));
+                    let parser = AbstractScene.GetIndividualParser(SceneComponentConstants.NAME_PARTICLESYSTEM);
+                    if (parser) {
+                        for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
+                            var parsedParticleSystem = parsedData.particleSystems[index];
+                            if (hierarchyIds.indexOf(parsedParticleSystem.emitterId) !== -1) {
+                                particleSystems.push(parser(parsedParticleSystem, scene, rootUrl));
+                            }
                         }
                     }
                 }

File diff suppressed because it is too large
+ 6 - 6
src/Loading/babylon.sceneLoader.ts


+ 2 - 2
src/Mesh/babylon.mesh.ts

@@ -1426,7 +1426,7 @@
         }
 
         /**
-         * Returns an array populated with ParticleSystem objects whose the mesh is the emitter. 
+         * Returns an array populated with IParticleSystem objects whose the mesh is the emitter. 
          */
         public getEmittedParticleSystems(): IParticleSystem[] {
             var results = new Array<IParticleSystem>();
@@ -1440,7 +1440,7 @@
         }
 
         /**
-         * Returns an array populated with ParticleSystem objects whose the mesh or its children are the emitter.
+         * Returns an array populated with IParticleSystem objects whose the mesh or its children are the emitter.
          */
         public getHierarchyEmittedParticleSystems(): IParticleSystem[] {
             var results = new Array<IParticleSystem>();

+ 1 - 1
src/Particles/babylon.IParticleSystem.ts

@@ -1,6 +1,6 @@
 module BABYLON {
     /**
-     * Interface representing a particle system in Babylon.
+     * Interface representing a particle system in Babylon.js.
      * This groups the common functionalities that needs to be implemented in order to create a particle system.
      * A particle system represents a way to manage particles from their emission to their animation and rendering.
      */

+ 1 - 1
src/Particles/babylon.particleHelper.ts

@@ -48,7 +48,7 @@ module BABYLON {
          * Please note that the emitter shape is not exported
          * @param system defines the particle systems to export
          */
-        public static ExportSet(systems: ParticleSystem[]): ParticleSystemSet {
+        public static ExportSet(systems: IParticleSystem[]): ParticleSystemSet {
             var set = new ParticleSystemSet();
 
             for (var system of systems) {

+ 70 - 0
src/Particles/babylon.particleSystemComponent.ts

@@ -0,0 +1,70 @@
+module BABYLON {
+    // Adds the parsers to the scene parsers.
+    AbstractScene.AddParser(SceneComponentConstants.NAME_PARTICLESYSTEM, (parsedData: any, scene: Scene, container: AssetContainer, rootUrl: string) => {
+
+        let individualParser = AbstractScene.GetIndividualParser(SceneComponentConstants.NAME_PARTICLESYSTEM); 
+
+        if (!individualParser) {
+            return;
+        }
+
+        // Particles Systems
+        if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
+            for (var index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
+                var parsedParticleSystem = parsedData.particleSystems[index];
+                container.particleSystems.push(individualParser(parsedParticleSystem, scene, rootUrl));
+            }
+        }
+    });
+
+    AbstractScene.AddIndividualParser(SceneComponentConstants.NAME_PARTICLESYSTEM, (parsedParticleSystem: any, scene: Scene, rootUrl: string) => {
+        if (parsedParticleSystem.activeParticleCount) {
+            let ps = GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+            return ps;
+        } else {
+            let ps = ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
+            return ps;
+        }
+    });
+
+    export interface Engine {
+        /**
+         * Create an effect to use with particle systems.
+         * Please note that some parameters like animation sheets or not being billboard are not supported in this configuration
+         * @param fragmentName defines the base name of the effect (The name of file without .fragment.fx)
+         * @param uniformsNames defines a list of attribute names 
+         * @param samplers defines an array of string used to represent textures
+         * @param defines defines the string containing the defines to use to compile the shaders
+         * @param fallbacks defines the list of potential fallbacks to use if shader conmpilation fails
+         * @param onCompiled defines a function to call when the effect creation is successful
+         * @param onError defines a function to call when the effect creation has failed
+         * @returns the new Effect
+         */
+        createEffectForParticles(fragmentName: string, uniformsNames: string[], samplers: string[], defines: string, fallbacks?: EffectFallbacks,
+            onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void): Effect
+    }
+
+    Engine.prototype.createEffectForParticles = function(fragmentName: string, uniformsNames: string[] = [], samplers: string[] = [], defines = "", fallbacks?: EffectFallbacks,
+        onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void): Effect {
+
+        var attributesNamesOrOptions = ParticleSystem._GetAttributeNamesOrOptions();
+        var effectCreationOption = ParticleSystem._GetEffectCreationOptions();
+
+        if (defines.indexOf(" BILLBOARD") === -1) {
+            defines += "\n#define BILLBOARD\n";
+        }
+
+        if (samplers.indexOf("diffuseSampler") === -1) {
+            samplers.push("diffuseSampler");
+        }
+
+        return this.createEffect(
+            {
+                vertex: "particles",
+                fragmentElement: fragmentName
+            },
+            attributesNamesOrOptions,
+            effectCreationOption.concat(uniformsNames),
+            samplers, defines, fallbacks, onCompiled, onError);
+    }
+} 

+ 2 - 2
src/Tools/babylon.assetsManager.ts

@@ -210,7 +210,7 @@ module BABYLON {
         /**
          * Gets the list of loaded particle systems
          */
-        public loadedParticleSystems: Array<ParticleSystem>;
+        public loadedParticleSystems: Array<IParticleSystem>;
         /**
          * Gets the list of loaded skeletons
          */
@@ -261,7 +261,7 @@ module BABYLON {
          */
         public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
             SceneLoader.ImportMesh(this.meshesNames, this.rootUrl, this.sceneFilename, scene,
-                (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => {
+                (meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[]) => {
                     this.loadedMeshes = meshes;
                     this.loadedParticleSystems = particleSystems;
                     this.loadedSkeletons = skeletons;

+ 49 - 2
src/babylon.abstractScene.ts

@@ -1,13 +1,20 @@
 module BABYLON {
     /**
      * Defines how the parser contract is defined.
+     * These parsers are used to parse a list of specific assets (like particle systems, etc..)
      */
     export type BabylonFileParser = (parsedData: any, scene: Scene, container: AssetContainer, rootUrl: string) => void;
 
     /**
+     * Defines how the individual parser contract is defined.
+     * These parser can parse an individual asset
+     */
+    export type IndividualBabylonFileParser = (parsedData: any, scene: Scene, rootUrl: string) => any;
+
+    /**
      * Base class of the scene acting as a container for the different elements composing a scene.
      * This class is dynamically extended by the different components of the scene increasing 
-     * flexibility and reducing coupling.
+     * flexibility and reducing coupling
      */
     export abstract class AbstractScene {
         /**
@@ -16,7 +23,12 @@
         private static _BabylonFileParsers: { [key: string]: BabylonFileParser } = { };
 
         /**
-         * Adds a parser in the list of availables ones.
+         * Stores the list of available individual parsers in the application.
+         */
+        private static _IndividualBabylonFileParsers: { [key: string]: IndividualBabylonFileParser } = { };
+
+        /**
+         * Adds a parser in the list of available ones
          * @param name Defines the name of the parser
          * @param parser Defines the parser to add
          */
@@ -25,6 +37,41 @@
         }
 
         /**
+         * Gets a general parser from the list of avaialble ones
+         * @param name Defines the name of the parser
+         * @returns the requested parser or null
+         */
+        public static GetParser(name: string): Nullable<BabylonFileParser> {
+            if (this._BabylonFileParsers[name]) {
+                return this._BabylonFileParsers[name];
+            }
+
+            return null;
+        }
+
+        /**
+         * Adds n individual parser in the list of available ones
+         * @param name Defines the name of the parser
+         * @param parser Defines the parser to add
+         */
+        public static AddIndividualParser(name: string, parser: IndividualBabylonFileParser): void {
+            this._IndividualBabylonFileParsers[name] = parser;
+        }
+
+        /**
+         * Gets an individual parser from the list of avaialble ones
+         * @param name Defines the name of the parser
+         * @returns the requested parser or null
+         */
+        public static GetIndividualParser(name: string): Nullable<IndividualBabylonFileParser> {
+            if (this._IndividualBabylonFileParsers[name]) {
+                return this._IndividualBabylonFileParsers[name];
+            }
+
+            return null;
+        }        
+
+        /**
          * Parser json data and populate both a scene and its associated container object
          * @param jsonData Defines the data to parse
          * @param scene Defines the scene to parse the data for

+ 0 - 6
src/babylon.assetContainer.ts

@@ -38,9 +38,6 @@ module BABYLON {
             this.skeletons.forEach((o) => {
                 this.scene.addSkeleton(o);
             });
-            this.particleSystems.forEach((o) => {
-                this.scene.addParticleSystem(o);
-            });
             this.animations.forEach((o) => {
                 this.scene.addAnimation(o);
             });
@@ -95,9 +92,6 @@ module BABYLON {
             this.skeletons.forEach((o) => {
                 this.scene.removeSkeleton(o);
             });
-            this.particleSystems.forEach((o) => {
-                this.scene.removeParticleSystem(o);
-            });
             this.animations.forEach((o) => {
                 this.scene.removeAnimation(o);
             });

+ 1 - 0
src/babylon.sceneComponent.ts

@@ -8,6 +8,7 @@
         public static readonly NAME_LAYER = "Layer";
         public static readonly NAME_LENSFLARESYSTEM = "LensFlareSystem";
         public static readonly NAME_BOUNDINGBOXRENDERER = "BoundingBoxRenderer";
+        public static readonly NAME_PARTICLESYSTEM = "ParticleSystem";
 
         public static readonly STEP_ISREADYFORMESH_EFFECTLAYER = 0;