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

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

noalak пре 8 година
родитељ
комит
5c63a8500e
100 измењених фајлова са 50401 додато и 28443 уклоњено
  1. 2 0
      Playground/indexStable.html
  2. 0 158
      Playground/js/perf.js
  3. 0 77
      Playground/perf.html
  4. 21 11
      Tools/Gulp/config.json
  5. 1465 1384
      dist/preview release/babylon.d.ts
  6. 47 47
      dist/preview release/babylon.js
  7. 711 332
      dist/preview release/babylon.max.js
  8. 1465 1384
      dist/preview release/babylon.module.d.ts
  9. 47 47
      dist/preview release/babylon.worker.js
  10. 3660 3579
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  11. 51 37
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  12. 37756 17519
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  13. 3660 3579
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  14. 69 3
      dist/preview release/gui/babylon.gui.d.ts
  15. 378 14
      dist/preview release/gui/babylon.gui.js
  16. 3 3
      dist/preview release/gui/babylon.gui.min.js
  17. 69 3
      dist/preview release/gui/babylon.gui.module.d.ts
  18. 2 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.js
  19. 1 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.min.js
  20. 2 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.js
  21. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.min.js
  22. 2 1
      dist/preview release/materialsLibrary/babylon.furMaterial.js
  23. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.min.js
  24. 2 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.js
  25. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js
  26. 2 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.js
  27. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js
  28. 2 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  29. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  30. 2 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.js
  31. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js
  32. 2 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  33. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  34. 2 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js
  35. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js
  36. 1 0
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  37. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  38. 6 3
      dist/preview release/what's new.md
  39. 58 7
      gui/src/advancedDynamicTexture.ts
  40. 10 0
      gui/src/controls/container.ts
  41. 11 0
      gui/src/controls/control.ts
  42. 216 11
      gui/src/controls/inputText.ts
  43. 136 0
      gui/src/controls/virtualKeyboard.ts
  44. 0 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  45. 48 48
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  46. 3 3
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  47. 5 4
      localDev/index.html
  48. 1 0
      materialsLibrary/src/cell/babylon.cellMaterial.ts
  49. 2 0
      materialsLibrary/src/cell/cell.fragment.fx
  50. 1 0
      materialsLibrary/src/fire/babylon.fireMaterial.ts
  51. 2 0
      materialsLibrary/src/fire/fire.fragment.fx
  52. 1 0
      materialsLibrary/src/fur/babylon.furMaterial.ts
  53. 2 0
      materialsLibrary/src/fur/fur.fragment.fx
  54. 1 0
      materialsLibrary/src/gradient/babylon.gradientMaterial.ts
  55. 2 0
      materialsLibrary/src/gradient/gradient.fragment.fx
  56. 1 0
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  57. 2 0
      materialsLibrary/src/lava/lava.fragment.fx
  58. 1 0
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  59. 2 0
      materialsLibrary/src/normal/normal.fragment.fx
  60. 1 0
      materialsLibrary/src/simple/babylon.simpleMaterial.ts
  61. 2 0
      materialsLibrary/src/simple/simple.fragment.fx
  62. 1 0
      materialsLibrary/src/terrain/babylon.terrainMaterial.ts
  63. 2 0
      materialsLibrary/src/terrain/terrain.fragment.fx
  64. 1 0
      materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts
  65. 2 0
      materialsLibrary/src/triPlanar/triplanar.fragment.fx
  66. 1 0
      materialsLibrary/src/water/babylon.waterMaterial.ts
  67. 3 2
      src/Animations/babylon.animation.ts
  68. 7 5
      src/Behaviors/Cameras/babylon.framingBehavior.ts
  69. 57 78
      src/Cameras/Inputs/babylon.arcRotateCameraKeyboardMoveInput.ts
  70. 39 8
      src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts
  71. 28 28
      src/Cameras/Inputs/babylon.freeCameraKeyboardMoveInput.ts
  72. 11 3
      src/Cameras/VR/babylon.webVRCamera.ts
  73. 22 4
      src/Cameras/babylon.arcRotateCamera.ts
  74. 16 2
      src/Cameras/babylon.camera.ts
  75. 4 4
      src/Cameras/babylon.freeCamera.ts
  76. 2 2
      src/Cameras/babylon.targetCamera.ts
  77. 5 5
      src/Collisions/babylon.collisionCoordinator.ts
  78. 33 0
      src/Events/babylon.keyboardEvents.ts
  79. 69 0
      src/Events/babylon.pointerEvents.ts
  80. 11 1
      src/Layer/babylon.highlightlayer.ts
  81. 11 1
      src/Lights/Shadows/babylon.shadowGenerator.ts
  82. 1 0
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  83. 2 0
      src/Materials/Textures/babylon.mirrorTexture.ts
  84. 16 0
      src/Materials/Textures/babylon.multiRenderTarget.ts
  85. 1 1
      src/Materials/Textures/babylon.renderTargetTexture.ts
  86. 6 2
      src/Materials/babylon.effect.ts
  87. 3 0
      src/Materials/babylon.material.ts
  88. 5 0
      src/Materials/babylon.materialHelper.ts
  89. 20 0
      src/Materials/babylon.standardMaterial.ts
  90. 2 2
      src/Mesh/babylon.abstractMesh.ts
  91. 3 1
      src/PostProcess/RenderPipeline/Pipelines/babylon.defaultRenderingPipeline.ts
  92. 1 1
      src/PostProcess/RenderPipeline/Pipelines/babylon.ssao2RenderingPipeline.ts
  93. 2 3
      src/PostProcess/RenderPipeline/Pipelines/babylon.standardRenderingPipeline.ts
  94. 11 1
      src/PostProcess/babylon.postProcess.ts
  95. 9 1
      src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts
  96. 1 1
      src/PostProcess/babylon.vrDistortionCorrectionPostProcess.ts
  97. 9 1
      src/Rendering/babylon.depthRenderer.ts
  98. 12 2
      src/Rendering/babylon.geometryBufferRenderer.ts
  99. 25 11
      src/Rendering/babylon.outlineRenderer.ts
  100. 0 0
      src/Rendering/babylon.renderingGroup.ts

+ 2 - 0
Playground/indexStable.html

@@ -45,6 +45,8 @@
     <script src="https://cdn.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
     <script src="https://cdn.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
 
+    <script src="https://cdn.babylonjs.com/gui/babylon.gui.min.js"></script>    
+
     <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
     <link href="css/index.css" rel="stylesheet" />
 </head>

+ 0 - 158
Playground/js/perf.js

@@ -1,158 +0,0 @@
-(function () {
-    var snippetUrl = "https://babylonjs-api2.azurewebsites.net/snippets";
-    var currentSnippetToken;
-    var engine;
-    var scripts;
-    var zipCode;
-    BABYLON.Engine.ShadersRepository = "/src/Shaders/";
-    var loadScript = function (scriptURL, title) {
-        var xhr = new XMLHttpRequest();
-
-        xhr.open('GET', scriptURL, true);
-
-        xhr.onreadystatechange = function () {
-            if (xhr.readyState === 4) {
-                if (xhr.status === 200) {
-                    blockEditorChange = true;
-                    console.log(xhr.responseText);
-                    jsEditor.setValue(xhr.responseText);
-                    jsEditor.setPosition({ lineNumber: 0, column: 0 });
-                    blockEditorChange = false;
-                    compileAndRun();
-
-                    document.getElementById("currentScript").innerHTML = title;
-
-                    currentSnippetToken = null;
-                }
-            }
-        };
-
-        xhr.send(null);
-    };
-
-    var showError = function(error) {
-        console.warn(error);
-    };
-
-    compileAndRun = function (code) {
-        try {
-
-            if (!BABYLON.Engine.isSupported()) {
-                showError("Your browser does not support WebGL");
-                return;
-            }
-
-            if (engine) {
-                engine.dispose();
-                engine = null;
-            }
-
-            var canvas = document.getElementById("renderCanvas");
-            engine = new BABYLON.Engine(canvas, true, {stencil: true});
-            engine.renderEvenInBackground = false;
-            BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault = true;
-
-            engine.runRenderLoop(function () {
-                if (engine.scenes.length === 0) {
-                    return;
-                }
-
-                if (canvas.width !== canvas.clientWidth) {
-                    engine.resize();
-                }
-
-                var scene = engine.scenes[0];
-
-                if (scene.activeCamera || scene.activeCameras.length > 0) {
-                    scene.render();
-                }
-            });
-
-            var scene;
-            if (code.indexOf("createScene") !== -1) { // createScene
-                eval(code);
-                scene = createScene();
-                if (!scene) {
-                    showError("createScene function must return a scene.");
-                    return;
-                }
-
-                zipCode = code + "\r\n\r\nvar scene = createScene();";
-            } else if (code.indexOf("CreateScene") !== -1) { // CreateScene
-                eval(code);
-                scene = CreateScene();
-                if (!scene) {
-                    showError("CreateScene function must return a scene.");
-                    return;
-                }
-
-                zipCode = code + "\r\n\r\nvar scene = CreateScene();";
-            } else if (code.indexOf("createscene") !== -1) { // createscene
-                eval(code);
-                scene = createscene();
-                if (!scene) {
-                    showError("createscene function must return a scene.");
-                    return;
-                }
-
-                zipCode = code + "\r\n\r\nvar scene = createscene();";
-            } else { // Direct code
-                scene = new BABYLON.Scene(engine);
-                eval("runScript = function(scene, canvas) {" + code + "}");
-                runScript(scene, canvas);
-
-                zipCode = "var scene = new BABYLON.Scene(engine);\r\n\r\n" + code;
-            }
-
-        } catch (e) {
-            // showError(e.message);
-        }
-    };
-    window.addEventListener("resize", function () {
-        if (engine) {
-            engine.resize();
-        }
-    });
-
-    // UI
-
-    var cleanHash = function () {
-        var splits = decodeURIComponent(location.hash.substr(1)).split("#");
-
-        if (splits.length > 2) {
-            splits.splice(2, splits.length - 2);
-        }
-
-        location.hash = splits.join("#");
-    };
-
-    var checkHash = function () {
-        if (location.hash) {
-            cleanHash();
-
-            try {
-                var xmlHttp = new XMLHttpRequest();
-                xmlHttp.onreadystatechange = function () {
-                    if (xmlHttp.readyState === 4) {
-                        if (xmlHttp.status === 200) {
-                            var snippetCode = JSON.parse(JSON.parse(xmlHttp.responseText)[0].jsonPayload).code;
-                            compileAndRun(snippetCode);
-                        }
-                    }
-                };
-
-                var hash = location.hash.substr(1);
-                currentSnippetToken = hash.split("#")[0];
-                if(!hash.split("#")[1]) hash += "#0";
-
-                xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));
-                xmlHttp.send();
-            } catch (e) {
-
-            }
-        }
-    };
-
-    checkHash();
-
-})();

+ 0 - 77
Playground/perf.html

@@ -1,77 +0,0 @@
-<!DOCTYPE html>
-<html>
-
-<head>
-    <title>Babylon.js Playground</title>
-    <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
-	<link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
-	<link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
-	<link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
-	<link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
-	<link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
-	<link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
-	<link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
-	<link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
-	<link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
-	<link rel="icon" type="image/png" sizes="192x192"  href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
-	<link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
-	<link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
-	<link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
-	<link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
-	<meta name="msapplication-TileColor" content="#ffffff">
-	<meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
-	<meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
-	<meta name="theme-color" content="#ffffff">
-
-    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <!-- Babylon.js -->
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/Oimo.js"></script>
-    <script src="https://preview.babylonjs.com/babylon.js"></script>    
-    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.fireMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.waterMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.lavaMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.normalMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.skyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.terrainMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gradientMaterial.min.js"></script>
-    <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>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
-
-    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
-    
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>    
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/canvas2D/dist/preview%20release/babylon.canvas2d.min.js"></script>
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
-    <link href="frame.css" rel="stylesheet" />
-</head>
-
-<body>
-    <canvas touch-action="none" id="renderCanvas"></canvas>
-    <script src="https://code.jquery.com/jquery.js"></script>
-    <script src="/js/perf.js"></script>
-</body>
-
-</html>

+ 21 - 11
Tools/Gulp/config.json

@@ -27,16 +27,19 @@
         "minimal": ["standardMaterial", "freeCamera", "hemisphericLight"],
         "minimalWithBuilder": ["meshBuilder", "standardMaterial", "freeCamera", "hemisphericLight"],
         "minimalGLTFViewer": [
-                "animations", "arcRotateCamera", "additionalTextures", "textureFormats",
-                "shadows", "pointLight", "directionalLight", "spotLight",
-                "multiMaterial", "pbrMaterial",
-                "meshBuilder", "layer",
-                "additionalPostProcess_blur", "additionalPostProcess_fxaa", "additionalPostProcess_highlights", 
-                "additionalPostProcess_imageProcessing", "colorCurves", "defaultRenderingPipeline", "imageProcessing",
-                "debug", "textureTools", "hdr",
-                "loader",
+                "standardMaterial", "pbrMaterial", "freeCamera", "arcRotateCamera", "hemisphericLight", 
+                "pointLight", "directionalLight", "spotLight", "animations", "actions", "sprites", "picking", "collisions",
+                "particles", "solidParticles", "additionalMeshes", "meshBuilder", "audio", "additionalTextures", "shadows",
+                "loader", "userData", "offline", "fresnel", "multiMaterial", "touchCamera", "procedural", "gamepad",
+                "additionalCameras", "postProcesses", "renderingPipeline", "additionalRenderingPipeline", "defaultRenderingPipeline",
+                "depthRenderer", "geometryBufferRenderer", "additionalPostProcesses",
+                "additionalPostProcess_blur", "additionalPostProcess_fxaa", "additionalPostProcess_imageProcessing",
+                "bones", "hdr", "polygonMesh", "csg", "lensFlares", "physics", "textureFormats", "debug", "morphTargets",
+                "colorCurves", "octrees", "simd", "vr", "virtualJoystick", "optimizations", "highlights", "assetsManager",
+                "mapTexture", "dynamicFloatArray",
+                "imageProcessing", "serialization", "probes", "layer", "textureTools", "cameraBehaviors",
                 "materialsLibrary/babylon.gridMaterial.js",
-                "loaders/babylon.glTFFileLoader.js", "cameraBehaviors", "morphTargets"
+                "loaders/babylon.glTFFileLoader.js"
         ],
         "distributed": ["minimalGLTFViewer"]
     },
@@ -45,6 +48,8 @@
         "core" :
         {
             "files":[
+                "../../src/Events/babylon.keyboardEvents.js",
+                "../../src/Events/babylon.pointerEvents.js",
                 "../../src/Math/babylon.math.js",
                 "../../src/Math/babylon.math.scalar.js",
                 "../../src/babylon.mixins.js",
@@ -82,6 +87,9 @@
                 "../../src/Mesh/babylon.geometry.js",
                 "../../src/PostProcess/babylon.postProcessManager.js",
                 "../../src/Tools/babylon.performanceMonitor.js"
+            ],
+            "shaderIncludes": [
+                "depthPrePass"
             ]
         },         
         "particles" : 
@@ -585,10 +593,11 @@
                 "geometry.fragment"
             ],
             "shaderIncludes": [
+                "mrtFragmentDeclaration",
                 "bones300Declaration",
                 "instances300Declaration",
                 "instancesVertex",
-                "bonesVertex"
+                "bonesVertex"               
             ]
         },
         "postProcesses" : 
@@ -1439,7 +1448,8 @@
                     "../../gui/src/controls/image.ts",
                     "../../gui/src/controls/button.ts",
                     "../../gui/src/controls/colorPicker.ts",
-                    "../../gui/src/controls/inputText.ts"
+                    "../../gui/src/controls/inputText.ts",
+                    "../../gui/src/controls/virtualKeyboard.ts"
                 ],
                 "output": "babylon.gui.js",
                 "buildAsModule": "true",

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


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


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


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


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


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


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


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


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


+ 69 - 3
dist/preview release/gui/babylon.gui.d.ts

@@ -1,14 +1,21 @@
 
 declare module BABYLON.GUI {
+    interface IFocusableControl {
+        onFocus(): void;
+        onBlur(): void;
+        processKeyboard(evt: KeyboardEvent): void;
+    }
     class AdvancedDynamicTexture extends DynamicTexture {
         private _isDirty;
         private _renderObserver;
         private _resizeObserver;
+        private _preKeyboardObserver;
         private _pointerMoveObserver;
         private _pointerObserver;
-        private _canvasBlurObserver;
+        private _canvasPointerOutObserver;
         private _background;
         _rootContainer: Container;
+        _lastPickedControl: Control;
         _lastControlOver: Control;
         _lastControlDown: Control;
         _capturingControl: Control;
@@ -20,12 +27,14 @@ declare module BABYLON.GUI {
         private _idealWidth;
         private _idealHeight;
         private _renderAtIdealSize;
+        private _focusedControl;
         background: string;
         idealWidth: number;
         idealHeight: number;
         renderAtIdealSize: boolean;
         readonly layer: Layer;
         readonly rootContainer: Container;
+        focusedControl: IFocusableControl;
         constructor(name: string, width: number, height: number, scene: Scene, generateMipMaps?: boolean, samplingMode?: number);
         executeOnAllControls(func: (control: Control) => void, container?: Container): void;
         markAsDirty(): void;
@@ -39,7 +48,7 @@ declare module BABYLON.GUI {
         private _doPicking(x, y, type);
         attach(): void;
         attachToMesh(mesh: AbstractMesh, supportPointerMove?: boolean): void;
-        private _attachToOnBlur(scene);
+        private _attachToOnPointerOut(scene);
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean): AdvancedDynamicTexture;
         static CreateFullscreenUI(name: string, foreground?: boolean, scene?: Scene): AdvancedDynamicTexture;
     }
@@ -159,6 +168,7 @@ declare module BABYLON.GUI {
         private _doNotRender;
         isHitTestVisible: boolean;
         isPointerBlocker: boolean;
+        isFocusInvisible: boolean;
         protected _linkOffsetX: ValueAndUnit;
         protected _linkOffsetY: ValueAndUnit;
         readonly typeName: string;
@@ -249,6 +259,7 @@ declare module BABYLON.GUI {
         forcePointerUp(): void;
         _processObservables(type: number, x: number, y: number): boolean;
         private _prepareFont();
+        dispose(): void;
         private static _HORIZONTAL_ALIGNMENT_LEFT;
         private static _HORIZONTAL_ALIGNMENT_RIGHT;
         private static _HORIZONTAL_ALIGNMENT_CENTER;
@@ -300,6 +311,7 @@ declare module BABYLON.GUI {
         _processPicking(x: number, y: number, type: number): boolean;
         protected _clipForChildren(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        dispose(): void;
     }
 }
 
@@ -584,22 +596,76 @@ declare module BABYLON.GUI {
 
 
 declare module BABYLON.GUI {
-    class InputText extends Control {
+    class InputText extends Control implements IFocusableControl {
         name: string;
         private _text;
         private _background;
+        private _focusedBackground;
         private _thickness;
         private _margin;
         private _autoStretchWidth;
         private _maxWidth;
+        private _isFocused;
+        private _blinkTimeout;
+        private _blinkIsEven;
+        private _cursorOffset;
+        private _scrollLeft;
+        promptMessage: string;
+        onTextChangedObservable: Observable<InputText>;
+        onFocusObservable: Observable<InputText>;
+        onBlurObservable: Observable<InputText>;
         maxWidth: string | number;
         margin: string;
         autoStretchWidth: boolean;
         thickness: number;
+        focusedBackground: string;
         background: string;
         text: string;
         constructor(name?: string, text?: string);
+        onBlur(): void;
+        onFocus(): void;
         protected _getTypeName(): string;
+        processKey(keyCode: number, key?: string): void;
+        processKeyboard(evt: KeyboardEvent): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _onPointerDown(coordinates: Vector2): boolean;
+        protected _onPointerUp(coordinates: Vector2): void;
+        dispose(): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
+    class KeyPropertySet {
+        width?: string;
+        height?: string;
+        paddingLeft?: string;
+        paddingRight?: string;
+        paddingTop?: string;
+        paddingBottom?: string;
+        color?: string;
+        background?: string;
+    }
+    class VirtualKeyboard extends StackPanel {
+        onKeyPressObservable: Observable<string>;
+        defaultButtonWidth: string;
+        defaultButtonHeight: string;
+        defaultButtonPaddingLeft: string;
+        defaultButtonPaddingRight: string;
+        defaultButtonPaddingTop: string;
+        defaultButtonPaddingBottom: string;
+        defaultButtonColor: string;
+        defaultButtonBackground: string;
+        protected _getTypeName(): string;
+        private _createKey(key, propertySet?);
+        addKeysRow(keys: Array<string>, propertySets?: Array<KeyPropertySet>): void;
+        private _connectedInputText;
+        private _onFocusObserver;
+        private _onBlurObserver;
+        private _onKeyPressObserver;
+        readonly connectedInputText: InputText;
+        connect(input: InputText): void;
+        disconnect(): void;
+        static CreateDefaultLayout(): VirtualKeyboard;
     }
 }

+ 378 - 14
dist/preview release/gui/babylon.gui.js

@@ -30,6 +30,15 @@ var BABYLON;
                 _this._idealHeight = 0;
                 _this._renderAtIdealSize = false;
                 _this._renderObserver = _this.getScene().onBeforeCameraRenderObservable.add(function (camera) { return _this._checkUpdate(camera); });
+                _this._preKeyboardObserver = _this.getScene().onPreKeyboardObservable.add(function (info) {
+                    if (!_this._focusedControl) {
+                        return;
+                    }
+                    if (info.type === BABYLON.KeyboardEventTypes.KEYDOWN) {
+                        _this._focusedControl.processKeyboard(info.event);
+                    }
+                    info.skipOnPointerObservable = true;
+                });
                 _this._rootContainer._link(null, _this);
                 _this.hasAlpha = true;
                 if (!width || !height) {
@@ -111,6 +120,25 @@ var BABYLON;
                 enumerable: true,
                 configurable: true
             });
+            Object.defineProperty(AdvancedDynamicTexture.prototype, "focusedControl", {
+                get: function () {
+                    return this._focusedControl;
+                },
+                set: function (control) {
+                    if (this._focusedControl === control) {
+                        return;
+                    }
+                    if (!this._focusedControl) {
+                        control.onFocus();
+                    }
+                    else {
+                        this._focusedControl.onBlur();
+                    }
+                    this._focusedControl = control;
+                },
+                enumerable: true,
+                configurable: true
+            });
             AdvancedDynamicTexture.prototype.executeOnAllControls = function (func, container) {
                 if (!container) {
                     container = this._rootContainer;
@@ -146,14 +174,15 @@ var BABYLON;
                 if (this._pointerObserver) {
                     this.getScene().onPointerObservable.remove(this._pointerObserver);
                 }
-                if (this._canvasBlurObserver) {
-                    this.getScene().getEngine().onCanvasBlurObservable.remove(this._canvasBlurObserver);
+                if (this._canvasPointerOutObserver) {
+                    this.getScene().getEngine().onCanvasPointerOutObservable.remove(this._canvasPointerOutObserver);
                 }
                 if (this._layerToDispose) {
                     this._layerToDispose.texture = null;
                     this._layerToDispose.dispose();
                     this._layerToDispose = null;
                 }
+                this._rootContainer.dispose();
                 _super.prototype.dispose.call(this);
             };
             AdvancedDynamicTexture.prototype._onResize = function () {
@@ -262,6 +291,15 @@ var BABYLON;
                         this._lastControlOver = null;
                     }
                 }
+                // Focus management
+                if (this._focusedControl) {
+                    if (this._focusedControl !== this._lastPickedControl) {
+                        if (this._lastPickedControl.isFocusInvisible) {
+                            return;
+                        }
+                        this.focusedControl = null;
+                    }
+                }
             };
             AdvancedDynamicTexture.prototype.attach = function () {
                 var _this = this;
@@ -281,7 +319,7 @@ var BABYLON;
                     _this._doPicking(x, y, pi.type);
                     pi.skipOnPointerObservable = _this._shouldBlockPointer && pi.type !== BABYLON.PointerEventTypes.POINTERUP;
                 });
-                this._attachToOnBlur(scene);
+                this._attachToOnPointerOut(scene);
             };
             AdvancedDynamicTexture.prototype.attachToMesh = function (mesh, supportPointerMove) {
                 var _this = this;
@@ -312,11 +350,11 @@ var BABYLON;
                     }
                 });
                 mesh.enablePointerMoveEvents = supportPointerMove;
-                this._attachToOnBlur(scene);
+                this._attachToOnPointerOut(scene);
             };
-            AdvancedDynamicTexture.prototype._attachToOnBlur = function (scene) {
+            AdvancedDynamicTexture.prototype._attachToOnPointerOut = function (scene) {
                 var _this = this;
-                this._canvasBlurObserver = scene.getEngine().onCanvasBlurObservable.add(function () {
+                this._canvasPointerOutObserver = scene.getEngine().onCanvasPointerOutObservable.add(function () {
                     if (_this._lastControlOver) {
                         _this._lastControlOver._onPointerOut();
                     }
@@ -692,6 +730,7 @@ var BABYLON;
                 this._doNotRender = false;
                 this.isHitTestVisible = true;
                 this.isPointerBlocker = false;
+                this.isFocusInvisible = false;
                 this._linkOffsetX = new GUI.ValueAndUnit(0);
                 this._linkOffsetY = new GUI.ValueAndUnit(0);
                 /**
@@ -1429,6 +1468,7 @@ var BABYLON;
                 if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
                     this._onPointerDown(this._dummyVector2);
                     this._host._lastControlDown = this;
+                    this._host._lastPickedControl = this;
                     return true;
                 }
                 if (type === BABYLON.PointerEventTypes.POINTERUP) {
@@ -1447,6 +1487,14 @@ var BABYLON;
                 this._font = this._fontSize.getValue(this._host) + "px " + this._fontFamily;
                 this._fontOffset = Control._GetFontOffset(this._font);
             };
+            Control.prototype.dispose = function () {
+                this.onDirtyObservable.clear();
+                this.onPointerDownObservable.clear();
+                this.onPointerEnterObservable.clear();
+                this.onPointerMoveObservable.clear();
+                this.onPointerOutObservable.clear();
+                this.onPointerUpObservable.clear();
+            };
             Object.defineProperty(Control, "HORIZONTAL_ALIGNMENT_LEFT", {
                 get: function () {
                     return Control._HORIZONTAL_ALIGNMENT_LEFT;
@@ -1646,6 +1694,7 @@ var BABYLON;
                     return this;
                 }
                 control._link(this, this._host);
+                control._markAllAsDirty();
                 this._reOrderControl(control);
                 this._markAsDirty();
                 return this;
@@ -1735,6 +1784,13 @@ var BABYLON;
                 _super.prototype._additionalProcessing.call(this, parentMeasure, context);
                 this._measureForChildren.copyFrom(this._currentMeasure);
             };
+            Container.prototype.dispose = function () {
+                _super.prototype.dispose.call(this);
+                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                    var control = _a[_i];
+                    control.dispose();
+                }
+            };
             return Container;
         }(GUI.Control));
         GUI.Container = Container;
@@ -3719,10 +3775,18 @@ var BABYLON;
                 _this.name = name;
                 _this._text = "";
                 _this._background = "black";
+                _this._focusedBackground = "black";
                 _this._thickness = 1;
                 _this._margin = new GUI.ValueAndUnit(10, GUI.ValueAndUnit.UNITMODE_PIXEL);
                 _this._autoStretchWidth = true;
                 _this._maxWidth = new GUI.ValueAndUnit(1, GUI.ValueAndUnit.UNITMODE_PERCENTAGE, false);
+                _this._isFocused = false;
+                _this._blinkIsEven = false;
+                _this._cursorOffset = 0;
+                _this.promptMessage = "Please enter text:";
+                _this.onTextChangedObservable = new BABYLON.Observable();
+                _this.onFocusObservable = new BABYLON.Observable();
+                _this.onBlurObservable = new BABYLON.Observable();
                 _this.text = text;
                 return _this;
             }
@@ -3784,6 +3848,20 @@ var BABYLON;
                 enumerable: true,
                 configurable: true
             });
+            Object.defineProperty(InputText.prototype, "focusedBackground", {
+                get: function () {
+                    return this._focusedBackground;
+                },
+                set: function (value) {
+                    if (this._focusedBackground === value) {
+                        return;
+                    }
+                    this._focusedBackground = value;
+                    this._markAsDirty();
+                },
+                enumerable: true,
+                configurable: true
+            });
             Object.defineProperty(InputText.prototype, "background", {
                 get: function () {
                     return this._background;
@@ -3808,33 +3886,178 @@ var BABYLON;
                     }
                     this._text = value;
                     this._markAsDirty();
+                    this.onTextChangedObservable.notifyObservers(this);
                 },
                 enumerable: true,
                 configurable: true
             });
+            InputText.prototype.onBlur = function () {
+                this._isFocused = false;
+                this._scrollLeft = null;
+                this._cursorOffset = 0;
+                clearTimeout(this._blinkTimeout);
+                this._markAsDirty();
+                this.onBlurObservable.notifyObservers(this);
+            };
+            InputText.prototype.onFocus = function () {
+                this._scrollLeft = null;
+                this._isFocused = true;
+                this._blinkIsEven = false;
+                this._cursorOffset = 0;
+                this._markAsDirty();
+                this.onFocusObservable.notifyObservers(this);
+                if (navigator.userAgent.indexOf("Mobile") !== -1) {
+                    this.text = prompt(this.promptMessage);
+                    this._host.focusedControl = null;
+                    return;
+                }
+            };
             InputText.prototype._getTypeName = function () {
                 return "InputText";
             };
+            InputText.prototype.processKey = function (keyCode, key) {
+                // Specific cases
+                switch (keyCode) {
+                    case 8:// BACKSPACE
+                        if (this._text && this._text.length > 0) {
+                            if (this._cursorOffset === 0) {
+                                this.text = this._text.substr(0, this._text.length - 1);
+                            }
+                            else {
+                                var deletePosition = this._text.length - this._cursorOffset;
+                                if (deletePosition > 0) {
+                                    this.text = this._text.slice(0, deletePosition - 1) + this._text.slice(deletePosition);
+                                }
+                            }
+                        }
+                        return;
+                    case 46:// DELETE
+                        if (this._text && this._text.length > 0) {
+                            var deletePosition = this._text.length - this._cursorOffset;
+                            this.text = this._text.slice(0, deletePosition) + this._text.slice(deletePosition + 1);
+                            this._cursorOffset--;
+                        }
+                        return;
+                    case 13:// RETURN
+                        this._host.focusedControl = null;
+                        return;
+                    case 35:// END
+                        this._cursorOffset = 0;
+                        this._blinkIsEven = false;
+                        this._markAsDirty();
+                        return;
+                    case 36:// HOME
+                        this._cursorOffset = this._text.length;
+                        this._blinkIsEven = false;
+                        this._markAsDirty();
+                        return;
+                    case 37:// LEFT
+                        this._cursorOffset++;
+                        if (this._cursorOffset > this._text.length) {
+                            this._cursorOffset = this._text.length;
+                        }
+                        this._blinkIsEven = false;
+                        this._markAsDirty();
+                        return;
+                    case 39:// RIGHT
+                        this._cursorOffset--;
+                        if (this._cursorOffset < 0) {
+                            this._cursorOffset = 0;
+                        }
+                        this._blinkIsEven = false;
+                        this._markAsDirty();
+                        return;
+                }
+                // Printable characters
+                if ((keyCode === -1) ||
+                    (keyCode === 32) ||
+                    (keyCode > 47 && keyCode < 58) ||
+                    (keyCode > 64 && keyCode < 91) ||
+                    (keyCode > 185 && keyCode < 193) ||
+                    (keyCode > 218 && keyCode < 223) ||
+                    (keyCode > 95 && keyCode < 112)) {
+                    if (this._cursorOffset === 0) {
+                        this.text += key;
+                    }
+                    else {
+                        var insertPosition = this._text.length - this._cursorOffset;
+                        this.text = this._text.slice(0, insertPosition) + key + this._text.slice(insertPosition);
+                    }
+                }
+            };
+            InputText.prototype.processKeyboard = function (evt) {
+                this.processKey(evt.keyCode, evt.key);
+            };
             InputText.prototype._draw = function (parentMeasure, context) {
+                var _this = this;
                 context.save();
                 this._applyStates(context);
                 if (this._processMeasures(parentMeasure, context)) {
                     // Background
-                    if (this._background) {
+                    if (this._isFocused) {
+                        if (this._focusedBackground) {
+                            context.fillStyle = this._focusedBackground;
+                            context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                        }
+                    }
+                    else if (this._background) {
                         context.fillStyle = this._background;
                         context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
                     }
+                    if (!this._fontOffset) {
+                        this._fontOffset = GUI.Control._GetFontOffset(context.font);
+                    }
                     // Text
-                    if (this._text) {
-                        if (this.color) {
-                            context.fillStyle = this.color;
+                    var clipTextLeft = this._currentMeasure.left + this._margin.getValueInPixel(this._host, parentMeasure.width);
+                    if (this.color) {
+                        context.fillStyle = this.color;
+                    }
+                    var textWidth = context.measureText(this._text).width;
+                    var marginWidth = this._margin.getValueInPixel(this._host, parentMeasure.width) * 2;
+                    if (this._autoStretchWidth) {
+                        this.width = Math.min(this._maxWidth.getValueInPixel(this._host, parentMeasure.width), textWidth + marginWidth) + "px";
+                    }
+                    var rootY = this._fontOffset.ascent + (this._currentMeasure.height - this._fontOffset.height) / 2;
+                    var availableWidth = this._width.getValueInPixel(this._host, parentMeasure.width) - marginWidth;
+                    context.save();
+                    context.beginPath();
+                    context.rect(clipTextLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, availableWidth + 2, this._currentMeasure.height);
+                    context.clip();
+                    if (this._isFocused && textWidth > availableWidth) {
+                        var textLeft = clipTextLeft - textWidth + availableWidth;
+                        if (!this._scrollLeft) {
+                            this._scrollLeft = textLeft;
                         }
-                        var rootY = this._fontOffset.ascent + (this._currentMeasure.height - this._fontOffset.height) / 2;
-                        context.fillText(this._text, this._currentMeasure.left + this._margin.getValueInPixel(this._host, parentMeasure.width), this._currentMeasure.top + rootY);
-                        if (this._autoStretchWidth) {
-                            this.width = Math.min(this._maxWidth.getValueInPixel(this._host, parentMeasure.width), context.measureText(this._text).width + this._margin.getValueInPixel(this._host, parentMeasure.width) * 2) + "px";
+                    }
+                    else {
+                        this._scrollLeft = clipTextLeft;
+                    }
+                    context.fillText(this._text, this._scrollLeft, this._currentMeasure.top + rootY);
+                    // Cursor
+                    if (this._isFocused) {
+                        if (!this._blinkIsEven) {
+                            var cursorOffsetText = this.text.substr(this._text.length - this._cursorOffset);
+                            var cursorOffsetWidth = context.measureText(cursorOffsetText).width;
+                            var cursorLeft = this._scrollLeft + textWidth - cursorOffsetWidth;
+                            if (cursorLeft < clipTextLeft) {
+                                this._scrollLeft += (clipTextLeft - cursorLeft);
+                                cursorLeft = clipTextLeft;
+                                this._markAsDirty();
+                            }
+                            else if (cursorLeft > clipTextLeft + availableWidth) {
+                                this._scrollLeft += (clipTextLeft + availableWidth - cursorLeft);
+                                cursorLeft = clipTextLeft + availableWidth;
+                                this._markAsDirty();
+                            }
+                            context.fillRect(cursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, 2, this._fontOffset.height);
                         }
+                        clearTimeout(this._blinkTimeout);
+                        this._blinkTimeout = setTimeout(function () {
+                            _this._blinkIsEven = !_this._blinkIsEven;
+                            _this._markAsDirty();
+                        }, 500);
                     }
+                    context.restore();
                     // Border
                     if (this._thickness) {
                         if (this.color) {
@@ -3846,8 +4069,149 @@ var BABYLON;
                 }
                 context.restore();
             };
+            InputText.prototype._onPointerDown = function (coordinates) {
+                if (!_super.prototype._onPointerDown.call(this, coordinates)) {
+                    return false;
+                }
+                this._host.focusedControl = this;
+                return true;
+            };
+            InputText.prototype._onPointerUp = function (coordinates) {
+                _super.prototype._onPointerUp.call(this, coordinates);
+            };
+            InputText.prototype.dispose = function () {
+                _super.prototype.dispose.call(this);
+                this.onBlurObservable.clear();
+                this.onFocusObservable.clear();
+                this.onTextChangedObservable.clear();
+            };
             return InputText;
         }(GUI.Control));
         GUI.InputText = InputText;
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
 })(BABYLON || (BABYLON = {}));
+
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        var KeyPropertySet = (function () {
+            function KeyPropertySet() {
+            }
+            return KeyPropertySet;
+        }());
+        GUI.KeyPropertySet = KeyPropertySet;
+        var VirtualKeyboard = (function (_super) {
+            __extends(VirtualKeyboard, _super);
+            function VirtualKeyboard() {
+                var _this = _super !== null && _super.apply(this, arguments) || this;
+                _this.onKeyPressObservable = new BABYLON.Observable();
+                _this.defaultButtonWidth = "40px";
+                _this.defaultButtonHeight = "40px";
+                _this.defaultButtonPaddingLeft = "2px";
+                _this.defaultButtonPaddingRight = "2px";
+                _this.defaultButtonPaddingTop = "2px";
+                _this.defaultButtonPaddingBottom = "2px";
+                _this.defaultButtonColor = "#DDD";
+                _this.defaultButtonBackground = "#070707";
+                return _this;
+            }
+            VirtualKeyboard.prototype._getTypeName = function () {
+                return "VirtualKeyboard";
+            };
+            VirtualKeyboard.prototype._createKey = function (key, propertySet) {
+                var _this = this;
+                var button = GUI.Button.CreateSimpleButton(key, key);
+                button.width = propertySet && propertySet.width ? propertySet.width : this.defaultButtonWidth;
+                button.height = propertySet && propertySet.height ? propertySet.height : this.defaultButtonHeight;
+                button.color = propertySet && propertySet.color ? propertySet.color : this.defaultButtonColor;
+                button.background = propertySet && propertySet.background ? propertySet.background : this.defaultButtonBackground;
+                button.paddingLeft = propertySet && propertySet.paddingLeft ? propertySet.paddingLeft : this.defaultButtonPaddingLeft;
+                button.paddingRight = propertySet && propertySet.paddingRight ? propertySet.paddingRight : this.defaultButtonPaddingRight;
+                button.paddingTop = propertySet && propertySet.paddingTop ? propertySet.paddingTop : this.defaultButtonPaddingTop;
+                button.paddingBottom = propertySet && propertySet.paddingBottom ? propertySet.paddingBottom : this.defaultButtonPaddingBottom;
+                button.thickness = 0;
+                button.isFocusInvisible = true;
+                button.onPointerUpObservable.add(function () {
+                    _this.onKeyPressObservable.notifyObservers(key);
+                });
+                return button;
+            };
+            VirtualKeyboard.prototype.addKeysRow = function (keys, propertySets) {
+                var panel = new GUI.StackPanel();
+                panel.isVertical = false;
+                panel.isFocusInvisible = true;
+                for (var i = 0; i < keys.length; i++) {
+                    var properties = null;
+                    if (propertySets && propertySets.length === keys.length) {
+                        properties = propertySets[i];
+                    }
+                    panel.addControl(this._createKey(keys[i], properties));
+                }
+                this.addControl(panel);
+            };
+            Object.defineProperty(VirtualKeyboard.prototype, "connectedInputText", {
+                get: function () {
+                    return this._connectedInputText;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            VirtualKeyboard.prototype.connect = function (input) {
+                var _this = this;
+                this.isVisible = false;
+                this._connectedInputText = input;
+                // Events hooking
+                this._onFocusObserver = input.onFocusObservable.add(function () {
+                    _this.isVisible = true;
+                });
+                this._onBlurObserver = input.onBlurObservable.add(function () {
+                    _this.isVisible = false;
+                });
+                this._onKeyPressObserver = this.onKeyPressObservable.add(function (key) {
+                    switch (key) {
+                        case "\u2190":
+                            _this._connectedInputText.processKey(8);
+                            return;
+                        case "\u21B5":
+                            _this._connectedInputText.processKey(13);
+                            return;
+                    }
+                    _this._connectedInputText.processKey(-1, key);
+                });
+            };
+            VirtualKeyboard.prototype.disconnect = function () {
+                if (!this._connectedInputText) {
+                    return;
+                }
+                this._connectedInputText.onFocusObservable.remove(this._onFocusObserver);
+                this._connectedInputText.onBlurObservable.remove(this._onBlurObserver);
+                this.onKeyPressObservable.remove(this._onKeyPressObserver);
+                this._connectedInputText = null;
+            };
+            // Statics
+            VirtualKeyboard.CreateDefaultLayout = function () {
+                var returnValue = new VirtualKeyboard();
+                returnValue.addKeysRow(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\u2190"]);
+                returnValue.addKeysRow(["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"]);
+                returnValue.addKeysRow(["a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "\u21B5"]);
+                returnValue.addKeysRow(["z", "x", "c", "v", "b", "n", "m", ",", ".", "/"]);
+                returnValue.addKeysRow([" "], [{ width: "200px" }]);
+                return returnValue;
+            };
+            return VirtualKeyboard;
+        }(GUI.StackPanel));
+        GUI.VirtualKeyboard = VirtualKeyboard;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));

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


+ 69 - 3
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1,14 +1,21 @@
 /// <reference path="../../dist/preview release/babylon.d.ts" />
 declare module BABYLON.GUI {
+    interface IFocusableControl {
+        onFocus(): void;
+        onBlur(): void;
+        processKeyboard(evt: KeyboardEvent): void;
+    }
     class AdvancedDynamicTexture extends DynamicTexture {
         private _isDirty;
         private _renderObserver;
         private _resizeObserver;
+        private _preKeyboardObserver;
         private _pointerMoveObserver;
         private _pointerObserver;
-        private _canvasBlurObserver;
+        private _canvasPointerOutObserver;
         private _background;
         _rootContainer: Container;
+        _lastPickedControl: Control;
         _lastControlOver: Control;
         _lastControlDown: Control;
         _capturingControl: Control;
@@ -20,12 +27,14 @@ declare module BABYLON.GUI {
         private _idealWidth;
         private _idealHeight;
         private _renderAtIdealSize;
+        private _focusedControl;
         background: string;
         idealWidth: number;
         idealHeight: number;
         renderAtIdealSize: boolean;
         readonly layer: Layer;
         readonly rootContainer: Container;
+        focusedControl: IFocusableControl;
         constructor(name: string, width: number, height: number, scene: Scene, generateMipMaps?: boolean, samplingMode?: number);
         executeOnAllControls(func: (control: Control) => void, container?: Container): void;
         markAsDirty(): void;
@@ -39,7 +48,7 @@ declare module BABYLON.GUI {
         private _doPicking(x, y, type);
         attach(): void;
         attachToMesh(mesh: AbstractMesh, supportPointerMove?: boolean): void;
-        private _attachToOnBlur(scene);
+        private _attachToOnPointerOut(scene);
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean): AdvancedDynamicTexture;
         static CreateFullscreenUI(name: string, foreground?: boolean, scene?: Scene): AdvancedDynamicTexture;
     }
@@ -159,6 +168,7 @@ declare module BABYLON.GUI {
         private _doNotRender;
         isHitTestVisible: boolean;
         isPointerBlocker: boolean;
+        isFocusInvisible: boolean;
         protected _linkOffsetX: ValueAndUnit;
         protected _linkOffsetY: ValueAndUnit;
         readonly typeName: string;
@@ -249,6 +259,7 @@ declare module BABYLON.GUI {
         forcePointerUp(): void;
         _processObservables(type: number, x: number, y: number): boolean;
         private _prepareFont();
+        dispose(): void;
         private static _HORIZONTAL_ALIGNMENT_LEFT;
         private static _HORIZONTAL_ALIGNMENT_RIGHT;
         private static _HORIZONTAL_ALIGNMENT_CENTER;
@@ -300,6 +311,7 @@ declare module BABYLON.GUI {
         _processPicking(x: number, y: number, type: number): boolean;
         protected _clipForChildren(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        dispose(): void;
     }
 }
 
@@ -584,23 +596,77 @@ declare module BABYLON.GUI {
 
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON.GUI {
-    class InputText extends Control {
+    class InputText extends Control implements IFocusableControl {
         name: string;
         private _text;
         private _background;
+        private _focusedBackground;
         private _thickness;
         private _margin;
         private _autoStretchWidth;
         private _maxWidth;
+        private _isFocused;
+        private _blinkTimeout;
+        private _blinkIsEven;
+        private _cursorOffset;
+        private _scrollLeft;
+        promptMessage: string;
+        onTextChangedObservable: Observable<InputText>;
+        onFocusObservable: Observable<InputText>;
+        onBlurObservable: Observable<InputText>;
         maxWidth: string | number;
         margin: string;
         autoStretchWidth: boolean;
         thickness: number;
+        focusedBackground: string;
         background: string;
         text: string;
         constructor(name?: string, text?: string);
+        onBlur(): void;
+        onFocus(): void;
         protected _getTypeName(): string;
+        processKey(keyCode: number, key?: string): void;
+        processKeyboard(evt: KeyboardEvent): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _onPointerDown(coordinates: Vector2): boolean;
+        protected _onPointerUp(coordinates: Vector2): void;
+        dispose(): void;
+    }
+}
+
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class KeyPropertySet {
+        width?: string;
+        height?: string;
+        paddingLeft?: string;
+        paddingRight?: string;
+        paddingTop?: string;
+        paddingBottom?: string;
+        color?: string;
+        background?: string;
+    }
+    class VirtualKeyboard extends StackPanel {
+        onKeyPressObservable: Observable<string>;
+        defaultButtonWidth: string;
+        defaultButtonHeight: string;
+        defaultButtonPaddingLeft: string;
+        defaultButtonPaddingRight: string;
+        defaultButtonPaddingTop: string;
+        defaultButtonPaddingBottom: string;
+        defaultButtonColor: string;
+        defaultButtonBackground: string;
+        protected _getTypeName(): string;
+        private _createKey(key, propertySet?);
+        addKeysRow(keys: Array<string>, propertySets?: Array<KeyPropertySet>): void;
+        private _connectedInputText;
+        private _onFocusObserver;
+        private _onBlurObserver;
+        private _onKeyPressObserver;
+        readonly connectedInputText: InputText;
+        connect(input: InputText): void;
+        disconnect(): void;
+        static CreateDefaultLayout(): VirtualKeyboard;
     }
 }
 

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


+ 1 - 0
dist/preview release/materialsLibrary/babylon.waterMaterial.js

@@ -25,6 +25,7 @@ var BABYLON;
             _this.REFLECTION = false;
             _this.CLIPPLANE = false;
             _this.ALPHATEST = false;
+            _this.DEPTHPREPASS = false;
             _this.POINTSIZE = false;
             _this.FOG = false;
             _this.NORMAL = false;

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


+ 6 - 3
dist/preview release/what's new.md

@@ -1,15 +1,18 @@
 # 3.1.0:
 
 ## Major updates
-- Added support for webgl context lost and restored events. (Doc here)[http://doc.babylonjs.com/tutorials/optimizing_your_scene#handling-webgl-context-lost] ([deltakosh](https://github.com/deltakosh))
+- Added support for webgl context lost and restored events. [Doc here](http://doc.babylonjs.com/tutorials/optimizing_your_scene#handling-webgl-context-lost) ([deltakosh](https://github.com/deltakosh))
 - Added support for non-pow2 textures when in WebGL2 mode ([deltakosh](https://github.com/deltakosh))
 - Engine can now be initialized with an existing webgl context ([deltakosh](https://github.com/deltakosh))
-- Introduced behaviors. (Doc here)[http://doc.babylonjs.com/overviews/behaviors] ([deltakosh](https://github.com/deltakosh))
-- Added support for WebGL Occlusion queries. (Doc here)[http://doc.babylonjs.com/overviews/occlusionquery] ([Ibraheem Osama](https://github.com/IbraheemOsama))
+- Introduced behaviors. [Doc here](http://doc.babylonjs.com/overviews/behaviors) ([deltakosh](https://github.com/deltakosh))
+- Added support for WebGL Occlusion queries. [Doc here](http://doc.babylonjs.com/overviews/occlusionquery) ([Ibraheem Osama](https://github.com/IbraheemOsama))
 - New behaviors for ArcRotateCamera:
  - AutoRotation ([deltakosh](https://github.com/deltakosh))
  - Framing ([deltakosh](https://github.com/deltakosh))
  - Bouncing ([deltakosh](https://github.com/deltakosh))
+- New InputText for Babylon.GUI. [Doc here](http://doc.babylonjs.com/overviews/gui#inputtext) ([deltakosh](https://github.com/deltakosh))
+- New VirtualKeyboard for Babylon.GUI. [Doc here](http://doc.babylonjs.com/overviews/gui#virtualkeyboard) ([deltakosh](https://github.com/deltakosh) / [adam](https://github.com/abow))
+- Added support for depth pre-pass rendering. [Doc here](http://doc.babylonjs.com/tutorials/transparency_and_how_meshes_are_rendered#depth-pre-pass-meshes) ([deltakosh](https://github.com/deltakosh))
 
 ## Updates
 - New `camera.storeState()` and `camera.restoreState()` functions to store / restore cameras position / rotation / fov. (Doc here)[http://doc.babylonjs.com/tutorials/cameras#state] ([deltakosh](https://github.com/deltakosh))

+ 58 - 7
gui/src/advancedDynamicTexture.ts

@@ -1,15 +1,23 @@
 /// <reference path="../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON.GUI {
+    export interface IFocusableControl {
+        onFocus(): void;
+        onBlur(): void;
+        processKeyboard(evt: KeyboardEvent): void;
+    }
+
     export class AdvancedDynamicTexture extends DynamicTexture {
         private _isDirty = false;
         private _renderObserver: Observer<Camera>;
         private _resizeObserver: Observer<Engine>;
+        private _preKeyboardObserver: Observer<KeyboardInfoPre>;
         private _pointerMoveObserver: Observer<PointerInfoPre>;
         private _pointerObserver: Observer<PointerInfo>;
-        private _canvasBlurObserver: Observer<Engine>;
+        private _canvasPointerOutObserver: Observer<Engine>;
         private _background: string;
         public _rootContainer = new Container("root");
+        public _lastPickedControl: Control;
         public _lastControlOver: Control;
         public _lastControlDown: Control;
         public _capturingControl: Control;
@@ -21,6 +29,7 @@ module BABYLON.GUI {
         private _idealWidth = 0;
         private _idealHeight = 0;
         private _renderAtIdealSize = false;
+        private _focusedControl: IFocusableControl;
 
         public get background(): string {
             return this._background;
@@ -83,11 +92,40 @@ module BABYLON.GUI {
         public get rootContainer(): Container {
             return this._rootContainer;
         }
+
+        public get focusedControl(): IFocusableControl {
+            return this._focusedControl;
+        }
+
+        public set focusedControl(control: IFocusableControl) {
+            if (this._focusedControl === control) {
+                return;
+            }
+
+            if (!this._focusedControl) {
+                control.onFocus();
+            } else {
+                this._focusedControl.onBlur();
+            }
+
+            this._focusedControl = control;
+        }
        
         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().onBeforeCameraRenderObservable.add((camera: Camera) => this._checkUpdate(camera));
+            this._preKeyboardObserver = this.getScene().onPreKeyboardObservable.add(info => {
+                if (!this._focusedControl) {
+                    return;
+                }
+
+                if (info.type === KeyboardEventTypes.KEYDOWN) {
+                    this._focusedControl.processKeyboard(info.event);
+                }
+
+                info.skipOnPointerObservable = true;
+            });
 
             this._rootContainer._link(null, this);
 
@@ -145,8 +183,8 @@ module BABYLON.GUI {
                 this.getScene().onPointerObservable.remove(this._pointerObserver);
             }
 
-            if (this._canvasBlurObserver) {
-                this.getScene().getEngine().onCanvasBlurObservable.remove(this._canvasBlurObserver);
+            if (this._canvasPointerOutObserver) {
+                this.getScene().getEngine().onCanvasPointerOutObservable.remove(this._canvasPointerOutObserver);
             }
 
             if (this._layerToDispose) {
@@ -155,6 +193,8 @@ module BABYLON.GUI {
                 this._layerToDispose = null;
             }
 
+            this._rootContainer.dispose();
+
             super.dispose();
         }
 
@@ -286,6 +326,17 @@ module BABYLON.GUI {
                     this._lastControlOver = null;
                 }
             }
+
+            // Focus management
+            if (this._focusedControl) {
+                if (this._focusedControl !== (<any>this._lastPickedControl)) {
+                    if (this._lastPickedControl.isFocusInvisible) {
+                        return;
+                    }
+
+                    this.focusedControl = null;
+                }
+            }
         }
 
         public attach(): void {
@@ -309,7 +360,7 @@ module BABYLON.GUI {
                 pi.skipOnPointerObservable = this._shouldBlockPointer && pi.type !== BABYLON.PointerEventTypes.POINTERUP;
             });
 
-            this._attachToOnBlur(scene);
+            this._attachToOnPointerOut(scene);
         }
 
         public attachToMesh(mesh: AbstractMesh, supportPointerMove = true): void {
@@ -339,11 +390,11 @@ module BABYLON.GUI {
             });
 
             mesh.enablePointerMoveEvents = supportPointerMove;
-            this._attachToOnBlur(scene);
+            this._attachToOnPointerOut(scene);
         }
 
-        private _attachToOnBlur(scene: Scene): void {
-            this._canvasBlurObserver = scene.getEngine().onCanvasBlurObservable.add(() => {
+        private _attachToOnPointerOut(scene: Scene): void {
+            this._canvasPointerOutObserver = scene.getEngine().onCanvasPointerOutObservable.add(() => {
                 if (this._lastControlOver) {
                     this._lastControlOver._onPointerOut();
                 }            

+ 10 - 0
gui/src/controls/container.ts

@@ -63,6 +63,8 @@ module BABYLON.GUI {
             }
             control._link(this, this._host);
 
+            control._markAllAsDirty();
+
             this._reOrderControl(control);
 
             this._markAsDirty();
@@ -176,5 +178,13 @@ module BABYLON.GUI {
 
             this._measureForChildren.copyFrom(this._currentMeasure);
         }
+
+        public dispose() {
+            super.dispose();
+
+            for (var control of this._children) {
+                control.dispose();
+            }
+        }
     }    
 }

+ 11 - 0
gui/src/controls/control.ts

@@ -47,6 +47,7 @@ module BABYLON.GUI {
 
         public isHitTestVisible = true;
         public isPointerBlocker = false;
+        public isFocusInvisible = false;
 
         protected _linkOffsetX = new ValueAndUnit(0);
         protected _linkOffsetY = new ValueAndUnit(0);
@@ -834,6 +835,7 @@ module BABYLON.GUI {
             if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
                 this._onPointerDown(this._dummyVector2);
                 this._host._lastControlDown = this;
+                this._host._lastPickedControl = this;
                 return true;
             }
 
@@ -858,6 +860,15 @@ module BABYLON.GUI {
             this._fontOffset = Control._GetFontOffset(this._font);
         }
 
+        public dispose() {
+            this.onDirtyObservable.clear();
+            this.onPointerDownObservable.clear();
+            this.onPointerEnterObservable.clear();
+            this.onPointerMoveObservable.clear();
+            this.onPointerOutObservable.clear();
+            this.onPointerUpObservable.clear();
+        }
+
         // Statics
         private static _HORIZONTAL_ALIGNMENT_LEFT = 0;
         private static _HORIZONTAL_ALIGNMENT_RIGHT = 1;

+ 216 - 11
gui/src/controls/inputText.ts

@@ -1,13 +1,25 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON.GUI {
-    export class InputText extends Control {
+    export class InputText extends Control implements IFocusableControl {
         private _text = "";
         private _background = "black";   
+        private _focusedBackground = "black";   
         private _thickness = 1;
         private _margin = new ValueAndUnit(10, ValueAndUnit.UNITMODE_PIXEL);
         private _autoStretchWidth = true;        
         private _maxWidth = new ValueAndUnit(1, ValueAndUnit.UNITMODE_PERCENTAGE, false);
+        private _isFocused = false;
+        private _blinkTimeout: number;
+        private _blinkIsEven = false;
+        private _cursorOffset = 0;        
+        private _scrollLeft: number;
+
+        public promptMessage = "Please enter text:";
+
+        public onTextChangedObservable = new Observable<InputText>();
+        public onFocusObservable = new Observable<InputText>();
+        public onBlurObservable = new Observable<InputText>();
 
         public get maxWidth(): string | number {
             return this._maxWidth.toString(this._host);
@@ -63,6 +75,19 @@ module BABYLON.GUI {
             this._markAsDirty();
         }          
 
+        public get focusedBackground(): string {
+            return this._focusedBackground;
+        }
+
+        public set focusedBackground(value: string) {
+            if (this._focusedBackground === value) {
+                return;
+            }
+
+            this._focusedBackground = value;
+            this._markAsDirty();
+        }  
+
         public get background(): string {
             return this._background;
         }
@@ -74,7 +99,7 @@ module BABYLON.GUI {
 
             this._background = value;
             this._markAsDirty();
-        }  
+        }          
 
         public get text(): string {
             return this._text;
@@ -86,6 +111,8 @@ module BABYLON.GUI {
             }
             this._text = value;
             this._markAsDirty();
+
+            this.onTextChangedObservable.notifyObservers(this);
         }
 
         constructor(public name?: string, text: string = "") {
@@ -94,37 +121,193 @@ module BABYLON.GUI {
             this.text = text;
         }
 
+        public onBlur(): void {
+            this._isFocused = false;
+            this._scrollLeft = null;
+            this._cursorOffset = 0;
+            clearTimeout(this._blinkTimeout);
+            this._markAsDirty();
+
+            this.onBlurObservable.notifyObservers(this);
+        }
+
+        public onFocus(): void {
+            this._scrollLeft = null;
+            this._isFocused = true;
+            this._blinkIsEven = false;
+            this._cursorOffset = 0;
+            this._markAsDirty();
+
+            this.onFocusObservable.notifyObservers(this);
+
+            if (navigator.userAgent.indexOf("Mobile") !== -1) {
+                this.text = prompt(this.promptMessage);
+                this._host.focusedControl = null;
+                return;
+            }
+        }
+
         protected _getTypeName(): string {
             return "InputText";
         }
 
-       public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        public processKey(keyCode: number, key?: string) {
+            // Specific cases
+            switch (keyCode) {
+                case 8: // BACKSPACE
+                    if (this._text && this._text.length > 0) {
+                        if (this._cursorOffset === 0) {
+                            this.text = this._text.substr(0, this._text.length - 1);
+                        } else {
+                            let deletePosition = this._text.length - this._cursorOffset;
+                            if (deletePosition > 0) {
+                                this.text = this._text.slice(0, deletePosition - 1) + this._text.slice(deletePosition);
+                            }
+                        }
+                    }
+                    return;
+                case 46: // DELETE
+                    if (this._text && this._text.length > 0) {
+                        let deletePosition = this._text.length - this._cursorOffset;
+                        this.text = this._text.slice(0, deletePosition) + this._text.slice(deletePosition + 1);
+                        this._cursorOffset--;
+                    }
+                    return;                    
+                case 13: // RETURN
+                    this._host.focusedControl = null;
+                    return;
+                case 35: // END
+                    this._cursorOffset = 0;
+                    this._blinkIsEven = false;
+                    this._markAsDirty();                
+                    return;
+                case 36: // HOME
+                    this._cursorOffset = this._text.length;
+                    this._blinkIsEven = false;
+                    this._markAsDirty();                
+                return;
+                case 37: // LEFT
+                    this._cursorOffset++;
+                    if (this._cursorOffset > this._text.length) {
+                        this._cursorOffset = this._text.length;
+                    }
+                    this._blinkIsEven = false;
+                    this._markAsDirty();
+                    return;
+                case 39: // RIGHT
+                    this._cursorOffset--;
+                    if (this._cursorOffset < 0) {
+                        this._cursorOffset = 0;
+                    }
+                    this._blinkIsEven = false;
+                    this._markAsDirty();
+                    return;
+            }
+
+            // Printable characters
+            if (
+                (keyCode === -1) ||                     // Direct access
+                (keyCode === 32) ||                     // Space
+                (keyCode > 47 && keyCode < 58) ||       // Numbers
+                (keyCode > 64 && keyCode < 91) ||       // Letters
+                (keyCode > 185 && keyCode < 193) ||     // Special characters
+                (keyCode > 218  && keyCode < 223) ||    // Special characters
+                (keyCode > 95 && keyCode < 112)) {      // Numpad
+                    if (this._cursorOffset === 0) {
+                        this.text += key;
+                    } else {
+                        let insertPosition = this._text.length - this._cursorOffset;
+
+                        this.text = this._text.slice(0, insertPosition) + key + this._text.slice(insertPosition);
+                    }
+                }
+        }
+
+        public processKeyboard(evt: KeyboardEvent): void {
+            this.processKey(evt.keyCode, evt.key);
+        }
+
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
 
             this._applyStates(context);
             if (this._processMeasures(parentMeasure, context)) {
                 
                 // Background
-                if (this._background) {
+                if (this._isFocused) {
+                    if (this._focusedBackground) {
+                        context.fillStyle = this._focusedBackground;
+    
+                        context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                    }                        
+                } else if (this._background) {
                     context.fillStyle = this._background;
 
                     context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
                 }
 
+                if (!this._fontOffset) {
+                    this._fontOffset = Control._GetFontOffset(context.font);
+                }
+
                 // Text
-                if (this._text) {
-                    if (this.color) {
-                        context.fillStyle = this.color;
+                let clipTextLeft = this._currentMeasure.left + this._margin.getValueInPixel(this._host, parentMeasure.width);
+                if (this.color) {
+                    context.fillStyle = this.color;
+                }
+
+                let textWidth = context.measureText(this._text).width;   
+                let marginWidth = this._margin.getValueInPixel(this._host, parentMeasure.width) * 2;
+                if (this._autoStretchWidth) {
+                    this.width = Math.min(this._maxWidth.getValueInPixel(this._host, parentMeasure.width), textWidth + marginWidth) + "px";
+                }
+
+                let rootY = this._fontOffset.ascent + (this._currentMeasure.height - this._fontOffset.height) / 2;
+                let availableWidth = this._width.getValueInPixel(this._host, parentMeasure.width) - marginWidth;
+                context.save();
+                context.beginPath();
+                context.rect(clipTextLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, availableWidth + 2, this._currentMeasure.height);
+                context.clip();
+
+                if (this._isFocused && textWidth > availableWidth) {      
+                    let textLeft = clipTextLeft - textWidth + availableWidth;
+                    if (!this._scrollLeft) {
+                        this._scrollLeft = textLeft;
                     }
+                } else {
+                    this._scrollLeft = clipTextLeft;
+                }
 
-                    let rootY = this._fontOffset.ascent + (this._currentMeasure.height - this._fontOffset.height) / 2;
-                    context.fillText(this._text, this._currentMeasure.left + this._margin.getValueInPixel(this._host, parentMeasure.width), this._currentMeasure.top + rootY);
+                context.fillText(this._text, this._scrollLeft, this._currentMeasure.top + rootY);
 
-                    if (this._autoStretchWidth) {
-                        this.width = Math.min(this._maxWidth.getValueInPixel(this._host, parentMeasure.width), context.measureText(this._text).width + this._margin.getValueInPixel(this._host, parentMeasure.width) * 2) + "px";
+                // Cursor
+                if (this._isFocused) {         
+                    if (!this._blinkIsEven) {
+                        let cursorOffsetText = this.text.substr(this._text.length - this._cursorOffset);
+                        let cursorOffsetWidth = context.measureText(cursorOffsetText).width;   
+                        let cursorLeft = this._scrollLeft  + textWidth - cursorOffsetWidth;
+    
+                        if (cursorLeft < clipTextLeft) {
+                            this._scrollLeft += (clipTextLeft - cursorLeft);
+                            cursorLeft = clipTextLeft;
+                            this._markAsDirty();
+                        } else if (cursorLeft > clipTextLeft + availableWidth) {
+                            this._scrollLeft += (clipTextLeft  + availableWidth - cursorLeft);
+                            cursorLeft = clipTextLeft + availableWidth;
+                            this._markAsDirty();
+                        }                   
+                        context.fillRect(cursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, 2, this._fontOffset.height);
                     }
+
+                    clearTimeout(this._blinkTimeout);
+                    this._blinkTimeout = setTimeout(() => {
+                        this._blinkIsEven = !this._blinkIsEven;
+                        this._markAsDirty();
+                    }, 500);
                 }
 
+                context.restore();
+
                 // Border
                 if (this._thickness) {
                     if (this.color) {
@@ -138,5 +321,27 @@ module BABYLON.GUI {
             }
             context.restore();
         }
+
+        protected _onPointerDown(coordinates: Vector2): boolean {
+            if (!super._onPointerDown(coordinates)) {
+                return false;
+            }
+
+            this._host.focusedControl = this;
+
+            return true;
+        }
+
+        protected _onPointerUp(coordinates: Vector2): void {
+            super._onPointerUp(coordinates);
+        }  
+
+        public dispose() {
+            super.dispose();
+
+            this.onBlurObservable.clear();
+            this.onFocusObservable.clear();
+            this.onTextChangedObservable.clear();
+        }
     }
 }

+ 136 - 0
gui/src/controls/virtualKeyboard.ts

@@ -0,0 +1,136 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+
+    export class KeyPropertySet {
+        width?: string;
+        height?: string;
+        paddingLeft?: string;
+        paddingRight?: string;
+        paddingTop?: string;
+        paddingBottom?: string;
+        color?: string;
+        background?: string;
+    }
+
+    export class VirtualKeyboard extends StackPanel {
+        public onKeyPressObservable = new Observable<string>();
+
+        public defaultButtonWidth = "40px";
+        public defaultButtonHeight = "40px";
+
+        public defaultButtonPaddingLeft= "2px";
+        public defaultButtonPaddingRight = "2px";
+        public defaultButtonPaddingTop = "2px";
+        public defaultButtonPaddingBottom = "2px";    
+        
+        public defaultButtonColor = "#DDD";
+        public defaultButtonBackground = "#070707";    
+        
+        protected _getTypeName(): string {
+            return "VirtualKeyboard";
+        }
+
+        private _createKey(key: string, propertySet?: KeyPropertySet) {
+            var button = Button.CreateSimpleButton(key, key);
+            
+           
+            button.width = propertySet && propertySet.width ? propertySet.width : this.defaultButtonWidth;
+            button.height = propertySet && propertySet.height ? propertySet.height : this.defaultButtonHeight;
+            button.color = propertySet && propertySet.color ? propertySet.color : this.defaultButtonColor;
+            button.background = propertySet && propertySet.background ? propertySet.background : this.defaultButtonBackground;
+            button.paddingLeft = propertySet && propertySet.paddingLeft ? propertySet.paddingLeft : this.defaultButtonPaddingLeft;
+            button.paddingRight = propertySet && propertySet.paddingRight ? propertySet.paddingRight : this.defaultButtonPaddingRight;
+            button.paddingTop = propertySet && propertySet.paddingTop ? propertySet.paddingTop : this.defaultButtonPaddingTop;
+            button.paddingBottom = propertySet && propertySet.paddingBottom ? propertySet.paddingBottom : this.defaultButtonPaddingBottom;
+        
+            button.thickness = 0;
+            button.isFocusInvisible = true;
+        
+            button.onPointerUpObservable.add(() => {
+                this.onKeyPressObservable.notifyObservers(key);
+            });
+    
+            return button;
+        }
+
+        public addKeysRow(keys: Array<string>, propertySets?: Array<KeyPropertySet>): void {
+            let panel = new StackPanel();
+            panel.isVertical = false;
+            panel.isFocusInvisible = true;
+        
+            for(var i = 0; i < keys.length; i++) {
+                let properties = null;
+
+                if (propertySets && propertySets.length === keys.length) {
+                    properties = propertySets[i];
+                }
+
+                panel.addControl(this._createKey(keys[i], properties));
+            }
+        
+            this.addControl(panel);
+        }
+
+        private _connectedInputText: InputText;
+        private _onFocusObserver: Observer<InputText>;
+        private _onBlurObserver: Observer<InputText>;
+        private _onKeyPressObserver: Observer<string>;
+
+        public get connectedInputText(): InputText {
+            return this._connectedInputText;
+        }
+
+        public connect(input: InputText): void {
+            this.isVisible = false;
+            this._connectedInputText = input;
+            
+            // Events hooking
+            this._onFocusObserver = input.onFocusObservable.add(() => {
+                this.isVisible = true;
+            });
+    
+            this._onBlurObserver = input.onBlurObservable.add(() => {
+                this.isVisible = false;
+            });		
+
+            this._onKeyPressObserver = this.onKeyPressObservable.add((key) => {
+                switch (key) {
+                    case "\u2190":
+                        this._connectedInputText.processKey(8);
+                        return;
+                    case "\u21B5":
+                        this._connectedInputText.processKey(13);
+                        return;                        
+                }
+
+                this._connectedInputText.processKey(-1, key);
+            });
+        }
+
+        public disconnect(): void {
+            if (!this._connectedInputText) {
+                return;
+            }
+
+            this._connectedInputText.onFocusObservable.remove(this._onFocusObserver);
+            this._connectedInputText.onBlurObservable.remove(this._onBlurObserver);
+            this.onKeyPressObservable.remove(this._onKeyPressObserver);
+
+            this._connectedInputText = null;
+        }
+
+        // Statics
+        public static CreateDefaultLayout(): VirtualKeyboard {
+            let returnValue = new VirtualKeyboard();
+
+            returnValue.addKeysRow(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0","\u2190"]);
+            returnValue.addKeysRow(["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"]);
+            returnValue.addKeysRow(["a", "s", "d", "f", "g", "h", "j", "k", "l",";","'","\u21B5"]);
+            returnValue.addKeysRow(["z", "x", "c", "v", "b", "n", "m", ",", ".", "/"]);
+            returnValue.addKeysRow([" "], [{ width: "200px"}]);
+        
+            return returnValue;
+        }
+    }
+}

+ 0 - 1
loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts

@@ -40,7 +40,6 @@ module BABYLON.GLTF2.Extensions {
 
             if (properties.diffuseTexture) {
                 babylonMaterial.albedoTexture = loader.loadTexture(properties.diffuseTexture);
-                loader.loadMaterialAlphaProperties(material);
             }
 
             if (properties.specularGlossinessTexture) {

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

@@ -12,7 +12,6 @@ module BABYLON.GLTF2 {
         private _errorCallback: (message: string) => void;
         private _renderReady: boolean = false;
         private _disposed: boolean = false;
-        private _objectURLs: string[] = new Array<string>();
         private _blockPendingTracking: boolean = false;
         private _nonBlockingData: Array<any>;
 
@@ -68,8 +67,13 @@ module BABYLON.GLTF2 {
             this._disposed = true;
 
             // Revoke object urls created during load
-            this._objectURLs.forEach(url => URL.revokeObjectURL(url));
-            this._objectURLs.length = 0;
+            if (this._gltf.textures) {
+                this._gltf.textures.forEach(texture => {
+                    if (texture.url) {
+                        URL.revokeObjectURL(texture.url);
+                    }
+                });
+            }
 
             this._gltf = undefined;
             this._babylonScene = undefined;
@@ -158,7 +162,7 @@ module BABYLON.GLTF2 {
 
             var binaryBuffer: IGLTFBuffer;
             var buffers = this._gltf.buffers;
-            if (buffers.length > 0 && buffers[0].uri === undefined) {
+            if (buffers && buffers[0].uri === undefined) {
                 binaryBuffer = buffers[0];
             }
 
@@ -182,10 +186,12 @@ module BABYLON.GLTF2 {
             rootMesh.rotation.y = Math.PI;
 
             var nodes = this._gltf.nodes;
-            for (var i = 0; i < nodes.length; i++) {
-                var mesh = nodes[i].babylonMesh;
-                if (mesh && !mesh.parent) {
-                    mesh.parent = rootMesh;
+            if (nodes) {
+                for (var i = 0; i < nodes.length; i++) {
+                    var mesh = nodes[i].babylonMesh;
+                    if (mesh && !mesh.parent) {
+                        mesh.parent = rootMesh;
+                    }
                 }
             }
         }
@@ -1131,6 +1137,8 @@ module BABYLON.GLTF2 {
                     Tools.Warn("Invalid alpha mode '" + material.alphaMode + "'");
                     break;
             }
+
+            babylonMaterial.alphaCutOff = material.alphaCutoff === undefined ? 0.5 : material.alphaCutoff;
         }
 
         public loadTexture(textureInfo: IGLTFTextureInfo): Texture {
@@ -1141,31 +1149,13 @@ module BABYLON.GLTF2 {
                 return null;
             }
 
-            // check the cache first
-            var babylonTexture: Texture;
-            if (texture.babylonTextures) {
-                babylonTexture = texture.babylonTextures[texCoord];
-                if (!babylonTexture) {
-                    for (var i = 0; i < texture.babylonTextures.length; i++) {
-                        babylonTexture = texture.babylonTextures[i];
-                        if (babylonTexture) {
-                            babylonTexture = babylonTexture.clone();
-                            babylonTexture.coordinatesIndex = texCoord;
-                            break;
-                        }
-                    }
-                }
-
-                return babylonTexture;
-            }
-
             var source = this._gltf.images[texture.source];
             var sampler = (texture.sampler === undefined ? <IGLTFSampler>{} : this._gltf.samplers[texture.sampler]);
             var noMipMaps = (sampler.minFilter === ETextureMinFilter.NEAREST || sampler.minFilter === ETextureMinFilter.LINEAR);
             var samplingMode = GLTFUtils.GetTextureSamplingMode(sampler.magFilter, sampler.minFilter);
 
             this.addPendingData(texture);
-            babylonTexture = new Texture(null, this._babylonScene, noMipMaps, false, samplingMode, () => {
+            var babylonTexture = new Texture(null, this._babylonScene, noMipMaps, false, samplingMode, () => {
                 if (!this._disposed) {
                     this.removePendingData(texture);
                 }
@@ -1176,27 +1166,41 @@ module BABYLON.GLTF2 {
                 }
             });
 
-            var setTextureData = data => {
-                var url = URL.createObjectURL(new Blob([data], { type: source.mimeType }));
-                this._objectURLs.push(url);
-                babylonTexture.updateURL(url);
-            };
-
-            if (!source.uri) {
-                var bufferView = this._gltf.bufferViews[source.bufferView];
-                this._loadBufferViewAsync(bufferView, 0, bufferView.byteLength, 1, EComponentType.UNSIGNED_BYTE, setTextureData);
+            if (texture.url) {
+                babylonTexture.updateURL(texture.url);
             }
-            else if (GLTFUtils.IsBase64(source.uri)) {
-                setTextureData(new Uint8Array(GLTFUtils.DecodeBase64(source.uri)));
+            else if (texture.dataReadyObservable) {
+                texture.dataReadyObservable.add(texture => {
+                    babylonTexture.updateURL(texture.url);
+                });
             }
             else {
-                Tools.LoadFile(this._rootUrl + source.uri, setTextureData, event => {
-                    if (!this._disposed) {
-                        this._onProgress(event);
-                    }
-                }, this._babylonScene.database, true, request => {
-                    this._onError("Failed to load file '" + source.uri + "': " + request.status + " " + request.statusText);
+                texture.dataReadyObservable = new Observable<IGLTFTexture>();
+                texture.dataReadyObservable.add(texture => {
+                    babylonTexture.updateURL(texture.url);
                 });
+
+                var setTextureData = data => {
+                    texture.url = URL.createObjectURL(new Blob([data], { type: source.mimeType }));
+                    texture.dataReadyObservable.notifyObservers(texture);
+                };
+
+                if (!source.uri) {
+                    var bufferView = this._gltf.bufferViews[source.bufferView];
+                    this._loadBufferViewAsync(bufferView, 0, bufferView.byteLength, 1, EComponentType.UNSIGNED_BYTE, setTextureData);
+                }
+                else if (GLTFUtils.IsBase64(source.uri)) {
+                    setTextureData(new Uint8Array(GLTFUtils.DecodeBase64(source.uri)));
+                }
+                else {
+                    Tools.LoadFile(this._rootUrl + source.uri, setTextureData, event => {
+                        if (!this._disposed) {
+                            this._onProgress(event);
+                        }
+                    }, this._babylonScene.database, true, request => {
+                        this._onError("Failed to load file '" + source.uri + "': " + request.status + " " + request.statusText);
+                    });
+                }
             }
 
             babylonTexture.coordinatesIndex = texCoord;
@@ -1204,10 +1208,6 @@ module BABYLON.GLTF2 {
             babylonTexture.wrapV = GLTFUtils.GetTextureWrapMode(sampler.wrapT);
             babylonTexture.name = texture.name || "texture" + textureInfo.index;
 
-            // Cache the texture
-            texture.babylonTextures = texture.babylonTextures || [];
-            texture.babylonTextures[texCoord] = babylonTexture;
-
             if (this._parent.onTextureLoaded) {
                 this._parent.onTextureLoaded(babylonTexture);
             }

+ 3 - 3
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -245,8 +245,9 @@ module BABYLON.GLTF2 {
         sampler?: number;
         source: number;
 
-        // Runtime values (one per coordinate index)
-        babylonTextures?: Texture[];
+        // Runtime values
+        url?: string;
+        dataReadyObservable?: Observable<IGLTFTexture>;
     }
 
     export interface IGLTFTextureInfo {
@@ -263,7 +264,6 @@ module BABYLON.GLTF2 {
         cameras?: IGLTFCamera[];
         extensionsUsed?: string[];
         extensionsRequired?: string[];
-        glExtensionsUsed?: string[];
         images?: IGLTFImage[];
         materials?: IGLTFMaterial[];
         meshes?: IGLTFMesh[];

+ 5 - 4
localDev/index.html

@@ -3,8 +3,9 @@
 <head>
 	<title>Local Development</title>
 	
-    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
+    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+	<script src="https://preview.babylonjs.com/cannon.js"></script>
+	<script src="https://preview.babylonjs.com/Oimo.js"></script>
 	<script src="../assets/refs/dat.gui.min.js"></script>
 	<script src="../tools/DevLoader/BabylonLoader.js"></script>
 	<script src="src/webgl-debug.js"></script>
@@ -39,11 +40,11 @@
 </head>
 <body>
 	<div id="fps">0</div>
-	<canvas id="renderCanvas"></canvas>
+	<canvas id="renderCanvas" touch-action="none"></canvas>
 	
 	<script>
 		var canvas = document.getElementById("renderCanvas");
-		// canvas = WebGLDebugUtils.makeLostContextSimulatingCanvas(canvas);
+	//	canvas = WebGLDebugUtils.makeLostContextSimulatingCanvas(canvas);
 		var divFps = document.getElementById("fps");
 
 		// Global to simulate PG.

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

@@ -18,6 +18,7 @@ module BABYLON {
         public NDOTL = true;
         public CUSTOMUSERLIGHTING = true;
         public CELLBASIC = true;
+        public DEPTHPREPASS = false;
         public USERIGHTHANDEDSYSTEM = false;
 
         constructor() {

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

@@ -107,6 +107,8 @@ void main(void)
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/fire/babylon.fireMaterial.ts

@@ -6,6 +6,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public UV1 = false;

+ 2 - 0
materialsLibrary/src/fire/fire.fragment.fx

@@ -71,6 +71,8 @@ void main(void) {
 	if (opacityColor.r < 0.1)
 		discard;
 #endif
+
+#include<depthPrePass>
 	
 	baseColor = texture2D(diffuseSampler, perturbedBaseCoords.xy) * 2.0;
 	baseColor *= opacityColor;

+ 1 - 0
materialsLibrary/src/fur/babylon.furMaterial.ts

@@ -6,6 +6,7 @@ module BABYLON {
         public HEIGHTMAP = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public NORMAL = false;

+ 2 - 0
materialsLibrary/src/fur/fur.fragment.fx

@@ -70,6 +70,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/gradient/babylon.gradientMaterial.ts

@@ -5,6 +5,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public LIGHT0 = false;

+ 2 - 0
materialsLibrary/src/gradient/gradient.fragment.fx

@@ -68,6 +68,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 #ifdef VERTEXCOLOR
 	baseColor.rgb *= vColor.rgb;
 #endif

+ 1 - 0
materialsLibrary/src/lava/babylon.lavaMaterial.ts

@@ -5,6 +5,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public LIGHT0 = false;

+ 2 - 0
materialsLibrary/src/lava/lava.fragment.fx

@@ -108,6 +108,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -5,6 +5,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public LIGHT0 = false;

+ 2 - 0
materialsLibrary/src/normal/normal.fragment.fx

@@ -60,6 +60,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/simple/babylon.simpleMaterial.ts

@@ -5,6 +5,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public NORMAL = false;

+ 2 - 0
materialsLibrary/src/simple/simple.fragment.fx

@@ -56,6 +56,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/terrain/babylon.terrainMaterial.ts

@@ -7,6 +7,7 @@ module BABYLON {
         public BUMP = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public SPECULARTERM = false;

+ 2 - 0
materialsLibrary/src/terrain/terrain.fragment.fx

@@ -137,6 +137,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vTextureInfos.y;
 	
 	vec4 diffuse1Color = texture2D(diffuse1Sampler, vTextureUV * diffuse1Infos);

+ 1 - 0
materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts

@@ -12,6 +12,7 @@ module BABYLON {
         
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public SPECULARTERM = false;

+ 2 - 0
materialsLibrary/src/triPlanar/triplanar.fragment.fx

@@ -108,6 +108,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 #ifdef VERTEXCOLOR
 	baseColor.rgb *= vColor.rgb;
 #endif

+ 1 - 0
materialsLibrary/src/water/babylon.waterMaterial.ts

@@ -6,6 +6,7 @@ module BABYLON {
         public REFLECTION = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public NORMAL = false;

+ 3 - 2
src/Animations/babylon.animation.ts

@@ -89,6 +89,8 @@
     }
 
     export class Animation {
+        public static AllowMatricesInterpolation = false;
+
         private _keys: Array<{frame:number, value: any, inTangent?: any, outTangent?: any}>;
         private _offsetsCache = {};
         private _highLimitsCache = {};
@@ -103,7 +105,6 @@
         public targetPropertyPath: string[];
         public currentFrame: number;
 
-        public allowMatricesInterpolation = false;
 
         public blendingSpeed = 0.01;
         private _originalBlendValue: any;
@@ -520,7 +521,7 @@
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                    if (this.allowMatricesInterpolation) {
+                                    if (Animation.AllowMatricesInterpolation) {
                                         return this.matrixInterpolateFunction(startValue, endValue, gradient);
                                     }
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:

+ 7 - 5
src/Behaviors/Cameras/babylon.framingBehavior.ts

@@ -205,12 +205,13 @@ module BABYLON {
 		 * @param radius Optional. If a cached radius position already exists, overrides default.
 		 * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
 		 * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+		 * @param onAnimationEnd Callback triggered at the end of the framing animation
 		 */
-		public zoomOnMesh(mesh: AbstractMesh, focusOnOriginXZ: boolean = false): void {
+		public zoomOnMesh(mesh: AbstractMesh, focusOnOriginXZ: boolean = false, onAnimationEnd: () => void = null): void {
 			mesh.computeWorldMatrix(true);
 
 			let boundingBox = mesh.getBoundingInfo().boundingBox;
-			this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ);
+			this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ, onAnimationEnd);
 		}
 
 		/**
@@ -219,8 +220,9 @@ module BABYLON {
 		 * @param radius Optional. If a cached radius position already exists, overrides default.
 		 * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
 		 * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+		 * @param onAnimationEnd Callback triggered at the end of the framing animation
 		 */
-		public zoomOnBoundingInfo(minimumWorld: Vector3, maximumWorld: Vector3, focusOnOriginXZ: boolean = false): void {
+		public zoomOnBoundingInfo(minimumWorld: Vector3, maximumWorld: Vector3, focusOnOriginXZ: boolean = false, onAnimationEnd: () => void = null): void {
 			let zoomTarget: BABYLON.Vector3;
 
 			// Find target by interpolating from bottom of bounding box in world-space to top via framingPositionY
@@ -265,8 +267,8 @@ module BABYLON {
 			}
 
 			this._animatables.push(Animation.TransitionTo("radius", radius, this._attachedCamera, this._attachedCamera.getScene(), 
-									60, this._radiusTransition, this._framingTime));															
-		}	
+				60, this._radiusTransition, this._framingTime, onAnimationEnd));
+		}
 		
 		/**
 		 * Calculates the lowest radius for the camera based on the bounding box of the mesh.

+ 57 - 78
src/Cameras/Inputs/babylon.arcRotateCameraKeyboardMoveInput.ts

@@ -2,11 +2,6 @@ module BABYLON {
     export class ArcRotateCameraKeyboardMoveInput implements ICameraInput<ArcRotateCamera> {
         camera: ArcRotateCamera;
         private _keys = [];
-        private _onKeyDown: (e: KeyboardEvent) => any;
-        private _onKeyUp: (e: KeyboardEvent) => any;
-        private _onLostFocus: (e: FocusEvent) => any;
-        private _onFocus: () => void;
-        private _onBlur: () => void;
         
         @serialize()
         public keysUp = [38];
@@ -27,97 +22,81 @@ module BABYLON {
         public panningSensibility: number = 50.0;        
 
         private _ctrlPressed: boolean;
+        private _onCanvasBlurObserver: Observer<Engine>;
+        private _onKeyboardObserver: Observer<KeyboardInfo>;
+        private _engine: Engine;
+        private _scene: Scene;
 
         public attachControl(element: HTMLElement, noPreventDefault?: boolean) {
-            element.tabIndex = 1;
-
-            this._onKeyDown = evt => {
-
-                this._ctrlPressed = evt.ctrlKey;
-
-                if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
-                    this.keysDown.indexOf(evt.keyCode) !== -1 ||
-                    this.keysLeft.indexOf(evt.keyCode) !== -1 ||
-                    this.keysRight.indexOf(evt.keyCode) !== -1 ||
-                    this.keysReset.indexOf(evt.keyCode) !== -1) {
-                    var index = this._keys.indexOf(evt.keyCode);
+            if (this._onCanvasBlurObserver) {
+                return;
+            }
+            
+            this._scene = this.camera.getScene();
+            this._engine = this._scene.getEngine();
 
-                    if (index === -1) {
-                        this._keys.push(evt.keyCode);
-                    }
+            this._onCanvasBlurObserver = this._engine.onCanvasBlurObservable.add(()=>{
+                this._keys = [];
+            });
+
+            this._onKeyboardObserver = this._scene.onKeyboardObservable.add(info => {
+                let evt = info.event;
+
+                if (info.type === KeyboardEventTypes.KEYDOWN) {
+                    this._ctrlPressed = evt.ctrlKey;
+                    
+                    if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
+                        this.keysDown.indexOf(evt.keyCode) !== -1 ||
+                        this.keysLeft.indexOf(evt.keyCode) !== -1 ||
+                        this.keysRight.indexOf(evt.keyCode) !== -1 ||
+                        this.keysReset.indexOf(evt.keyCode) !== -1) {
+                        var index = this._keys.indexOf(evt.keyCode);
+
+                        if (index === -1) {
+                            this._keys.push(evt.keyCode);
+                        }
 
-                    if (evt.preventDefault) {
-                        if (!noPreventDefault) {
-                            evt.preventDefault();
+                        if (evt.preventDefault) {
+                            if (!noPreventDefault) {
+                                evt.preventDefault();
+                            }
                         }
                     }
-                }
-            };
-
-            this._onKeyUp = evt => {
-                
-                if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
-                    this.keysDown.indexOf(evt.keyCode) !== -1 ||
-                    this.keysLeft.indexOf(evt.keyCode) !== -1 ||
-                    this.keysRight.indexOf(evt.keyCode) !== -1 ||
-                    this.keysReset.indexOf(evt.keyCode) !== -1) {
-                    var index = this._keys.indexOf(evt.keyCode);
-
-                    if (index >= 0) {
-                        this._keys.splice(index, 1);
-                    }
-
-                    if (evt.preventDefault) {
-                        if (!noPreventDefault) {
-                            evt.preventDefault();
+                } else {
+                    if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
+                        this.keysDown.indexOf(evt.keyCode) !== -1 ||
+                        this.keysLeft.indexOf(evt.keyCode) !== -1 ||
+                        this.keysRight.indexOf(evt.keyCode) !== -1 ||
+                        this.keysReset.indexOf(evt.keyCode) !== -1) {
+                        var index = this._keys.indexOf(evt.keyCode);
+    
+                        if (index >= 0) {
+                            this._keys.splice(index, 1);
+                        }
+    
+                        if (evt.preventDefault) {
+                            if (!noPreventDefault) {
+                                evt.preventDefault();
+                            }
                         }
                     }
                 }
-            };
-
-            this._onLostFocus = () => {
-                this._keys = [];
-            };
-
-            this._onFocus = () => {
-                element.addEventListener("keydown", this._onKeyDown, false);
-                element.addEventListener("keyup", this._onKeyUp, false);   
-            }
-
-            this._onBlur = () => {
-                element.removeEventListener("keydown", this._onKeyDown);
-                element.removeEventListener("keyup", this._onKeyUp);
-            }
-
-            element.addEventListener("focus", this._onFocus);
-            element.addEventListener("blur", this._onBlur);
-
-            Tools.RegisterTopRootEvents([
-                { name: "blur", handler: this._onLostFocus }
-            ]);
+            });    
         }
 
         public detachControl(element: HTMLElement) {
-            if (element && this._onBlur) {
-                this._onBlur();
-                element.removeEventListener("focus", this._onFocus);
-                element.removeEventListener("blur", this._onBlur);
+            if (this._scene) {
+                this._scene.onKeyboardObservable.remove(this._onKeyboardObserver);
+                this._engine.onCanvasBlurObservable.remove(this._onCanvasBlurObserver);
+                this._onKeyboardObserver = null;
+                this._onCanvasBlurObserver = null;
             }
 
-            Tools.UnregisterTopRootEvents([
-                { name: "blur", handler: this._onLostFocus }
-            ]);
-            
             this._keys = [];
-            this._onKeyDown = null;
-            this._onKeyUp = null;
-            this._onLostFocus = null;
-            this._onBlur = null;
-            this._onFocus = null;
         }
 
         public checkInputs() {
-            if (this._onKeyDown){
+            if (this._onKeyboardObserver){
                 var camera = this.camera;
 
                 for (var index = 0; index < this._keys.length; index++) {

+ 39 - 8
src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts

@@ -19,6 +19,9 @@ module BABYLON {
         @serialize()
         public panningSensibility: number = 50.0;
 
+        @serialize()
+        public multiTouchPanning: boolean = true;
+
         private _isPanClick: boolean = false;
         public pinchInwards = true;
 
@@ -35,7 +38,9 @@ module BABYLON {
             var engine = this.camera.getEngine();
             var cacheSoloPointer: { x: number, y: number, pointerId: number, type: any }; // cache pointer object for better perf on camera rotation
             var pointA: { x: number, y: number, pointerId: number, type: any }, pointB: { x: number, y: number, pointerId: number, type: any };
+            var previousPinchSquaredDistance = 0;
             var previousPinchDistance = 0;
+            var previousMultiTouchPanPosition: { x: number, y: number, isPaning: boolean } = { x: 0, y:0, isPaning: false };
 
             this._pointerInput = (p, s) => {
                 var evt = <PointerEvent>p.event;
@@ -78,7 +83,9 @@ module BABYLON {
                     }
 
                     cacheSoloPointer = null;
+                    previousPinchSquaredDistance = 0;
                     previousPinchDistance = 0;
+                    previousMultiTouchPanPosition.isPaning = false;
 
                     //would be better to use pointers.remove(evt.pointerId) for multitouch gestures, 
                     //but emptying completly pointers collection is required to fix a bug on iPhone : 
@@ -97,8 +104,7 @@ module BABYLON {
                     // One button down
                     if (pointA && pointB === undefined) {
                         if (this.panningSensibility !== 0 &&
-                            ((evt.ctrlKey && this.camera._useCtrlForPanning) ||
-                                (!this.camera._useCtrlForPanning && this._isPanClick))) {
+                            ((evt.ctrlKey && this.camera._useCtrlForPanning) || this._isPanClick)) {
                             this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / this.panningSensibility;
                             this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / this.panningSensibility;
                         } else {
@@ -112,7 +118,7 @@ module BABYLON {
                         cacheSoloPointer.y = evt.clientY;
                     }
 
-                    // Two buttons down: pinch
+                    // Two buttons down: pinch/pan
                     else if (pointA && pointB) {
                         //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be useful to force preventDefault to avoid html page scroll/zoom in some mobile browsers
                         var ed = (pointA.pointerId === evt.pointerId) ? pointA : pointB;
@@ -122,19 +128,42 @@ module BABYLON {
                         var distX = pointA.x - pointB.x;
                         var distY = pointA.y - pointB.y;
                         var pinchSquaredDistance = (distX * distX) + (distY * distY);
-                        if (previousPinchDistance === 0) {
-                            previousPinchDistance = pinchSquaredDistance;
+                        var pinchDistance = Math.sqrt(pinchSquaredDistance);
+                        if (previousPinchSquaredDistance === 0) {
+                            previousPinchSquaredDistance = pinchSquaredDistance;
+                            previousPinchDistance = pinchDistance;
                             return;
                         }
 
-                        if (pinchSquaredDistance !== previousPinchDistance) {
+                        if (Math.abs(pinchDistance - previousPinchDistance) > this.camera.pinchToPanMaxDistance) {
                             this.camera
-                                .inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) /
+                                .inertialRadiusOffset += (pinchSquaredDistance - previousPinchSquaredDistance) /
                                 (this.pinchPrecision *
                                     ((this.angularSensibilityX + this.angularSensibilityY) / 2) *
                                     direction);
-                            previousPinchDistance = pinchSquaredDistance;
+                            previousMultiTouchPanPosition.isPaning = false;
+                        }
+                        else {
+                            if (cacheSoloPointer.pointerId === ed.pointerId && this.panningSensibility !== 0 && this.multiTouchPanning) {
+                                if (!previousMultiTouchPanPosition.isPaning) {
+                                    previousMultiTouchPanPosition.isPaning = true;
+                                    previousMultiTouchPanPosition.x = ed.x;
+                                    previousMultiTouchPanPosition.y = ed.y;
+                                    return;
+                                }
+
+                                this.camera.inertialPanningX += -(ed.x - previousMultiTouchPanPosition.x) / this.panningSensibility;
+                                this.camera.inertialPanningY += (ed.y - previousMultiTouchPanPosition.y) / this.panningSensibility;
+                            }
                         }
+
+                        if (cacheSoloPointer.pointerId === evt.pointerId) {
+                            previousMultiTouchPanPosition.x = ed.x;
+                            previousMultiTouchPanPosition.y = ed.y;
+                        }
+
+                        previousPinchSquaredDistance = pinchSquaredDistance;
+                        previousPinchDistance = pinchDistance;
                     }
                 }
             }
@@ -152,7 +181,9 @@ module BABYLON {
             this._onLostFocus = () => {
                 //this._keys = [];
                 pointA = pointB = undefined;
+                previousPinchSquaredDistance = 0;
                 previousPinchDistance = 0;
+                previousMultiTouchPanPosition.isPaning = false;
                 cacheSoloPointer = null;
             };
 

+ 28 - 28
src/Cameras/Inputs/babylon.freeCameraKeyboardMoveInput.ts

@@ -2,8 +2,10 @@ module BABYLON {
     export class FreeCameraKeyboardMoveInput implements ICameraInput<FreeCamera> {
         camera: FreeCamera;
         private _keys = [];
-        private _onKeyDown: (e: KeyboardEvent) => any;
-        private _onKeyUp: (e: KeyboardEvent) => any;
+        private _onCanvasBlurObserver: Observer<Engine>;
+        private _onKeyboardObserver: Observer<KeyboardInfo>;
+        private _engine: Engine;
+        private _scene: Scene;        
 
         @serialize()
         public keysUp = [38];
@@ -18,10 +20,21 @@ module BABYLON {
         public keysRight = [39];
 
         attachControl(element : HTMLElement, noPreventDefault?: boolean) {
-            if (!this._onKeyDown) {
-                element.tabIndex = 1;
+            if (this._onCanvasBlurObserver) {
+                return;
+            }
+
+            this._scene = this.camera.getScene();
+            this._engine = this._scene.getEngine();
+
+            this._onCanvasBlurObserver = this._engine.onCanvasBlurObservable.add(()=>{
+                this._keys = [];
+            });
 
-                this._onKeyDown = evt => {
+            this._onKeyboardObserver = this._scene.onKeyboardObservable.add(info => {
+                let evt = info.event;
+
+                if (info.type === KeyboardEventTypes.KEYDOWN) {
                     if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
                         this.keysDown.indexOf(evt.keyCode) !== -1 ||
                         this.keysLeft.indexOf(evt.keyCode) !== -1 ||
@@ -35,9 +48,7 @@ module BABYLON {
                             evt.preventDefault();
                         }
                     }
-                };
-
-                this._onKeyUp = evt => {
+                } else {
                     if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
                         this.keysDown.indexOf(evt.keyCode) !== -1 ||
                         this.keysLeft.indexOf(evt.keyCode) !== -1 ||
@@ -51,33 +62,22 @@ module BABYLON {
                             evt.preventDefault();
                         }
                     }
-                };
-
-                element.addEventListener("keydown", this._onKeyDown, false);
-                element.addEventListener("keyup", this._onKeyUp, false);
-
-                Tools.RegisterTopRootEvents([
-                    { name: "blur", handler: this._onLostFocus }
-                ]);
-            }
+                }
+            });     
         }
 
         detachControl(element : HTMLElement) {
-            if (this._onKeyDown) {
-                element.removeEventListener("keydown", this._onKeyDown);
-                element.removeEventListener("keyup", this._onKeyUp);
-
-                Tools.UnregisterTopRootEvents([
-                    { name: "blur", handler: this._onLostFocus }
-                ]);
-                this._keys = [];
-                this._onKeyDown = null;
-                this._onKeyUp = null;
+            if (this._scene) {
+                this._scene.onKeyboardObservable.remove(this._onKeyboardObserver);
+                this._engine.onCanvasBlurObservable.remove(this._onCanvasBlurObserver);
+                this._onKeyboardObserver = null;
+                this._onCanvasBlurObserver = null;
             }
+            this._keys = [];
         }
         
         public checkInputs() {
-            if (this._onKeyDown){
+            if (this._onKeyboardObserver){
                 var camera = this.camera;
                 // Keyboard
                 for (var index = 0; index < this._keys.length; index++) {

+ 11 - 3
src/Cameras/VR/babylon.webVRCamera.ts

@@ -406,9 +406,17 @@ module BABYLON {
                                 if (!this._lightOnControllers) {
                                     this._lightOnControllers = new BABYLON.HemisphericLight("vrControllersLight", new BABYLON.Vector3(0, 1, 0), this.getScene());
                                 }
-                                loadedMesh.getChildren().forEach((mesh) => {
-                                    this._lightOnControllers.includedOnlyMeshes.push(<AbstractMesh>mesh);
-                                });
+                                let activateLightOnSubMeshes = function(mesh: AbstractMesh, light: HemisphericLight) {
+                                    let children = mesh.getChildren();
+                                    if (children.length !== 0) {
+                                        children.forEach((mesh) => {
+                                            light.includedOnlyMeshes.push(<AbstractMesh>mesh);
+                                            activateLightOnSubMeshes(<AbstractMesh>mesh, light);
+                                        });
+                                    }
+                                }
+                                this._lightOnControllers.includedOnlyMeshes.push(loadedMesh);
+                                activateLightOnSubMeshes(loadedMesh, this._lightOnControllers);
                             }
                         });
                     }

+ 22 - 4
src/Cameras/babylon.arcRotateCamera.ts

@@ -57,6 +57,15 @@ module BABYLON {
         public inertialPanningY: number = 0;
 
         @serialize()
+        public pinchToPanMaxDistance: number = 2;
+
+        @serialize()
+        public panningDistanceLimit: number = null;
+
+        @serializeAsVector3()
+        public panningOriginTarget: Vector3 = Vector3.Zero();
+
+        @serialize()
         public panningInertia = 0.9;
 
         //-- begin properties for backward compatibility for inputs
@@ -365,8 +374,8 @@ module BABYLON {
         /**
          * Restored camera state. You must call storeState() first
          */
-        public restoreState(): boolean {
-            if (!super.restoreState()) {
+        public _restoreStateValues(): boolean {
+            if (!super._restoreStateValues()) {
                 return false;
             }
 
@@ -382,7 +391,7 @@ module BABYLON {
             this.inertialPanningY = 0;
         
             return true;
-        }             
+        }
 
         // Synchronized
         public _isSynchronizedViewMatrix(): boolean {
@@ -467,7 +476,16 @@ module BABYLON {
                 }
 
                 if (!this._targetHost) {
-                    this._target.addInPlace(this._transformedDirection);
+                    if (this.panningDistanceLimit) {
+                        this._transformedDirection.addInPlace(this._target);
+                        var distanceSquared = Vector3.DistanceSquared(this._transformedDirection, this.panningOriginTarget);
+                        if (distanceSquared <= (this.panningDistanceLimit * this.panningDistanceLimit)) {
+                            this._target.copyFrom(this._transformedDirection);
+                        }
+                    }
+                    else {
+                        this._target.addInPlace(this._transformedDirection);
+                    }
                 }
 
                 this.inertialPanningX *= this.panningInertia;

+ 16 - 2
src/Cameras/babylon.camera.ts

@@ -127,6 +127,7 @@
         public onViewMatrixChangedObservable = new Observable<Camera>();
         public onProjectionMatrixChangedObservable = new Observable<Camera>();
         public onAfterCheckInputsObservable = new Observable<Camera>();
+        public onRestoreStateObservable = new Observable<Camera>();
 
         // Cache
         private _computedViewMatrix = Matrix.Identity();
@@ -168,9 +169,9 @@
         }
 
         /**
-         * Restored camera state. You must call storeState() first
+         * Restores the camera state values if it has been stored. You must call storeState() first
          */
-        public restoreState(): boolean {
+        protected _restoreStateValues(): boolean {
             if (!this._stateStored) {
                 return false;
             }
@@ -180,6 +181,18 @@
             return true;
         }
 
+        /**
+         * Restored camera state. You must call storeState() first
+         */
+        public restoreState(): boolean {
+            if (this._restoreStateValues()) {
+                this.onRestoreStateObservable.notifyObservers(this);
+                return true;
+            }
+
+            return false;
+        }
+
         public getClassName(): string {
             return "Camera";
         }
@@ -577,6 +590,7 @@
             this.onViewMatrixChangedObservable.clear();
             this.onProjectionMatrixChangedObservable.clear();
             this.onAfterCheckInputsObservable.clear();
+            this.onRestoreStateObservable.clear();
 
             // Inputs
             if (this.inputs) {

+ 4 - 4
src/Cameras/babylon.freeCamera.ts

@@ -114,7 +114,7 @@
             this._collisionMask = !isNaN(mask) ? mask : -1;
         }
 	 
-        public _collideWithWorld(direction: Vector3): void {
+        public _collideWithWorld(displacement: Vector3): void {
             var globalPosition: Vector3;
 
             if (this.parent) {
@@ -133,15 +133,15 @@
             this._collider.collisionMask = this._collisionMask;
 		
             //no need for clone, as long as gravity is not on.
-            var actualDirection = direction;
+            var actualDisplacement = displacement;
 			
             //add gravity to the direction to prevent the dual-collision checking
             if (this.applyGravity) {
                 //this prevents mending with cameraDirection, a global variable of the free camera class.
-                actualDirection = direction.add(this.getScene().gravity);
+                actualDisplacement = displacement.add(this.getScene().gravity);
             }
 
-            this.getScene().collisionCoordinator.getNewPosition(this._oldPosition, actualDirection, this._collider, 3, null, this._onCollisionPositionChange, this.uniqueId);
+            this.getScene().collisionCoordinator.getNewPosition(this._oldPosition, actualDisplacement, this._collider, 3, null, this._onCollisionPositionChange, this.uniqueId);
 
         }
 

+ 2 - 2
src/Cameras/babylon.targetCamera.ts

@@ -79,8 +79,8 @@ module BABYLON {
         /**
          * Restored camera state. You must call storeState() first
          */
-        public restoreState(): boolean {
-            if (!super.restoreState()) {
+        public _restoreStateValues(): boolean {
+            if (!super._restoreStateValues()) {
                 return false;
             }
 

+ 5 - 5
src/Collisions/babylon.collisionCoordinator.ts

@@ -4,7 +4,7 @@ module BABYLON {
     export var CollisionWorker = "";
 
     export interface ICollisionCoordinator {
-        getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
+        getNewPosition(position: Vector3, displacement: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void;
         init(scene: Scene): void;
         destroy(): void;
 
@@ -186,12 +186,12 @@ module BABYLON {
             }
         }
 
-        public getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void {
+        public getNewPosition(position: Vector3, displacement: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void {
             if (!this._init) return;
             if (this._collisionsCallbackArray[collisionIndex] || this._collisionsCallbackArray[collisionIndex + 100000]) return;
 
             position.divideToRef(collider.radius, this._scaledPosition);
-            velocity.divideToRef(collider.radius, this._scaledVelocity);
+            displacement.divideToRef(collider.radius, this._scaledVelocity);
 
             this._collisionsCallbackArray[collisionIndex] = onNewPosition;
 
@@ -347,9 +347,9 @@ module BABYLON {
 
         private _finalPosition = Vector3.Zero();
 
-        public getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void {
+        public getNewPosition(position: Vector3, displacement: Vector3, collider: Collider, maximumRetry: number, excludedMesh: AbstractMesh, onNewPosition: (collisionIndex: number, newPosition: Vector3, collidedMesh?: AbstractMesh) => void, collisionIndex: number): void {
             position.divideToRef(collider.radius, this._scaledPosition);
-            velocity.divideToRef(collider.radius, this._scaledVelocity);
+            displacement.divideToRef(collider.radius, this._scaledVelocity);
             collider.collidedMesh = null;
             collider.retry = 0;
             collider.initialVelocity = this._scaledVelocity;

+ 33 - 0
src/Events/babylon.keyboardEvents.ts

@@ -0,0 +1,33 @@
+module BABYLON {
+    
+    export class KeyboardEventTypes {
+        static _KEYDOWN = 0x01;
+        static _KEYUP = 0x02;
+
+        public static get KEYDOWN(): number {
+            return KeyboardEventTypes._KEYDOWN;
+        }
+
+        public static get KEYUP(): number {
+            return KeyboardEventTypes._KEYUP;
+        }
+    }
+
+    export class KeyboardInfo {
+        constructor(public type: number, public event: KeyboardEvent) {
+        }
+    }
+
+    /**
+     * This class is used to store keyboard related info for the onPreKeyboardObservable event.
+     * Set the skipOnKeyboardObservable property to true if you want the engine to stop any process after this event is triggered, even not calling onKeyboardObservable
+     */
+    export class KeyboardInfoPre extends KeyboardInfo {
+        constructor(type: number, event: KeyboardEvent) {
+            super(type, event);
+            this.skipOnPointerObservable = false;
+        }
+
+        public skipOnPointerObservable: boolean;
+    }   
+}

+ 69 - 0
src/Events/babylon.pointerEvents.ts

@@ -0,0 +1,69 @@
+module BABYLON {
+    export class PointerEventTypes {
+        static _POINTERDOWN = 0x01;
+        static _POINTERUP = 0x02;
+        static _POINTERMOVE = 0x04;
+        static _POINTERWHEEL = 0x08;
+        static _POINTERPICK = 0x10;
+        static _POINTERTAP = 0x20;
+        static _POINTERDOUBLETAP = 0x40;
+
+        public static get POINTERDOWN(): number {
+            return PointerEventTypes._POINTERDOWN;
+        }
+
+        public static get POINTERUP(): number {
+            return PointerEventTypes._POINTERUP;
+        }
+
+        public static get POINTERMOVE(): number {
+            return PointerEventTypes._POINTERMOVE;
+        }
+
+        public static get POINTERWHEEL(): number {
+            return PointerEventTypes._POINTERWHEEL;
+        }
+
+        public static get POINTERPICK(): number {
+            return PointerEventTypes._POINTERPICK;
+        }
+
+        public static get POINTERTAP(): number {
+            return PointerEventTypes._POINTERTAP;
+        }
+
+        public static get POINTERDOUBLETAP(): number {
+            return PointerEventTypes._POINTERDOUBLETAP;
+        }
+    }
+
+    export class PointerInfoBase {
+        constructor(public type: number, public event: PointerEvent | MouseWheelEvent) {
+        }
+    }
+
+    /**
+     * This class is used to store pointer related info for the onPrePointerObservable event.
+     * Set the skipOnPointerObservable property to true if you want the engine to stop any process after this event is triggered, even not calling onPointerObservable
+     */
+    export class PointerInfoPre extends PointerInfoBase {
+        constructor(type: number, event: PointerEvent | MouseWheelEvent, localX, localY) {
+            super(type, event);
+            this.skipOnPointerObservable = false;
+            this.localPosition = new Vector2(localX, localY);
+        }
+
+        public localPosition: Vector2;
+        public skipOnPointerObservable: boolean;
+    }
+
+    /**
+     * This type contains all the data related to a pointer event in Babylon.js.
+     * The event member is an instance of PointerEvent for all types except PointerWheel and is of type MouseWheelEvent when type equals PointerWheel. The different event types can be found in the PointerEventTypes class.
+     */
+    export class PointerInfo extends PointerInfoBase {
+        constructor(type: number, event: PointerEvent | MouseWheelEvent, public pickInfo: PickingInfo) {
+            super(type, event);
+        }
+    }    
+}

+ 11 - 1
src/Layer/babylon.highlightlayer.ts

@@ -486,11 +486,21 @@ module BABYLON {
                 }
             };
 
-            this._mainTexture.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>): void => {
+            this._mainTexture.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
                 this.onBeforeRenderMainTextureObservable.notifyObservers(this);
 
                 var index: number;
 
+                let engine = this._scene.getEngine();
+                
+                if (depthOnlySubMeshes.length) {
+                    engine.setColorWrite(false);            
+                    for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                        renderSubMesh(depthOnlySubMeshes.data[index]);
+                    }
+                    engine.setColorWrite(true);
+                }                
+
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }

+ 11 - 1
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -444,8 +444,18 @@
             }
         }
 
-        private _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>): void {
+        private _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void {
             var index: number;
+            let engine = this._scene.getEngine();
+
+            if (depthOnlySubMeshes.length) {
+                engine.setColorWrite(false);            
+                for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                    this._renderSubMeshForShadowMap(depthOnlySubMeshes.data[index]);
+                }
+                engine.setColorWrite(true);
+            }
+            
             for (index = 0; index < opaqueSubMeshes.length; index++) {
                 this._renderSubMeshForShadowMap(opaqueSubMeshes.data[index]);
             }

+ 1 - 0
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -20,6 +20,7 @@
         public OPACITYDIRECTUV = 0;
         public OPACITYRGB = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public ALPHABLEND = false;
         public ALPHAFROMALBEDO = false;
         public ALPHATESTVALUE = 0.5;

+ 2 - 0
src/Materials/Textures/babylon.mirrorTexture.ts

@@ -61,6 +61,8 @@ module BABYLON {
         constructor(name: string, size: any, scene: Scene, generateMipMaps?: boolean, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, samplingMode = Texture.BILINEAR_SAMPLINGMODE, generateDepthBuffer = true) {
             super(name, size, scene, generateMipMaps, true, type, false, samplingMode, generateDepthBuffer);
 
+            this.ignoreCameraViewport = true;
+
             this.onBeforeRenderObservable.add(() => {
                 Matrix.ReflectionToRef(this.mirrorPlane, this._mirrorMatrix);
                 this._savedViewMatrix = scene.getViewMatrix();

+ 16 - 0
src/Materials/Textures/babylon.multiRenderTarget.ts

@@ -29,6 +29,22 @@ module BABYLON {
             return this._textures[this._textures.length - 1];
         }
 
+        public set wrapU (wrap: number) {
+            if (this._textures) {
+                for (var i = 0; i < this._textures.length; i++) {
+                    this._textures[i].wrapU = wrap;
+                }
+            }
+        }
+
+        public set wrapV (wrap: number) {
+            if (this._textures) {
+                for (var i = 0; i < this._textures.length; i++) {
+                    this._textures[i].wrapV = wrap;
+                }
+            }
+        }
+
         constructor(name: string, size: any, count: number, scene: Scene, options?: any) {
             options = options || {};
 

+ 1 - 1
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -30,7 +30,7 @@
         public renderSprites = false;
         public coordinatesMode = Texture.PROJECTION_MODE;
         public activeCamera: Camera;
-        public customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, beforeTransparents?: () => void) => void;
+        public customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>, beforeTransparents?: () => void) => void;
         public useCameraPostProcesses: boolean;
         public ignoreCameraViewport: boolean = false;
 

+ 6 - 2
src/Materials/babylon.effect.ts

@@ -378,12 +378,15 @@
                 callback(preparedSourceCode.replace("#version 300 es", ""));
                 return;
             }
+
+            var hasDrawBuffersExtension = preparedSourceCode.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
             
             // Remove extensions 
             // #extension GL_OES_standard_derivatives : enable
             // #extension GL_EXT_shader_texture_lod : enable
             // #extension GL_EXT_frag_depth : enable
-            var regex = /#extension.+(GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth).+enable/g;
+            // #extension GL_EXT_draw_buffers : require
+            var regex = /#extension.+(GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth|GL_EXT_draw_buffers).+(enable|require)/g;
             var result = preparedSourceCode.replace(regex, "");
 
             // Migrate to GLSL v300
@@ -398,7 +401,8 @@
                 result = result.replace(/textureCube\(/g, "texture(");
                 result = result.replace(/gl_FragDepthEXT/g, "gl_FragDepth");
                 result = result.replace(/gl_FragColor/g, "glFragColor");
-                result = result.replace(/void\s+?main\(/g, "out vec4 glFragColor;\nvoid main(");
+                result = result.replace(/gl_FragData/g, "glFragData");
+                result = result.replace(/void\s+?main\(/g, (hasDrawBuffersExtension ? "" : "out vec4 glFragColor;\n") + "void main(");
             }
             
             callback(result);

+ 3 - 0
src/Materials/babylon.material.ts

@@ -285,6 +285,9 @@
         public alphaMode = Engine.ALPHA_COMBINE;
 
         @serialize()
+        public needDepthPrePass = false;
+
+        @serialize()
         public disableDepthWrite = false;
 
         @serialize("fogEnabled")

+ 5 - 0
src/Materials/babylon.materialHelper.ts

@@ -46,6 +46,11 @@
                 changed = true;
             }
 
+            if (defines["DEPTHPREPASS"] !== !engine.getColorWrite()) {
+                defines["DEPTHPREPASS"] = !defines["DEPTHPREPASS"];
+                changed = true;
+            }            
+
             if (defines["INSTANCES"] !== useInstances) {
                 defines["INSTANCES"] = useInstances;
                 changed = true;

+ 20 - 0
src/Materials/babylon.standardMaterial.ts

@@ -21,6 +21,7 @@ module BABYLON {
         public SPECULAROVERALPHA = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public ALPHAFROMDIFFUSE = false;
         public POINTSIZE = false;
         public FOG = false;
@@ -428,6 +429,25 @@ module BABYLON {
             this._imageProcessingConfiguration.colorGradingTexture = value;
         }
 
+        /**
+         * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT). 
+         * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
+         * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; 
+         * corresponding to low luminance, medium luminance, and high luminance areas respectively.
+         */
+        public get cameraColorCurves(): ColorCurves {
+            return this._imageProcessingConfiguration.colorCurves;
+        }
+        /**
+         * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT). 
+         * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
+         * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image; 
+         * corresponding to low luminance, medium luminance, and high luminance areas respectively.
+         */
+        public set cameraColorCurves(value: ColorCurves) {
+            this._imageProcessingConfiguration.colorCurves = value;
+        }        
+
         public customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines) => string;
 
         protected _renderTargets = new SmartArray<RenderTargetTexture>(16);

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

@@ -1533,7 +1533,7 @@
             }
         }
 
-        public moveWithCollisions(direction: Vector3): AbstractMesh {
+        public moveWithCollisions(displacement: Vector3): AbstractMesh {
             var globalPosition = this.getAbsolutePosition();
 
             globalPosition.subtractFromFloatsToRef(0, this.ellipsoid.y, 0, this._oldPositionForCollisions);
@@ -1545,7 +1545,7 @@
 
             this._collider.radius = this.ellipsoid;
 
-            this.getScene().collisionCoordinator.getNewPosition(this._oldPositionForCollisions, direction, this._collider, 3, this, this._onCollisionPositionChange, this.uniqueId);
+            this.getScene().collisionCoordinator.getNewPosition(this._oldPositionForCollisions, displacement, this._collider, 3, this, this._onCollisionPositionChange, this.uniqueId);
             return this;
         }
 

+ 3 - 1
src/PostProcess/RenderPipeline/Pipelines/babylon.defaultRenderingPipeline.ts

@@ -223,8 +223,10 @@
                 this.imageProcessing = new BABYLON.ImageProcessingPostProcess("imageProcessing",  1.0, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, engine, false, this._defaultPipelineTextureType);
                 if (this._hdr) {
                     this.addEffect(new PostProcessRenderEffect(engine, this.ImageProcessingPostProcessId, () => { return this.imageProcessing; }, true));
+                } else {
+                    this._scene.imageProcessingConfiguration.applyByPostProcess = false;
                 }
-            }
+            } 
 
 			if (this.fxaaEnabled) {
                 this.fxaa = new FxaaPostProcess("fxaa", 1.0, null, Texture.BILINEAR_SAMPLINGMODE, engine, false, this._defaultPipelineTextureType);

+ 1 - 1
src/PostProcess/RenderPipeline/Pipelines/babylon.ssao2RenderingPipeline.ts

@@ -120,7 +120,7 @@
         */
         public static get IsSupported(): boolean {
             var engine = Engine.LastCreatedEngine;
-            return engine.webGLVersion > 1;
+            return engine.getCaps().drawBuffersExtension;
         }
 
         private _scene: Scene;

+ 2 - 3
src/PostProcess/RenderPipeline/Pipelines/babylon.standardRenderingPipeline.ts

@@ -726,9 +726,8 @@
         }
 
         private _getDepthTexture(): Texture {
-            var geometry = this._scene.enableGeometryBufferRenderer();
-            if (geometry) {
-                return geometry.getGBuffer().textures[0];
+            if (this._scene.getEngine().getCaps().drawBuffersExtension) {
+                return this._scene.enableGeometryBufferRenderer().getGBuffer().textures[0];
             }
 
             return this._scene.enableDepthRenderer().getDepthMap();

+ 11 - 1
src/PostProcess/babylon.postProcess.ts

@@ -20,6 +20,7 @@
         public scaleMode = Engine.SCALEMODE_FLOOR;
         public alwaysForcePOT = false;
         public samples = 1;
+        public adaptScaleToCurrentViewport = false;
 
         private _camera: Camera;
         private _scene: Scene;
@@ -221,9 +222,18 @@
                 var requiredWidth = ((sourceTexture ? sourceTexture.width : this._engine.getRenderingCanvas().width) * <number>this._options) | 0;
                 var requiredHeight = ((sourceTexture ? sourceTexture.height : this._engine.getRenderingCanvas().height) * <number>this._options) | 0;
 
-                var desiredWidth = (<PostProcessOptions>this._options).width || requiredWidth;
+                var desiredWidth = ((<PostProcessOptions>this._options).width || requiredWidth);
                 var desiredHeight = (<PostProcessOptions>this._options).height || requiredHeight;
 
+                if (this.adaptScaleToCurrentViewport) {
+                    let currentViewport = engine.currentViewport;
+
+                    if (currentViewport) {
+                        desiredWidth *= currentViewport.width;
+                        desiredHeight *= currentViewport.height;
+                    }
+                }
+
                 if (this.renderTargetSamplingMode === Texture.TRILINEAR_SAMPLINGMODE || this.alwaysForcePOT) {
                     if (!(<PostProcessOptions>this._options).width) {
                         desiredWidth = engine.needPOTTextures ? Tools.GetExponentOfTwo(desiredWidth, maxSize, this.scaleMode) : desiredWidth;

+ 9 - 1
src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts

@@ -333,9 +333,17 @@
                 scene.clearColor = savedSceneClearColor;
             });
             
-            this._volumetricLightScatteringRTT.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>): void => {
+            this._volumetricLightScatteringRTT.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
                 var engine = scene.getEngine();
                 var index: number;
+                
+                if (depthOnlySubMeshes.length) {
+                    engine.setColorWrite(false);            
+                    for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                        renderSubMesh(depthOnlySubMeshes.data[index]);
+                    }
+                    engine.setColorWrite(true);
+                }                   
 
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);

+ 1 - 1
src/PostProcess/babylon.vrDistortionCorrectionPostProcess.ts

@@ -10,7 +10,6 @@
         private _scaleFactor: Vector2;
         private _lensCenter: Vector2;
 
-        //ANY
         constructor(name: string, camera: Camera, isRightEye: boolean, vrMetrics: VRCameraMetrics) {
             super(name, "vrDistortionCorrection", [
                 'LensCenter',
@@ -23,6 +22,7 @@
             this._distortionFactors = vrMetrics.distortionK;
             this._postProcessScaleFactor = vrMetrics.postProcessScaleFactor;
             this._lensCenterOffset = vrMetrics.lensCenterOffset;
+            this.adaptScaleToCurrentViewport = true;
 
             this.onSizeChangedObservable.add(() => {
                 this.aspectRatio = this.width * .5 / this.height;

+ 9 - 1
src/Rendering/babylon.depthRenderer.ts

@@ -73,9 +73,17 @@
                 }
             };
 
-            this._depthMap.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>): void => {
+            this._depthMap.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
                 var index;
 
+                if (depthOnlySubMeshes.length) {
+                    engine.setColorWrite(false);            
+                    for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                        renderSubMesh(depthOnlySubMeshes.data[index]);
+                    }
+                    engine.setColorWrite(true);
+                }     
+
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }

+ 12 - 2
src/Rendering/babylon.geometryBufferRenderer.ts

@@ -102,7 +102,9 @@ module BABYLON {
                 this._effect = this._scene.getEngine().createEffect("geometry",
                     attribs,
                     ["world", "mBones", "viewProjection", "diffuseMatrix", "view"],
-                    ["diffuseSampler"], join);
+                    ["diffuseSampler"], join,
+                    null, null, null,
+                    { buffersCount: this._enablePosition ? 3 : 2 });
             }
 
             return this._effect.isReady();
@@ -180,9 +182,17 @@ module BABYLON {
                 }
             };
 
-            this._multiRenderTarget.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>): void => {
+            this._multiRenderTarget.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
                 var index;
 
+                if (depthOnlySubMeshes.length) {
+                    engine.setColorWrite(false);            
+                    for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                        renderSubMesh(depthOnlySubMeshes.data[index]);
+                    }
+                    engine.setColorWrite(true);
+                }                  
+
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }

+ 25 - 11
src/Rendering/babylon.outlineRenderer.ts

@@ -24,6 +24,13 @@
             var material = subMesh.getMaterial();
 
             engine.enableEffect(this._effect);
+
+            // Logarithmic depth
+            if((<any> material).useLogarithmicDepth)
+            {
+                this._effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));
+            }
+
             this._effect.setFloat("offset", useOverlay ? 0 : mesh.outlineWidth);
             this._effect.setColor4("color", useOverlay ? mesh.overlayColor : mesh.outlineColor, useOverlay ? mesh.overlayAlpha : material.alpha);
             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
@@ -59,19 +66,26 @@
             var mesh = subMesh.getMesh();
             var material = subMesh.getMaterial();
 
-            // Alpha test
-            if (material && material.needAlphaTesting()) {
-                defines.push("#define ALPHATEST");
-                if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
-                    attribs.push(VertexBuffer.UVKind);
-                    defines.push("#define UV1");
+            if (material) {
+                // Alpha test
+                if(material.needAlphaTesting())
+                {
+                    defines.push("#define ALPHATEST");
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
+                        attribs.push(VertexBuffer.UVKind);
+                        defines.push("#define UV1");
+                    }
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
+                        attribs.push(VertexBuffer.UV2Kind);
+                        defines.push("#define UV2");
+                    }
                 }
-                if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
-                    attribs.push(VertexBuffer.UV2Kind);
-                    defines.push("#define UV2");
+                //Logarithmic depth
+                if((<any> material).useLogarithmicDepth)
+                {
+                    defines.push("#define LOGARITHMICDEPTH");
                 }
             }
-
             // Bones
             if (mesh.useBones && mesh.computeBonesUsingShaders) {
                 attribs.push(VertexBuffer.MatricesIndicesKind);
@@ -101,7 +115,7 @@
                 this._cachedDefines = join;
                 this._effect = this._scene.getEngine().createEffect("outline",
                     attribs,
-                    ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color"],
+                    ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"],
                     ["diffuseSampler"], join);
             }
 

+ 0 - 0
src/Rendering/babylon.renderingGroup.ts


Неке датотеке нису приказане због велике количине промена