Browse Source

merged with master

Benjamin Guignabert 8 years ago
parent
commit
5593261ba5
67 changed files with 4046 additions and 1361 deletions
  1. 2 1
      .vscode/settings.json
  2. 2 0
      Playground/debug.html
  3. 2 0
      Playground/frame.html
  4. 2 0
      Playground/index.html
  5. 15 1
      Tools/Gulp/config.json
  6. BIN
      assets/meshes/0.jpg
  7. 1 0
      assets/meshes/Rabbit.babylon.manifest
  8. 262 48
      dist/preview release/babylon.d.ts
  9. 42 1
      dist/preview release/babylon.js
  10. 136 42
      dist/preview release/babylon.max.js
  11. 912 906
      dist/preview release/babylon.module.d.ts
  12. 41 0
      dist/preview release/babylon.worker.js
  13. 1 1
      dist/preview release/canvas2D/babylon.canvas2d.js
  14. 11 11
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  15. 60 2
      dist/preview release/gui/babylon.gui.d.ts
  16. 319 18
      dist/preview release/gui/babylon.gui.js
  17. 1 1
      dist/preview release/gui/babylon.gui.min.js
  18. 252 114
      dist/preview release/inspector/babylon.inspector.bundle.js
  19. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  20. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  21. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  22. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  23. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  24. 28 0
      dist/preview release/materialsLibrary/babylon.cellMaterial.d.ts
  25. 276 0
      dist/preview release/materialsLibrary/babylon.cellMaterial.js
  26. 1 0
      dist/preview release/materialsLibrary/babylon.cellMaterial.min.js
  27. 13 13
      dist/preview release/materialsLibrary/babylon.customMaterial.d.ts
  28. 39 39
      dist/preview release/materialsLibrary/babylon.customMaterial.js
  29. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  30. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  31. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  32. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  33. 2 0
      dist/preview release/what's new.md
  34. 1 5
      gui/readme.md
  35. 54 8
      gui/src/advancedDynamicTexture.ts
  36. 39 1
      gui/src/controls/button.ts
  37. 24 4
      gui/src/controls/container.ts
  38. 265 22
      gui/src/controls/control.ts
  39. 79 0
      gui/src/controls/ellipse.ts
  40. 1 1
      gui/src/controls/image.ts
  41. 164 0
      gui/src/controls/line.ts
  42. 25 0
      gui/src/controls/stackPanel.ts
  43. 1 1
      gui/src/controls/textBlock.ts
  44. 114 0
      gui/src/math2D.ts
  45. 15 0
      loaders/src/glTF/README.md
  46. 8 2
      materialsLibrary/index.html
  47. 296 0
      materialsLibrary/src/cell/babylon.cellMaterial.ts
  48. 144 0
      materialsLibrary/src/cell/cell.fragment.fx
  49. 101 0
      materialsLibrary/src/cell/cell.vertex.fx
  50. 47 47
      materialsLibrary/src/custom/babylon.customMaterial.ts
  51. 3 3
      materialsLibrary/src/custom/readme.md
  52. 1 1
      materialsLibrary/src/fur/readme.md
  53. 22 0
      materialsLibrary/test/addCell.js
  54. 1 1
      materialsLibrary/test/addfur.js
  55. 1 1
      materialsLibrary/test/addterrain.js
  56. 14 4
      src/Audio/babylon.audioEngine.ts
  57. 0 10
      src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts
  58. 8 2
      src/Lights/babylon.light.ts
  59. 5 5
      src/Materials/babylon.material.ts
  60. 2 2
      src/Materials/babylon.pbrMaterial.ts
  61. 2 2
      src/Materials/babylon.standardMaterial.ts
  62. 24 16
      src/Mesh/babylon.geometry.ts
  63. 3 3
      src/Mesh/babylon.mesh.ts
  64. 86 8
      src/PostProcess/babylon.standardRenderingPipeline.ts
  65. 6 1
      src/Shaders/ShadersInclude/lightFragment.fx
  66. 17 0
      src/Shaders/ShadersInclude/lightsFragmentFunctions.fx
  67. 40 0
      src/Shaders/standard.fragment.fx

+ 2 - 1
.vscode/settings.json

@@ -32,7 +32,8 @@
         "**/*.js": { 
              "when":"$(basename).ts"
          },
-        "**/*.d.ts": true
+        "**/*.d.ts": true,
+        "assets":true
     },
     "typescript.check.workspaceVersion": false
 }

+ 2 - 0
Playground/debug.html

@@ -33,6 +33,8 @@
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
 
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>

+ 2 - 0
Playground/frame.html

@@ -22,6 +22,8 @@
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
 
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>

+ 2 - 0
Playground/index.html

@@ -33,6 +33,8 @@
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
+    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
 
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
     <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>

+ 15 - 1
Tools/Gulp/config.json

@@ -1055,6 +1055,16 @@
                     "../../materialsLibrary/src/custom/babylon.customMaterial.ts"
                 ], 
                 "output": "babylon.customMaterial.js"
+            },
+            {
+                "files": [
+                    "../../materialsLibrary/src/cell/babylon.cellMaterial.ts"
+                ],
+                "shaderFiles": [
+                    "../../materialsLibrary/src/cell/cell.vertex.fx",
+                    "../../materialsLibrary/src/cell/cell.fragment.fx"
+                ],
+                "output": "babylon.cellMaterial.js"
             }
         ],
         "build": {
@@ -1257,10 +1267,14 @@
                 "files": [
                     "../../gui/src/advancedDynamicTexture.ts",
                     "../../gui/src/measure.ts",
+                    "../../gui/src/math2D.ts",
                     "../../gui/src/valueAndUnit.ts",
                     "../../gui/src/controls/control.ts",
                     "../../gui/src/controls/container.ts",
+                    "../../gui/src/controls/stackPanel.ts",
                     "../../gui/src/controls/rectangle.ts",
+                    "../../gui/src/controls/ellipse.ts",
+                    "../../gui/src/controls/line.ts",
                     "../../gui/src/controls/textBlock.ts",
                     "../../gui/src/controls/image.ts",
                     "../../gui/src/controls/button.ts"
@@ -1278,7 +1292,7 @@
             {
                 "files": [
                     "../../canvas2D/src/Tools/babylon.math2D.ts",
-                    "../../canvas2D/src/Tools/babylon.iPropertyChanged.ts",
+                    "../../canvas2D/src/Tools/babylon.IPropertyChanged.ts",
                     "../../canvas2D/src/Tools/babylon.c2dlogging.ts",
                     "../../canvas2D/src/Tools/babylon.observableArray.ts",
                     "../../canvas2D/src/Tools/babylon.observableStringDictionary.ts",

BIN
assets/meshes/0.jpg


+ 1 - 0
assets/meshes/Rabbit.babylon.manifest

@@ -0,0 +1 @@
+{"version" : 1,    "enableSceneOffline" : true,    "enableTexturesOffline" : true}

+ 262 - 48
dist/preview release/babylon.d.ts

@@ -5040,6 +5040,259 @@ declare module BABYLON.Debug {
 }
 
 declare module BABYLON {
+    }
+}
+
+declare module BABYLON {
+    var CollisionWorker: string;
+    interface ICollisionCoordinator {
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): any;
+        onMeshUpdated(mesh: AbstractMesh): any;
+        onMeshRemoved(mesh: AbstractMesh): any;
+        onGeometryAdded(geometry: Geometry): any;
+        onGeometryUpdated(geometry: Geometry): any;
+        onGeometryDeleted(geometry: Geometry): any;
+    }
+    interface SerializedMesh {
+        id: string;
+        name: string;
+        uniqueId: number;
+        geometryId: string;
+        sphereCenter: Array<number>;
+        sphereRadius: number;
+        boxMinimum: Array<number>;
+        boxMaximum: Array<number>;
+        worldMatrixFromCache: any;
+        subMeshes: Array<SerializedSubMesh>;
+        checkCollisions: boolean;
+    }
+    interface SerializedSubMesh {
+        position: number;
+        verticesStart: number;
+        verticesCount: number;
+        indexStart: number;
+        indexCount: number;
+        hasMaterial: boolean;
+        sphereCenter: Array<number>;
+        sphereRadius: number;
+        boxMinimum: Array<number>;
+        boxMaximum: Array<number>;
+    }
+    interface SerializedGeometry {
+        id: string;
+        positions: Float32Array;
+        indices: Uint32Array;
+        normals: Float32Array;
+    }
+    interface BabylonMessage {
+        taskType: WorkerTaskType;
+        payload: InitPayload | CollidePayload | UpdatePayload;
+    }
+    interface SerializedColliderToWorker {
+        position: Array<number>;
+        velocity: Array<number>;
+        radius: Array<number>;
+    }
+    enum WorkerTaskType {
+        INIT = 0,
+        UPDATE = 1,
+        COLLIDE = 2,
+    }
+    interface WorkerReply {
+        error: WorkerReplyType;
+        taskType: WorkerTaskType;
+        payload?: any;
+    }
+    interface CollisionReplyPayload {
+        newPosition: Array<number>;
+        collisionId: number;
+        collidedMeshUniqueId: number;
+    }
+    interface InitPayload {
+    }
+    interface CollidePayload {
+        collisionId: number;
+        collider: SerializedColliderToWorker;
+        maximumRetry: number;
+        excludedMeshUniqueId?: number;
+    }
+    interface UpdatePayload {
+        updatedMeshes: {
+            [n: number]: SerializedMesh;
+        };
+        updatedGeometries: {
+            [s: string]: SerializedGeometry;
+        };
+        removedMeshes: Array<number>;
+        removedGeometries: Array<string>;
+    }
+    enum WorkerReplyType {
+        SUCCESS = 0,
+        UNKNOWN_ERROR = 1,
+    }
+    class CollisionCoordinatorWorker implements ICollisionCoordinator {
+        private _scene;
+        private _scaledPosition;
+        private _scaledVelocity;
+        private _collisionsCallbackArray;
+        private _init;
+        private _runningUpdated;
+        private _runningCollisionTask;
+        private _worker;
+        private _addUpdateMeshesList;
+        private _addUpdateGeometriesList;
+        private _toRemoveMeshesArray;
+        private _toRemoveGeometryArray;
+        constructor();
+        static SerializeMesh: (mesh: AbstractMesh) => SerializedMesh;
+        static SerializeGeometry: (geometry: Geometry) => SerializedGeometry;
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): void;
+        onMeshUpdated: (mesh: AbstractMesh) => void;
+        onMeshRemoved(mesh: AbstractMesh): void;
+        onGeometryAdded(geometry: Geometry): void;
+        onGeometryUpdated: (geometry: Geometry) => void;
+        onGeometryDeleted(geometry: Geometry): void;
+        private _afterRender;
+        private _onMessageFromWorker;
+    }
+    class CollisionCoordinatorLegacy implements ICollisionCoordinator {
+        private _scene;
+        private _scaledPosition;
+        private _scaledVelocity;
+        private _finalPosition;
+        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        init(scene: Scene): void;
+        destroy(): void;
+        onMeshAdded(mesh: AbstractMesh): void;
+        onMeshUpdated(mesh: AbstractMesh): void;
+        onMeshRemoved(mesh: AbstractMesh): void;
+        onGeometryAdded(geometry: Geometry): void;
+        onGeometryUpdated(geometry: Geometry): void;
+        onGeometryDeleted(geometry: Geometry): void;
+        private _collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh?);
+    }
+}
+
+declare module BABYLON {
+    var WorkerIncluded: boolean;
+    class CollisionCache {
+        private _meshes;
+        private _geometries;
+        getMeshes(): {
+            [n: number]: SerializedMesh;
+        };
+        getGeometries(): {
+            [s: number]: SerializedGeometry;
+        };
+        getMesh(id: any): SerializedMesh;
+        addMesh(mesh: SerializedMesh): void;
+        removeMesh(uniqueId: number): void;
+        getGeometry(id: string): SerializedGeometry;
+        addGeometry(geometry: SerializedGeometry): void;
+        removeGeometry(id: string): void;
+    }
+    class CollideWorker {
+        collider: Collider;
+        private _collisionCache;
+        private finalPosition;
+        private collisionsScalingMatrix;
+        private collisionTranformationMatrix;
+        constructor(collider: Collider, _collisionCache: CollisionCache, finalPosition: Vector3);
+        collideWithWorld(position: Vector3, velocity: Vector3, maximumRetry: number, excludedMeshUniqueId?: number): void;
+        private checkCollision(mesh);
+        private processCollisionsForSubMeshes(transformMatrix, mesh);
+        private collideForSubMesh(subMesh, transformMatrix, meshGeometry);
+        private checkSubmeshCollision(subMesh);
+    }
+    interface ICollisionDetector {
+        onInit(payload: InitPayload): void;
+        onUpdate(payload: UpdatePayload): void;
+        onCollision(payload: CollidePayload): void;
+    }
+    class CollisionDetectorTransferable implements ICollisionDetector {
+        private _collisionCache;
+        onInit(payload: InitPayload): void;
+        onUpdate(payload: UpdatePayload): void;
+        onCollision(payload: CollidePayload): void;
+    }
+}
+
+declare module BABYLON {
+    class IntersectionInfo {
+        bu: number;
+        bv: number;
+        distance: number;
+        faceId: number;
+        subMeshId: number;
+        constructor(bu: number, bv: number, distance: number);
+    }
+    class PickingInfo {
+        hit: boolean;
+        distance: number;
+        pickedPoint: Vector3;
+        pickedMesh: AbstractMesh;
+        bu: number;
+        bv: number;
+        faceId: number;
+        subMeshId: number;
+        pickedSprite: Sprite;
+        getNormal(useWorldCoordinates?: boolean, useVerticesNormals?: boolean): Vector3;
+        getTextureCoordinates(): Vector2;
+    }
+}
+
+declare module BABYLON {
+    class LensFlare {
+        size: number;
+        position: number;
+        color: Color3;
+        texture: Texture;
+        alphaMode: number;
+        private _system;
+        constructor(size: number, position: number, color: any, imgUrl: string, system: LensFlareSystem);
+        dispose: () => void;
+    }
+}
+
+declare module BABYLON {
+    class LensFlareSystem {
+        name: string;
+        lensFlares: LensFlare[];
+        borderLimit: number;
+        viewportBorder: number;
+        meshesSelectionPredicate: (mesh: Mesh) => boolean;
+        layerMask: number;
+        id: string;
+        private _scene;
+        private _emitter;
+        private _vertexBuffers;
+        private _indexBuffer;
+        private _effect;
+        private _positionX;
+        private _positionY;
+        private _isEnabled;
+        constructor(name: string, emitter: any, scene: Scene);
+        isEnabled: boolean;
+        getScene(): Scene;
+        getEmitter(): any;
+        setEmitter(newEmitter: any): void;
+        getEmitterPosition(): Vector3;
+        computeEffectivePosition(globalViewport: Viewport): boolean;
+        _isVisible(): boolean;
+        render(): boolean;
+        dispose(): void;
+        static Parse(parsedLensFlareSystem: any, scene: Scene, rootUrl: string): LensFlareSystem;
+        serialize(): any;
+    }
+}
+
+declare module BABYLON {
     class BoundingBox implements ICullable {
         minimum: Vector3;
         maximum: Vector3;
@@ -5154,51 +5407,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class LensFlare {
-        size: number;
-        position: number;
-        color: Color3;
-        texture: Texture;
-        alphaMode: number;
-        private _system;
-        constructor(size: number, position: number, color: any, imgUrl: string, system: LensFlareSystem);
-        dispose: () => void;
-    }
-}
-
-declare module BABYLON {
-    class LensFlareSystem {
-        name: string;
-        lensFlares: LensFlare[];
-        borderLimit: number;
-        viewportBorder: number;
-        meshesSelectionPredicate: (mesh: Mesh) => boolean;
-        layerMask: number;
-        id: string;
-        private _scene;
-        private _emitter;
-        private _vertexBuffers;
-        private _indexBuffer;
-        private _effect;
-        private _positionX;
-        private _positionY;
-        private _isEnabled;
-        constructor(name: string, emitter: any, scene: Scene);
-        isEnabled: boolean;
-        getScene(): Scene;
-        getEmitter(): any;
-        setEmitter(newEmitter: any): void;
-        getEmitterPosition(): Vector3;
-        computeEffectivePosition(globalViewport: Viewport): boolean;
-        _isVisible(): boolean;
-        render(): boolean;
-        dispose(): void;
-        static Parse(parsedLensFlareSystem: any, scene: Scene, rootUrl: string): LensFlareSystem;
-        serialize(): any;
-    }
-}
-
-declare module BABYLON {
     /**
      * Highlight layer options. This helps customizing the behaviour
      * of the highlight layer.
@@ -10196,6 +10404,7 @@ declare module BABYLON {
         dispose(): void;
         copy(id: string): Geometry;
         serialize(): any;
+        private toNumberArray(origin);
         serializeVerticeData(): any;
         static ExtractFromMesh(mesh: Mesh, id: string): Geometry;
         /**
@@ -14056,6 +14265,7 @@ declare module BABYLON {
         hdrFinalPostProcess: PostProcess;
         lensFlarePostProcess: PostProcess;
         lensFlareComposePostProcess: PostProcess;
+        motionBlurPostProcess: PostProcess;
         depthOfFieldPostProcess: PostProcess;
         brightThreshold: number;
         blurWidth: number;
@@ -14077,6 +14287,7 @@ declare module BABYLON {
         lensFlareDirtTexture: Texture;
         depthOfFieldDistance: number;
         depthOfFieldBlurWidth: number;
+        motionStrength: number;
         animations: Animation[];
         /**
         * Private members
@@ -14086,12 +14297,16 @@ declare module BABYLON {
         private _currentDepthOfFieldSource;
         private _currentHDRSource;
         private _hdrCurrentLuminance;
+        private _motionBlurSamples;
         private _depthOfFieldEnabled;
         private _lensFlareEnabled;
         private _hdrEnabled;
+        private _motionBlurEnabled;
         DepthOfFieldEnabled: boolean;
         LensFlareEnabled: boolean;
         HDREnabled: boolean;
+        MotionBlurEnabled: boolean;
+        motionBlurSamples: number;
         /**
          * @constructor
          * @param {string} name - The rendering pipeline name
@@ -14105,10 +14320,11 @@ declare module BABYLON {
         private _createBrightPassPostProcess(scene, ratio);
         private _createGaussianBlurPostProcesses(scene, ratio, indice, blurWidthKey?);
         private _createTextureAdderPostProcess(scene, ratio);
-        private _createLuminancePostProcesses(scene);
+        private _createLuminancePostProcesses(scene, textureType);
         private _createHdrPostProcess(scene, ratio);
         private _createLensFlarePostProcess(scene, ratio);
         private _createDepthOfFieldPostProcess(scene, ratio);
+        private _createMotionBlurPostProcess(scene, ratio);
         dispose(): void;
         serialize(): any;
         static Parse(source: any, scene: Scene, rootUrl: string): StandardRenderingPipeline;
@@ -16173,8 +16389,6 @@ declare module BABYLON {
         pinchInwards: boolean;
         private _pointerInput;
         private _observer;
-        private _onKeyDown;
-        private _onKeyUp;
         private _onMouseMove;
         private _onGestureStart;
         private _onGesture;

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


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


File diff suppressed because it is too large
+ 912 - 906
dist/preview release/babylon.module.d.ts


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


+ 1 - 1
dist/preview release/canvas2D/babylon.canvas2d.js

@@ -604,7 +604,7 @@ var BABYLON;
     BABYLON.PropertyChangedBase = PropertyChangedBase;
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=babylon.iPropertyChanged.js.map
+//# sourceMappingURL=babylon.IPropertyChanged.js.map
 
 var BABYLON;
 (function (BABYLON) {

File diff suppressed because it is too large
+ 11 - 11
dist/preview release/canvas2D/babylon.canvas2d.min.js


+ 60 - 2
dist/preview release/gui/babylon.gui.d.ts

@@ -8,6 +8,9 @@ declare module BABYLON.GUI {
         private _background;
         private _rootContainer;
         _lastControlOver: Control;
+        _lastControlDown: Control;
+        _shouldBlockPointer: boolean;
+        _toDispose: IDisposable;
         background: string;
         constructor(name: string, width: number, height: number, scene: Scene, generateMipMaps?: boolean, samplingMode?: number);
         markAsDirty(): void;
@@ -40,6 +43,27 @@ declare module BABYLON.GUI {
 
 /// <reference path="../../dist/preview release/babylon.d.ts" />
 declare module BABYLON.GUI {
+    class Matrix2D {
+        m: Float32Array;
+        constructor(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number);
+        fromValues(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number): Matrix2D;
+        determinant(): number;
+        invertToRef(result: Matrix2D): Matrix2D;
+        multiplyToRef(other: Matrix2D, result: Matrix2D): Matrix2D;
+        static Identity(): Matrix2D;
+        static TranslationToRef(x: number, y: number, result: Matrix2D): void;
+        static ScalingToRef(x: number, y: number, result: Matrix2D): void;
+        static RotationToRef(angle: number, result: Matrix2D): void;
+        private static _TempPreTranslationMatrix;
+        private static _TempPostTranslationMatrix;
+        private static _TempRotationMatrix;
+        private static _TempScalingMatrix;
+        static ComposeToRef(tx: number, ty: number, angle: number, scaleX: number, scaleY: number, parentMatrix: Matrix2D, result: Matrix2D): void;
+    }
+}
+
+/// <reference path="../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
     class ValueAndUnit {
         value: number;
         unit: number;
@@ -87,6 +111,18 @@ declare module BABYLON.GUI {
         private _marginBottom;
         private _left;
         private _top;
+        private _scaleX;
+        private _scaleY;
+        private _rotation;
+        private _transformCenterX;
+        private _transformCenterY;
+        private _transformMatrix;
+        private _invertTransformMatrix;
+        private _isMatrixDirty;
+        private _cachedOffsetX;
+        private _cachedOffsetY;
+        isHitTestVisible: boolean;
+        isPointerBlocker: boolean;
         /**
         * An event triggered when the pointer move over the control.
         * @type {BABYLON.Observable}
@@ -107,6 +143,16 @@ declare module BABYLON.GUI {
         * @type {BABYLON.Observable}
         */
         onPointerUpObservable: Observable<Control>;
+        /**
+        * An event triggered when pointer enters the control
+        * @type {BABYLON.Observable}
+        */
+        onPointerEnterObservable: Observable<Control>;
+        scaleX: number;
+        scaleY: number;
+        rotation: number;
+        transformCenterY: number;
+        transformCenterX: number;
         horizontalAlignment: number;
         verticalAlignment: number;
         width: string;
@@ -125,15 +171,21 @@ declare module BABYLON.GUI {
         constructor(name: string);
         protected _markAsDirty(): void;
         _link(root: Container, host: AdvancedDynamicTexture): void;
-        protected applyStates(context: CanvasRenderingContext2D): void;
+        protected _transform(context: CanvasRenderingContext2D): void;
+        protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _clip(context: CanvasRenderingContext2D): void;
         protected _measure(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        protected _contains(x: number, y: number): boolean;
+        contains(x: number, y: number): boolean;
         _processPicking(x: number, y: number, type: number): boolean;
+        protected _onPointerMove(): void;
+        protected _onPointerEnter(): void;
+        protected _onPointerOut(): void;
+        protected _onPointerDown(): void;
+        protected _onPointerUp(): void;
         protected _processObservables(type: number): boolean;
         private _prepareFont();
         private static _HORIZONTAL_ALIGNMENT_LEFT;
@@ -168,6 +220,7 @@ declare module BABYLON.GUI {
         removeControl(control: Control): Container;
         _reOrderControl(control: Control): void;
         protected _localDraw(context: CanvasRenderingContext2D): void;
+        _link(root: Container, host: AdvancedDynamicTexture): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _processPicking(x: number, y: number, type: number): boolean;
         protected _clipForChildren(context: CanvasRenderingContext2D): void;
@@ -244,6 +297,11 @@ declare module BABYLON.GUI {
         name: string;
         constructor(name: string);
         _processPicking(x: number, y: number, type: number): boolean;
+        protected _onPointerEnter(): void;
+        protected _onPointerOut(): void;
+        protected _onPointerDown(): void;
+        protected _onPointerUp(): void;
         static CreateImageButton(name: string, text: string, imageUrl: string): Button;
+        static CreateSimpleButton(name: string, text: string): Button;
     }
 }

+ 319 - 18
dist/preview release/gui/babylon.gui.js

@@ -63,7 +63,11 @@ var BABYLON;
                     this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
                 }
                 if (this._pointerMoveObserver) {
-                    this.getScene().onPointerObservable.remove(this._pointerMoveObserver);
+                    this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
+                }
+                if (this._toDispose) {
+                    this._toDispose.dispose();
+                    this._toDispose = null;
                 }
                 _super.prototype.dispose.call(this);
             };
@@ -116,13 +120,15 @@ var BABYLON;
             AdvancedDynamicTexture.prototype.attach = function () {
                 var _this = this;
                 var scene = this.getScene();
-                this._pointerMoveObserver = scene.onPointerObservable.add(function (pi, state) {
+                this._pointerMoveObserver = scene.onPrePointerObservable.add(function (pi, state) {
                     if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE
                         && pi.type !== BABYLON.PointerEventTypes.POINTERUP
                         && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
                         return;
                     }
+                    _this._shouldBlockPointer = false;
                     _this._doPicking(scene.pointerX, scene.pointerY, pi.type);
+                    pi.skipOnPointerObservable = _this._shouldBlockPointer;
                 });
             };
             // Statics
@@ -143,6 +149,7 @@ var BABYLON;
                 // Display
                 var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
                 layer.texture = result;
+                result._toDispose = layer;
                 // Attach
                 result.attach();
                 return result;
@@ -204,6 +211,104 @@ var BABYLON;
 (function (BABYLON) {
     var GUI;
     (function (GUI) {
+        var Matrix2D = (function () {
+            function Matrix2D(m00, m01, m10, m11, m20, m21) {
+                this.m = new Float32Array(6);
+                this.fromValues(m00, m01, m10, m11, m20, m21);
+            }
+            Matrix2D.prototype.fromValues = function (m00, m01, m10, m11, m20, m21) {
+                this.m[0] = m00;
+                this.m[1] = m01;
+                this.m[2] = m10;
+                this.m[3] = m11;
+                this.m[4] = m20;
+                this.m[5] = m21;
+                return this;
+            };
+            Matrix2D.prototype.determinant = function () {
+                return this.m[0] * this.m[3] - this.m[1] * this.m[2];
+            };
+            Matrix2D.prototype.invertToRef = function (result) {
+                var l0 = this.m[0];
+                var l1 = this.m[1];
+                var l2 = this.m[2];
+                var l3 = this.m[3];
+                var l4 = this.m[4];
+                var l5 = this.m[5];
+                var det = this.determinant();
+                if (det < (BABYLON.Epsilon * BABYLON.Epsilon)) {
+                    throw new Error("Can't invert matrix, near null determinant");
+                }
+                var detDiv = 1 / det;
+                var det4 = l2 * l5 - l3 * l4;
+                var det5 = l1 * l4 - l0 * l5;
+                result.m[0] = l3 * detDiv;
+                result.m[1] = -l1 * detDiv;
+                result.m[2] = -l2 * detDiv;
+                result.m[3] = l0 * detDiv;
+                result.m[4] = det4 * detDiv;
+                result.m[5] = det5 * detDiv;
+                return this;
+            };
+            Matrix2D.prototype.multiplyToRef = function (other, result) {
+                var l0 = this.m[0];
+                var l1 = this.m[1];
+                var l2 = this.m[2];
+                var l3 = this.m[3];
+                var l4 = this.m[4];
+                var l5 = this.m[5];
+                var r0 = other.m[0];
+                var r1 = other.m[1];
+                var r2 = other.m[2];
+                var r3 = other.m[3];
+                var r4 = other.m[4];
+                var r5 = other.m[5];
+                result.m[0] = l0 * r0 + l1 * r2;
+                result.m[1] = l0 * r1 + l1 * r3;
+                result.m[2] = l2 * r0 + l3 * r2;
+                result.m[3] = l2 * r1 + l3 * r3;
+                result.m[4] = l4 * r0 + l5 * r2 + r4;
+                result.m[5] = l4 * r1 + l5 * r3 + r5;
+                return this;
+            };
+            // Statics
+            Matrix2D.Identity = function () {
+                return new Matrix2D(1, 0, 0, 1, 0, 0);
+            };
+            Matrix2D.TranslationToRef = function (x, y, result) {
+                result.fromValues(1, 0, 0, 1, x, y);
+            };
+            Matrix2D.ScalingToRef = function (x, y, result) {
+                result.fromValues(x, 0, 0, y, 0, 0);
+            };
+            Matrix2D.RotationToRef = function (angle, result) {
+                var s = Math.sin(angle);
+                var c = Math.cos(angle);
+                result.fromValues(c, s, -s, c, 0, 0);
+            };
+            Matrix2D.ComposeToRef = function (tx, ty, angle, scaleX, scaleY, parentMatrix, result) {
+                Matrix2D.TranslationToRef(tx, ty, Matrix2D._TempPreTranslationMatrix);
+                Matrix2D.ScalingToRef(scaleX, scaleY, Matrix2D._TempScalingMatrix);
+                Matrix2D.RotationToRef(angle, Matrix2D._TempRotationMatrix);
+                Matrix2D.TranslationToRef(-tx, -ty, Matrix2D._TempPostTranslationMatrix);
+            };
+            return Matrix2D;
+        }());
+        Matrix2D._TempPreTranslationMatrix = Matrix2D.Identity();
+        Matrix2D._TempPostTranslationMatrix = Matrix2D.Identity();
+        Matrix2D._TempRotationMatrix = Matrix2D.Identity();
+        Matrix2D._TempScalingMatrix = Matrix2D.Identity();
+        GUI.Matrix2D = Matrix2D;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=math2D.js.map
+
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
         var ValueAndUnit = (function () {
             function ValueAndUnit(value, unit, negativeValueAllowed) {
                 if (value === void 0) { value = 1; }
@@ -316,6 +421,16 @@ var BABYLON;
                 this._marginBottom = new GUI.ValueAndUnit(0);
                 this._left = new GUI.ValueAndUnit(0);
                 this._top = new GUI.ValueAndUnit(0);
+                this._scaleX = 1.0;
+                this._scaleY = 1.0;
+                this._rotation = 0;
+                this._transformCenterX = 0.5;
+                this._transformCenterY = 0.5;
+                this._transformMatrix = GUI.Matrix2D.Identity();
+                this._invertTransformMatrix = GUI.Matrix2D.Identity();
+                this._isMatrixDirty = true;
+                this.isHitTestVisible = true;
+                this.isPointerBlocker = false;
                 // Properties
                 /**
                 * An event triggered when the pointer move over the control.
@@ -337,8 +452,88 @@ var BABYLON;
                 * @type {BABYLON.Observable}
                 */
                 this.onPointerUpObservable = new BABYLON.Observable();
+                /**
+                * An event triggered when pointer enters the control
+                * @type {BABYLON.Observable}
+                */
+                this.onPointerEnterObservable = new BABYLON.Observable();
                 this.fontFamily = "Arial";
             }
+            Object.defineProperty(Control.prototype, "scaleX", {
+                get: function () {
+                    return this._scaleX;
+                },
+                set: function (value) {
+                    if (this._scaleX === value) {
+                        return;
+                    }
+                    this._scaleX = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Control.prototype, "scaleY", {
+                get: function () {
+                    return this._scaleY;
+                },
+                set: function (value) {
+                    if (this._scaleY === value) {
+                        return;
+                    }
+                    this._scaleY = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Control.prototype, "rotation", {
+                get: function () {
+                    return this._rotation;
+                },
+                set: function (value) {
+                    if (this._rotation === value) {
+                        return;
+                    }
+                    this._rotation = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Control.prototype, "transformCenterY", {
+                get: function () {
+                    return this._transformCenterY;
+                },
+                set: function (value) {
+                    if (this._transformCenterY === value) {
+                        return;
+                    }
+                    this._transformCenterY = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Control.prototype, "transformCenterX", {
+                get: function () {
+                    return this._transformCenterX;
+                },
+                set: function (value) {
+                    if (this._transformCenterX === value) {
+                        return;
+                    }
+                    this._transformCenterX = value;
+                    this._markAsDirty();
+                    this._isMatrixDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
             Object.defineProperty(Control.prototype, "horizontalAlignment", {
                 get: function () {
                     return this._horizontalAlignment;
@@ -543,7 +738,30 @@ var BABYLON;
                 this._root = root;
                 this._host = host;
             };
-            Control.prototype.applyStates = function (context) {
+            Control.prototype._transform = function (context) {
+                if (this._scaleX === 1 && this._scaleY === 1 && this._rotation === 0) {
+                    return;
+                }
+                // preTranslate
+                var offsetX = this._currentMeasure.width * this._transformCenterX + this._currentMeasure.left;
+                var offsetY = this._currentMeasure.height * this._transformCenterY + this._currentMeasure.top;
+                context.translate(offsetX, offsetY);
+                // scale
+                context.scale(this._scaleX, this._scaleY);
+                // rotate
+                context.rotate(this._rotation);
+                // postTranslate
+                context.translate(-offsetX, -offsetY);
+                // Need to update matrices?
+                if (this._isMatrixDirty || this._cachedOffsetX !== offsetX || this._cachedOffsetY !== offsetY) {
+                    this._cachedOffsetX = offsetX;
+                    this._cachedOffsetY = offsetY;
+                    this._isMatrixDirty = false;
+                    GUI.Matrix2D.ComposeToRef(offsetX, offsetY, this._rotation, this._scaleX, this._scaleY, this._root ? this._root._transformMatrix : null, this._transformMatrix);
+                    this._transformMatrix.invertToRef(this._invertTransformMatrix);
+                }
+            };
+            Control.prototype._applyStates = function (context) {
                 if (this._font) {
                     context.font = this._font;
                 }
@@ -566,6 +784,8 @@ var BABYLON;
                     this._isDirty = false;
                     this._cachedParentMeasure.copyFrom(parentMeasure);
                 }
+                // Transform
+                this._transform(context);
                 // Clip
                 this._clip(context);
                 context.clip();
@@ -668,7 +888,11 @@ var BABYLON;
             Control.prototype._draw = function (parentMeasure, context) {
                 // Do nothing
             };
-            Control.prototype._contains = function (x, y) {
+            Control.prototype.contains = function (x, y) {
+                // Invert transform
+                if (this._scaleX !== 1 || this._scaleY !== 1 || this.rotation !== 0) {
+                }
+                // Check
                 if (x < this._currentMeasure.left) {
                     return false;
                 }
@@ -681,31 +905,70 @@ var BABYLON;
                 if (y > this._currentMeasure.top + this._currentMeasure.height) {
                     return false;
                 }
+                if (this.isPointerBlocker) {
+                    this._host._shouldBlockPointer = true;
+                }
                 return true;
             };
             Control.prototype._processPicking = function (x, y, type) {
-                if (!this._contains(x, y)) {
+                if (!this.contains(x, y)) {
                     return false;
                 }
                 this._processObservables(type);
                 return true;
             };
-            Control.prototype._processObservables = function (type) {
-                if (type === BABYLON.PointerEventTypes.POINTERMOVE && this.onPointerMoveObservable.hasObservers()) {
+            Control.prototype._onPointerMove = function () {
+                if (this.onPointerMoveObservable.hasObservers()) {
                     this.onPointerMoveObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._onPointerEnter = function () {
+                if (this.onPointerEnterObservable.hasObservers()) {
+                    this.onPointerEnterObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._onPointerOut = function () {
+                if (this.onPointerOutObservable.hasObservers()) {
+                    this.onPointerOutObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._onPointerDown = function () {
+                if (this.onPointerDownObservable.hasObservers()) {
+                    this.onPointerDownObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._onPointerUp = function () {
+                if (this.onPointerUpObservable.hasObservers()) {
+                    this.onPointerUpObservable.notifyObservers(this);
+                }
+            };
+            Control.prototype._processObservables = function (type) {
+                if (!this.isHitTestVisible) {
+                    return false;
+                }
+                if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
+                    this._onPointerMove();
                     var previousControlOver = this._host._lastControlOver;
-                    if (previousControlOver && previousControlOver !== this && previousControlOver.onPointerOutObservable.hasObservers()) {
-                        previousControlOver.onPointerOutObservable.notifyObservers(previousControlOver);
+                    if (previousControlOver && previousControlOver !== this) {
+                        previousControlOver._onPointerOut();
+                    }
+                    if (previousControlOver !== this) {
+                        this._onPointerEnter();
                     }
                     this._host._lastControlOver = this;
                     return true;
                 }
-                if (type === BABYLON.PointerEventTypes.POINTERDOWN && this.onPointerDownObservable.hasObservers()) {
-                    this.onPointerDownObservable.notifyObservers(this);
+                if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
+                    this._onPointerDown();
+                    this._host._lastControlDown = this;
                     return true;
                 }
-                if (type === BABYLON.PointerEventTypes.POINTERUP && this.onPointerUpObservable.hasObservers()) {
-                    this.onPointerUpObservable.notifyObservers(this);
+                if (type === BABYLON.PointerEventTypes.POINTERUP) {
+                    this._onPointerUp();
+                    if (this._host._lastControlDown !== this) {
+                        this._host._lastControlDown._onPointerUp();
+                        this._host._lastControlDown = null;
+                    }
                     return true;
                 }
                 return false;
@@ -863,10 +1126,17 @@ var BABYLON;
             Container.prototype._localDraw = function (context) {
                 // Implemented by child to be injected inside main draw
             };
+            Container.prototype._link = function (root, host) {
+                _super.prototype._link.call(this, root, host);
+                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                    var child = _a[_i];
+                    child._link(root, host);
+                }
+            };
             Container.prototype._draw = function (parentMeasure, context) {
                 context.save();
                 _super.prototype._processMeasures.call(this, parentMeasure, context);
-                this.applyStates(context);
+                this._applyStates(context);
                 this._localDraw(context);
                 this._clipForChildren(context);
                 for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
@@ -876,7 +1146,7 @@ var BABYLON;
                 context.restore();
             };
             Container.prototype._processPicking = function (x, y, type) {
-                if (!_super.prototype._contains.call(this, x, y)) {
+                if (!_super.prototype.contains.call(this, x, y)) {
                     return false;
                 }
                 // Checking backwards to pick closest first
@@ -1139,7 +1409,7 @@ var BABYLON;
             };
             TextBlock.prototype._draw = function (parentMeasure, context) {
                 context.save();
-                this.applyStates(context);
+                this._applyStates(context);
                 _super.prototype._processMeasures.call(this, parentMeasure, context);
                 // Render lines
                 this._renderLines(context);
@@ -1254,7 +1524,7 @@ var BABYLON;
             });
             Image.prototype._draw = function (parentMeasure, context) {
                 context.save();
-                this.applyStates(context);
+                this._applyStates(context);
                 _super.prototype._processMeasures.call(this, parentMeasure, context);
                 if (this._loaded) {
                     switch (this._stretch) {
@@ -1329,16 +1599,38 @@ var BABYLON;
             function Button(name) {
                 var _this = _super.call(this, name) || this;
                 _this.name = name;
+                _this.thickness = 1;
+                _this.isPointerBlocker = true;
                 return _this;
             }
             // While being a container, the button behaves like a control.
             Button.prototype._processPicking = function (x, y, type) {
-                if (!this._contains(x, y)) {
+                if (!this.contains(x, y)) {
                     return false;
                 }
                 this._processObservables(type);
                 return true;
             };
+            Button.prototype._onPointerEnter = function () {
+                this.scaleX += 0.01;
+                this.scaleY += 0.01;
+                _super.prototype._onPointerEnter.call(this);
+            };
+            Button.prototype._onPointerOut = function () {
+                this.scaleX -= 0.01;
+                this.scaleY -= 0.01;
+                _super.prototype._onPointerOut.call(this);
+            };
+            Button.prototype._onPointerDown = function () {
+                this.scaleX -= 0.05;
+                this.scaleY -= 0.05;
+                _super.prototype._onPointerDown.call(this);
+            };
+            Button.prototype._onPointerUp = function () {
+                this.scaleX += 0.05;
+                this.scaleY += 0.05;
+                _super.prototype._onPointerUp.call(this);
+            };
             // Statics
             Button.CreateImageButton = function (name, text, imageUrl) {
                 var result = new Button(name);
@@ -1356,6 +1648,15 @@ var BABYLON;
                 result.addControl(iconImage);
                 return result;
             };
+            Button.CreateSimpleButton = function (name, text) {
+                var result = new Button(name);
+                // Adding text
+                var textBlock = new BABYLON.GUI.TextBlock(name + "_button", text);
+                textBlock.textWrapping = true;
+                textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
+                result.addControl(textBlock);
+                return result;
+            };
             return Button;
         }(GUI.Rectangle));
         GUI.Button = Button;

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


File diff suppressed because it is too large
+ 252 - 114
dist/preview release/inspector/babylon.inspector.bundle.js


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


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


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


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


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


+ 28 - 0
dist/preview release/materialsLibrary/babylon.cellMaterial.d.ts

@@ -0,0 +1,28 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    class CellMaterial extends PushMaterial {
+        private _diffuseTexture;
+        diffuseTexture: BaseTexture;
+        diffuseColor: Color3;
+        _computeHighLevel: boolean;
+        computeHighLevel: boolean;
+        private _disableLighting;
+        disableLighting: boolean;
+        private _maxSimultaneousLights;
+        maxSimultaneousLights: number;
+        private _worldViewProjectionMatrix;
+        private _scaledDiffuse;
+        private _renderId;
+        constructor(name: string, scene: Scene);
+        needAlphaBlending(): boolean;
+        needAlphaTesting(): boolean;
+        getAlphaTestTexture(): BaseTexture;
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
+        getAnimatables(): IAnimatable[];
+        dispose(forceDisposeEffect?: boolean): void;
+        clone(name: string): CellMaterial;
+        serialize(): any;
+        static Parse(source: any, scene: Scene, rootUrl: string): CellMaterial;
+    }
+}

File diff suppressed because it is too large
+ 276 - 0
dist/preview release/materialsLibrary/babylon.cellMaterial.js


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


+ 13 - 13
dist/preview release/materialsLibrary/babylon.customMaterial.d.ts

@@ -8,16 +8,16 @@ declare module BABYLON {
     class ShaderSpecialParts {
         constructor();
         Fragment_Begin: string;
-        Fragment_Definations: string;
+        Fragment_Definitions: string;
         Fragment_MainBegin: string;
-        Fragment_Custom_Deffiuse: string;
+        Fragment_Custom_Diffuse: string;
         Fragment_Custom_Alpha: string;
         Fragment_Before_FragColor: string;
         Vertex_Begin: string;
-        Vertex_Definations: string;
+        Vertex_Definitions: string;
         Vertex_MainBegin: string;
-        Vertex_Befor_PositionUpdated: string;
-        Vertex_Befor_NormalUpdated: string;
+        Vertex_Before_PositionUpdated: string;
+        Vertex_Before_NormalUpdated: string;
     }
     class ShaderForVer3_0 extends CustomShaderStructure {
         constructor();
@@ -29,9 +29,9 @@ declare module BABYLON {
         static ShaderIndexer: number;
         CustomParts: ShaderSpecialParts;
         ShaderVersion: CustomShaderStructure;
-        _customUnifrom: string[];
-        _newUnifroms: string[];
-        _newUnifromInstances: any[];
+        _customUniform: string[];
+        _newUniforms: string[];
+        _newUniformInstances: any[];
         _newSamplerInstances: Texture[];
         AttachAfterBind(mesh: Mesh, effect: Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
@@ -40,15 +40,15 @@ declare module BABYLON {
         constructor(name: string, scene: Scene);
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         Fragment_Begin(shaderPart: string): CustomMaterial;
-        Fragment_Definations(shaderPart: string): CustomMaterial;
+        Fragment_Definitions(shaderPart: string): CustomMaterial;
         Fragment_MainBegin(shaderPart: string): CustomMaterial;
-        Fragment_Custom_Deffiuse(shaderPart: string): CustomMaterial;
+        Fragment_Custom_Diffuse(shaderPart: string): CustomMaterial;
         Fragment_Custom_Alpha(shaderPart: string): CustomMaterial;
         Fragment_Before_FragColor(shaderPart: string): CustomMaterial;
         Vertex_Begin(shaderPart: string): CustomMaterial;
-        Vertex_Definations(shaderPart: string): CustomMaterial;
+        Vertex_Definitions(shaderPart: string): CustomMaterial;
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
-        Vertex_Befor_PositionUpdated(shaderPart: string): CustomMaterial;
-        Vertex_Befor_NormalUpdated(shaderPart: string): CustomMaterial;
+        Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
+        Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
     }
 }

+ 39 - 39
dist/preview release/materialsLibrary/babylon.customMaterial.js

@@ -117,7 +117,7 @@ varying vec3 vDirectionW;\n\
 #include<logDepthDeclaration>\n\
 #include<fogFragmentDeclaration>\n\
 \n\
-#[Fragment_Definations]\n\
+#[Fragment_Definitions]\n\
 \n\
 void main(void) {\n\
 \n\
@@ -128,7 +128,7 @@ vec3 viewDirectionW=normalize(vEyePosition-vPositionW);\n\
 \n\
 vec4 baseColor=vec4(1.,1.,1.,1.);\n\
 vec3 diffuseColor=vDiffuseColor.rgb;\n\
-#[Fragment_Custom_Deffiuse]\n\
+#[Fragment_Custom_Diffuse]\n\
 \n\
 float alpha=vDiffuseColor.a;\n\
 #[Fragment_Custom_Alpha]\n\
@@ -390,7 +390,7 @@ varying vec3 vDirectionW;\n\
 #endif\n\
 #include<logDepthDeclaration>\n\
 \n\
-#[Vertex_Definations]\n\
+#[Vertex_Definitions]\n\
 \n\
 void main(void) {\n\
     \n\
@@ -410,14 +410,14 @@ vPositionUVW=positionUpdated;\n\
 #include<instancesVertex>\n\
 #include<bonesVertex>\n\
 \n\
-#[Vertex_Befor_PositionUpdated]\n\
+#[Vertex_Before_PositionUpdated]\n\
 \n\
 gl_Position=viewProjection*finalWorld*vec4(positionUpdated,1.0);\n\
 vec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\n\
 vPositionW=vec3(worldPos);\n\
 #ifdef NORMAL\n\
 \n\
-#[Vertex_Befor_NormalUpdated]\n\
+#[Vertex_Before_NormalUpdated]\n\
 \n\
 vNormalW=normalize(vec3(finalWorld*vec4(normalUpdated,0.0)));\n\
 #endif\n\
@@ -533,18 +533,18 @@ vColor=color;\n\
             return _this;
         }
         CustomMaterial.prototype.AttachAfterBind = function (mesh, effect) {
-            for (var el in this._newUnifromInstances) {
+            for (var el in this._newUniformInstances) {
                 var ea = el.toString().split('-');
                 if (ea[0] == 'vec2')
-                    effect.setVector2(ea[1], this._newUnifromInstances[el]);
+                    effect.setVector2(ea[1], this._newUniformInstances[el]);
                 else if (ea[0] == 'vec3')
-                    effect.setVector3(ea[1], this._newUnifromInstances[el]);
+                    effect.setVector3(ea[1], this._newUniformInstances[el]);
                 else if (ea[0] == 'vec4')
-                    effect.setVector4(ea[1], this._newUnifromInstances[el]);
+                    effect.setVector4(ea[1], this._newUniformInstances[el]);
                 else if (ea[0] == 'mat4')
-                    effect.setMatrix(ea[1], this._newUnifromInstances[el]);
+                    effect.setMatrix(ea[1], this._newUniformInstances[el]);
                 else if (ea[0] == 'float')
-                    effect.setFloat(ea[1], this._newUnifromInstances[el]);
+                    effect.setFloat(ea[1], this._newUniformInstances[el]);
             }
             for (var el in this._newSamplerInstances) {
                 var ea = el.toString().split('-');
@@ -554,14 +554,14 @@ vColor=color;\n\
         };
         CustomMaterial.prototype.ReviewUniform = function (name, arr) {
             if (name == "uniform") {
-                for (var ind in this._newUnifroms)
-                    if (this._customUnifrom[ind].indexOf('sampler') == -1)
-                        arr.push(this._newUnifroms[ind]);
+                for (var ind in this._newUniforms)
+                    if (this._customUniform[ind].indexOf('sampler') == -1)
+                        arr.push(this._newUniforms[ind]);
             }
             if (name == "sampler") {
-                for (var ind in this._newUnifroms)
-                    if (this._customUnifrom[ind].indexOf('sampler') != -1)
-                        arr.push(this._newUnifroms[ind]);
+                for (var ind in this._newUniforms)
+                    if (this._customUniform[ind].indexOf('sampler') != -1)
+                        arr.push(this._newUniforms[ind]);
             }
             return arr;
         };
@@ -581,15 +581,15 @@ vColor=color;\n\
             };
             BABYLON.Effect.ShadersStore[name + "VertexShader"] = this.ShaderVersion.VertexStore
                 .replace('#[Vertex_Begin]', (this.CustomParts.Vertex_Begin ? this.CustomParts.Vertex_Begin : ""))
-                .replace('#[Vertex_Definations]', (this._customUnifrom ? this._customUnifrom.join("\n") : "") + (this.CustomParts.Vertex_Definations ? this.CustomParts.Vertex_Definations : ""))
+                .replace('#[Vertex_Definitions]', (this._customUniform ? this._customUniform.join("\n") : "") + (this.CustomParts.Vertex_Definitions ? this.CustomParts.Vertex_Definitions : ""))
                 .replace('#[Vertex_MainBegin]', (this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
-                .replace('#[Vertex_Befor_PositionUpdated]', (this.CustomParts.Vertex_Befor_PositionUpdated ? this.CustomParts.Vertex_Befor_PositionUpdated : ""))
-                .replace('#[Vertex_Befor_NormalUpdated]', (this.CustomParts.Vertex_Befor_NormalUpdated ? this.CustomParts.Vertex_Befor_NormalUpdated : ""));
+                .replace('#[Vertex_Before_PositionUpdated]', (this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
+                .replace('#[Vertex_Before_NormalUpdated]', (this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : ""));
             BABYLON.Effect.ShadersStore[name + "PixelShader"] = this.ShaderVersion.FragmentStore
                 .replace('#[Fragment_Begin]', (this.CustomParts.Fragment_Begin ? this.CustomParts.Fragment_Begin : ""))
                 .replace('#[Fragment_MainBegin]', (this.CustomParts.Fragment_MainBegin ? this.CustomParts.Fragment_MainBegin : ""))
-                .replace('#[Fragment_Definations]', (this._customUnifrom ? this._customUnifrom.join("\n") : "") + (this.CustomParts.Fragment_Definations ? this.CustomParts.Fragment_Definations : ""))
-                .replace('#[Fragment_Custom_Deffiuse]', (this.CustomParts.Fragment_Custom_Deffiuse ? this.CustomParts.Fragment_Custom_Deffiuse : ""))
+                .replace('#[Fragment_Definitions]', (this._customUniform ? this._customUniform.join("\n") : "") + (this.CustomParts.Fragment_Definitions ? this.CustomParts.Fragment_Definitions : ""))
+                .replace('#[Fragment_Custom_Diffuse]', (this.CustomParts.Fragment_Custom_Diffuse ? this.CustomParts.Fragment_Custom_Diffuse : ""))
                 .replace('#[Fragment_Custom_Alpha]', (this.CustomParts.Fragment_Custom_Alpha ? this.CustomParts.Fragment_Custom_Alpha : ""))
                 .replace('#[Fragment_Before_FragColor]', (this.CustomParts.Fragment_Before_FragColor ? this.CustomParts.Fragment_Before_FragColor : ""));
             return name;
@@ -602,38 +602,38 @@ vColor=color;\n\
             }
         };
         CustomMaterial.prototype.AddUniform = function (name, kind, param) {
-            if (!this._customUnifrom) {
-                this._customUnifrom = new Array();
-                this._newUnifroms = new Array();
+            if (!this._customUniform) {
+                this._customUniform = new Array();
+                this._newUniforms = new Array();
                 this._newSamplerInstances = new Array();
-                this._newUnifromInstances = new Array();
+                this._newUniformInstances = new Array();
             }
             if (param) {
                 if (kind.indexOf("sampler") == -1) {
-                    this._newUnifromInstances[kind + "-" + name] = param;
+                    this._newUniformInstances[kind + "-" + name] = param;
                 }
                 else {
                     this._newSamplerInstances[kind + "-" + name] = param;
                 }
             }
-            this._customUnifrom.push("uniform " + kind + " " + name + ";");
-            this._newUnifroms.push(name);
+            this._customUniform.push("uniform " + kind + " " + name + ";");
+            this._newUniforms.push(name);
             return this;
         };
         CustomMaterial.prototype.Fragment_Begin = function (shaderPart) {
             this.CustomParts.Fragment_Begin = shaderPart;
             return this;
         };
-        CustomMaterial.prototype.Fragment_Definations = function (shaderPart) {
-            this.CustomParts.Fragment_Definations = shaderPart;
+        CustomMaterial.prototype.Fragment_Definitions = function (shaderPart) {
+            this.CustomParts.Fragment_Definitions = shaderPart;
             return this;
         };
         CustomMaterial.prototype.Fragment_MainBegin = function (shaderPart) {
             this.CustomParts.Fragment_MainBegin = shaderPart;
             return this;
         };
-        CustomMaterial.prototype.Fragment_Custom_Deffiuse = function (shaderPart) {
-            this.CustomParts.Fragment_Custom_Deffiuse = shaderPart.replace("result", "diffuseColor");
+        CustomMaterial.prototype.Fragment_Custom_Diffuse = function (shaderPart) {
+            this.CustomParts.Fragment_Custom_Diffuse = shaderPart.replace("result", "diffuseColor");
             return this;
         };
         CustomMaterial.prototype.Fragment_Custom_Alpha = function (shaderPart) {
@@ -648,20 +648,20 @@ vColor=color;\n\
             this.CustomParts.Vertex_Begin = shaderPart;
             return this;
         };
-        CustomMaterial.prototype.Vertex_Definations = function (shaderPart) {
-            this.CustomParts.Vertex_Definations = shaderPart;
+        CustomMaterial.prototype.Vertex_Definitions = function (shaderPart) {
+            this.CustomParts.Vertex_Definitions = shaderPart;
             return this;
         };
         CustomMaterial.prototype.Vertex_MainBegin = function (shaderPart) {
             this.CustomParts.Vertex_MainBegin = shaderPart;
             return this;
         };
-        CustomMaterial.prototype.Vertex_Befor_PositionUpdated = function (shaderPart) {
-            this.CustomParts.Vertex_Befor_PositionUpdated = shaderPart.replace("result", "positionUpdated");
+        CustomMaterial.prototype.Vertex_Before_PositionUpdated = function (shaderPart) {
+            this.CustomParts.Vertex_Before_PositionUpdated = shaderPart.replace("result", "positionUpdated");
             return this;
         };
-        CustomMaterial.prototype.Vertex_Befor_NormalUpdated = function (shaderPart) {
-            this.CustomParts.Vertex_Befor_NormalUpdated = shaderPart.replace("result", "normalUpdated");
+        CustomMaterial.prototype.Vertex_Before_NormalUpdated = function (shaderPart) {
+            this.CustomParts.Vertex_Before_NormalUpdated = shaderPart.replace("result", "normalUpdated");
             return this;
         };
         return CustomMaterial;

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


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


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


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


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

@@ -18,6 +18,7 @@
  - Multi-platform Compressed Textures for Desktops & Mobile Devices with fall back.  Batch (dos) scripts to convert entire directories of .jpg's & .png's [Doc](http://doc.babylonjs.com/tutorials/multi-platform_compressed_textures) ([jcpalmer](https://github.com/Palmer-JC))
  - All deprecated functions and properties were removed ([deltakosh](https://github.com/deltakosh))
  - New build system based on workloads. [More info here](http://doc.babylonjs.com/generals/how_to_start#custom-builds) ([deltakosh](https://github.com/deltakosh))
+ - New `Cell Shading` material added into `Materials Library` [Demo](http://www.babylonjs.com/Demos/CellShading/) - ([Julien Moreau-Mathis](https://github.com/julien-moreau))
 
 ### Updates
 - Added `FIXED_EQUIRECTANGULAR_MIRRORED_MODE` mode for reflection texture. [Demo here](http://www.babylonjs-playground.com/#11GAIH#22) ([deltakosh](https://github.com/deltakosh))
@@ -51,6 +52,7 @@
 - Added `material.twoSidedLighting` to PBRMaterial and StandardMaterial to enable flipping normals when backfaceCulling is false ([BeardedGnome](https://github.com/BeardedGnome), [bghgary](https://github.com/bghgary))
 - Added a [HTML page](https://github.com/BabylonJS/Babylon.js/blob/master/Tools/Gulp/profiling.html) with embedded directions to improve the custom build process. ([jcpalmer](https://github.com/Palmer-JC))
 - Added glTF 2.0 loader with versioning support ([bghgary](https://github.com/bghgary), thanks to [BeardedGnome](https://github.com/BeardedGnome) for animation updates)
+- New `Motion Blur` effect added into `StandardRenderingPipeline` [Demo](http://www.babylonjs.com/Demos/MotionBlur/) - ([Julien Moreau-Mathis](https://github.com/julien-moreau))
  
 ### Bug fixes
 - Fixed a bug with spotlight direction ([deltakosh](https://github.com/deltakosh)) 

+ 1 - 5
gui/readme.md

@@ -13,8 +13,4 @@ The Babylon.js GUI library is an extension you can use to generate interactive u
 * Text wrapping
 
 ==> ideas
-* lines (with cap)
-* ellipse
-* button
-* interactions
-* rotate / scale
+* pick on mesh

+ 54 - 8
gui/src/advancedDynamicTexture.ts

@@ -3,12 +3,17 @@
 module BABYLON.GUI {
     export class AdvancedDynamicTexture extends DynamicTexture {
         private _isDirty = false;
-        private _renderObserver: Observer<Scene>;
+        private _renderObserver: Observer<Camera>;
         private _resizeObserver: Observer<Engine>;
-        private _pointerMoveObserver: Observer<PointerInfo>;
+        private _pointerMoveObserver: Observer<PointerInfoPre>;
         private _background: string;
-        private _rootContainer = new Container("root");
+        public _rootContainer = new Container("root");
         public _lastControlOver: Control;
+        public _lastControlDown: Control;
+        public _shouldBlockPointer: boolean;
+        public _toDispose: IDisposable;
+        public _linkedControls = new Array<Control>();
+        private _isFullscreen = false;
 
         public get background(): string {
             return this._background;
@@ -26,7 +31,7 @@ module BABYLON.GUI {
         constructor(name: string, width = 0, height = 0, scene: Scene, generateMipMaps = false, samplingMode = Texture.NEAREST_SAMPLINGMODE) {
             super(name, {width: width, height: height}, scene, generateMipMaps, samplingMode, Engine.TEXTUREFORMAT_RGBA);
 
-            this._renderObserver = this.getScene().onBeforeRenderObservable.add(() => this._checkUpdate());
+            this._renderObserver = this.getScene().onBeforeCameraRenderObservable.add((camera: Camera) => this._checkUpdate(camera));
 
             this._rootContainer._link(null, this);
 
@@ -54,14 +59,19 @@ module BABYLON.GUI {
         }
 
         public dispose() {
-            this.getScene().onBeforeRenderObservable.remove(this._renderObserver);
+            this.getScene().onBeforeCameraRenderObservable.remove(this._renderObserver);
 
             if (this._resizeObserver) {
                 this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
             }
 
             if (this._pointerMoveObserver) {
-                this.getScene().onPointerObservable.remove(this._pointerMoveObserver);
+                this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
+            }
+
+            if (this._toDispose) {
+                this._toDispose.dispose();
+                this._toDispose = null;
             }
 
             super.dispose();
@@ -80,7 +90,23 @@ module BABYLON.GUI {
             }
         }
 
-        private _checkUpdate(): void {
+        private _checkUpdate(camera: Camera): void {
+            if (this._isFullscreen && this._linkedControls.length) {
+                var scene = this.getScene();
+                var engine = scene.getEngine();
+                var viewport = camera.viewport;
+                var globalViewport = viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
+
+                for (var control of this._linkedControls) {
+                    var mesh = control._linkedMesh;
+                    
+                    var position = mesh.getBoundingInfo().boundingSphere.center;
+                    var projectedPosition = Vector3.Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
+
+                    control._moveToProjectedPosition(projectedPosition);
+                }
+            }
+
             if (!this._isDirty && !this._rootContainer.isDirty) {
                 return;
             }
@@ -106,6 +132,7 @@ module BABYLON.GUI {
             }
 
             // Render
+            context.font = "18px Arial";
             var measure = new Measure(0, 0, renderWidth, renderHeight);
             this._rootContainer._draw(measure, context);
         }
@@ -125,14 +152,17 @@ module BABYLON.GUI {
 
         public attach(): void {
             var scene = this.getScene();
-            this._pointerMoveObserver = scene.onPointerObservable.add((pi, state) => {
+            this._pointerMoveObserver = scene.onPrePointerObservable.add((pi, state) => {
                 if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE 
                     && pi.type !== BABYLON.PointerEventTypes.POINTERUP
                     && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
                     return;
                 }
 
+                this._shouldBlockPointer = false;
                 this._doPicking(scene.pointerX, scene.pointerY, pi.type);
+
+                pi.skipOnPointerObservable = this._shouldBlockPointer && pi.type !== BABYLON.PointerEventTypes.POINTERUP;
             });
         }
 
@@ -142,11 +172,24 @@ module BABYLON.GUI {
 
             var material = new BABYLON.StandardMaterial("AdvancedDynamicTextureMaterial", mesh.getScene());
             material.backFaceCulling = false;
+            material.diffuseColor = BABYLON.Color3.Black();
+            material.specularColor = BABYLON.Color3.Black();
             material.emissiveTexture = result;
             material.opacityTexture = result;
 
             mesh.material = material;
 
+            mesh.getScene().onPointerObservable.add(function(pi, state) {
+                if (pi.type !== BABYLON.PointerEventTypes.POINTERUP && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
+                    return;
+                }
+
+                if (pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
+                    var uv = pi.pickInfo.getTextureCoordinates();
+                    result._doPicking(uv.x * width, (1.0 - uv.y) * height, pi.type);
+                }
+            });
+
             return result;
         }
 
@@ -157,6 +200,9 @@ module BABYLON.GUI {
             var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
             layer.texture = result;
 
+            result._toDispose = layer;
+            result._isFullscreen = true;
+
             // Attach
             result.attach();
 

+ 39 - 1
gui/src/controls/button.ts

@@ -4,11 +4,13 @@ module BABYLON.GUI {
     export class Button extends Rectangle {      
         constructor(public name: string) {
             super(name);
+            this.thickness = 1;
+            this.isPointerBlocker = true;
         }
 
         // While being a container, the button behaves like a control.
         public _processPicking(x: number, y: number, type: number): boolean {
-            if (!this._contains(x, y)) {
+            if (!this.contains(x, y)) {
                 return false;
             }
 
@@ -17,6 +19,30 @@ module BABYLON.GUI {
             return true;
         }
 
+        protected _onPointerEnter(): void {
+            this.alpha -= 0.2;
+            super._onPointerEnter();
+        }
+
+        protected _onPointerOut(): void {
+            this.alpha += 0.2;
+            super._onPointerOut();
+        }
+
+        protected _onPointerDown(): void {
+            this.scaleX -= 0.05;
+            this.scaleY -= 0.05;
+
+            super._onPointerDown();
+        }
+
+        protected _onPointerUp (): void {
+            this.scaleX += 0.05;
+            this.scaleY += 0.05;
+
+            super._onPointerUp();
+        }        
+
         // Statics
         public static CreateImageButton(name: string, text: string, imageUrl: string): Button {
             var result = new Button(name);
@@ -37,5 +63,17 @@ module BABYLON.GUI {
 
             return result;
         }
+
+        public static CreateSimpleButton(name: string, text: string): Button {
+            var result = new Button(name);
+
+            // Adding text
+            var textBlock = new BABYLON.GUI.TextBlock(name + "_button", text);
+            textBlock.textWrapping = true;
+            textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
+            result.addControl(textBlock);           
+
+            return result;
+        }
     }    
 }

+ 24 - 4
gui/src/controls/container.ts

@@ -2,14 +2,18 @@
 
 module BABYLON.GUI {
     export class Container extends Control {
-        private _children = new Array<Control>();
+        protected _children = new Array<Control>();
         protected _measureForChildren = Measure.Empty();     
 
         constructor(public name: string) {
             super(name);
         }
 
-       public addControl(control: Control): Container {
+        public containsControl(control: Control): boolean {
+            return this._children.indexOf(control) !== -1;
+        }
+
+        public addControl(control: Control): Container {
            var index = this._children.indexOf(control);
 
             if (index !== -1) {
@@ -49,15 +53,31 @@ module BABYLON.GUI {
             this._markAsDirty();
         }
 
+        public _markMatrixAsDirty(): void {
+            super._markMatrixAsDirty();
+
+            for (var index = 0; index < this._children.length; index++) {
+                this._children[index]._markMatrixAsDirty();
+            }
+        }
+
         protected _localDraw(context: CanvasRenderingContext2D): void {
             // Implemented by child to be injected inside main draw
         }
 
+        public _link(root: Container, host: AdvancedDynamicTexture): void {
+            super._link(root, host);
+
+            for (var child of this._children) {
+                child._link(root, host);
+            }
+        }
+
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
             super._processMeasures(parentMeasure, context);
            
-            this.applyStates(context);
+            this._applyStates(context);
 
             this._localDraw(context);
 
@@ -69,7 +89,7 @@ module BABYLON.GUI {
         }
 
         public _processPicking(x: number, y: number, type: number): boolean {
-            if (!super._contains(x, y)) {
+            if (!super.contains(x, y)) {
                 return false;
             }
 

+ 265 - 22
gui/src/controls/control.ts

@@ -1,21 +1,22 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON.GUI {
-    export class Control {        
+    export class Control {       
+        private _alpha = 1; 
         private _zIndex = 0;
         public _root: Container;
         public _host: AdvancedDynamicTexture;
         public _currentMeasure = Measure.Empty();
-        private _fontFamily: string;
-        private _fontSize = 18;
+        private _fontFamily = "Arial";
+        private _fontSize: number;
         private _font: string;
         private _width = new ValueAndUnit(1, ValueAndUnit.UNITMODE_PERCENTAGE, false);
         private _height = new ValueAndUnit(1, ValueAndUnit.UNITMODE_PERCENTAGE, false);
         private _lastMeasuredFont: string;
         protected _fontOffset: {ascent: number, height: number, descent: number};
         private _color: string;
-        private _horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
-        private _verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
+        protected _horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
+        protected _verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
         private _isDirty = true;
         private _cachedParentMeasure = Measure.Empty();
         private _marginLeft = new ValueAndUnit(0);
@@ -24,6 +25,24 @@ module BABYLON.GUI {
         private _marginBottom = new ValueAndUnit(0);        
         private _left = new ValueAndUnit(0);
         private _top = new ValueAndUnit(0);
+        private _scaleX = 1.0;
+        private _scaleY = 1.0;
+        private _rotation = 0;
+        private _transformCenterX = 0.5;
+        private _transformCenterY = 0.5;
+        private _transformMatrix = Matrix2D.Identity();
+        private _invertTransformMatrix = Matrix2D.Identity();
+        private _transformedPosition = Vector2.Zero();
+        private _isMatrixDirty = true;
+        private _cachedOffsetX: number;
+        private _cachedOffsetY: number;
+        public _linkedMesh: AbstractMesh;
+
+        public isHitTestVisible = true;
+        public isPointerBlocker = false;
+
+        public linkOffsetX = 0;
+        public linkOffsetY = 0;
         
         // Properties
 
@@ -51,6 +70,101 @@ module BABYLON.GUI {
         */
         public onPointerUpObservable = new Observable<Control>();     
 
+        /**
+        * An event triggered when pointer enters the control
+        * @type {BABYLON.Observable}
+        */
+        public onPointerEnterObservable = new Observable<Control>();    
+
+        /**
+        * An event triggered when the control is marked as dirty
+        * @type {BABYLON.Observable}
+        */
+        public onDirtyObservable = new Observable<Control>();           
+
+        public get alpha(): number {
+            return this._alpha;
+        }
+
+        public set alpha(value: number) {
+            if (this._alpha === value) {
+                return;
+            }
+
+            this._alpha = value;
+            this._markAsDirty();
+        }                 
+
+        public get scaleX(): number {
+            return this._scaleX;
+        }
+
+        public set scaleX(value: number) {
+            if (this._scaleX === value) {
+                return;
+            }
+
+            this._scaleX = value;
+            this._markAsDirty();
+            this._markMatrixAsDirty();
+        }     
+
+        public get scaleY(): number {
+            return this._scaleY;
+        }
+
+        public set scaleY(value: number) {
+            if (this._scaleY === value) {
+                return;
+            }
+
+            this._scaleY = value;
+            this._markAsDirty();
+            this._markMatrixAsDirty();
+        }  
+
+        public get rotation(): number {
+            return this._rotation;
+        }
+
+        public set rotation(value: number) {
+            if (this._rotation === value) {
+                return;
+            }
+
+            this._rotation = value;
+            this._markAsDirty();
+            this._markMatrixAsDirty();
+        }    
+
+        public get transformCenterY(): number {
+            return this._transformCenterY;
+        }
+
+        public set transformCenterY(value: number) {
+            if (this._transformCenterY === value) {
+                return;
+            }
+
+            this._transformCenterY = value;
+            this._markAsDirty();
+            this._markMatrixAsDirty();
+        }     
+
+        public get transformCenterX(): number {
+            return this._transformCenterX;
+        }
+
+        public set transformCenterX(value: number) {
+            if (this._transformCenterX === value) {
+                return;
+            }
+
+            this._transformCenterX = value;
+            this._markAsDirty();
+            this._markMatrixAsDirty();
+        }    
+
         public get horizontalAlignment(): number {
             return this._horizontalAlignment;
         }
@@ -154,7 +268,10 @@ module BABYLON.GUI {
             }
 
             this._zIndex = value;
-            this._root._reOrderControl(this);
+
+            if (this._root) {
+                this._root._reOrderControl(this);
+            }
         }
 
         public get isDirty(): boolean {
@@ -219,11 +336,44 @@ module BABYLON.GUI {
             if (this._top.fromString(value)) {
                 this._markAsDirty();
             }
+        }     
+
+        public get centerX(): number {
+            return this._currentMeasure.left + this._currentMeasure.width / 2;
+        }       
+
+        public get centerY(): number {
+            return this._currentMeasure.top + this._currentMeasure.height / 2;
         }                   
 
         // Functions
         constructor(public name: string) {
-            this.fontFamily = "Arial";
+        }
+
+        public linkWithMesh(mesh: AbstractMesh): void {
+            if (!this._host || this._root !== this._host._rootContainer) {
+                Tools.Error("Cannot link a control to a mesh if the control is not at root level");
+                return;
+            }
+
+            if (this._host._linkedControls.indexOf(this) !== -1) {
+                return;
+            }
+
+
+            this.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            this.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+            this._linkedMesh = mesh;
+            this._host._linkedControls.push(this);
+        }
+
+        public _moveToProjectedPosition(projectedPosition: Vector3): void {
+            this.left = ((projectedPosition.x + this.linkOffsetX) - this._currentMeasure.width / 2) + "px";
+            this.top = ((projectedPosition.y + this.linkOffsetY) - this._currentMeasure.height / 2) + "px";
+        }
+
+        public _markMatrixAsDirty(): void {
+            this._isMatrixDirty = true;
         }
 
         protected _markAsDirty(): void {            
@@ -240,7 +390,38 @@ module BABYLON.GUI {
             this._host = host;
         }
 
-        protected applyStates(context: CanvasRenderingContext2D): void {
+        protected _transform(context: CanvasRenderingContext2D): void {
+            if (!this._isMatrixDirty && this._scaleX === 1 && this._scaleY ===1 && this._rotation === 0) {
+                return;
+            }
+
+            // preTranslate
+            var offsetX = this._currentMeasure.width * this._transformCenterX + this._currentMeasure.left;
+            var offsetY = this._currentMeasure.height * this._transformCenterY + this._currentMeasure.top;
+            context.translate(offsetX, offsetY);
+
+            // scale
+            context.scale(this._scaleX, this._scaleY);
+
+            // rotate
+            context.rotate(this._rotation);
+
+            // postTranslate
+            context.translate(-offsetX, -offsetY);    
+
+            // Need to update matrices?
+            if (this._isMatrixDirty || this._cachedOffsetX !== offsetX || this._cachedOffsetY !== offsetY) {
+                this._cachedOffsetX = offsetX;
+                this._cachedOffsetY = offsetY;
+                this._isMatrixDirty = false;
+
+                Matrix2D.ComposeToRef(-offsetX, -offsetY, this._rotation, this._scaleX, this._scaleY, this._root ? this._root._transformMatrix : null, this._transformMatrix);
+
+                this._transformMatrix.invertToRef(this._invertTransformMatrix);
+            }
+        }
+
+        protected _applyStates(context: CanvasRenderingContext2D): void {
             if (this._font) {
                 context.font = this._font;
             }
@@ -248,13 +429,16 @@ module BABYLON.GUI {
             if (this._color) {
                 context.fillStyle = this._color;
             }
+
+            context.globalAlpha = this._alpha;
         }
 
         protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D) {     
             if (this._isDirty || !this._cachedParentMeasure.isEqualsTo(parentMeasure)) {
+                this._isDirty = false;
                 this._currentMeasure.copyFrom(parentMeasure);
 
-                this._measure(parentMeasure, context);
+                this._measure();
                 this._computeAlignment(parentMeasure, context);
 
                 // Convert to int values
@@ -266,9 +450,15 @@ module BABYLON.GUI {
                 // Let children add more features
                 this._additionalProcessing(parentMeasure, context);
 
-                this._isDirty = false;
                 this._cachedParentMeasure.copyFrom(parentMeasure);
-            }      
+
+                if (this.onDirtyObservable.hasObservers()) {
+                    this.onDirtyObservable.notifyObservers(this);
+                }                
+            }     
+
+            // Transform
+            this._transform(context); 
                         
             // Clip
             this._clip(context);
@@ -280,7 +470,7 @@ module BABYLON.GUI {
             context.rect(this._currentMeasure.left ,this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
         }
 
-        protected _measure(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
+        public _measure(): void {  
             // Width / Height
             if (this._width.isPixel) {
                 this._currentMeasure.width = this._width.value;
@@ -382,7 +572,14 @@ module BABYLON.GUI {
             // Do nothing
         }
 
-        protected _contains(x: number, y: number) : boolean {
+        public contains(x: number, y: number) : boolean {
+            // Invert transform
+            this._invertTransformMatrix.transformCoordinates(x, y, this._transformedPosition);
+
+            x = this._transformedPosition.x;
+            y = this._transformedPosition.y;
+
+            // Check
             if (x < this._currentMeasure.left) {
                 return false;
             }
@@ -399,11 +596,18 @@ module BABYLON.GUI {
                 return false;
             } 
 
+            if (this.isPointerBlocker) {
+                this._host._shouldBlockPointer = true;
+            }
             return true;
         }
 
         public _processPicking(x: number, y: number, type: number): boolean {
-            if (!this._contains(x, y)) {
+            if (!this.isHitTestVisible) {
+                return false;
+            }
+
+            if (!this.contains(x, y)) {
                 return false;
             }
 
@@ -412,25 +616,64 @@ module BABYLON.GUI {
             return true;
         }
 
-        protected _processObservables(type: number): boolean {
-            if (type === BABYLON.PointerEventTypes.POINTERMOVE && this.onPointerMoveObservable.hasObservers()) {
+        protected _onPointerMove(): void {
+            if (this.onPointerMoveObservable.hasObservers()) {
                 this.onPointerMoveObservable.notifyObservers(this);
+            }
+        }
+
+        protected _onPointerEnter(): void {
+            if (this.onPointerEnterObservable.hasObservers()) {
+                this.onPointerEnterObservable.notifyObservers(this);
+            }
+        }
+
+        protected _onPointerOut(): void {
+            if (this.onPointerOutObservable.hasObservers()) {
+                this.onPointerOutObservable.notifyObservers(this);
+            }
+        }
+
+        protected _onPointerDown(): void {
+            if (this.onPointerDownObservable.hasObservers()) {
+                this.onPointerDownObservable.notifyObservers(this);
+            }
+        }
+
+        protected _onPointerUp(): void {
+            if (this.onPointerUpObservable.hasObservers()) {
+                this.onPointerUpObservable.notifyObservers(this);
+            }
+        }
+
+        protected _processObservables(type: number): boolean {
+            if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
+                this._onPointerMove();
 
                 var previousControlOver = this._host._lastControlOver;
-                if (previousControlOver && previousControlOver !== this && previousControlOver.onPointerOutObservable.hasObservers()) {
-                    previousControlOver.onPointerOutObservable.notifyObservers(previousControlOver);
+                if (previousControlOver && previousControlOver !== this) {
+                    previousControlOver._onPointerOut();
+                }
+
+                if (previousControlOver !== this) {
+                    this._onPointerEnter();
                 }
+
                 this._host._lastControlOver = this;
                 return true;
             }
 
-            if (type === BABYLON.PointerEventTypes.POINTERDOWN && this.onPointerDownObservable.hasObservers()) {
-                this.onPointerDownObservable.notifyObservers(this);
+            if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
+                this._onPointerDown();
+                this._host._lastControlDown = this;
                 return true;
             }
 
-            if (type === BABYLON.PointerEventTypes.POINTERUP && this.onPointerUpObservable.hasObservers()) {
-                this.onPointerUpObservable.notifyObservers(this);
+            if (type === BABYLON.PointerEventTypes.POINTERUP) {
+                if (this._host._lastControlDown) {
+                    this._host._lastControlDown._onPointerUp();
+                }
+                this._host._lastControlDown = null;
                 return true;
             }
         

+ 79 - 0
gui/src/controls/ellipse.ts

@@ -0,0 +1,79 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    export class Ellipse extends Container {
+        private _thickness = 1;
+        private _background: string;          
+        
+        public get thickness(): number {
+            return this._thickness;
+        }
+
+        public set thickness(value: number) {
+            if (this._thickness === value) {
+                return;
+            }
+
+            this._thickness = value;
+            this._markAsDirty();
+        }   
+       
+        public get background(): string {
+            return this._background;
+        }
+
+        public set background(value: string) {
+            if (this._background === value) {
+                return;
+            }
+
+            this._background = value;
+            this._markAsDirty();
+        }           
+     
+        constructor(public name: string) {
+            super(name);
+        }
+
+        protected _localDraw(context: CanvasRenderingContext2D): void {
+            context.save();
+
+            context.beginPath();
+            context.ellipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, 
+                            this._currentMeasure.width / 2 - this._thickness / 2, this._currentMeasure.height / 2 - this._thickness / 2, 0, 0, 2 * Math.PI);
+            context.closePath();
+
+            if (this._background) {
+                context.fillStyle = this._background;
+
+                context.fill();
+            }
+
+            if (this._thickness) {
+                if (this.color) {
+                    context.strokeStyle = this.color;
+                }
+                context.lineWidth = this._thickness;
+
+                context.stroke();
+            }
+        
+            context.restore();
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
+            super._additionalProcessing(parentMeasure, context);
+
+            this._measureForChildren.width -= 2 * this._thickness;
+            this._measureForChildren.height -= 2 * this._thickness;
+            this._measureForChildren.left += this._thickness;
+            this._measureForChildren.top += this._thickness;            
+        }
+
+       protected _clipForChildren(context: CanvasRenderingContext2D) {
+            context.beginPath();
+            context.ellipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, this._currentMeasure.width / 2, this._currentMeasure.height / 2, 0, 0, 2 * Math.PI);
+            context.clip();
+        }
+    }    
+}

+ 1 - 1
gui/src/controls/image.ts

@@ -42,7 +42,7 @@ module BABYLON.GUI {
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
 
-            this.applyStates(context);
+            this._applyStates(context);
             super._processMeasures(parentMeasure, context);
 
             if (this._loaded) {

+ 164 - 0
gui/src/controls/line.ts

@@ -0,0 +1,164 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+var DOMImage = Image;
+
+module BABYLON.GUI {
+    export class Line extends Control {
+        private _lineWidth = 1;
+        private _background: string;
+        private _x1 = 0;
+        private _y1 = 0;
+        private _x2 = 0;
+        private _y2 = 0;
+        private _dash = new Array<number>();
+        private _connectedControl: Control;
+
+        public get dash(): Array<number> {
+            return this._dash;
+        }
+
+        public set dash(value: Array<number>) {
+            if (this._dash === value) {
+                return;
+            }
+
+            this._dash = value;
+            this._markAsDirty();
+        }     
+
+        public get connectedControl(): Control {
+            return this._connectedControl;
+        }
+
+        public set connectedControl(value: Control) {
+            if (this._connectedControl === value) {
+                return;
+            }
+
+            this._connectedControl = value;
+            this._markAsDirty();
+        }              
+
+        public get x1(): number {
+            return this._x1;
+        }
+
+        public set x1(value: number) {
+            if (this._x1 === value) {
+                return;
+            }
+
+            this._x1 = value;
+            this._markAsDirty();
+        }    
+
+        public get y1(): number {
+            return this._y1;
+        }
+
+        public set y1(value: number) {
+            if (this._y1 === value) {
+                return;
+            }
+
+            this._y1 = value;
+            this._markAsDirty();
+        }     
+
+        public get x2(): number {
+            if (this._connectedControl) {
+                return this._connectedControl.centerX;
+            }
+            return this._x2;
+        }
+
+        public set x2(value: number) {
+            if (this._x2 === value) {
+                return;
+            }
+
+            this._x2 = value;
+            this._markAsDirty();
+        }    
+
+        public get y2(): number {
+            if (this._connectedControl) {
+                return this._connectedControl.centerY;
+            }
+            return this._y2;
+        }
+
+        public set y2(value: number) {
+            if (this._y2 === value) {
+                return;
+            }
+
+            this._y2 = value;
+            this._markAsDirty();
+        }                       
+        
+        public get lineWidth(): number {
+            return this._lineWidth;
+        }
+
+        public set lineWidth(value: number) {
+            if (this._lineWidth === value) {
+                return;
+            }
+
+            this._lineWidth = value;
+            this._markAsDirty();
+        }   
+
+        public set horizontalAlignment(value: number) {
+            return;
+        } 
+
+        public set verticalAlignment(value: number) {
+            return;
+        }         
+
+        constructor(public name: string) {
+            super(name);
+
+            this.isHitTestVisible = false;
+            this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+            this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;            
+        }
+
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            context.save();
+
+            this._applyStates(context);
+            super._processMeasures(parentMeasure, context);
+
+            context.strokeStyle = this.color;
+            context.lineWidth = this._lineWidth;
+            context.setLineDash(this._dash);
+
+            context.beginPath();
+            context.moveTo(this._x1, this._y1);
+            context.lineTo(this.x2, this.y2);
+
+            context.stroke();
+
+            context.restore();
+        }
+
+        public _measure(): void {  
+            // Width / Height
+            this._currentMeasure.width = Math.abs(this._x1 - this.x2);
+            this._currentMeasure.height = Math.abs(this._y1 - this.y2);
+        }
+
+        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {          
+            this._currentMeasure.left = Math.min(this._x1, this.x2);
+            this._currentMeasure.top = Math.min(this._y1, this.y2);            
+        }   
+
+        public _moveToProjectedPosition(projectedPosition: Vector3): void {
+            this.x1 = projectedPosition.x + this.linkOffsetX;
+            this.y1 = projectedPosition.y + this.linkOffsetY;
+        }
+    }    
+}

+ 25 - 0
gui/src/controls/stackPanel.ts

@@ -0,0 +1,25 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    export class StackPanel extends Container {
+    
+        constructor(public name: string) {
+            super(name);
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            var top = 0;
+            for (var child of this._children) {
+                child._currentMeasure.copyFrom(parentMeasure);
+                child._measure();
+                child.top = top + "px";
+                top += child._currentMeasure.height;
+                child.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+            }
+
+            this.height = top + "px";
+
+            super._additionalProcessing(parentMeasure, context);
+        }    
+    }    
+}

+ 1 - 1
gui/src/controls/textBlock.ts

@@ -88,7 +88,7 @@ module BABYLON.GUI {
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
 
-            this.applyStates(context);
+            this._applyStates(context);
             super._processMeasures(parentMeasure, context);
             
             // Render lines

+ 114 - 0
gui/src/math2D.ts

@@ -0,0 +1,114 @@
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    export class Matrix2D {
+        public m = new Float32Array(6);
+
+        constructor(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number) {
+            this.fromValues(m00, m01, m10, m11, m20, m21);
+        }
+
+        public fromValues(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number): Matrix2D {
+            this.m[0] = m00; this.m[1] = m01; 
+            this.m[2] = m10; this.m[3] = m11;
+            this.m[4] = m20; this.m[5] = m21;
+            return this;
+        }
+
+        public determinant(): number {
+            return this.m[0] * this.m[3] - this.m[1] * this.m[2];
+        }
+
+        public invertToRef(result: Matrix2D): Matrix2D {
+            let l0 = this.m[0]; let l1 = this.m[1];
+            let l2 = this.m[2]; let l3 = this.m[3];
+            let l4 = this.m[4]; let l5 = this.m[5];
+
+            let det = this.determinant();
+            if (det < (Epsilon * Epsilon)) {
+                throw new Error("Can't invert matrix, near null determinant");
+            }
+
+            let detDiv = 1 / det;
+
+            let det4 = l2 * l5 - l3 * l4;
+            let det5 = l1 * l4 - l0 * l5;
+
+            result.m[0] = l3 * detDiv;     result.m[1] = -l1 * detDiv;
+            result.m[2] = -l2 * detDiv;    result.m[3] = l0 * detDiv;
+            result.m[4] = det4 * detDiv;   result.m[5] = det5 * detDiv;
+
+            return this;
+        }
+
+        public multiplyToRef(other: Matrix2D, result: Matrix2D): Matrix2D {
+            let l0 = this.m[0];     let l1 = this.m[1];
+            let l2 = this.m[2];     let l3 = this.m[3];
+            let l4 = this.m[4];     let l5 = this.m[5];
+
+            let r0 = other.m[0];    let r1 = other.m[1];
+            let r2 = other.m[2];    let r3 = other.m[3];
+            let r4 = other.m[4];    let r5 = other.m[5];
+
+            result.m[0] = l0 * r0 + l1 * r2;        result.m[1] = l0 * r1 + l1 * r3;
+            result.m[2] = l2 * r0 + l3 * r2;        result.m[3] = l2 * r1 + l3 * r3;
+            result.m[4] = l4 * r0 + l5 * r2 + r4;   result.m[5] = l4 * r1 + l5 * r3 + r5;
+
+            return this;
+        }
+
+        public transformCoordinates(x: number, y: number, result: Vector2): Matrix2D {
+            result.x = x * this.m[0] + y * this.m[2] + this.m[4];
+            result.y = x * this.m[1] + y * this.m[3] + this.m[5];
+
+            return this;
+        }
+
+        // Statics
+        public static Identity(): Matrix2D {
+            return new Matrix2D(1, 0, 0, 1, 0, 0);
+        }
+
+        public static TranslationToRef(x: number, y: number, result: Matrix2D): void {
+            result.fromValues(1, 0, 0, 1, x, y);
+        }
+
+        public static ScalingToRef(x: number, y: number, result: Matrix2D): void {
+            result.fromValues(x, 0, 0, y,  0, 0);
+        }
+
+        public static RotationToRef(angle: number, result: Matrix2D): void {
+            var s = Math.sin(angle);
+            var c = Math.cos(angle);
+
+            result.fromValues(c, s, -s, c,  0, 0);
+        }
+
+        private static _TempPreTranslationMatrix = Matrix2D.Identity();
+        private static _TempPostTranslationMatrix = Matrix2D.Identity();
+        private static _TempRotationMatrix = Matrix2D.Identity();
+        private static _TempScalingMatrix = Matrix2D.Identity();
+        private static _TempCompose0 = Matrix2D.Identity();
+        private static _TempCompose1 = Matrix2D.Identity();
+        private static _TempCompose2 = Matrix2D.Identity();
+
+        public static ComposeToRef(tx: number, ty: number, angle: number, scaleX: number, scaleY: number, parentMatrix: Matrix2D,  result: Matrix2D): void {
+            Matrix2D.TranslationToRef(tx, ty, Matrix2D._TempPreTranslationMatrix);
+
+            Matrix2D.ScalingToRef(scaleX, scaleY, Matrix2D._TempScalingMatrix);
+
+            Matrix2D.RotationToRef(angle, Matrix2D._TempRotationMatrix);
+
+            Matrix2D.TranslationToRef(-tx, -ty, Matrix2D._TempPostTranslationMatrix);
+
+            Matrix2D._TempPreTranslationMatrix.multiplyToRef(Matrix2D._TempScalingMatrix, Matrix2D._TempCompose0);
+            Matrix2D._TempCompose0.multiplyToRef(Matrix2D._TempRotationMatrix, Matrix2D._TempCompose1);
+            if (parentMatrix) {
+                Matrix2D._TempCompose1.multiplyToRef(Matrix2D._TempPostTranslationMatrix, Matrix2D._TempCompose2);
+                Matrix2D._TempCompose2.multiplyToRef(parentMatrix, result);
+            } else {
+                Matrix2D._TempCompose1.multiplyToRef(Matrix2D._TempPostTranslationMatrix, result);
+            }
+        }
+    }    
+}

+ 15 - 0
loaders/src/glTF/README.md

@@ -3,6 +3,8 @@
 # Usage
 The glTF file loader is a SceneLoader plugin.
 
+[glTF2 Playground example](http://www.babylonjs-playground.com/#6MZV8R)
+
 ## Step 1 - Include the glTF File Loader
 
 **Full Version**
@@ -47,6 +49,19 @@ BABYLON.SceneLoader.ImportMesh(["myMesh1", "myMesh2", "..."], "./", "duck.gltf",
 });
 ```
 
+You can also append a glTF file to a scene. When using `SceneLoader.Append`, configure the scene to use right handed system by setting the property `useRightHandedSystem` to true. 
+
+```
+// glTF Files use right handed system 
+scene.useRightHandedSystem = true;
+
+// Append sample glTF model to scene
+BABYLON.SceneLoader.Append("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoomBox/glTF/", "BoomBox.gltf", scene, function (scene) {
+}, null, function (scene) {
+    alert("error");
+});
+```
+
 ## Step 3 (V1 Only) - Optionally Specify Flags
 
 If you want to disable incremental loading, you can set the property `IncrementalLoading` to false.

+ 8 - 2
materialsLibrary/index.html

@@ -3,7 +3,7 @@
 <head>
 	<title>Shaders Library</title>
 	<script src="../assets/refs/dat.gui.min.js"></script>
-	<script src="../tools/DevLoader/BabylonLoader.js"></script>
+	<script src="../Tools/DevLoader/BabylonLoader.js"></script>
 
 	<style>
 		html, body {
@@ -49,6 +49,7 @@
 	<script src="test/addsky.js"></script>
 	<script src="test/addgrid.js"></script>
     <script src="test/addpbr.js"></script>
+	<script src="test/addCell.js"></script>
 	
 	<script>
 	BABYLONDEVTOOLS.Loader.load(function() {
@@ -202,13 +203,15 @@
                 var grid = prepareGrid();
 
 				var shadowOnly = new BABYLON.ShadowOnlyMaterial();
+
+				var cell = prepareCell();
 				
 				// Default to std
 				var currentMaterial = std;
 				sphere.material = std;				
 				sphere.receiveShadows = true;
 
-				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr', 'fur', 'triPlanar', 'gradient', 'sky', 'grid', 'shadowOnly']).onFinishChange(function () {
+				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr', 'fur', 'triPlanar', 'gradient', 'sky', 'grid', 'shadowOnly', 'cell']).onFinishChange(function () {
 					water.enableRenderTargets(false);
 					skybox.material = skyboxMaterial;
 					currentMesh.isVisible = true;
@@ -258,6 +261,9 @@
                         case "grid":
                             currentMaterial = grid;
                             break;
+						case "cell":
+							currentMaterial = cell;
+							break;
 						default:
 							currentMaterial = std;
 							break;

+ 296 - 0
materialsLibrary/src/cell/babylon.cellMaterial.ts

@@ -0,0 +1,296 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON {
+    class CellMaterialDefines extends MaterialDefines {
+        public DIFFUSE = false;
+        public CLIPPLANE = false;
+        public ALPHATEST = false;
+        public POINTSIZE = false;
+        public FOG = false;
+        public NORMAL = false;
+        public UV1 = false;
+        public UV2 = false;
+        public VERTEXCOLOR = false;
+        public VERTEXALPHA = false;
+        public NUM_BONE_INFLUENCERS = 0;
+        public BonesPerMesh = 0;
+        public INSTANCES = false;
+        public NDOTL = true;
+        public CUSTOMUSERLIGHTING = true;
+        public CELLBASIC = true;
+
+        constructor() {
+            super();
+            this.rebuild();
+        }
+    }
+
+    export class CellMaterial extends PushMaterial {
+        @serializeAsTexture("diffuseTexture")
+        private _diffuseTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTexture: BaseTexture;
+
+        @serializeAsColor3("diffuseColor")
+        public diffuseColor = new Color3(1, 1, 1);
+
+        @serialize("computeHighLevel")
+        public _computeHighLevel: boolean = false;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public computeHighLevel: boolean;
+        
+        @serialize("disableLighting")
+        private _disableLighting = false;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public disableLighting: boolean;   
+        
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number; 
+
+        private _worldViewProjectionMatrix = Matrix.Zero();
+        private _scaledDiffuse = new Color3();
+        private _renderId: number;
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+        }
+
+        public needAlphaBlending(): boolean {
+            return (this.alpha < 1.0);
+        }
+
+        public needAlphaTesting(): boolean {
+            return false;
+        }
+
+        public getAlphaTestTexture(): BaseTexture {
+            return null;
+        }
+
+        // Methods   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {   
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
+                    return true;
+                }
+            }
+
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new CellMaterialDefines();
+            }
+
+            var defines = <CellMaterialDefines>subMesh._materialDefines;
+            var scene = this.getScene();
+
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
+                if (this._renderId === scene.getRenderId()) {
+                    return true;
+                }
+            }
+
+            var engine = scene.getEngine();
+
+            // Textures
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                        if (!this._diffuseTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
+                    }                
+                }
+            }
+
+            // High level
+            defines.CELLBASIC = !this.computeHighLevel;
+
+            // Misc.
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, defines);
+
+            // Lights
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
+            
+            // Attribs
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
+
+            // Get correct effect      
+            if (defines.isDirty) {
+                defines.markAsProcessed();
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();             
+                if (defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
+                
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
+                    fallbacks.addCPUSkinningFallback(0, mesh);
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (defines.UV2) {
+                    attribs.push(VertexBuffer.UV2Kind);
+                }
+
+                if (defines.VERTEXCOLOR) {
+                    attribs.push(VertexBuffer.ColorKind);
+                }
+
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
+
+                var shaderName = "cell";
+                var join = defines.toString();
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                                "vFogInfos", "vFogColor", "pointSize",
+                                "vDiffuseInfos", 
+                                "mBones",
+                                "vClipPlane", "diffuseMatrix", "depthValues"
+                ];
+                var samplers = ["diffuseSampler"];
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this.maxSimultaneousLights - 1 }
+                    }, engine), defines);
+
+            }
+            if (!subMesh.effect.isReady()) {
+                return false;
+            }
+
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            return true;
+        }
+
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
+            var scene = this.getScene();
+
+            var defines = <CellMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            this._activeEffect = effect;
+
+            // Matrices        
+            this.bindOnlyWorldMatrix(world);
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+
+            if (this._mustRebind(scene, effect)) {
+                // Textures        
+                if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    this._activeEffect.setTexture("diffuseSampler", this._diffuseTexture);
+
+                    this._activeEffect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
+                    this._activeEffect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
+                }
+                
+                // Clip plane
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
+
+                // Point size
+                if (this.pointsCloud) {
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
+                }
+
+                this._activeEffect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+            }
+
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+
+            // Lights
+            if (scene.lightsEnabled && !this.disableLighting) {
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights);          
+            }
+
+            // View
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
+            }
+
+            // Fog
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+
+            this._afterBind(mesh, this._activeEffect);
+        }
+
+        public getAnimatables(): IAnimatable[] {
+            var results = [];
+
+            if (this._diffuseTexture && this._diffuseTexture.animations && this._diffuseTexture.animations.length > 0) {
+                results.push(this._diffuseTexture);
+            }
+
+            return results;
+        }
+
+        public dispose(forceDisposeEffect?: boolean): void {
+            if (this._diffuseTexture) {
+                this._diffuseTexture.dispose();
+            }
+
+            super.dispose(forceDisposeEffect);
+        }
+
+        public clone(name: string): CellMaterial {
+            return SerializationHelper.Clone<CellMaterial>(() => new CellMaterial(name, this.getScene()), this);
+        }
+        
+        public serialize(): any {
+            var serializationObject = SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.CellMaterial";
+            return serializationObject;
+        }
+
+        // Statics
+        public static Parse(source: any, scene: Scene, rootUrl: string): CellMaterial {
+            return SerializationHelper.Parse(() => new CellMaterial(source.name, scene), source, scene, rootUrl);
+        }
+    }
+} 
+

+ 144 - 0
materialsLibrary/src/cell/cell.fragment.fx

@@ -0,0 +1,144 @@
+precision highp float;
+
+// Constants
+uniform vec3 vEyePosition;
+uniform vec4 vDiffuseColor;
+
+// Input
+varying vec3 vPositionW;
+
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+// Lights
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
+
+#include<lightsFragmentFunctions>
+#include<shadowsFragmentFunctions>
+
+// Samplers
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform sampler2D diffuseSampler;
+uniform vec2 vDiffuseInfos;
+#endif
+
+#include<clipPlaneFragmentDeclaration>
+
+// Fog
+#include<fogFragmentDeclaration>
+
+// Custom
+vec3 computeCustomDiffuseLighting(lightingInfo info, vec3 diffuseBase, float shadow)
+{
+	diffuseBase = info.diffuse * shadow;
+
+#ifdef CELLBASIC
+	float level = 1.0;
+	if (info.ndl < 0.5)
+		level = 0.5;
+	
+	diffuseBase.rgb * vec3(level, level, level);
+#else
+	float ToonThresholds[4];
+	ToonThresholds[0] = 0.95;
+	ToonThresholds[1] = 0.5;
+	ToonThresholds[2] = 0.2;
+	ToonThresholds[3] = 0.03;
+
+	float ToonBrightnessLevels[5];
+	ToonBrightnessLevels[0] = 1.0;
+	ToonBrightnessLevels[1] = 0.8;
+	ToonBrightnessLevels[2] = 0.6;
+	ToonBrightnessLevels[3] = 0.35;
+	ToonBrightnessLevels[4] = 0.2;
+
+	if (info.ndl > ToonThresholds[0])
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[0];
+	}
+	else if (info.ndl > ToonThresholds[1])
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[1];
+	}
+	else if (info.ndl > ToonThresholds[2])
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[2];
+	}
+	else if (info.ndl > ToonThresholds[3])
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[3];
+	}
+	else
+	{
+		diffuseBase.rgb *= ToonBrightnessLevels[4];
+	}
+#endif
+
+	return max(diffuseBase, vec3(0.2));
+}
+
+void main(void)
+{
+#include<clipPlaneFragment>
+
+	vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
+
+	// Base color
+	vec4 baseColor = vec4(1., 1., 1., 1.);
+	vec3 diffuseColor = vDiffuseColor.rgb;
+
+	// Alpha
+	float alpha = vDiffuseColor.a;
+
+#ifdef DIFFUSE
+	baseColor = texture2D(diffuseSampler, vDiffuseUV);
+
+#ifdef ALPHATEST
+	if (baseColor.a < 0.4)
+		discard;
+#endif
+
+	baseColor.rgb *= vDiffuseInfos.y;
+#endif
+
+#ifdef VERTEXCOLOR
+	baseColor.rgb *= vColor.rgb;
+#endif
+
+	// Normal
+#ifdef NORMAL
+	vec3 normalW = normalize(vNormalW);
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+#endif
+
+	// Lighting
+    lightingInfo info;
+	vec3 diffuseBase = vec3(0., 0., 0.);
+	float shadow = 1.;
+    float glossiness = 0.;
+
+#ifdef SPECULARTERM
+	vec3 specularBase = vec3(0., 0., 0.);
+#endif    
+#include<lightFragment>[0..maxSimultaneousLights]
+
+#ifdef VERTEXALPHA
+	alpha *= vColor.a;
+#endif
+
+	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;;
+
+	// Composition
+	vec4 color = vec4(finalDiffuse, alpha);
+
+#include<fogFragment>
+
+	gl_FragColor = color;
+}

+ 101 - 0
materialsLibrary/src/cell/cell.vertex.fx

@@ -0,0 +1,101 @@
+precision highp float;
+
+// Attributes
+attribute vec3 position;
+#ifdef NORMAL
+attribute vec3 normal;
+#endif
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#ifdef VERTEXCOLOR
+attribute vec4 color;
+#endif
+
+#include<bonesDeclaration>
+
+// Uniforms
+#include<instancesDeclaration>
+
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform mat4 diffuseMatrix;
+uniform vec2 vDiffuseInfos;
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif
+
+// Output
+varying vec3 vPositionW;
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+
+#include<clipPlaneVertexDeclaration>
+
+#include<fogVertexDeclaration>
+#include<shadowsVertexDeclaration>[0..maxSimultaneousLights]
+
+void main(void) {
+
+#include<instancesVertex>
+#include<bonesVertex>
+
+	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+
+	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vPositionW = vec3(worldPos);
+
+#ifdef NORMAL
+	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+#endif
+
+	// Texture coordinates
+#ifndef UV1
+	vec2 uv = vec2(0., 0.);
+#endif
+#ifndef UV2
+	vec2 uv2 = vec2(0., 0.);
+#endif
+
+#ifdef DIFFUSE
+	if (vDiffuseInfos.x == 0.)
+	{
+		vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+	// Clip plane
+#include<clipPlaneVertex>
+
+    // Fog
+#include<fogVertex>
+#include<shadowsVertex>[0..maxSimultaneousLights]
+
+	// Vertex color
+#ifdef VERTEXCOLOR
+	vColor = color;
+#endif
+
+	// Point size
+#ifdef POINTSIZE
+	gl_PointSize = pointSize;
+#endif
+}

+ 47 - 47
materialsLibrary/src/custom/babylon.customMaterial.ts

@@ -20,11 +20,11 @@ module BABYLON {
     constructor(){}
 
     public Fragment_Begin:string;
-    public Fragment_Definations:string;
+    public Fragment_Definitions:string;
     public Fragment_MainBegin: string;
     
     // diffuseColor
-    public Fragment_Custom_Deffiuse: string;
+    public Fragment_Custom_Diffuse: string;
     
     // alpha
     public Fragment_Custom_Alpha : string;
@@ -32,14 +32,14 @@ module BABYLON {
     public Fragment_Before_FragColor: string;
 
     public Vertex_Begin:string;
-    public Vertex_Definations:string;
+    public Vertex_Definitions:string;
     public Vertex_MainBegin: string;
     
     // positionUpdated
-    public Vertex_Befor_PositionUpdated:string;
+    public Vertex_Before_PositionUpdated:string;
 
     // normalUpdated
-    public Vertex_Befor_NormalUpdated : string;
+    public Vertex_Before_NormalUpdated : string;
   }
 
   export class ShaderForVer3_0 extends CustomShaderStructure {
@@ -138,7 +138,7 @@ varying vec3 vDirectionW;\n\
 #include<logDepthDeclaration>\n\
 #include<fogFragmentDeclaration>\n\
 \n\
-#[Fragment_Definations]\n\
+#[Fragment_Definitions]\n\
 \n\
 void main(void) {\n\
 \n\
@@ -149,7 +149,7 @@ vec3 viewDirectionW=normalize(vEyePosition-vPositionW);\n\
 \n\
 vec4 baseColor=vec4(1.,1.,1.,1.);\n\
 vec3 diffuseColor=vDiffuseColor.rgb;\n\
-#[Fragment_Custom_Deffiuse]\n\
+#[Fragment_Custom_Diffuse]\n\
 \n\
 float alpha=vDiffuseColor.a;\n\
 #[Fragment_Custom_Alpha]\n\
@@ -413,7 +413,7 @@ varying vec3 vDirectionW;\n\
 #endif\n\
 #include<logDepthDeclaration>\n\
 \n\
-#[Vertex_Definations]\n\
+#[Vertex_Definitions]\n\
 \n\
 void main(void) {\n\
     \n\
@@ -433,14 +433,14 @@ vPositionUVW=positionUpdated;\n\
 #include<instancesVertex>\n\
 #include<bonesVertex>\n\
 \n\
-#[Vertex_Befor_PositionUpdated]\n\
+#[Vertex_Before_PositionUpdated]\n\
 \n\
 gl_Position=viewProjection*finalWorld*vec4(positionUpdated,1.0);\n\
 vec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\n\
 vPositionW=vec3(worldPos);\n\
 #ifdef NORMAL\n\
 \n\
-#[Vertex_Befor_NormalUpdated]\n\
+#[Vertex_Before_NormalUpdated]\n\
 \n\
 vNormalW=normalize(vec3(finalWorld*vec4(normalUpdated,0.0)));\n\
 #endif\n\
@@ -552,19 +552,19 @@ vColor=color;\n\
          public static ShaderIndexer = 1;
          public CustomParts :  ShaderSpecialParts;
          public ShaderVersion : CustomShaderStructure ;
-         _customUnifrom : string[];
-         _newUnifroms : string[];
-         _newUnifromInstances : any[];
+         _customUniform : string[];
+         _newUniforms : string[];
+         _newUniformInstances : any[];
          _newSamplerInstances : Texture[];
 
          public AttachAfterBind(mesh:Mesh,effect:Effect){ 
-             for(var el in this._newUnifromInstances){
+             for(var el in this._newUniformInstances){
                  var ea = el.toString().split('-');
-                 if(ea[0] == 'vec2') effect.setVector2(ea[1],this._newUnifromInstances[el]);
-                 else if(ea[0] == 'vec3') effect.setVector3(ea[1],this._newUnifromInstances[el]);
-                 else if(ea[0] == 'vec4') effect.setVector4(ea[1],this._newUnifromInstances[el]);
-                 else if(ea[0] == 'mat4') effect.setMatrix(ea[1],this._newUnifromInstances[el]);
-                 else if(ea[0] == 'float') effect.setFloat(ea[1],this._newUnifromInstances[el]); 
+                 if(ea[0] == 'vec2') effect.setVector2(ea[1],this._newUniformInstances[el]);
+                 else if(ea[0] == 'vec3') effect.setVector3(ea[1],this._newUniformInstances[el]);
+                 else if(ea[0] == 'vec4') effect.setVector4(ea[1],this._newUniformInstances[el]);
+                 else if(ea[0] == 'mat4') effect.setMatrix(ea[1],this._newUniformInstances[el]);
+                 else if(ea[0] == 'float') effect.setFloat(ea[1],this._newUniformInstances[el]); 
              }
 
               for(var el in this._newSamplerInstances){ 
@@ -577,16 +577,16 @@ vColor=color;\n\
          public ReviewUniform(name:string, arr : string[] ) : string[]{
              if(name == "uniform")
               {
-                  for(var ind in this._newUnifroms)
-                    if(this._customUnifrom[ind].indexOf('sampler')== -1) 
-                        arr.push(this._newUnifroms[ind]);
+                  for(var ind in this._newUniforms)
+                    if(this._customUniform[ind].indexOf('sampler')== -1) 
+                        arr.push(this._newUniforms[ind]);
               }
 
                  if(name == "sampler")
               {
-                   for(var ind in this._newUnifroms)
-                    if(this._customUnifrom[ind].indexOf('sampler')!= -1) 
-                        arr.push(this._newUnifroms[ind]);
+                   for(var ind in this._newUniforms)
+                    if(this._customUniform[ind].indexOf('sampler')!= -1) 
+                        arr.push(this._newUniforms[ind]);
               }
 
              return arr;
@@ -608,16 +608,16 @@ vColor=color;\n\
 
             BABYLON.Effect.ShadersStore[name+"VertexShader"] = this.ShaderVersion.VertexStore
             .replace('#[Vertex_Begin]',(this.CustomParts.Vertex_Begin ? this.CustomParts.Vertex_Begin : ""))
-            .replace('#[Vertex_Definations]',(this._customUnifrom? this._customUnifrom.join("\n"):"")+ (this.CustomParts.Vertex_Definations ? this.CustomParts.Vertex_Definations : ""))
+            .replace('#[Vertex_Definitions]',(this._customUniform? this._customUniform.join("\n"):"")+ (this.CustomParts.Vertex_Definitions ? this.CustomParts.Vertex_Definitions : ""))
             .replace('#[Vertex_MainBegin]',(this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
-            .replace('#[Vertex_Befor_PositionUpdated]',(this.CustomParts.Vertex_Befor_PositionUpdated ? this.CustomParts.Vertex_Befor_PositionUpdated : ""))
-            .replace('#[Vertex_Befor_NormalUpdated]',(this.CustomParts.Vertex_Befor_NormalUpdated ? this.CustomParts.Vertex_Befor_NormalUpdated : "")) ;
+            .replace('#[Vertex_Before_PositionUpdated]',(this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
+            .replace('#[Vertex_Before_NormalUpdated]',(this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : "")) ;
 
             BABYLON.Effect.ShadersStore[name+"PixelShader"] = this.ShaderVersion.FragmentStore
             .replace('#[Fragment_Begin]',(this.CustomParts.Fragment_Begin ? this.CustomParts.Fragment_Begin : ""))
             .replace('#[Fragment_MainBegin]',(this.CustomParts.Fragment_MainBegin  ? this.CustomParts.Fragment_MainBegin : ""))
-            .replace('#[Fragment_Definations]',(this._customUnifrom? this._customUnifrom.join("\n"):"")+(this.CustomParts.Fragment_Definations ? this.CustomParts.Fragment_Definations : ""))
-            .replace('#[Fragment_Custom_Deffiuse]',(this.CustomParts.Fragment_Custom_Deffiuse ? this.CustomParts.Fragment_Custom_Deffiuse : ""))
+            .replace('#[Fragment_Definitions]',(this._customUniform? this._customUniform.join("\n"):"")+(this.CustomParts.Fragment_Definitions ? this.CustomParts.Fragment_Definitions : ""))
+            .replace('#[Fragment_Custom_Diffuse]',(this.CustomParts.Fragment_Custom_Diffuse ? this.CustomParts.Fragment_Custom_Diffuse : ""))
             .replace('#[Fragment_Custom_Alpha]',(this.CustomParts.Fragment_Custom_Alpha ? this.CustomParts.Fragment_Custom_Alpha : ""))
             .replace('#[Fragment_Before_FragColor]',(this.CustomParts.Fragment_Before_FragColor ? this.CustomParts.Fragment_Before_FragColor : "")) ;
  
@@ -639,24 +639,24 @@ vColor=color;\n\
             this.SelectVersion("3.0.0"); 
          } 
          public AddUniform(name:string,kind:string,param:any):CustomMaterial{
-             if(!this._customUnifrom)
+             if(!this._customUniform)
               {  
-                  this._customUnifrom = new Array();
-                  this._newUnifroms = new Array();
+                  this._customUniform = new Array();
+                  this._newUniforms = new Array();
                   this._newSamplerInstances = new Array();
-                  this._newUnifromInstances = new Array();
+                  this._newUniformInstances = new Array();
               }
               if(param){
               if(kind.indexOf("sampler") == -1) {
-                    this._newUnifromInstances[kind+"-"+name] = param;
+                    this._newUniformInstances[kind+"-"+name] = param;
               }
               else{
                   this._newSamplerInstances[kind+"-"+name] = param;
               }
              }
 
-            this._customUnifrom.push("uniform "+kind+" "+name+";");
-            this._newUnifroms.push(name);
+            this._customUniform.push("uniform "+kind+" "+name+";");
+            this._newUniforms.push(name);
              
             return this;
          }
@@ -665,8 +665,8 @@ vColor=color;\n\
             return this;
          }
 
-         public Fragment_Definations(shaderPart:string):CustomMaterial{            
-            this.CustomParts.Fragment_Definations = shaderPart;
+         public Fragment_Definitions(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Fragment_Definitions = shaderPart;
             return this;
          }
 
@@ -674,8 +674,8 @@ vColor=color;\n\
             this.CustomParts.Fragment_MainBegin = shaderPart;
             return this;
          }
-         public Fragment_Custom_Deffiuse(shaderPart:string):CustomMaterial{            
-            this.CustomParts.Fragment_Custom_Deffiuse = shaderPart.replace("result","diffuseColor");
+         public Fragment_Custom_Diffuse(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Fragment_Custom_Diffuse = shaderPart.replace("result","diffuseColor");
             return this;
          }
          public Fragment_Custom_Alpha(shaderPart:string):CustomMaterial{            
@@ -690,21 +690,21 @@ vColor=color;\n\
             this.CustomParts.Vertex_Begin = shaderPart;
             return this;
          }
-         public Vertex_Definations(shaderPart:string):CustomMaterial{            
-            this.CustomParts.Vertex_Definations = shaderPart;
+         public Vertex_Definitions(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Vertex_Definitions = shaderPart;
             return this;
          }
          public Vertex_MainBegin(shaderPart:string):CustomMaterial{            
             this.CustomParts.Vertex_MainBegin = shaderPart;
             return this;
          }
-         public Vertex_Befor_PositionUpdated(shaderPart:string):CustomMaterial{            
-            this.CustomParts.Vertex_Befor_PositionUpdated = shaderPart.replace("result","positionUpdated");
+         public Vertex_Before_PositionUpdated(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Vertex_Before_PositionUpdated = shaderPart.replace("result","positionUpdated");
             return this;
          } 
          
-          public Vertex_Befor_NormalUpdated(shaderPart:string):CustomMaterial{            
-            this.CustomParts.Vertex_Befor_NormalUpdated = shaderPart.replace("result","normalUpdated");
+          public Vertex_Before_NormalUpdated(shaderPart:string):CustomMaterial{            
+            this.CustomParts.Vertex_Before_NormalUpdated = shaderPart.replace("result","normalUpdated");
             return this;
          } 
           

+ 3 - 3
materialsLibrary/src/custom/readme.md

@@ -56,10 +56,10 @@ method : Fragment_MainBegin(shaderPart:string):CustomMaterial
 > shaderPart is Shader Structure append in start place of the main function in fragment shader 
 
 
-method : Fragment_Custom_Deffiuse(shaderPart:string):CustomMaterial 
+method : Fragment_Custom_Diffuse(shaderPart:string):CustomMaterial 
 > shaderPart is Shader Structure append after diffuseColor is defined of the main function in fragment shader </br>
-> usage : new CustomMaterial(...).Fragment_Custom_Deffiuse('diffuseColor = vec3(sin(vPositionW.x));')  </br>
->       : new CustomMaterial(...).Fragment_Custom_Deffiuse('result = vec3(sin(vPositionW.x));')  </br>
+> usage : new CustomMaterial(...).Fragment_Custom_Diffuse('diffuseColor = vec3(sin(vPositionW.x));')  </br>
+>       : new CustomMaterial(...).Fragment_Custom_Diffuse('result = vec3(sin(vPositionW.x));')  </br>
 > * diffuseColor is vec3 variable </br>
 > * you can use result (vec3) too that replaced by diffuseColor
 

+ 1 - 1
materialsLibrary/src/fur/readme.md

@@ -46,7 +46,7 @@ The leopard fur texture used in the test is by Martin Wegmann from [Wikimedia Co
 under the [license](https://creativecommons.org/licenses/by-sa/3.0/deed.en)
 
 ```
-furMaterial.diffuseTexture = new BABYLON.Texture("leopard_fur.jpg", scene); // Set the fur length with a texture.
+furMaterial.diffuseTexture = new BABYLON.Texture("leopard_fur.JPG, scene); // Set the fur length with a texture.
 ```
 
 # Using the High Level mode

+ 22 - 0
materialsLibrary/test/addCell.js

@@ -0,0 +1,22 @@
+window.prepareCell = function() {
+    var cell = new BABYLON.CellMaterial("cell", scene);
+	cell.diffuseTexture = new BABYLON.Texture("../assets/textures//amiga.jpg", scene);
+	cell.diffuseTexture.uScale = cell.diffuseTexture.vScale = 3;
+	cell.computeHighLevel = true;
+
+    registerRangeUI("cell", "Hight Level Cell", false, true, function(value) {
+        cell.computeHighLevel = value;
+    }, function() {
+        return cell.computeHighLevel;
+    });
+
+    registerColorPicker("cell", "Diffuse Color", "#FFFFFF", function(value) {		
+		cell.diffuseColor.r = value.r/255;
+		cell.diffuseColor.g = value.g/255;
+		cell.diffuseColor.b = value.b/255;
+	}, function() {
+		return cell.diffuseColor;
+	});
+
+    return cell;
+};

+ 1 - 1
materialsLibrary/test/addfur.js

@@ -2,7 +2,7 @@ window.prepareFur = function() {
 	var shells = 30;
 	var meshes = [];
 	
-	var diffuseTexture = new BABYLON.Texture("../assets/textures/leopard_fur.jpg", scene);
+	var diffuseTexture = new BABYLON.Texture("../assets/textures/leopard_fur.JPG", scene);
 	var heightTexture = new BABYLON.Texture("../assets/textures/speckles.jpg", scene);
 	var furTexture = BABYLON.FurMaterial.GenerateTexture("furTexture", scene);
 	

+ 1 - 1
materialsLibrary/test/addterrain.js

@@ -7,7 +7,7 @@ window.prepareTerrain = function() {
     terrain.diffuseTexture2 = new BABYLON.Texture("../assets/textures/rock.png", scene);
     terrain.diffuseTexture3 = new BABYLON.Texture("../assets/textures/grass.png", scene);
     
-    terrain.bumpTexture1 = new BABYLON.Texture("../assets/textures/floor_bump.png", scene);
+    terrain.bumpTexture1 = new BABYLON.Texture("../assets/textures/floor_bump.PNG", scene);
     terrain.bumpTexture2 = new BABYLON.Texture("../assets/textures/rockn.png", scene);
     terrain.bumpTexture3 = new BABYLON.Texture("../assets/textures/grassn.png", scene);
     

+ 14 - 4
src/Audio/babylon.audioEngine.ts

@@ -28,12 +28,22 @@
 
             var audioElem = document.createElement('audio');
 
-            if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '')) {
-                this.isMP3supported = true;
+            try {
+                if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '')) {
+                    this.isMP3supported = true;
+                }
+            }
+            catch (e) {
+                // protect error during capability check.
             }
 
-            if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '')) {
-                this.isOGGsupported = true;
+            try {
+                if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '')) {
+                    this.isOGGsupported = true;
+                }
+            }
+            catch (e) {
+                // protect error during capability check.
             }
 
             if (/iPad|iPhone|iPod/.test(navigator.platform)) {

+ 0 - 10
src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts

@@ -24,8 +24,6 @@ module BABYLON {
 
         private _pointerInput: (p: PointerInfo, s: EventState) => void;
         private _observer: Observer<PointerInfo>;
-        private _onKeyDown: (e: KeyboardEvent) => any;
-        private _onKeyUp: (e: KeyboardEvent) => any;
         private _onMouseMove: (e: MouseEvent) => any;
         private _onGestureStart: (e: PointerEvent) => void;
         private _onGesture: (e: MSGestureEvent) => void;
@@ -202,9 +200,6 @@ module BABYLON {
             element.addEventListener("MSPointerDown", this._onGestureStart, false);
             element.addEventListener("MSGestureChange", this._onGesture, false);
 
-            element.addEventListener("keydown", this._onKeyDown, false);
-            element.addEventListener("keyup", this._onKeyUp, false);
-
             Tools.RegisterTopRootEvents([
                 { name: "blur", handler: this._onLostFocus }
             ]);
@@ -220,14 +215,9 @@ module BABYLON {
                 element.removeEventListener("MSPointerDown", this._onGestureStart);
                 element.removeEventListener("MSGestureChange", this._onGesture);
 
-                element.removeEventListener("keydown", this._onKeyDown);
-                element.removeEventListener("keyup", this._onKeyUp);
-
                 this._isPanClick = false;
                 this.pinchInwards = true;
 
-                this._onKeyDown = null;
-                this._onKeyUp = null;
                 this._onMouseMove = null;
                 this._onGestureStart = null;
                 this._onGesture = null;

+ 8 - 2
src/Lights/babylon.light.ts

@@ -222,11 +222,11 @@
                 return true;
             }
 
-            if (this.includedOnlyMeshes.length > 0 && this.includedOnlyMeshes.indexOf(mesh) === -1) {
+            if (this.includedOnlyMeshes && this.includedOnlyMeshes.length > 0 && this.includedOnlyMeshes.indexOf(mesh) === -1) {
                 return false;
             }
 
-            if (this.excludedMeshes.length > 0 && this.excludedMeshes.indexOf(mesh) !== -1) {
+            if (this.excludedMeshes && this.excludedMeshes.length > 0 && this.excludedMeshes.indexOf(mesh) !== -1) {
                 return false;
             }
 
@@ -414,6 +414,10 @@
 
                 return deleted;
             }
+
+            for (var item of array) {
+                item._resyncLighSource(this);
+            }
         }
 
         private _hookArrayForIncludedOnly(array: AbstractMesh[]): void {
@@ -434,6 +438,8 @@
 
                 return deleted;
             }
+
+            this._resyncMeshes();
         }
 
         private _resyncMeshes() {

+ 5 - 5
src/Materials/babylon.material.ts

@@ -170,11 +170,11 @@
             return Material._CounterClockWiseSideOrientation;
         }
 
-        private static _TextureDirtyFlag = 0;
-        private static _LightDirtyFlag = 1;
-        private static _FresnelDirtyFlag = 2;
-        private static _AttributesDirtyFlag = 4;
-        private static _MiscDirtyFlag = 8;
+        private static _TextureDirtyFlag = 1;
+        private static _LightDirtyFlag = 2;
+        private static _FresnelDirtyFlag = 4;
+        private static _AttributesDirtyFlag = 8;
+        private static _MiscDirtyFlag = 16;
 
         public static get TextureDirtyFlag(): number {
             return Material._TextureDirtyFlag;

+ 2 - 2
src/Materials/babylon.pbrMaterial.ts

@@ -554,11 +554,11 @@
             this.getRenderTargetTextures = (): SmartArray<RenderTargetTexture> => {
                 this._renderTargets.reset();
 
-                if (this.reflectionTexture && this.reflectionTexture.isRenderTarget) {
+                if (StandardMaterial.ReflectionTextureEnabled && this.reflectionTexture && this.reflectionTexture.isRenderTarget) {
                     this._renderTargets.push(this.reflectionTexture);
                 }
 
-                if (this.refractionTexture && this.refractionTexture.isRenderTarget) {
+                if (StandardMaterial.RefractionTextureEnabled && this.refractionTexture && this.refractionTexture.isRenderTarget) {
                     this._renderTargets.push(this.refractionTexture);
                 }
 

+ 2 - 2
src/Materials/babylon.standardMaterial.ts

@@ -303,11 +303,11 @@ module BABYLON {
             this.getRenderTargetTextures = (): SmartArray<RenderTargetTexture> => {
                 this._renderTargets.reset();
 
-                if (this._reflectionTexture && this._reflectionTexture.isRenderTarget) {
+                if (StandardMaterial.ReflectionTextureEnabled && this._reflectionTexture && this._reflectionTexture.isRenderTarget) {
                     this._renderTargets.push(this._reflectionTexture);
                 }
 
-                if (this._refractionTexture && this._refractionTexture.isRenderTarget) {
+                if (StandardMaterial.RefractionTextureEnabled && this._refractionTexture && this._refractionTexture.isRenderTarget) {
                     this._renderTargets.push(this._refractionTexture);
                 }
 

+ 24 - 16
src/Mesh/babylon.geometry.ts

@@ -24,8 +24,8 @@
         private _vertexArrayObjects: { [key: string]: WebGLVertexArrayObject; };
 
         /**
-         *  The Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y 
-         * @returns The Bias Vector 
+         *  The Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y
+         * @returns The Bias Vector
          */
         public get boundingBias(): Vector2 {
             return this._boundingBias;
@@ -208,7 +208,7 @@
             }
         }
 
-        public _bind(effect: Effect, indexToBind: WebGLBuffer = undefined): void {  
+        public _bind(effect: Effect, indexToBind: WebGLBuffer = undefined): void {
             if (indexToBind === undefined) {
                 indexToBind = this._indexBuffer;
             }
@@ -352,7 +352,7 @@
             if (!effect || !this._vertexArrayObjects) {
                 return;
             }
-            
+
             if (this._vertexArrayObjects[effect.key]) {
                 this._engine.releaseVertexArrayObject(this._vertexArrayObjects[effect.key]);
                 delete this._vertexArrayObjects[effect.key];
@@ -635,74 +635,82 @@
             return serializationObject;
         }
 
+        private toNumberArray(origin: Float32Array | IndicesArray) : number[] {
+            if (Array.isArray(origin)) {
+                return origin;
+            } else {
+                return Array.prototype.slice.call(origin);
+            }
+        }
+
         public serializeVerticeData(): any {
             var serializationObject = this.serialize();
 
             if (this.isVerticesDataPresent(VertexBuffer.PositionKind)) {
-                serializationObject.positions = this.getVerticesData(VertexBuffer.PositionKind);
+                serializationObject.positions = this.toNumberArray(this.getVerticesData(VertexBuffer.PositionKind));
                 if (this.getVertexBuffer(VertexBuffer.PositionKind).isUpdatable) {
                     serializationObject.positions._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.NormalKind)) {
-                serializationObject.normals = this.getVerticesData(VertexBuffer.NormalKind);
+                serializationObject.normals = this.toNumberArray(this.getVerticesData(VertexBuffer.NormalKind));
                 if (this.getVertexBuffer(VertexBuffer.NormalKind).isUpdatable) {
                     serializationObject.normals._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UVKind)) {
-                serializationObject.uvs = this.getVerticesData(VertexBuffer.UVKind);
+                serializationObject.uvs = this.toNumberArray(this.getVerticesData(VertexBuffer.UVKind));
                 if (this.getVertexBuffer(VertexBuffer.UVKind).isUpdatable) {
                     serializationObject.uvs._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
-                serializationObject.uv2s = this.getVerticesData(VertexBuffer.UV2Kind);
+                serializationObject.uv2s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV2Kind));
                 if (this.getVertexBuffer(VertexBuffer.UV2Kind).isUpdatable) {
                     serializationObject.uv2s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV3Kind)) {
-                serializationObject.uv3s = this.getVerticesData(VertexBuffer.UV3Kind);
+                serializationObject.uv3s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV3Kind));
                 if (this.getVertexBuffer(VertexBuffer.UV3Kind).isUpdatable) {
                     serializationObject.uv3s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV4Kind)) {
-                serializationObject.uv4s = this.getVerticesData(VertexBuffer.UV4Kind);
+                serializationObject.uv4s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV4Kind));
                 if (this.getVertexBuffer(VertexBuffer.UV4Kind).isUpdatable) {
                     serializationObject.uv4s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV5Kind)) {
-                serializationObject.uv5s = this.getVerticesData(VertexBuffer.UV5Kind);
+                serializationObject.uv5s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV5Kind));
                 if (this.getVertexBuffer(VertexBuffer.UV5Kind).isUpdatable) {
                     serializationObject.uv5s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.UV6Kind)) {
-                serializationObject.uv6s = this.getVerticesData(VertexBuffer.UV6Kind);
+                serializationObject.uv6s = this.toNumberArray(this.getVerticesData(VertexBuffer.UV6Kind));
                 if (this.getVertexBuffer(VertexBuffer.UV6Kind).isUpdatable) {
                     serializationObject.uv6s._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.ColorKind)) {
-                serializationObject.colors = this.getVerticesData(VertexBuffer.ColorKind);
+                serializationObject.colors = this.toNumberArray(this.getVerticesData(VertexBuffer.ColorKind));
                 if (this.getVertexBuffer(VertexBuffer.ColorKind).isUpdatable) {
                     serializationObject.colors._updatable = true;
                 }
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
-                serializationObject.matricesIndices = this.getVerticesData(VertexBuffer.MatricesIndicesKind);
+                serializationObject.matricesIndices = this.toNumberArray(this.getVerticesData(VertexBuffer.MatricesIndicesKind));
                 serializationObject.matricesIndices._isExpanded = true;
                 if (this.getVertexBuffer(VertexBuffer.MatricesIndicesKind).isUpdatable) {
                     serializationObject.matricesIndices._updatable = true;
@@ -710,13 +718,13 @@
             }
 
             if (this.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
-                serializationObject.matricesWeights = this.getVerticesData(VertexBuffer.MatricesWeightsKind);
+                serializationObject.matricesWeights = this.toNumberArray(this.getVerticesData(VertexBuffer.MatricesWeightsKind));
                 if (this.getVertexBuffer(VertexBuffer.MatricesWeightsKind).isUpdatable) {
                     serializationObject.matricesWeights._updatable = true;
                 }
             }
 
-            serializationObject.indices = this.getIndices();
+            serializationObject.indices = this.toNumberArray(this.getIndices());
 
             return serializationObject;
         }

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

@@ -1287,7 +1287,7 @@
         public setMaterialByID(id: string): Mesh {
             var materials = this.getScene().materials;
             var index: number;
-            for (index = 0; index < materials.length; index++) {
+            for (index = materials.length - 1; index > -1; index--) {
                 if (materials[index].id === id) {
                     this.material = materials[index];
                     return this;
@@ -1296,7 +1296,7 @@
 
             // Multi
             var multiMaterials = this.getScene().multiMaterials;
-            for (index = 0; index < multiMaterials.length; index++) {
+            for (index = multiMaterials.length - 1; index > -1; index--) {
                 if (multiMaterials[index].id === id) {
                     this.material = multiMaterials[index];
                     return this;
@@ -2998,7 +2998,7 @@
             for (index = 0; index < meshes.length; index++) {
                 if (meshes[index]) {
                     meshes[index].computeWorldMatrix(true);
-                    otherVertexData = VertexData.ExtractFromMesh(meshes[index], false, true);
+                    otherVertexData = VertexData.ExtractFromMesh(meshes[index], true);
                     otherVertexData.transform(meshes[index].getWorldMatrix());
 
                     if (vertexData) {

+ 86 - 8
src/PostProcess/babylon.standardRenderingPipeline.ts

@@ -19,12 +19,13 @@ module BABYLON {
 
         public textureAdderFinalPostProcess: PostProcess = null;
         public lensFlareFinalPostProcess: PostProcess = null;
-
         public hdrFinalPostProcess: PostProcess = null;
 
         public lensFlarePostProcess: PostProcess = null;
         public lensFlareComposePostProcess: PostProcess = null;
 
+        public motionBlurPostProcess: PostProcess = null;
+
         public depthOfFieldPostProcess: PostProcess = null;
 
         // Values
@@ -75,6 +76,9 @@ module BABYLON {
         @serialize()
         public depthOfFieldBlurWidth: number = 2.0;
 
+        @serialize()
+        public motionStrength: number = 1.0;
+
         // IAnimatable
         public animations: Animation[] = [];
 
@@ -88,10 +92,13 @@ module BABYLON {
         private _currentHDRSource: PostProcess = null;
         private _hdrCurrentLuminance: number = 1.0;
 
+        private _motionBlurSamples: number = 64;
+
         // Getters and setters
         private _depthOfFieldEnabled: boolean = true;
         private _lensFlareEnabled: boolean = true;
         private _hdrEnabled: boolean = true;
+        private _motionBlurEnabled: boolean = true;
 
         public set DepthOfFieldEnabled(enabled: boolean) {
             var blurIndex = this.gaussianBlurHPostProcesses.length - 1;
@@ -170,6 +177,33 @@ module BABYLON {
             return this._hdrEnabled;
         }
 
+        public set MotionBlurEnabled(enabled: boolean) {
+            if (enabled && !this._motionBlurEnabled) {
+                this._scene.postProcessRenderPipelineManager.enableEffectInPipeline(this._name, "HDRMotionBlur", this._scene.cameras);
+                this._depthRenderer = this._scene.enableDepthRenderer();
+            }
+            else if (!enabled && this._motionBlurEnabled) {
+                this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRMotionBlur", this._scene.cameras);
+            }
+
+            this._motionBlurEnabled = enabled;
+        }
+
+        @serialize()
+        public get MotionBlurEnabled(): boolean {
+            return this._motionBlurEnabled;
+        }
+
+        @serialize()
+        public get motionBlurSamples(): number {
+            return this._motionBlurSamples;
+        }
+
+        public set motionBlurSamples(samples: number) {
+            this.motionBlurPostProcess.updateEffect("#define MOTION_BLUR\n#define MAX_MOTION_SAMPLES " + samples.toFixed(1));
+            this._motionBlurSamples = samples;
+        }
+
         /**
          * @constructor
          * @param {string} name - The rendering pipeline name
@@ -185,9 +219,12 @@ module BABYLON {
             // Initialize
             this._scene = scene;
 
-            // Create pass post-processe
+            // Misc
+            var floatTextureType = scene.getEngine().getCaps().textureFloatRender ? Engine.TEXTURETYPE_FLOAT : Engine.TEXTURETYPE_HALF_FLOAT;
+
+            // Create pass post-process
             if (!originalPostProcess) {
-                this.originalPostProcess = new PostProcess("HDRPass", "standard", [], [], ratio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define PASS_POST_PROCESS", Engine.TEXTURETYPE_FLOAT);
+                this.originalPostProcess = new PostProcess("HDRPass", "standard", [], [], ratio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define PASS_POST_PROCESS", floatTextureType);
             }
             else {
                 this.originalPostProcess = originalPostProcess;
@@ -222,12 +259,12 @@ module BABYLON {
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), "HDRPostLensFlareDepthOfFieldSource", () => { return this.lensFlareFinalPostProcess; }, true));
 
             // Create luminance
-            this._createLuminancePostProcesses(scene);
+            this._createLuminancePostProcesses(scene, floatTextureType);
 
             // Create HDR
             this._createHdrPostProcess(scene, ratio);
 
-            // Create depth-of-field source post-process post lens-flare and disable it now
+            // Create depth-of-field source post-process post hdr and disable it now
             this.hdrFinalPostProcess = new PostProcess("HDRPostHDReDepthOfFieldSource", "standard", [], [], ratio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define PASS_POST_PROCESS", Engine.TEXTURETYPE_UNSIGNED_INT);
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), "HDRPostHDReDepthOfFieldSource", () => { return this.hdrFinalPostProcess; }, true));
 
@@ -237,6 +274,9 @@ module BABYLON {
             // Create depth-of-field post-process
             this._createDepthOfFieldPostProcess(scene, ratio);
 
+            // Create motion blur post-process
+            this._createMotionBlurPostProcess(scene, ratio);
+
             // Finish
             scene.postProcessRenderPipelineManager.addPipeline(this);
 
@@ -248,6 +288,7 @@ module BABYLON {
             this.LensFlareEnabled = false;
             this.DepthOfFieldEnabled = false;
             this.HDREnabled = false;
+            this.MotionBlurEnabled = false;
         }
 
         // Down Sample X4 Post-Processs
@@ -374,10 +415,10 @@ module BABYLON {
         }
 
         // Create luminance
-        private _createLuminancePostProcesses(scene: Scene): void {
+        private _createLuminancePostProcesses(scene: Scene, textureType: number): void {
             // Create luminance
             var size = Math.pow(3, StandardRenderingPipeline.LuminanceSteps);
-            this.luminancePostProcess = new PostProcess("HDRLuminance", "standard", ["lumOffsets"], [], { width: size, height: size }, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define LUMINANCE", Engine.TEXTURETYPE_FLOAT);
+            this.luminancePostProcess = new PostProcess("HDRLuminance", "standard", ["lumOffsets"], [], { width: size, height: size }, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define LUMINANCE", textureType);
 
             var offsets: number[] = [];
             this.luminancePostProcess.onApply = (effect: Effect) => {
@@ -408,7 +449,7 @@ module BABYLON {
                     defines += "#define FINAL_DOWN_SAMPLER";
                 }
 
-                var postProcess = new PostProcess("HDRLuminanceDownSample" + i, "standard", ["dsOffsets", "halfDestPixelSize"], [], { width: size, height: size }, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, defines, Engine.TEXTURETYPE_FLOAT);
+                var postProcess = new PostProcess("HDRLuminanceDownSample" + i, "standard", ["dsOffsets", "halfDestPixelSize"], [], { width: size, height: size }, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, defines, textureType);
                 this.luminanceDownSamplePostProcesses.push(postProcess);
             }
 
@@ -575,6 +616,42 @@ module BABYLON {
             this.addEffect(new PostProcessRenderEffect(scene.getEngine(), "HDRDepthOfField", () => { return this.depthOfFieldPostProcess; }, true));
         }
 
+        // Create motion blur post-process
+        private _createMotionBlurPostProcess(scene: Scene, ratio: number): void {
+            this.motionBlurPostProcess = new PostProcess("HDRMotionBlur", "standard",
+                ["inverseViewProjection", "prevViewProjection", "screenSize", "motionScale", "motionStrength"],
+                ["depthSampler"],
+                ratio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define MOTION_BLUR\n#define MAX_MOTION_SAMPLES " + this.motionBlurSamples.toFixed(1), Engine.TEXTURETYPE_UNSIGNED_INT);
+
+            var motionScale: number = 0;
+            var prevViewProjection = Matrix.Identity();
+            var invViewProjection = Matrix.Identity();
+            var viewProjection = Matrix.Identity();
+            var screenSize = Vector2.Zero();
+
+            this.motionBlurPostProcess.onApply = (effect: Effect) => {
+                viewProjection = scene.getProjectionMatrix().multiply(scene.getViewMatrix());
+
+                viewProjection.invertToRef(invViewProjection);
+                effect.setMatrix("inverseViewProjection", invViewProjection);
+
+                effect.setMatrix("prevViewProjection", prevViewProjection);
+                prevViewProjection = viewProjection;
+
+                screenSize.x = this.motionBlurPostProcess.width;
+                screenSize.y = this.motionBlurPostProcess.height;
+                effect.setVector2("screenSize", screenSize);
+
+                motionScale = scene.getEngine().getFps() / 60.0;
+                effect.setFloat("motionScale", motionScale);
+                effect.setFloat("motionStrength", this.motionStrength);
+
+                effect.setTexture("depthSampler", this._depthRenderer.getDepthMap());
+            };
+
+            this.addEffect(new PostProcessRenderEffect(scene.getEngine(), "HDRMotionBlur", () => { return this.motionBlurPostProcess; }, true));
+        }
+
         // Dispose
         public dispose(): void {
             for (var i = 0; i < this._cameras.length; i++) {
@@ -597,6 +674,7 @@ module BABYLON {
                 this.lensFlarePostProcess.dispose(camera);
                 this.lensFlareComposePostProcess.dispose(camera);
                 this.depthOfFieldPostProcess.dispose(camera);
+                this.motionBlurPostProcess.dispose(camera);
             }
 
             this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._cameras);

+ 6 - 1
src/Shaders/ShadersInclude/lightFragment.fx

@@ -37,7 +37,12 @@
 	#else
 		shadow = 1.;
 	#endif
-    #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})
+	#ifdef CUSTOMUSERLIGHTING
+		diffuseBase += computeCustomDiffuseLighting(info, diffuseBase, shadow);
+		#ifdef SPECULARTERM
+			specularBase += computeCustomSpecularLighting(info, specularBase, shadow);
+		#endif
+    #elif defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})
 	    diffuseBase += lightmapColor * shadow;
 	    #ifdef SPECULARTERM
             #ifndef LIGHTMAPNOSPECULAR{X}

+ 17 - 0
src/Shaders/ShadersInclude/lightsFragmentFunctions.fx

@@ -5,6 +5,9 @@ struct lightingInfo
 #ifdef SPECULARTERM
 	vec3 specular;
 #endif
+#ifdef NDOTL
+	float ndl;
+#endif
 };
 
 lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float glossiness) {
@@ -26,6 +29,10 @@ lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData,
 
 	// diffuse
 	float ndl = max(0., dot(vNormal, lightVectorW));
+#ifdef NDOTL
+	result.ndl = ndl;
+#endif
+
 	result.diffuse = ndl * diffuseColor * attenuation;
 
 #ifdef SPECULARTERM
@@ -56,6 +63,9 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
 
 		// Diffuse
 		float ndl = max(0., dot(vNormal, lightVectorW));
+#ifdef NDOTL
+		result.ndl = ndl;
+#endif
 		result.diffuse = ndl * diffuseColor * attenuation;
 
 #ifdef SPECULARTERM
@@ -73,6 +83,9 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
 #ifdef SPECULARTERM
 	result.specular = vec3(0.);
 #endif
+#ifdef NDOTL
+	result.ndl = 0.;
+#endif
 
 	return result;
 }
@@ -82,6 +95,10 @@ lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4
 
 	// Diffuse
 	float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
+#ifdef NDOTL
+	result.ndl = ndl;
+#endif
+
 	result.diffuse = mix(groundColor, diffuseColor, ndl);
 
 #ifdef SPECULARTERM

+ 40 - 0
src/Shaders/standard.fragment.fx

@@ -356,5 +356,45 @@ void main(void)
 	factor = clamp(factor, 0.0, 0.90);
 	gl_FragColor = mix(sharp, blur, factor);
 }
+#endif
+
+#if defined(MOTION_BLUR)
+uniform mat4 inverseViewProjection;
+uniform mat4 prevViewProjection;
+
+uniform vec2 screenSize;
+
+uniform float motionScale;
+uniform float motionStrength;
+
+uniform sampler2D depthSampler;
+
+void main(void)
+{
+	vec2 texelSize = 1.0 / screenSize;
+	float depth = texture2D(depthSampler, vUV).r;
+
+	vec4 cpos = vec4(vUV * 2.0 - 1.0, depth, 1.0);
+	cpos = cpos * inverseViewProjection;
+
+	vec4 ppos = cpos * prevViewProjection;
+	ppos.xyz /= ppos.w;
+	ppos.xy = ppos.xy * 0.5 + 0.5;
+
+	vec2 velocity = (ppos.xy - vUV) * motionScale * motionStrength;
+	float speed = length(velocity / texelSize);
+	int nSamples = int(clamp(speed, 1.0, MAX_MOTION_SAMPLES));
 
+	vec4 result = texture2D(textureSampler, vUV);
+
+	for (int i = 1; i < int(MAX_MOTION_SAMPLES); ++i) {
+		if (i >= nSamples)
+			break;
+		
+		vec2 offset1 = vUV + velocity * (float(i) / float(nSamples - 1) - 0.5);
+		result += texture2D(textureSampler, offset1);
+	}
+
+	gl_FragColor = result / float(nSamples);
+}
 #endif