Browse Source

Merge branch 'master' into utilityLayerFixes

Trevor Baron 7 năm trước cách đây
mục cha
commit
bdec2f7767
100 tập tin đã thay đổi với 19362 bổ sung18519 xóa
  1. 6 0
      .gitignore
  2. 1 1
      .vscode/tasks.json
  3. 1463 1470
      Playground/babylon.d.txt
  4. 79 0
      Playground/css/color_ts.css
  5. 421 419
      Playground/debug.html
  6. 5 1
      Playground/index-local.html
  7. 11 10
      Playground/index.html
  8. 11 3
      Playground/js/index.js
  9. 24 0
      Playground/ts.html
  10. 31 24
      Tools/DevLoader/BabylonLoader.js
  11. 93 151
      Tools/Gulp/config.json
  12. 94 33
      Tools/Gulp/gulpfile.js
  13. 2 1
      Tools/Gulp/package.json
  14. 44 19
      Tools/Gulp/processViewerDeclaration.js
  15. 6 3
      Tools/Publisher/index.js
  16. 139 0
      Tools/WebpackShaderLoader/index.js
  17. 6 4
      Viewer/package.json
  18. 3 1
      Viewer/src/configuration/types/default.ts
  19. 62 0
      Viewer/src/templating/plugins/printButton.ts
  20. 2 0
      Viewer/src/viewer/defaultViewer.ts
  21. 2 1
      Viewer/tests/unit/tsconfig.json
  22. 4 2
      Viewer/tests/unit/webpack.config.js
  23. 1 1
      Viewer/tsconfig-gulp.json
  24. 2 2
      Viewer/tsconfig.json
  25. 4 2
      Viewer/webpack.assets.config.js
  26. 4 3
      Viewer/webpack.config.js
  27. 9 10
      Viewer/webpack.gulp.config.js
  28. 8115 8114
      dist/preview release/babylon.d.ts
  29. 47 47
      dist/preview release/babylon.js
  30. 23 18
      dist/preview release/babylon.max.js
  31. 23 18
      dist/preview release/babylon.no-module.max.js
  32. 47 47
      dist/preview release/babylon.worker.js
  33. 23 18
      dist/preview release/es6.js
  34. 1 2
      dist/preview release/gui/package.json
  35. 3 0
      dist/preview release/inspector/package.json
  36. 1 0
      dist/preview release/loaders/babylon.objFileLoader.d.ts
  37. 37 1
      dist/preview release/loaders/babylon.objFileLoader.js
  38. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  39. 1 0
      dist/preview release/loaders/babylonjs.loaders.d.ts
  40. 37 1
      dist/preview release/loaders/babylonjs.loaders.js
  41. 4 4
      dist/preview release/loaders/babylonjs.loaders.min.js
  42. 1 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  43. 77 43
      dist/preview release/viewer/babylon.viewer.d.ts
  44. 58 58
      dist/preview release/viewer/babylon.viewer.js
  45. 290 195
      dist/preview release/viewer/babylon.viewer.max.js
  46. 77 43
      dist/preview release/viewer/babylon.viewer.module.d.ts
  47. 6 2
      dist/preview release/what's new.md
  48. 41 0
      gui/package.json
  49. 3 3
      gui/readme.md
  50. 587 589
      gui/src/2D/advancedDynamicTexture.ts
  51. 182 180
      gui/src/2D/controls/button.ts
  52. 118 118
      gui/src/2D/controls/checkbox.ts
  53. 354 356
      gui/src/2D/controls/colorpicker.ts
  54. 261 260
      gui/src/2D/controls/container.ts
  55. 1135 1159
      gui/src/2D/controls/control.ts
  56. 71 71
      gui/src/2D/controls/ellipse.ts
  57. 277 276
      gui/src/2D/controls/grid.ts
  58. 279 279
      gui/src/2D/controls/image.ts
  59. 19 0
      gui/src/2D/controls/index.ts
  60. 10 12
      gui/src/2D/controls/inputPassword.ts
  61. 426 424
      gui/src/2D/controls/inputText.ts
  62. 216 215
      gui/src/2D/controls/line.ts
  63. 187 186
      gui/src/2D/controls/multiLine.ts
  64. 136 136
      gui/src/2D/controls/radioButton.ts
  65. 117 118
      gui/src/2D/controls/rectangle.ts
  66. 359 358
      gui/src/2D/controls/slider.ts
  67. 127 127
      gui/src/2D/controls/stackPanel.ts
  68. 53 0
      gui/src/2D/controls/statics.ts
  69. 329 328
      gui/src/2D/controls/textBlock.ts
  70. 199 196
      gui/src/2D/controls/virtualKeyboard.ts
  71. 8 0
      gui/src/2D/index.ts
  72. 184 186
      gui/src/2D/math2D.ts
  73. 57 60
      gui/src/2D/measure.ts
  74. 106 106
      gui/src/2D/multiLinePoint.ts
  75. 79 79
      gui/src/2D/style.ts
  76. 135 137
      gui/src/2D/valueAndUnit.ts
  77. 17 18
      gui/src/3D/controls/abstractButton3D.ts
  78. 135 134
      gui/src/3D/controls/button3D.ts
  79. 121 122
      gui/src/3D/controls/container3D.ts
  80. 346 345
      gui/src/3D/controls/control3D.ts
  81. 48 48
      gui/src/3D/controls/cylinderPanel.ts
  82. 210 206
      gui/src/3D/controls/holographicButton.ts
  83. 12 0
      gui/src/3D/controls/index.ts
  84. 50 51
      gui/src/3D/controls/meshButton3D.ts
  85. 29 28
      gui/src/3D/controls/planePanel.ts
  86. 91 95
      gui/src/3D/controls/scatterPanel.ts
  87. 49 49
      gui/src/3D/controls/spherePanel.ts
  88. 87 88
      gui/src/3D/controls/stackPanel3D.ts
  89. 155 161
      gui/src/3D/controls/volumeBasedPanel.ts
  90. 180 181
      gui/src/3D/gui3DManager.ts
  91. 5 0
      gui/src/3D/index.ts
  92. 237 235
      gui/src/3D/materials/fluentMaterial.ts
  93. 1 0
      gui/src/3D/materials/index.ts
  94. 12 0
      gui/src/3D/materials/shaders/fluent.ts
  95. 12 14
      gui/src/3D/vector3WithInfo.ts
  96. 2 0
      gui/src/index.ts
  97. 0 12
      gui/src/tsconfig.json
  98. 31 0
      gui/tsconfig.json
  99. 76 0
      gui/webpack.config.js
  100. 0 0
      inspector/package.json

+ 6 - 0
.gitignore

@@ -13,6 +13,7 @@ TestResults
 *.user
 *.sln.docstates
 *.map
+!dist/**/*.map
 
 # javascript files
 src/**/*.js
@@ -161,8 +162,12 @@ node_modules
 *.js.fx
 *.d.ts
 !dist/**/*.d.ts
+!dist/**/*.js.map
 !lib.d.ts
 
+# Split declaration file
+!ISplit.d.ts
+
 # local dev
 localDev/src/*
 /dist/preview release/babylon.custom.js
@@ -183,3 +188,4 @@ Viewer/tests/unit/src/**/*.js
 Viewer/tests/Lib/**/*.js
 Viewer/tests/commons/**/*.js
 .sass-cache/
+gui/dist/

+ 1 - 1
.vscode/tasks.json

@@ -66,7 +66,7 @@
                     "background": {
                         "activeOnStart": true,
                         "beginsPattern": "Project is running at",
-                        "endsPattern": "webpack: Compiled successfully."
+                        "endsPattern": "Compiled successfully."
                     }
                 }
             ],

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1463 - 1470
Playground/babylon.d.txt


+ 79 - 0
Playground/css/color_ts.css

@@ -0,0 +1,79 @@
+@import url("https://fonts.googleapis.com/css?family=Montserrat:300,400");
+@import url("https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css");
+#waitTitle {
+    color: rgb(208, 23, 211);
+}
+#exampleList #exampleBanner h1 {
+    color: #ae00ef;
+}
+#exampleList .horizontalSeparator {
+    border-top: 1px solid #ae00ef;
+}
+#exampleList .categoryContainer .itemLine .itemContent .itemLineDocLink {
+    color: #ae00ef;
+}
+#exampleList .categoryContainer .itemLine .itemContent .itemLinePGLink {
+    color: #ae00ef;
+}
+
+#fpsLabel {
+    background-color: #9147c9;
+}
+.navbar .title {
+    color: #bb47c9;
+}
+.navbar .version {
+    color: #9147c9;
+}
+
+.button {
+    background-color: #9147c9;
+}
+.button:hover {
+    background-color: #bb47c9;
+}
+.navbar .button.run {
+    background-color: #bb47c9;
+}
+.navbar .select .toDisplay {
+    border: 1px solid #9147c9;
+}
+.navbar .select .subSelect .toDisplaySub {
+    border: 1px solid #9147c9;
+}
+
+.navbar .select .toDisplay .option {
+    font-size: 0.9em;
+    height: 35px;
+    line-height: 35px;
+    padding: 0px 5px 0px 5px;
+    text-align: center;
+    border-bottom : 1px solid rgba(0,0,0,0.1);
+}
+
+.navbar .select .toDisplay .option.light:hover {
+    cursor: pointer;
+    background-color: #d9d9d9;
+}
+
+
+.navbar .select .toDisplay .option.dark {
+    background-color: #333;
+    color: white;
+}
+.navbar .select .toDisplay .option.light {
+    background-color: white;
+    color: #9147c9;
+}
+.navbar .select .toDisplayBig {
+    border: 1px solid #9147c9;
+}
+
+.navbar .select .toDisplayBig.light {    
+    color: #bb47c9;
+}
+.navbar .select .toDisplayBig a.light {
+    color: #9147c9;
+}
+
+

+ 421 - 419
Playground/debug.html

@@ -1,510 +1,512 @@
 <!DOCTYPE html>
 <html>
 
-<head>
-    <title>Babylon.js Playground</title>
-    <meta charset='utf-8' />
-    <meta name="viewport" content="width=device-width, user-scalable=no">
-    <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>
-    <!--For canvas/code separator-->
-    <script src="js/libs/split.js"></script>
-
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
-    <!-- jszip -->
-    <script src="js/libs/jszip.min.js"></script>
-    <script src="js/libs/fileSaver.js"></script>
-    <!-- Monaco -->
-    <script src="node_modules/monaco-editor/min/vs/loader.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.max.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.js"></script>
-
-    <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.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/CompoundShader/src/babylonx.CompoundShader.js"></script>
-    <link href="css/index.css" rel="stylesheet" />
-
-</head>
-
-<body>
-    <div class="navbar navBar1600">
-        <div class="title">
-            Babylon.js Playground
-        </div>
-        <div class="version" id="mainTitle">
-            v3.0-alpha
-        </div>
-
-        <div class="category">
-            <div class="button run" id="runButton1600">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
+    <head>
+        <title>Babylon.js Playground</title>
+        <meta charset='utf-8' />
+        <meta name="viewport" content="width=device-width, user-scalable=no">
+        <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>
+        <!--For canvas/code separator-->
+        <script src="js/libs/split.js"></script>
+
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
+        <!-- jszip -->
+        <script src="js/libs/jszip.min.js"></script>
+        <script src="js/libs/fileSaver.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.max.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.js"></script>
+
+        <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.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/CompoundShader/src/babylonx.CompoundShader.js"></script>
+        <link href="css/index.css" rel="stylesheet" />
+
+        <!-- Monaco -->
+        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+
+    </head>
+
+    <body>
+        <div class="navbar navBar1600">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+                v3.0-alpha
+            </div>
+
+            <div class="category">
+                <div class="button run" id="runButton1600">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1600">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1600">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="newButton1600">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1600">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1600">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="zipButton1600">Zip
-                <i class="fa fa-download" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="saveButton1600">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1600">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1600">Dark</div>
-                            <div class="option" id="lightTheme1600">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1600">Dark</div>
+                                <div class="option" id="lightTheme1600">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1600">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1600">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle1600">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1600">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1600">Format code</div>
+                        <div class="option" id="minimapToggle1600">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                    </div>
-                    <div class="option" id="safemodeToggle1600">Safe mode
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option checked" id="editorButton1600">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1600">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1600">Format code</div>
-                    <div class="option" id="minimapToggle1600">Minimap
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
                     </div>
                 </div>
-            </div>
 
-            <div class="button uncheck" id="debugButton1600">Inspector
-                <i class="fa fa-square-o" aria-hidden="true"></i>
+                <div class="button uncheck" id="debugButton1600">Inspector
+                    <i class="fa fa-square-o" aria-hidden="true"></i>
+                </div>
+                <div class="button" id="metadataButton1600">Metadata</div>
             </div>
-            <div class="button" id="metadataButton1600">Metadata</div>
-        </div>
 
 
 
-        <div class="category right">
-            <div class="button select">
-                <span id="currentVersion1600">Version: Latest</span>
-                <div class="toDisplay">
-                    <div class="option" onclick="setVersion('latest');">Latest</div>
-                    <div class="option" onclick="setVersion('2.5');">2.5</div>
+            <div class="category right">
+                <div class="button select">
+                    <span id="currentVersion1600">Version: Latest</span>
+                    <div class="toDisplay">
+                        <div class="option" onclick="setVersion('latest');">Latest</div>
+                        <div class="option" onclick="setVersion('2.5');">2.5</div>
+                    </div>
+                </div>
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
                 </div>
-            </div>
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
             </div>
         </div>
-    </div>
 
-    <div class="navbar navBar1475">
-        <div class="title">
-            Babylon.js Playground
-        </div>
-        <div class="version" id="mainTitle">
-            v3.0-alpha
-        </div>
+        <div class="navbar navBar1475">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+                v3.0-alpha
+            </div>
 
-        <div class="category">
-            <div class="button run" id="runButton1475">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button run" id="runButton1475">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1475">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1475">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="newButton1475">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1475">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1475">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="zipButton1475">Zip
-                <i class="fa fa-download" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="saveButton1475">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1475">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1475">Dark</div>
-                            <div class="option" id="lightTheme1475">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1475">Dark</div>
+                                <div class="option" id="lightTheme1475">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1475">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1475">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option" id='safemodeToggle1475'>Safe mode
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option checked" id="editorButton1475">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1475">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1475">Format code</div>
-                    <div class="option" id="minimapToggle1475">Minimap
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="debugButton1475">Inspector
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="metadataButton1475">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion1475">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('2.5');">2.5</div>
+                        <div class="option" id='safemodeToggle1475'>Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1475">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1475">Format code</div>
+                        <div class="option" id="minimapToggle1475">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton1475">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1475">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1475">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('2.5');">2.5</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
             </div>
         </div>
-    </div>
 
-    <div class="navbar navBar1030">
-        <div class="category">
-            <div class="button run" id="runButton1030">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
+        <div class="navbar navBar1030">
+            <div class="category">
+                <div class="button run" id="runButton1030">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1030">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1030">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="newButton1030">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1030">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1030">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="zipButton1030">Zip
-                <i class="fa fa-download" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="saveButton1030">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1030">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1030">Dark</div>
-                            <div class="option" id="lightTheme1030">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1030">Dark</div>
+                                <div class="option" id="lightTheme1030">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1030">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1030">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option" id="safemodeToggle1030">Safe mode
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option checked" id="editorButton1030">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1030">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1030">Format code</div>
-                    <div class="option" id="minimapToggle1030">Minimap
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="debugButton1030">Inspector
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="metadataButton1030">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion1030">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('2.5');">2.5</div>
+                        <div class="option" id="safemodeToggle1030">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1030">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1030">Format code</div>
+                        <div class="option" id="minimapToggle1030">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton1030">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1030">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1030">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('2.5');">2.5</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
             </div>
         </div>
-    </div>
-
-    <div class="navbar navBar750">
-        <div class="category">
-            <div class="button select">File
-                <div class="toDisplay">
-                    <div class="option" id="runButton750">Run
-                        <i class="fa fa-play" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="newButton750">New
-                        <i class="fa fa-file" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="clearButton750">Clear
-                        <i class="fa fa-trash" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="saveButton750">Save
-                        <i class="fa fa-floppy-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="zipButton750">Zip
-                        <i class="fa fa-download" aria-hidden="true"></i>
+
+        <div class="navbar navBar750">
+            <div class="category">
+                <div class="button select">File
+                    <div class="toDisplay">
+                        <div class="option" id="runButton750">Run
+                            <i class="fa fa-play" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="newButton750">New
+                            <i class="fa fa-file" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="clearButton750">Clear
+                            <i class="fa fa-trash" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="saveButton750">Save
+                            <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="zipButton750">Zip
+                            <i class="fa fa-download" aria-hidden="true"></i>
+                        </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme750">Dark</div>
-                            <div class="option" id="lightTheme750">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme750">Dark</div>
+                                <div class="option" id="lightTheme750">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize750">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize750">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option" id="safemodeToggle750">Safe mode
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div style="display:none;" class="option checked" id="editorButton750">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton750">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
-                    <div class="option" id="formatButton750">Format code</div>
-                    <div class="option" id="minimapToggle750">Minimap
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="debugButton750">Inspector
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="metadataButton750">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion750">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('2.5');">2.5</div>
+                        <div class="option" id="safemodeToggle750">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div style="display:none;" class="option checked" id="editorButton750">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton750">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
+                        <div class="option" id="formatButton750">Format code</div>
+                        <div class="option" id="minimapToggle750">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton750">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton750">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion750">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('2.5');">2.5</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
             </div>
         </div>
-    </div>
 
-    <div class="wrapper">
-        <div id="jsEditor"></div>
-        <div id="canvasZone">
-            <canvas touch-action="none" id="renderCanvas"></canvas>
+        <div class="wrapper">
+            <div id="jsEditor"></div>
+            <div id="canvasZone">
+                <canvas touch-action="none" id="renderCanvas"></canvas>
+            </div>
         </div>
-    </div>
-    <div id="exampleList">
-        <div id="exampleBanner">
-            <h1>Examples</h1>
+        <div id="exampleList">
+            <div id="exampleBanner">
+                <h1>Examples</h1>
+            </div>
+            <div class="horizontalSeparator"></div>
+            <input id="filterBar" type="text" placeholder="Filter examples...">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
         </div>
-        <div class="horizontalSeparator"></div>
-        <input id="filterBar" type="text" placeholder="Filter examples...">
-        <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
-    </div>
 
-    <span class="label" id="fpsLabel">FPS</span>
+        <span class="label" id="fpsLabel">FPS</span>
 
-    <div id="errorZone">
-    </div>
+        <div id="errorZone">
+        </div>
 
-    <div class="navbarBottom">
-        <div id="statusBar"></div>
-        <div class="links">
-            <div class='link'>
-                <a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a>
-            </div>
-            <div class='link'>
-                <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a>
-            </div>
-            <div class='link'>
-                <a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a>
-            </div>
-            <div class='link'>
-                <a target='_new' href="https://doc.babylonjs.com">Documentation</a>
-            </div>
-            <div class='link'>
-                <a target='_new' href="https://doc.babylonjs.com/playground">Search</a>
+        <div class="navbarBottom">
+            <div id="statusBar"></div>
+            <div class="links">
+                <div class='link'>
+                    <a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com">Documentation</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com/playground">Search</a>
+                </div>
             </div>
         </div>
-    </div>
 
-    <div id="saveLayer" class="save-layer">
-        <div class="save-form">
-            <label for="saveFormTitle">TITLE</label>
-            <div class="separator"></div>
-            <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+        <div id="saveLayer" class="save-layer">
+            <div class="save-form">
+                <label for="saveFormTitle">TITLE</label>
+                <div class="separator"></div>
+                <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
 
-            <label for="saveFormDescription">DESCRIPTION</label>
-            <div class="separator"></div>
-            <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+                <label for="saveFormDescription">DESCRIPTION</label>
+                <div class="separator"></div>
+                <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
 
-            <label for="saveFormTags">TAGS (separated by comma)</label>
-            <div class="separator"></div>
-            <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+                <label for="saveFormTags">TAGS (separated by comma)</label>
+                <div class="separator"></div>
+                <textarea id="saveFormTags" rows="4" cols="10"></textarea>
 
-            <div class="save-form-buttons" id="saveFormButtons">
+                <div class="save-form-buttons" id="saveFormButtons">
 
-                <div id="saveFormButtonOk" class="button">OK</div>
-                <div id="saveFormButtonCancel" class="button">Cancel</div>
+                    <div id="saveFormButtonOk" class="button">OK</div>
+                    <div id="saveFormButtonCancel" class="button">Cancel</div>
+                </div>
             </div>
         </div>
-    </div>
 
-    <script src="https://code.jquery.com/jquery.js"></script>
+        <script src="https://code.jquery.com/jquery.js"></script>
 
-    <script src="js/actions.js"></script>
-    <script src="js/pbt.js"></script>
-    <script src="js/index.js"></script>
+        <script src="js/actions.js"></script>
+        <script src="js/pbt.js"></script>
+        <script src="js/index.js"></script>
 
-    <!-- Global site tag (gtag.js) - Google Analytics -->
-    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
-    <script>
-    window.dataLayer = window.dataLayer || [];
-    function gtag(){dataLayer.push(arguments);}
-    gtag('js', new Date());
+        <!-- Global site tag (gtag.js) - Google Analytics -->
+        <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
+        <script>
+            window.dataLayer = window.dataLayer || [];
+            function gtag() { dataLayer.push(arguments); }
+            gtag('js', new Date());
 
-    gtag('config', 'UA-41767310-2');
-    </script>    
-</body>
+            gtag('config', 'UA-41767310-2');
+        </script>
+    </body>
 
 </html>

+ 5 - 1
Playground/index-local.html

@@ -18,7 +18,7 @@
         <script src="../dist/preview%20release/Oimo.js"></script>
         <script src="../dist/preview%20release/earcut.min.js"></script>
         <!-- Monaco -->
-        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+
         <!-- Babylon.js -->
         <script src="../tools/DevLoader/BabylonLoader.js"></script>
 
@@ -454,6 +454,10 @@
                         wasmBinaryUrl: "../dist/preview%20release/draco_decoder_gltf.wasm",
                         fallbackUrl: "../dist/preview%20release/draco_decoder_gltf.js"
                     };
+                    var script = document.createElement('script');
+                    script.type = 'text/javascript';
+                    script.src = "node_modules/monaco-editor/min/vs/loader.js";
+                    document.head.appendChild(script);
                 });
         </script>
     </body>

+ 11 - 10
Playground/index.html

@@ -37,8 +37,6 @@
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
         <script src="https://preview.babylonjs.com/earcut.min.js"></script>
-        <!-- Monaco -->
-        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
         <!-- Babylon.js -->
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
@@ -48,13 +46,16 @@
         <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
         <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
         <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+        <!-- Monaco -->
+        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+
 
         <!-- Extensions -->
         <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js" async></script>
         <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js" async></script>
         <script src="https://www.babylontoolkit.com/playground/scripts/babylon.navmesh.js"></script>
         <script src="https://www.babylontoolkit.com/playground/scripts/babylon.manager.js"></script>
-                               
+
         <link href="css/index.css" rel="stylesheet" />
     </head>
 
@@ -408,7 +409,7 @@
                 <canvas touch-action="none" id="renderCanvas"></canvas>
             </div>
         </div>
-        <div id="exampleList">
+        <div id="exampleList" class = "javascript">
             <div id="exampleBanner">
                 <h1>Examples</h1>
             </div>
@@ -479,16 +480,16 @@
         <script src="js/actions.js"></script>
         <script src="js/pbt.js"></script>
         <script src="js/index.js"></script>
-        
+
         <!-- Global site tag (gtag.js) - Google Analytics -->
         <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
         <script>
-        window.dataLayer = window.dataLayer || [];
-        function gtag(){dataLayer.push(arguments);}
-        gtag('js', new Date());
+            window.dataLayer = window.dataLayer || [];
+            function gtag() { dataLayer.push(arguments); }
+            gtag('js', new Date());
 
-        gtag('config', 'UA-41767310-2');
-        </script>        
+            gtag('config', 'UA-41767310-2');
+        </script>
     </body>
 
 </html>

+ 11 - 3
Playground/js/index.js

@@ -241,9 +241,17 @@ function showError(errorMessage, errorEvent) {
         };
 
         var loadScriptsList = function () {
-            var xhr = new XMLHttpRequest();
 
-            xhr.open('GET', 'https://raw.githubusercontent.com/BabylonJS/Documentation/master/examples/list.json', true);
+            var exampleList = document.getElementById("exampleList");
+           
+            var xhr = new XMLHttpRequest();
+            //Open Typescript or Javascript examples
+            if(exampleList.className != 'typescript') {
+                xhr.open('GET', 'https://raw.githubusercontent.com/BabylonJS/Documentation/master/examples/list.json', true);
+            }
+            else {
+                xhr.open('GET', 'https://raw.githubusercontent.com/BabylonJS/Documentation/master/examples/list_ts.json', true);
+            }
 
             xhr.onreadystatechange = function () {
                 if (xhr.readyState === 4) {
@@ -257,7 +265,7 @@ function showError(errorMessage, errorEvent) {
                         }
                         scripts.sort(sortScriptsList);
 
-                        var exampleList = document.getElementById("exampleList");
+                                                
 
                         if (exampleList) {
                             for (var i = 0; i < scripts.length; i++) {

+ 24 - 0
Playground/ts.html

@@ -56,6 +56,7 @@
         <script src="https://www.babylontoolkit.com/playground/scripts/babylon.manager.js"></script>
                                
         <link href="css/index.css" rel="stylesheet" />
+        <link href="css/color_ts.css" rel="stylesheet" />
     </head>
 
     <body>
@@ -144,6 +145,9 @@
                         <div class="option" onclick="setVersion('stable');">Stable</div>
                     </div>
                 </div>
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
             </div>
         </div>
 
@@ -228,6 +232,12 @@
                     </div>
                 </div>
             </div>
+
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
+            </div>
         </div>
 
         <div class="navbar navBar1030">
@@ -305,6 +315,12 @@
                     </div>
                 </div>
             </div>
+
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
+            </div>
         </div>
 
         <div class="navbar navBar750">
@@ -387,6 +403,14 @@
                 <canvas touch-action="none" id="renderCanvas"></canvas>
             </div>
         </div>
+        <div id="exampleList" class = "typescript">
+            <div id="exampleBanner">
+                <h1>Examples</h1>
+            </div>
+            <div class="horizontalSeparator"></div>
+            <input id="filterBar" type="text" placeholder="Filter examples...">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+        </div>
 
         <span class="label" id="fpsLabel">FPS</span>
 

+ 31 - 24
Tools/DevLoader/BabylonLoader.js

@@ -141,36 +141,44 @@ var BABYLONDEVTOOLS;
         }
 
         Loader.prototype.loadLibrary = function (library, module) {
+            if (library.preventLoadLibrary) {
+                return;
+            }
+
             if (!useDist) {
-                var i = 0;
-                for (; i < library.files.length; i++) {
-                    var file = library.files[i];
-                    if (file.indexOf('lib.d.ts') > 0) {
-                        continue;
-                    }
+                if (library.useOutputForDebugging) {
+                    this.loadScript(babylonJSPath + '/.temp' + module.build.distOutputDirectory + library.output);
+                } else {
+                    var i = 0;
+                    for (; i < library.files.length; i++) {
+                        var file = library.files[i];
+                        if (file.indexOf('lib.d.ts') > 0) {
+                            continue;
+                        }
 
-                    file = file.replace('.ts', '.js');
-                    file = file.replace('../', '');
-                    file = babylonJSPath + '/' + file;
-                    this.loadScript(file);
-                }
+                        file = file.replace('.ts', '.js');
+                        file = file.replace('../', '');
+                        file = babylonJSPath + '/' + file;
+                        this.loadScript(file);
+                    }
 
-                if (library.shaderFiles && library.shaderFiles.length > 0) {
-                    var shaderFile = library.shaderFiles[0];
-                    var endDirectoryIndex = shaderFile.lastIndexOf('/');
-                    shaderFile = shaderFile.substring(0, endDirectoryIndex + 1);
-                    shaderFile += library.output.replace('.js', '.js.fx');
-                    this.loadScript(shaderFile);
-                    if (library.shadersIncludeFiles) {
-                        var includeShaderFile = shaderFile.replace('.js.fx', '.js.include.fx');
-                        this.loadScript(includeShaderFile);
+                    if (library.shaderFiles && library.shaderFiles.length > 0) {
+                        var shaderFile = library.shaderFiles[0];
+                        var endDirectoryIndex = shaderFile.lastIndexOf('/');
+                        shaderFile = shaderFile.substring(0, endDirectoryIndex + 1);
+                        shaderFile += library.output.replace('.js', '.js.fx');
+                        this.loadScript(shaderFile);
+                        if (library.shadersIncludeFiles) {
+                            var includeShaderFile = shaderFile.replace('.js.fx', '.js.include.fx');
+                            this.loadScript(includeShaderFile);
+                        }
                     }
                 }
             }
             else if (min) {
                 if (library.webpack) {
                     if (module.build.distOutputDirectory)
-                        this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output.replace('.js', '.bundle.js'));
+                        this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output);
                 }
                 else {
                     this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output.replace('.js', '.min.js'));
@@ -181,6 +189,7 @@ var BABYLONDEVTOOLS;
                     this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output);
             }
 
+            // Currently not being used
             if (!min && library.sassFiles && library.sassFiles.length > 0) {
                 var cssFile = library.output.replace('.js', '.css');
                 cssFile = babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + cssFile;
@@ -242,10 +251,8 @@ var BABYLONDEVTOOLS;
 
             // Modules
             if (loadModules) {
+
                 for (var i = 0; i < settings.modules.length; i++) {
-                    if (settings.modules[i] === "viewer") {
-                        continue;
-                    }
                     this.loadModule(settings[settings.modules[i]]);
                 }
             }

+ 93 - 151
Tools/Gulp/config.json

@@ -8,6 +8,7 @@
         "declarationModuleFilename": "babylon.module.d.ts",
         "outputDirectory": "../../dist/preview release",
         "playgroundDirectory": "../../Playground/",
+        "tempDirectory": "../../.temp/",
         "intellisenseFile": "babylon.d.txt",
         "intellisenseSources": [
             "../../dist/preview release/babylon.d.ts",
@@ -136,7 +137,7 @@
             "picking",
             "backgroundMaterial",
             "videoDome"
-        ]      
+        ]
     },
     "workloads": {
         "core": {
@@ -227,7 +228,7 @@
                 "fresnelFunction",
                 "reflectionFunction",
                 "imageProcessingDeclaration",
-                "imageProcessingFunctions",                
+                "imageProcessingFunctions",
                 "bumpFragmentFunctions",
                 "clipPlaneFragmentDeclaration",
                 "fogFragmentDeclaration",
@@ -246,7 +247,7 @@
                 "core",
                 "debug"
             ]
-        },          
+        },
         "occlusionQuery": {
             "files": [
                 "../../src/Engine/Extensions/babylon.engine.occlusionQuery.js"
@@ -255,7 +256,7 @@
                 "core",
                 "debug"
             ]
-        },          
+        },
         "behaviors": {
             "files": [
                 "../../src/Behaviors/babylon.behavior.js"
@@ -263,7 +264,7 @@
             "dependUpon": [
                 "core"
             ]
-        },   
+        },
         "imageProcessing": {
             "files": [
                 "../../src/Materials/babylon.imageProcessingConfiguration.js",
@@ -273,8 +274,8 @@
             "dependUpon": [
                 "core"
             ]
-        },  
-        "noise" : {
+        },
+        "noise": {
             "files": [
                 "../../src/Materials/Textures/Procedurals/babylon.noiseProceduralTexture.js"
             ],
@@ -285,7 +286,7 @@
             "shaders": [
                 "noise.fragment"
             ]
-        },      
+        },
         "particles": {
             "files": [
                 "../../src/Particles/babylon.particle.js",
@@ -1083,7 +1084,7 @@
             ]
         },
         "textureFormats": {
-            "files": [ ],
+            "files": [],
             "dependUpon": [
                 "dds",
                 "tga",
@@ -1208,7 +1209,7 @@
             "shaders": [
                 "anaglyph.fragment"
             ]
-        },       
+        },
         "stereoscopic": {
             "files": [
                 "../../src/PostProcess/babylon.stereoscopicInterlacePostProcess.js",
@@ -1226,7 +1227,7 @@
             "shaders": [
                 "stereoscopicInterlace.fragment"
             ]
-        },           
+        },
         "vr": {
             "files": [
                 "../../src/PostProcess/babylon.vrDistortionCorrectionPostProcess.js",
@@ -1409,8 +1410,8 @@
         "proceduralTexturesLibrary",
         "loaders",
         "serializers",
-        "inspector",
         "gui",
+        "inspector",
         "viewer",
         "viewer-assets"
     ],
@@ -1844,146 +1845,72 @@
     "gui": {
         "libraries": [
             {
-                "files": [
-                    "../../gui/src/2D/style.ts",
-                    "../../gui/src/2D/valueAndUnit.ts",
-                    "../../gui/src/2D/advancedDynamicTexture.ts",
-                    "../../gui/src/2D/measure.ts",
-                    "../../gui/src/2D/math2D.ts",
-                    "../../gui/src/2D/multiLinePoint.ts",
-                    "../../gui/src/2D/controls/control.ts",
-                    "../../gui/src/2D/controls/container.ts",
-                    "../../gui/src/2D/controls/stackPanel.ts",
-                    "../../gui/src/2D/controls/rectangle.ts",
-                    "../../gui/src/2D/controls/ellipse.ts",
-                    "../../gui/src/2D/controls/line.ts",
-                    "../../gui/src/2D/controls/slider.ts",
-                    "../../gui/src/2D/controls/checkbox.ts",
-                    "../../gui/src/2D/controls/radioButton.ts",
-                    "../../gui/src/2D/controls/textBlock.ts",
-                    "../../gui/src/2D/controls/image.ts",
-                    "../../gui/src/2D/controls/button.ts",
-                    "../../gui/src/2D/controls/colorpicker.ts",
-                    "../../gui/src/2D/controls/inputText.ts",
-                    "../../gui/src/2D/controls/inputPassword.ts",
-                    "../../gui/src/2D/controls/virtualKeyboard.ts",
-                    "../../gui/src/2D/controls/multiLine.ts",
-                    "../../gui/src/2D/controls/grid.ts",                    
-                    "../../gui/src/3D/gui3DManager.ts",
-                    "../../gui/src/3D/materials/fluentMaterial.ts",
-                    "../../gui/src/3D/vector3WithInfo.ts",
-                    "../../gui/src/3D/controls/control3D.ts",
-                    "../../gui/src/3D/controls/container3D.ts",
-                    "../../gui/src/3D/controls/abstractButton3D.ts",
-                    "../../gui/src/3D/controls/button3D.ts",
-                    "../../gui/src/3D/controls/meshButton3D.ts",
-                    "../../gui/src/3D/controls/holographicButton.ts",
-                    "../../gui/src/3D/controls/stackPanel3D.ts",
-                    "../../gui/src/3D/controls/volumeBasedPanel.ts",
-                    "../../gui/src/3D/controls/spherePanel.ts",
-                    "../../gui/src/3D/controls/planePanel.ts",
-                    "../../gui/src/3D/controls/scatterPanel.ts",
-                    "../../gui/src/3D/controls/cylinderPanel.ts"
-                ],
-                "shaderFiles": [
-                    "../../gui/src/3D/materials/shaders/fluent.vertex.fx",
-                    "../../gui/src/3D/materials/shaders/fluent.fragment.fx"
-                ],
-                "output": "babylon.gui.js",
-                "buildAsModule": true,
-                "moduleName": "babylonjs-gui",
-                "moduleDeclaration": {
-                    "name": "GUI",
-                    "module": "babylonjs-gui"
-                }
+                "files": [],
+                "noBundleInName": true,
+                "output": "babylon.gui.min.js",
+                "webpack": "../../gui/webpack.config.js",
+                "bundle": "true",
+                "babylonIncluded": false,
+                "useOutputForDebugging": true
             }
         ],
         "build": {
-            "srcOutputDirectory": "../../gui/",
-            "distOutputDirectory": "/gui/"
+            "srcOutputDirectory": "../../gui/src/",
+            "distOutputDirectory": "/gui/",
+            "dtsBundle": {
+                "name": "babylonjs-gui",
+                "main": "../../dist/preview release/gui/build/index.d.ts",
+                "out": "../babylon.gui.module.d.ts",
+                "baseDir": "../../dist/preview release/gui/build/",
+                "headerText": "BabylonJS GUI"
+            },
+            "processDeclaration": {
+                "filename": "babylon.gui.module.d.ts",
+                "packageName": "babylonjs-gui",
+                "moduleName": "BABYLON.GUI",
+                "importsToRemove": [],
+                "classMap": {
+                    "babylonjs": "BABYLON",
+                    "babylonjs-loaders": "BABYLON",
+                    "babylonjs-serializers": "BABYLON"
+                }
+            }
         }
     },
     "inspector": {
         "libraries": [
             {
-                "files": [
-                    "../../inspector/src/Inspector.ts",
-                    "../../inspector/src/properties.ts",
-                    "../../inspector/src/properties_gui.ts",
-                    "../../inspector/src/gui/BasicElement.ts",
-                    "../../inspector/src/adapters/Adapter.ts",
-                    "../../inspector/src/adapters/CameraAdapter.ts",
-                    "../../inspector/src/adapters/PhysicsImpostorAdapter.ts",
-                    "../../inspector/src/adapters/GUIAdapter.ts",
-                    "../../inspector/src/adapters/SoundAdapter.ts",
-                    "../../inspector/src/adapters/TextureAdapter.ts",
-                    "../../inspector/src/adapters/LightAdapter.ts",
-                    "../../inspector/src/adapters/MaterialAdapter.ts",
-                    "../../inspector/src/adapters/MeshAdapter.ts",
-                    "../../inspector/src/adapters/PhysicsImpostorAdapter.ts",
-                    "../../inspector/src/details/DetailPanel.ts",
-                    "../../inspector/src/details/Property.ts",
-                    "../../inspector/src/details/PropertyLine.ts",
-                    "../../inspector/src/gui/ColorElement.ts",
-                    "../../inspector/src/gui/ColorPickerElement.ts",
-                    "../../inspector/src/gui/CubeTextureElement.ts",
-                    "../../inspector/src/gui/HDRCubeTextureElement.ts",
-                    "../../inspector/src/gui/SearchBar.ts",
-                    "../../inspector/src/gui/TextureElement.ts",
-                    "../../inspector/src/gui/Tooltip.ts",
-                    "../../inspector/src/helpers/Helpers.ts",
-                    "../../inspector/src/scheduler/Scheduler.ts",
-                    "../../inspector/src/tabs/Tab.ts",
-                    "../../inspector/src/tabs/PropertyTab.ts",
-                    "../../inspector/src/tabs/CameraTab.ts",
-                    "../../inspector/src/tabs/GUITab.ts",
-                    "../../inspector/src/tabs/PhysicsTab.ts",
-                    "../../inspector/src/tabs/SoundTab.ts",
-                    "../../inspector/src/tabs/TextureTab.ts",
-                    "../../inspector/src/tabs/LightTab.ts",
-                    "../../inspector/src/tabs/MaterialTab.ts",
-                    "../../inspector/src/tabs/MeshTab.ts",
-                    "../../inspector/src/tabs/SceneTab.ts",
-                    "../../inspector/src/tabs/ConsoleTab.ts",
-                    "../../inspector/src/tabs/StatsTab.ts",
-                    "../../inspector/src/tabs/GLTFTab.ts",
-                    "../../inspector/src/tabs/ToolsTab.ts",
-                    "../../inspector/src/tabs/TabBar.ts",
-                    "../../inspector/src/tools/AbstractTool.ts",
-                    "../../inspector/src/tools/PauseScheduleTool.ts",
-                    "../../inspector/src/tools/PickTool.ts",
-                    "../../inspector/src/tools/PopupTool.ts",
-                    "../../inspector/src/tools/RefreshTool.ts",
-                    "../../inspector/src/tools/LabelTool.ts",
-                    "../../inspector/src/tools/Toolbar.ts",
-                    "../../inspector/src/tools/DisposeTool.ts",
-                    "../../inspector/src/tools/FullscreenTool.ts",
-                    "../../inspector/src/tree/TreeItem.ts",
-                    "../../inspector/src/treetools/AbstractTreeTool.ts",
-                    "../../inspector/src/treetools/BoundingBox.ts",
-                    "../../inspector/src/treetools/CameraPOV.ts",
-                    "../../inspector/src/treetools/SoundInteractions.ts",
-                    "../../inspector/src/treetools/Checkbox.ts",
-                    "../../inspector/src/treetools/DebugArea.ts",
-                    "../../inspector/src/treetools/Info.ts",
-                    "../../inspector/src/lib.d.ts"
-                ],
-                "sassFiles": [
-                    "../../inspector/sass/**/*.scss"
-                ],
-                "output": "babylon.inspector.js",
+                "files": [],
+                "sassFiles": [],
+                "output": "babylon.inspector.bundle.js",
                 "webpack": "../../inspector/webpack.config.js",
                 "bundle": "true",
-                "moduleDeclaration": {
-                    "name": "INSPECTOR",
-                    "module": "babylonjs-inspector"
-                },
-                "extendsRoot": true
+                "extendsRoot": true,
+                "useOutputForDebugging": true
             }
         ],
         "build": {
-            "srcOutputDirectory": "../../inspector/",
-            "distOutputDirectory": "/inspector/"
+            "srcOutputDirectory": "../../inspector/src/",
+            "distOutputDirectory": "/inspector/",
+            "dtsBundle": {
+                "name": "babylonjs-inspector",
+                "main": "../../dist/preview release/inspector/build/index.d.ts",
+                "out": "../babylon.inspector.module.d.ts",
+                "baseDir": "../../dist/preview release/inspector/build/",
+                "headerText": "BabylonJS Inspector"
+            },
+            "processDeclaration": {
+                "filename": "babylon.inspector.module.d.ts",
+                "packageName": "babylonjs-inspector",
+                "moduleName": "INSPECTOR",
+                "importsToRemove": [],
+                "classMap": {
+                    "babylonjs": "BABYLON",
+                    "babylonjs-loaders": "BABYLON",
+                    "babylonjs-serializers": "BABYLON",
+                    "babylonjs-gui": "BABYLON.GUI"
+                }
+            }
         }
     },
     "viewer": {
@@ -1998,18 +1925,32 @@
                     "name": "BabylonViewer",
                     "module": "babylonjs-viewer"
                 },
-                "babylonIncluded": true
+                "babylonIncluded": true,
+                "noWatch": true,
+                "preventLoadLibrary": true
             }
         ],
         "build": {
             "srcOutputDirectory": "../../Viewer/",
+            "distOutputDirectory": "/viewer/",
             "dtsBundle": {
                 "name": "babylonjs-viewer",
-                "main": "../../Viewer/dist/build/src/index.d.ts",
-                "out": "../../../../dist/preview release/viewer/babylon.viewer.module.d.ts",
-                "legacyDeclaration": true,
+                "main": "../../dist/preview release/viewer/build/src/index.d.ts",
+                "out": "../../babylon.viewer.module.d.ts",
                 "prependText": "/// <reference path=\"./babylon.d.ts\"/>\n/// <reference path=\"./babylon.glTF2Interface.d.ts\"/>\n/// <reference path=\"./babylonjs.loaders.d.ts\"/>\ndeclare module \"babylonjs-loaders\"{ export=BABYLON;}\n"
             },
+            "processDeclaration": {
+                "packageName": "babylonjs-viewer",
+                "moduleName": "BabylonViewer",
+                "importsToRemove": [
+                    "pep",
+                    "babylonjs-loaders"
+                ],
+                "classMap": {
+                    "babylonjs": "BABYLON",
+                    "babylonjs-loaders": "BABYLON"
+                }
+            },
             "outputs": [
                 {
                     "destination": [
@@ -2026,8 +1967,7 @@
                                 "glTF2Interface/babylon.glTF2Interface.d.ts"
                             ]
                         }
-                    ],
-                    "minified": true
+                    ]
                 },
                 {
                     "destination": [
@@ -2056,23 +1996,25 @@
                     "name": "BabylonViewerAssets",
                     "module": "babylonjs-viewer-assets"
                 },
-                "babylonIncluded": true
+                "babylonIncluded": true,
+                "noWatch": true,
+                "preventLoadLibrary": true
             }
         ],
         "build": {
             "srcOutputDirectory": "../../Viewer/",
+            "distOutputDirectory": "/viewer/",
             "dtsBundle": {
                 "name": "babylonjs-viewer-assets",
-                "baseDir": "../../Viewer/dist/build/src/assets/",
-                "main": "../../Viewer/dist/build/src/assets/index.d.ts",
-                "out": "../../../build/assets/babylon.viewer.assets.module.d.ts"
+                "main": "../../dist/preview release/viewer/build/src/assets/index.d.ts",
+                "out": "../../../../../../Viewer/build/assets/babylon.viewer.assets.module.d.ts"
             },
             "outputs": [
                 {
                     "destination": [
                         {
                             "filename": "babylon.viewer.assets.js",
-                            "outputDirectory": "/../../Viewer/dist/build/assets/"
+                            "outputDirectory": "/../../Viewer/build/assets/"
                         }
                     ],
                     "minified": true
@@ -2080,4 +2022,4 @@
             ]
         }
     }
-}
+}

+ 94 - 33
Tools/Gulp/gulpfile.js

@@ -16,7 +16,6 @@ var merge2 = require("merge2");
 var concat = require("gulp-concat");
 var rename = require("gulp-rename");
 var cleants = require("gulp-clean-ts-extends");
-var changedInPlace = require("gulp-changed-in-place");
 var runSequence = require("run-sequence");
 var replace = require("gulp-replace");
 var uncommentShader = require("./gulp-removeShaderComments");
@@ -25,17 +24,17 @@ var optimisejs = require("gulp-optimize-js");
 var webserver = require("gulp-webserver");
 var path = require("path");
 var sass = require("gulp-sass");
-var webpack = require("webpack-stream");
+const webpack = require('webpack');
+var webpackStream = require("webpack-stream");
 var typedoc = require("gulp-typedoc");
 var validateTypedoc = require("./gulp-validateTypedoc");
-var request = require('request');
 var fs = require("fs");
 var dtsBundle = require('dts-bundle');
 const through = require('through2');
 var karmaServer = require('karma').Server;
 
 //viewer declaration
-var processViewerDeclaration = require('./processViewerDeclaration');
+var processDeclaration = require('./processViewerDeclaration');
 
 var config = require("./config.json");
 
@@ -448,7 +447,7 @@ var buildExternalLibrary = function (library, settings, watch) {
 
         if (library.webpack) {
             let sequence = [waitAll];
-            let wpBuild = webpack(require(library.webpack));
+            let wpBuild = webpackStream(require(library.webpack), webpack);
             if (settings.build.outputs) {
                 //shoud dtsBundle create the declaration?
                 if (settings.build.dtsBundle) {
@@ -459,7 +458,7 @@ var buildExternalLibrary = function (library, settings, watch) {
                             if (isdts) this.push(file);
                             cb();
                         }))
-                        .pipe(gulp.dest('.'));
+                        .pipe(gulp.dest(outputDirectory));
                     // dts-bundle does NOT support (gulp) streams, so files have to be saved and reloaded, 
                     // until I fix it
                     event.on("end", function () {
@@ -471,8 +470,8 @@ var buildExternalLibrary = function (library, settings, watch) {
                             if (err) throw err;
                             data = (settings.build.dtsBundle.prependText || "") + '\n' + data.toString();
                             fs.writeFile(fileLocation, data);
-                            if (settings.build.dtsBundle.legacyDeclaration) {
-                                var newData = processViewerDeclaration(data);
+                            if (settings.build.processDeclaration) {
+                                var newData = processDeclaration(data, settings.build.processDeclaration);
                                 fs.writeFile(fileLocation.replace('.module', ''), newData);
                             }
                         });
@@ -541,14 +540,50 @@ var buildExternalLibrary = function (library, settings, watch) {
                 sequence.push(build);
 
             } else {
+
+                let buildEvent = wpBuild
+                    .pipe(gulp.dest(outputDirectory))
+                    //back-compat
+                    .pipe(through.obj(function (file, enc, cb) {
+                        // only js files
+                        const isjs = /\.js$/.test(file.path);
+                        if (isjs) this.push(file);
+                        cb();
+                    }))
+                    .pipe(rename(library.output.replace(".js", ".max.js")))
+                    .pipe(rename(library.output.replace(".min.max.", ".")))
+                    .pipe(rename(library.output.replace(".bundle.max.", ".")))
+                    .pipe(gulp.dest(outputDirectory));
                 sequence.push(
-                    wpBuild
-                        .pipe(rename(library.output.replace(".js", library.noBundleInName ? '.js' : ".bundle.js")))
-                        .pipe(addModuleExports(library.moduleDeclaration, { subModule: false, extendsRoot: library.extendsRoot, externalUsingBabylon: true }))
-                        .pipe(uglify())
-                        .pipe(optimisejs())
-                        .pipe(gulp.dest(outputDirectory))
-                )
+                    buildEvent
+                );
+                if (settings.build.dtsBundle || settings.build.processDeclaration) {
+                    buildEvent.on("end", function () {
+                        if (settings.build.dtsBundle) {
+                            dtsBundle.bundle(settings.build.dtsBundle);
+                        } if (settings.build.processDeclaration) {
+                            let fileLocation = path.join(outputDirectory, settings.build.processDeclaration.filename);
+                            fs.readFile(fileLocation, function (err, data) {
+                                if (err) throw err;
+                                var newData = processDeclaration(data, settings.build.processDeclaration);
+                                fs.writeFile(fileLocation.replace('.module', ''), newData);
+                            });
+                        }
+                    });
+                }
+                /*if (settings.build.processDeclaration) {
+                    sequence.push(
+                        wpBuild
+                            .pipe(through.obj(function (file, enc, cb) {
+                                // only js files
+                                const isDts = /\.d.ts$/.test(file.path);
+                                file.contents = new Buffer(processDeclaration(file.contents, settings.build.processDeclaration));
+                                if (isDts) this.push(file);
+                                cb();
+                            }))
+                            .pipe(gulp.dest(outputDirectory))
+                    )
+                }*/
             }
 
             return merge2(sequence);
@@ -600,7 +635,7 @@ gulp.task("build-custom", function (cb) {
  * Do it all.
  */
 gulp.task("typescript-all", function (cb) {
-    runSequence("typescript", "typescript-libraries", cb);
+    runSequence("typescript", "typescript-libraries", "netlify-cleanup", cb);
 });
 
 /**
@@ -623,22 +658,35 @@ gulp.task("watch", ["srcTscWatch"], function () {
     var tasks = [];
 
     config.modules.map(function (module) {
+
         config[module].libraries.map(function (library) {
-            tasks.push(gulp.watch(library.files, { interval: interval }, function () {
-                console.log(library.output);
-                return buildExternalLibrary(library, config[module], true)
-                    .pipe(debug());
-            }));
-            tasks.push(gulp.watch(library.shaderFiles, { interval: interval }, function () {
-                console.log(library.output);
-                return buildExternalLibrary(library, config[module], true)
-                    .pipe(debug())
-            }));
-            tasks.push(gulp.watch(library.sassFiles, { interval: interval }, function () {
-                console.log(library.output);
-                return buildExternalLibrary(library, config[module], true)
-                    .pipe(debug())
-            }));
+            if (library.webpack) {
+                if (library.noWatch) return;
+                var outputDirectory = config.build.tempDirectory + config[module].build.distOutputDirectory;
+                let wpconfig = require(library.webpack);
+                wpconfig.watch = true;
+                // dev mode and absolute path sourcemaps for debugging
+                wpconfig.mode = "development";
+                wpconfig.output.devtoolModuleFilenameTemplate = "[absolute-resource-path]";
+                //config.stats = "minimal";
+                tasks.push(webpackStream(wpconfig, webpack).pipe(gulp.dest(outputDirectory)))
+            } else {
+                tasks.push(gulp.watch(library.files, { interval: interval }, function () {
+                    console.log(library.output);
+                    return buildExternalLibrary(library, config[module], true)
+                        .pipe(debug());
+                }));
+                tasks.push(gulp.watch(library.shaderFiles, { interval: interval }, function () {
+                    console.log(library.output);
+                    return buildExternalLibrary(library, config[module], true)
+                        .pipe(debug())
+                }));
+                tasks.push(gulp.watch(library.sassFiles, { interval: interval }, function () {
+                    console.log(library.output);
+                    return buildExternalLibrary(library, config[module], true)
+                        .pipe(debug())
+                }));
+            }
         });
     });
 
@@ -696,6 +744,19 @@ gulp.task("clean-JS-MAP", function () {
     ], { force: true });
 });
 
+gulp.task("netlify-cleanup", function () {
+    //set by netlify
+    if (process.env.REPOSITORY_URL) {
+        return del([
+            "../../inspector/node_modules/**/*", "../../gui/node_modules/**/*",
+            "../../Viewer/node_modules/**/*"
+        ], { force: true });
+    }
+    else {
+        return true;
+    }
+})
+
 // this is needed for the modules for the declaration files.
 gulp.task("modules-compile", function () {
     var tsResult = gulp.src(config.typescript)
@@ -1131,7 +1192,7 @@ gulp.task("tests-viewer-validation-browserstack", ["tests-viewer-validation-tran
  */
 gulp.task("tests-viewer-validation-transpile", function (done) {
 
-    let wpBuild = webpack(require('../../Viewer//webpack.gulp.config.js'));
+    let wpBuild = webpackStream(require('../../Viewer/webpack.gulp.config.js'), webpack);
 
     // clean the built directory
     rmDir("../../Viewer/tests/build/");
@@ -1150,7 +1211,7 @@ gulp.task("tests-viewer-validation-transpile", function (done) {
  */
 gulp.task("tests-viewer-transpile", function (done) {
 
-    let wpBuild = webpack(require('../../Viewer/tests/unit/webpack.config.js'));
+    let wpBuild = webpackStream(require('../../Viewer/tests/unit/webpack.config.js'), webpack);
 
     // clean the built directory
     rmDir("../../Viewer/tests/build/");

+ 2 - 1
Tools/Gulp/package.json

@@ -59,10 +59,11 @@
         "ts-loader": "^2.3.7",
         "typedoc": "^0.9.0",
         "typescript": "~2.8.1",
+        "webpack": "^4.16.0",
         "webpack-stream": "^4.0.1"
     },
     "scripts": {
-        "install": "npm --prefix ../../Playground/ install ../../Playground/ && npm --prefix ../../tests/unit/ install ../../tests/unit/ && npm --prefix ../../Viewer/tests/ install ../../Viewer/tests/ && cd ../../Viewer && npm install && cd ../Tools/Gulp/ && gulp deployLocalDev"
+        "install": "cd ../../gui && npm install && cd ../Tools/Gulp/ &&  cd ../../inspector && npm install && cd ../Tools/Gulp/ && npm --prefix ../../Playground/ install ../../Playground/ && npm --prefix ../../tests/unit/ install ../../tests/unit/ && npm --prefix ../../Viewer/tests/ install ../../Viewer/tests/ && cd ../../Viewer && npm install && cd ../Tools/Gulp/ && gulp deployLocalDev"
     },
     "dependencies": {
         "dts-bundle": "^0.7.3",

+ 44 - 19
Tools/Gulp/processViewerDeclaration.js

@@ -1,4 +1,13 @@
-module.exports = function (data) {
+module.exports = function (data, options) {
+
+    /*
+    {
+        packageName: string,
+        moduleName: string,
+        importsToRemove: Array<string>,
+        classMap
+    }
+    */
 
     var str = "" + data;
 
@@ -6,35 +15,51 @@ module.exports = function (data) {
     // str = str.replace(/declare module 'babylonjs-viewer\/' {((?!(declare))(.|\n))*\n}/g, '');
 
     let lines = str.split('\n');
-    var firstIndex = lines.findIndex((line => { return line.indexOf("'babylonjs-viewer/'") !== -1 }));
+    var firstIndex = lines.findIndex((line => { return line.indexOf(`'${options.packageName}/'`) !== -1 }));
     var lastIndex = lines.findIndex(((line, idx) => { return line.trim() === '}' && idx > firstIndex }));
     lines.splice(firstIndex, lastIndex - firstIndex + 1);
     str = lines.join('\n');
 
-    str = str.replace(/declare module (.*) {/g, 'declare module BabylonViewer {').replace("import * as BABYLON from 'babylonjs';", "");
-    str = str.replace(/import {(.*)} from ['"]babylonjs-viewer(.*)['"];/g, '').replace(/import 'babylonjs-loaders';/, '').replace(/import 'pep';/, '');
+    str = str.replace(/declare module (.*) {/g, `declare module ${options.moduleName} {`);
+
+    str = str.replace("import * as BABYLON from 'babylonjs';", "");
+    let regexp = new RegExp(`import {(.*)} from ['"]${options.packageName}(.*)['"];`, 'g');
+    str = str.replace(regexp, '');
+
+    if (options.importsToRemove) {
+        while (options.importsToRemove.length) {
+            let remove = options.importsToRemove.pop();
+            str = str.replace(new RegExp(`import '${remove}';`), '');
+        }
+    }
 
     //find all used BABYLON and BABYLON-Loaders classes:
 
-    var babylonRegex = /import {(.*)} from ['"](babylonjs|babylonjs-loaders)['"];/g
+    if ((options.classMap)) {
+        Object.keys(options.classMap).forEach(package => {
+            var babylonRegex = new RegExp(`import {(.*)} from ['"](${package})['"];`, "g");
 
-    var match = babylonRegex.exec(str);
-    let classes = new Set();
-    while (match != null) {
-        if (match[1]) {
-            match[1].split(",").forEach(element => {
-                classes.add(element.trim());
+            var match = babylonRegex.exec(str);
+            let classes = new Set();
+            while (match != null) {
+                if (match[1]) {
+                    match[1].split(",").forEach(element => {
+                        classes.add(element.trim());
+                    });
+                }
+                match = babylonRegex.exec(str);
+            }
+            str = str.replace(babylonRegex, '');
+            classes.forEach(cls => {
+                let rg = new RegExp(`([ <])(${cls})([^\\w])`, "g")
+                str = str.replace(rg, `$1${options.classMap[package]}.$2$3`);
             });
-        }
-        match = babylonRegex.exec(str);
+        })
     }
-    str = str.replace(babylonRegex, '');
-    classes.forEach(cls => {
-        let rg = new RegExp(`([ <])(${cls})([^\\w])`, "g")
-        str = str.replace(rg, "$1BABYLON.$2$3");
-    });
 
-    str = str.replace(/export {(.*)};/g, '')
+    str = str.replace(/export {(.*)};/g, '');
+
+    str = str.split("\n").filter(line => line.trim()).filter(line => line.indexOf("export * from") === -1).join("\n");
 
     return str;
 }

+ 6 - 3
Tools/Publisher/index.js

@@ -56,7 +56,7 @@ let packages = [
     },
     {
         name: 'viewer-assets',
-        path: basePath + '/../../Viewer/dist/build/assets/',
+        path: basePath + '/../../Viewer/build/assets/',
         required: [
             basePath + '/../../Viewer/assets/readme.md',
             basePath + '/../../Viewer/assets/package.json',
@@ -215,7 +215,7 @@ function processCore(package, version) {
 
 function processViewer(package, version) {
 
-    let buildPath = package.path + "dist/build/src/";
+    let buildPath = package.path + "build/src/";
     let projectPath = '../../Viewer';
 
     if (package.required) {
@@ -257,7 +257,10 @@ function publish(version, packageName, basePath) {
 
     //publish the respected package
     console.log("executing " + 'npm publish \"' + basePath + "\"" + ' ' + tagDef);
-    shelljs.exec('npm publish \"' + basePath + "\"" + ' ' + tagDef);
+    if (process.argv.indexOf('--no-publish') === -1) {
+        shelljs.exec('npm publish \"' + basePath + "\"" + ' ' + tagDef);
+    }
+
 }
 
 function getFiles(dir, files_) {

+ 139 - 0
Tools/WebpackShaderLoader/index.js

@@ -0,0 +1,139 @@
+//modified https://github.com/grieve/webpack-glsl-loader/blob/master/index.js
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+
+function parse(loader, source, context, cb) {
+    var imports = [];
+    var importPattern = /@import ([.\/\w_-]+);/gi;
+    var match = importPattern.exec(source);
+
+    while (match != null) {
+        imports.push({
+            key: match[1],
+            target: match[0],
+            content: ''
+        });
+        match = importPattern.exec(source);
+    }
+
+    source = uncomment(source);
+
+    processImports(loader, source, context, imports, cb);
+}
+
+var singleComment = 1;
+var multiComment = 2;
+
+function uncomment(str) {
+
+    var currentChar;
+    var nextChar;
+    var insideString = false;
+    var insideComment = 0;
+    var offset = 0;
+    var ret = '';
+
+    str = str.replace(/\r\n/g, '\n');
+    str = str.replace(/[ \f\t\v]+/g, ' ');
+    str = str.replace(/^\s*\n/gm, '');
+    str = str.replace(/ \+ /g, '+');
+    str = str.replace(/ \- /g, '-');
+    str = str.replace(/ \/ /g, '/');
+    str = str.replace(/ \* /g, '*');
+    str = str.replace(/ > /g, '>');
+    str = str.replace(/ < /g, '<');
+    str = str.replace(/ >= /g, '>=');
+    str = str.replace(/ <= /g, '<=');
+    str = str.replace(/ \+= /g, '+=');
+    str = str.replace(/ \-= /g, '-=');
+    str = str.replace(/ \/= /g, '/=');
+    str = str.replace(/ \*= /g, '*=');
+    str = str.replace(/ = /g, '=');
+    str = str.replace(/, /g, ',');
+    str = str.replace(/\n\n/g, '\n');
+    str = str.replace(/\n /g, '\n');
+
+    for (var i = 0; i < str.length; i++) {
+        currentChar = str[i];
+        nextChar = str[i + 1];
+
+        if (!insideComment && currentChar === '"') {
+            var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\';
+            if (!escaped) {
+                insideString = !insideString;
+            }
+        }
+
+        if (insideString) {
+            continue;
+        }
+
+        if (!insideComment && currentChar + nextChar === '//') {
+            ret += str.slice(offset, i);
+            offset = i;
+            insideComment = singleComment;
+            i++;
+        } else if (insideComment === singleComment && currentChar === '\n') {
+            insideComment = 0;
+            offset = i;
+        } else if (!insideComment && currentChar + nextChar === '/*') {
+            ret += str.slice(offset, i);
+            offset = i;
+            insideComment = multiComment;
+            i++;
+            continue;
+        } else if (insideComment === multiComment && currentChar + nextChar === '*/') {
+            i++;
+            insideComment = 0;
+            offset = i + 1;
+            continue;
+        }
+    }
+
+    return ret + (insideComment ? '' : str.substr(offset));
+}
+
+function processImports(loader, source, context, imports, cb) {
+    if (imports.length === 0) {
+        return cb(null, source);
+    }
+
+    var imp = imports.pop();
+
+    loader.resolve(context, imp.key + '.fx', function (err, resolved) {
+        if (err) {
+            return cb(err);
+        }
+
+        loader.addDependency(resolved);
+        fs.readFile(resolved, 'utf-8', function (err, src) {
+            if (err) {
+                return cb(err);
+            }
+
+            parse(loader, src, path.dirname(resolved), function (err, bld) {
+                if (err) {
+                    return cb(err);
+                }
+
+                source = source.replace(imp.target, bld);
+                processImports(loader, source, context, imports, cb);
+            });
+        });
+    });
+}
+
+module.exports = function (source) {
+    this.cacheable();
+    var cb = this.async();
+    parse(this, source, this.context, function (err, bld) {
+        if (err) {
+            return cb(err);
+        }
+
+        cb(null, 'module.exports = ' + JSON.stringify(bld));
+    });
+};

+ 6 - 4
Viewer/package.json

@@ -27,15 +27,17 @@
         "@types/node": "^8.9.4",
         "base64-font-loader": "0.0.4",
         "base64-image-loader": "^1.2.1",
+        "base64-inline-loader": "^1.1.1",
         "deepmerge": "^2.1.1",
         "handlebars": "^4.0.11",
         "html-loader": "^0.5.5",
         "json-loader": "^0.5.7",
-        "ts-loader": "^2.3.7",
-        "typescript": "^2.7.2",
+        "ts-loader": "^4.4.0",
+        "typescript": "^2.9.2",
         "uglifyjs-webpack-plugin": "^1.2.2",
-        "webpack": "^3.11.0",
-        "webpack-dev-server": "^2.11.2"
+        "webpack": "^4.16.0",
+        "webpack-cli": "^3.0.8",
+        "webpack-dev-server": "^3.1.4"
     },
     "dependencies": {
         "pepjs": "^0.4.3"

+ 3 - 1
Viewer/src/configuration/types/default.ts

@@ -51,12 +51,14 @@ export let defaultConfiguration: ViewerConfiguration = {
                 hideHelp: true,
                 hideHd: true,
                 hideVr: true,
+                hidePrint: true,
                 disableOnFullscreen: false,
                 text: {
                     hdButton: "Toggle HD",
                     fullscreenButton: "Fullscreen",
                     helpButton: "Help",
-                    vrButton: "Toggle VR"
+                    vrButton: "Toggle VR",
+                    printButton: "Print model in 3D"
                 }
             },
             events: {

+ 62 - 0
Viewer/src/templating/plugins/printButton.ts

@@ -0,0 +1,62 @@
+import { AbstractViewerNavbarButton } from "../viewerTemplatePlugin";
+import { DefaultViewer } from "../../viewer/defaultViewer";
+import { EventCallback } from "../templateManager";
+import { Tools } from "babylonjs";
+
+export class PrintButtonPlugin extends AbstractViewerNavbarButton {
+
+    private _currentModelUrl: string;
+
+    constructor(private _viewer: DefaultViewer) {
+        super("print", "print-button", PrintButtonPlugin.HtmlTemplate);
+
+        this._viewer.onModelLoadedObservable.add((model) => {
+            this._currentModelUrl = "";
+            if (model.configuration.url) {
+                let filename = Tools.GetFilename(model.configuration.url) || model.configuration.url;
+                let baseUrl = model.configuration.root || Tools.GetFolderPath(model.configuration.url);
+
+                //gltf, obj, stl
+                let extension = model.configuration.loader || filename.split(".").pop() || "";
+                let printable = false;
+                // not using .some sue to IE11
+                ["gltf", "glb", "obj", "stl"].forEach(ext => {
+                    if (extension.indexOf(ext) !== -1) {
+                        printable = true;
+                    }
+                })
+                if (printable) {
+                    this._currentModelUrl = baseUrl + filename;
+                }
+            }
+        })
+    }
+
+    onEvent(event: EventCallback): void {
+        if (this._currentModelUrl) {
+            let printUrl = this._currentModelUrl.replace(/https?:\/\//, "com.microsoft.print3d://");
+            window.open(printUrl);
+        }
+    }
+
+    protected static HtmlTemplate: string = `
+{{#unless hidePrint}}
+<style>
+
+/* Show only if it's a windows 10 printer  */
+.print-icon.not-win-10 {
+    display: none;
+}
+
+.print-icon:after {
+    font-size: 16px;
+    content: "\\E914";
+}
+
+</style>
+<button class="print-button ${window.navigator.userAgent.indexOf("Windows NT 10.0") === -1 ? "no-win-10" : ""}" title="{{text.printButton}}">
+     <span class="icon print-icon"></span>
+ </button>
+ {{/unless}}
+`;
+}

+ 2 - 0
Viewer/src/viewer/defaultViewer.ts

@@ -8,6 +8,7 @@ import { ViewerModel } from '../model/viewerModel';
 import { IModelAnimation, AnimationState } from '../model/modelAnimation';
 import { IViewerTemplatePlugin } from '../templating/viewerTemplatePlugin';
 import { HDButtonPlugin } from '../templating/plugins/hdButtonPlugin';
+import { PrintButtonPlugin } from '../templating/plugins/printButton';
 
 /**
  * The Default viewer is the default implementation of the AbstractViewer.
@@ -148,6 +149,7 @@ export class DefaultViewer extends AbstractViewer {
             }
 
             this.registerTemplatePlugin(new HDButtonPlugin(this));
+            this.registerTemplatePlugin(new PrintButtonPlugin(this));
         }
     }
 

+ 2 - 1
Viewer/tests/unit/tsconfig.json

@@ -20,7 +20,7 @@
         "skipDefaultLibCheck": true,
         "skipLibCheck": true,
         "baseUrl": "./src/",
-        "rootDir": "./",
+        "rootDir": "../../",
         "paths": {
             "babylonjs": [
                 "../../../../dist/preview release/babylon.d.ts"
@@ -35,6 +35,7 @@
                 "../../src/assets/"
             ]
         },
+        "outDir": "./build"
     },
     "include": [
         "./src/**/*.ts"

+ 4 - 2
Viewer/tests/unit/webpack.config.js

@@ -1,6 +1,7 @@
 const path = require('path');
 
 module.exports = {
+    context: __dirname,
     entry: {
         'test': __dirname + '/src/index.ts'
     },
@@ -24,9 +25,10 @@ module.exports = {
         oimo: 'OIMO',
         "earcut": true
     },
+    mode: "development",
     devtool: 'source-map',
     module: {
-        loaders: [{
+        rules: [{
             test: /\.tsx?$/,
             loader: 'ts-loader',
             exclude: /node_modules/
@@ -46,7 +48,7 @@ module.exports = {
         },
         {
             test: /\.(woff|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
-            loader: 'base64-font-loader'
+            loader: 'base64-inline-loader?limit=1000&name=[name].[ext]'
         }]
     },
     devServer: {

+ 1 - 1
Viewer/tsconfig-gulp.json

@@ -41,7 +41,7 @@
                 "./assets/"
             ]
         },
-        "outDir": "./dist/build"
+        "outDir": "./build"
     },
     "exclude": [
         "node_modules",

+ 2 - 2
Viewer/tsconfig.json

@@ -1,6 +1,6 @@
 {
     "compilerOptions": {
-        "target": "es2015",
+        "target": "es5",
         "module": "commonjs",
         "declaration": true,
         "experimentalDecorators": true,
@@ -44,6 +44,6 @@
                 "./assets/*"
             ]
         },
-        "outDir": "./dist/build"
+        "outDir": "./build"
     }
 }

+ 4 - 2
Viewer/webpack.assets.config.js

@@ -1,4 +1,5 @@
 module.exports = {
+    context: __dirname,
     entry: [
         __dirname + '/src/assets/index.ts'
     ],
@@ -10,8 +11,9 @@ module.exports = {
     resolve: {
         extensions: ['.ts']
     },
+    mode: "production",
     module: {
-        loaders: [{
+        rules: [{
             test: /\.tsx?$/,
             use: {
                 loader: 'ts-loader',
@@ -36,7 +38,7 @@ module.exports = {
         },
         {
             test: /\.(woff|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
-            loader: 'base64-font-loader'
+            loader: 'base64-inline-loader?limit=1000&name=[name].[ext]'
         }]
     }
 }

+ 4 - 3
Viewer/webpack.config.js

@@ -54,7 +54,7 @@ module.exports = /*[
             libraryTarget: 'umd',
             library: 'BabylonViewer',
             umdNamedDefine: true,
-            devtoolModuleFilenameTemplate: '[relative-resource-path]'
+            devtoolModuleFilenameTemplate: '[absolute-resource-path]'
         },
         resolve: {
             extensions: ['.ts', '.js'],
@@ -71,6 +71,7 @@ module.exports = /*[
             oimo: 'OIMO',
             earcut: true
         },
+        mode: "development",
         devtool: 'source-map',
         plugins: [
             new webpack.WatchIgnorePlugin([
@@ -78,7 +79,7 @@ module.exports = /*[
             ])
         ],
         module: {
-            loaders: [{
+            rules: [{
                 test: /\.tsx?$/,
                 loader: 'ts-loader',
                 exclude: /node_modules/
@@ -98,7 +99,7 @@ module.exports = /*[
             },
             {
                 test: /\.(woff|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
-                loader: 'base64-font-loader'
+                loader: 'base64-inline-loader?limit=1000&name=[name].[ext]'
             }]
         },
         devServer: {

+ 9 - 10
Viewer/webpack.gulp.config.js

@@ -1,7 +1,10 @@
+const path = require('path');
+const webpack = require('webpack');
+
 module.exports = {
-    //context: __dirname,
+    context: __dirname,
     entry: [
-        __dirname + '/src/index.ts'
+        path.resolve(__dirname, './src/index.ts')
     ],
     output: {
         libraryTarget: 'var',
@@ -22,15 +25,11 @@ module.exports = {
             "babylonjs-viewer-assets": __dirname + '/src/assets/index.ts'
         }
     },
+    mode: "production",
     module: {
-        loaders: [{
+        rules: [{
             test: /\.tsx?$/,
-            use: {
-                loader: 'ts-loader',
-                options: {
-                    configFile: 'tsconfig-gulp.json'
-                }
-            },
+            loader: 'ts-loader',
             exclude: /node_modules/
         },
         {
@@ -48,7 +47,7 @@ module.exports = {
         },
         {
             test: /\.(woff|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
-            loader: 'base64-font-loader'
+            loader: 'base64-inline-loader?limit=1000&name=[name].[ext]'
         }]
     }
 }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 8115 - 8114
dist/preview release/babylon.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 47 - 47
dist/preview release/babylon.js


+ 23 - 18
dist/preview release/babylon.max.js

@@ -15760,7 +15760,6 @@ var BABYLON;
             var gl = this._gl;
             var texture = new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_CUBERAW);
             texture.isCube = true;
-            texture.generateMipMaps = generateMipMaps;
             texture.format = format;
             texture.type = type;
             if (!this._doNotHandleContextLost) {
@@ -15771,6 +15770,25 @@ var BABYLON;
             if (internalFormat === gl.RGB) {
                 internalFormat = gl.RGBA;
             }
+            // Mipmap generation needs a sized internal format that is both color-renderable and texture-filterable
+            if (textureType === gl.FLOAT && !this._caps.textureFloatLinearFiltering) {
+                generateMipMaps = false;
+                samplingMode = Engine.TEXTURE_NEAREST_SAMPLINGMODE;
+                BABYLON.Tools.Warn("Float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
+            }
+            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
+                generateMipMaps = false;
+                samplingMode = Engine.TEXTURE_NEAREST_SAMPLINGMODE;
+                BABYLON.Tools.Warn("Half float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
+            }
+            else if (textureType === gl.FLOAT && !this._caps.textureFloatRender) {
+                generateMipMaps = false;
+                BABYLON.Tools.Warn("Render to float textures is not supported. Mipmap generation forced to false.");
+            }
+            else if (textureType === gl.HALF_FLOAT && !this._caps.colorBufferFloat) {
+                generateMipMaps = false;
+                BABYLON.Tools.Warn("Render to half float textures is not supported. Mipmap generation forced to false.");
+            }
             var width = size;
             var height = width;
             texture.width = width;
@@ -15789,22 +15807,13 @@ var BABYLON;
             if (data && generateMipMaps) {
                 this._gl.generateMipmap(this._gl.TEXTURE_CUBE_MAP);
             }
-            if (textureType === gl.FLOAT && !this._caps.textureFloatLinearFiltering) {
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
-            }
-            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
-            }
-            else {
-                var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
-            }
+            var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
+            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
+            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
+            texture.generateMipMaps = generateMipMaps;
             return texture;
         };
         /**
@@ -15871,10 +15880,6 @@ var BABYLON;
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
                 }
                 else {
-                    texture.generateMipMaps = !noMipmap;
-                    if (type === Engine.TEXTURETYPE_FLOAT && !_this._caps.textureFloatLinearFiltering) {
-                        texture.generateMipMaps = false;
-                    }
                     _this.updateRawCubeTexture(texture, faceDataArrays, format, type, invertY);
                 }
                 texture.isReady = true;

+ 23 - 18
dist/preview release/babylon.no-module.max.js

@@ -15727,7 +15727,6 @@ var BABYLON;
             var gl = this._gl;
             var texture = new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_CUBERAW);
             texture.isCube = true;
-            texture.generateMipMaps = generateMipMaps;
             texture.format = format;
             texture.type = type;
             if (!this._doNotHandleContextLost) {
@@ -15738,6 +15737,25 @@ var BABYLON;
             if (internalFormat === gl.RGB) {
                 internalFormat = gl.RGBA;
             }
+            // Mipmap generation needs a sized internal format that is both color-renderable and texture-filterable
+            if (textureType === gl.FLOAT && !this._caps.textureFloatLinearFiltering) {
+                generateMipMaps = false;
+                samplingMode = Engine.TEXTURE_NEAREST_SAMPLINGMODE;
+                BABYLON.Tools.Warn("Float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
+            }
+            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
+                generateMipMaps = false;
+                samplingMode = Engine.TEXTURE_NEAREST_SAMPLINGMODE;
+                BABYLON.Tools.Warn("Half float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
+            }
+            else if (textureType === gl.FLOAT && !this._caps.textureFloatRender) {
+                generateMipMaps = false;
+                BABYLON.Tools.Warn("Render to float textures is not supported. Mipmap generation forced to false.");
+            }
+            else if (textureType === gl.HALF_FLOAT && !this._caps.colorBufferFloat) {
+                generateMipMaps = false;
+                BABYLON.Tools.Warn("Render to half float textures is not supported. Mipmap generation forced to false.");
+            }
             var width = size;
             var height = width;
             texture.width = width;
@@ -15756,22 +15774,13 @@ var BABYLON;
             if (data && generateMipMaps) {
                 this._gl.generateMipmap(this._gl.TEXTURE_CUBE_MAP);
             }
-            if (textureType === gl.FLOAT && !this._caps.textureFloatLinearFiltering) {
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
-            }
-            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
-            }
-            else {
-                var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
-            }
+            var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
+            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
+            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
+            texture.generateMipMaps = generateMipMaps;
             return texture;
         };
         /**
@@ -15838,10 +15847,6 @@ var BABYLON;
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
                 }
                 else {
-                    texture.generateMipMaps = !noMipmap;
-                    if (type === Engine.TEXTURETYPE_FLOAT && !_this._caps.textureFloatLinearFiltering) {
-                        texture.generateMipMaps = false;
-                    }
                     _this.updateRawCubeTexture(texture, faceDataArrays, format, type, invertY);
                 }
                 texture.isReady = true;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 47 - 47
dist/preview release/babylon.worker.js


+ 23 - 18
dist/preview release/es6.js

@@ -15727,7 +15727,6 @@ var BABYLON;
             var gl = this._gl;
             var texture = new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_CUBERAW);
             texture.isCube = true;
-            texture.generateMipMaps = generateMipMaps;
             texture.format = format;
             texture.type = type;
             if (!this._doNotHandleContextLost) {
@@ -15738,6 +15737,25 @@ var BABYLON;
             if (internalFormat === gl.RGB) {
                 internalFormat = gl.RGBA;
             }
+            // Mipmap generation needs a sized internal format that is both color-renderable and texture-filterable
+            if (textureType === gl.FLOAT && !this._caps.textureFloatLinearFiltering) {
+                generateMipMaps = false;
+                samplingMode = Engine.TEXTURE_NEAREST_SAMPLINGMODE;
+                BABYLON.Tools.Warn("Float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
+            }
+            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
+                generateMipMaps = false;
+                samplingMode = Engine.TEXTURE_NEAREST_SAMPLINGMODE;
+                BABYLON.Tools.Warn("Half float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
+            }
+            else if (textureType === gl.FLOAT && !this._caps.textureFloatRender) {
+                generateMipMaps = false;
+                BABYLON.Tools.Warn("Render to float textures is not supported. Mipmap generation forced to false.");
+            }
+            else if (textureType === gl.HALF_FLOAT && !this._caps.colorBufferFloat) {
+                generateMipMaps = false;
+                BABYLON.Tools.Warn("Render to half float textures is not supported. Mipmap generation forced to false.");
+            }
             var width = size;
             var height = width;
             texture.width = width;
@@ -15756,22 +15774,13 @@ var BABYLON;
             if (data && generateMipMaps) {
                 this._gl.generateMipmap(this._gl.TEXTURE_CUBE_MAP);
             }
-            if (textureType === gl.FLOAT && !this._caps.textureFloatLinearFiltering) {
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
-            }
-            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
-            }
-            else {
-                var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
-                gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
-            }
+            var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
+            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
+            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
+            texture.generateMipMaps = generateMipMaps;
             return texture;
         };
         /**
@@ -15838,10 +15847,6 @@ var BABYLON;
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
                 }
                 else {
-                    texture.generateMipMaps = !noMipmap;
-                    if (type === Engine.TEXTURETYPE_FLOAT && !_this._caps.textureFloatLinearFiltering) {
-                        texture.generateMipMaps = false;
-                    }
                     _this.updateRawCubeTexture(texture, faceDataArrays, format, type, invertY);
                 }
                 texture.isReady = true;

+ 1 - 2
dist/preview release/gui/package.json

@@ -11,9 +11,8 @@
     },
     "main": "babylon.gui.min.js",
     "files": [
-        "babylon.gui.js",
         "babylon.gui.min.js",
-        "babylon.gui.d.ts",
+        "babylon.gui.min.js.map",
         "babylon.gui.module.d.ts",
         "readme.md",
         "package.json"

+ 3 - 0
dist/preview release/inspector/package.json

@@ -12,9 +12,12 @@
     "main": "babylon.inspector.bundle.js",
     "files": [
         "babylon.inspector.bundle.js",
+        "babylon.inspector.bundle.js.map",
+        "babylon.inspector.module.d.ts",
         "readme.md",
         "package.json"
     ],
+    "typings": "babylon.inspector.module.d.ts",
     "keywords": [
         "3D",
         "javascript",

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

@@ -45,6 +45,7 @@ declare module BABYLON {
         facePattern2: RegExp;
         facePattern3: RegExp;
         facePattern4: RegExp;
+        facePattern5: RegExp;
         /**
          * Calls synchronously the MTL file attached to this obj.
          * Load function or importMesh function don't enable to load 2 files in the same time asynchronously.

+ 37 - 1
dist/preview release/loaders/babylon.objFileLoader.js

@@ -231,6 +231,8 @@ var BABYLON;
             this.facePattern3 = /f\s+((([\d]{1,}\/[\d]{1,}\/[\d]{1,}[\s]?){3,})+)/;
             // f vertex//normal vertex//normal vertex//normal ...
             this.facePattern4 = /f\s+((([\d]{1,}\/\/[\d]{1,}[\s]?){3,})+)/;
+            // f -vertex/-uvs/-normal -vertex/-uvs/-normal -vertex/-uvs/-normal ...
+            this.facePattern5 = /f\s+(((-[\d]{1,}\/-[\d]{1,}\/-[\d]{1,}[\s]?){3,})+)/;
         }
         /**
          * Calls synchronously the MTL file attached to this obj.
@@ -413,11 +415,12 @@ var BABYLON;
              * Create triangles from polygons by recursion
              * The best to understand how it works is to draw it in the same time you get the recursion.
              * It is important to notice that a triangle is a polygon
-             * We get 4 patterns of face defined in OBJ File :
+             * We get 5 patterns of face defined in OBJ File :
              * facePattern1 = ["1","2","3","4","5","6"]
              * facePattern2 = ["1/1","2/2","3/3","4/4","5/5","6/6"]
              * facePattern3 = ["1/1/1","2/2/2","3/3/3","4/4/4","5/5/5","6/6/6"]
              * facePattern4 = ["1//1","2//2","3//3","4//4","5//5","6//6"]
+             * facePattern5 = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-4/-4/-4","-5/-5/-5","-6/-6/-6"]
              * Each pattern is divided by the same method
              * @param face Array[String] The indices of elements
              * @param v Integer The variable to increment
@@ -437,6 +440,7 @@ var BABYLON;
                 //Pattern2 => triangle = ["1/1","2/2","3/3","1/1","3/3","4/4"];
                 //Pattern3 => triangle = ["1/1/1","2/2/2","3/3/3","1/1/1","3/3/3","4/4/4"];
                 //Pattern4 => triangle = ["1//1","2//2","3//3","1//1","3//3","4//4"];
+                //Pattern5 => triangle = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-1/-1/-1","-3/-3/-3","-4/-4/-4"];
             };
             /**
              * Create triangles and push the data for each polygon for the pattern 1
@@ -532,6 +536,31 @@ var BABYLON;
                 //Reset variable for the next line
                 triangles = [];
             };
+            /**
+             * Create triangles and push the data for each polygon for the pattern 3
+             * In this pattern we get vertice positions, uvs and normals
+             * @param face
+             * @param v
+             */
+            var setDataForCurrentFaceWithPattern5 = function (face, v) {
+                //Get the indices of triangles for each polygon
+                getTriangles(face, v);
+                for (var k = 0; k < triangles.length; k++) {
+                    //triangle[k] = "-1/-1/-1"
+                    //Split the data for getting position, uv, and normals
+                    var point = triangles[k].split("/"); // ["-1", "-1", "-1"]
+                    // Set position indice
+                    var indicePositionFromObj = positions.length + parseInt(point[0]);
+                    // Set uv indice
+                    var indiceUvsFromObj = uvs.length + parseInt(point[1]);
+                    // Set normal indice
+                    var indiceNormalFromObj = normals.length + parseInt(point[2]);
+                    setData(indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, positions[indicePositionFromObj], uvs[indiceUvsFromObj], normals[indiceNormalFromObj] //Set the vector for each component
+                    );
+                }
+                //Reset variable for the next line
+                triangles = [];
+            };
             var addPreviousObjMesh = function () {
                 //Check if it is not the first mesh. Otherwise we don't have data.
                 if (meshesFromObj.length > 0) {
@@ -604,6 +633,13 @@ var BABYLON;
                     setDataForCurrentFaceWithPattern4(result[1].trim().split(" "), // ["1//1", "2//2", "3//3"]
                     1);
                 }
+                else if ((result = this.facePattern5.exec(line)) !== null) {
+                    //Value of result:
+                    //["f -1/-1/-1 -2/-2/-2 -3/-3/-3", "-1/-1/-1 -2/-2/-2 -3/-3/-3"...]
+                    //Set the data for this face
+                    setDataForCurrentFaceWithPattern5(result[1].trim().split(" "), // ["-1/-1/-1", "-2/-2/-2", "-3/-3/-3"]
+                    1);
+                }
                 else if ((result = this.facePattern2.exec(line)) !== null) {
                     //Value of result:
                     //["f 1/1 2/2 3/3", "1/1 2/2 3/3"...]

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 1 - 0
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -63,6 +63,7 @@ declare module BABYLON {
         facePattern2: RegExp;
         facePattern3: RegExp;
         facePattern4: RegExp;
+        facePattern5: RegExp;
         /**
          * Calls synchronously the MTL file attached to this obj.
          * Load function or importMesh function don't enable to load 2 files in the same time asynchronously.

+ 37 - 1
dist/preview release/loaders/babylonjs.loaders.js

@@ -430,6 +430,8 @@ var BABYLON;
             this.facePattern3 = /f\s+((([\d]{1,}\/[\d]{1,}\/[\d]{1,}[\s]?){3,})+)/;
             // f vertex//normal vertex//normal vertex//normal ...
             this.facePattern4 = /f\s+((([\d]{1,}\/\/[\d]{1,}[\s]?){3,})+)/;
+            // f -vertex/-uvs/-normal -vertex/-uvs/-normal -vertex/-uvs/-normal ...
+            this.facePattern5 = /f\s+(((-[\d]{1,}\/-[\d]{1,}\/-[\d]{1,}[\s]?){3,})+)/;
         }
         /**
          * Calls synchronously the MTL file attached to this obj.
@@ -612,11 +614,12 @@ var BABYLON;
              * Create triangles from polygons by recursion
              * The best to understand how it works is to draw it in the same time you get the recursion.
              * It is important to notice that a triangle is a polygon
-             * We get 4 patterns of face defined in OBJ File :
+             * We get 5 patterns of face defined in OBJ File :
              * facePattern1 = ["1","2","3","4","5","6"]
              * facePattern2 = ["1/1","2/2","3/3","4/4","5/5","6/6"]
              * facePattern3 = ["1/1/1","2/2/2","3/3/3","4/4/4","5/5/5","6/6/6"]
              * facePattern4 = ["1//1","2//2","3//3","4//4","5//5","6//6"]
+             * facePattern5 = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-4/-4/-4","-5/-5/-5","-6/-6/-6"]
              * Each pattern is divided by the same method
              * @param face Array[String] The indices of elements
              * @param v Integer The variable to increment
@@ -636,6 +639,7 @@ var BABYLON;
                 //Pattern2 => triangle = ["1/1","2/2","3/3","1/1","3/3","4/4"];
                 //Pattern3 => triangle = ["1/1/1","2/2/2","3/3/3","1/1/1","3/3/3","4/4/4"];
                 //Pattern4 => triangle = ["1//1","2//2","3//3","1//1","3//3","4//4"];
+                //Pattern5 => triangle = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-1/-1/-1","-3/-3/-3","-4/-4/-4"];
             };
             /**
              * Create triangles and push the data for each polygon for the pattern 1
@@ -731,6 +735,31 @@ var BABYLON;
                 //Reset variable for the next line
                 triangles = [];
             };
+            /**
+             * Create triangles and push the data for each polygon for the pattern 3
+             * In this pattern we get vertice positions, uvs and normals
+             * @param face
+             * @param v
+             */
+            var setDataForCurrentFaceWithPattern5 = function (face, v) {
+                //Get the indices of triangles for each polygon
+                getTriangles(face, v);
+                for (var k = 0; k < triangles.length; k++) {
+                    //triangle[k] = "-1/-1/-1"
+                    //Split the data for getting position, uv, and normals
+                    var point = triangles[k].split("/"); // ["-1", "-1", "-1"]
+                    // Set position indice
+                    var indicePositionFromObj = positions.length + parseInt(point[0]);
+                    // Set uv indice
+                    var indiceUvsFromObj = uvs.length + parseInt(point[1]);
+                    // Set normal indice
+                    var indiceNormalFromObj = normals.length + parseInt(point[2]);
+                    setData(indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, positions[indicePositionFromObj], uvs[indiceUvsFromObj], normals[indiceNormalFromObj] //Set the vector for each component
+                    );
+                }
+                //Reset variable for the next line
+                triangles = [];
+            };
             var addPreviousObjMesh = function () {
                 //Check if it is not the first mesh. Otherwise we don't have data.
                 if (meshesFromObj.length > 0) {
@@ -803,6 +832,13 @@ var BABYLON;
                     setDataForCurrentFaceWithPattern4(result[1].trim().split(" "), // ["1//1", "2//2", "3//3"]
                     1);
                 }
+                else if ((result = this.facePattern5.exec(line)) !== null) {
+                    //Value of result:
+                    //["f -1/-1/-1 -2/-2/-2 -3/-3/-3", "-1/-1/-1 -2/-2/-2 -3/-3/-3"...]
+                    //Set the data for this face
+                    setDataForCurrentFaceWithPattern5(result[1].trim().split(" "), // ["-1/-1/-1", "-2/-2/-2", "-3/-3/-3"]
+                    1);
+                }
                 else if ((result = this.facePattern2.exec(line)) !== null) {
                     //Value of result:
                     //["f 1/1 2/2 3/3", "1/1 2/2 3/3"...]

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 4 - 4
dist/preview release/loaders/babylonjs.loaders.min.js


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

@@ -70,6 +70,7 @@ declare module BABYLON {
         facePattern2: RegExp;
         facePattern3: RegExp;
         facePattern4: RegExp;
+        facePattern5: RegExp;
         /**
          * Calls synchronously the MTL file attached to this obj.
          * Load function or importMesh function don't enable to load 2 files in the same time asynchronously.

+ 77 - 43
dist/preview release/viewer/babylon.viewer.d.ts

@@ -1006,6 +1006,7 @@ declare module BabylonViewer {
 declare module BabylonViewer {
     
     
+    
     export function getConfigurationKey(key: string, configObject: any): any;
     export interface ViewerConfiguration {
             version?: string;
@@ -1054,6 +1055,7 @@ declare module BabylonViewer {
                     minecraft?: boolean;
                     [propName: string]: boolean | undefined;
             };
+            environmentMap?: IEnvironmentMapConfiguration;
             vr?: IVRConfiguration;
             lab?: {
                     flashlight?: boolean | {
@@ -1072,12 +1074,14 @@ declare module BabylonViewer {
                             };
                     };
                     hideLoadingDelay?: number;
+                    /** Deprecated */
                     assetsRootURL?: string;
                     environmentMainColor?: {
                             r: number;
                             g: number;
                             b: number;
                     };
+                    /** Deprecated */
                     environmentMap?: {
                             /**
                                 * Environment map texture path in relative to the asset folder.
@@ -1369,6 +1373,7 @@ declare module BabylonViewer {
     
     
     
+    
     /**
         * This interface describes the structure of the variable sent with the configuration observables of the scene manager.
         * O - the type of object we are dealing with (Light, BABYLON.ArcRotateCamera, BABYLON.Scene, etc')
@@ -1514,6 +1519,7 @@ declare module BabylonViewer {
                 * @param modelConfiguration the configuration to use to reconfigure the models
                 */
             protected _configureVR(vrConfig: IVRConfiguration): void;
+            protected _configureEnvironmentMap(environmentMapConfiguration: IEnvironmentMapConfiguration): any;
             /**
                 * (Re) configure the camera. The camera will only be created once and from this point will only be reconfigured.
                 * @param cameraConfig the new camera configuration
@@ -1652,6 +1658,32 @@ declare module BabylonViewer {
     export * from 'babylonjs-viewer/configuration/interfaces/skyboxConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/templateConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/vrConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/environmentMapConfiguration';
+}
+
+declare module BabylonViewer {
+    export interface IEnvironmentMapConfiguration {
+            /**
+                * Environment map texture path in relative to the asset folder.
+                */
+            texture: string;
+            /**
+                * Default rotation to apply to the environment map.
+                */
+            rotationY: number;
+            /**
+                * Tint level of the main color on the environment map.
+                */
+            tintLevel: number;
+            /**
+                * The environment's main color.
+                */
+            mainColor?: {
+                    r?: number;
+                    g?: number;
+                    b?: number;
+            };
+    }
 }
 
 declare module BabylonViewer {
@@ -2110,49 +2142,51 @@ declare module BabylonViewer {
     
     
     export interface ISceneConfiguration {
-        debug?: boolean;
-        clearColor?: {
-            r: number;
-            g: number;
-            b: number;
-            a: number;
-        };
-        mainColor?: {
-            r?: number;
-            g?: number;
-            b?: number;
-        };
-        imageProcessingConfiguration?: IImageProcessingConfiguration;
-        environmentTexture?: string;
-        colorGrading?: IColorGradingConfiguration;
-        environmentRotationY?: number;
-        /**
-          * Deprecated, please use default rendering pipeline
-          */
-        glow?: boolean | BABYLON.IGlowLayerOptions;
-        disableHdr?: boolean;
-        renderInBackground?: boolean;
-        disableCameraControl?: boolean;
-        animationPropertiesOverride?: {
-            [propName: string]: any;
-        };
-        defaultMaterial?: {
-            materialType: "standard" | "pbr";
-            [propName: string]: any;
-        };
-        flags?: {
-            shadowsEnabled?: boolean;
-            particlesEnabled?: boolean;
-            collisionsEnabled?: boolean;
-            lightsEnabled?: boolean;
-            texturesEnabled?: boolean;
-            lensFlaresEnabled?: boolean;
-            proceduralTexturesEnabled?: boolean;
-            renderTargetsEnabled?: boolean;
-            spritesEnabled?: boolean;
-            skeletonsEnabled?: boolean;
-            audioEnabled?: boolean;
-        };
+            debug?: boolean;
+            clearColor?: {
+                    r: number;
+                    g: number;
+                    b: number;
+                    a: number;
+            };
+            /** Deprecated, use environmentMap.mainColor instead. */
+            mainColor?: {
+                    r?: number;
+                    g?: number;
+                    b?: number;
+            };
+            imageProcessingConfiguration?: IImageProcessingConfiguration;
+            environmentTexture?: string;
+            colorGrading?: IColorGradingConfiguration;
+            environmentRotationY?: number;
+            /**
+                * Deprecated, please use default rendering pipeline
+                */
+            glow?: boolean | BABYLON.IGlowLayerOptions;
+            disableHdr?: boolean;
+            renderInBackground?: boolean;
+            disableCameraControl?: boolean;
+            animationPropertiesOverride?: {
+                    [propName: string]: any;
+            };
+            defaultMaterial?: {
+                    materialType: "standard" | "pbr";
+                    [propName: string]: any;
+            };
+            flags?: {
+                    shadowsEnabled?: boolean;
+                    particlesEnabled?: boolean;
+                    collisionsEnabled?: boolean;
+                    lightsEnabled?: boolean;
+                    texturesEnabled?: boolean;
+                    lensFlaresEnabled?: boolean;
+                    proceduralTexturesEnabled?: boolean;
+                    renderTargetsEnabled?: boolean;
+                    spritesEnabled?: boolean;
+                    skeletonsEnabled?: boolean;
+                    audioEnabled?: boolean;
+            };
+            assetsRootURL?: string;
     }
 }
 

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 58 - 58
dist/preview release/viewer/babylon.viewer.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 290 - 195
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -1006,6 +1006,7 @@ declare module 'babylonjs-viewer/configuration' {
 declare module 'babylonjs-viewer/configuration/configuration' {
     import { EngineOptions } from 'babylonjs';
     import { ICameraConfiguration, IDefaultRenderingPipelineConfiguration, IGroundConfiguration, ILightConfiguration, IModelConfiguration, IObserversConfiguration, ISceneConfiguration, ISceneOptimizerConfiguration, ISkyboxConfiguration, ITemplateConfiguration, IVRConfiguration } from 'babylonjs-viewer/configuration/interfaces';
+    import { IEnvironmentMapConfiguration } from 'babylonjs-viewer/configuration/interfaces/environmentMapConfiguration';
     export function getConfigurationKey(key: string, configObject: any): any;
     export interface ViewerConfiguration {
             version?: string;
@@ -1054,6 +1055,7 @@ declare module 'babylonjs-viewer/configuration/configuration' {
                     minecraft?: boolean;
                     [propName: string]: boolean | undefined;
             };
+            environmentMap?: IEnvironmentMapConfiguration;
             vr?: IVRConfiguration;
             lab?: {
                     flashlight?: boolean | {
@@ -1072,12 +1074,14 @@ declare module 'babylonjs-viewer/configuration/configuration' {
                             };
                     };
                     hideLoadingDelay?: number;
+                    /** Deprecated */
                     assetsRootURL?: string;
                     environmentMainColor?: {
                             r: number;
                             g: number;
                             b: number;
                     };
+                    /** Deprecated */
                     environmentMap?: {
                             /**
                                 * Environment map texture path in relative to the asset folder.
@@ -1369,6 +1373,7 @@ declare module 'babylonjs-viewer/managers/sceneManager' {
     import { ViewerLabs } from 'babylonjs-viewer/labs/viewerLabs';
     import { ObservablesManager } from 'babylonjs-viewer/managers/observablesManager';
     import { ConfigurationContainer } from 'babylonjs-viewer/configuration/configurationContainer';
+    import { IEnvironmentMapConfiguration } from 'babylonjs-viewer/configuration/interfaces/environmentMapConfiguration';
     /**
         * This interface describes the structure of the variable sent with the configuration observables of the scene manager.
         * O - the type of object we are dealing with (Light, ArcRotateCamera, Scene, etc')
@@ -1514,6 +1519,7 @@ declare module 'babylonjs-viewer/managers/sceneManager' {
                 * @param modelConfiguration the configuration to use to reconfigure the models
                 */
             protected _configureVR(vrConfig: IVRConfiguration): void;
+            protected _configureEnvironmentMap(environmentMapConfiguration: IEnvironmentMapConfiguration): any;
             /**
                 * (Re) configure the camera. The camera will only be created once and from this point will only be reconfigured.
                 * @param cameraConfig the new camera configuration
@@ -1652,6 +1658,32 @@ declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/skyboxConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/templateConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/vrConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/environmentMapConfiguration';
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/environmentMapConfiguration' {
+    export interface IEnvironmentMapConfiguration {
+            /**
+                * Environment map texture path in relative to the asset folder.
+                */
+            texture: string;
+            /**
+                * Default rotation to apply to the environment map.
+                */
+            rotationY: number;
+            /**
+                * Tint level of the main color on the environment map.
+                */
+            tintLevel: number;
+            /**
+                * The environment's main color.
+                */
+            mainColor?: {
+                    r?: number;
+                    g?: number;
+                    b?: number;
+            };
+    }
 }
 
 declare module 'babylonjs-viewer/templating/eventManager' {
@@ -2110,49 +2142,51 @@ declare module 'babylonjs-viewer/configuration/interfaces/sceneConfiguration' {
     import { IColorGradingConfiguration } from "babylonjs-viewer/configuration/interfaces/colorGradingConfiguration";
     import { IGlowLayerOptions } from "babylonjs";
     export interface ISceneConfiguration {
-        debug?: boolean;
-        clearColor?: {
-            r: number;
-            g: number;
-            b: number;
-            a: number;
-        };
-        mainColor?: {
-            r?: number;
-            g?: number;
-            b?: number;
-        };
-        imageProcessingConfiguration?: IImageProcessingConfiguration;
-        environmentTexture?: string;
-        colorGrading?: IColorGradingConfiguration;
-        environmentRotationY?: number;
-        /**
-          * Deprecated, please use default rendering pipeline
-          */
-        glow?: boolean | IGlowLayerOptions;
-        disableHdr?: boolean;
-        renderInBackground?: boolean;
-        disableCameraControl?: boolean;
-        animationPropertiesOverride?: {
-            [propName: string]: any;
-        };
-        defaultMaterial?: {
-            materialType: "standard" | "pbr";
-            [propName: string]: any;
-        };
-        flags?: {
-            shadowsEnabled?: boolean;
-            particlesEnabled?: boolean;
-            collisionsEnabled?: boolean;
-            lightsEnabled?: boolean;
-            texturesEnabled?: boolean;
-            lensFlaresEnabled?: boolean;
-            proceduralTexturesEnabled?: boolean;
-            renderTargetsEnabled?: boolean;
-            spritesEnabled?: boolean;
-            skeletonsEnabled?: boolean;
-            audioEnabled?: boolean;
-        };
+            debug?: boolean;
+            clearColor?: {
+                    r: number;
+                    g: number;
+                    b: number;
+                    a: number;
+            };
+            /** Deprecated, use environmentMap.mainColor instead. */
+            mainColor?: {
+                    r?: number;
+                    g?: number;
+                    b?: number;
+            };
+            imageProcessingConfiguration?: IImageProcessingConfiguration;
+            environmentTexture?: string;
+            colorGrading?: IColorGradingConfiguration;
+            environmentRotationY?: number;
+            /**
+                * Deprecated, please use default rendering pipeline
+                */
+            glow?: boolean | IGlowLayerOptions;
+            disableHdr?: boolean;
+            renderInBackground?: boolean;
+            disableCameraControl?: boolean;
+            animationPropertiesOverride?: {
+                    [propName: string]: any;
+            };
+            defaultMaterial?: {
+                    materialType: "standard" | "pbr";
+                    [propName: string]: any;
+            };
+            flags?: {
+                    shadowsEnabled?: boolean;
+                    particlesEnabled?: boolean;
+                    collisionsEnabled?: boolean;
+                    lightsEnabled?: boolean;
+                    texturesEnabled?: boolean;
+                    lensFlaresEnabled?: boolean;
+                    proceduralTexturesEnabled?: boolean;
+                    renderTargetsEnabled?: boolean;
+                    spritesEnabled?: boolean;
+                    skeletonsEnabled?: boolean;
+                    audioEnabled?: boolean;
+            };
+            assetsRootURL?: string;
     }
 }
 

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

@@ -7,7 +7,7 @@
 - New GUI 3D controls toolset. [Complete doc + demos](http://doc.babylonjs.com/how_to/gui3d) ([Deltakosh](https://github.com/deltakosh))
 - Added [Environment Texture Tools](https://doc.babylonjs.com/how_to/physically_based_rendering#creating-a-compressed-environment-texture) to reduce the size of the usual .DDS file ([sebavan](http://www.github.com/sebavan))
 - New GUI control: the [Grid](http://doc.babylonjs.com/how_to/gui#grid) ([Deltakosh](https://github.com/deltakosh))
-- Gizmo and GizmoManager classes used to manipulate meshes in a scene. Gizmo types include: position, rotation, scale and bounding box. [Doc](http://doc.babylonjs.com/how_to/gizmo) ([TrevorDev](https://github.com/TrevorDev))
+- Gizmo and GizmoManager classes used to manipulate meshes in a scene. Gizmo types include: position, scale, rotation and bounding box. [Doc](http://doc.babylonjs.com/how_to/gizmo) ([TrevorDev](https://github.com/TrevorDev))
 - New behaviors: PointerDragBehavior, SixDofDragBehavior and MultiPointerScaleBehavior to enable smooth drag and drop/scaling with mouse or 6dof controller on a mesh. [Doc](http://doc.babylonjs.com/how_to/meshbehavior) ([TrevorDev](https://github.com/TrevorDev))
 - Particle system improvements ([Deltakosh](https://github.com/deltakosh))
   - Added a ParticleHelper class to create some pre-configured particle systems in a one-liner method style. [Doc](https://doc.babylonjs.com/How_To/ParticleHelper) ([Deltakosh](https://github.com/deltakosh)) / ([DevChris](https://github.com/yovanoc))
@@ -24,10 +24,13 @@
   - Added support for size gradients. [Doc](https://doc.babylonjs.com/babylon101/particles#size)
   - Added support for life time gradients. [Doc](https://doc.babylonjs.com/babylon101/particles#lifetime)
   - Added support for angular speed gradients. [Doc](https://doc.babylonjs.com/babylon101/particles#rotation)
+  - Added support for noise textures. [Doc](http://doc.babylonjs.com/babylon101/particles#noise-texture)
 - Added SceneComponent to help decoupling Scene from its components. ([sebavan](http://www.github.com/sebavan))
 - Playground can now be used with TypeScript directly!. [Demo](https://www.babylonjs-playground.com/ts.html) ([Deltakosh](https://github.com/deltakosh), [NasimiAsl](https://github.com/NasimiAsl))
 - New GUI control: [InputPassword](https://doc.babylonjs.com/how_to/gui#inputpassword) ([theom](https://github.com/theom))
 - Added dead key support and before key add observable to InputText. [Doc](https://doc.babylonjs.com/how_to/gui#using-onbeforekeyaddobservable-for-extended-keyboard-layouts-and-input-masks)([theom](https://github.com/theom))
+- GUI and Inspector are now ES-Modules ([RaananW](https://github.com/RaananW))
+- Added support for noise procedural textures. [Doc](http://doc.babylonjs.com/how_to/how_to_use_procedural_textures#noise-procedural-texture) ([Deltakosh](https://github.com/deltakosh))
 
 ## Updates
 
@@ -99,6 +102,7 @@
 - The default viewer has a plugin system with which new buttons can be added externally ([RaananW](https://github.com/RaananW))
 - The extended configuration is now the default when not providing the "extended" parameter ([RaananW](https://github.com/RaananW))
 - viewer.updateConfiguration also accepts a URL to download configuration remotely ([RaananW](https://github.com/RaananW))
+- Viewer supports 3D printing on windows 10 ([RaananW](https://github.com/RaananW))
 - The viewer's environment map is using the new .env feature ([RaananW](https://github.com/RaananW))
 
 ### Documentation
@@ -118,7 +122,7 @@
 - Parse geometry when load binary mesh ([SinhNQ](https://github.com/quocsinh))
 - Removing observers during observable notify should not skip over valid observers ([TrevorDev](https://github.com/TrevorDev))
 - Initializing gamepadManager should register the gamepad update events ([TrevorDev](https://github.com/TrevorDev))
-- Do not generate mipmaps for HDRCubeTexture if OES_texture_float_linear isn't supported ([PeapBoy](https://github.com/NicolasBuecher))
+- Do not generate mipmaps for RawCubeTexture if OES_texture_float_linear and/or EXT_color_buffer_float extensions are not supported ([PeapBoy](https://github.com/NicolasBuecher))
 
 ### Core Engine
 

+ 41 - 0
gui/package.json

@@ -0,0 +1,41 @@
+{
+    "name": "babylonjs-gui",
+    "version": "1.0.0",
+    "description": "The js GUI library is an extension you can use to generate interactive user interface.\r It is build on top of the DynamicTexture.",
+    "scripts": {
+        "start:server": "webpack-dev-server",
+        "start:watch": "webpack -w",
+        "build:dev": "webpack",
+        "build:prod": "webpack --mode=production",
+        "test": "echo \"Error: no test specified\" && exit 1"
+    },
+    "repository": {
+        "type": "git",
+        "url": "git+https://github.com/BabylonJS/Babylon.js.git"
+    },
+    "keywords": [
+        "3d",
+        "webgl",
+        "viewer"
+    ],
+    "license": "Apache2",
+    "bugs": {
+        "url": "https://github.com/BabylonJS/Babylon.js/issues"
+    },
+    "homepage": "https://github.com/BabylonJS/Babylon.js#readme",
+    "devDependencies": {
+        "@types/node": "^10.5.2",
+        "clean-webpack-plugin": "^0.1.19",
+        "ts-loader": "^4.0.0",
+        "typescript": "^2.9.2",
+        "webpack": "^4.16.0",
+        "webpack-cli": "^3.0.8",
+        "webpack-dev-server": "^3.1.4"
+    },
+    "peerDependencies": {
+        "babylonjs": ">3.2.0"
+    },
+    "dependencies": {
+        "dts-bundle-webpack": "^1.0.0"
+    }
+}

+ 3 - 3
gui/readme.md

@@ -1,6 +1,6 @@
-# Babylon.js GUI library
-The Babylon.js GUI library is an extension you can use to generate interactive user interface.
+# js GUI library
+The js GUI library is an extension you can use to generate interactive user interface.
 It is build on top of the DynamicTexture.
 
 Documentation: http://doc.babylonjs.com/how_to/gui
-API: http://doc.babylonjs.com/api/modules/babylon.gui
+API: http://doc.babylonjs.com/api/modules/gui

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 587 - 589
gui/src/2D/advancedDynamicTexture.ts


+ 182 - 180
gui/src/2D/controls/button.ts

@@ -1,207 +1,209 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Rectangle } from "./rectangle";
+import { Control } from "./control";
+import { TextBlock } from "./textBlock";
+import { Image } from "./image";
+import { Vector2 } from "babylonjs";
+
+/**
+ * Class used to create 2D buttons
+ */
+export class Button extends Rectangle {
+    /**
+     * Function called to generate a pointer enter animation
+     */
+    public pointerEnterAnimation: () => void;
+    /**
+     * Function called to generate a pointer out animation
+     */
+    public pointerOutAnimation: () => void;
+    /**
+     * Function called to generate a pointer down animation
+     */
+    public pointerDownAnimation: () => void;
+    /**
+     * Function called to generate a pointer up animation
+     */
+    public pointerUpAnimation: () => void;
 
-module BABYLON.GUI {
     /**
-     * Class used to create 2D buttons
+     * Creates a new Button
+     * @param name defines the name of the button
      */
-    export class Button extends Rectangle {    
-        /**
-         * Function called to generate a pointer enter animation
-         */
-        public pointerEnterAnimation: () => void;
-        /**
-         * Function called to generate a pointer out animation
-         */        
-        public pointerOutAnimation: () => void;
-        /**
-         * Function called to generate a pointer down animation
-         */        
-        public pointerDownAnimation: () => void;
-        /**
-         * Function called to generate a pointer up animation
-         */        
-        public pointerUpAnimation: () => void;
-
-        /**
-         * Creates a new Button
-         * @param name defines the name of the button
-         */
-        constructor(public name?: string) {
-            super(name);
-          
-            this.thickness = 1;
-            this.isPointerBlocker = true;
-
-            this.pointerEnterAnimation = () => {
-                this.alpha -= 0.1;
-            }
-
-            this.pointerOutAnimation = () => {
-                this.alpha += 0.1;
-            }    
-
-            this.pointerDownAnimation = () => {
-                this.scaleX -= 0.05;
-                this.scaleY -= 0.05;
-            }
-
-            this.pointerUpAnimation = () => {
-                this.scaleX += 0.05;
-                this.scaleY += 0.05;
-            }                      
+    constructor(public name?: string) {
+        super(name);
+
+        this.thickness = 1;
+        this.isPointerBlocker = true;
+
+        this.pointerEnterAnimation = () => {
+            this.alpha -= 0.1;
         }
 
-        protected _getTypeName(): string {
-            return "Button";
+        this.pointerOutAnimation = () => {
+            this.alpha += 0.1;
         }
 
-        // While being a container, the button behaves like a control.
-        /** @hidden */
-        public _processPicking(x: number, y: number, type: number, pointerId:number, buttonIndex: number): boolean {
-            if (!this.isHitTestVisible || !this.isVisible || this.notRenderable) {
-                return false;
-            }
+        this.pointerDownAnimation = () => {
+            this.scaleX -= 0.05;
+            this.scaleY -= 0.05;
+        }
 
-            if (!super.contains(x, y)) {
-                return false;
-            }
+        this.pointerUpAnimation = () => {
+            this.scaleX += 0.05;
+            this.scaleY += 0.05;
+        }
+    }
 
-            this._processObservables(type, x, y, pointerId, buttonIndex);
+    protected _getTypeName(): string {
+        return "Button";
+    }
 
-            return true;
+    // While being a container, the button behaves like a control.
+    /** @hidden */
+    public _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean {
+        if (!this.isHitTestVisible || !this.isVisible || this.notRenderable) {
+            return false;
         }
 
-        /** @hidden */
-        public _onPointerEnter(target: Control): boolean {
-            if (!super._onPointerEnter(target)) {
-                return false;
-            }
+        if (!super.contains(x, y)) {
+            return false;
+        }
 
-            if (this.pointerEnterAnimation) {
-                this.pointerEnterAnimation();
-            }
+        this._processObservables(type, x, y, pointerId, buttonIndex);
 
-            return true;
-        }
+        return true;
+    }
 
-        /** @hidden */
-        public _onPointerOut(target: Control): void {
-            if (this.pointerOutAnimation) {
-                this.pointerOutAnimation();
-            }
+    /** @hidden */
+    public _onPointerEnter(target: Control): boolean {
+        if (!super._onPointerEnter(target)) {
+            return false;
+        }
 
-            super._onPointerOut(target);
+        if (this.pointerEnterAnimation) {
+            this.pointerEnterAnimation();
         }
 
-        /** @hidden */
-        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
-                return false;
-            }
+        return true;
+    }
 
+    /** @hidden */
+    public _onPointerOut(target: Control): void {
+        if (this.pointerOutAnimation) {
+            this.pointerOutAnimation();
+        }
 
-            if (this.pointerDownAnimation) {
-                this.pointerDownAnimation();
-            }
+        super._onPointerOut(target);
+    }
 
-            return true;
+    /** @hidden */
+    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
+        if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
+            return false;
         }
 
-        /** @hidden */
-        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
-            if (this.pointerUpAnimation) {
-                this.pointerUpAnimation();
-            }
-
-            super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
-        }        
-
-        // Statics
-        /**
-         * Creates a new button made with an image and a text
-         * @param name defines the name of the button
-         * @param text defines the text of the button
-         * @param imageUrl defines the url of the image
-         * @returns a new Button
-         */
-        public static CreateImageButton(name: string, text: string, imageUrl: string): Button {
-            var result = new Button(name);
-
-            // Adding text
-            var textBlock = new BABYLON.GUI.TextBlock(name + "_button", text);
-            textBlock.textWrapping = true;
-            textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
-            textBlock.paddingLeft = "20%";
-            result.addControl(textBlock);   
-
-            // Adding image
-            var iconImage = new BABYLON.GUI.Image(name + "_icon", imageUrl);
-            iconImage.width = "20%";
-            iconImage.stretch = BABYLON.GUI.Image.STRETCH_UNIFORM;
-            iconImage.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
-            result.addControl(iconImage);            
-
-            return result;
-        }
 
-        /**
-         * Creates a new button made with an image
-         * @param name defines the name of the button
-         * @param imageUrl defines the url of the image
-         * @returns a new Button
-         */
-        public static CreateImageOnlyButton(name: string, imageUrl: string): Button {
-            var result = new Button(name);
-
-            // Adding image
-            var iconImage = new BABYLON.GUI.Image(name + "_icon", imageUrl);
-            iconImage.stretch = BABYLON.GUI.Image.STRETCH_FILL;
-            iconImage.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
-            result.addControl(iconImage);            
-
-            return result;
+        if (this.pointerDownAnimation) {
+            this.pointerDownAnimation();
         }
 
-        /**
-         * Creates a new button made with a text
-         * @param name defines the name of the button
-         * @param text defines the text of the button
-         * @returns a new Button
-         */        
-        public static CreateSimpleButton(name: string, text: string): Button {
-            var result = new Button(name);
-
-            // Adding text
-            var textBlock = new BABYLON.GUI.TextBlock(name + "_button", text);
-            textBlock.textWrapping = true;
-            textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
-            result.addControl(textBlock);           
-
-            return result;
-        }
-        
-        /**
-         * Creates a new button made with an image and a centered text
-         * @param name defines the name of the button
-         * @param text defines the text of the button
-         * @param imageUrl defines the url of the image
-         * @returns a new Button
-         */        
-        public static CreateImageWithCenterTextButton(name: string, text: string, imageUrl: string): Button {
-            var result = new Button(name);
-
-            // Adding image
-            var iconImage = new BABYLON.GUI.Image(name + "_icon", imageUrl);
-            iconImage.stretch = BABYLON.GUI.Image.STRETCH_FILL;
-            result.addControl(iconImage);         
-            
-            // Adding text
-            var textBlock = new BABYLON.GUI.TextBlock(name + "_button", text);
-            textBlock.textWrapping = true;
-            textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
-            result.addControl(textBlock);   
-
-            return result;
+        return true;
+    }
+
+    /** @hidden */
+    public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
+        if (this.pointerUpAnimation) {
+            this.pointerUpAnimation();
         }
-    }    
-}
+
+        super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
+    }
+
+    // Statics
+    /**
+     * Creates a new button made with an image and a text
+     * @param name defines the name of the button
+     * @param text defines the text of the button
+     * @param imageUrl defines the url of the image
+     * @returns a new Button
+     */
+    public static CreateImageButton(name: string, text: string, imageUrl: string): Button {
+        var result = new Button(name);
+
+        // Adding text
+        var textBlock = new TextBlock(name + "_button", text);
+        textBlock.textWrapping = true;
+        textBlock.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
+        textBlock.paddingLeft = "20%";
+        result.addControl(textBlock);
+
+        // Adding image
+        var iconImage = new Image(name + "_icon", imageUrl);
+        iconImage.width = "20%";
+        iconImage.stretch = Image.STRETCH_UNIFORM;
+        iconImage.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+        result.addControl(iconImage);
+
+        return result;
+    }
+
+    /**
+     * Creates a new button made with an image
+     * @param name defines the name of the button
+     * @param imageUrl defines the url of the image
+     * @returns a new Button
+     */
+    public static CreateImageOnlyButton(name: string, imageUrl: string): Button {
+        var result = new Button(name);
+
+        // Adding image
+        var iconImage = new Image(name + "_icon", imageUrl);
+        iconImage.stretch = Image.STRETCH_FILL;
+        iconImage.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+        result.addControl(iconImage);
+
+        return result;
+    }
+
+    /**
+     * Creates a new button made with a text
+     * @param name defines the name of the button
+     * @param text defines the text of the button
+     * @returns a new Button
+     */
+    public static CreateSimpleButton(name: string, text: string): Button {
+        var result = new Button(name);
+
+        // Adding text
+        var textBlock = new TextBlock(name + "_button", text);
+        textBlock.textWrapping = true;
+        textBlock.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
+        result.addControl(textBlock);
+
+        return result;
+    }
+
+    /**
+     * Creates a new button made with an image and a centered text
+     * @param name defines the name of the button
+     * @param text defines the text of the button
+     * @param imageUrl defines the url of the image
+     * @returns a new Button
+     */
+    public static CreateImageWithCenterTextButton(name: string, text: string, imageUrl: string): Button {
+        var result = new Button(name);
+
+        // Adding image
+        var iconImage = new Image(name + "_icon", imageUrl);
+        iconImage.stretch = Image.STRETCH_FILL;
+        result.addControl(iconImage);
+
+        // Adding text
+        var textBlock = new TextBlock(name + "_button", text);
+        textBlock.textWrapping = true;
+        textBlock.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
+        result.addControl(textBlock);
+
+        return result;
+    }
+}    

+ 118 - 118
gui/src/2D/controls/checkbox.ts

@@ -1,145 +1,145 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Control } from "./control";
+import { Measure } from "../measure";
+import { Observable, Vector2 } from "babylonjs";
+
+/**
+ * Class used to represent a 2D checkbox
+ */
+export class Checkbox extends Control {
+    private _isChecked = false;
+    private _background = "black";
+    private _checkSizeRatio = 0.8;
+    private _thickness = 1;
+
+    /** Gets or sets border thickness  */
+    public get thickness(): number {
+        return this._thickness;
+    }
+
+    public set thickness(value: number) {
+        if (this._thickness === value) {
+            return;
+        }
+
+        this._thickness = value;
+        this._markAsDirty();
+    }
 
-module BABYLON.GUI {
     /**
-     * Class used to represent a 2D checkbox
+     * Observable raised when isChecked property changes
      */
-    export class Checkbox extends Control {
-        private _isChecked = false;
-        private _background = "black";   
-        private _checkSizeRatio = 0.8;
-        private _thickness = 1;
-        
-        /** Gets or sets border thickness  */
-        public get thickness(): number {
-            return this._thickness;
-        }
-
-        public set thickness(value: number) {
-            if (this._thickness === value) {
-                return;
-            }
+    public onIsCheckedChangedObservable = new Observable<boolean>();
 
-            this._thickness = value;
-            this._markAsDirty();
-        }           
+    /** Gets or sets a value indicating the ratio between overall size and check size */
+    public get checkSizeRatio(): number {
+        return this._checkSizeRatio;
+    }
 
-        /**
-         * Observable raised when isChecked property changes
-         */
-        public onIsCheckedChangedObservable = new Observable<boolean>();
+    public set checkSizeRatio(value: number) {
+        value = Math.max(Math.min(1, value), 0);
 
-        /** Gets or sets a value indicating the ratio between overall size and check size */
-        public get checkSizeRatio(): number {
-            return this._checkSizeRatio;
+        if (this._checkSizeRatio === value) {
+            return;
         }
 
-        public set checkSizeRatio(value: number) {
-            value = Math.max(Math.min(1, value), 0);
+        this._checkSizeRatio = value;
+        this._markAsDirty();
+    }
 
-            if (this._checkSizeRatio === value) {
-                return;
-            }
-
-            this._checkSizeRatio = value;
-            this._markAsDirty();
-        }             
+    /** Gets or sets background color */
+    public get background(): string {
+        return this._background;
+    }
 
-        /** Gets or sets background color */
-        public get background(): string {
-            return this._background;
+    public set background(value: string) {
+        if (this._background === value) {
+            return;
         }
 
-        public set background(value: string) {
-            if (this._background === value) {
-                return;
-            }
+        this._background = value;
+        this._markAsDirty();
+    }
 
-            this._background = value;
-            this._markAsDirty();
-        }     
+    /** Gets or sets a boolean indicating if the checkbox is checked or not */
+    public get isChecked(): boolean {
+        return this._isChecked;
+    }
 
-        /** Gets or sets a boolean indicating if the checkbox is checked or not */
-        public get isChecked(): boolean {
-            return this._isChecked;
+    public set isChecked(value: boolean) {
+        if (this._isChecked === value) {
+            return;
         }
 
-        public set isChecked(value: boolean) {
-            if (this._isChecked === value) {
-                return;
-            }
+        this._isChecked = value;
+        this._markAsDirty();
 
-            this._isChecked = value;
-            this._markAsDirty();
+        this.onIsCheckedChangedObservable.notifyObservers(value);
+    }
 
-            this.onIsCheckedChangedObservable.notifyObservers(value);
-        }                             
+    /**
+     * Creates a new CheckBox
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
+        this.isPointerBlocker = true;
+    }
+
+    protected _getTypeName(): string {
+        return "CheckBox";
+    }
+
+    /** @hidden */
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
+
+        this._applyStates(context);
+        if (this._processMeasures(parentMeasure, context)) {
+            let actualWidth = this._currentMeasure.width - this._thickness;
+            let actualHeight = this._currentMeasure.height - this._thickness;
+
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
+            }
 
-        /**
-         * Creates a new CheckBox
-         * @param name defines the control name
-         */
-        constructor(public name?: string) {
-            super(name);
-            this.isPointerBlocker = true;
-        }
+            context.fillStyle = this._background;
+            context.fillRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2, actualWidth, actualHeight);
 
-        protected _getTypeName(): string {
-            return "CheckBox";
-        }
-        
-        /** @hidden */
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
-
-            this._applyStates(context);
-            if (this._processMeasures(parentMeasure, context)) {
-                let actualWidth = this._currentMeasure.width - this._thickness;
-                let actualHeight = this._currentMeasure.height - this._thickness;
-
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                    context.shadowColor = this.shadowColor;
-                    context.shadowBlur = this.shadowBlur;
-                    context.shadowOffsetX = this.shadowOffsetX;
-                    context.shadowOffsetY = this.shadowOffsetY;
-                }
-                
-                context.fillStyle = this._background;
-                context.fillRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2, actualWidth, actualHeight);   
-
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                    context.shadowBlur = 0;
-                    context.shadowOffsetX = 0;
-                    context.shadowOffsetY = 0;
-                }
-
-                if (this._isChecked) {
-                    context.fillStyle = this.color;
-                    let offsetWidth = actualWidth * this._checkSizeRatio;
-                    let offseHeight = actualHeight * this._checkSizeRatio;
-
-                    context.fillRect(this._currentMeasure.left + this._thickness / 2 + (actualWidth - offsetWidth) / 2, this._currentMeasure.top + this._thickness / 2 + (actualHeight - offseHeight) / 2, offsetWidth, offseHeight);
-                }
-
-                context.strokeStyle = this.color;
-                context.lineWidth = this._thickness;
-
-                context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2, actualWidth, actualHeight);                       
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowBlur = 0;
+                context.shadowOffsetX = 0;
+                context.shadowOffsetY = 0;
             }
-            context.restore();
-        }
 
-        // Events
+            if (this._isChecked) {
+                context.fillStyle = this.color;
+                let offsetWidth = actualWidth * this._checkSizeRatio;
+                let offseHeight = actualHeight * this._checkSizeRatio;
 
-        /** @hidden */
-        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
-                return false;
+                context.fillRect(this._currentMeasure.left + this._thickness / 2 + (actualWidth - offsetWidth) / 2, this._currentMeasure.top + this._thickness / 2 + (actualHeight - offseHeight) / 2, offsetWidth, offseHeight);
             }
 
-            this.isChecked = !this.isChecked;
+            context.strokeStyle = this.color;
+            context.lineWidth = this._thickness;
 
-            return true;
+            context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2, actualWidth, actualHeight);
         }
-    }    
-}
+        context.restore();
+    }
+
+    // Events
+
+    /** @hidden */
+    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
+        if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
+            return false;
+        }
+
+        this.isChecked = !this.isChecked;
+
+        return true;
+    }
+}   

+ 354 - 356
gui/src/2D/controls/colorpicker.ts

@@ -1,430 +1,428 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
-    /** Class used to create color pickers */
-    export class ColorPicker extends Control {
-        private _colorWheelCanvas: HTMLCanvasElement;
-        
-        private _value: Color3 = Color3.Red();
-        private _tmpColor = new Color3();
-
-        private _pointerStartedOnSquare = false;
-        private _pointerStartedOnWheel = false;
-        
-        private _squareLeft = 0;
-        private _squareTop = 0;
-        private _squareSize = 0;
-
-        private _h = 360;
-        private _s = 1;
-        private _v = 1;
-        
-        /**
-         * Observable raised when the value changes
-         */
-        public onValueChangedObservable = new Observable<Color3>();
-
-        /** Gets or sets the color of the color picker */
-        public get value(): Color3 {
-            return this._value;
-        }
+import { Control } from "./control";
+import { Color3, Observable, Vector2 } from "babylonjs";
+import { Measure } from "../measure";
 
-        public set value(value: Color3) {
-            if (this._value.equals(value)) {
-                return;
-            }
+/** Class used to create color pickers */
+export class ColorPicker extends Control {
+    private _colorWheelCanvas: HTMLCanvasElement;
 
-            this._value.copyFrom(value);
+    private _value: Color3 = Color3.Red();
+    private _tmpColor = new Color3();
 
-            this._RGBtoHSV(this._value, this._tmpColor);
-            
-            this._h = this._tmpColor.r;
-            this._s = Math.max(this._tmpColor.g, 0.00001);
-            this._v = Math.max(this._tmpColor.b, 0.00001);
+    private _pointerStartedOnSquare = false;
+    private _pointerStartedOnWheel = false;
 
-            this._markAsDirty();
+    private _squareLeft = 0;
+    private _squareTop = 0;
+    private _squareSize = 0;
 
-            this.onValueChangedObservable.notifyObservers(this._value);
-        }
+    private _h = 360;
+    private _s = 1;
+    private _v = 1;
 
-        /** Gets or sets control width */
-        public set width(value: string | number ) {
-            if (this._width.toString(this._host) === value) {
-                return;
-            }
+    /**
+     * Observable raised when the value changes
+     */
+    public onValueChangedObservable = new Observable<Color3>();
 
-            if (this._width.fromString(value)) {
-                this._height.fromString(value);
-                this._markAsDirty();
-            }
+    /** Gets or sets the color of the color picker */
+    public get value(): Color3 {
+        return this._value;
+    }
+
+    public set value(value: Color3) {
+        if (this._value.equals(value)) {
+            return;
         }
 
-        /** Gets or sets control height */
-        public set height(value: string | number ) {
-            if (this._height.toString(this._host) === value) {
-                return;
-            }
+        this._value.copyFrom(value);
 
-            if (this._height.fromString(value)) {
-                this._width.fromString(value);
-                this._markAsDirty();
-            }
-        }
+        this._RGBtoHSV(this._value, this._tmpColor);
 
-        /** Gets or sets control size */
-        public get size(): string | number {
-            return this.width;
-        }
+        this._h = this._tmpColor.r;
+        this._s = Math.max(this._tmpColor.g, 0.00001);
+        this._v = Math.max(this._tmpColor.b, 0.00001);
+
+        this._markAsDirty();
+
+        this.onValueChangedObservable.notifyObservers(this._value);
+    }
 
-        public set size(value: string | number){
-            this.width = value;
-        }              
-
-        /**
-         * Creates a new ColorPicker
-         * @param name defines the control name
-         */
-        constructor(public name?: string) {
-            super(name);
-            this.value = new BABYLON.Color3(.88, .1, .1);
-            this.size = "200px";
-            this.isPointerBlocker = true;
+    /** Gets or sets control width */
+    public set width(value: string | number) {
+        if (this._width.toString(this._host) === value) {
+            return;
         }
 
-        protected _getTypeName(): string {
-            return "ColorPicker";
-        }        
+        if (this._width.fromString(value)) {
+            this._height.fromString(value);
+            this._markAsDirty();
+        }
+    }
 
-        private _updateSquareProps():void {
-            var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height)*.5;
-            var wheelThickness = radius*.2;
-            var innerDiameter = (radius-wheelThickness)*2;
-            var squareSize = innerDiameter/(Math.sqrt(2));
-            var offset = radius - squareSize*.5;
+    /** Gets or sets control height */
+    public set height(value: string | number) {
+        if (this._height.toString(this._host) === value) {
+            return;
+        }
 
-            this._squareLeft = this._currentMeasure.left + offset;
-            this._squareTop = this._currentMeasure.top + offset;
-            this._squareSize = squareSize;
+        if (this._height.fromString(value)) {
+            this._width.fromString(value);
+            this._markAsDirty();
         }
+    }
+
+    /** Gets or sets control size */
+    public get size(): string | number {
+        return this.width;
+    }
+
+    public set size(value: string | number) {
+        this.width = value;
+    }
+
+    /**
+     * Creates a new ColorPicker
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
+        this.value = new Color3(.88, .1, .1);
+        this.size = "200px";
+        this.isPointerBlocker = true;
+    }
+
+    protected _getTypeName(): string {
+        return "ColorPicker";
+    }
+
+    private _updateSquareProps(): void {
+        var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * .5;
+        var wheelThickness = radius * .2;
+        var innerDiameter = (radius - wheelThickness) * 2;
+        var squareSize = innerDiameter / (Math.sqrt(2));
+        var offset = radius - squareSize * .5;
+
+        this._squareLeft = this._currentMeasure.left + offset;
+        this._squareTop = this._currentMeasure.top + offset;
+        this._squareSize = squareSize;
+    }
+
+    private _drawGradientSquare(hueValue: number, left: number, top: number, width: number, height: number, context: CanvasRenderingContext2D) {
+        var lgh = context.createLinearGradient(left, top, width + left, top);
+        lgh.addColorStop(0, '#fff');
+        lgh.addColorStop(1, 'hsl(' + hueValue + ', 100%, 50%)');
+
+        context.fillStyle = lgh;
+        context.fillRect(left, top, width, height);
+
+        var lgv = context.createLinearGradient(left, top, left, height + top);
+        lgv.addColorStop(0, 'rgba(0,0,0,0)');
+        lgv.addColorStop(1, '#000');
+
+        context.fillStyle = lgv;
+        context.fillRect(left, top, width, height);
+    }
+
+    private _drawCircle(centerX: number, centerY: number, radius: number, context: CanvasRenderingContext2D) {
+        context.beginPath();
+        context.arc(centerX, centerY, radius + 1, 0, 2 * Math.PI, false);
+        context.lineWidth = 3;
+        context.strokeStyle = '#333333';
+        context.stroke();
+        context.beginPath();
+        context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
+        context.lineWidth = 3;
+        context.strokeStyle = '#ffffff';
+        context.stroke();
+    }
+
+    private _createColorWheelCanvas(radius: number, thickness: number): HTMLCanvasElement {
+        var canvas = document.createElement("canvas");
+        canvas.width = radius * 2;
+        canvas.height = radius * 2;
+        var context = <CanvasRenderingContext2D>canvas.getContext("2d");
+        var image = context.getImageData(0, 0, radius * 2, radius * 2);
+        var data = image.data;
+
+        var color = this._tmpColor;
+        var maxDistSq = radius * radius;
+        var innerRadius = radius - thickness;
+        var minDistSq = innerRadius * innerRadius;
+
+        for (var x = -radius; x < radius; x++) {
+            for (var y = -radius; y < radius; y++) {
+
+                var distSq = x * x + y * y;
+
+                if (distSq > maxDistSq || distSq < minDistSq) {
+                    continue;
+                }
 
-        private _drawGradientSquare(hueValue:number, left:number, top:number, width:number, height:number, context: CanvasRenderingContext2D) {
-            var lgh = context.createLinearGradient(left, top, width+left, top);
-            lgh.addColorStop(0, '#fff');
-            lgh.addColorStop(1,  'hsl(' + hueValue + ', 100%, 50%)');
+                var dist = Math.sqrt(distSq);
+                var ang = Math.atan2(y, x);
 
-            context.fillStyle = lgh;
-            context.fillRect(left, top,  width, height);
+                this._HSVtoRGB(ang * 180 / Math.PI + 180, dist / radius, 1, color);
 
-            var lgv = context.createLinearGradient(left, top, left, height+top);
-            lgv.addColorStop(0, 'rgba(0,0,0,0)');
-            lgv.addColorStop(1,  '#000');
+                var index = ((x + radius) + ((y + radius) * 2 * radius)) * 4;
 
-            context.fillStyle = lgv;
-            context.fillRect(left, top, width, height);
-        }
+                data[index] = color.r * 255;
+                data[index + 1] = color.g * 255;
+                data[index + 2] = color.b * 255;
+                var alphaRatio = (dist - innerRadius) / (radius - innerRadius);
 
-        private _drawCircle(centerX:number, centerY:number, radius:number, context: CanvasRenderingContext2D) {
-            context.beginPath();
-            context.arc(centerX, centerY, radius+1, 0, 2 * Math.PI, false);
-            context.lineWidth = 3;
-            context.strokeStyle = '#333333';
-            context.stroke();
-            context.beginPath();
-            context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
-            context.lineWidth = 3;
-            context.strokeStyle = '#ffffff';
-            context.stroke();
-        }
+                //apply less alpha to bigger color pickers
+                var alphaAmount = .2;
+                var maxAlpha = .2;
+                var minAlpha = .04;
+                var lowerRadius = 50;
+                var upperRadius = 150;
+
+                if (radius < lowerRadius) {
+                    alphaAmount = maxAlpha;
+                } else if (radius > upperRadius) {
+                    alphaAmount = minAlpha;
+                } else {
+                    alphaAmount = (minAlpha - maxAlpha) * (radius - lowerRadius) / (upperRadius - lowerRadius) + maxAlpha;
+                }
 
-        private _createColorWheelCanvas(radius:number, thickness:number): HTMLCanvasElement {
-            var canvas = document.createElement("canvas");
-            canvas.width = radius * 2;
-            canvas.height = radius * 2;
-            var context = <CanvasRenderingContext2D>canvas.getContext("2d");
-            var image = context.getImageData(0, 0, radius * 2, radius * 2);
-            var data = image.data;
-            
-            var color = this._tmpColor;
-            var maxDistSq = radius*radius;
-            var innerRadius = radius - thickness;
-            var minDistSq = innerRadius*innerRadius;
-
-            for (var x = -radius; x < radius; x++) {
-                for (var y = -radius; y < radius; y++) {
-                    
-                    var distSq = x*x + y*y;
-                    
-                    if (distSq > maxDistSq || distSq < minDistSq) {
-                        continue;
-                    }
-
-                    var dist = Math.sqrt(distSq);
-                    var ang = Math.atan2(y, x);
-                    
-                    this._HSVtoRGB(ang * 180/Math.PI + 180, dist/radius, 1, color);
-                    
-                    var index = ((x + radius) + ((y + radius)*2*radius)) * 4;
-                    
-                    data[index] = color.r*255;
-                    data[index + 1] = color.g*255;
-                    data[index + 2] = color.b*255;      
-                    var alphaRatio = (dist - innerRadius) / (radius - innerRadius);
-
-                    //apply less alpha to bigger color pickers
-                    var alphaAmount = .2;
-                    var maxAlpha = .2;
-                    var minAlpha = .04;
-                    var lowerRadius = 50;
-                    var upperRadius = 150;
-
-                    if(radius < lowerRadius){
-                        alphaAmount = maxAlpha;
-                    }else if(radius > upperRadius){
-                        alphaAmount = minAlpha;
-                    }else{
-                        alphaAmount = (minAlpha - maxAlpha)*(radius - lowerRadius)/(upperRadius - lowerRadius) + maxAlpha;
-                    }
-                    
-                    var alphaRatio = (dist - innerRadius) / (radius - innerRadius);
-
-                    if (alphaRatio < alphaAmount) {
-                        data[index + 3] = 255 * (alphaRatio / alphaAmount);
-                    } else if (alphaRatio > 1 - alphaAmount) {
-                        data[index + 3] = 255 * (1.0 - ((alphaRatio - (1 - alphaAmount)) / alphaAmount));
-                    } else {
-                        data[index + 3] = 255;
-                    }
+                var alphaRatio = (dist - innerRadius) / (radius - innerRadius);
 
+                if (alphaRatio < alphaAmount) {
+                    data[index + 3] = 255 * (alphaRatio / alphaAmount);
+                } else if (alphaRatio > 1 - alphaAmount) {
+                    data[index + 3] = 255 * (1.0 - ((alphaRatio - (1 - alphaAmount)) / alphaAmount));
+                } else {
+                    data[index + 3] = 255;
                 }
+
             }
+        }
 
-            context.putImageData(image, 0, 0);
+        context.putImageData(image, 0, 0);
 
-            return canvas;
-        }
+        return canvas;
+    }
 
-        private _RGBtoHSV(color:Color3, result:Color3){
-            var r = color.r;
-            var g = color.g;
-            var b = color.b;
-
-            var max = Math.max(r, g, b);
-            var min = Math.min(r, g, b);
-            var h = 0;
-            var s = 0;
-            var v = max;
-            
-            var dm = max - min;
-            
-            if(max !== 0){
-                s = dm / max;
-            }
+    private _RGBtoHSV(color: Color3, result: Color3) {
+        var r = color.r;
+        var g = color.g;
+        var b = color.b;
+
+        var max = Math.max(r, g, b);
+        var min = Math.min(r, g, b);
+        var h = 0;
+        var s = 0;
+        var v = max;
+
+        var dm = max - min;
+
+        if (max !== 0) {
+            s = dm / max;
+        }
 
-            if(max != min) {
-                if(max == r){
-                    h = (g - b) / dm;
-                    if(g < b){
-                        h += 6;
-                    }
-                }else if(max == g){
-                    h = (b - r) / dm + 2;
-                }else if(max == b){
-                    h = (r - g) / dm + 4;
+        if (max != min) {
+            if (max == r) {
+                h = (g - b) / dm;
+                if (g < b) {
+                    h += 6;
                 }
-                h *= 60;
+            } else if (max == g) {
+                h = (b - r) / dm + 2;
+            } else if (max == b) {
+                h = (r - g) / dm + 4;
             }
-            
-            result.r = h;
-            result.g = s;
-            result.b = v;
+            h *= 60;
         }
 
-        private _HSVtoRGB(hue:number, saturation:number, value:number, result:Color3) {
-            var chroma = value * saturation;
-            var h = hue / 60;
-            var x = chroma * (1- Math.abs((h % 2) - 1));
-            var r = 0;
-            var g = 0;
-            var b = 0;
-
-            if (h >= 0 && h <= 1) {
-                r = chroma;
-                g = x;
-            } else if (h >= 1 && h <= 2) {
-                r = x;
-                g = chroma;
-            } else if (h >= 2 && h <= 3) {
-                g = chroma;
-                b = x;
-            } else if (h >= 3 && h <= 4) {
-                g = x;
-                b = chroma;
-            } else if (h >= 4 && h <= 5) {
-                r = x;
-                b = chroma;
-            } else if (h >= 5 && h <= 6) {
-                r = chroma;
-                b = x;
-            }
-            
-            var m = value - chroma;
-            result.set((r+m), (g+m), (b+m));            
+        result.r = h;
+        result.g = s;
+        result.b = v;
+    }
+
+    private _HSVtoRGB(hue: number, saturation: number, value: number, result: Color3) {
+        var chroma = value * saturation;
+        var h = hue / 60;
+        var x = chroma * (1 - Math.abs((h % 2) - 1));
+        var r = 0;
+        var g = 0;
+        var b = 0;
+
+        if (h >= 0 && h <= 1) {
+            r = chroma;
+            g = x;
+        } else if (h >= 1 && h <= 2) {
+            r = x;
+            g = chroma;
+        } else if (h >= 2 && h <= 3) {
+            g = chroma;
+            b = x;
+        } else if (h >= 3 && h <= 4) {
+            g = x;
+            b = chroma;
+        } else if (h >= 4 && h <= 5) {
+            r = x;
+            b = chroma;
+        } else if (h >= 5 && h <= 6) {
+            r = chroma;
+            b = x;
         }
 
-        /** @hidden */
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
+        var m = value - chroma;
+        result.set((r + m), (g + m), (b + m));
+    }
 
-            this._applyStates(context);
-            if (this._processMeasures(parentMeasure, context)) {
+    /** @hidden */
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
 
-                var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height)*.5;
-                var wheelThickness = radius*.2;
-                var left = this._currentMeasure.left;
-                var top = this._currentMeasure.top;
+        this._applyStates(context);
+        if (this._processMeasures(parentMeasure, context)) {
 
-                if(!this._colorWheelCanvas || this._colorWheelCanvas.width != radius*2){
-                    this._colorWheelCanvas = this._createColorWheelCanvas(radius, wheelThickness);
-                }
+            var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * .5;
+            var wheelThickness = radius * .2;
+            var left = this._currentMeasure.left;
+            var top = this._currentMeasure.top;
 
-                this._updateSquareProps();
+            if (!this._colorWheelCanvas || this._colorWheelCanvas.width != radius * 2) {
+                this._colorWheelCanvas = this._createColorWheelCanvas(radius, wheelThickness);
+            }
 
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){                
-                    context.shadowColor = this.shadowColor;
-                    context.shadowBlur = this.shadowBlur;
-                    context.shadowOffsetX = this.shadowOffsetX;
-                    context.shadowOffsetY = this.shadowOffsetY; 
-                    
-                    context.fillRect(this._squareLeft, this._squareTop, this._squareSize, this._squareSize);
-                }
+            this._updateSquareProps();
 
-                context.drawImage(this._colorWheelCanvas, left, top);
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
 
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                    context.shadowBlur = 0;
-                    context.shadowOffsetX = 0;
-                    context.shadowOffsetY = 0;
-                }
+                context.fillRect(this._squareLeft, this._squareTop, this._squareSize, this._squareSize);
+            }
 
-                this._drawGradientSquare(this._h, 
-                                        this._squareLeft,
-                                        this._squareTop,
-                                        this._squareSize, 
-                                        this._squareSize,
-                                        context);
-                
-                var cx = this._squareLeft + this._squareSize*this._s;
-                var cy = this._squareTop + this._squareSize*(1 - this._v);
-                
-                this._drawCircle(cx, cy, radius*.04, context);
-
-                var dist = radius - wheelThickness*.5;
-                cx = left + radius + Math.cos((this._h-180)*Math.PI/180)*dist;
-                cy = top + radius + Math.sin((this._h-180)*Math.PI/180)*dist;
-                this._drawCircle(cx, cy, wheelThickness*.35, context);
+            context.drawImage(this._colorWheelCanvas, left, top);
 
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowBlur = 0;
+                context.shadowOffsetX = 0;
+                context.shadowOffsetY = 0;
             }
-            context.restore();
-        }
 
-        // Events
-        private _pointerIsDown = false;
+            this._drawGradientSquare(this._h,
+                this._squareLeft,
+                this._squareTop,
+                this._squareSize,
+                this._squareSize,
+                context);
 
-        private _updateValueFromPointer(x: number, y:number): void {
-            if(this._pointerStartedOnWheel)
-            {
-                var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height)*.5;
-                var centerX = radius + this._currentMeasure.left;
-                var centerY = radius + this._currentMeasure.top;
-                this._h = Math.atan2(y - centerY, x - centerX)*180/Math.PI + 180;
-            }
-            else if(this._pointerStartedOnSquare)
-            {
-                this._updateSquareProps();
-                this._s = (x - this._squareLeft) / this._squareSize;
-                this._v = 1 - (y - this._squareTop) / this._squareSize;
-                this._s = Math.min(this._s, 1);
-                this._s = Math.max(this._s, 0.00001);
-                this._v = Math.min(this._v, 1);
-                this._v = Math.max(this._v, 0.00001);
-            }
+            var cx = this._squareLeft + this._squareSize * this._s;
+            var cy = this._squareTop + this._squareSize * (1 - this._v);
+
+            this._drawCircle(cx, cy, radius * .04, context);
 
-            this._HSVtoRGB(this._h, this._s, this._v, this._tmpColor);
+            var dist = radius - wheelThickness * .5;
+            cx = left + radius + Math.cos((this._h - 180) * Math.PI / 180) * dist;
+            cy = top + radius + Math.sin((this._h - 180) * Math.PI / 180) * dist;
+            this._drawCircle(cx, cy, wheelThickness * .35, context);
 
-            this.value = this._tmpColor;
         }
+        context.restore();
+    }
 
-        private _isPointOnSquare(coordinates: Vector2):boolean {
+    // Events
+    private _pointerIsDown = false;
+
+    private _updateValueFromPointer(x: number, y: number): void {
+        if (this._pointerStartedOnWheel) {
+            var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * .5;
+            var centerX = radius + this._currentMeasure.left;
+            var centerY = radius + this._currentMeasure.top;
+            this._h = Math.atan2(y - centerY, x - centerX) * 180 / Math.PI + 180;
+        }
+        else if (this._pointerStartedOnSquare) {
             this._updateSquareProps();
+            this._s = (x - this._squareLeft) / this._squareSize;
+            this._v = 1 - (y - this._squareTop) / this._squareSize;
+            this._s = Math.min(this._s, 1);
+            this._s = Math.max(this._s, 0.00001);
+            this._v = Math.min(this._v, 1);
+            this._v = Math.max(this._v, 0.00001);
+        }
 
-            var left = this._squareLeft;
-            var top = this._squareTop;
-            var size = this._squareSize;
+        this._HSVtoRGB(this._h, this._s, this._v, this._tmpColor);
 
-            if(coordinates.x >= left && coordinates.x <= left + size &&
-               coordinates.y >= top && coordinates.y <= top + size){
-                return true;
-            }
+        this.value = this._tmpColor;
+    }
 
-            return false;
+    private _isPointOnSquare(coordinates: Vector2): boolean {
+        this._updateSquareProps();
+
+        var left = this._squareLeft;
+        var top = this._squareTop;
+        var size = this._squareSize;
+
+        if (coordinates.x >= left && coordinates.x <= left + size &&
+            coordinates.y >= top && coordinates.y <= top + size) {
+            return true;
         }
 
-        private _isPointOnWheel(coordinates: Vector2):boolean {
-            var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height)*.5;
-            var centerX = radius + this._currentMeasure.left;
-            var centerY = radius + this._currentMeasure.top;
-            var wheelThickness = radius*.2;
-            var innerRadius = radius-wheelThickness;
-            var radiusSq = radius*radius;
-            var innerRadiusSq = innerRadius*innerRadius;
+        return false;
+    }
 
-            var dx = coordinates.x - centerX;
-            var dy = coordinates.y - centerY;
+    private _isPointOnWheel(coordinates: Vector2): boolean {
+        var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * .5;
+        var centerX = radius + this._currentMeasure.left;
+        var centerY = radius + this._currentMeasure.top;
+        var wheelThickness = radius * .2;
+        var innerRadius = radius - wheelThickness;
+        var radiusSq = radius * radius;
+        var innerRadiusSq = innerRadius * innerRadius;
 
-            var distSq = dx*dx + dy*dy;
+        var dx = coordinates.x - centerX;
+        var dy = coordinates.y - centerY;
 
-            if(distSq <= radiusSq && distSq >= innerRadiusSq){
-                return true;
-            }
+        var distSq = dx * dx + dy * dy;
+
+        if (distSq <= radiusSq && distSq >= innerRadiusSq) {
+            return true;
+        }
 
+        return false;
+    }
+
+    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
+        if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
             return false;
         }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
-                return false;
-            }            
+        this._pointerIsDown = true;
 
-            this._pointerIsDown = true;
+        this._pointerStartedOnSquare = false;
+        this._pointerStartedOnWheel = false;
 
-            this._pointerStartedOnSquare = false;
-            this._pointerStartedOnWheel = false;
+        if (this._isPointOnSquare(coordinates)) {
+            this._pointerStartedOnSquare = true;
+        } else if (this._isPointOnWheel(coordinates)) {
+            this._pointerStartedOnWheel = true;
+        }
 
-            if(this._isPointOnSquare(coordinates)){
-                this._pointerStartedOnSquare = true;
-            }else if(this._isPointOnWheel(coordinates)){
-                this._pointerStartedOnWheel = true;
-            }
+        this._updateValueFromPointer(coordinates.x, coordinates.y);
+        this._host._capturingControl[pointerId] = this;
 
-            this._updateValueFromPointer(coordinates.x, coordinates.y);
-            this._host._capturingControl[pointerId] = this;
+        return true;
+    }
 
-            return true;
+    public _onPointerMove(target: Control, coordinates: Vector2): void {
+        if (this._pointerIsDown) {
+            this._updateValueFromPointer(coordinates.x, coordinates.y);
         }
 
-        public _onPointerMove(target: Control, coordinates: Vector2): void {
-            if (this._pointerIsDown) {
-                this._updateValueFromPointer(coordinates.x, coordinates.y);
-            }
+        super._onPointerMove(target, coordinates);
+    }
 
-            super._onPointerMove(target, coordinates);
-        }
+    public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
+        this._pointerIsDown = false;
 
-        public _onPointerUp (target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
-            this._pointerIsDown = false;
-            
-            delete this._host._capturingControl[pointerId];
-            super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
-        }     
-    }    
-}
+        delete this._host._capturingControl[pointerId];
+        super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
+    }
+}  

+ 261 - 260
gui/src/2D/controls/container.ts

@@ -1,339 +1,340 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
-    /**
-     * Root class for 2D containers
-     * @see http://doc.babylonjs.com/how_to/gui#containers
-     */
-    export class Container extends Control {
-        /** @hidden */
-        protected _children = new Array<Control>();
-        /** @hidden */
-        protected _measureForChildren = Measure.Empty();  
-        /** @hidden */
-        protected _background: string;   
-        /** @hidden */
-        protected _adaptWidthToChildren = false;
-        /** @hidden */
-        protected _adaptHeightToChildren = false;
-
-        /** Gets or sets a boolean indicating if the container should try to adapt to its children height */
-        public get adaptHeightToChildren(): boolean {
-            return this._adaptHeightToChildren;
+import { Control } from "./control";
+import { Measure } from "../measure";
+import { Nullable } from "babylonjs";
+import { AdvancedDynamicTexture } from "../advancedDynamicTexture";
+
+/**
+ * Root class for 2D containers
+ * @see http://doc.babylonjs.com/how_to/gui#containers
+ */
+export class Container extends Control {
+    /** @hidden */
+    protected _children = new Array<Control>();
+    /** @hidden */
+    protected _measureForChildren = Measure.Empty();
+    /** @hidden */
+    protected _background: string;
+    /** @hidden */
+    protected _adaptWidthToChildren = false;
+    /** @hidden */
+    protected _adaptHeightToChildren = false;
+
+    /** Gets or sets a boolean indicating if the container should try to adapt to its children height */
+    public get adaptHeightToChildren(): boolean {
+        return this._adaptHeightToChildren;
+    }
+
+    public set adaptHeightToChildren(value: boolean) {
+        if (this._adaptHeightToChildren === value) {
+            return;
         }
 
-        public set adaptHeightToChildren(value: boolean) {
-            if (this._adaptHeightToChildren === value) {
-                return;
-            }
-
-            this._adaptHeightToChildren = value;
-
-            if (value) {
-                this.height = "100%";
-            }
+        this._adaptHeightToChildren = value;
 
-            this._markAsDirty();
-        }       
-        
-        /** Gets or sets a boolean indicating if the container should try to adapt to its children width */
-        public get adaptWidthToChildren(): boolean {
-            return this._adaptWidthToChildren;
+        if (value) {
+            this.height = "100%";
         }
 
-        public set adaptWidthToChildren(value: boolean) {
-            if (this._adaptWidthToChildren === value) {
-                return;
-            }
+        this._markAsDirty();
+    }
 
-            this._adaptWidthToChildren = value;
+    /** Gets or sets a boolean indicating if the container should try to adapt to its children width */
+    public get adaptWidthToChildren(): boolean {
+        return this._adaptWidthToChildren;
+    }
 
-            if (value) {
-                this.width = "100%";
-            }
+    public set adaptWidthToChildren(value: boolean) {
+        if (this._adaptWidthToChildren === value) {
+            return;
+        }
 
-            this._markAsDirty();
-        }           
+        this._adaptWidthToChildren = value;
 
-        /** Gets or sets background color */
-        public get background(): string {
-            return this._background;
+        if (value) {
+            this.width = "100%";
         }
 
-        public set background(value: string) {
-            if (this._background === value) {
-                return;
-            }
+        this._markAsDirty();
+    }
+
+    /** Gets or sets background color */
+    public get background(): string {
+        return this._background;
+    }
 
-            this._background = value;
-            this._markAsDirty();
-        }  
-
-        /** Gets the list of children */
-        public get children(): Control[] {
-            return this._children;
-        }        
-
-        /**
-         * Creates a new Container
-         * @param name defines the name of the container
-         */
-        constructor(public name?: string) {
-            super(name);
+    public set background(value: string) {
+        if (this._background === value) {
+            return;
         }
 
-        protected _getTypeName(): string {
-            return "Container";
-        }           
-
-        /**
-         * Gets a child using its name
-         * @param name defines the child name to look for
-         * @returns the child control if found
-         */
-        public getChildByName(name: string): Nullable<Control> {
-            for (var child of this.children) {
-                if (child.name === name) {
-                    return child;
-                }
-            }
+        this._background = value;
+        this._markAsDirty();
+    }
 
-            return null;
-        }       
-
-        /**
-         * Gets a child using its type and its name
-         * @param name defines the child name to look for
-         * @param type defines the child type to look for
-         * @returns the child control if found
-         */        
-        public getChildByType(name: string, type: string): Nullable<Control> {
-            for (var child of this.children) {
-                if (child.typeName === type) {
-                    return child;
-                }
-            }
+    /** Gets the list of children */
+    public get children(): Control[] {
+        return this._children;
+    }
 
-            return null;
-        }            
+    /**
+     * Creates a new Container
+     * @param name defines the name of the container
+     */
+    constructor(public name?: string) {
+        super(name);
+    }
 
-        /**
-         * Search for a specific control in children
-         * @param control defines the control to look for
-         * @returns true if the control is in child list
-         */
-        public containsControl(control: Control): boolean {
-            return this.children.indexOf(control) !== -1;
-        }
+    protected _getTypeName(): string {
+        return "Container";
+    }
 
-        /**
-         * Adds a new control to the current container
-         * @param control defines the control to add
-         * @returns the current container
-         */
-        public addControl(control: Nullable<Control>): Container {
-            if (!control) {
-                return this;
+    /**
+     * Gets a child using its name
+     * @param name defines the child name to look for
+     * @returns the child control if found
+     */
+    public getChildByName(name: string): Nullable<Control> {
+        for (var child of this.children) {
+            if (child.name === name) {
+                return child;
             }
+        }
 
-           var index = this._children.indexOf(control);
+        return null;
+    }
 
-            if (index !== -1) {
-                return this;
+    /**
+     * Gets a child using its type and its name
+     * @param name defines the child name to look for
+     * @param type defines the child type to look for
+     * @returns the child control if found
+     */
+    public getChildByType(name: string, type: string): Nullable<Control> {
+        for (var child of this.children) {
+            if (child.typeName === type) {
+                return child;
             }
-            control._link(this, this._host);
+        }
 
-            control._markAllAsDirty();
+        return null;
+    }
 
-            this._reOrderControl(control);
+    /**
+     * Search for a specific control in children
+     * @param control defines the control to look for
+     * @returns true if the control is in child list
+     */
+    public containsControl(control: Control): boolean {
+        return this.children.indexOf(control) !== -1;
+    }
 
-            this._markAsDirty();
+    /**
+     * Adds a new control to the current container
+     * @param control defines the control to add
+     * @returns the current container
+     */
+    public addControl(control: Nullable<Control>): Container {
+        if (!control) {
             return this;
         }
 
-        /**
-         * Removes a control from the current container
-         * @param control defines the control to remove
-         * @returns the current container
-         */        
-        public removeControl(control: Control): Container {
-            var index = this._children.indexOf(control);
+        var index = this._children.indexOf(control);
 
-            if (index !== -1) {
-                this._children.splice(index, 1);
+        if (index !== -1) {
+            return this;
+        }
+        control._link(this, this._host);
 
-                control.parent = null;
-            }
+        control._markAllAsDirty();
 
-            control.linkWithMesh(null);
+        this._reOrderControl(control);
 
-            if (this._host) {
-                this._host._cleanControlAfterRemoval(control);
-            }
+        this._markAsDirty();
+        return this;
+    }
 
-            this._markAsDirty();
-            return this;
+    /**
+     * Removes a control from the current container
+     * @param control defines the control to remove
+     * @returns the current container
+     */
+    public removeControl(control: Control): Container {
+        var index = this._children.indexOf(control);
+
+        if (index !== -1) {
+            this._children.splice(index, 1);
+
+            control.parent = null;
         }
 
-        /** @hidden */
-        public _reOrderControl(control: Control): void {
-            this.removeControl(control);
+        control.linkWithMesh(null);
 
-            for (var index = 0; index < this._children.length; index++) {
-                if (this._children[index].zIndex > control.zIndex) {
-                    this._children.splice(index, 0, control);
-                    return;
-                }
-            }
+        if (this._host) {
+            this._host._cleanControlAfterRemoval(control);
+        }
 
-            this._children.push(control);
+        this._markAsDirty();
+        return this;
+    }
 
-            control.parent = this;
+    /** @hidden */
+    public _reOrderControl(control: Control): void {
+        this.removeControl(control);
 
-            this._markAsDirty();
+        for (var index = 0; index < this._children.length; index++) {
+            if (this._children[index].zIndex > control.zIndex) {
+                this._children.splice(index, 0, control);
+                return;
+            }
         }
 
-        /** @hidden */       
-        public _markMatrixAsDirty(): void {
-            super._markMatrixAsDirty();
+        this._children.push(control);
 
-            for (var index = 0; index < this._children.length; index++) {
-                this._children[index]._markMatrixAsDirty();
-            }
+        control.parent = this;
+
+        this._markAsDirty();
+    }
+
+    /** @hidden */
+    public _markMatrixAsDirty(): void {
+        super._markMatrixAsDirty();
+
+        for (var index = 0; index < this._children.length; index++) {
+            this._children[index]._markMatrixAsDirty();
         }
+    }
 
-        /** @hidden */ 
-        public _markAllAsDirty(): void {
-            super._markAllAsDirty();
+    /** @hidden */
+    public _markAllAsDirty(): void {
+        super._markAllAsDirty();
 
-            for (var index = 0; index < this._children.length; index++) {
-                this._children[index]._markAllAsDirty();
-            }
+        for (var index = 0; index < this._children.length; index++) {
+            this._children[index]._markAllAsDirty();
         }
+    }
+
+    /** @hidden */
+    protected _localDraw(context: CanvasRenderingContext2D): void {
+        if (this._background) {
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
+            }
 
-        /** @hidden */ 
-        protected _localDraw(context: CanvasRenderingContext2D): void {
-            if (this._background) {
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                    context.shadowColor = this.shadowColor;
-                    context.shadowBlur = this.shadowBlur;
-                    context.shadowOffsetX = this.shadowOffsetX;
-                    context.shadowOffsetY = this.shadowOffsetY;
-                }
-                
-                context.fillStyle = this._background;
-                context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                    context.shadowBlur = 0;
-                    context.shadowOffsetX = 0;
-                    context.shadowOffsetY = 0;
-                }
+            context.fillStyle = this._background;
+            context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowBlur = 0;
+                context.shadowOffsetX = 0;
+                context.shadowOffsetY = 0;
             }
         }
+    }
 
-        /** @hidden */ 
-        public _link(root: Nullable<Container>, host: AdvancedDynamicTexture): void {
-            super._link(root, host);
+    /** @hidden */
+    public _link(root: Nullable<Container>, host: AdvancedDynamicTexture): void {
+        super._link(root, host);
 
-            for (var child of this._children) {
-                child._link(root, host);
-            }
+        for (var child of this._children) {
+            child._link(root, host);
         }
+    }
 
-        /** @hidden */ 
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {      
-            if (!this.isVisible || this.notRenderable) {
-                return;
-            }
-            context.save();
-           
-            this._applyStates(context);
+    /** @hidden */
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        if (!this.isVisible || this.notRenderable) {
+            return;
+        }
+        context.save();
 
-            if (this._processMeasures(parentMeasure, context)) {
-                this._localDraw(context);
+        this._applyStates(context);
 
-                this._clipForChildren(context);
+        if (this._processMeasures(parentMeasure, context)) {
+            this._localDraw(context);
 
-                let computedWidth = -1;
-                let computedHeight = -1;
+            this._clipForChildren(context);
 
-                for (var child of this._children) {
-                    if (child.isVisible && !child.notRenderable) {
-                        child._tempParentMeasure.copyFrom(this._measureForChildren);
-                        child._draw(this._measureForChildren, context);
+            let computedWidth = -1;
+            let computedHeight = -1;
 
-                        if (child.onAfterDrawObservable.hasObservers()) {
-                            child.onAfterDrawObservable.notifyObservers(child);
-                        }
+            for (var child of this._children) {
+                if (child.isVisible && !child.notRenderable) {
+                    child._tempParentMeasure.copyFrom(this._measureForChildren);
+                    child._draw(this._measureForChildren, context);
 
-                        if (this.adaptWidthToChildren && child._width.isPixel) {
-                            computedWidth = Math.max(computedWidth, child._currentMeasure.width);
-                        }
-                        if (this.adaptHeightToChildren && child._height.isPixel) {
-                            computedHeight = Math.max(computedHeight, child._currentMeasure.height);
-                        }                        
+                    if (child.onAfterDrawObservable.hasObservers()) {
+                        child.onAfterDrawObservable.notifyObservers(child);
                     }
-                }
 
-                if (this.adaptWidthToChildren && computedWidth >= 0) {
-                    this.width = computedWidth + "px";
+                    if (this.adaptWidthToChildren && child._width.isPixel) {
+                        computedWidth = Math.max(computedWidth, child._currentMeasure.width);
+                    }
+                    if (this.adaptHeightToChildren && child._height.isPixel) {
+                        computedHeight = Math.max(computedHeight, child._currentMeasure.height);
+                    }
                 }
-                if (this.adaptHeightToChildren && computedHeight >= 0) {
-                    this.height = computedHeight + "px";
-                }                
             }
-            context.restore();
 
-            if (this.onAfterDrawObservable.hasObservers()) {
-                this.onAfterDrawObservable.notifyObservers(this);
+            if (this.adaptWidthToChildren && computedWidth >= 0) {
+                this.width = computedWidth + "px";
+            }
+            if (this.adaptHeightToChildren && computedHeight >= 0) {
+                this.height = computedHeight + "px";
             }
         }
+        context.restore();
 
-        /** @hidden */ 
-        public _processPicking(x: number, y: number, type: number, pointerId:number, buttonIndex: number): boolean {
-            if (!this.isVisible || this.notRenderable) {
-                return false;
-            }
+        if (this.onAfterDrawObservable.hasObservers()) {
+            this.onAfterDrawObservable.notifyObservers(this);
+        }
+    }
 
-            if (!super.contains(x, y)) {
-                return false;
-            }
+    /** @hidden */
+    public _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean {
+        if (!this.isVisible || this.notRenderable) {
+            return false;
+        }
 
-            // Checking backwards to pick closest first
-            for (var index = this._children.length - 1; index >= 0; index--) {
-                var child = this._children[index];
-                if (child._processPicking(x, y, type, pointerId, buttonIndex)) {
-                    return true;
-                }
-            }
+        if (!super.contains(x, y)) {
+            return false;
+        }
 
-            if (!this.isHitTestVisible) {
-                return false;
+        // Checking backwards to pick closest first
+        for (var index = this._children.length - 1; index >= 0; index--) {
+            var child = this._children[index];
+            if (child._processPicking(x, y, type, pointerId, buttonIndex)) {
+                return true;
             }
-
-            return this._processObservables(type, x, y, pointerId, buttonIndex);
         }
 
-        /** @hidden */ 
-        protected _clipForChildren(context: CanvasRenderingContext2D): void {
-            // DO nothing
+        if (!this.isHitTestVisible) {
+            return false;
         }
 
-        /** @hidden */ 
-        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
-            super._additionalProcessing(parentMeasure, context);
+        return this._processObservables(type, x, y, pointerId, buttonIndex);
+    }
 
-            this._measureForChildren.copyFrom(this._currentMeasure);
-        }
+    /** @hidden */
+    protected _clipForChildren(context: CanvasRenderingContext2D): void {
+        // DO nothing
+    }
 
-        /** Releases associated resources */
-        public dispose() {
-            super.dispose();
+    /** @hidden */
+    protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        super._additionalProcessing(parentMeasure, context);
 
-            for (var control of this._children) {
-                control.dispose();
-            }
+        this._measureForChildren.copyFrom(this._currentMeasure);
+    }
+
+    /** Releases associated resources */
+    public dispose() {
+        super.dispose();
+
+        for (var control of this._children) {
+            control.dispose();
         }
-    }    
-}
+    }
+}   

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1135 - 1159
gui/src/2D/controls/control.ts


+ 71 - 71
gui/src/2D/controls/ellipse.ts

@@ -1,87 +1,87 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
-    /** Class used to create 2D ellipse containers */
-    export class Ellipse extends Container {
-        private _thickness = 1;       
-        
-        /** Gets or sets border thickness */
-        public get thickness(): number {
-            return this._thickness;
+import { Container } from "./container";
+import { Control } from "./control";
+import { Measure } from "../measure";
+
+/** Class used to create 2D ellipse containers */
+export class Ellipse extends Container {
+    private _thickness = 1;
+
+    /** Gets or sets border thickness */
+    public get thickness(): number {
+        return this._thickness;
+    }
+
+    public set thickness(value: number) {
+        if (this._thickness === value) {
+            return;
         }
 
-        public set thickness(value: number) {
-            if (this._thickness === value) {
-                return;
-            }
-
-            this._thickness = value;
-            this._markAsDirty();
-        }                
-     
-        /**
-         * Creates a new Ellipse
-         * @param name defines the control name
-         */
-        constructor(public name?: string) {
-            super(name);
+        this._thickness = value;
+        this._markAsDirty();
+    }
+
+    /**
+     * Creates a new Ellipse
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
+    }
+
+    protected _getTypeName(): string {
+        return "Ellipse";
+    }
+
+    protected _localDraw(context: CanvasRenderingContext2D): void {
+        context.save();
+
+        if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+            context.shadowColor = this.shadowColor;
+            context.shadowBlur = this.shadowBlur;
+            context.shadowOffsetX = this.shadowOffsetX;
+            context.shadowOffsetY = this.shadowOffsetY;
         }
 
-        protected _getTypeName(): string {
-            return "Ellipse";
-        }              
-
-        protected _localDraw(context: CanvasRenderingContext2D): void {
-            context.save();
+        Control.drawEllipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2,
+            this._currentMeasure.width / 2 - this._thickness / 2, this._currentMeasure.height / 2 - this._thickness / 2, context);
 
-            if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                context.shadowColor = this.shadowColor;
-                context.shadowBlur = this.shadowBlur;
-                context.shadowOffsetX = this.shadowOffsetX;
-                context.shadowOffsetY = this.shadowOffsetY;
-            }
+        if (this._background) {
+            context.fillStyle = this._background;
 
-            Control.drawEllipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, 
-                            this._currentMeasure.width / 2 - this._thickness / 2, this._currentMeasure.height / 2 - this._thickness / 2, context);
+            context.fill();
+        }
 
-            if (this._background) {
-                context.fillStyle = this._background;
+        if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+            context.shadowBlur = 0;
+            context.shadowOffsetX = 0;
+            context.shadowOffsetY = 0;
+        }
 
-                context.fill();
+        if (this._thickness) {
+            if (this.color) {
+                context.strokeStyle = this.color;
             }
+            context.lineWidth = this._thickness;
 
-            if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                context.shadowBlur = 0;
-                context.shadowOffsetX = 0;
-                context.shadowOffsetY = 0;
-            }
+            context.stroke();
+        }
 
-            if (this._thickness) {
-                if (this.color) {
-                    context.strokeStyle = this.color;
-                }
-                context.lineWidth = this._thickness;
+        context.restore();
+    }
 
-                context.stroke();
-            }
-        
-            context.restore();
-        }
+    protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        super._additionalProcessing(parentMeasure, context);
 
-        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
-            super._additionalProcessing(parentMeasure, context);
+        this._measureForChildren.width -= 2 * this._thickness;
+        this._measureForChildren.height -= 2 * this._thickness;
+        this._measureForChildren.left += this._thickness;
+        this._measureForChildren.top += this._thickness;
+    }
 
-            this._measureForChildren.width -= 2 * this._thickness;
-            this._measureForChildren.height -= 2 * this._thickness;
-            this._measureForChildren.left += this._thickness;
-            this._measureForChildren.top += this._thickness;            
-        }
+    protected _clipForChildren(context: CanvasRenderingContext2D) {
 
-       protected _clipForChildren(context: CanvasRenderingContext2D) {
+        Control.drawEllipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, this._currentMeasure.width / 2, this._currentMeasure.height / 2, context);
 
-            Control.drawEllipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, this._currentMeasure.width / 2, this._currentMeasure.height / 2, context);
-            
-            context.clip();
-        }
-    }    
-}
+        context.clip();
+    }
+}   

+ 277 - 276
gui/src/2D/controls/grid.ts

@@ -1,350 +1,351 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Container } from "./container";
+import { ValueAndUnit } from "../valueAndUnit";
+import { Control } from "./control";
+import { Measure } from "../measure";
+
+/**
+ * Class used to create a 2D grid container
+ */
+export class Grid extends Container {
+    private _rowDefinitions = new Array<ValueAndUnit>();
+    private _columnDefinitions = new Array<ValueAndUnit>();
+    private _cells: { [key: string]: Container } = {};
+    private _childControls = new Array<Control>();
+
+    /** Gets the list of children */
+    public get children(): Control[] {
+        return this._childControls;
+    }
 
-module BABYLON.GUI {
     /**
-     * Class used to create a 2D grid container
+     * Adds a new row to the grid
+     * @param height defines the height of the row (either in pixel or a value between 0 and 1)
+     * @param isPixel defines if the height is expressed in pixel (or in percentage)
+     * @returns the current grid
      */
-    export class Grid extends Container {
-        private _rowDefinitions = new Array<ValueAndUnit>();
-        private _columnDefinitions = new Array<ValueAndUnit>();
-        private _cells: {[key: string]:Container} = {};
-        private _childControls = new Array<Control>();
-
-        /** Gets the list of children */
-        public get children(): Control[] {
-            return this._childControls;
-        }             
-
-        /**
-         * Adds a new row to the grid
-         * @param height defines the height of the row (either in pixel or a value between 0 and 1)
-         * @param isPixel defines if the height is expressed in pixel (or in percentage)
-         * @returns the current grid
-         */
-        public addRowDefinition(height: number, isPixel = false): Grid {
-            this._rowDefinitions.push(new ValueAndUnit(height, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE));
-
-            this._markAsDirty();
+    public addRowDefinition(height: number, isPixel = false): Grid {
+        this._rowDefinitions.push(new ValueAndUnit(height, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE));
 
-            return this;
-        }
+        this._markAsDirty();
 
-        /**
-         * Adds a new column to the grid
-         * @param width defines the width of the column (either in pixel or a value between 0 and 1)
-         * @param isPixel defines if the width is expressed in pixel (or in percentage)
-         * @returns the current grid
-         */
-        public addColumnDefinition(width: number, isPixel = false): Grid {
-            this._columnDefinitions.push(new ValueAndUnit(width, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE));
-            
-            this._markAsDirty();
+        return this;
+    }
 
-            return this;
-        }     
-
-        /**
-         * Update a row definition
-         * @param index defines the index of the row to update
-         * @param height defines the height of the row (either in pixel or a value between 0 and 1)
-         * @param isPixel defines if the weight is expressed in pixel (or in percentage)
-         * @returns the current grid
-         */
-        public setRowDefinition(index: number, height: number, isPixel = false): Grid {
-            if (index < 0 || index >= this._rowDefinitions.length) {
-                return this;
-            }
+    /**
+     * Adds a new column to the grid
+     * @param width defines the width of the column (either in pixel or a value between 0 and 1)
+     * @param isPixel defines if the width is expressed in pixel (or in percentage)
+     * @returns the current grid
+     */
+    public addColumnDefinition(width: number, isPixel = false): Grid {
+        this._columnDefinitions.push(new ValueAndUnit(width, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE));
 
-            this._rowDefinitions[index] = new ValueAndUnit(height,isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE);
+        this._markAsDirty();
 
-            this._markAsDirty();
+        return this;
+    }
 
+    /**
+     * Update a row definition
+     * @param index defines the index of the row to update
+     * @param height defines the height of the row (either in pixel or a value between 0 and 1)
+     * @param isPixel defines if the weight is expressed in pixel (or in percentage)
+     * @returns the current grid
+     */
+    public setRowDefinition(index: number, height: number, isPixel = false): Grid {
+        if (index < 0 || index >= this._rowDefinitions.length) {
             return this;
         }
 
-        /**
-         * Update a column definition
-         * @param index defines the index of the column to update
-         * @param width defines the width of the column (either in pixel or a value between 0 and 1)
-         * @param isPixel defines if the width is expressed in pixel (or in percentage)
-         * @returns the current grid
-         */
-        public setColumnDefinition(index: number, width: number, isPixel = false): Grid {
-            if (index < 0 || index >= this._columnDefinitions.length) {
-                return this;
-            }
+        this._rowDefinitions[index] = new ValueAndUnit(height, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE);
 
-            this._columnDefinitions[index] = new ValueAndUnit(width, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE);
+        this._markAsDirty();
 
-            this._markAsDirty();
+        return this;
+    }
 
+    /**
+     * Update a column definition
+     * @param index defines the index of the column to update
+     * @param width defines the width of the column (either in pixel or a value between 0 and 1)
+     * @param isPixel defines if the width is expressed in pixel (or in percentage)
+     * @returns the current grid
+     */
+    public setColumnDefinition(index: number, width: number, isPixel = false): Grid {
+        if (index < 0 || index >= this._columnDefinitions.length) {
             return this;
-        }        
+        }
 
-        private _removeCell(cell: Container, key: string) {
-            if (!cell) {
-                return;
-            }
+        this._columnDefinitions[index] = new ValueAndUnit(width, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE);
+
+        this._markAsDirty();
+
+        return this;
+    }
+
+    private _removeCell(cell: Container, key: string) {
+        if (!cell) {
+            return;
+        }
 
-            super.removeControl(cell);
+        super.removeControl(cell);
 
-            for (var control of cell.children) {
-                let childIndex = this._childControls.indexOf(control);
+        for (var control of cell.children) {
+            let childIndex = this._childControls.indexOf(control);
 
-                if (childIndex !== -1) {
-                    this._childControls.splice(childIndex, 1);
-                }
+            if (childIndex !== -1) {
+                this._childControls.splice(childIndex, 1);
             }
+        }
+
+        delete this._cells[key];
+    }
 
-            delete this._cells[key];
+    private _offsetCell(previousKey: string, key: string) {
+        if (!this._cells[key]) {
+            return;
         }
 
-        private _offsetCell(previousKey: string, key: string) {
-            if (!this._cells[key]) {
-                return;
-            }
+        this._cells[previousKey] = this._cells[key];
 
-            this._cells[previousKey] = this._cells[key];
+        for (var control of this._cells[previousKey].children) {
+            control._tag = previousKey;
+        }
 
-            for (var control of this._cells[previousKey].children) {
-                control._tag = previousKey;
-            } 
+        delete this._cells[key];
+    }
 
-            delete this._cells[key];
+    /**
+     * Remove a column definition at specified index
+     * @param index defines the index of the column to remove
+     * @returns the current grid
+     */
+    public removeColumnDefinition(index: number): Grid {
+        if (index < 0 || index >= this._columnDefinitions.length) {
+            return this;
         }
 
-        /**
-         * Remove a column definition at specified index
-         * @param index defines the index of the column to remove
-         * @returns the current grid
-         */
-        public removeColumnDefinition(index: number): Grid {
-            if (index < 0 || index >= this._columnDefinitions.length) {
-                return this;
-            }
+        for (var x = 0; x < this._rowDefinitions.length; x++) {
+            let key = `${x}:${index}`;
+            let cell = this._cells[key];
+
+            this._removeCell(cell, key);
+        }
 
-            for (var x = 0; x < this._rowDefinitions.length; x++) {
-                let key = `${x}:${index}`;
-                let cell = this._cells[key];
+        for (var x = 0; x < this._rowDefinitions.length; x++) {
+            for (var y = index + 1; y < this._columnDefinitions.length; y++) {
+                let previousKey = `${x}:${y - 1}`;
+                let key = `${x}:${y}`;
 
-                this._removeCell(cell, key);
+                this._offsetCell(previousKey, key);
             }
+        }
 
-            for (var x = 0; x < this._rowDefinitions.length; x++) {
-                for (var y = index + 1; y < this._columnDefinitions.length; y++) {
-                    let previousKey = `${x}:${y - 1}`;
-                    let key = `${x}:${y}`;
+        this._columnDefinitions.splice(index, 1);
 
-                    this._offsetCell(previousKey, key);
-                }
-            }
-            
-            this._columnDefinitions.splice(index, 1);
+        this._markAsDirty();
 
-            this._markAsDirty();
+        return this;
+    }
 
+    /**
+     * Remove a row definition at specified index
+     * @param index defines the index of the row to remove
+     * @returns the current grid
+     */
+    public removeRowDefinition(index: number): Grid {
+        if (index < 0 || index >= this._rowDefinitions.length) {
             return this;
         }
 
-        /**
-         * Remove a row definition at specified index
-         * @param index defines the index of the row to remove
-         * @returns the current grid
-         */
-        public removeRowDefinition(index: number): Grid {
-            if (index < 0 || index >= this._rowDefinitions.length) {
-                return this;
-            }
+        for (var y = 0; y < this._columnDefinitions.length; y++) {
+            let key = `${index}:${y}`;
+            let cell = this._cells[key];
 
-            for (var y = 0; y < this._columnDefinitions.length; y++) {
-                let key = `${index}:${y}`;
-                let cell = this._cells[key];
+            this._removeCell(cell, key);
+        }
 
-                this._removeCell(cell, key);
+        for (var y = 0; y < this._columnDefinitions.length; y++) {
+            for (var x = index + 1; x < this._rowDefinitions.length; x++) {
+                let previousKey = `${x - 1}:${y}`;
+                let key = `${x}:${y}`;
+
+                this._offsetCell(previousKey, key);
             }
+        }
 
-            for (var y = 0; y < this._columnDefinitions.length; y++) {
-                for (var x = index + 1; x < this._rowDefinitions.length; x++) {
-                    let previousKey = `${x - 1}:${y}`;
-                    let key = `${x}:${y}`;
+        this._rowDefinitions.splice(index, 1);
 
-                    this._offsetCell(previousKey, key);
-                }
-            }
-            
-            this._rowDefinitions.splice(index, 1);
+        this._markAsDirty();
 
-            this._markAsDirty();
+        return this;
+    }
 
-            return this;
+    /**
+     * Adds a new control to the current grid
+     * @param control defines the control to add
+     * @param row defines the row where to add the control (0 by default)
+     * @param column defines the column where to add the control (0 by default)
+     * @returns the current grid
+     */
+    public addControl(control: Control, row: number = 0, column: number = 0): Grid {
+        if (this._rowDefinitions.length === 0) {
+            // Add default row definition
+            this.addRowDefinition(1, false);
         }
 
-        /**
-         * Adds a new control to the current grid
-         * @param control defines the control to add
-         * @param row defines the row where to add the control (0 by default)
-         * @param column defines the column where to add the control (0 by default)
-         * @returns the current grid
-         */
-        public addControl(control: Control, row: number = 0, column: number = 0): Grid {
-            if (this._rowDefinitions.length === 0) {
-                // Add default row definition
-                this.addRowDefinition(1, false);
-            }
+        if (this._columnDefinitions.length === 0) {
+            // Add default column definition
+            this.addColumnDefinition(1, false);
+        }
 
-            if (this._columnDefinitions.length === 0) {
-                // Add default column definition
-                this.addColumnDefinition(1, false);
-            }
+        let x = Math.min(row, this._rowDefinitions.length - 1);
+        let y = Math.min(column, this._columnDefinitions.length - 1);
+        let key = `${x}:${y}`;
+        let goodContainer = this._cells[key];
+
+        if (!goodContainer) {
+            goodContainer = new Container(key);
+            this._cells[key] = goodContainer;
+            goodContainer.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+            goodContainer.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
+            super.addControl(goodContainer);
+        }
 
-            let x = Math.min(row, this._rowDefinitions.length - 1);
-            let y = Math.min(column, this._columnDefinitions.length - 1);
-            let key = `${x}:${y}`;
-            let goodContainer = this._cells[key];
-
-            if (!goodContainer) {
-                goodContainer = new Container(key);
-                this._cells[key] = goodContainer;
-                goodContainer.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
-                goodContainer.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
-                super.addControl(goodContainer);
-            }
+        goodContainer.addControl(control);
+        this._childControls.push(control);
+        control._tag = key;
 
-            goodContainer.addControl(control);
-            this._childControls.push(control);
-            control._tag = key;
+        this._markAsDirty();
 
-            this._markAsDirty();            
+        return this;
+    }
 
-            return this;
+    /**
+     * Removes a control from the current container
+     * @param control defines the control to remove
+     * @returns the current container
+     */
+    public removeControl(control: Control): Container {
+        var index = this._childControls.indexOf(control);
+
+        if (index !== -1) {
+            this._childControls.splice(index, 1);
         }
 
-        /**
-         * Removes a control from the current container
-         * @param control defines the control to remove
-         * @returns the current container
-         */        
-        public removeControl(control: Control): Container {
-            var index = this._childControls.indexOf(control);
+        let cell = this._cells[control._tag];
 
-            if (index !== -1) {
-                this._childControls.splice(index, 1);
-            }
+        if (cell) {
+            cell.removeControl(control);
+        }
 
-            let cell = this._cells[control._tag];
+        this._markAsDirty();
+        return this;
+    }
 
-            if (cell) {
-                cell.removeControl(control);
-            }
+    /**
+     * Creates a new Grid
+     * @param name defines control name
+     */
+    constructor(public name?: string) {
+        super(name);
+    }
 
-            this._markAsDirty();
-            return this;
-        }        
-
-        /**
-         * Creates a new Grid
-         * @param name defines control name
-         */
-        constructor(public name?: string) {
-            super(name);
-        }
+    protected _getTypeName(): string {
+        return "Grid";
+    }
 
-        protected _getTypeName(): string {
-            return "Grid";
-        }   
-
-        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            let widths = [];
-            let heights = [];
-            let lefts = [];
-            let tops = [];
-
-            let availableWidth = this._currentMeasure.width;
-            let globalWidthPercentage = 0;
-            let availableHeight = this._currentMeasure.height;
-            let globalHeightPercentage = 0;
-
-            // Heights
-            let index = 0;
-            for (var value of this._rowDefinitions) {
-                if (value.isPixel) {
-                    let height = value.getValue(this._host);
-                    availableHeight -= height;
-                    heights[index] = height;
-                } else {
-                    globalHeightPercentage += value.internalValue;
-                }
-                index++;
+    protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        let widths = [];
+        let heights = [];
+        let lefts = [];
+        let tops = [];
+
+        let availableWidth = this._currentMeasure.width;
+        let globalWidthPercentage = 0;
+        let availableHeight = this._currentMeasure.height;
+        let globalHeightPercentage = 0;
+
+        // Heights
+        let index = 0;
+        for (var value of this._rowDefinitions) {
+            if (value.isPixel) {
+                let height = value.getValue(this._host);
+                availableHeight -= height;
+                heights[index] = height;
+            } else {
+                globalHeightPercentage += value.internalValue;
             }
+            index++;
+        }
 
-            let top = 0;
-            index = 0;
-            for (var value of this._rowDefinitions) {
-                tops.push(top);
-
-                if (!value.isPixel) {
-                    let height = (value.internalValue / globalHeightPercentage) * availableHeight;
-                    top += height;
-                    heights[index] = height;
-                } else {
-                    top += value.getValue(this._host);
-                }
-                index++;
+        let top = 0;
+        index = 0;
+        for (var value of this._rowDefinitions) {
+            tops.push(top);
+
+            if (!value.isPixel) {
+                let height = (value.internalValue / globalHeightPercentage) * availableHeight;
+                top += height;
+                heights[index] = height;
+            } else {
+                top += value.getValue(this._host);
             }
+            index++;
+        }
 
-            // Widths
-            index = 0;
-            for (var value of this._columnDefinitions) {
-                if (value.isPixel) {
-                    let width = value.getValue(this._host);
-                    availableWidth -= width;
-                    widths[index] = width;
-                } else {
-                    globalWidthPercentage += value.internalValue;
-                }
-                index++;
+        // Widths
+        index = 0;
+        for (var value of this._columnDefinitions) {
+            if (value.isPixel) {
+                let width = value.getValue(this._host);
+                availableWidth -= width;
+                widths[index] = width;
+            } else {
+                globalWidthPercentage += value.internalValue;
             }
+            index++;
+        }
 
-            let left = 0;
-            index = 0;
-            for (var value of this._columnDefinitions) {
-                lefts.push(left);
-                if (!value.isPixel) {
-                    let width = (value.internalValue / globalWidthPercentage) * availableWidth;
-                    left += width;
-                    widths[index] = width;
-                }  else {
-                    left += value.getValue(this._host);
-                }
-                index++;
-            }       
-            
-            // Setting child sizes
-            for (var key in this._cells) {
-                if (!this._cells.hasOwnProperty(key)) {
-                    continue;
-                }
-                let split = key.split(":");
-                let x = parseInt(split[0]);
-                let y = parseInt(split[1]);
-                let cell = this._cells[key];
-
-                cell.left = lefts[y] + "px";
-                cell.top = tops[x] + "px";
-                cell.width = widths[y] + "px";
-                cell.height = heights[x] + "px";
+        let left = 0;
+        index = 0;
+        for (var value of this._columnDefinitions) {
+            lefts.push(left);
+            if (!value.isPixel) {
+                let width = (value.internalValue / globalWidthPercentage) * availableWidth;
+                left += width;
+                widths[index] = width;
+            } else {
+                left += value.getValue(this._host);
             }
+            index++;
+        }
 
-            super._additionalProcessing(parentMeasure, context);
+        // Setting child sizes
+        for (var key in this._cells) {
+            if (!this._cells.hasOwnProperty(key)) {
+                continue;
+            }
+            let split = key.split(":");
+            let x = parseInt(split[0]);
+            let y = parseInt(split[1]);
+            let cell = this._cells[key];
+
+            cell.left = lefts[y] + "px";
+            cell.top = tops[x] + "px";
+            cell.width = widths[y] + "px";
+            cell.height = heights[x] + "px";
         }
 
-        /** Releases associated resources */
-        public dispose() {
-            super.dispose();
+        super._additionalProcessing(parentMeasure, context);
+    }
+
+    /** Releases associated resources */
+    public dispose() {
+        super.dispose();
 
-            for (var control of this._childControls) {
-                control.dispose();
-            }
+        for (var control of this._childControls) {
+            control.dispose();
         }
     }
 }

+ 279 - 279
gui/src/2D/controls/image.ts

@@ -1,351 +1,351 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Control } from "./control";
+import { Nullable, Tools } from "babylonjs";
+import { Measure } from "../measure";
+
+/**
+ * Class used to create 2D images
+ */
+class GUIImage extends Control {
+    private _domImage: HTMLImageElement;
+    private _imageWidth: number;
+    private _imageHeight: number;
+    private _loaded = false;
+    private _stretch = GUIImage.STRETCH_FILL;
+    private _source: Nullable<string>;
+    private _autoScale = false;
+
+    private _sourceLeft = 0;
+    private _sourceTop = 0;
+    private _sourceWidth = 0;
+    private _sourceHeight = 0;
+
+    private _cellWidth: number = 0;
+    private _cellHeight: number = 0;
+    private _cellId: number = -1;
 
-var DOMImage = Image;
-
-module BABYLON.GUI {
     /**
-     * Class used to create 2D images
+     * Gets or sets the left coordinate in the source image
      */
-    export class Image extends Control {
-        private _domImage: HTMLImageElement;
-        private _imageWidth: number;
-        private _imageHeight: number;
-        private _loaded = false;
-        private _stretch = Image.STRETCH_FILL;
-        private _source: Nullable<string>;
-        private _autoScale = false;
-
-        private _sourceLeft = 0;
-        private _sourceTop = 0;
-        private _sourceWidth = 0;
-        private _sourceHeight = 0;
-
-        private _cellWidth: number = 0;
-        private _cellHeight: number = 0;
-        private _cellId: number = -1;
-
-        /**
-         * Gets or sets the left coordinate in the source image
-         */
-        public get sourceLeft(): number {
-            return this._sourceLeft;
+    public get sourceLeft(): number {
+        return this._sourceLeft;
+    }
+
+    public set sourceLeft(value: number) {
+        if (this._sourceLeft === value) {
+            return;
         }
 
-        public set sourceLeft(value: number) {
-            if (this._sourceLeft === value) {
-                return;
-            }
+        this._sourceLeft = value;
 
-            this._sourceLeft = value;
+        this._markAsDirty();
+    }
 
-            this._markAsDirty();
-        }
+    /**
+     * Gets or sets the top coordinate in the source image
+     */
+    public get sourceTop(): number {
+        return this._sourceTop;
+    }
 
-        /**
-         * Gets or sets the top coordinate in the source image
-         */        
-        public get sourceTop(): number {
-            return this._sourceTop;
+    public set sourceTop(value: number) {
+        if (this._sourceTop === value) {
+            return;
         }
 
-        public set sourceTop(value: number) {
-            if (this._sourceTop === value) {
-                return;
-            }
+        this._sourceTop = value;
 
-            this._sourceTop = value;
+        this._markAsDirty();
+    }
 
-            this._markAsDirty();
-        }
+    /**
+     * Gets or sets the width to capture in the source image
+     */
+    public get sourceWidth(): number {
+        return this._sourceWidth;
+    }
 
-        /**
-         * Gets or sets the width to capture in the source image
-         */        
-        public get sourceWidth(): number {
-            return this._sourceWidth;
+    public set sourceWidth(value: number) {
+        if (this._sourceWidth === value) {
+            return;
         }
 
-        public set sourceWidth(value: number) {
-            if (this._sourceWidth === value) {
-                return;
-            }
+        this._sourceWidth = value;
 
-            this._sourceWidth = value;
+        this._markAsDirty();
+    }
 
-            this._markAsDirty();
-        }
+    /**
+     * Gets or sets the height to capture in the source image
+     */
+    public get sourceHeight(): number {
+        return this._sourceHeight;
+    }
 
-        /**
-         * Gets or sets the height to capture in the source image
-         */        
-        public get sourceHeight(): number {
-            return this._sourceHeight;
+    public set sourceHeight(value: number) {
+        if (this._sourceHeight === value) {
+            return;
         }
 
-        public set sourceHeight(value: number) {
-            if (this._sourceHeight === value) {
-                return;
-            }
+        this._sourceHeight = value;
 
-            this._sourceHeight = value;
+        this._markAsDirty();
+    }
 
-            this._markAsDirty();
-        }
+    /** 
+     * Gets or sets a boolean indicating if the image can force its container to adapt its size 
+     * @see http://doc.babylonjs.com/how_to/gui#image
+     */
+    public get autoScale(): boolean {
+        return this._autoScale;
+    }
 
-        /** 
-         * Gets or sets a boolean indicating if the image can force its container to adapt its size 
-         * @see http://doc.babylonjs.com/how_to/gui#image
-         */
-        public get autoScale(): boolean {
-            return this._autoScale;
+    public set autoScale(value: boolean) {
+        if (this._autoScale === value) {
+            return;
         }
 
-        public set autoScale(value: boolean) {
-            if (this._autoScale === value) {
-                return;
-            }
-
-            this._autoScale = value;
+        this._autoScale = value;
 
-            if (value && this._loaded) {
-                this.synchronizeSizeWithContent();
-            }
+        if (value && this._loaded) {
+            this.synchronizeSizeWithContent();
         }
+    }
 
-        /** Gets or sets the streching mode used by the image */
-        public get stretch(): number {
-            return this._stretch;
-        }
+    /** Gets or sets the streching mode used by the image */
+    public get stretch(): number {
+        return this._stretch;
+    }
 
-        public set stretch(value: number) {
-            if (this._stretch === value) {
-                return;
-            }
+    public set stretch(value: number) {
+        if (this._stretch === value) {
+            return;
+        }
 
-            this._stretch = value;
+        this._stretch = value;
 
-            this._markAsDirty();
-        }
+        this._markAsDirty();
+    }
 
-        /**
-         * Gets or sets the internal DOM image used to render the control
-         */
-        public set domImage(value: HTMLImageElement) {
-            this._domImage = value;
-            this._loaded = false;
+    /**
+     * Gets or sets the internal DOM image used to render the control
+     */
+    public set domImage(value: HTMLImageElement) {
+        this._domImage = value;
+        this._loaded = false;
 
-            if (this._domImage.width) {
+        if (this._domImage.width) {
+            this._onImageLoaded();
+        } else {
+            this._domImage.onload = () => {
                 this._onImageLoaded();
-            } else {
-                this._domImage.onload = () => {
-                    this._onImageLoaded();
-                }
             }
         }
+    }
 
-        public get domImage(): HTMLImageElement {
-            return this._domImage;
-        }
-
-        private _onImageLoaded(): void {
-            this._imageWidth = this._domImage.width;
-            this._imageHeight = this._domImage.height;
-            this._loaded = true;
+    public get domImage(): HTMLImageElement {
+        return this._domImage;
+    }
 
-            if (this._autoScale) {
-                this.synchronizeSizeWithContent();
-            }
+    private _onImageLoaded(): void {
+        this._imageWidth = this._domImage.width;
+        this._imageHeight = this._domImage.height;
+        this._loaded = true;
 
-            this._markAsDirty();
+        if (this._autoScale) {
+            this.synchronizeSizeWithContent();
         }
 
-        /**
-         * Gets or sets image source url
-         */
-        public set source(value: Nullable<string>) {
-            if (this._source === value) {
-                return;
-            }
+        this._markAsDirty();
+    }
 
-            this._loaded = false;
-            this._source = value;
+    /**
+     * Gets or sets image source url
+     */
+    public set source(value: Nullable<string>) {
+        if (this._source === value) {
+            return;
+        }
 
-            this._domImage = new DOMImage();
+        this._loaded = false;
+        this._source = value;
 
-            this._domImage.onload = () => {
-                this._onImageLoaded();
-            }
-            if (value) {
-                Tools.SetCorsBehavior(value, this._domImage);
-                this._domImage.src = value;
-            }
-        }
+        this._domImage = new Image();
 
-        /** 
-         * Gets or sets the cell width to use when animation sheet is enabled 
-         * @see http://doc.babylonjs.com/how_to/gui#image
-         */
-        get cellWidth(): number {
-            return this._cellWidth;
+        this._domImage.onload = () => {
+            this._onImageLoaded();
         }
-        set cellWidth(value: number) {
-            if(this._cellWidth === value){
-                return;
-            }
-            
-            this._cellWidth = value;
-            this._markAsDirty();
+        if (value) {
+            Tools.SetCorsBehavior(value, this._domImage);
+            this._domImage.src = value;
         }
+    }
 
-        /** 
-         * Gets or sets the cell height to use when animation sheet is enabled 
-         * @see http://doc.babylonjs.com/how_to/gui#image
-         */
-        get cellHeight(): number {
-            return this._cellHeight;
-        }
-        set cellHeight(value: number) {
-            if(this._cellHeight === value){
-                return;
-            }
-            
-            this._cellHeight = value;
-            this._markAsDirty();
-        }
-    
-        /** 
-         * Gets or sets the cell id to use (this will turn on the animation sheet mode)
-         * @see http://doc.babylonjs.com/how_to/gui#image
-         */
-        get cellId(): number {
-            return this._cellId;
-        }
-        set cellId(value: number) {
-            if (this._cellId === value) {
-                 return;
-             }
-            
-            this._cellId = value;
-            this._markAsDirty();
+    /** 
+     * Gets or sets the cell width to use when animation sheet is enabled 
+     * @see http://doc.babylonjs.com/how_to/gui#image
+     */
+    get cellWidth(): number {
+        return this._cellWidth;
+    }
+    set cellWidth(value: number) {
+        if (this._cellWidth === value) {
+            return;
         }
 
-        /**
-         * Creates a new Image
-         * @param name defines the control name
-         * @param url defines the image url
-         */
-        constructor(public name?: string, url: Nullable<string> = null) {
-            super(name);
+        this._cellWidth = value;
+        this._markAsDirty();
+    }
 
-            this.source = url;
+    /** 
+     * Gets or sets the cell height to use when animation sheet is enabled 
+     * @see http://doc.babylonjs.com/how_to/gui#image
+     */
+    get cellHeight(): number {
+        return this._cellHeight;
+    }
+    set cellHeight(value: number) {
+        if (this._cellHeight === value) {
+            return;
         }
 
-        protected _getTypeName(): string {
-            return "Image";
+        this._cellHeight = value;
+        this._markAsDirty();
+    }
+
+    /** 
+     * Gets or sets the cell id to use (this will turn on the animation sheet mode)
+     * @see http://doc.babylonjs.com/how_to/gui#image
+     */
+    get cellId(): number {
+        return this._cellId;
+    }
+    set cellId(value: number) {
+        if (this._cellId === value) {
+            return;
         }
 
-        /** Force the control to synchronize with its content */
-        public synchronizeSizeWithContent() {
-            if (!this._loaded) {
-                return;
-            }
+        this._cellId = value;
+        this._markAsDirty();
+    }
 
-            this.width = this._domImage.width + "px";
-            this.height = this._domImage.height + "px";
+    /**
+     * Creates a new Image
+     * @param name defines the control name
+     * @param url defines the image url
+     */
+    constructor(public name?: string, url: Nullable<string> = null) {
+        super(name);
+
+        this.source = url;
+    }
+
+    protected _getTypeName(): string {
+        return "Image";
+    }
+
+    /** Force the control to synchronize with its content */
+    public synchronizeSizeWithContent() {
+        if (!this._loaded) {
+            return;
         }
 
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
+        this.width = this._domImage.width + "px";
+        this.height = this._domImage.height + "px";
+    }
 
-            if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                context.shadowColor = this.shadowColor;
-                context.shadowBlur = this.shadowBlur;
-                context.shadowOffsetX = this.shadowOffsetX;
-                context.shadowOffsetY = this.shadowOffsetY;
-            }
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
 
-            let x, y, width, height;
-            if (this.cellId == -1) {
-                x = this._sourceLeft;
-                y = this._sourceTop;
+        if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+            context.shadowColor = this.shadowColor;
+            context.shadowBlur = this.shadowBlur;
+            context.shadowOffsetX = this.shadowOffsetX;
+            context.shadowOffsetY = this.shadowOffsetY;
+        }
 
-                width = this._sourceWidth ? this._sourceWidth : this._imageWidth;
-                height = this._sourceHeight ? this._sourceHeight : this._imageHeight;
-            }
-            else {
-                let rowCount = this._domImage.naturalWidth / this.cellWidth;
-                let column = (this.cellId / rowCount) >> 0;
-                let row = this.cellId % rowCount;
-
-                x = this.cellWidth * row;
-                y = this.cellHeight * column;
-                width = this.cellWidth;
-                height = this.cellHeight;
-            }
+        let x, y, width, height;
+        if (this.cellId == -1) {
+            x = this._sourceLeft;
+            y = this._sourceTop;
 
-            this._applyStates(context);
-            if (this._processMeasures(parentMeasure, context)) {
-                if (this._loaded) {
-                    switch (this._stretch) {
-                        case Image.STRETCH_NONE:
-                            context.drawImage(this._domImage, x, y, width, height,
-                                this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                            break;
-                        case Image.STRETCH_FILL:
-                            context.drawImage(this._domImage, x, y, width, height,
-                                this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                            break;
-                        case Image.STRETCH_UNIFORM:
-                            var hRatio = this._currentMeasure.width / width;
-                            var vRatio = this._currentMeasure.height / height;
-                            var ratio = Math.min(hRatio, vRatio);
-                            var centerX = (this._currentMeasure.width - width * ratio) / 2;
-                            var centerY = (this._currentMeasure.height - height * ratio) / 2;
-
-                            context.drawImage(this._domImage, x, y, width, height,
-                                this._currentMeasure.left + centerX, this._currentMeasure.top + centerY, width * ratio, height * ratio);
-                            break;
-                        case Image.STRETCH_EXTEND:
-                            context.drawImage(this._domImage, x, y, width, height,
-                                this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                            if (this._autoScale) {
-                                this.synchronizeSizeWithContent();
-                            }
-                            if (this._root && this._root.parent) { // Will update root size if root is not the top root
-                                this._root.width = this.width;
-                                this._root.height = this.height;
-                            }
-                            break;
-                    }
+            width = this._sourceWidth ? this._sourceWidth : this._imageWidth;
+            height = this._sourceHeight ? this._sourceHeight : this._imageHeight;
+        }
+        else {
+            let rowCount = this._domImage.naturalWidth / this.cellWidth;
+            let column = (this.cellId / rowCount) >> 0;
+            let row = this.cellId % rowCount;
+
+            x = this.cellWidth * row;
+            y = this.cellHeight * column;
+            width = this.cellWidth;
+            height = this.cellHeight;
+        }
+
+        this._applyStates(context);
+        if (this._processMeasures(parentMeasure, context)) {
+            if (this._loaded) {
+                switch (this._stretch) {
+                    case GUIImage.STRETCH_NONE:
+                        context.drawImage(this._domImage, x, y, width, height,
+                            this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                        break;
+                    case GUIImage.STRETCH_FILL:
+                        context.drawImage(this._domImage, x, y, width, height,
+                            this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                        break;
+                    case GUIImage.STRETCH_UNIFORM:
+                        var hRatio = this._currentMeasure.width / width;
+                        var vRatio = this._currentMeasure.height / height;
+                        var ratio = Math.min(hRatio, vRatio);
+                        var centerX = (this._currentMeasure.width - width * ratio) / 2;
+                        var centerY = (this._currentMeasure.height - height * ratio) / 2;
+
+                        context.drawImage(this._domImage, x, y, width, height,
+                            this._currentMeasure.left + centerX, this._currentMeasure.top + centerY, width * ratio, height * ratio);
+                        break;
+                    case GUIImage.STRETCH_EXTEND:
+                        context.drawImage(this._domImage, x, y, width, height,
+                            this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                        if (this._autoScale) {
+                            this.synchronizeSizeWithContent();
+                        }
+                        if (this._root && this._root.parent) { // Will update root size if root is not the top root
+                            this._root.width = this.width;
+                            this._root.height = this.height;
+                        }
+                        break;
                 }
             }
-            context.restore();
         }
+        context.restore();
+    }
 
-        // Static
-        private static _STRETCH_NONE = 0;
-        private static _STRETCH_FILL = 1;
-        private static _STRETCH_UNIFORM = 2;
-        private static _STRETCH_EXTEND = 3;
+    // Static
+    private static _STRETCH_NONE = 0;
+    private static _STRETCH_FILL = 1;
+    private static _STRETCH_UNIFORM = 2;
+    private static _STRETCH_EXTEND = 3;
 
-        /** STRETCH_NONE */
-        public static get STRETCH_NONE(): number {
-            return Image._STRETCH_NONE;
-        }
+    /** STRETCH_NONE */
+    public static get STRETCH_NONE(): number {
+        return GUIImage._STRETCH_NONE;
+    }
 
-        /** STRETCH_FILL */
-        public static get STRETCH_FILL(): number {
-            return Image._STRETCH_FILL;
-        }
+    /** STRETCH_FILL */
+    public static get STRETCH_FILL(): number {
+        return GUIImage._STRETCH_FILL;
+    }
 
-        /** STRETCH_UNIFORM */
-        public static get STRETCH_UNIFORM(): number {
-            return Image._STRETCH_UNIFORM;
-        }
+    /** STRETCH_UNIFORM */
+    public static get STRETCH_UNIFORM(): number {
+        return GUIImage._STRETCH_UNIFORM;
+    }
 
-        /** STRETCH_EXTEND */
-        public static get STRETCH_EXTEND(): number {
-            return Image._STRETCH_EXTEND;
-        }
+    /** STRETCH_EXTEND */
+    public static get STRETCH_EXTEND(): number {
+        return GUIImage._STRETCH_EXTEND;
     }
 }
+
+export { GUIImage as Image };

+ 19 - 0
gui/src/2D/controls/index.ts

@@ -0,0 +1,19 @@
+export * from "./button";
+export * from "./checkbox";
+export * from "./colorpicker";
+export * from "./container";
+export * from "./control";
+export * from "./ellipse";
+export * from "./grid";
+export * from "./image";
+export * from "./inputText";
+export * from "./line";
+export * from "./multiLine";
+export * from "./radioButton";
+export * from "./stackPanel";
+export * from "./textBlock";
+export * from "./virtualKeyboard";
+export * from "./slider";
+export * from "./rectangle";
+
+export * from "./statics";

+ 10 - 12
gui/src/2D/controls/inputPassword.ts

@@ -1,16 +1,14 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { InputText } from "./inputText";
 
-module BABYLON.GUI {
-    /**
-     * Class used to create a password control
-     */
-    export class InputPassword extends InputText {
-        protected _beforeRenderText(text: string): string {
-            let txt = "";
-            for (let i = 0; i < text.length; i++) {
-                txt += "\u2022";
-            }
-            return txt;
+/**
+ * Class used to create a password control
+ */
+export class InputPassword extends InputText {
+    protected _beforeRenderText(text: string): string {
+        let txt = "";
+        for (let i = 0; i < text.length; i++) {
+            txt += "\u2022";
         }
+        return txt;
     }
 }

+ 426 - 424
gui/src/2D/controls/inputText.ts

@@ -1,536 +1,538 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Control } from "./control";
+import { IFocusableControl } from "../advancedDynamicTexture";
+import { ValueAndUnit } from "../valueAndUnit";
+import { Nullable, Observable, Vector2 } from "babylonjs";
+import { Measure } from "../measure";
+
+/**
+ * Class used to create input text control
+ */
+export class InputText extends Control implements IFocusableControl {
+    private _text = "";
+    private _placeholderText = "";
+    private _background = "#222222";
+    private _focusedBackground = "#000000";
+    private _placeholderColor = "gray";
+    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: Nullable<number>;
+    private _textWidth: number;
+    private _clickedCoordinate: Nullable<number>;
+    private _deadKey = false;
+    private _addKey = true;
+    private _currentKey = "";
+
+    /** Gets or sets a string representing the message displayed on mobile when the control gets the focus */
+    public promptMessage = "Please enter text:";
+
+    /** Observable raised when the text changes */
+    public onTextChangedObservable = new Observable<InputText>();
+    /** Observable raised just before an entered character is to be added */
+    public onBeforeKeyAddObservable = new Observable<InputText>();
+    /** Observable raised when the control gets the focus */
+    public onFocusObservable = new Observable<InputText>();
+    /** Observable raised when the control loses the focus */
+    public onBlurObservable = new Observable<InputText>();
+
+    /** Gets or sets the maximum width allowed by the control */
+    public get maxWidth(): string | number {
+        return this._maxWidth.toString(this._host);
+    }
 
-module BABYLON.GUI {
-    /**
-     * Class used to create input text control
-     */
-    export class InputText extends Control implements IFocusableControl {
-        private _text = "";
-        private _placeholderText = "";
-        private _background = "#222222";
-        private _focusedBackground = "#000000";
-        private _placeholderColor = "gray";
-        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: Nullable<number>;
-        private _textWidth: number;
-        private _clickedCoordinate: Nullable<number>;
-        private _deadKey = false;
-        private _addKey = true;
-        private _currentKey = "";
-
-        /** Gets or sets a string representing the message displayed on mobile when the control gets the focus */
-        public promptMessage = "Please enter text:";
-
-        /** Observable raised when the text changes */
-        public onTextChangedObservable = new Observable<InputText>();
-        /** Observable raised just before an entered character is to be added */
-        public onBeforeKeyAddObservable = new Observable<InputText>();
-        /** Observable raised when the control gets the focus */
-        public onFocusObservable = new Observable<InputText>();
-        /** Observable raised when the control loses the focus */
-        public onBlurObservable = new Observable<InputText>();
-
-        /** Gets or sets the maximum width allowed by the control */
-        public get maxWidth(): string | number {
-            return this._maxWidth.toString(this._host);
+    /** Gets the maximum width allowed by the control in pixels */
+    public get maxWidthInPixels(): number {
+        return this._maxWidth.getValueInPixel(this._host, this._cachedParentMeasure.width);
+    }
+
+    public set maxWidth(value: string | number) {
+        if (this._maxWidth.toString(this._host) === value) {
+            return;
         }
 
-        /** Gets the maximum width allowed by the control in pixels */
-        public get maxWidthInPixels(): number {
-            return this._maxWidth.getValueInPixel(this._host, this._cachedParentMeasure.width);
+        if (this._maxWidth.fromString(value)) {
+            this._markAsDirty();
         }
+    }
 
-        public set maxWidth(value: string | number) {
-            if (this._maxWidth.toString(this._host) === value) {
-                return;
-            }
+    /** Gets or sets control margin */
+    public get margin(): string {
+        return this._margin.toString(this._host);
+    }
 
-            if (this._maxWidth.fromString(value)) {
-                this._markAsDirty();
-            }
-        }
+    /** Gets control margin in pixels */
+    public get marginInPixels(): number {
+        return this._margin.getValueInPixel(this._host, this._cachedParentMeasure.width);
+    }
 
-        /** Gets or sets control margin */
-        public get margin(): string {
-            return this._margin.toString(this._host);
+    public set margin(value: string) {
+        if (this._margin.toString(this._host) === value) {
+            return;
         }
 
-        /** Gets control margin in pixels */
-        public get marginInPixels(): number {
-            return this._margin.getValueInPixel(this._host, this._cachedParentMeasure.width);
+        if (this._margin.fromString(value)) {
+            this._markAsDirty();
         }
+    }
 
-        public set margin(value: string) {
-            if (this._margin.toString(this._host) === value) {
-                return;
-            }
+    /** Gets or sets a boolean indicating if the control can auto stretch its width to adapt to the text */
+    public get autoStretchWidth(): boolean {
+        return this._autoStretchWidth;
+    }
 
-            if (this._margin.fromString(value)) {
-                this._markAsDirty();
-            }
+    public set autoStretchWidth(value: boolean) {
+        if (this._autoStretchWidth === value) {
+            return;
         }
 
-        /** Gets or sets a boolean indicating if the control can auto stretch its width to adapt to the text */
-        public get autoStretchWidth(): boolean {
-            return this._autoStretchWidth;
-        }
+        this._autoStretchWidth = value;
+        this._markAsDirty();
+    }
 
-        public set autoStretchWidth(value: boolean) {
-            if (this._autoStretchWidth === value) {
-                return;
-            }
+    /** Gets or sets border thickness */
+    public get thickness(): number {
+        return this._thickness;
+    }
 
-            this._autoStretchWidth = value;
-            this._markAsDirty();
+    public set thickness(value: number) {
+        if (this._thickness === value) {
+            return;
         }
 
-        /** Gets or sets border thickness */
-        public get thickness(): number {
-            return this._thickness;
-        }
+        this._thickness = value;
+        this._markAsDirty();
+    }
 
-        public set thickness(value: number) {
-            if (this._thickness === value) {
-                return;
-            }
+    /** Gets or sets the background color when focused */
+    public get focusedBackground(): string {
+        return this._focusedBackground;
+    }
 
-            this._thickness = value;
-            this._markAsDirty();
+    public set focusedBackground(value: string) {
+        if (this._focusedBackground === value) {
+            return;
         }
 
-        /** Gets or sets the background color when focused */
-        public get focusedBackground(): string {
-            return this._focusedBackground;
-        }
+        this._focusedBackground = value;
+        this._markAsDirty();
+    }
 
-        public set focusedBackground(value: string) {
-            if (this._focusedBackground === value) {
-                return;
-            }
+    /** Gets or sets the background color */
+    public get background(): string {
+        return this._background;
+    }
 
-            this._focusedBackground = value;
-            this._markAsDirty();
+    public set background(value: string) {
+        if (this._background === value) {
+            return;
         }
 
-        /** Gets or sets the background color */
-        public get background(): string {
-            return this._background;
-        }
+        this._background = value;
+        this._markAsDirty();
+    }
 
-        public set background(value: string) {
-            if (this._background === value) {
-                return;
-            }
+    /** Gets or sets the placeholder color */
+    public get placeholderColor(): string {
+        return this._placeholderColor;
+    }
 
-            this._background = value;
-            this._markAsDirty();
+    public set placeholderColor(value: string) {
+        if (this._placeholderColor === value) {
+            return;
         }
 
-        /** Gets or sets the placeholder color */
-        public get placeholderColor(): string {
-            return this._placeholderColor;
-        }
+        this._placeholderColor = value;
+        this._markAsDirty();
+    }
 
-        public set placeholderColor(value: string) {
-            if (this._placeholderColor === value) {
-                return;
-            }
+    /** Gets or sets the text displayed when the control is empty */
+    public get placeholderText(): string {
+        return this._placeholderText;
+    }
 
-            this._placeholderColor = value;
-            this._markAsDirty();
+    public set placeholderText(value: string) {
+        if (this._placeholderText === value) {
+            return;
         }
+        this._placeholderText = value;
+        this._markAsDirty();
+    }
 
-        /** Gets or sets the text displayed when the control is empty */
-        public get placeholderText(): string {
-            return this._placeholderText;
-        }
+    /** Gets or sets the dead key flag */
+    public get deadKey(): boolean {
+        return this._deadKey;
+    }
 
-        public set placeholderText(value: string) {
-            if (this._placeholderText === value) {
-                return;
-            }
-            this._placeholderText = value;
-            this._markAsDirty();
-        }
+    public set deadKey(flag: boolean) {
+        this._deadKey = flag;
+    }
 
-        /** Gets or sets the dead key flag */
-        public get deadKey(): boolean {
-            return this._deadKey;
-        }
+    /** Gets or sets if the current key should be added */
+    public get addKey(): boolean {
+        return this._addKey;
+    }
 
-        public set deadKey(flag: boolean) {
-            this._deadKey = flag;
-        }
+    public set addKey(flag: boolean) {
+        this._addKey = flag;
+    }
 
-        /** Gets or sets if the current key should be added */
-        public get addKey(): boolean {
-            return this._addKey;
-        }
+    /** Gets or sets the value of the current key being entered */
+    public get currentKey(): string {
+        return this._currentKey;
+    }
 
-        public set addKey(flag: boolean) {
-            this._addKey = flag;
-        }
+    public set currentKey(key: string) {
+        this._currentKey = key;
+    }
 
-        /** Gets or sets the value of the current key being entered */
-        public get currentKey(): string {
-            return this._currentKey;
-        }
+    /** Gets or sets the text displayed in the control */
+    public get text(): string {
+        return this._text;
+    }
 
-        public set currentKey(key: string) {
-            this._currentKey = key;
+    public set text(value: string) {
+        if (this._text === value) {
+            return;
         }
+        this._text = value;
+        this._markAsDirty();
 
-        /** Gets or sets the text displayed in the control */
-        public get text(): string {
-            return this._text;
-        }
+        this.onTextChangedObservable.notifyObservers(this);
+    }
 
-        public set text(value: string) {
-            if (this._text === value) {
-                return;
-            }
-            this._text = value;
-            this._markAsDirty();
+    /** Gets or sets control width */
+    public get width(): string | number {
+        return this._width.toString(this._host);
+    }
 
-            this.onTextChangedObservable.notifyObservers(this);
+    public set width(value: string | number) {
+        if (this._width.toString(this._host) === value) {
+            return;
         }
 
-        /** Gets or sets control width */
-        public get width(): string | number {
-            return this._width.toString(this._host);
+        if (this._width.fromString(value)) {
+            this._markAsDirty();
         }
 
-        public set width(value: string | number) {
-            if (this._width.toString(this._host) === value) {
-                return;
-            }
-
-            if (this._width.fromString(value)) {
-                this._markAsDirty();
-            }
+        this.autoStretchWidth = false;
+    }
 
-            this.autoStretchWidth = false;
-        }
+    /**
+     * Creates a new InputText
+     * @param name defines the control name
+     * @param text defines the text of the control
+     */
+    constructor(public name?: string, text: string = "") {
+        super(name);
 
-        /**
-         * Creates a new InputText
-         * @param name defines the control name
-         * @param text defines the text of the control
-         */
-        constructor(public name?: string, text: string = "") {
-            super(name);
+        this.text = text;
+    }
 
-            this.text = text;
-        }
+    /** @hidden */
+    public onBlur(): void {
+        this._isFocused = false;
+        this._scrollLeft = null;
+        this._cursorOffset = 0;
+        clearTimeout(this._blinkTimeout);
+        this._markAsDirty();
 
-        /** @hidden */
-        public onBlur(): void {
-            this._isFocused = false;
-            this._scrollLeft = null;
-            this._cursorOffset = 0;
-            clearTimeout(this._blinkTimeout);
-            this._markAsDirty();
-
-            this.onBlurObservable.notifyObservers(this);
-        }
+        this.onBlurObservable.notifyObservers(this);
+    }
 
-        /** @hidden */
-        public onFocus(): void {
-            this._scrollLeft = null;
-            this._isFocused = true;
-            this._blinkIsEven = false;
-            this._cursorOffset = 0;
-            this._markAsDirty();
+    /** @hidden */
+    public onFocus(): void {
+        this._scrollLeft = null;
+        this._isFocused = true;
+        this._blinkIsEven = false;
+        this._cursorOffset = 0;
+        this._markAsDirty();
 
-            this.onFocusObservable.notifyObservers(this);
+        this.onFocusObservable.notifyObservers(this);
 
-            if (navigator.userAgent.indexOf("Mobile") !== -1) {
-                let value = prompt(this.promptMessage);
+        if (navigator.userAgent.indexOf("Mobile") !== -1) {
+            let value = prompt(this.promptMessage);
 
-                if (value !== null) {
-                    this.text = value;
-                }
-                this._host.focusedControl = null;
-                return;
+            if (value !== null) {
+                this.text = value;
             }
+            this._host.focusedControl = null;
+            return;
         }
+    }
 
-        protected _getTypeName(): string {
-            return "InputText";
-        }
+    protected _getTypeName(): string {
+        return "InputText";
+    }
 
-        /** @hidden */
-        public processKey(keyCode: number, key?: string) {
-            // Specific cases
-            switch (keyCode) {
-                case 32: //SPACE
-                    key = " "; //ie11 key for space is "Spacebar"
-                    break;
-                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) {
+    /** @hidden */
+    public processKey(keyCode: number, key?: string) {
+        // Specific cases
+        switch (keyCode) {
+            case 32: //SPACE
+                key = " "; //ie11 key for space is "Spacebar"
+                break;
+            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;
-                        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;
+                        if (deletePosition > 0) {
+                            this.text = this._text.slice(0, deletePosition - 1) + this._text.slice(deletePosition);
+                        }
                     }
-                    this._blinkIsEven = false;
-                    this._markAsDirty();
-                    return;
-                case 39: // RIGHT
+                }
+                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--;
-                    if (this._cursorOffset < 0) {
-                        this._cursorOffset = 0;
-                    }
-                    this._blinkIsEven = false;
-                    this._markAsDirty();
-                    return;
-                case 222: // Dead
-                    this.deadKey = true;
-                    return;
-            }
+                }
+                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;
+            case 222: // Dead
+                this.deadKey = true;
+                return;
+        }
 
-            // Printable characters
-            if (key &&
-                ((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
-                this._currentKey = key;
-                this.onBeforeKeyAddObservable.notifyObservers(this);
-                key = this._currentKey;
-                if (this._addKey) {
-                    if (this._cursorOffset === 0) {
-                        this.text += key;
-                    } else {
-                        let insertPosition = this._text.length - this._cursorOffset;
+        // Printable characters
+        if (key &&
+            ((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
+            this._currentKey = key;
+            this.onBeforeKeyAddObservable.notifyObservers(this);
+            key = this._currentKey;
+            if (this._addKey) {
+                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);
-                    }
+                    this.text = this._text.slice(0, insertPosition) + key + this._text.slice(insertPosition);
                 }
             }
         }
+    }
 
-        /** @hidden */
-        public processKeyboard(evt: KeyboardEvent): void {
-            this.processKey(evt.keyCode, evt.key);
-        }
-
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
+    /** @hidden */
+    public processKeyboard(evt: KeyboardEvent): void {
+        this.processKey(evt.keyCode, evt.key);
+    }
 
-            this._applyStates(context);
-            if (this._processMeasures(parentMeasure, context)) {
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
 
-                if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
-                    context.shadowColor = this.shadowColor;
-                    context.shadowBlur = this.shadowBlur;
-                    context.shadowOffsetX = this.shadowOffsetX;
-                    context.shadowOffsetY = this.shadowOffsetY;
-                }
+        this._applyStates(context);
+        if (this._processMeasures(parentMeasure, context)) {
 
-                // Background
-                if (this._isFocused) {
-                    if (this._focusedBackground) {
-                        context.fillStyle = this._focusedBackground;
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
+            }
 
-                        context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                    }
-                } else if (this._background) {
-                    context.fillStyle = this._background;
+            // 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;
 
-                if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
-                    context.shadowBlur = 0;
-                    context.shadowOffsetX = 0;
-                    context.shadowOffsetY = 0;
-                }
+                context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+            }
 
-                if (!this._fontOffset) {
-                    this._fontOffset = Control._GetFontOffset(context.font);
-                }
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowBlur = 0;
+                context.shadowOffsetX = 0;
+                context.shadowOffsetY = 0;
+            }
 
-                // Text
-                let clipTextLeft = this._currentMeasure.left + this._margin.getValueInPixel(this._host, parentMeasure.width);
-                if (this.color) {
-                    context.fillStyle = this.color;
-                }
+            if (!this._fontOffset) {
+                this._fontOffset = Control._GetFontOffset(context.font);
+            }
 
-                let text = this._beforeRenderText(this._text);
+            // Text
+            let clipTextLeft = this._currentMeasure.left + this._margin.getValueInPixel(this._host, parentMeasure.width);
+            if (this.color) {
+                context.fillStyle = this.color;
+            }
 
-                if (!this._isFocused && !this._text && this._placeholderText) {
-                    text = this._placeholderText;
+            let text = this._beforeRenderText(this._text);
 
-                    if (this._placeholderColor) {
-                        context.fillStyle = this._placeholderColor;
-                    }
-                }
+            if (!this._isFocused && !this._text && this._placeholderText) {
+                text = this._placeholderText;
 
-                this._textWidth = context.measureText(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), this._textWidth + marginWidth) + "px";
+                if (this._placeholderColor) {
+                    context.fillStyle = this._placeholderColor;
                 }
+            }
 
-                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 && this._textWidth > availableWidth) {
-                    let textLeft = clipTextLeft - this._textWidth + availableWidth;
-                    if (!this._scrollLeft) {
-                        this._scrollLeft = textLeft;
-                    }
-                } else {
-                    this._scrollLeft = clipTextLeft;
+            this._textWidth = context.measureText(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), this._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 && this._textWidth > availableWidth) {
+                let textLeft = clipTextLeft - this._textWidth + availableWidth;
+                if (!this._scrollLeft) {
+                    this._scrollLeft = textLeft;
                 }
+            } else {
+                this._scrollLeft = clipTextLeft;
+            }
 
-                context.fillText(text, this._scrollLeft, this._currentMeasure.top + rootY);
-
-                // Cursor
-                if (this._isFocused) {
-
-                    // Need to move cursor
-                    if (this._clickedCoordinate) {
-                        var rightPosition = this._scrollLeft + this._textWidth;
-                        var absoluteCursorPosition = rightPosition - this._clickedCoordinate;
-                        var currentSize = 0;
-                        this._cursorOffset = 0;
-                        var previousDist = 0;
-                        do {
-                            if (this._cursorOffset) {
-                                previousDist = Math.abs(absoluteCursorPosition - currentSize);
-                            }
-                            this._cursorOffset++;
-                            currentSize = context.measureText(text.substr(text.length - this._cursorOffset, this._cursorOffset)).width;
-
-                        } while (currentSize < absoluteCursorPosition && (text.length >= this._cursorOffset));
-
-                        // Find closest move
-                        if (Math.abs(absoluteCursorPosition - currentSize) > previousDist) {
-                            this._cursorOffset--;
-                        }
+            context.fillText(text, this._scrollLeft, this._currentMeasure.top + rootY);
 
-                        this._blinkIsEven = false;
-                        this._clickedCoordinate = null;
-                    }
+            // Cursor
+            if (this._isFocused) {
 
-                    // Render cursor
-                    if (!this._blinkIsEven) {
-                        let cursorOffsetText = this.text.substr(this._text.length - this._cursorOffset);
-                        let cursorOffsetWidth = context.measureText(cursorOffsetText).width;
-                        let cursorLeft = this._scrollLeft + this._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();
+                // Need to move cursor
+                if (this._clickedCoordinate) {
+                    var rightPosition = this._scrollLeft + this._textWidth;
+                    var absoluteCursorPosition = rightPosition - this._clickedCoordinate;
+                    var currentSize = 0;
+                    this._cursorOffset = 0;
+                    var previousDist = 0;
+                    do {
+                        if (this._cursorOffset) {
+                            previousDist = Math.abs(absoluteCursorPosition - currentSize);
                         }
-                        context.fillRect(cursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, 2, this._fontOffset.height);
+                        this._cursorOffset++;
+                        currentSize = context.measureText(text.substr(text.length - this._cursorOffset, this._cursorOffset)).width;
+
+                    } while (currentSize < absoluteCursorPosition && (text.length >= this._cursorOffset));
+
+                    // Find closest move
+                    if (Math.abs(absoluteCursorPosition - currentSize) > previousDist) {
+                        this._cursorOffset--;
                     }
 
-                    clearTimeout(this._blinkTimeout);
-                    this._blinkTimeout = setTimeout(() => {
-                        this._blinkIsEven = !this._blinkIsEven;
-                        this._markAsDirty();
-                    }, 500);
+                    this._blinkIsEven = false;
+                    this._clickedCoordinate = null;
                 }
 
-                context.restore();
+                // Render cursor
+                if (!this._blinkIsEven) {
+                    let cursorOffsetText = this.text.substr(this._text.length - this._cursorOffset);
+                    let cursorOffsetWidth = context.measureText(cursorOffsetText).width;
+                    let cursorLeft = this._scrollLeft + this._textWidth - cursorOffsetWidth;
 
-                // Border
-                if (this._thickness) {
-                    if (this.color) {
-                        context.strokeStyle = this.color;
+                    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.lineWidth = this._thickness;
-
-                    context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2,
-                        this._currentMeasure.width - this._thickness, this._currentMeasure.height - this._thickness);
+                    context.fillRect(cursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, 2, this._fontOffset.height);
                 }
+
+                clearTimeout(this._blinkTimeout);
+                this._blinkTimeout = <any>setTimeout(() => {
+                    this._blinkIsEven = !this._blinkIsEven;
+                    this._markAsDirty();
+                }, 500);
             }
+
             context.restore();
-        }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
-                return false;
-            }
+            // Border
+            if (this._thickness) {
+                if (this.color) {
+                    context.strokeStyle = this.color;
+                }
+                context.lineWidth = this._thickness;
 
-            this._clickedCoordinate = coordinates.x;
-            if (this._host.focusedControl === this) {
-                // Move cursor
-                clearTimeout(this._blinkTimeout);
-                this._markAsDirty();
-                return true;
+                context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2,
+                    this._currentMeasure.width - this._thickness, this._currentMeasure.height - this._thickness);
             }
-            this._host.focusedControl = this;
-
-            return true;
         }
+        context.restore();
+    }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
-            super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
+    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
+        if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
+            return false;
         }
 
-        protected _beforeRenderText(text: string): string {
-            return text;
+        this._clickedCoordinate = coordinates.x;
+        if (this._host.focusedControl === this) {
+            // Move cursor
+            clearTimeout(this._blinkTimeout);
+            this._markAsDirty();
+            return true;
         }
+        this._host.focusedControl = this;
+
+        return true;
+    }
 
-        public dispose() {
-            super.dispose();
+    public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
+        super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
+    }
 
-            this.onBlurObservable.clear();
-            this.onFocusObservable.clear();
-            this.onTextChangedObservable.clear();
-        }
+    protected _beforeRenderText(text: string): string {
+        return text;
+    }
+
+    public dispose() {
+        super.dispose();
+
+        this.onBlurObservable.clear();
+        this.onFocusObservable.clear();
+        this.onTextChangedObservable.clear();
     }
 }

+ 216 - 215
gui/src/2D/controls/line.ts

@@ -1,244 +1,245 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
-    /** Class used to render 2D lines */
-    export class Line extends Control {
-        private _lineWidth = 1;
-        private _x1 = new ValueAndUnit(0);
-        private _y1 = new ValueAndUnit(0);
-        private _x2 = new ValueAndUnit(0);
-        private _y2 = new ValueAndUnit(0);
-        private _dash = new Array<number>();
-        private _connectedControl: Control;
-        private _connectedControlDirtyObserver: Nullable<Observer<Control>>;
-
-        /** Gets or sets the dash pattern */
-        public get dash(): Array<number> {
-            return this._dash;
-        }
-
-        public set dash(value: Array<number>) {
-            if (this._dash === value) {
-                return;
-            }
-
-            this._dash = value;
-            this._markAsDirty();
-        }     
-
-        /** Gets or sets the control connected with the line end */
-        public get connectedControl(): Control {
-            return this._connectedControl;
+import { Control } from "./control";
+import { ValueAndUnit } from "../valueAndUnit";
+import { Nullable, Observer, Vector3, Scene, Tools, Matrix } from "babylonjs";
+import { Measure } from "../measure";
+
+/** Class used to render 2D lines */
+export class Line extends Control {
+    private _lineWidth = 1;
+    private _x1 = new ValueAndUnit(0);
+    private _y1 = new ValueAndUnit(0);
+    private _x2 = new ValueAndUnit(0);
+    private _y2 = new ValueAndUnit(0);
+    private _dash = new Array<number>();
+    private _connectedControl: Control;
+    private _connectedControlDirtyObserver: Nullable<Observer<Control>>;
+
+    /** Gets or sets the dash pattern */
+    public get dash(): Array<number> {
+        return this._dash;
+    }
+
+    public set dash(value: Array<number>) {
+        if (this._dash === value) {
+            return;
         }
 
-        public set connectedControl(value: Control) {
-            if (this._connectedControl === value) {
-                return;
-            }
+        this._dash = value;
+        this._markAsDirty();
+    }
 
-            if (this._connectedControlDirtyObserver && this._connectedControl) {
-                this._connectedControl.onDirtyObservable.remove(this._connectedControlDirtyObserver);
-                this._connectedControlDirtyObserver = null;
-            }
+    /** Gets or sets the control connected with the line end */
+    public get connectedControl(): Control {
+        return this._connectedControl;
+    }
 
-            if (value) {
-                this._connectedControlDirtyObserver = value.onDirtyObservable.add(() => this._markAsDirty());
-            }            
+    public set connectedControl(value: Control) {
+        if (this._connectedControl === value) {
+            return;
+        }
 
-            this._connectedControl = value;
-            this._markAsDirty();
-        }              
+        if (this._connectedControlDirtyObserver && this._connectedControl) {
+            this._connectedControl.onDirtyObservable.remove(this._connectedControlDirtyObserver);
+            this._connectedControlDirtyObserver = null;
+        }
 
-        /** Gets or sets start coordinates on X axis */
-        public get x1(): string | number  {
-            return this._x1.toString(this._host);
+        if (value) {
+            this._connectedControlDirtyObserver = value.onDirtyObservable.add(() => this._markAsDirty());
         }
 
-        public set x1(value: string | number ) {
-            if (this._x1.toString(this._host) === value) {
-                return;
-            }
+        this._connectedControl = value;
+        this._markAsDirty();
+    }
 
-            if (this._x1.fromString(value)) {
-                this._markAsDirty();
-            }
-        }    
+    /** Gets or sets start coordinates on X axis */
+    public get x1(): string | number {
+        return this._x1.toString(this._host);
+    }
 
-        /** Gets or sets start coordinates on Y axis */        
-        public get y1(): string | number  {
-            return this._y1.toString(this._host);
+    public set x1(value: string | number) {
+        if (this._x1.toString(this._host) === value) {
+            return;
         }
 
-        public set y1(value: string | number ) {
-            if (this._y1.toString(this._host) === value) {
-                return;
-            }
+        if (this._x1.fromString(value)) {
+            this._markAsDirty();
+        }
+    }
 
-            if (this._y1.fromString(value)) {
-                this._markAsDirty();
-            }
-        }     
+    /** Gets or sets start coordinates on Y axis */
+    public get y1(): string | number {
+        return this._y1.toString(this._host);
+    }
 
-        /** Gets or sets end coordinates on X axis */        
-        public get x2(): string | number  {
-            return this._x2.toString(this._host);
+    public set y1(value: string | number) {
+        if (this._y1.toString(this._host) === value) {
+            return;
         }
 
-        public set x2(value: string | number ) {
-            if (this._x2.toString(this._host) === value) {
-                return;
-            }
+        if (this._y1.fromString(value)) {
+            this._markAsDirty();
+        }
+    }
 
-            if (this._x2.fromString(value)) {
-                this._markAsDirty();
-            }
-        }    
+    /** Gets or sets end coordinates on X axis */
+    public get x2(): string | number {
+        return this._x2.toString(this._host);
+    }
 
-        /** Gets or sets end coordinates on Y axis */        
-        public get y2(): string | number  {
-            return this._y2.toString(this._host);
+    public set x2(value: string | number) {
+        if (this._x2.toString(this._host) === value) {
+            return;
         }
 
-        public set y2(value: string | number ) {
-            if (this._y2.toString(this._host) === value) {
-                return;
-            }
-
-            if (this._y2.fromString(value)) {
-                this._markAsDirty();
-            }
-        }                       
-        
-        /** Gets or sets line width */
-        public get lineWidth(): number {
-            return this._lineWidth;
+        if (this._x2.fromString(value)) {
+            this._markAsDirty();
         }
+    }
 
-        public set lineWidth(value: number) {
-            if (this._lineWidth === value) {
-                return;
-            }
+    /** Gets or sets end coordinates on Y axis */
+    public get y2(): string | number {
+        return this._y2.toString(this._host);
+    }
 
-            this._lineWidth = value;
+    public set y2(value: string | number) {
+        if (this._y2.toString(this._host) === value) {
+            return;
+        }
+
+        if (this._y2.fromString(value)) {
             this._markAsDirty();
-        }   
+        }
+    }
+
+    /** Gets or sets line width */
+    public get lineWidth(): number {
+        return this._lineWidth;
+    }
 
-        /** Gets or sets horizontal alignment */
-        public set horizontalAlignment(value: number) {
+    public set lineWidth(value: number) {
+        if (this._lineWidth === value) {
             return;
-        } 
+        }
+
+        this._lineWidth = value;
+        this._markAsDirty();
+    }
+
+    /** Gets or sets horizontal alignment */
+    public set horizontalAlignment(value: number) {
+        return;
+    }
+
+    /** Gets or sets vertical alignment */
+    public set verticalAlignment(value: number) {
+        return;
+    }
+
+    private get _effectiveX2(): number {
+        return (this._connectedControl ? this._connectedControl.centerX : 0) + this._x2.getValue(this._host);
+    }
+
+    private get _effectiveY2(): number {
+        return (this._connectedControl ? this._connectedControl.centerY : 0) + this._y2.getValue(this._host);
+    }
+
+    /**
+     * Creates a new Line
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
+
+        this.isHitTestVisible = false;
+        this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+        this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
+    }
+
+    protected _getTypeName(): string {
+        return "Line";
+    }
+
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
+
+        if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+            context.shadowColor = this.shadowColor;
+            context.shadowBlur = this.shadowBlur;
+            context.shadowOffsetX = this.shadowOffsetX;
+            context.shadowOffsetY = this.shadowOffsetY;
+        }
+
+        this._applyStates(context);
+        if (this._processMeasures(parentMeasure, context)) {
+            context.strokeStyle = this.color;
+            context.lineWidth = this._lineWidth;
+            context.setLineDash(this._dash);
+
+            context.beginPath();
+            context.moveTo(this._x1.getValue(this._host), this._y1.getValue(this._host));
+
+            context.lineTo(this._effectiveX2, this._effectiveY2);
 
-        /** Gets or sets vertical alignment */
-        public set verticalAlignment(value: number) {
+            context.stroke();
+        }
+
+        context.restore();
+    }
+
+    public _measure(): void {
+        // Width / Height
+        this._currentMeasure.width = Math.abs(this._x1.getValue(this._host) - this._effectiveX2) + this._lineWidth;
+        this._currentMeasure.height = Math.abs(this._y1.getValue(this._host) - this._effectiveY2) + this._lineWidth;
+    }
+
+    protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        this._currentMeasure.left = Math.min(this._x1.getValue(this._host), this._effectiveX2) - this._lineWidth / 2;
+        this._currentMeasure.top = Math.min(this._y1.getValue(this._host), this._effectiveY2) - this._lineWidth / 2;
+    }
+
+    /**
+     * Move one end of the line given 3D cartesian coordinates.
+     * @param position Targeted world position
+     * @param scene Scene
+     * @param end (opt) Set to true to assign x2 and y2 coordinates of the line. Default assign to x1 and y1.
+     */
+    public moveToVector3(position: Vector3, scene: Scene, end: boolean = false): void {
+        if (!this._host || this._root !== this._host._rootContainer) {
+            Tools.Error("Cannot move a control to a vector3 if the control is not at root level");
             return;
-        }    
+        }
+
+        var globalViewport = this._host._getGlobalViewport(scene);
+        var projectedPosition = Vector3.Project(position, Matrix.Identity(), scene.getTransformMatrix(), globalViewport);
 
-        private get _effectiveX2(): number {
-            return (this._connectedControl ? this._connectedControl.centerX : 0) + this._x2.getValue(this._host);
-        }   
-
-        private get _effectiveY2(): number {
-            return (this._connectedControl ? this._connectedControl.centerY : 0) + this._y2.getValue(this._host);
-        }           
-
-        /**
-         * Creates a new Line
-         * @param name defines the control name
-         */
-        constructor(public name?: string) {
-            super(name);
-
-            this.isHitTestVisible = false;
-            this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
-            this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;            
-        }
-
-        protected _getTypeName(): string {
-            return "Line";
-        }              
-
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
-
-            if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                context.shadowColor = this.shadowColor;
-                context.shadowBlur = this.shadowBlur;
-                context.shadowOffsetX = this.shadowOffsetX;
-                context.shadowOffsetY = this.shadowOffsetY;
-            }
-
-            this._applyStates(context);
-            if (this._processMeasures(parentMeasure, context)) {
-                context.strokeStyle = this.color;
-                context.lineWidth = this._lineWidth;
-                context.setLineDash(this._dash);
-
-                context.beginPath();
-                context.moveTo(this._x1.getValue(this._host), this._y1.getValue(this._host));
-
-                context.lineTo(this._effectiveX2, this._effectiveY2);
-
-                context.stroke();
-            }
-
-            context.restore();
-        }
-
-        public _measure(): void {  
-            // Width / Height
-            this._currentMeasure.width = Math.abs(this._x1.getValue(this._host) - this._effectiveX2) + this._lineWidth;
-            this._currentMeasure.height = Math.abs(this._y1.getValue(this._host) - this._effectiveY2) + this._lineWidth;
-        }
-
-        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {          
-            this._currentMeasure.left = Math.min(this._x1.getValue(this._host), this._effectiveX2) - this._lineWidth / 2;
-            this._currentMeasure.top = Math.min(this._y1.getValue(this._host), this._effectiveY2) - this._lineWidth / 2;            
-        }
-
-        /**
-         * Move one end of the line given 3D cartesian coordinates.
-         * @param position Targeted world position
-         * @param scene Scene
-         * @param end (opt) Set to true to assign x2 and y2 coordinates of the line. Default assign to x1 and y1.
-         */
-        public moveToVector3(position: Vector3, scene: Scene, end: boolean = false): void {
-            if (!this._host || this._root !== this._host._rootContainer) {
-                Tools.Error("Cannot move a control to a vector3 if the control is not at root level");
-                return;
-            }
-
-            var globalViewport = this._host._getGlobalViewport(scene);
-            var projectedPosition = Vector3.Project(position, Matrix.Identity(), scene.getTransformMatrix(), globalViewport);
-
-            this._moveToProjectedPosition(projectedPosition, end)
-
-            if (projectedPosition.z < 0 || projectedPosition.z > 1) {
-                this.notRenderable = true;
-                return;
-            }
-            this.notRenderable = false;
-        }
-
-        /**
-         * Move one end of the line to a position in screen absolute space.
-         * @param projectedPosition Position in screen absolute space (X, Y)
-         * @param end (opt) Set to true to assign x2 and y2 coordinates of the line. Default assign to x1 and y1.
-         */
-        public _moveToProjectedPosition(projectedPosition: Vector3, end: boolean = false): void {
-            let x: string = (projectedPosition.x + this._linkOffsetX.getValue(this._host)) + "px";
-            let y: string = (projectedPosition.y + this._linkOffsetY.getValue(this._host)) + "px";
-
-            if (end) {
-                this.x2 = x;
-                this.y2 = y;
-                this._x2.ignoreAdaptiveScaling = true;
-                this._y2.ignoreAdaptiveScaling = true;
-            } else {
-                this.x1 = x;
-                this.y1 = y;
-                this._x1.ignoreAdaptiveScaling = true;
-                this._y1.ignoreAdaptiveScaling = true;
-            }
-        }
-    }    
-}
+        this._moveToProjectedPosition(projectedPosition, end)
+
+        if (projectedPosition.z < 0 || projectedPosition.z > 1) {
+            this.notRenderable = true;
+            return;
+        }
+        this.notRenderable = false;
+    }
+
+    /**
+     * Move one end of the line to a position in screen absolute space.
+     * @param projectedPosition Position in screen absolute space (X, Y)
+     * @param end (opt) Set to true to assign x2 and y2 coordinates of the line. Default assign to x1 and y1.
+     */
+    public _moveToProjectedPosition(projectedPosition: Vector3, end: boolean = false): void {
+        let x: string = (projectedPosition.x + this._linkOffsetX.getValue(this._host)) + "px";
+        let y: string = (projectedPosition.y + this._linkOffsetY.getValue(this._host)) + "px";
+
+        if (end) {
+            this.x2 = x;
+            this.y2 = y;
+            this._x2.ignoreAdaptiveScaling = true;
+            this._y2.ignoreAdaptiveScaling = true;
+        } else {
+            this.x1 = x;
+            this.y1 = y;
+            this._x1.ignoreAdaptiveScaling = true;
+            this._y1.ignoreAdaptiveScaling = true;
+        }
+    }
+}   

+ 187 - 186
gui/src/2D/controls/multiLine.ts

@@ -1,248 +1,249 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Control } from "./control";
+import { MultiLinePoint } from "../multiLinePoint";
+import { Nullable, AbstractMesh } from "babylonjs";
+import { Measure } from "../measure";
 
-module BABYLON.GUI {
+
+/**
+ * Class used to create multi line control
+ */
+export class MultiLine extends Control {
+
+    private _lineWidth: number = 1;
+    private _dash: number[];
+    private _points: Nullable<MultiLinePoint>[];
+
+    private _minX: Nullable<number>;
+    private _minY: Nullable<number>;
+    private _maxX: Nullable<number>;
+    private _maxY: Nullable<number>;
 
     /**
-     * Class used to create multi line control
+     * Creates a new MultiLine
+     * @param name defines the control name
      */
-    export class MultiLine extends Control {
-
-        private _lineWidth: number = 1;
-        private _dash: number[];
-        private _points: Nullable<MultiLinePoint>[];
-
-        private _minX: Nullable<number>;
-        private _minY: Nullable<number>;
-        private _maxX: Nullable<number>;
-        private _maxY: Nullable<number>;
-
-        /**
-         * Creates a new MultiLine
-         * @param name defines the control name
-         */
-        constructor(public name?: string) {
-            super(name);
-
-            this.isHitTestVisible = false;
-            this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
-            this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
-
-            this._dash = [];
-            this._points = [];
-        }
+    constructor(public name?: string) {
+        super(name);
 
-        /** Gets or sets dash pattern */
-        public get dash(): Array<number> {
-            return this._dash;
-        }
+        this.isHitTestVisible = false;
+        this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+        this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
 
-        public set dash(value: Array<number>) {
-            if (this._dash === value) {
-                return;
-            }
+        this._dash = [];
+        this._points = [];
+    }
+
+    /** Gets or sets dash pattern */
+    public get dash(): Array<number> {
+        return this._dash;
+    }
 
-            this._dash = value;
-            this._markAsDirty();
+    public set dash(value: Array<number>) {
+        if (this._dash === value) {
+            return;
         }
 
-        /**
-         * Gets point stored at specified index
-         * @param index defines the index to look for
-         * @returns the requested point if found
-         */
-        public getAt(index: number): MultiLinePoint {
-            if (!this._points[index]) {
-                this._points[index] = new MultiLinePoint(this);
-            }
+        this._dash = value;
+        this._markAsDirty();
+    }
 
-            return this._points[index] as MultiLinePoint;
+    /**
+     * Gets point stored at specified index
+     * @param index defines the index to look for
+     * @returns the requested point if found
+     */
+    public getAt(index: number): MultiLinePoint {
+        if (!this._points[index]) {
+            this._points[index] = new MultiLinePoint(this);
         }
 
-        /** Function called when a point is updated */
-        public onPointUpdate = (): void => {
-            this._markAsDirty();
-        }
+        return this._points[index] as MultiLinePoint;
+    }
 
-        /**
-         * Adds new points to the point collection
-         * @param items defines the list of items (mesh, control or 2d coordiantes) to add 
-         * @returns the list of created MultiLinePoint
-         */
-        public add(...items: (AbstractMesh | Control | { x: string | number, y: string | number })[]): MultiLinePoint[] {
-            return items.map(item => this.push(item));
-        }
+    /** Function called when a point is updated */
+    public onPointUpdate = (): void => {
+        this._markAsDirty();
+    }
 
-        /**
-         * Adds a new point to the point collection
-         * @param item defines the item (mesh, control or 2d coordiantes) to add 
-         * @returns the created MultiLinePoint
-         */
-        public push(item?: (AbstractMesh | Control | { x: string | number, y: string | number })): MultiLinePoint {
-            var point: MultiLinePoint = this.getAt(this._points.length);
+    /**
+     * Adds new points to the point collection
+     * @param items defines the list of items (mesh, control or 2d coordiantes) to add 
+     * @returns the list of created MultiLinePoint
+     */
+    public add(...items: (AbstractMesh | Control | { x: string | number, y: string | number })[]): MultiLinePoint[] {
+        return items.map(item => this.push(item));
+    }
 
-            if (item == null) return point;
+    /**
+     * Adds a new point to the point collection
+     * @param item defines the item (mesh, control or 2d coordiantes) to add 
+     * @returns the created MultiLinePoint
+     */
+    public push(item?: (AbstractMesh | Control | { x: string | number, y: string | number })): MultiLinePoint {
+        var point: MultiLinePoint = this.getAt(this._points.length);
 
-            if (item instanceof AbstractMesh) {
-                point.mesh = item;
-            }
-            else if (item instanceof Control) {
-                point.control = item;
-            }
-            else if (item.x != null && item.y != null) {
-                point.x = item.x;
-                point.y = item.y;
-            }
+        if (item == null) return point;
 
-            return point;
+        if (item instanceof AbstractMesh) {
+            point.mesh = item;
+        }
+        else if (item instanceof Control) {
+            point.control = item;
+        }
+        else if (item.x != null && item.y != null) {
+            point.x = item.x;
+            point.y = item.y;
         }
 
-        /**
-         * Remove a specific value or point from the active point collection
-         * @param value defines the value or point to remove
-         */
-        public remove(value: number | MultiLinePoint): void {
-            var index: number;
-            
-            if (value instanceof MultiLinePoint) {
-                index = this._points.indexOf(value);
-
-                if (index === -1) {
-                    return;
-                }
-            }
-            else {
-                index = value;
-            }
-            
-            var point: Nullable<MultiLinePoint> = this._points[index];
+        return point;
+    }
 
-            if (!point) {
+    /**
+     * Remove a specific value or point from the active point collection
+     * @param value defines the value or point to remove
+     */
+    public remove(value: number | MultiLinePoint): void {
+        var index: number;
+
+        if (value instanceof MultiLinePoint) {
+            index = this._points.indexOf(value);
+
+            if (index === -1) {
                 return;
             }
+        }
+        else {
+            index = value;
+        }
 
-            point.dispose();
+        var point: Nullable<MultiLinePoint> = this._points[index];
 
-            this._points.splice(index, 1);
-        }
-        
-        /** Gets or sets line width */
-        public get lineWidth(): number {
-            return this._lineWidth;
+        if (!point) {
+            return;
         }
 
-        public set lineWidth(value: number) {
-            if (this._lineWidth === value) {
-                return;
-            }
+        point.dispose();
 
-            this._lineWidth = value;
-            this._markAsDirty();
-        }   
+        this._points.splice(index, 1);
+    }
 
-        public set horizontalAlignment(value: number) {
-            return;
-        } 
+    /** Gets or sets line width */
+    public get lineWidth(): number {
+        return this._lineWidth;
+    }
 
-        public set verticalAlignment(value: number) {
+    public set lineWidth(value: number) {
+        if (this._lineWidth === value) {
             return;
         }
 
-        protected _getTypeName(): string {
-            return "MultiLine";
-        }              
-
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
-
-            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                context.shadowColor = this.shadowColor;
-                context.shadowBlur = this.shadowBlur;
-                context.shadowOffsetX = this.shadowOffsetX;
-                context.shadowOffsetY = this.shadowOffsetY;
-            }
+        this._lineWidth = value;
+        this._markAsDirty();
+    }
 
-            this._applyStates(context);
+    public set horizontalAlignment(value: number) {
+        return;
+    }
 
-            if (this._processMeasures(parentMeasure, context)) {
-                context.strokeStyle = this.color;
-                context.lineWidth = this._lineWidth;
-                context.setLineDash(this._dash);
+    public set verticalAlignment(value: number) {
+        return;
+    }
 
-                context.beginPath();
+    protected _getTypeName(): string {
+        return "MultiLine";
+    }
 
-                var first: boolean = true; //first index is not necessarily 0
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
 
-                this._points.forEach(point => {
-                    if (!point) {
-                        return;
-                    }
+        if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+            context.shadowColor = this.shadowColor;
+            context.shadowBlur = this.shadowBlur;
+            context.shadowOffsetX = this.shadowOffsetX;
+            context.shadowOffsetY = this.shadowOffsetY;
+        }
 
-                    if (first) {
-                        context.moveTo(point._point.x, point._point.y);
+        this._applyStates(context);
 
-                        first = false;
-                    }
-                    else {
-                        context.lineTo(point._point.x, point._point.y);
-                    }
-                });
+        if (this._processMeasures(parentMeasure, context)) {
+            context.strokeStyle = this.color;
+            context.lineWidth = this._lineWidth;
+            context.setLineDash(this._dash);
 
-                context.stroke();
-            }
+            context.beginPath();
 
-            context.restore();
-        }
+            var first: boolean = true; //first index is not necessarily 0
 
-        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            this._minX = null;
-            this._minY = null;
-            this._maxX = null;
-            this._maxY = null;
-            
-            this._points.forEach((point, index) => {
+            this._points.forEach(point => {
                 if (!point) {
                     return;
                 }
 
-                point.translate();
+                if (first) {
+                    context.moveTo(point._point.x, point._point.y);
 
-                if (this._minX == null || point._point.x < this._minX) this._minX = point._point.x;
-                if (this._minY == null || point._point.y < this._minY) this._minY = point._point.y;
-                if (this._maxX == null || point._point.x > this._maxX) this._maxX = point._point.x;
-                if (this._maxY == null || point._point.y > this._maxY) this._maxY = point._point.y;
+                    first = false;
+                }
+                else {
+                    context.lineTo(point._point.x, point._point.y);
+                }
             });
 
-            if (this._minX == null) this._minX = 0;
-            if (this._minY == null) this._minY = 0;
-            if (this._maxX == null) this._maxX = 0;
-            if (this._maxY == null) this._maxY = 0;
+            context.stroke();
         }
 
-        public _measure(): void {
-            if (this._minX == null || this._maxX == null || this._minY == null || this._maxY == null) {
+        context.restore();
+    }
+
+    protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        this._minX = null;
+        this._minY = null;
+        this._maxX = null;
+        this._maxY = null;
+
+        this._points.forEach((point, index) => {
+            if (!point) {
                 return;
             }
 
-            this._currentMeasure.width = Math.abs(this._maxX - this._minX) + this._lineWidth;
-            this._currentMeasure.height = Math.abs(this._maxY - this._minY) + this._lineWidth;
+            point.translate();
+
+            if (this._minX == null || point._point.x < this._minX) this._minX = point._point.x;
+            if (this._minY == null || point._point.y < this._minY) this._minY = point._point.y;
+            if (this._maxX == null || point._point.x > this._maxX) this._maxX = point._point.x;
+            if (this._maxY == null || point._point.y > this._maxY) this._maxY = point._point.y;
+        });
+
+        if (this._minX == null) this._minX = 0;
+        if (this._minY == null) this._minY = 0;
+        if (this._maxX == null) this._maxX = 0;
+        if (this._maxY == null) this._maxY = 0;
+    }
+
+    public _measure(): void {
+        if (this._minX == null || this._maxX == null || this._minY == null || this._maxY == null) {
+            return;
         }
 
-        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            if (this._minX == null || this._minY == null) {
-                return;
-            }
+        this._currentMeasure.width = Math.abs(this._maxX - this._minX) + this._lineWidth;
+        this._currentMeasure.height = Math.abs(this._maxY - this._minY) + this._lineWidth;
+    }
 
-            this._currentMeasure.left = this._minX - this._lineWidth / 2;
-            this._currentMeasure.top = this._minY - this._lineWidth / 2;  
+    protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        if (this._minX == null || this._minY == null) {
+            return;
         }
 
-        public dispose(): void {
-            while (this._points.length > 0) {
-                this.remove(this._points.length - 1);
-            }
+        this._currentMeasure.left = this._minX - this._lineWidth / 2;
+        this._currentMeasure.top = this._minY - this._lineWidth / 2;
+    }
 
-            super.dispose();
+    public dispose(): void {
+        while (this._points.length > 0) {
+            this.remove(this._points.length - 1);
         }
 
-    }    
-}
+        super.dispose();
+    }
+
+}    

+ 136 - 136
gui/src/2D/controls/radioButton.ts

@@ -1,172 +1,172 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
-    /**
-     * Class used to create radio button controls
-     */
-    export class RadioButton extends Control {
-        private _isChecked = false;
-        private _background = "black";   
-        private _checkSizeRatio = 0.8;
-        private _thickness = 1;
-        
-        /** Gets or sets border thickness */
-        public get thickness(): number {
-            return this._thickness;
+import { Control } from "./control";
+import { Observable, Vector2 } from "babylonjs";
+import { Measure } from "../measure";
+
+/**
+ * Class used to create radio button controls
+ */
+export class RadioButton extends Control {
+    private _isChecked = false;
+    private _background = "black";
+    private _checkSizeRatio = 0.8;
+    private _thickness = 1;
+
+    /** Gets or sets border thickness */
+    public get thickness(): number {
+        return this._thickness;
+    }
+
+    public set thickness(value: number) {
+        if (this._thickness === value) {
+            return;
         }
 
-        public set thickness(value: number) {
-            if (this._thickness === value) {
-                return;
-            }
+        this._thickness = value;
+        this._markAsDirty();
+    }
 
-            this._thickness = value;
-            this._markAsDirty();
-        }           
+    /** Gets or sets group name */
+    public group = "";
 
-        /** Gets or sets group name */
-        public group = "";        
+    /** Observable raised when isChecked is changed */
+    public onIsCheckedChangedObservable = new Observable<boolean>();
 
-        /** Observable raised when isChecked is changed */
-        public onIsCheckedChangedObservable = new Observable<boolean>();
+    /** Gets or sets a value indicating the ratio between overall size and check size */
+    public get checkSizeRatio(): number {
+        return this._checkSizeRatio;
+    }
 
-        /** Gets or sets a value indicating the ratio between overall size and check size */
-        public get checkSizeRatio(): number {
-            return this._checkSizeRatio;
-        }
+    public set checkSizeRatio(value: number) {
+        value = Math.max(Math.min(1, value), 0);
 
-        public set checkSizeRatio(value: number) {
-            value = Math.max(Math.min(1, value), 0);
+        if (this._checkSizeRatio === value) {
+            return;
+        }
 
-            if (this._checkSizeRatio === value) {
-                return;
-            }
+        this._checkSizeRatio = value;
+        this._markAsDirty();
+    }
 
-            this._checkSizeRatio = value;
-            this._markAsDirty();
-        }             
+    /** Gets or sets background color */
+    public get background(): string {
+        return this._background;
+    }
 
-        /** Gets or sets background color */
-        public get background(): string {
-            return this._background;
+    public set background(value: string) {
+        if (this._background === value) {
+            return;
         }
 
-        public set background(value: string) {
-            if (this._background === value) {
-                return;
-            }
+        this._background = value;
+        this._markAsDirty();
+    }
 
-            this._background = value;
-            this._markAsDirty();
-        }     
+    /** Gets or sets a boolean indicating if the checkbox is checked or not */
+    public get isChecked(): boolean {
+        return this._isChecked;
+    }
 
-        /** Gets or sets a boolean indicating if the checkbox is checked or not */
-        public get isChecked(): boolean {
-            return this._isChecked;
+    public set isChecked(value: boolean) {
+        if (this._isChecked === value) {
+            return;
         }
 
-        public set isChecked(value: boolean) {
-            if (this._isChecked === value) {
-                return;
-            }
+        this._isChecked = value;
+        this._markAsDirty();
 
-            this._isChecked = value;
-            this._markAsDirty();
-
-            this.onIsCheckedChangedObservable.notifyObservers(value);
-
-            if (this._isChecked && this._host) {
-                // Update all controls from same group
-                this._host.executeOnAllControls((control) => {
-                    if (control === this) {
-                        return;
-                    }
-
-                    if ((<any>control).group === undefined) {
-                        return;
-                    }
-                    var childRadio = (<RadioButton>control);
-                    if (childRadio.group === this.group) {
-                        childRadio.isChecked = false;
-                    }
-                });
-            }
-        }                             
+        this.onIsCheckedChangedObservable.notifyObservers(value);
 
-        /**
-         * Creates a new RadioButton
-         * @param name defines the control name
-         */        
-        constructor(public name?: string) {
-            super(name);
+        if (this._isChecked && this._host) {
+            // Update all controls from same group
+            this._host.executeOnAllControls((control) => {
+                if (control === this) {
+                    return;
+                }
 
-            this.isPointerBlocker = true;
+                if ((<any>control).group === undefined) {
+                    return;
+                }
+                var childRadio = (<RadioButton>control);
+                if (childRadio.group === this.group) {
+                    childRadio.isChecked = false;
+                }
+            });
         }
+    }
+
+    /**
+     * Creates a new RadioButton
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
 
-        protected _getTypeName(): string {
-            return "RadioButton";
-        }              
+        this.isPointerBlocker = true;
+    }
 
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
+    protected _getTypeName(): string {
+        return "RadioButton";
+    }
 
-            this._applyStates(context);
-            if (this._processMeasures(parentMeasure, context)) {
-                let actualWidth = this._currentMeasure.width - this._thickness;
-                let actualHeight = this._currentMeasure.height - this._thickness;
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
 
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                    context.shadowColor = this.shadowColor;
-                    context.shadowBlur = this.shadowBlur;
-                    context.shadowOffsetX = this.shadowOffsetX;
-                    context.shadowOffsetY = this.shadowOffsetY;
-                }
-                
-                // Outer
-                Control.drawEllipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, 
-                            this._currentMeasure.width / 2 - this._thickness / 2, this._currentMeasure.height / 2 - this._thickness / 2, context);
-                
-                context.fillStyle = this._background;
-                context.fill();
+        this._applyStates(context);
+        if (this._processMeasures(parentMeasure, context)) {
+            let actualWidth = this._currentMeasure.width - this._thickness;
+            let actualHeight = this._currentMeasure.height - this._thickness;
 
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                    context.shadowBlur = 0;
-                    context.shadowOffsetX = 0;
-                    context.shadowOffsetY = 0;
-                }
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
+            }
+
+            // Outer
+            Control.drawEllipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2,
+                this._currentMeasure.width / 2 - this._thickness / 2, this._currentMeasure.height / 2 - this._thickness / 2, context);
 
-                context.strokeStyle = this.color;
-                context.lineWidth = this._thickness;
+            context.fillStyle = this._background;
+            context.fill();
 
-                context.stroke();
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowBlur = 0;
+                context.shadowOffsetX = 0;
+                context.shadowOffsetY = 0;
+            }
 
-                // Inner
-                if (this._isChecked) {
-                    context.fillStyle = this.color;
-                    let offsetWidth = actualWidth * this._checkSizeRatio;
-                    let offseHeight = actualHeight * this._checkSizeRatio;
+            context.strokeStyle = this.color;
+            context.lineWidth = this._thickness;
 
-                    Control.drawEllipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, 
-                                    offsetWidth / 2 - this._thickness / 2, offseHeight / 2  - this._thickness / 2, context);
+            context.stroke();
 
-                    context.fill();
-                }
+            // Inner
+            if (this._isChecked) {
+                context.fillStyle = this.color;
+                let offsetWidth = actualWidth * this._checkSizeRatio;
+                let offseHeight = actualHeight * this._checkSizeRatio;
 
+                Control.drawEllipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2,
+                    offsetWidth / 2 - this._thickness / 2, offseHeight / 2 - this._thickness / 2, context);
+
+                context.fill();
             }
-            context.restore();
+
         }
+        context.restore();
+    }
 
-        // Events
-        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
-                return false;
-            }
-            
-            if (!this.isChecked) {
-                this.isChecked = true;
-            }
+    // Events
+    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
+        if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
+            return false;
+        }
 
-            return true;
+        if (!this.isChecked) {
+            this.isChecked = true;
         }
-    }    
-}
+
+        return true;
+    }
+}   

+ 117 - 118
gui/src/2D/controls/rectangle.ts

@@ -1,136 +1,135 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
-    /** Class used to create rectangle container */
-    export class Rectangle extends Container {
-        private _thickness = 1;
-        private _cornerRadius = 0;
-        
-        /** Gets or sets border thickness */        
-        public get thickness(): number {
-            return this._thickness;
+import { Container } from "./container";
+import { Measure } from "../measure";
+
+/** Class used to create rectangle container */
+export class Rectangle extends Container {
+    private _thickness = 1;
+    private _cornerRadius = 0;
+
+    /** Gets or sets border thickness */
+    public get thickness(): number {
+        return this._thickness;
+    }
+
+    public set thickness(value: number) {
+        if (this._thickness === value) {
+            return;
         }
 
-        public set thickness(value: number) {
-            if (this._thickness === value) {
-                return;
-            }
+        this._thickness = value;
+        this._markAsDirty();
+    }
 
-            this._thickness = value;
-            this._markAsDirty();
-        }   
-        
-        /** Gets or sets the corner radius angle */
-        public get cornerRadius(): number {
-            return this._cornerRadius;
-        }
+    /** Gets or sets the corner radius angle */
+    public get cornerRadius(): number {
+        return this._cornerRadius;
+    }
 
-        public set cornerRadius(value: number) {
-            if (value < 0) {
-                value = 0;
-            }
+    public set cornerRadius(value: number) {
+        if (value < 0) {
+            value = 0;
+        }
 
-            if (this._cornerRadius === value) {
-                return;
-            }
+        if (this._cornerRadius === value) {
+            return;
+        }
 
-            this._cornerRadius = value;
-            this._markAsDirty();
-        }   
-     
-        /**
-         * Creates a new Rectangle
-         * @param name defines the control name
-         */       
-        constructor(public name?: string) {
-            super(name);
+        this._cornerRadius = value;
+        this._markAsDirty();
+    }
+
+    /**
+     * Creates a new Rectangle
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
+    }
+
+    protected _getTypeName(): string {
+        return "Rectangle";
+    }
+
+    protected _localDraw(context: CanvasRenderingContext2D): void {
+        context.save();
+
+        if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+            context.shadowColor = this.shadowColor;
+            context.shadowBlur = this.shadowBlur;
+            context.shadowOffsetX = this.shadowOffsetX;
+            context.shadowOffsetY = this.shadowOffsetY;
         }
 
-        protected _getTypeName(): string {
-            return "Rectangle";
-        }              
-
-        protected _localDraw(context: CanvasRenderingContext2D): void {
-            context.save();
-            
-            if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                context.shadowColor = this.shadowColor;
-                context.shadowBlur = this.shadowBlur;
-                context.shadowOffsetX = this.shadowOffsetX;
-                context.shadowOffsetY = this.shadowOffsetY;
+        if (this._background) {
+            context.fillStyle = this._background;
+
+            if (this._cornerRadius) {
+                this._drawRoundedRect(context, this._thickness / 2);
+                context.fill();
+            } else {
+                context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
             }
+        }
 
-            if (this._background) {
-                context.fillStyle = this._background;
+        if (this._thickness) {
 
-                if (this._cornerRadius) {
-                    this._drawRoundedRect(context, this._thickness / 2);
-                    context.fill();
-                } else {
-                    context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                }
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowBlur = 0;
+                context.shadowOffsetX = 0;
+                context.shadowOffsetY = 0;
             }
 
-            if (this._thickness) {
-
-                if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
-                    context.shadowBlur = 0;
-                    context.shadowOffsetX = 0;
-                    context.shadowOffsetY = 0;
-                }
-
-                if (this.color) {
-                    context.strokeStyle = this.color;
-                }
-                context.lineWidth = this._thickness;
-
-                if (this._cornerRadius) {
-                    this._drawRoundedRect(context, this._thickness / 2);
-                    context.stroke();
-                } else {                
-                    context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2, 
-                                       this._currentMeasure.width - this._thickness, this._currentMeasure.height - this._thickness);
-                }
+            if (this.color) {
+                context.strokeStyle = this.color;
             }
+            context.lineWidth = this._thickness;
 
-            context.restore();
-        }
-
-        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
-            super._additionalProcessing(parentMeasure, context);
-
-            this._measureForChildren.width -= 2 * this._thickness;
-            this._measureForChildren.height -= 2 * this._thickness;
-            this._measureForChildren.left += this._thickness;
-            this._measureForChildren.top += this._thickness;            
-        }
-
-        private _drawRoundedRect(context: CanvasRenderingContext2D, offset: number = 0): void {
-            var x = this._currentMeasure.left + offset;
-            var y = this._currentMeasure.top + offset;
-            var width = this._currentMeasure.width - offset * 2;
-            var height = this._currentMeasure.height - offset * 2;
-
-            var radius = Math.min(height / 2 - 2, Math.min(width / 2 - 2, this._cornerRadius));
-
-            context.beginPath();
-            context.moveTo(x + radius, y);
-            context.lineTo(x + width - radius, y);
-            context.quadraticCurveTo(x + width, y, x + width, y + radius);
-            context.lineTo(x + width, y + height - radius);
-            context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
-            context.lineTo(x + radius, y + height);
-            context.quadraticCurveTo(x, y + height, x, y + height - radius);
-            context.lineTo(x, y + radius);
-            context.quadraticCurveTo(x, y, x + radius, y);
-            context.closePath();
-        } 
-
-        protected _clipForChildren(context: CanvasRenderingContext2D) {
             if (this._cornerRadius) {
-                this._drawRoundedRect(context, this._thickness);
-                context.clip();
+                this._drawRoundedRect(context, this._thickness / 2);
+                context.stroke();
+            } else {
+                context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2,
+                    this._currentMeasure.width - this._thickness, this._currentMeasure.height - this._thickness);
             }
         }
-    }    
-}
+
+        context.restore();
+    }
+
+    protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        super._additionalProcessing(parentMeasure, context);
+
+        this._measureForChildren.width -= 2 * this._thickness;
+        this._measureForChildren.height -= 2 * this._thickness;
+        this._measureForChildren.left += this._thickness;
+        this._measureForChildren.top += this._thickness;
+    }
+
+    private _drawRoundedRect(context: CanvasRenderingContext2D, offset: number = 0): void {
+        var x = this._currentMeasure.left + offset;
+        var y = this._currentMeasure.top + offset;
+        var width = this._currentMeasure.width - offset * 2;
+        var height = this._currentMeasure.height - offset * 2;
+
+        var radius = Math.min(height / 2 - 2, Math.min(width / 2 - 2, this._cornerRadius));
+
+        context.beginPath();
+        context.moveTo(x + radius, y);
+        context.lineTo(x + width - radius, y);
+        context.quadraticCurveTo(x + width, y, x + width, y + radius);
+        context.lineTo(x + width, y + height - radius);
+        context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
+        context.lineTo(x + radius, y + height);
+        context.quadraticCurveTo(x, y + height, x, y + height - radius);
+        context.lineTo(x, y + radius);
+        context.quadraticCurveTo(x, y, x + radius, y);
+        context.closePath();
+    }
+
+    protected _clipForChildren(context: CanvasRenderingContext2D) {
+        if (this._cornerRadius) {
+            this._drawRoundedRect(context, this._thickness);
+            context.clip();
+        }
+    }
+}    

+ 359 - 358
gui/src/2D/controls/slider.ts

@@ -1,463 +1,464 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Control } from "./control";
+import { ValueAndUnit } from "../valueAndUnit";
+import { Observable, Vector2 } from "babylonjs";
+import { Measure } from "../measure";
+
+/**
+ * Class used to create slider controls
+ */
+export class Slider extends Control {
+    private _thumbWidth = new ValueAndUnit(20, ValueAndUnit.UNITMODE_PIXEL, false);
+    private _minimum = 0;
+    private _maximum = 100;
+    private _value = 50;
+    private _isVertical = false;
+    private _background = "black";
+    private _borderColor = "white";
+    private _barOffset = new ValueAndUnit(5, ValueAndUnit.UNITMODE_PIXEL, false);
+    private _isThumbCircle = false;
+    private _isThumbClamped = false;
+
+    /** Observable raised when the sldier value changes */
+    public onValueChangedObservable = new Observable<number>();
+
+    /** Gets or sets border color */
+    public get borderColor(): string {
+        return this._borderColor;
+    }
 
-module BABYLON.GUI {
-    /**
-     * Class used to create slider controls
-     */
-    export class Slider extends Control {
-        private _thumbWidth = new ValueAndUnit(20, ValueAndUnit.UNITMODE_PIXEL, false);
-        private _minimum = 0;
-        private _maximum = 100;
-        private _value = 50;
-        private _isVertical = false;
-        private _background = "black";
-        private _borderColor = "white";
-        private _barOffset = new ValueAndUnit(5, ValueAndUnit.UNITMODE_PIXEL, false);
-        private _isThumbCircle = false;
-        private _isThumbClamped = false;
-
-        /** Observable raised when the sldier value changes */
-        public onValueChangedObservable = new Observable<number>();
-
-        /** Gets or sets border color */
-        public get borderColor(): string {
-            return this._borderColor;
+    public set borderColor(value: string) {
+        if (this._borderColor === value) {
+            return;
         }
 
-        public set borderColor(value: string) {
-            if (this._borderColor === value) {
-                return;
-            }
+        this._borderColor = value;
+        this._markAsDirty();
+    }
 
-            this._borderColor = value;
-            this._markAsDirty();
-        }
+    /** Gets or sets background color */
+    public get background(): string {
+        return this._background;
+    }
 
-        /** Gets or sets background color */
-        public get background(): string {
-            return this._background;
+    public set background(value: string) {
+        if (this._background === value) {
+            return;
         }
 
-        public set background(value: string) {
-            if (this._background === value) {
-                return;
-            }
+        this._background = value;
+        this._markAsDirty();
+    }
 
-            this._background = value;
-            this._markAsDirty();
-        }
+    /** Gets or sets main bar offset */
+    public get barOffset(): string | number {
+        return this._barOffset.toString(this._host);
+    }
 
-        /** Gets or sets main bar offset */
-        public get barOffset(): string | number {
-            return this._barOffset.toString(this._host);
+    /** Gets main bar offset in pixels*/
+    public get barOffsetInPixels(): number {
+        return this._barOffset.getValueInPixel(this._host, this._cachedParentMeasure.width);
+    }
+
+    public set barOffset(value: string | number) {
+        if (this._barOffset.toString(this._host) === value) {
+            return;
         }
 
-        /** Gets main bar offset in pixels*/
-        public get barOffsetInPixels(): number {
-            return this._barOffset.getValueInPixel(this._host, this._cachedParentMeasure.width);
+        if (this._barOffset.fromString(value)) {
+            this._markAsDirty();
         }
+    }
 
-        public set barOffset(value: string | number) {
-            if (this._barOffset.toString(this._host) === value) {
-                return;
-            }
+    /** Gets or sets thumb width */
+    public get thumbWidth(): string | number {
+        return this._thumbWidth.toString(this._host);
+    }
 
-            if (this._barOffset.fromString(value)) {
-                this._markAsDirty();
-            }
-        }
+    /** Gets thumb width in pixels */
+    public get thumbWidthInPixels(): number {
+        return this._thumbWidth.getValueInPixel(this._host, this._cachedParentMeasure.width);
+    }
 
-        /** Gets or sets thumb width */
-        public get thumbWidth(): string | number {
-            return this._thumbWidth.toString(this._host);
+    public set thumbWidth(value: string | number) {
+        if (this._thumbWidth.toString(this._host) === value) {
+            return;
         }
 
-        /** Gets thumb width in pixels */       
-        public get thumbWidthInPixels(): number {
-            return this._thumbWidth.getValueInPixel(this._host, this._cachedParentMeasure.width);
+        if (this._thumbWidth.fromString(value)) {
+            this._markAsDirty();
         }
+    }
 
-        public set thumbWidth(value: string | number) {
-            if (this._thumbWidth.toString(this._host) === value) {
-                return;
-            }
+    /** Gets or sets minimum value */
+    public get minimum(): number {
+        return this._minimum;
+    }
 
-            if (this._thumbWidth.fromString(value)) {
-                this._markAsDirty();
-            }
+    public set minimum(value: number) {
+        if (this._minimum === value) {
+            return;
         }
 
-        /** Gets or sets minimum value */
-        public get minimum(): number {
-            return this._minimum;
-        }
+        this._minimum = value;
+        this._markAsDirty();
 
-        public set minimum(value: number) {
-            if (this._minimum === value) {
-                return;
-            }
+        this.value = Math.max(Math.min(this.value, this._maximum), this._minimum);
+    }
 
-            this._minimum = value;
-            this._markAsDirty();
+    /** Gets or sets maximum value */
+    public get maximum(): number {
+        return this._maximum;
+    }
 
-            this.value = Math.max(Math.min(this.value, this._maximum), this._minimum);
+    public set maximum(value: number) {
+        if (this._maximum === value) {
+            return;
         }
 
-        /** Gets or sets maximum value */        
-        public get maximum(): number {
-            return this._maximum;
-        }
+        this._maximum = value;
+        this._markAsDirty();
 
-        public set maximum(value: number) {
-            if (this._maximum === value) {
-                return;
-            }
+        this.value = Math.max(Math.min(this.value, this._maximum), this._minimum);
+    }
 
-            this._maximum = value;
-            this._markAsDirty();
+    /** Gets or sets current value */
+    public get value(): number {
+        return this._value;
+    }
 
-            this.value = Math.max(Math.min(this.value, this._maximum), this._minimum);
-        }
+    public set value(value: number) {
+        value = Math.max(Math.min(value, this._maximum), this._minimum);
 
-        /** Gets or sets current value */
-        public get value(): number {
-            return this._value;
+        if (this._value === value) {
+            return;
         }
 
-        public set value(value: number) {
-            value = Math.max(Math.min(value, this._maximum), this._minimum);
+        this._value = value;
+        this._markAsDirty();
+        this.onValueChangedObservable.notifyObservers(this._value);
+    }
 
-            if (this._value === value) {
-                return;
-            }
+    /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
+    public get isVertical(): boolean {
+        return this._isVertical;
+    }
 
-            this._value = value;
-            this._markAsDirty();
-            this.onValueChangedObservable.notifyObservers(this._value);
+    public set isVertical(value: boolean) {
+        if (this._isVertical === value) {
+            return;
         }
 
-        /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
-        public get isVertical(): boolean {
-            return this._isVertical;
-        }
+        this._isVertical = value;
+        this._markAsDirty();
+    }
 
-        public set isVertical(value: boolean) {
-            if(this._isVertical === value){
-                return;
-            }
+    /** Gets or sets a boolean indicating if the thumb should be round or square */
+    public get isThumbCircle(): boolean {
+        return this._isThumbCircle;
+    }
 
-            this._isVertical = value;
-            this._markAsDirty();
+    public set isThumbCircle(value: boolean) {
+        if (this._isThumbCircle === value) {
+            return;
         }
 
-        /** Gets or sets a boolean indicating if the thumb should be round or square */
-        public get isThumbCircle(): boolean {
-            return this._isThumbCircle;
-        }
+        this._isThumbCircle = value;
+        this._markAsDirty();
+    }
 
-        public set isThumbCircle(value: boolean) {
-            if (this._isThumbCircle === value) {
-                return;
-            }
+    /** Gets or sets a value indicating if the thumb can go over main bar extends */
+    public get isThumbClamped(): boolean {
+        return this._isThumbClamped;
+    }
 
-            this._isThumbCircle = value;
-            this._markAsDirty();
+    public set isThumbClamped(value: boolean) {
+        if (this._isThumbClamped === value) {
+            return;
         }
 
-        /** Gets or sets a value indicating if the thumb can go over main bar extends */
-        public get isThumbClamped(): boolean {
-            return this._isThumbClamped;
-        }
+        this._isThumbClamped = value;
+        this._markAsDirty();
+    }
 
-        public set isThumbClamped(value: boolean) {
-            if (this._isThumbClamped === value) {
-                return;
-            }
+    /**
+     * Creates a new Slider
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
 
-            this._isThumbClamped = value;
-            this._markAsDirty();
-        }
+        this.isPointerBlocker = true;
+    }
 
-       /**
-        * Creates a new Slider
-        * @param name defines the control name
-        */
-        constructor(public name?: string) {
-            super(name);
+    protected _getTypeName(): string {
+        return "Slider";
+    }
 
-            this.isPointerBlocker = true;
+    protected _getThumbThickness(type: string, backgroundLength: number): number {
+        var thumbThickness = 0;
+        switch (type) {
+            case "circle":
+                if (this._thumbWidth.isPixel) {
+                    thumbThickness = Math.max(this._thumbWidth.getValue(this._host), backgroundLength);
+                }
+                else {
+                    thumbThickness = backgroundLength * this._thumbWidth.getValue(this._host);
+                }
+                break;
+            case "rectangle":
+                if (this._thumbWidth.isPixel) {
+                    thumbThickness = Math.min(this._thumbWidth.getValue(this._host), backgroundLength);
+                }
+                else {
+                    thumbThickness = backgroundLength * this._thumbWidth.getValue(this._host);
+                }
         }
+        return thumbThickness;
+    }
 
-        protected _getTypeName(): string {
-            return "Slider";
-        }
 
-        protected _getThumbThickness(type:string, backgroundLength:number): number {
-            var thumbThickness = 0;
-            switch(type) {
-                case "circle":
-                    if (this._thumbWidth.isPixel) {
-                        thumbThickness = Math.max(this._thumbWidth.getValue(this._host), backgroundLength);
-                    }
-                    else {
-                        thumbThickness = backgroundLength * this._thumbWidth.getValue(this._host);
-                    }
-                    break;
-                case "rectangle":
-                    if (this._thumbWidth.isPixel) {
-                        thumbThickness = Math.min(this._thumbWidth.getValue(this._host), backgroundLength);
-                    }
-                    else {
-                        thumbThickness = backgroundLength * this._thumbWidth.getValue(this._host);
-                    }
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
+
+        this._applyStates(context);
+        if (this._processMeasures(parentMeasure, context)) {
+            // Main bar
+            var effectiveBarOffset = 0;
+            var type = this.isThumbCircle ? "circle" : "rectangle";
+            var left = this._currentMeasure.left;
+            var top = this._currentMeasure.top;
+            var width = this._currentMeasure.width;
+            var height = this._currentMeasure.height;
+
+            var backgroundBoxLength = Math.max(this._currentMeasure.width, this._currentMeasure.height);
+            var backgroundBoxThickness = Math.min(this._currentMeasure.width, this._currentMeasure.height);
+
+            var effectiveThumbThickness = this._getThumbThickness(type, backgroundBoxThickness);
+            backgroundBoxLength -= effectiveThumbThickness;
+
+            var radius = 0;
+
+
+            //throw error when height is less than width for vertical slider
+            if ((this._isVertical && this._currentMeasure.height < this._currentMeasure.width)) {
+                console.error("Height should be greater than width");
+                return;
+            }
+            if (this._barOffset.isPixel) {
+                effectiveBarOffset = Math.min(this._barOffset.getValue(this._host), backgroundBoxThickness);
+            }
+            else {
+                effectiveBarOffset = backgroundBoxThickness * this._barOffset.getValue(this._host);
             }
-            return thumbThickness;
-        }
 
+            backgroundBoxThickness -= (effectiveBarOffset * 2);
 
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
-
-            this._applyStates(context);
-            if (this._processMeasures(parentMeasure, context)) {
-                // Main bar
-                var effectiveBarOffset = 0;
-                var type = this.isThumbCircle ? "circle" : "rectangle";
-                var left = this._currentMeasure.left;
-                var top = this._currentMeasure.top;
-                var width = this._currentMeasure.width;
-                var height = this._currentMeasure.height;
-            
-                var backgroundBoxLength = Math.max(this._currentMeasure.width, this._currentMeasure.height);
-                var backgroundBoxThickness = Math.min(this._currentMeasure.width, this._currentMeasure.height);
-                
-                var effectiveThumbThickness = this._getThumbThickness(type, backgroundBoxThickness);
-                backgroundBoxLength -= effectiveThumbThickness;
-
-                var radius = 0;
-
-
-                //throw error when height is less than width for vertical slider
-                if ((this._isVertical && this._currentMeasure.height < this._currentMeasure.width)) {
-                    console.error("Height should be greater than width");
-                    return;
-                }
-                if (this._barOffset.isPixel) {
-                    effectiveBarOffset = Math.min(this._barOffset.getValue(this._host), backgroundBoxThickness);
+            if (this._isVertical) {
+                left += effectiveBarOffset;
+                if (!this.isThumbClamped) {
+                    top += (effectiveThumbThickness / 2);
                 }
-                else {
-                    effectiveBarOffset = backgroundBoxThickness * this._barOffset.getValue(this._host);
+
+                height = backgroundBoxLength;
+                width = backgroundBoxThickness;
+
+            }
+            else {
+                top += effectiveBarOffset;
+                if (!this.isThumbClamped) {
+                    left += (effectiveThumbThickness / 2);
                 }
+                height = backgroundBoxThickness;
+                width = backgroundBoxLength;
+            }
 
-                backgroundBoxThickness -= (effectiveBarOffset * 2);
+            if (this.isThumbClamped && this.isThumbCircle) {
+                if (this._isVertical)
+                    top += (effectiveThumbThickness / 2);
+                else
+                    left += (effectiveThumbThickness / 2);
 
-                if (this._isVertical) {
-                    left += effectiveBarOffset;
-                    if(!this.isThumbClamped) {
-                       top += (effectiveThumbThickness / 2);
-                    }
-    
-                    height = backgroundBoxLength;
-                    width = backgroundBoxThickness;
+                radius = backgroundBoxThickness / 2;
+            }
+            else {
+                radius = (effectiveThumbThickness - effectiveBarOffset) / 2;
+            }
+
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
+            }
+
+            var thumbPosition = (this._isVertical) ? ((this._maximum - this._value) / (this._maximum - this._minimum)) * backgroundBoxLength : ((this._value - this._minimum) / (this._maximum - this._minimum)) * backgroundBoxLength;
+            context.fillStyle = this._background;
 
+            if (this._isVertical) {
+                if (this.isThumbClamped) {
+                    if (this.isThumbCircle) {
+                        context.beginPath();
+                        context.arc(left + backgroundBoxThickness / 2, top, radius, Math.PI, 2 * Math.PI);
+                        context.fill();
+                        context.fillRect(left, top, width, height);
+                    }
+                    else {
+                        context.fillRect(left, top, width, height + effectiveThumbThickness);
+                    }
                 }
                 else {
-                    top += effectiveBarOffset;
-                    if(!this.isThumbClamped) {
-                       left += (effectiveThumbThickness / 2);
-                    }
-                    height = backgroundBoxThickness;
-                    width = backgroundBoxLength;
+                    context.fillRect(left, top, width, height);
                 }
-
-                if(this.isThumbClamped && this.isThumbCircle){
-                    if(this._isVertical)
-                        top += (effectiveThumbThickness / 2);
-                    else 
-                        left += (effectiveThumbThickness / 2);
-
-                    radius = backgroundBoxThickness / 2;
+            }
+            else {
+                if (this.isThumbClamped) {
+                    if (this.isThumbCircle) {
+                        context.beginPath();
+                        context.arc(left + backgroundBoxLength, top + (backgroundBoxThickness / 2), radius, 0, 2 * Math.PI);
+                        context.fill();
+                        context.fillRect(left, top, width, height);
+                    }
+                    else {
+                        context.fillRect(left, top, width + effectiveThumbThickness, height);
+                    }
                 }
-                else{
-                    radius = (effectiveThumbThickness- effectiveBarOffset) / 2;
+                else {
+                    context.fillRect(left, top, width, height);
                 }
+            }
 
-                if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
-                    context.shadowColor = this.shadowColor;
-                    context.shadowBlur = this.shadowBlur;
-                    context.shadowOffsetX = this.shadowOffsetX;
-                    context.shadowOffsetY = this.shadowOffsetY;
-                }
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowBlur = 0;
+                context.shadowOffsetX = 0;
+                context.shadowOffsetY = 0;
+            }
 
-                var thumbPosition = (this._isVertical) ? ((this._maximum - this._value) / (this._maximum - this._minimum)) * backgroundBoxLength : ((this._value - this._minimum) / (this._maximum - this._minimum)) * backgroundBoxLength;
-                context.fillStyle = this._background;
-                
-                if(this._isVertical){
-                    if (this.isThumbClamped) {
-                        if (this.isThumbCircle) {
-                            context.beginPath();
-                            context.arc(left + backgroundBoxThickness / 2, top, radius, Math.PI, 2 * Math.PI);
-                            context.fill();
-                            context.fillRect(left, top, width , height);
-                        }
-                        else {
-                            context.fillRect(left, top, width, height + effectiveThumbThickness);
-                        }
+            context.fillStyle = this.color;
+            if (this._isVertical) {
+                if (this.isThumbClamped) {
+                    if (this.isThumbCircle) {
+                        context.beginPath();
+                        context.arc(left + backgroundBoxThickness / 2, top + backgroundBoxLength, radius, 0, 2 * Math.PI);
+                        context.fill();
+                        context.fillRect(left, top + thumbPosition, width, height - thumbPosition);
                     }
                     else {
-                        context.fillRect(left, top , width, height);
+                        context.fillRect(left, top + thumbPosition, width, this._currentMeasure.height - thumbPosition);
                     }
                 }
-                else{
-                    if (this.isThumbClamped) {
-                        if (this.isThumbCircle) {
-                            context.beginPath();
-                            context.arc(left + backgroundBoxLength , top + (backgroundBoxThickness/2), radius, 0,  2* Math.PI);
-                            context.fill();
-                            context.fillRect(left, top, width, height);
-                        }
-                        else {
-                            context.fillRect(left, top, width + effectiveThumbThickness, height);
-                        }
+                else {
+                    context.fillRect(left, top + thumbPosition, width, height - thumbPosition);
+                }
+            }
+            else {
+                if (this.isThumbClamped) {
+                    if (this.isThumbCircle) {
+                        context.beginPath();
+                        context.arc(left, top + backgroundBoxThickness / 2, radius, 0, 2 * Math.PI);
+                        context.fill();
+                        context.fillRect(left, top, thumbPosition, height);
                     }
                     else {
-                        context.fillRect(left, top, width, height);
+                        context.fillRect(left, top, thumbPosition, height);
                     }
                 }
+                else {
+                    context.fillRect(left, top, thumbPosition, height);
+                }
+            }
+
 
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
+            }
+            if (this._isThumbCircle) {
+                context.beginPath();
+                if (this._isVertical) {
+                    context.arc(left + backgroundBoxThickness / 2, top + thumbPosition, radius, 0, 2 * Math.PI);
+                }
+                else {
+                    context.arc(left + thumbPosition, top + (backgroundBoxThickness / 2), radius, 0, 2 * Math.PI);
+                }
+                context.fill();
                 if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
                     context.shadowBlur = 0;
                     context.shadowOffsetX = 0;
                     context.shadowOffsetY = 0;
                 }
-                
-                context.fillStyle = this.color;
-                if(this._isVertical){
-                    if (this.isThumbClamped) {
-                        if (this.isThumbCircle) {
-                            context.beginPath();
-                            context.arc(left + backgroundBoxThickness / 2, top + backgroundBoxLength, radius, 0, 2 * Math.PI);
-                            context.fill();
-                            context.fillRect(left, top + thumbPosition, width, height - thumbPosition);
-                        }
-                        else {
-                            context.fillRect(left, top + thumbPosition, width, this._currentMeasure.height - thumbPosition);
-                        }
-                    }
-                    else {
-                        context.fillRect(left, top + thumbPosition ,width,  height - thumbPosition);
-                    }
+                context.strokeStyle = this._borderColor;
+                context.stroke();
+            }
+            else {
+                if (this._isVertical) {
+                    context.fillRect(left - effectiveBarOffset, this._currentMeasure.top + thumbPosition, this._currentMeasure.width, effectiveThumbThickness);
                 }
-                else{
-                    if (this.isThumbClamped) {
-                        if (this.isThumbCircle) {
-                            context.beginPath();
-                            context.arc(left , top + backgroundBoxThickness/2 , radius, 0, 2 * Math.PI);
-                            context.fill();
-                            context.fillRect(left, top, thumbPosition, height);
-                        }
-                        else {
-                            context.fillRect(left, top, thumbPosition, height);
-                        }
-                    }
-                    else {
-                        context.fillRect(left , top, thumbPosition,  height);
-                    }
+                else {
+                    context.fillRect(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, effectiveThumbThickness, this._currentMeasure.height);
                 }
-               
-               
                 if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
-                    context.shadowColor = this.shadowColor;
-                    context.shadowBlur = this.shadowBlur;
-                    context.shadowOffsetX = this.shadowOffsetX;
-                    context.shadowOffsetY = this.shadowOffsetY;
+                    context.shadowBlur = 0;
+                    context.shadowOffsetX = 0;
+                    context.shadowOffsetY = 0;
                 }
-                if (this._isThumbCircle) {
-                    context.beginPath();
-                    if (this._isVertical) {
-                        context.arc(left + backgroundBoxThickness / 2, top + thumbPosition, radius, 0, 2 * Math.PI);
-                    }
-                    else {
-                        context.arc(left + thumbPosition, top + ( backgroundBoxThickness/2), radius, 0, 2 * Math.PI);
-                    }
-                    context.fill();
-                    if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
-                        context.shadowBlur = 0;
-                        context.shadowOffsetX = 0;
-                        context.shadowOffsetY = 0;
-                    }
-                    context.strokeStyle = this._borderColor;
-                    context.stroke();
+                context.strokeStyle = this._borderColor;
+                if (this._isVertical) {
+                    context.strokeRect(left - effectiveBarOffset, this._currentMeasure.top + thumbPosition, this._currentMeasure.width, effectiveThumbThickness);
                 }
                 else {
-                    if (this._isVertical) {
-                        context.fillRect(left - effectiveBarOffset, this._currentMeasure.top + thumbPosition, this._currentMeasure.width, effectiveThumbThickness);
-                    }
-                    else {
-                        context.fillRect(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, effectiveThumbThickness, this._currentMeasure.height);
-                    }
-                    if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
-                        context.shadowBlur = 0;
-                        context.shadowOffsetX = 0;
-                        context.shadowOffsetY = 0;
-                    }
-                    context.strokeStyle = this._borderColor;
-                    if (this._isVertical) {
-                        context.strokeRect(left - effectiveBarOffset, this._currentMeasure.top + thumbPosition, this._currentMeasure.width, effectiveThumbThickness);
-                    }
-                    else {
-                        context.strokeRect(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, effectiveThumbThickness, this._currentMeasure.height);
-                    }
+                    context.strokeRect(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, effectiveThumbThickness, this._currentMeasure.height);
                 }
             }
-            context.restore();
         }
+        context.restore();
+    }
 
 
-        // Events
-        private _pointerIsDown = false;
+    // Events
+    private _pointerIsDown = false;
 
-        private _updateValueFromPointer(x: number, y: number): void {
-            if (this.rotation != 0) {
-                this._invertTransformMatrix.transformCoordinates(x, y, this._transformedPosition);
-                x = this._transformedPosition.x;
-                y = this._transformedPosition.y;
-            }
-            
-            if(this._isVertical){
-                this.value = this._minimum + (1 - ((y - this._currentMeasure.top) / this._currentMeasure.height)) * (this._maximum - this._minimum);
-            }
-            else{
-                this.value = this._minimum + ((x - this._currentMeasure.left) / this._currentMeasure.width) * (this._maximum - this._minimum);
-            }
+    private _updateValueFromPointer(x: number, y: number): void {
+        if (this.rotation != 0) {
+            this._invertTransformMatrix.transformCoordinates(x, y, this._transformedPosition);
+            x = this._transformedPosition.x;
+            y = this._transformedPosition.y;
         }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
-                return false;
-            }
+        if (this._isVertical) {
+            this.value = this._minimum + (1 - ((y - this._currentMeasure.top) / this._currentMeasure.height)) * (this._maximum - this._minimum);
+        }
+        else {
+            this.value = this._minimum + ((x - this._currentMeasure.left) / this._currentMeasure.width) * (this._maximum - this._minimum);
+        }
+    }
 
-            this._pointerIsDown = true;
+    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
+        if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
+            return false;
+        }
 
-            this._updateValueFromPointer(coordinates.x, coordinates.y);
-            this._host._capturingControl[pointerId] = this;
+        this._pointerIsDown = true;
 
-            return true;
-        }
+        this._updateValueFromPointer(coordinates.x, coordinates.y);
+        this._host._capturingControl[pointerId] = this;
 
-        public _onPointerMove(target: Control, coordinates: Vector2): void {
-            if (this._pointerIsDown) {
-                this._updateValueFromPointer(coordinates.x, coordinates.y);
-            }
+        return true;
+    }
 
-            super._onPointerMove(target, coordinates);
+    public _onPointerMove(target: Control, coordinates: Vector2): void {
+        if (this._pointerIsDown) {
+            this._updateValueFromPointer(coordinates.x, coordinates.y);
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
-            this._pointerIsDown = false;
+        super._onPointerMove(target, coordinates);
+    }
 
-            delete this._host._capturingControl[pointerId];
-            super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
-        }
+    public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
+        this._pointerIsDown = false;
+
+        delete this._host._capturingControl[pointerId];
+        super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
     }
 }

+ 127 - 127
gui/src/2D/controls/stackPanel.ts

@@ -1,153 +1,153 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Container } from "./container";
+import { Measure } from "../measure";
+import { Control } from "./control";
+
+/**
+ * Class used to create a 2D stack panel container
+ */
+export class StackPanel extends Container {
+    private _isVertical = true;
+    private _manualWidth = false;
+    private _manualHeight = false;
+    private _doNotTrackManualChanges = false;
+    private _tempMeasureStore = Measure.Empty();
+
+    /** Gets or sets a boolean indicating if the stack panel is vertical or horizontal*/
+    public get isVertical(): boolean {
+        return this._isVertical;
+    }
+
+    public set isVertical(value: boolean) {
+        if (this._isVertical === value) {
+            return;
+        }
 
-module BABYLON.GUI {
-    /**
-     * Class used to create a 2D stack panel container
-     */
-    export class StackPanel extends Container {
-        private _isVertical = true;
-        private _manualWidth = false;
-        private _manualHeight = false;
-        private _doNotTrackManualChanges = false;
-        private _tempMeasureStore = Measure.Empty();
-
-        /** Gets or sets a boolean indicating if the stack panel is vertical or horizontal*/
-        public get isVertical(): boolean {
-            return this._isVertical;
+        this._isVertical = value;
+        this._markAsDirty();
+    }
+
+    /** Gets or sets panel width */
+    public set width(value: string | number) {
+        if (!this._doNotTrackManualChanges) {
+            this._manualWidth = true;
         }
 
-        public set isVertical(value: boolean) {
-            if (this._isVertical === value) {
-                return;
-            }
+        if (this._width.toString(this._host) === value) {
+            return;
+        }
 
-            this._isVertical = value;
+        if (this._width.fromString(value)) {
             this._markAsDirty();
         }
-       
-        /** Gets or sets panel width */
-        public set width(value: string | number ) {
-            if (!this._doNotTrackManualChanges) {
-                this._manualWidth = true;
-            }
+    }
 
-            if (this._width.toString(this._host) === value) {
-                return;
-            }
+    public get width(): string | number {
+        return this._width.toString(this._host);
+    }
 
-            if (this._width.fromString(value)) {
-                this._markAsDirty();
-            }
+    /** Gets or sets panel height */
+    public set height(value: string | number) {
+        if (!this._doNotTrackManualChanges) {
+            this._manualHeight = true;
         }
 
-        public get width(): string | number {
-            return this._width.toString(this._host);
-        }        
+        if (this._height.toString(this._host) === value) {
+            return;
+        }
 
-        /** Gets or sets panel height */
-        public set height(value: string | number ) {
-            if (!this._doNotTrackManualChanges) {
-                this._manualHeight = true;
-            }
+        if (this._height.fromString(value)) {
+            this._markAsDirty();
+        }
+    }
 
-            if (this._height.toString(this._host) === value) {
-                return;
-            }
+    public get height(): string | number {
+        return this._height.toString(this._host);
+    }
 
-            if (this._height.fromString(value)) {
-                this._markAsDirty();
+    /**
+     * Creates a new StackPanel
+     * @param name defines control name
+     */
+    constructor(public name?: string) {
+        super(name);
+    }
+
+    protected _getTypeName(): string {
+        return "StackPanel";
+    }
+
+    protected _preMeasure(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        var stackWidth = 0;
+        var stackHeight = 0;
+        for (var child of this._children) {
+            this._tempMeasureStore.copyFrom(child._currentMeasure);
+            child._currentMeasure.copyFrom(parentMeasure);
+            child._measure();
+
+            if (this._isVertical) {
+                child.top = stackHeight + "px";
+                if (!child._top.ignoreAdaptiveScaling) {
+                    child._markAsDirty();
+                }
+                child._top.ignoreAdaptiveScaling = true;
+                stackHeight += child._currentMeasure.height;
+                if (child._currentMeasure.width > stackWidth) {
+                    stackWidth = child._currentMeasure.width;
+                }
+                child.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
+            } else {
+                child.left = stackWidth + "px";
+                if (!child._left.ignoreAdaptiveScaling) {
+                    child._markAsDirty();
+                }
+                child._left.ignoreAdaptiveScaling = true;
+                stackWidth += child._currentMeasure.width;
+                if (child._currentMeasure.height > stackHeight) {
+                    stackHeight = child._currentMeasure.height;
+                }
+                child.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
             }
-        }        
-                
-        public get height(): string | number  {
-            return this._height.toString(this._host);
-        }
-    
-        /**
-         * Creates a new StackPanel
-         * @param name defines control name
-         */
-        constructor(public name?: string) {
-            super(name);
+
+            child._currentMeasure.copyFrom(this._tempMeasureStore);
         }
 
-        protected _getTypeName(): string {
-            return "StackPanel";
-        }              
-
-        protected _preMeasure(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            var stackWidth = 0;
-            var stackHeight = 0;
-            for (var child of this._children) {
-                this._tempMeasureStore.copyFrom(child._currentMeasure);
-                child._currentMeasure.copyFrom(parentMeasure);
-                child._measure();
-                
-                if (this._isVertical) {
-                    child.top = stackHeight + "px";
-                    if (!child._top.ignoreAdaptiveScaling) {
-                        child._markAsDirty();
-                    }
-                    child._top.ignoreAdaptiveScaling = true;
-                    stackHeight += child._currentMeasure.height;
-                    if(child._currentMeasure.width > stackWidth) {
-                        stackWidth = child._currentMeasure.width;                        
-                    }
-                    child.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
-                } else {
-                    child.left = stackWidth + "px";
-                    if (!child._left.ignoreAdaptiveScaling) {
-                        child._markAsDirty();
-                    }                    
-                    child._left.ignoreAdaptiveScaling = true;
-                    stackWidth += child._currentMeasure.width;
-                    if(child._currentMeasure.height > stackHeight) {
-                        stackHeight = child._currentMeasure.height;                        
-                    }
-                    child.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
-                }
+        this._doNotTrackManualChanges = true;
 
-                child._currentMeasure.copyFrom(this._tempMeasureStore);
-            }
-            
-            this._doNotTrackManualChanges = true;
+        // Let stack panel width and height default to stackHeight and stackWidth if dimensions are not specified.
+        // User can now define their own height and width for stack panel.
 
-            // Let stack panel width and height default to stackHeight and stackWidth if dimensions are not specified.
-            // User can now define their own height and width for stack panel.
+        let panelWidthChanged = false;
+        let panelHeightChanged = false;
 
-            let panelWidthChanged = false;
-            let panelHeightChanged = false;
+        let previousHeight = this.height;
+        let previousWidth = this.width;
 
-            let previousHeight = this.height;
-            let previousWidth = this.width;
+        if (!this._manualHeight) {
+            // do not specify height if strictly defined by user
+            this.height = stackHeight + "px";
+        }
+        if (!this._manualWidth) {
+            // do not specify width if strictly defined by user
+            this.width = stackWidth + "px";
+        }
 
-            if (!this._manualHeight) {
-                // do not specify height if strictly defined by user
-                this.height = stackHeight + "px";
-            }
-            if (!this._manualWidth) {
-                // do not specify width if strictly defined by user
-                this.width = stackWidth + "px";
-            }
+        panelWidthChanged = previousWidth !== this.width || !this._width.ignoreAdaptiveScaling;
+        panelHeightChanged = previousHeight !== this.height || !this._height.ignoreAdaptiveScaling;
 
-            panelWidthChanged = previousWidth !== this.width || !this._width.ignoreAdaptiveScaling;
-            panelHeightChanged = previousHeight !== this.height || !this._height.ignoreAdaptiveScaling;
+        if (panelHeightChanged) {
+            this._height.ignoreAdaptiveScaling = true;
+        }
 
-            if (panelHeightChanged) {
-                this._height.ignoreAdaptiveScaling = true;
-            }
+        if (panelWidthChanged) {
+            this._width.ignoreAdaptiveScaling = true;
+        }
 
-            if (panelWidthChanged) {
-                this._width.ignoreAdaptiveScaling = true;
-            }
+        this._doNotTrackManualChanges = false;
 
-            this._doNotTrackManualChanges = false;
+        if (panelWidthChanged || panelHeightChanged) {
+            this._markAllAsDirty();
+        }
 
-            if (panelWidthChanged || panelHeightChanged) {
-                this._markAllAsDirty();
-            }
-            
-            super._preMeasure(parentMeasure, context);
-        }    
-    }    
-}
+        super._preMeasure(parentMeasure, context);
+    }
+}  

+ 53 - 0
gui/src/2D/controls/statics.ts

@@ -0,0 +1,53 @@
+import { Control } from "./control";
+import { StackPanel } from "./stackPanel";
+import { TextBlock } from "./textBlock";
+
+/**
+ * Forcing an export so that this code will execute
+ * @hidden
+ */
+const name = "Statics";
+
+export { name };
+
+/**
+ * Creates a stack panel that can be used to render headers
+ * @param control defines the control to associate with the header
+ * @param text defines the text of the header
+ * @param size defines the size of the header
+ * @param options defines options used to configure the header
+ * @returns a new StackPanel
+ */
+Control.AddHeader = function (control: Control, text: string, size: string | number, options: { isHorizontal: boolean, controlFirst: boolean }): StackPanel {
+    let panel = new StackPanel("panel");
+    let isHorizontal = options ? options.isHorizontal : true;
+    let controlFirst = options ? options.controlFirst : true;
+
+    panel.isVertical = !isHorizontal;
+
+    let header = new TextBlock("header");
+    header.text = text;
+    header.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+    if (isHorizontal) {
+        header.width = size;
+    } else {
+        header.height = size;
+    }
+
+    if (controlFirst) {
+        panel.addControl(control);
+        panel.addControl(header);
+        header.paddingLeft = "5px";
+    } else {
+        panel.addControl(header);
+        panel.addControl(control);
+        header.paddingRight = "5px";
+    }
+
+    header.shadowBlur = control.shadowBlur;
+    header.shadowColor = control.shadowColor;
+    header.shadowOffsetX = control.shadowOffsetX;
+    header.shadowOffsetY = control.shadowOffsetY;
+
+    return panel;
+}

+ 329 - 328
gui/src/2D/controls/textBlock.ts

@@ -1,414 +1,415 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Observable } from "babylonjs";
+import { Measure } from "../measure";
+import { ValueAndUnit } from "../valueAndUnit";
+import { Control } from "./control";
+
+/**
+ * Enum that determines the text-wrapping mode to use.
+ */
+export enum TextWrapping {
+    /**
+     * Clip the text when it's larger than Control.width; this is the default mode.
+     */
+    Clip = 0,
 
-module BABYLON.GUI {
     /**
-     * Enum that determines the text-wrapping mode to use.
+     * Wrap the text word-wise, i.e. try to add line-breaks at word boundary to fit within Control.width.
      */
-    export enum TextWrapping {
-        /**
-         * Clip the text when it's larger than Control.width; this is the default mode.
-         */
-        Clip = 0,
+    WordWrap = 1,
 
-        /**
-         * Wrap the text word-wise, i.e. try to add line-breaks at word boundary to fit within Control.width.
-         */
-        WordWrap = 1,
+    /**
+     * Ellipsize the text, i.e. shrink with trailing … when text is larger than Control.width.
+     */
+    Ellipsis,
+}
+
+/**
+ * Class used to create text block control
+ */
+export class TextBlock extends Control {
+    private _text = "";
+    private _textWrapping = TextWrapping.Clip;
+    private _textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
+    private _textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
+
+    private _lines: any[];
+    private _resizeToFit: boolean = false;
+    private _lineSpacing: ValueAndUnit = new ValueAndUnit(0);
+    private _outlineWidth: number = 0;
+    private _outlineColor: string = "white";
+    /**
+    * An event triggered after the text is changed
+    */
+    public onTextChangedObservable = new Observable<TextBlock>();
 
-        /**
-         * Ellipsize the text, i.e. shrink with trailing … when text is larger than Control.width.
-         */
-        Ellipsis,
+    /**
+    * An event triggered after the text was broken up into lines
+    */
+    public onLinesReadyObservable = new Observable<TextBlock>();
+
+    /**
+     * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
+     */
+    public get lines(): any[] {
+        return this._lines;
     }
 
     /**
-     * Class used to create text block control
+     * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
      */
-    export class TextBlock extends Control {
-        private _text = "";
-        private _textWrapping = TextWrapping.Clip;
-        private _textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
-        private _textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
-
-        private _lines: any[];
-        private _resizeToFit: boolean = false;
-        private _lineSpacing: ValueAndUnit = new ValueAndUnit(0);
-        private _outlineWidth: number = 0;
-        private _outlineColor: string = "white";
-        /**
-        * An event triggered after the text is changed
-        */
-        public onTextChangedObservable = new Observable<TextBlock>();
+    public get resizeToFit(): boolean {
+        return this._resizeToFit;
+    }
 
-        /**
-        * An event triggered after the text was broken up into lines
-        */
-        public onLinesReadyObservable = new Observable<TextBlock>();
+    /**
+     * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+     */
+    public set resizeToFit(value: boolean) {
+        this._resizeToFit = value;
 
-        /**
-         * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
-         */
-        public get lines(): any[] {
-            return this._lines;
-        }
-        
-        /**
-         * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
-         */
-        public get resizeToFit(): boolean {
-            return this._resizeToFit;
+        if (this._resizeToFit) {
+            this._width.ignoreAdaptiveScaling = true;
+            this._height.ignoreAdaptiveScaling = true;
         }
+    }
 
-        /**
-         * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
-         */        
-        public set resizeToFit(value: boolean) {
-            this._resizeToFit = value;
-
-            if (this._resizeToFit) {
-                this._width.ignoreAdaptiveScaling = true;
-                this._height.ignoreAdaptiveScaling = true;
-            }
-        }
+    /**
+     * Gets or sets a boolean indicating if text must be wrapped
+     */
+    public get textWrapping(): TextWrapping | boolean {
+        return this._textWrapping;
+    }
 
-        /**
-         * Gets or sets a boolean indicating if text must be wrapped
-         */
-        public get textWrapping(): TextWrapping | boolean {
-            return this._textWrapping;
+    /**
+     * Gets or sets a boolean indicating if text must be wrapped
+     */
+    public set textWrapping(value: TextWrapping | boolean) {
+        if (this._textWrapping === value) {
+            return;
         }
+        this._textWrapping = +value;
+        this._markAsDirty();
+    }
 
-        /**
-         * Gets or sets a boolean indicating if text must be wrapped
-         */        
-        public set textWrapping(value: TextWrapping | boolean) {
-            if (this._textWrapping === value) {
-                return;
-            }
-            this._textWrapping = +value;
-            this._markAsDirty();
-        }
+    /**
+     * Gets or sets text to display
+     */
+    public get text(): string {
+        return this._text;
+    }
 
-        /**
-         * Gets or sets text to display
-         */
-        public get text(): string {
-            return this._text;
+    /**
+     * Gets or sets text to display
+     */
+    public set text(value: string) {
+        if (this._text === value) {
+            return;
         }
+        this._text = value;
+        this._markAsDirty();
 
-        /**
-         * Gets or sets text to display
-         */
-        public set text(value: string) {
-            if (this._text === value) {
-                return;
-            }
-            this._text = value;
-            this._markAsDirty();
+        this.onTextChangedObservable.notifyObservers(this);
+    }
 
-            this.onTextChangedObservable.notifyObservers(this);
-        }
+    /**
+     * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+     */
+    public get textHorizontalAlignment(): number {
+        return this._textHorizontalAlignment;
+    }
 
-        /**
-         * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
-         */
-        public get textHorizontalAlignment(): number {
-            return this._textHorizontalAlignment;
+    /**
+     * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+     */
+    public set textHorizontalAlignment(value: number) {
+        if (this._textHorizontalAlignment === value) {
+            return;
         }
 
-        /**
-         * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
-         */        
-        public set textHorizontalAlignment(value: number) {
-            if (this._textHorizontalAlignment === value) {
-                return;
-            }
+        this._textHorizontalAlignment = value;
+        this._markAsDirty();
+    }
 
-            this._textHorizontalAlignment = value;
-            this._markAsDirty();
-        }
+    /**
+     * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+     */
+    public get textVerticalAlignment(): number {
+        return this._textVerticalAlignment;
+    }
 
-        /**
-         * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
-         */        
-        public get textVerticalAlignment(): number {
-            return this._textVerticalAlignment;
+    /**
+     * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+     */
+    public set textVerticalAlignment(value: number) {
+        if (this._textVerticalAlignment === value) {
+            return;
         }
 
-        /**
-         * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
-         */           
-        public set textVerticalAlignment(value: number) {
-            if (this._textVerticalAlignment === value) {
-                return;
-            }
+        this._textVerticalAlignment = value;
+        this._markAsDirty();
+    }
 
-            this._textVerticalAlignment = value;
+    /**
+     * Gets or sets line spacing value
+     */
+    public set lineSpacing(value: string | number) {
+        if (this._lineSpacing.fromString(value)) {
             this._markAsDirty();
         }
+    }
 
-        /**
-         * Gets or sets line spacing value
-         */
-        public set lineSpacing(value: string | number) {
-            if (this._lineSpacing.fromString(value)) {
-                this._markAsDirty();
-            }
-        }
+    /**
+     * Gets or sets line spacing value
+     */
+    public get lineSpacing(): string | number {
+        return this._lineSpacing.toString(this._host);
+    }
 
-        /**
-         * Gets or sets line spacing value
-         */        
-        public get lineSpacing(): string | number {
-            return this._lineSpacing.toString(this._host);
-        }
+    /**
+     * Gets or sets outlineWidth of the text to display
+     */
+    public get outlineWidth(): number {
+        return this._outlineWidth;
+    }
 
-        /**
-         * Gets or sets outlineWidth of the text to display
-         */
-        public get outlineWidth(): number {
-            return this._outlineWidth;
+    /**
+     * Gets or sets outlineWidth of the text to display
+     */
+    public set outlineWidth(value: number) {
+        if (this._outlineWidth === value) {
+            return;
         }
+        this._outlineWidth = value;
+        this._markAsDirty();
+    }
 
-        /**
-         * Gets or sets outlineWidth of the text to display
-         */
-        public set outlineWidth(value: number) {
-            if (this._outlineWidth === value) {
-                return;
-            }
-            this._outlineWidth = value;
-            this._markAsDirty();
-        }
+    /**
+     * Gets or sets outlineColor of the text to display
+     */
+    public get outlineColor(): string {
+        return this._outlineColor;
+    }
 
-        /**
-         * Gets or sets outlineColor of the text to display
-         */
-        public get outlineColor(): string {
-            return this._outlineColor;
+    /**
+     * Gets or sets outlineColor of the text to display
+     */
+    public set outlineColor(value: string) {
+        if (this._outlineColor === value) {
+            return;
         }
+        this._outlineColor = value;
+        this._markAsDirty();
+    }
 
+    /**
+     * Creates a new TextBlock object
+     * @param name defines the name of the control
+     * @param text defines the text to display (emptry string by default)
+     */
+    constructor(
         /**
-         * Gets or sets outlineColor of the text to display
+         * Defines the name of the control
          */
-        public set outlineColor(value: string) {
-            if (this._outlineColor === value) {
-                return;
-            }
-            this._outlineColor = value;
-            this._markAsDirty();
+        public name?: string,
+        text: string = "") {
+        super(name);
+
+        this.text = text;
+    }
+
+    protected _getTypeName(): string {
+        return "TextBlock";
+    }
+
+    private _drawText(text: string, textWidth: number, y: number, context: CanvasRenderingContext2D): void {
+        var width = this._currentMeasure.width;
+        var x = 0;
+        switch (this._textHorizontalAlignment) {
+            case Control.HORIZONTAL_ALIGNMENT_LEFT:
+                x = 0
+                break;
+            case Control.HORIZONTAL_ALIGNMENT_RIGHT:
+                x = width - textWidth;
+                break;
+            case Control.HORIZONTAL_ALIGNMENT_CENTER:
+                x = (width - textWidth) / 2;
+                break;
         }
 
-        /**
-         * Creates a new TextBlock object
-         * @param name defines the name of the control
-         * @param text defines the text to display (emptry string by default)
-         */
-        constructor(
-            /**
-             * Defines the name of the control
-             */
-            public name?: string, 
-            text: string = "") {
-            super(name);
-
-            this.text = text;
+        if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+            context.shadowColor = this.shadowColor;
+            context.shadowBlur = this.shadowBlur;
+            context.shadowOffsetX = this.shadowOffsetX;
+            context.shadowOffsetY = this.shadowOffsetY;
         }
 
-        protected _getTypeName(): string {
-            return "TextBlock";
+        if (this.outlineWidth) {
+            context.strokeText(text, this._currentMeasure.left + x, y);
         }
+        context.fillText(text, this._currentMeasure.left + x, y);
+    }
 
-        private _drawText(text: string, textWidth: number, y: number, context: CanvasRenderingContext2D): void {
-            var width = this._currentMeasure.width;
-            var x = 0;
-            switch (this._textHorizontalAlignment) {
-                case Control.HORIZONTAL_ALIGNMENT_LEFT:
-                    x = 0
-                    break;
-                case Control.HORIZONTAL_ALIGNMENT_RIGHT:
-                    x = width - textWidth;
-                    break;
-                case Control.HORIZONTAL_ALIGNMENT_CENTER:
-                    x = (width - textWidth) / 2;
-                    break;
-            }
+    /** @hidden */
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
 
-            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
-                context.shadowColor = this.shadowColor;
-                context.shadowBlur = this.shadowBlur;
-                context.shadowOffsetX = this.shadowOffsetX;
-                context.shadowOffsetY = this.shadowOffsetY;
-            }
+        this._applyStates(context);
 
-            if (this.outlineWidth) {
-                context.strokeText(text, this._currentMeasure.left + x, y);
-            }
-            context.fillText(text, this._currentMeasure.left + x, y);
+        if (this._processMeasures(parentMeasure, context)) {
+            // Render lines
+            this._renderLines(context);
         }
+        context.restore();
+    }
 
-        /** @hidden */
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            context.save();
+    protected _applyStates(context: CanvasRenderingContext2D): void {
+        super._applyStates(context);
+        if (this.outlineWidth) {
+            context.lineWidth = this.outlineWidth;
+            context.strokeStyle = this.outlineColor;
+        }
+    }
 
-            this._applyStates(context);
+    protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        this._lines = this._breakLines(this._currentMeasure.width, context);
+        this.onLinesReadyObservable.notifyObservers(this);
+    }
 
-            if (this._processMeasures(parentMeasure, context)) {
-                // Render lines
-                this._renderLines(context);
-            }
-            context.restore();
-        }
+    protected _breakLines(refWidth: number, context: CanvasRenderingContext2D): object[] {
+        var lines = [];
+        var _lines = this.text.split("\n");
 
-        protected _applyStates(context: CanvasRenderingContext2D): void {
-            super._applyStates(context);
-            if (this.outlineWidth) {
-                context.lineWidth = this.outlineWidth;
-                context.strokeStyle = this.outlineColor;
+        if (this._textWrapping === TextWrapping.Ellipsis && !this._resizeToFit) {
+            for (var _line of _lines) {
+                lines.push(this._parseLineEllipsis(_line, refWidth, context));
+            }
+        } else if (this._textWrapping === TextWrapping.WordWrap && !this._resizeToFit) {
+            for (var _line of _lines) {
+                lines.push(...this._parseLineWordWrap(_line, refWidth, context));
+            }
+        } else {
+            for (var _line of _lines) {
+                lines.push(this._parseLine(_line, context));
             }
         }
 
-        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            this._lines = this._breakLines(this._currentMeasure.width, context);
-            this.onLinesReadyObservable.notifyObservers(this);
-        }
+        return lines;
+    }
 
-        protected _breakLines(refWidth: number, context: CanvasRenderingContext2D): object[] {
-            var lines = [];
-            var _lines = this.text.split("\n");
+    protected _parseLine(line: string = '', context: CanvasRenderingContext2D): object {
+        return { text: line, width: context.measureText(line).width };
+    }
 
-            if (this._textWrapping === TextWrapping.Ellipsis && !this._resizeToFit) {
-                for (var _line of _lines) {
-                    lines.push(this._parseLineEllipsis(_line, refWidth, context));
-                }
-            } else if (this._textWrapping === TextWrapping.WordWrap && !this._resizeToFit) {
-                for (var _line of _lines) {
-                    lines.push(...this._parseLineWordWrap(_line, refWidth, context));
-                }
-            } else {
-                for (var _line of _lines) {
-                    lines.push(this._parseLine(_line, context));
-                }
-            }
+    protected _parseLineEllipsis(line: string = '', width: number,
+        context: CanvasRenderingContext2D): object {
+        var lineWidth = context.measureText(line).width;
 
-            return lines;
+        if (lineWidth > width) {
+            line += '…';
         }
-
-        protected _parseLine(line: string = '', context: CanvasRenderingContext2D): object {
-            return { text: line, width: context.measureText(line).width };
+        while (line.length > 2 && lineWidth > width) {
+            line = line.slice(0, -2) + '…';
+            lineWidth = context.measureText(line).width;
         }
 
-        protected _parseLineEllipsis(line: string = '', width: number,
-                                     context: CanvasRenderingContext2D): object {
-            var lineWidth = context.measureText(line).width;
+        return { text: line, width: lineWidth };
+    }
 
-            if (lineWidth > width) {
-                line += '…';
-            }
-            while (line.length > 2 && lineWidth > width) {
-                line = line.slice(0, -2) + '…';
+    protected _parseLineWordWrap(line: string = '', width: number,
+        context: CanvasRenderingContext2D): object[] {
+        var lines = [];
+        var words = line.split(' ');
+        var lineWidth = 0;
+
+        for (var n = 0; n < words.length; n++) {
+            var testLine = n > 0 ? line + " " + words[n] : words[0];
+            var metrics = context.measureText(testLine);
+            var testWidth = metrics.width;
+            if (testWidth > width && n > 0) {
+                lines.push({ text: line, width: lineWidth });
+                line = words[n];
                 lineWidth = context.measureText(line).width;
             }
-
-            return { text: line, width: lineWidth };
-        }
-
-        protected _parseLineWordWrap(line: string = '', width: number,
-                                     context: CanvasRenderingContext2D): object[] {
-            var lines = [];
-            var words = line.split(' ');
-            var lineWidth = 0;
-
-            for (var n = 0; n < words.length; n++) {
-                var testLine = n > 0 ? line + " " + words[n] : words[0];
-                var metrics = context.measureText(testLine);
-                var testWidth = metrics.width;
-                if (testWidth > width && n > 0) {
-                    lines.push({ text: line, width: lineWidth });
-                    line = words[n];
-                    lineWidth = context.measureText(line).width;
-                }
-                else {
-                    lineWidth = testWidth;
-                    line = testLine;
-                }
+            else {
+                lineWidth = testWidth;
+                line = testLine;
             }
-            lines.push({ text: line, width: lineWidth });
-
-            return lines;
         }
+        lines.push({ text: line, width: lineWidth });
 
-        protected _renderLines(context: CanvasRenderingContext2D): void {
-            var height = this._currentMeasure.height;
+        return lines;
+    }
 
-            if (!this._fontOffset) {
-                this._fontOffset = Control._GetFontOffset(context.font);
-            }
-            var rootY = 0;
-            switch (this._textVerticalAlignment) {
-                case Control.VERTICAL_ALIGNMENT_TOP:
-                    rootY = this._fontOffset.ascent;
-                    break;
-                case Control.VERTICAL_ALIGNMENT_BOTTOM:
-                    rootY = height - this._fontOffset.height * (this._lines.length - 1) - this._fontOffset.descent;
-                    break;
-                case Control.VERTICAL_ALIGNMENT_CENTER:
-                    rootY = this._fontOffset.ascent + (height - this._fontOffset.height * this._lines.length) / 2;
-                    break;
-            }
+    protected _renderLines(context: CanvasRenderingContext2D): void {
+        var height = this._currentMeasure.height;
 
-            rootY += this._currentMeasure.top;
+        if (!this._fontOffset) {
+            this._fontOffset = Control._GetFontOffset(context.font);
+        }
+        var rootY = 0;
+        switch (this._textVerticalAlignment) {
+            case Control.VERTICAL_ALIGNMENT_TOP:
+                rootY = this._fontOffset.ascent;
+                break;
+            case Control.VERTICAL_ALIGNMENT_BOTTOM:
+                rootY = height - this._fontOffset.height * (this._lines.length - 1) - this._fontOffset.descent;
+                break;
+            case Control.VERTICAL_ALIGNMENT_CENTER:
+                rootY = this._fontOffset.ascent + (height - this._fontOffset.height * this._lines.length) / 2;
+                break;
+        }
 
-            var maxLineWidth: number = 0;
+        rootY += this._currentMeasure.top;
 
-            for (let i = 0; i < this._lines.length; i++) {
-                const line = this._lines[i];
+        var maxLineWidth: number = 0;
 
-                if (i !== 0 && this._lineSpacing.internalValue !== 0) {
+        for (let i = 0; i < this._lines.length; i++) {
+            const line = this._lines[i];
 
-                    if (this._lineSpacing.isPixel) {
-                        rootY += this._lineSpacing.getValue(this._host);
-                    } else {                        
-                        rootY = rootY + (this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host,  this._cachedParentMeasure.height));
-                    }
+            if (i !== 0 && this._lineSpacing.internalValue !== 0) {
+
+                if (this._lineSpacing.isPixel) {
+                    rootY += this._lineSpacing.getValue(this._host);
+                } else {
+                    rootY = rootY + (this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host, this._cachedParentMeasure.height));
                 }
+            }
 
-                this._drawText(line.text, line.width, rootY, context);
-                rootY += this._fontOffset.height;
+            this._drawText(line.text, line.width, rootY, context);
+            rootY += this._fontOffset.height;
 
-                if (line.width > maxLineWidth) maxLineWidth = line.width;
-            }
+            if (line.width > maxLineWidth) maxLineWidth = line.width;
+        }
 
-            if (this._resizeToFit) {
-                this.width = this.paddingLeftInPixels + this.paddingRightInPixels + maxLineWidth + 'px';
-                this.height = this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * this._lines.length + 'px';
-            }
+        if (this._resizeToFit) {
+            this.width = this.paddingLeftInPixels + this.paddingRightInPixels + maxLineWidth + 'px';
+            this.height = this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * this._lines.length + 'px';
         }
+    }
 
-        /**
-         * Given a width constraint applied on the text block, find the expected height
-         * @returns expected height
-         */
-        public computeExpectedHeight(): number {
-            if (this.text && this.widthInPixels) {
-                const context = document.createElement('canvas').getContext('2d');
-                if (context) {
-                    this._applyStates(context);
-                    if (!this._fontOffset) {
-                        this._fontOffset = Control._GetFontOffset(context.font);
-                    }
-                    const lines = this._lines ? this._lines : this._breakLines(
-                        this.widthInPixels - this.paddingLeftInPixels - this.paddingRightInPixels, context);
-                    return this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * lines.length;
+    /**
+     * Given a width constraint applied on the text block, find the expected height
+     * @returns expected height
+     */
+    public computeExpectedHeight(): number {
+        if (this.text && this.widthInPixels) {
+            const context = document.createElement('canvas').getContext('2d');
+            if (context) {
+                this._applyStates(context);
+                if (!this._fontOffset) {
+                    this._fontOffset = Control._GetFontOffset(context.font);
                 }
+                const lines = this._lines ? this._lines : this._breakLines(
+                    this.widthInPixels - this.paddingLeftInPixels - this.paddingRightInPixels, context);
+                return this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * lines.length;
             }
-            return 0;
         }
+        return 0;
+    }
 
-        dispose(): void {
-            super.dispose();
+    dispose(): void {
+        super.dispose();
 
-            this.onTextChangedObservable.clear();
-        }
+        this.onTextChangedObservable.clear();
     }
-}
+}

+ 199 - 196
gui/src/2D/controls/virtualKeyboard.ts

@@ -1,238 +1,241 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
+import { StackPanel } from "./stackPanel";
+import { Observable, Nullable, Observer } from "babylonjs";
+import { Button } from "./button";
+import { Container } from "./container";
+import { TextBlock } from "./textBlock";
+import { InputText } from "./inputText";
+
+
+/**
+ * Class used to store key control properties
+ */
+export class KeyPropertySet {
+    /** Width */
+    width?: string;
+    /** Height */
+    height?: string;
+    /** Left padding */
+    paddingLeft?: string;
+    /** Right padding */
+    paddingRight?: string;
+    /** Top padding */
+    paddingTop?: string;
+    /** Bottom padding */
+    paddingBottom?: string;
+    /** Foreground color */
+    color?: string;
+    /** Background color */
+    background?: string;
+}
 
-    /**
-     * Class used to store key control properties
-     */
-    export class KeyPropertySet {
-        /** Width */
-        width?: string;
-        /** Height */
-        height?: string;
-        /** Left padding */
-        paddingLeft?: string;
-        /** Right padding */
-        paddingRight?: string;
-        /** Top padding */
-        paddingTop?: string;
-        /** Bottom padding */
-        paddingBottom?: string;
-        /** Foreground color */
-        color?: string;
-        /** Background color */
-        background?: string;
+/**
+ * Class used to create virtual keyboard
+ */
+export class VirtualKeyboard extends StackPanel {
+    /** Observable raised when a key is pressed */
+    public onKeyPressObservable = new Observable<string>();
+
+    /** Gets or sets default key button width */
+    public defaultButtonWidth = "40px";
+    /** Gets or sets default key button height */
+    public defaultButtonHeight = "40px";
+
+    /** Gets or sets default key button left padding */
+    public defaultButtonPaddingLeft = "2px";
+    /** Gets or sets default key button right padding */
+    public defaultButtonPaddingRight = "2px";
+    /** Gets or sets default key button top padding */
+    public defaultButtonPaddingTop = "2px";
+    /** Gets or sets default key button bottom padding */
+    public defaultButtonPaddingBottom = "2px";
+
+    /** Gets or sets default key button foreground color */
+    public defaultButtonColor = "#DDD";
+    /** Gets or sets default key button background color */
+    public defaultButtonBackground = "#070707";
+
+    /** Gets or sets shift button foreground color */
+    public shiftButtonColor = "#7799FF";
+    /** Gets or sets shift button thickness*/
+    public selectedShiftThickness = 1;
+
+    /** Gets shift key state */
+    public shiftState = 0;
+
+    protected _getTypeName(): string {
+        return "VirtualKeyboard";
     }
 
-    /**
-     * Class used to create virtual keyboard
-     */
-    export class VirtualKeyboard extends StackPanel {
-        /** Observable raised when a key is pressed */
-        public onKeyPressObservable = new Observable<string>();
-
-        /** Gets or sets default key button width */
-        public defaultButtonWidth = "40px";
-        /** Gets or sets default key button height */
-        public defaultButtonHeight = "40px";
-
-        /** Gets or sets default key button left padding */
-        public defaultButtonPaddingLeft = "2px";
-        /** Gets or sets default key button right padding */
-        public defaultButtonPaddingRight = "2px";
-        /** Gets or sets default key button top padding */
-        public defaultButtonPaddingTop = "2px";
-        /** Gets or sets default key button bottom padding */
-        public defaultButtonPaddingBottom = "2px";
-
-        /** Gets or sets default key button foreground color */
-        public defaultButtonColor = "#DDD";
-        /** Gets or sets default key button background color */
-        public defaultButtonBackground = "#070707";
-
-        /** Gets or sets shift button foreground color */
-        public shiftButtonColor = "#7799FF";
-        /** Gets or sets shift button thickness*/
-        public selectedShiftThickness = 1;
-
-        /** Gets shift key state */
-        public shiftState = 0;
-
-        protected _getTypeName(): string {
-            return "VirtualKeyboard";
-        }
+    private _createKey(key: string, propertySet: Nullable<KeyPropertySet>) {
+        var button = Button.CreateSimpleButton(key, key);
 
-        private _createKey(key: string, propertySet: Nullable<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.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.thickness = 0;
-            button.isFocusInvisible = true;
+        button.shadowColor = this.shadowColor;
+        button.shadowBlur = this.shadowBlur;
+        button.shadowOffsetX = this.shadowOffsetX;
+        button.shadowOffsetY = this.shadowOffsetY;
 
-            button.shadowColor = this.shadowColor;
-            button.shadowBlur = this.shadowBlur;
-            button.shadowOffsetX = this.shadowOffsetX;
-            button.shadowOffsetY = this.shadowOffsetY;
+        button.onPointerUpObservable.add(() => {
+            this.onKeyPressObservable.notifyObservers(key);
+        });
 
-            button.onPointerUpObservable.add(() => {
-                this.onKeyPressObservable.notifyObservers(key);
-            });
+        return button;
+    }
 
-            return button;
-        }
+    /**
+     * Adds a new row of keys
+     * @param keys defines the list of keys to add
+     * @param propertySets defines the associated property sets
+     */
+    public addKeysRow(keys: Array<string>, propertySets?: Array<KeyPropertySet>): void {
+        let panel = new StackPanel();
+        panel.isVertical = false;
+        panel.isFocusInvisible = true;
 
-        /**
-         * Adds a new row of keys
-         * @param keys defines the list of keys to add
-         * @param propertySets defines the associated property sets
-         */
-        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];
-                }
+        for (var i = 0; i < keys.length; i++) {
+            let properties = null;
 
-                panel.addControl(this._createKey(keys[i], properties));
+            if (propertySets && propertySets.length === keys.length) {
+                properties = propertySets[i];
             }
 
-            this.addControl(panel);
+            panel.addControl(this._createKey(keys[i], properties));
         }
 
-        /**
-         * Set the shift key to a specific state
-         * @param shiftState defines the new shift state
-         */
-        public applyShiftState(shiftState: number): void {
-            if (!this.children) {
-                return;
-            }
+        this.addControl(panel);
+    }
 
-            for (var i = 0; i < this.children.length; i++) {
-                let row = this.children[i];
-                if (!row || !(<Container>row).children) {
-                    continue;
-                }
+    /**
+     * Set the shift key to a specific state
+     * @param shiftState defines the new shift state
+     */
+    public applyShiftState(shiftState: number): void {
+        if (!this.children) {
+            return;
+        }
 
-                let rowContainer = <Container>row;
-                for (var j = 0; j < rowContainer.children.length; j++) {
-                    let button = rowContainer.children[j] as Button;
+        for (var i = 0; i < this.children.length; i++) {
+            let row = this.children[i];
+            if (!row || !(<Container>row).children) {
+                continue;
+            }
 
-                    if (!button || !button.children[0]) {
-                        continue;
-                    }
+            let rowContainer = <Container>row;
+            for (var j = 0; j < rowContainer.children.length; j++) {
+                let button = rowContainer.children[j] as Button;
 
-                    let button_tblock = button.children[0] as TextBlock;
+                if (!button || !button.children[0]) {
+                    continue;
+                }
 
-                    if (button_tblock.text === "\u21E7") {
-                        button.color = (shiftState ? this.shiftButtonColor : this.defaultButtonColor);
-                        button.thickness = (shiftState > 1 ? this.selectedShiftThickness : 0);
-                    }
+                let button_tblock = button.children[0] as TextBlock;
 
-                    button_tblock.text = (shiftState > 0 ? button_tblock.text.toUpperCase() : button_tblock.text.toLowerCase());
+                if (button_tblock.text === "\u21E7") {
+                    button.color = (shiftState ? this.shiftButtonColor : this.defaultButtonColor);
+                    button.thickness = (shiftState > 1 ? this.selectedShiftThickness : 0);
                 }
-            }
-        }
-
-        private _connectedInputText: Nullable<InputText>;
-        private _onFocusObserver: Nullable<Observer<InputText>>;
-        private _onBlurObserver: Nullable<Observer<InputText>>;
-        private _onKeyPressObserver: Nullable<Observer<string>>;
 
-        /** Gets the input text control attached with the keyboard */
-        public get connectedInputText(): Nullable<InputText> {
-            return this._connectedInputText;
+                button_tblock.text = (shiftState > 0 ? button_tblock.text.toUpperCase() : button_tblock.text.toLowerCase());
+            }
         }
+    }
 
-        /**
-         * Connects the keyboard with an input text control
-         * @param input defines the target control
-         */
-        public connect(input: InputText): void {
-            this.isVisible = false;
-            this._connectedInputText = input;
+    private _connectedInputText: Nullable<InputText>;
+    private _onFocusObserver: Nullable<Observer<InputText>>;
+    private _onBlurObserver: Nullable<Observer<InputText>>;
+    private _onKeyPressObserver: Nullable<Observer<string>>;
 
-            // Events hooking
-            this._onFocusObserver = input.onFocusObservable.add(() => {
-                this.isVisible = true;
-            });
+    /** Gets the input text control attached with the keyboard */
+    public get connectedInputText(): Nullable<InputText> {
+        return this._connectedInputText;
+    }
 
-            this._onBlurObserver = input.onBlurObservable.add(() => {
-                this.isVisible = false;
-            });
+    /**
+     * Connects the keyboard with an input text control
+     * @param input defines the target control
+     */
+    public connect(input: InputText): void {
+        this.isVisible = false;
+        this._connectedInputText = input;
 
-            this._onKeyPressObserver = this.onKeyPressObservable.add((key) => {
-                if (!this._connectedInputText) {
-                    return;
-                }
-                switch (key) {
-                    case "\u21E7":
-                        this.shiftState++;
-                        if (this.shiftState > 2) {
-                            this.shiftState = 0;
-                        }
-                        this.applyShiftState(this.shiftState);
-                        return;
-                    case "\u2190":
-                        this._connectedInputText.processKey(8);
-                        return;
-                    case "\u21B5":
-                        this._connectedInputText.processKey(13);
-                        return;
-                }
-                this._connectedInputText.processKey(-1, (this.shiftState ? key.toUpperCase() : key));
+        // Events hooking
+        this._onFocusObserver = input.onFocusObservable.add(() => {
+            this.isVisible = true;
+        });
 
-                if (this.shiftState === 1) {
-                    this.shiftState = 0;
-                    this.applyShiftState(this.shiftState);
-                }
-            });
-        }
+        this._onBlurObserver = input.onBlurObservable.add(() => {
+            this.isVisible = false;
+        });
 
-        /**
-         * Disconnects the keyboard from an input text control
-         */
-        public disconnect(): void {
+        this._onKeyPressObserver = this.onKeyPressObservable.add((key) => {
             if (!this._connectedInputText) {
                 return;
             }
+            switch (key) {
+                case "\u21E7":
+                    this.shiftState++;
+                    if (this.shiftState > 2) {
+                        this.shiftState = 0;
+                    }
+                    this.applyShiftState(this.shiftState);
+                    return;
+                case "\u2190":
+                    this._connectedInputText.processKey(8);
+                    return;
+                case "\u21B5":
+                    this._connectedInputText.processKey(13);
+                    return;
+            }
+            this._connectedInputText.processKey(-1, (this.shiftState ? key.toUpperCase() : key));
 
-            this._connectedInputText.onFocusObservable.remove(this._onFocusObserver);
-            this._connectedInputText.onBlurObservable.remove(this._onBlurObserver);
-            this.onKeyPressObservable.remove(this._onKeyPressObserver);
+            if (this.shiftState === 1) {
+                this.shiftState = 0;
+                this.applyShiftState(this.shiftState);
+            }
+        });
+    }
 
-            this._connectedInputText = null;
+    /**
+     * Disconnects the keyboard from an input text control
+     */
+    public disconnect(): void {
+        if (!this._connectedInputText) {
+            return;
         }
 
-        // Statics
+        this._connectedInputText.onFocusObservable.remove(this._onFocusObserver);
+        this._connectedInputText.onBlurObservable.remove(this._onBlurObserver);
+        this.onKeyPressObservable.remove(this._onKeyPressObserver);
 
-        /**
-         * Creates a new keyboard using a default layout
-         * @returns a new VirtualKeyboard
-         */
-        public static CreateDefaultLayout(): VirtualKeyboard {
-            let returnValue = new VirtualKeyboard();
+        this._connectedInputText = null;
+    }
 
-            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(["\u21E7", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/"]);
-            returnValue.addKeysRow([" "], [{ width: "200px" }]);
+    // Statics
 
-            return returnValue;
-        }
+    /**
+     * Creates a new keyboard using a default layout
+     * @returns a new VirtualKeyboard
+     */
+    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(["\u21E7", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/"]);
+        returnValue.addKeysRow([" "], [{ width: "200px" }]);
+
+        return returnValue;
     }
 }

+ 8 - 0
gui/src/2D/index.ts

@@ -0,0 +1,8 @@
+export * from "./controls";
+
+export * from "./advancedDynamicTexture";
+export * from "./math2D";
+export * from "./measure";
+export * from "./multiLinePoint";
+export * from "./style";
+export * from "./valueAndUnit";

+ 184 - 186
gui/src/2D/math2D.ts

@@ -1,207 +1,205 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+import { Vector2, Epsilon, Nullable } from "babylonjs";
 
-module BABYLON.GUI {
+/**
+ * Class used to transport Vector2 information for pointer events
+ */
+export class Vector2WithInfo extends Vector2 {
     /**
-     * Class used to transport Vector2 information for pointer events
-     */    
-    export class Vector2WithInfo extends Vector2 {    
-        /**
-         * Creates a new Vector2WithInfo
-         * @param source defines the vector2 data to transport
-         * @param buttonIndex defines the current mouse button index
-         */    
-        public constructor(source: Vector2, 
-            /** defines the current mouse button index */
-            public buttonIndex: number = 0) {
-            super(source.x, source.y);
-        }
+     * Creates a new Vector2WithInfo
+     * @param source defines the vector2 data to transport
+     * @param buttonIndex defines the current mouse button index
+     */
+    public constructor(source: Vector2,
+        /** defines the current mouse button index */
+        public buttonIndex: number = 0) {
+        super(source.x, source.y);
     }
+}
 
-    /** Class used to provide 2D matrix features */
-    export class Matrix2D {
-        /** Gets the internal array of 6 floats used to store matrix data */
-        public m = new Float32Array(6);
-
-        /**
-         * Creates a new matrix
-         * @param m00 defines value for (0, 0)
-         * @param m01 defines value for (0, 1) 
-         * @param m10 defines value for (1, 0) 
-         * @param m11 defines value for (1, 1) 
-         * @param m20 defines value for (2, 0) 
-         * @param m21 defines value for (2, 1) 
-         */
-        constructor(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number) {
-            this.fromValues(m00, m01, m10, m11, m20, m21);
-        }
+/** Class used to provide 2D matrix features */
+export class Matrix2D {
+    /** Gets the internal array of 6 floats used to store matrix data */
+    public m = new Float32Array(6);
 
-        /**
-         * Fills the matrix from direct values
-         * @param m00 defines value for (0, 0)
-         * @param m01 defines value for (0, 1)
-         * @param m10 defines value for (1, 0)
-         * @param m11 defines value for (1, 1)
-         * @param m20 defines value for (2, 0)
-         * @param m21 defines value for (2, 1)
-         * @returns the current modified matrix
-         */
-        public fromValues(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number): Matrix2D {
-            this.m[0] = m00; this.m[1] = m01; 
-            this.m[2] = m10; this.m[3] = m11;
-            this.m[4] = m20; this.m[5] = m21;
-            return this;
-        }
+    /**
+     * Creates a new matrix
+     * @param m00 defines value for (0, 0)
+     * @param m01 defines value for (0, 1) 
+     * @param m10 defines value for (1, 0) 
+     * @param m11 defines value for (1, 1) 
+     * @param m20 defines value for (2, 0) 
+     * @param m21 defines value for (2, 1) 
+     */
+    constructor(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number) {
+        this.fromValues(m00, m01, m10, m11, m20, m21);
+    }
 
-        /** 
-         * Gets matrix determinant
-         * @returns the determinant
-         */
-        public determinant(): number {
-            return this.m[0] * this.m[3] - this.m[1] * this.m[2];
-        }
+    /**
+     * Fills the matrix from direct values
+     * @param m00 defines value for (0, 0)
+     * @param m01 defines value for (0, 1)
+     * @param m10 defines value for (1, 0)
+     * @param m11 defines value for (1, 1)
+     * @param m20 defines value for (2, 0)
+     * @param m21 defines value for (2, 1)
+     * @returns the current modified matrix
+     */
+    public fromValues(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number): Matrix2D {
+        this.m[0] = m00; this.m[1] = m01;
+        this.m[2] = m10; this.m[3] = m11;
+        this.m[4] = m20; this.m[5] = m21;
+        return this;
+    }
 
-        /**
-         * Inverses the matrix and stores it in a target matrix
-         * @param result defines the target matrix
-         * @returns the current matrix
-         */
-        public invertToRef(result: Matrix2D): Matrix2D {
-            let l0 = this.m[0]; let l1 = this.m[1];
-            let l2 = this.m[2]; let l3 = this.m[3];
-            let l4 = this.m[4]; let l5 = this.m[5];
-
-            let det = this.determinant();
-            if (det < (Epsilon * Epsilon)) {
-                result.m[0] = 0;     result.m[1] = 0;
-                result.m[2] = 0;    result.m[3] = 0;
-                result.m[4] = 0;   result.m[5] = 0;
-                return this;
-            }
-
-            let detDiv = 1 / det;
-
-            let det4 = l2 * l5 - l3 * l4;
-            let det5 = l1 * l4 - l0 * l5;
-
-            result.m[0] = l3 * detDiv;     result.m[1] = -l1 * detDiv;
-            result.m[2] = -l2 * detDiv;    result.m[3] = l0 * detDiv;
-            result.m[4] = det4 * detDiv;   result.m[5] = det5 * detDiv;
+    /** 
+     * Gets matrix determinant
+     * @returns the determinant
+     */
+    public determinant(): number {
+        return this.m[0] * this.m[3] - this.m[1] * this.m[2];
+    }
 
+    /**
+     * Inverses the matrix and stores it in a target matrix
+     * @param result defines the target matrix
+     * @returns the current matrix
+     */
+    public invertToRef(result: Matrix2D): Matrix2D {
+        let l0 = this.m[0]; let l1 = this.m[1];
+        let l2 = this.m[2]; let l3 = this.m[3];
+        let l4 = this.m[4]; let l5 = this.m[5];
+
+        let det = this.determinant();
+        if (det < (Epsilon * Epsilon)) {
+            result.m[0] = 0; result.m[1] = 0;
+            result.m[2] = 0; result.m[3] = 0;
+            result.m[4] = 0; result.m[5] = 0;
             return this;
         }
 
-        /**
-         * Multiplies the current matrix with another one
-         * @param other defines the second operand
-         * @param result defines the target matrix 
-         * @returns the current matrix
-         */
-        public multiplyToRef(other: Matrix2D, result: Matrix2D): Matrix2D {
-            let l0 = this.m[0];     let l1 = this.m[1];
-            let l2 = this.m[2];     let l3 = this.m[3];
-            let l4 = this.m[4];     let l5 = this.m[5];
-
-            let r0 = other.m[0];    let r1 = other.m[1];
-            let r2 = other.m[2];    let r3 = other.m[3];
-            let r4 = other.m[4];    let r5 = other.m[5];
-
-            result.m[0] = l0 * r0 + l1 * r2;        result.m[1] = l0 * r1 + l1 * r3;
-            result.m[2] = l2 * r0 + l3 * r2;        result.m[3] = l2 * r1 + l3 * r3;
-            result.m[4] = l4 * r0 + l5 * r2 + r4;   result.m[5] = l4 * r1 + l5 * r3 + r5;
+        let detDiv = 1 / det;
 
-            return this;
-        }
+        let det4 = l2 * l5 - l3 * l4;
+        let det5 = l1 * l4 - l0 * l5;
 
-        /**
-         * Applies the current matrix to a set of 2 floats and stores the result in a vector2
-         * @param x defines the x coordinate to transform
-         * @param y defines the x coordinate to transform 
-         * @param result defines the target vector2 
-         * @returns the current matrix
-         */
-        public transformCoordinates(x: number, y: number, result: Vector2): Matrix2D {
-            result.x = x * this.m[0] + y * this.m[2] + this.m[4];
-            result.y = x * this.m[1] + y * this.m[3] + this.m[5];
+        result.m[0] = l3 * detDiv; result.m[1] = -l1 * detDiv;
+        result.m[2] = -l2 * detDiv; result.m[3] = l0 * detDiv;
+        result.m[4] = det4 * detDiv; result.m[5] = det5 * detDiv;
 
-            return this;
-        }
+        return this;
+    }
 
-        // Statics
-        /**
-         * Creates an identity matrix
-         * @returns a new matrix
-         */
-        public static Identity(): Matrix2D {
-            return new Matrix2D(1, 0, 0, 1, 0, 0);
-        }
+    /**
+     * Multiplies the current matrix with another one
+     * @param other defines the second operand
+     * @param result defines the target matrix 
+     * @returns the current matrix
+     */
+    public multiplyToRef(other: Matrix2D, result: Matrix2D): Matrix2D {
+        let l0 = this.m[0]; let l1 = this.m[1];
+        let l2 = this.m[2]; let l3 = this.m[3];
+        let l4 = this.m[4]; let l5 = this.m[5];
+
+        let r0 = other.m[0]; let r1 = other.m[1];
+        let r2 = other.m[2]; let r3 = other.m[3];
+        let r4 = other.m[4]; let r5 = other.m[5];
+
+        result.m[0] = l0 * r0 + l1 * r2; result.m[1] = l0 * r1 + l1 * r3;
+        result.m[2] = l2 * r0 + l3 * r2; result.m[3] = l2 * r1 + l3 * r3;
+        result.m[4] = l4 * r0 + l5 * r2 + r4; result.m[5] = l4 * r1 + l5 * r3 + r5;
+
+        return this;
+    }
 
-        /**
-         * Creates a translation matrix and stores it in a target matrix
-         * @param x defines the x coordinate of the translation
-         * @param y defines the y coordinate of the translation 
-         * @param result defines the target matrix
-         */
-        public static TranslationToRef(x: number, y: number, result: Matrix2D): void {
-            result.fromValues(1, 0, 0, 1, x, y);
-        }
+    /**
+     * Applies the current matrix to a set of 2 floats and stores the result in a vector2
+     * @param x defines the x coordinate to transform
+     * @param y defines the x coordinate to transform 
+     * @param result defines the target vector2 
+     * @returns the current matrix
+     */
+    public transformCoordinates(x: number, y: number, result: Vector2): Matrix2D {
+        result.x = x * this.m[0] + y * this.m[2] + this.m[4];
+        result.y = x * this.m[1] + y * this.m[3] + this.m[5];
+
+        return this;
+    }
 
-        /**
-         * Creates a scaling matrix and stores it in a target matrix
-         * @param x defines the x coordinate of the scaling
-         * @param y defines the y coordinate of the scaling 
-         * @param result defines the target matrix
-         */
-        public static ScalingToRef(x: number, y: number, result: Matrix2D): void {
-            result.fromValues(x, 0, 0, y,  0, 0);
-        }
+    // Statics
+    /**
+     * Creates an identity matrix
+     * @returns a new matrix
+     */
+    public static Identity(): Matrix2D {
+        return new Matrix2D(1, 0, 0, 1, 0, 0);
+    }
 
-        /**
-         * Creates a rotation matrix and stores it in a target matrix
-         * @param angle defines the rotation angle
-         * @param result defines the target matrix
-         */        
-        public static RotationToRef(angle: number, result: Matrix2D): void {
-            var s = Math.sin(angle);
-            var c = Math.cos(angle);
+    /**
+     * Creates a translation matrix and stores it in a target matrix
+     * @param x defines the x coordinate of the translation
+     * @param y defines the y coordinate of the translation 
+     * @param result defines the target matrix
+     */
+    public static TranslationToRef(x: number, y: number, result: Matrix2D): void {
+        result.fromValues(1, 0, 0, 1, x, y);
+    }
 
-            result.fromValues(c, s, -s, c,  0, 0);
-        }
+    /**
+     * Creates a scaling matrix and stores it in a target matrix
+     * @param x defines the x coordinate of the scaling
+     * @param y defines the y coordinate of the scaling 
+     * @param result defines the target matrix
+     */
+    public static ScalingToRef(x: number, y: number, result: Matrix2D): void {
+        result.fromValues(x, 0, 0, y, 0, 0);
+    }
+
+    /**
+     * Creates a rotation matrix and stores it in a target matrix
+     * @param angle defines the rotation angle
+     * @param result defines the target matrix
+     */
+    public static RotationToRef(angle: number, result: Matrix2D): void {
+        var s = Math.sin(angle);
+        var c = Math.cos(angle);
+
+        result.fromValues(c, s, -s, c, 0, 0);
+    }
 
-        private static _TempPreTranslationMatrix = Matrix2D.Identity();
-        private static _TempPostTranslationMatrix = Matrix2D.Identity();
-        private static _TempRotationMatrix = Matrix2D.Identity();
-        private static _TempScalingMatrix = Matrix2D.Identity();
-        private static _TempCompose0 = Matrix2D.Identity();
-        private static _TempCompose1 = Matrix2D.Identity();
-        private static _TempCompose2 = Matrix2D.Identity();
-
-        /**
-         * Composes a matrix from translation, rotation, scaling and parent matrix and stores it in a target matrix 
-         * @param tx defines the x coordinate of the translation
-         * @param ty defines the y coordinate of the translation 
-         * @param angle defines the rotation angle 
-         * @param scaleX defines the x coordinate of the scaling
-         * @param scaleY defines the y coordinate of the scaling 
-         * @param parentMatrix defines the parent matrix to multiply by (can be null)
-         * @param result defines the target matrix 
-         */
-        public static ComposeToRef(tx: number, ty: number, angle: number, scaleX: number, scaleY: number, parentMatrix: Nullable<Matrix2D>,  result: Matrix2D): void {
-            Matrix2D.TranslationToRef(tx, ty, Matrix2D._TempPreTranslationMatrix);
-
-            Matrix2D.ScalingToRef(scaleX, scaleY, Matrix2D._TempScalingMatrix);
-
-            Matrix2D.RotationToRef(angle, Matrix2D._TempRotationMatrix);
-
-            Matrix2D.TranslationToRef(-tx, -ty, Matrix2D._TempPostTranslationMatrix);
-
-            Matrix2D._TempPreTranslationMatrix.multiplyToRef(Matrix2D._TempScalingMatrix, Matrix2D._TempCompose0);
-            Matrix2D._TempCompose0.multiplyToRef(Matrix2D._TempRotationMatrix, Matrix2D._TempCompose1);
-            if (parentMatrix) {
-                Matrix2D._TempCompose1.multiplyToRef(Matrix2D._TempPostTranslationMatrix, Matrix2D._TempCompose2);
-                Matrix2D._TempCompose2.multiplyToRef(parentMatrix, result);
-            } else {
-                Matrix2D._TempCompose1.multiplyToRef(Matrix2D._TempPostTranslationMatrix, result);
-            }
+    private static _TempPreTranslationMatrix = Matrix2D.Identity();
+    private static _TempPostTranslationMatrix = Matrix2D.Identity();
+    private static _TempRotationMatrix = Matrix2D.Identity();
+    private static _TempScalingMatrix = Matrix2D.Identity();
+    private static _TempCompose0 = Matrix2D.Identity();
+    private static _TempCompose1 = Matrix2D.Identity();
+    private static _TempCompose2 = Matrix2D.Identity();
+
+    /**
+     * Composes a matrix from translation, rotation, scaling and parent matrix and stores it in a target matrix 
+     * @param tx defines the x coordinate of the translation
+     * @param ty defines the y coordinate of the translation 
+     * @param angle defines the rotation angle 
+     * @param scaleX defines the x coordinate of the scaling
+     * @param scaleY defines the y coordinate of the scaling 
+     * @param parentMatrix defines the parent matrix to multiply by (can be null)
+     * @param result defines the target matrix 
+     */
+    public static ComposeToRef(tx: number, ty: number, angle: number, scaleX: number, scaleY: number, parentMatrix: Nullable<Matrix2D>, result: Matrix2D): void {
+        Matrix2D.TranslationToRef(tx, ty, Matrix2D._TempPreTranslationMatrix);
+
+        Matrix2D.ScalingToRef(scaleX, scaleY, Matrix2D._TempScalingMatrix);
+
+        Matrix2D.RotationToRef(angle, Matrix2D._TempRotationMatrix);
+
+        Matrix2D.TranslationToRef(-tx, -ty, Matrix2D._TempPostTranslationMatrix);
+
+        Matrix2D._TempPreTranslationMatrix.multiplyToRef(Matrix2D._TempScalingMatrix, Matrix2D._TempCompose0);
+        Matrix2D._TempCompose0.multiplyToRef(Matrix2D._TempRotationMatrix, Matrix2D._TempCompose1);
+        if (parentMatrix) {
+            Matrix2D._TempCompose1.multiplyToRef(Matrix2D._TempPostTranslationMatrix, Matrix2D._TempCompose2);
+            Matrix2D._TempCompose2.multiplyToRef(parentMatrix, result);
+        } else {
+            Matrix2D._TempCompose1.multiplyToRef(Matrix2D._TempPostTranslationMatrix, result);
         }
-    }    
-}
+    }
+}   

+ 57 - 60
gui/src/2D/measure.ts

@@ -1,72 +1,69 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
-module BABYLON.GUI {
+/**
+ * Class used to store 2D control sizes
+ */
+export class Measure {
     /**
-     * Class used to store 2D control sizes
+     * Creates a new measure
+     * @param left defines left coordinate
+     * @param top defines top coordinate 
+     * @param width defines width dimension
+     * @param height defines height dimension
      */
-    export class Measure {
-        /**
-         * Creates a new measure
-         * @param left defines left coordinate
-         * @param top defines top coordinate 
-         * @param width defines width dimension
-         * @param height defines height dimension
-         */
-        public constructor(
-            /** defines left coordinate */
-            public left: number, 
-            /** defines top coordinate  */
-            public top: number, 
-            /** defines width dimension  */
-            public width: number, 
-            /** defines height dimension */
-            public height: number) {
+    public constructor(
+        /** defines left coordinate */
+        public left: number,
+        /** defines top coordinate  */
+        public top: number,
+        /** defines width dimension  */
+        public width: number,
+        /** defines height dimension */
+        public height: number) {
 
-        }
-
-        /**
-         * Copy from another measure
-         * @param other defines the other measure to copy from
-         */
-        public copyFrom(other: Measure): void {
-            this.left = other.left;
-            this.top = other.top;
-            this.width = other.width;
-            this.height = other.height;
-        }
-
-        /**
-         * Check equality between this measure and another one
-         * @param other defines the other measures
-         * @returns true if both measures are equals
-         */
-        public isEqualsTo(other: Measure): boolean {
+    }
 
-            if (this.left !== other.left) {
-                return false;
-            }
+    /**
+     * Copy from another measure
+     * @param other defines the other measure to copy from
+     */
+    public copyFrom(other: Measure): void {
+        this.left = other.left;
+        this.top = other.top;
+        this.width = other.width;
+        this.height = other.height;
+    }
 
-            if (this.top !== other.top) {
-                return false;
-            }
+    /**
+     * Check equality between this measure and another one
+     * @param other defines the other measures
+     * @returns true if both measures are equals
+     */
+    public isEqualsTo(other: Measure): boolean {
 
-            if (this.width !== other.width) {
-                return false;
-            }
+        if (this.left !== other.left) {
+            return false;
+        }
 
-            if (this.height !== other.height) {
-                return false;
-            }
+        if (this.top !== other.top) {
+            return false;
+        }
 
-            return true;
+        if (this.width !== other.width) {
+            return false;
         }
 
-        /**
-         * Creates an empty measure
-         * @returns a new measure
-         */
-        public static Empty(): Measure {
-            return new Measure(0, 0, 0, 0);
+        if (this.height !== other.height) {
+            return false;
         }
-    }    
-}
+
+        return true;
+    }
+
+    /**
+     * Creates an empty measure
+     * @returns a new measure
+     */
+    public static Empty(): Measure {
+        return new Measure(0, 0, 0, 0);
+    }
+}   

+ 106 - 106
gui/src/2D/multiLinePoint.ts

@@ -1,150 +1,150 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+import { MultiLine } from "./controls/multiLine";
+import { ValueAndUnit } from "./valueAndUnit";
+import { Control } from "./controls/control";
+import { AbstractMesh, Nullable, Observer, Camera, Vector2 } from "babylonjs";
 
-module BABYLON.GUI {
 
-    /**
-     * Class used to store a point for a MultiLine object.
-     * The point can be pure 2D coordinates, a mesh or a control
-     */
-    export class MultiLinePoint {
+/**
+ * Class used to store a point for a MultiLine object.
+ * The point can be pure 2D coordinates, a mesh or a control
+ */
+export class MultiLinePoint {
+
+    private _multiLine: MultiLine;
+
+    private _x: ValueAndUnit;
+    private _y: ValueAndUnit;
+    private _control: Nullable<Control>;
+    private _mesh: Nullable<AbstractMesh>;
 
-        private _multiLine: MultiLine;
+    private _controlObserver: Nullable<Observer<Control>>;
+    private _meshObserver: Nullable<Observer<Camera>>;
 
-        private _x: ValueAndUnit;
-        private _y: ValueAndUnit;
-        private _control: Nullable<Control>;
-        private _mesh: Nullable<AbstractMesh>;
+    /** @hidden */
+    public _point: Vector2;
 
-        private _controlObserver: Nullable< Observer<Control> >;
-        private _meshObserver: Nullable< Observer<Camera> >;
+    /**
+     * Creates a new MultiLinePoint
+     * @param multiLine defines the source MultiLine object
+     */
+    constructor(multiLine: MultiLine) {
+        this._multiLine = multiLine;
 
-        /** @hidden */
-        public _point: Vector2;
+        this._x = new ValueAndUnit(0);
+        this._y = new ValueAndUnit(0);
 
-        /**
-         * Creates a new MultiLinePoint
-         * @param multiLine defines the source MultiLine object
-         */
-        constructor(multiLine: MultiLine) {
-            this._multiLine = multiLine;
+        this._point = new Vector2(0, 0);
+    }
 
-            this._x = new ValueAndUnit(0);
-            this._y = new ValueAndUnit(0);
+    /** Gets or sets x coordinate */
+    public get x(): string | number {
+        return this._x.toString(this._multiLine._host);
+    }
 
-            this._point = new Vector2(0, 0);
+    public set x(value: string | number) {
+        if (this._x.toString(this._multiLine._host) === value) {
+            return;
         }
 
-        /** Gets or sets x coordinate */
-        public get x(): string | number {
-            return this._x.toString(this._multiLine._host);
+        if (this._x.fromString(value)) {
+            this._multiLine._markAsDirty();
         }
+    }
 
-        public set x(value: string | number) {
-            if (this._x.toString(this._multiLine._host) === value) {
-                return;
-            }
+    /** Gets or sets y coordinate */
+    public get y(): string | number {
+        return this._y.toString(this._multiLine._host);
+    }
 
-            if (this._x.fromString(value)) {
-                this._multiLine._markAsDirty();
-            }
+    public set y(value: string | number) {
+        if (this._y.toString(this._multiLine._host) === value) {
+            return;
         }
 
-        /** Gets or sets y coordinate */
-        public get y(): string | number {
-            return this._y.toString(this._multiLine._host);
+        if (this._y.fromString(value)) {
+            this._multiLine._markAsDirty();
         }
+    }
 
-        public set y(value: string | number) {
-            if (this._y.toString(this._multiLine._host) === value) {
-                return;
-            }
+    /** Gets or sets the control associated with this point */
+    public get control(): Nullable<Control> {
+        return this._control;
+    }
 
-            if (this._y.fromString(value)) {
-                this._multiLine._markAsDirty();
-            }
+    public set control(value: Nullable<Control>) {
+        if (this._control === value) {
+            return;
         }
 
-        /** Gets or sets the control associated with this point */
-        public get control(): Nullable<Control> {
-            return this._control;
-        }
+        if (this._control && this._controlObserver) {
+            this._control.onDirtyObservable.remove(this._controlObserver);
 
-        public set control(value: Nullable<Control>) {
-            if (this._control === value) {
-                return;
-            }
+            this._controlObserver = null;
+        }
 
-            if (this._control && this._controlObserver) {
-                this._control.onDirtyObservable.remove(this._controlObserver);
+        this._control = value;
 
-                this._controlObserver = null;
-            }
+        if (this._control) {
+            this._controlObserver = this._control.onDirtyObservable.add(this._multiLine.onPointUpdate);
+        }
 
-            this._control = value;
+        this._multiLine._markAsDirty();
+    }
 
-            if (this._control) {
-                this._controlObserver = this._control.onDirtyObservable.add(this._multiLine.onPointUpdate);
-            }
+    /** Gets or sets the mesh associated with this point */
+    public get mesh(): Nullable<AbstractMesh> {
+        return this._mesh;
+    }
 
-            this._multiLine._markAsDirty();
+    public set mesh(value: Nullable<AbstractMesh>) {
+        if (this._mesh === value) {
+            return;
         }
 
-        /** Gets or sets the mesh associated with this point */
-        public get mesh(): Nullable<AbstractMesh> {
-            return this._mesh;
+        if (this._mesh && this._meshObserver) {
+            this._mesh.getScene().onAfterCameraRenderObservable.remove(this._meshObserver);
         }
 
-        public set mesh(value: Nullable<AbstractMesh>) {
-            if (this._mesh === value) {
-                return;
-            }
-
-            if (this._mesh && this._meshObserver) {
-                this._mesh.getScene().onAfterCameraRenderObservable.remove(this._meshObserver);
-            }
+        this._mesh = value;
 
-            this._mesh = value;
+        if (this._mesh) {
+            this._meshObserver = this._mesh.getScene().onAfterCameraRenderObservable.add(this._multiLine.onPointUpdate);
+        }
 
-            if (this._mesh) {
-                this._meshObserver = this._mesh.getScene().onAfterCameraRenderObservable.add(this._multiLine.onPointUpdate);
-            }
+        this._multiLine._markAsDirty();
+    }
 
-            this._multiLine._markAsDirty();
-        }
+    /** 
+     * Gets a translation vector
+     * @returns the translation vector
+     */
+    public translate(): Vector2 {
+        this._point = this._translatePoint();
 
-        /** 
-         * Gets a translation vector
-         * @returns the translation vector
-         */
-        public translate(): Vector2 {
-            this._point = this._translatePoint();
+        return this._point;
+    }
 
-            return this._point;
+    private _translatePoint(): Vector2 {
+        if (this._mesh != null) {
+            return this._multiLine._host.getProjectedPosition(this._mesh.getBoundingInfo().boundingSphere.center, this._mesh.getWorldMatrix());
         }
-
-        private _translatePoint(): Vector2 {
-            if (this._mesh != null) {
-                return this._multiLine._host.getProjectedPosition(this._mesh.getBoundingInfo().boundingSphere.center, this._mesh.getWorldMatrix());
-            }
-            else if (this._control != null) {
-                return new Vector2(this._control.centerX, this._control.centerY);
-            }
-            else {
-                var host: any = this._multiLine._host as any;
-
-                var xValue: number = this._x.getValueInPixel(host, Number(host._canvas.width));
-                var yValue: number = this._y.getValueInPixel(host, Number(host._canvas.height));
-                
-                return new Vector2(xValue, yValue);
-            }
+        else if (this._control != null) {
+            return new Vector2(this._control.centerX, this._control.centerY);
         }
+        else {
+            var host: any = this._multiLine._host as any;
+
+            var xValue: number = this._x.getValueInPixel(host, Number(host._canvas.width));
+            var yValue: number = this._y.getValueInPixel(host, Number(host._canvas.height));
 
-        /** Release associated resources */
-        public dispose(): void {
-            this.control = null;
-            this.mesh = null;
+            return new Vector2(xValue, yValue);
         }
+    }
 
+    /** Release associated resources */
+    public dispose(): void {
+        this.control = null;
+        this.mesh = null;
     }
 
 }

+ 79 - 79
gui/src/2D/style.ts

@@ -1,98 +1,98 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+import { IDisposable, Observable } from "babylonjs";
+import { AdvancedDynamicTexture } from "./advancedDynamicTexture";
+import { ValueAndUnit } from "./valueAndUnit";
+
+/**
+ * Define a style used by control to automatically setup properties based on a template.
+ * Only support font related properties so far
+ */
+export class Style implements IDisposable {
+    private _fontFamily = "Arial";
+    private _fontStyle = "";
+    private _fontWeight = "";
+    /** @hidden */
+    public _host: AdvancedDynamicTexture;
+    /** @hidden */
+    public _fontSize = new ValueAndUnit(18, ValueAndUnit.UNITMODE_PIXEL, false);
 
-module BABYLON.GUI {
     /**
-     * Define a style used by control to automatically setup properties based on a template.
-     * Only support font related properties so far
+     * Observable raised when the style values are changed
      */
-    export class Style implements BABYLON.IDisposable {
-        private _fontFamily = "Arial";
-        private _fontStyle = "";       
-        private _fontWeight = "";     
-        /** @hidden */ 
-        public _host: AdvancedDynamicTexture;
-        /** @hidden */
-        public _fontSize = new ValueAndUnit(18, ValueAndUnit.UNITMODE_PIXEL, false);
-
-        /**
-         * Observable raised when the style values are changed
-         */
-        public onChangedObservable = new BABYLON.Observable<Style>();
-
-        /**
-         * Creates a new style object
-         * @param host defines the AdvancedDynamicTexture which hosts this style
-         */
-        public constructor(host: AdvancedDynamicTexture) {
-            this._host = host;
-        }
+    public onChangedObservable = new Observable<Style>();
 
-        /**
-         * Gets or sets the font size
-         */
-        public get fontSize(): string | number {
-            return this._fontSize.toString(this._host);
-        }
+    /**
+     * Creates a new style object
+     * @param host defines the AdvancedDynamicTexture which hosts this style
+     */
+    public constructor(host: AdvancedDynamicTexture) {
+        this._host = host;
+    }
 
-        public set fontSize(value: string | number) {
-            if (this._fontSize.toString(this._host) === value) {
-                return;
-            }
-
-            if (this._fontSize.fromString(value)) {
-                this.onChangedObservable.notifyObservers(this);
-            }
-        }        
-        
-        /**
-         * Gets or sets the font family
-         */
-        public get fontFamily(): string {
-            return this._fontFamily;
-        }
+    /**
+     * Gets or sets the font size
+     */
+    public get fontSize(): string | number {
+        return this._fontSize.toString(this._host);
+    }
 
-        public set fontFamily(value: string) {
-            if (this._fontFamily === value) {
-                return;
-            }
+    public set fontSize(value: string | number) {
+        if (this._fontSize.toString(this._host) === value) {
+            return;
+        }
 
-            this._fontFamily = value;
+        if (this._fontSize.fromString(value)) {
             this.onChangedObservable.notifyObservers(this);
         }
+    }
 
-        /**
-         * Gets or sets the font style 
-         */
-        public get fontStyle(): string {
-            return this._fontStyle;
+    /**
+     * Gets or sets the font family
+     */
+    public get fontFamily(): string {
+        return this._fontFamily;
+    }
+
+    public set fontFamily(value: string) {
+        if (this._fontFamily === value) {
+            return;
         }
 
-        public set fontStyle(value: string) {
-            if (this._fontStyle === value) {
-                return;
-            }
+        this._fontFamily = value;
+        this.onChangedObservable.notifyObservers(this);
+    }
 
-            this._fontStyle = value;
-            this.onChangedObservable.notifyObservers(this);
-        }
+    /**
+     * Gets or sets the font style 
+     */
+    public get fontStyle(): string {
+        return this._fontStyle;
+    }
 
-        /** Gets or sets font weight */
-        public get fontWeight(): string {
-            return this._fontWeight;
+    public set fontStyle(value: string) {
+        if (this._fontStyle === value) {
+            return;
         }
 
-        public set fontWeight(value: string) {
-            if (this._fontWeight === value) {
-                return;
-            }
+        this._fontStyle = value;
+        this.onChangedObservable.notifyObservers(this);
+    }
 
-            this._fontWeight = value;            
-            this.onChangedObservable.notifyObservers(this);
-        }          
+    /** Gets or sets font weight */
+    public get fontWeight(): string {
+        return this._fontWeight;
+    }
 
-        /** Dispose all associated resources */
-        public dispose() {
-            this.onChangedObservable.clear();
+    public set fontWeight(value: string) {
+        if (this._fontWeight === value) {
+            return;
         }
-    }    
-}
+
+        this._fontWeight = value;
+        this.onChangedObservable.notifyObservers(this);
+    }
+
+    /** Dispose all associated resources */
+    public dispose() {
+        this.onChangedObservable.clear();
+    }
+}    

+ 135 - 137
gui/src/2D/valueAndUnit.ts

@@ -1,165 +1,163 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+import { AdvancedDynamicTexture } from "./advancedDynamicTexture";
 
-module BABYLON.GUI {
+/**
+ * Class used to specific a value and its associated unit
+ */
+export class ValueAndUnit {
+    private _value = 1;
     /**
-     * Class used to specific a value and its associated unit
+     * Gets or sets a value indicating that this value will not scale accordingly with adaptive scaling property
+     * @see http://doc.babylonjs.com/how_to/gui#adaptive-scaling
      */
-    export class ValueAndUnit {
-        private _value = 1;
-        /**
-         * Gets or sets a value indicating that this value will not scale accordingly with adaptive scaling property
-         * @see http://doc.babylonjs.com/how_to/gui#adaptive-scaling
-         */
-        public ignoreAdaptiveScaling = false;
-
-        /**
-         * Creates a new ValueAndUnit
-         * @param value defines the value to store
-         * @param unit defines the unit to store
-         * @param negativeValueAllowed defines a boolean indicating if the value can be negative
-         */
-        public constructor(value: number, 
-            /** defines the unit to store */
-            public unit = ValueAndUnit.UNITMODE_PIXEL, 
-            /** defines a boolean indicating if the value can be negative */
-            public negativeValueAllowed = true) {
-            this._value = value;
-        }
+    public ignoreAdaptiveScaling = false;
 
-        /** Gets a boolean indicating if the value is a percentage */
-        public get isPercentage(): boolean {
-            return this.unit === ValueAndUnit.UNITMODE_PERCENTAGE;
-        }
+    /**
+     * Creates a new ValueAndUnit
+     * @param value defines the value to store
+     * @param unit defines the unit to store
+     * @param negativeValueAllowed defines a boolean indicating if the value can be negative
+     */
+    public constructor(value: number,
+        /** defines the unit to store */
+        public unit = ValueAndUnit.UNITMODE_PIXEL,
+        /** defines a boolean indicating if the value can be negative */
+        public negativeValueAllowed = true) {
+        this._value = value;
+    }
+
+    /** Gets a boolean indicating if the value is a percentage */
+    public get isPercentage(): boolean {
+        return this.unit === ValueAndUnit.UNITMODE_PERCENTAGE;
+    }
+
+    /** Gets a boolean indicating if the value is store as pixel */
+    public get isPixel(): boolean {
+        return this.unit === ValueAndUnit.UNITMODE_PIXEL;
+    }
+
+    /** Gets direct internal value */
+    public get internalValue(): number {
+        return this._value;
+    }
 
-        /** Gets a boolean indicating if the value is store as pixel */
-        public get isPixel(): boolean {
-            return this.unit === ValueAndUnit.UNITMODE_PIXEL;
+    /**
+     * Gets value as pixel
+     * @param host defines the root host
+     * @param refValue defines the reference value for percentages
+     * @returns the value as pixel
+     */
+    public getValueInPixel(host: AdvancedDynamicTexture, refValue: number): number {
+        if (this.isPixel) {
+            return this.getValue(host);
         }
 
-        /** Gets direct internal value */
-        public get internalValue(): number {
-            return this._value;
-        }
+        return this.getValue(host) * refValue;
+    }
 
-        /**
-         * Gets value as pixel
-         * @param host defines the root host
-         * @param refValue defines the reference value for percentages
-         * @returns the value as pixel
-         */
-        public getValueInPixel(host: AdvancedDynamicTexture, refValue: number): number {
-            if (this.isPixel) {
-                return this.getValue(host);
+    /**
+     * Gets the value accordingly to its unit
+     * @param host  defines the root host
+     * @returns the value
+     */
+    public getValue(host: AdvancedDynamicTexture): number {
+        if (host && !this.ignoreAdaptiveScaling && this.unit !== ValueAndUnit.UNITMODE_PERCENTAGE) {
+            var width: number = 0;
+            var height: number = 0;
+
+            if (host.idealWidth) {
+                width = (this._value * host.getSize().width) / host.idealWidth;
             }
 
-            return this.getValue(host) * refValue;
-        }
+            if (host.idealHeight) {
+                height = (this._value * host.getSize().height) / host.idealHeight;
+            }
 
-        /**
-         * Gets the value accordingly to its unit
-         * @param host  defines the root host
-         * @returns the value
-         */
-        public getValue(host: AdvancedDynamicTexture): number {
-            if (host && !this.ignoreAdaptiveScaling && this.unit !== ValueAndUnit.UNITMODE_PERCENTAGE) {
-                var width: number = 0;
-                var height: number = 0;
-
-                if (host.idealWidth) {
-                    width = (this._value * host.getSize().width) / host.idealWidth;
-                }
-                
-                if (host.idealHeight) {
-                    height = (this._value * host.getSize().height) / host.idealHeight;
-                }
-
-                if (host.useSmallestIdeal && host.idealWidth && host.idealHeight) {
-                    return window.innerWidth < window.innerHeight ? width : height;
-                }
-
-                if (host.idealWidth) { // horizontal
-                    return width;
-                }
-                
-                if (host.idealHeight) { // vertical
-                    return height;
-                }
+            if (host.useSmallestIdeal && host.idealWidth && host.idealHeight) {
+                return window.innerWidth < window.innerHeight ? width : height;
+            }
+
+            if (host.idealWidth) { // horizontal
+                return width;
             }
-            return this._value;
-        }
 
-        /**
-         * Gets a string representation of the value
-         * @param host defines the root host
-         * @returns a string
-         */
-        public toString(host: AdvancedDynamicTexture): string {
-            switch (this.unit) {
-                case ValueAndUnit.UNITMODE_PERCENTAGE:
-                    return (this.getValue(host) * 100) + "%";
-                case ValueAndUnit.UNITMODE_PIXEL:
-                    return this.getValue(host) + "px";
+            if (host.idealHeight) { // vertical
+                return height;
             }
+        }
+        return this._value;
+    }
 
-            return this.unit.toString();
+    /**
+     * Gets a string representation of the value
+     * @param host defines the root host
+     * @returns a string
+     */
+    public toString(host: AdvancedDynamicTexture): string {
+        switch (this.unit) {
+            case ValueAndUnit.UNITMODE_PERCENTAGE:
+                return (this.getValue(host) * 100) + "%";
+            case ValueAndUnit.UNITMODE_PIXEL:
+                return this.getValue(host) + "px";
         }
 
-        /**
-         * Store a value parsed from a string
-         * @param source defines the source string
-         * @returns true if the value was successfully parsed
-         */
-        public fromString(source: string | number ): boolean {
-            var match = ValueAndUnit._Regex.exec(source.toString());
+        return this.unit.toString();
+    }
 
-            if (!match || match.length === 0) {
-                return false;
-            }
+    /**
+     * Store a value parsed from a string
+     * @param source defines the source string
+     * @returns true if the value was successfully parsed
+     */
+    public fromString(source: string | number): boolean {
+        var match = ValueAndUnit._Regex.exec(source.toString());
 
-            var sourceValue = parseFloat(match[1]);
-            var sourceUnit = this.unit;
+        if (!match || match.length === 0) {
+            return false;
+        }
 
-            if (!this.negativeValueAllowed) {
-                if (sourceValue < 0) {
-                    sourceValue = 0;
-                }
-            }
-            
-            if (match.length === 4) {
-                switch(match[3]) {
-                    case "px":
-                        sourceUnit = ValueAndUnit.UNITMODE_PIXEL;
-                        break;
-                    case "%":
-                        sourceUnit = ValueAndUnit.UNITMODE_PERCENTAGE;
-                        sourceValue /= 100.0;
-                        break;
-                }
-            }
+        var sourceValue = parseFloat(match[1]);
+        var sourceUnit = this.unit;
 
-            if (sourceValue === this._value && sourceUnit === this.unit) {
-                return false;
+        if (!this.negativeValueAllowed) {
+            if (sourceValue < 0) {
+                sourceValue = 0;
             }
+        }
 
-            this._value = sourceValue;
-            this.unit = sourceUnit;
+        if (match.length === 4) {
+            switch (match[3]) {
+                case "px":
+                    sourceUnit = ValueAndUnit.UNITMODE_PIXEL;
+                    break;
+                case "%":
+                    sourceUnit = ValueAndUnit.UNITMODE_PERCENTAGE;
+                    sourceValue /= 100.0;
+                    break;
+            }
+        }
 
-            return true;
+        if (sourceValue === this._value && sourceUnit === this.unit) {
+            return false;
         }
 
-        // Static
-        private static _Regex = /(^-?\d*(\.\d+)?)(%|px)?/;
-        private static _UNITMODE_PERCENTAGE = 0;
-        private static _UNITMODE_PIXEL = 1;
+        this._value = sourceValue;
+        this.unit = sourceUnit;
 
-        /** UNITMODE_PERCENTAGE */
-        public static get UNITMODE_PERCENTAGE(): number {
-            return ValueAndUnit._UNITMODE_PERCENTAGE;
-        }
+        return true;
+    }
+
+    // Static
+    private static _Regex = /(^-?\d*(\.\d+)?)(%|px)?/;
+    private static _UNITMODE_PERCENTAGE = 0;
+    private static _UNITMODE_PIXEL = 1;
+
+    /** UNITMODE_PERCENTAGE */
+    public static get UNITMODE_PERCENTAGE(): number {
+        return ValueAndUnit._UNITMODE_PERCENTAGE;
+    }
 
-        /** UNITMODE_PIXEL */
-        public static get UNITMODE_PIXEL(): number {
-            return ValueAndUnit._UNITMODE_PIXEL;
-        }   
-    }    
-}
+    /** UNITMODE_PIXEL */
+    public static get UNITMODE_PIXEL(): number {
+        return ValueAndUnit._UNITMODE_PIXEL;
+    }
+}  

+ 17 - 18
gui/src/3D/controls/abstractButton3D.ts

@@ -1,25 +1,24 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Control3D } from "./control3D";
+import { TransformNode, Scene } from "babylonjs";
 
-module BABYLON.GUI {
+/**
+ * Class used as a root to all buttons
+ */
+export class AbstractButton3D extends Control3D {
     /**
-     * Class used as a root to all buttons
+     * Creates a new button
+     * @param name defines the control name
      */
-    export class AbstractButton3D extends Control3D {
-        /**
-         * Creates a new button
-         * @param name defines the control name
-         */
-        constructor(name?: string) {
-            super(name);
-        }
+    constructor(name?: string) {
+        super(name);
+    }
 
-        protected _getTypeName(): string {
-            return "AbstractButton3D";
-        }        
+    protected _getTypeName(): string {
+        return "AbstractButton3D";
+    }
 
-        // Mesh association
-        protected _createNode(scene: Scene): TransformNode {
-            return new TransformNode("button" + this.name);
-        }    
+    // Mesh association
+    protected _createNode(scene: Scene): TransformNode {
+        return new TransformNode("button" + this.name);
     }
 }

+ 135 - 134
gui/src/3D/controls/button3D.ts

@@ -1,177 +1,178 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { AbstractButton3D } from "./abstractButton3D";
+import { Material, Nullable, int, Color3, StandardMaterial, Texture, Scene, TransformNode, Vector4, MeshBuilder, AbstractMesh } from "babylonjs";
+import { AdvancedDynamicTexture } from "../../2D/advancedDynamicTexture";
+import { Control } from "../../2D/controls/control";
+
+/**
+ * Class used to create a button in 3D
+ */
+export class Button3D extends AbstractButton3D {
+    /** @hidden */
+    protected _currentMaterial: Material;
+    private _facadeTexture: Nullable<AdvancedDynamicTexture>;
+    private _content: Control;
+    private _contentResolution = 512;
+    private _contentScaleRatio = 2;
 
-module BABYLON.GUI {
     /**
-     * Class used to create a button in 3D
+     * Gets or sets the texture resolution used to render content (512 by default)
      */
-    export class Button3D extends AbstractButton3D {
-        /** @hidden */
-        protected _currentMaterial: Material;
-        private _facadeTexture: Nullable<AdvancedDynamicTexture>;
-        private _content: Control;
-        private _contentResolution = 512;
-        private _contentScaleRatio = 2;
-
-        /**
-         * Gets or sets the texture resolution used to render content (512 by default)
-         */
-        public get contentResolution(): int {
-            return this._contentResolution;
+    public get contentResolution(): int {
+        return this._contentResolution;
+    }
+
+    public set contentResolution(value: int) {
+        if (this._contentResolution === value) {
+            return;
         }
 
-        public set contentResolution(value: int) {
-            if (this._contentResolution === value) {
-                return;
-            }
+        this._contentResolution = value;
+        this._resetContent();
+    }
 
-            this._contentResolution = value;
-            this._resetContent();
+    /**
+     * Gets or sets the texture scale ratio used to render content (2 by default)
+     */
+    public get contentScaleRatio(): number {
+        return this._contentScaleRatio;
+    }
+
+    public set contentScaleRatio(value: number) {
+        if (this._contentScaleRatio === value) {
+            return;
         }
 
-        /**
-         * Gets or sets the texture scale ratio used to render content (2 by default)
-         */
-        public get contentScaleRatio(): number {
-            return this._contentScaleRatio;
+        this._contentScaleRatio = value;
+        this._resetContent();
+    }
+
+    protected _disposeFacadeTexture() {
+        if (this._facadeTexture) {
+            this._facadeTexture.dispose();
+            this._facadeTexture = null;
         }
+    }
 
-        public set contentScaleRatio(value: number) {
-            if (this._contentScaleRatio === value) {
-                return;
-            }
+    protected _resetContent() {
+        this._disposeFacadeTexture();
+        this.content = this._content;
+    }
+
+    /**
+     * Creates a new button
+     * @param name defines the control name
+     */
+    constructor(name?: string) {
+        super(name);
+
+        // Default animations
 
-            this._contentScaleRatio = value;
-            this._resetContent();
-        }   
-        
-        protected _disposeFacadeTexture() {
-            if (this._facadeTexture) {
-                this._facadeTexture.dispose();
-                this._facadeTexture = null;
+        this.pointerEnterAnimation = () => {
+            if (!this.mesh) {
+                return;
             }
+            (<StandardMaterial>this._currentMaterial).emissiveColor = Color3.Red();
         }
 
-        protected _resetContent() {
-            this._disposeFacadeTexture();
-            this.content = this._content;
+        this.pointerOutAnimation = () => {
+            (<StandardMaterial>this._currentMaterial).emissiveColor = Color3.Black();
         }
 
-        /**
-         * Creates a new button
-         * @param name defines the control name
-         */
-        constructor(name?: string) {
-            super(name);
+        this.pointerDownAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
 
-            // Default animations
+            this.mesh.scaling.scaleInPlace(0.95);
+        }
 
-            this.pointerEnterAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
-                (<StandardMaterial>this._currentMaterial).emissiveColor = Color3.Red();
+        this.pointerUpAnimation = () => {
+            if (!this.mesh) {
+                return;
             }
 
-            this.pointerOutAnimation = () => {
-                (<StandardMaterial>this._currentMaterial).emissiveColor = Color3.Black();
-            }    
-
-            this.pointerDownAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
+            this.mesh.scaling.scaleInPlace(1.0 / 0.95);
+        }
+    }
 
-                this.mesh.scaling.scaleInPlace(0.95);
-            }
+    /**
+     * Gets or sets the GUI 2D content used to display the button's facade
+     */
+    public get content(): Control {
+        return this._content;
+    }
 
-            this.pointerUpAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
+    public set content(value: Control) {
+        this._content = value;
 
-                this.mesh.scaling.scaleInPlace(1.0 / 0.95);
-            }                     
+        if (!this._host || !this._host.utilityLayer) {
+            return;
         }
 
-        /**
-         * Gets or sets the GUI 2D content used to display the button's facade
-         */
-        public get content(): Control {
-            return this._content;
+        if (!this._facadeTexture) {
+            this._facadeTexture = new AdvancedDynamicTexture("Facade", this._contentResolution, this._contentResolution, this._host.utilityLayer.utilityLayerScene, true, Texture.TRILINEAR_SAMPLINGMODE);
+            this._facadeTexture.rootContainer.scaleX = this._contentScaleRatio;
+            this._facadeTexture.rootContainer.scaleY = this._contentScaleRatio;
+            this._facadeTexture.premulAlpha = true;
         }
 
-        public set content(value: Control) {
-            this._content = value;
+        this._facadeTexture.addControl(value);
 
-            if (!this._host || !this._host.utilityLayer) {
-                return;
-            }
+        this._applyFacade(this._facadeTexture);
+    }
 
-            if (!this._facadeTexture) {
-                this._facadeTexture = new BABYLON.GUI.AdvancedDynamicTexture("Facade", this._contentResolution, this._contentResolution, this._host.utilityLayer.utilityLayerScene, true, BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
-                this._facadeTexture.rootContainer.scaleX = this._contentScaleRatio;
-                this._facadeTexture.rootContainer.scaleY = this._contentScaleRatio;
-                this._facadeTexture.premulAlpha = true;
-            }
-            
-            this._facadeTexture.addControl(value);
+    /**
+     * Apply the facade texture (created from the content property).
+     * This function can be overloaded by child classes
+     * @param facadeTexture defines the AdvancedDynamicTexture to use
+     */
+    protected _applyFacade(facadeTexture: AdvancedDynamicTexture) {
+        (<any>this._currentMaterial).emissiveTexture = facadeTexture;
+    }
 
-            this._applyFacade(this._facadeTexture);
-        }
+    protected _getTypeName(): string {
+        return "Button3D";
+    }
 
-        /**
-         * Apply the facade texture (created from the content property).
-         * This function can be overloaded by child classes
-         * @param facadeTexture defines the AdvancedDynamicTexture to use
-         */
-        protected _applyFacade(facadeTexture: AdvancedDynamicTexture) {
-            (<any>this._currentMaterial).emissiveTexture = facadeTexture;
-        }
+    // Mesh association
+    protected _createNode(scene: Scene): TransformNode {
+        var faceUV = new Array(6);
 
-        protected _getTypeName(): string {
-            return "Button3D";
-        }        
+        for (var i = 0; i < 6; i++) {
+            faceUV[i] = new Vector4(0, 0, 0, 0);
+        }
+        faceUV[1] = new Vector4(0, 0, 1, 1);
 
-        // Mesh association
-        protected _createNode(scene: Scene): TransformNode {
-            var faceUV = new Array(6);
+        let mesh = MeshBuilder.CreateBox(this.name + "_rootMesh", {
+            width: 1.0,
+            height: 1.0,
+            depth: 0.08,
+            faceUV: faceUV
+        }, scene);
 
-            for (var i = 0; i < 6; i++) {
-                faceUV[i] = new BABYLON.Vector4(0, 0, 0, 0);
-            }
-            faceUV[1] = new BABYLON.Vector4(0, 0, 1, 1);
-
-            let mesh = MeshBuilder.CreateBox(this.name + "_rootMesh", {
-                width: 1.0, 
-                height: 1.0,
-                depth: 0.08,
-                faceUV: faceUV
-            }, scene); 
-           
-            return mesh;
-        }
+        return mesh;
+    }
 
-        protected _affectMaterial(mesh: AbstractMesh) {
-            let material = new StandardMaterial(this.name + "Material", mesh.getScene());
-            material.specularColor = Color3.Black();
+    protected _affectMaterial(mesh: AbstractMesh) {
+        let material = new StandardMaterial(this.name + "Material", mesh.getScene());
+        material.specularColor = Color3.Black();
 
-            mesh.material = material;
-            this._currentMaterial = material;
+        mesh.material = material;
+        this._currentMaterial = material;
 
-            this._resetContent();
-        }
+        this._resetContent();
+    }
 
-        /**
-         * Releases all associated resources
-         */
-        public dispose() {
-            super.dispose();
+    /**
+     * Releases all associated resources
+     */
+    public dispose() {
+        super.dispose();
 
-            this._disposeFacadeTexture();
+        this._disposeFacadeTexture();
 
-            if (this._currentMaterial) {
-                this._currentMaterial.dispose();
-            }
+        if (this._currentMaterial) {
+            this._currentMaterial.dispose();
         }
     }
 }

+ 121 - 122
gui/src/3D/controls/container3D.ts

@@ -1,161 +1,160 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Control3D } from "./control3D";
+import { Scene, Nullable, TransformNode } from "babylonjs";
+
+/**
+ * Class used to create containers for controls
+ */
+export class Container3D extends Control3D {
+    private _blockLayout = false;
 
-module BABYLON.GUI {
     /**
-     * Class used to create containers for controls
+     * Gets the list of child controls
      */
-    export class Container3D extends Control3D {
-        private _blockLayout = false;
-
-        /**
-         * Gets the list of child controls
-         */
-        protected _children = new Array<Control3D>();
-
-        /**
-         * Gets the list of child controls
-         */
-        public get children(): Array<Control3D> {
-            return this._children;
-        }
-
-        /**
-         * Gets or sets a boolean indicating if the layout must be blocked (default is false).
-         * This is helpful to optimize layout operation when adding multiple children in a row
-         */
-        public get blockLayout(): boolean {
-            return this._blockLayout;
-        }
+    protected _children = new Array<Control3D>();
 
-        public set blockLayout(value: boolean) {
-            if (this._blockLayout === value) {
-                return;
-            }
+    /**
+     * Gets the list of child controls
+     */
+    public get children(): Array<Control3D> {
+        return this._children;
+    }
 
-            this._blockLayout = value;
+    /**
+     * Gets or sets a boolean indicating if the layout must be blocked (default is false).
+     * This is helpful to optimize layout operation when adding multiple children in a row
+     */
+    public get blockLayout(): boolean {
+        return this._blockLayout;
+    }
 
-            if (!this._blockLayout) {
-                this._arrangeChildren();
-            }
+    public set blockLayout(value: boolean) {
+        if (this._blockLayout === value) {
+            return;
         }
 
-        /**
-         * Creates a new container
-         * @param name defines the container name
-         */
-        constructor(name?: string) {
-            super(name);
-        }
+        this._blockLayout = value;
 
-        /**
-         * Force the container to update the layout. Please note that it will not take blockLayout property in account
-         * @returns the current container
-         */
-        public updateLayout(): Container3D {
+        if (!this._blockLayout) {
             this._arrangeChildren();
-            return this;
         }
+    }
 
-        /**
-         * Gets a boolean indicating if the given control is in the children of this control
-         * @param control defines the control to check
-         * @returns true if the control is in the child list
-         */
-        public containsControl(control: Control3D): boolean {
-            return this._children.indexOf(control) !== -1;
-        }
+    /**
+     * Creates a new container
+     * @param name defines the container name
+     */
+    constructor(name?: string) {
+        super(name);
+    }
+
+    /**
+     * Force the container to update the layout. Please note that it will not take blockLayout property in account
+     * @returns the current container
+     */
+    public updateLayout(): Container3D {
+        this._arrangeChildren();
+        return this;
+    }
 
-        /**
-         * Adds a control to the children of this control
-         * @param control defines the control to add
-         * @returns the current container
-         */
-        public addControl(control: Control3D): Container3D {
-           var index = this._children.indexOf(control);
+    /**
+     * Gets a boolean indicating if the given control is in the children of this control
+     * @param control defines the control to check
+     * @returns true if the control is in the child list
+     */
+    public containsControl(control: Control3D): boolean {
+        return this._children.indexOf(control) !== -1;
+    }
 
-            if (index !== -1) {
-                return this;
-            }
-            control.parent = this;
-            control._host = this._host;
+    /**
+     * Adds a control to the children of this control
+     * @param control defines the control to add
+     * @returns the current container
+     */
+    public addControl(control: Control3D): Container3D {
+        var index = this._children.indexOf(control);
 
-            this._children.push(control);
+        if (index !== -1) {
+            return this;
+        }
+        control.parent = this;
+        control._host = this._host;
 
-            if (this._host.utilityLayer) {
-                control._prepareNode(this._host.utilityLayer.utilityLayerScene);
+        this._children.push(control);
 
-                if (control.node) {
-                    control.node.parent = this.node;
-                }
+        if (this._host.utilityLayer) {
+            control._prepareNode(this._host.utilityLayer.utilityLayerScene);
 
-                if (!this.blockLayout) {
-                    this._arrangeChildren();
-                }
+            if (control.node) {
+                control.node.parent = this.node;
             }
 
-            return this;
+            if (!this.blockLayout) {
+                this._arrangeChildren();
+            }
         }
 
+        return this;
+    }
 
-        /**
-         * This function will be called everytime a new control is added 
-         */
-        protected _arrangeChildren() {
-        }
 
-        protected _createNode(scene: Scene): Nullable<TransformNode> {
-            return new TransformNode("ContainerNode", scene);
-        }
+    /**
+     * This function will be called everytime a new control is added 
+     */
+    protected _arrangeChildren() {
+    }
 
-        /**
-         * Removes a control from the children of this control
-         * @param control defines the control to remove
-         * @returns the current container
-         */
-        public removeControl(control: Control3D): Container3D {
-            var index = this._children.indexOf(control);
+    protected _createNode(scene: Scene): Nullable<TransformNode> {
+        return new TransformNode("ContainerNode", scene);
+    }
 
-            if (index !== -1) {
-                this._children.splice(index, 1);
+    /**
+     * Removes a control from the children of this control
+     * @param control defines the control to remove
+     * @returns the current container
+     */
+    public removeControl(control: Control3D): Container3D {
+        var index = this._children.indexOf(control);
 
-                control.parent = null;
-                control._disposeNode();
-            }
+        if (index !== -1) {
+            this._children.splice(index, 1);
 
-            return this;
+            control.parent = null;
+            control._disposeNode();
         }
 
-        protected _getTypeName(): string {
-            return "Container3D";
-        }
-        
-        /**
-         * Releases all associated resources
-         */
-        public dispose() {
-            for (var control of this._children) {
-                control.dispose();
-            }
+        return this;
+    }
 
-            this._children = [];
+    protected _getTypeName(): string {
+        return "Container3D";
+    }
 
-            super.dispose();
+    /**
+     * Releases all associated resources
+     */
+    public dispose() {
+        for (var control of this._children) {
+            control.dispose();
         }
 
-        /** Control rotation will remain unchanged  */
-        public static readonly UNSET_ORIENTATION = 0;
+        this._children = [];
 
-        /** Control will rotate to make it look at sphere central axis */
-        public static readonly FACEORIGIN_ORIENTATION = 1;
+        super.dispose();
+    }
 
-        /** Control will rotate to make it look back at sphere central axis */
-        public static readonly FACEORIGINREVERSED_ORIENTATION = 2;
+    /** Control rotation will remain unchanged  */
+    public static readonly UNSET_ORIENTATION = 0;
 
-        /** Control will rotate to look at z axis (0, 0, 1) */
-        public static readonly FACEFORWARD_ORIENTATION = 3;
+    /** Control will rotate to make it look at sphere central axis */
+    public static readonly FACEORIGIN_ORIENTATION = 1;
 
-        /** Control will rotate to look at negative z axis (0, 0, -1) */
-        public static readonly FACEFORWARDREVERSED_ORIENTATION = 4;
+    /** Control will rotate to make it look back at sphere central axis */
+    public static readonly FACEORIGINREVERSED_ORIENTATION = 2;
 
-    }
-}
+    /** Control will rotate to look at z axis (0, 0, 1) */
+    public static readonly FACEFORWARD_ORIENTATION = 3;
+
+    /** Control will rotate to look at negative z axis (0, 0, -1) */
+    public static readonly FACEFORWARDREVERSED_ORIENTATION = 4;
+
+}

+ 346 - 345
gui/src/3D/controls/control3D.ts

@@ -1,424 +1,425 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { IDisposable, IBehaviorAware, Nullable, TransformNode, Vector3, Observable, Behavior, AbstractMesh, Scene, PointerEventTypes } from "babylonjs";
+import { GUI3DManager } from "../gui3DManager";
+import { Vector3WithInfo } from "../vector3WithInfo";
+import { Container3D } from "./container3D";
+
+/**
+ * Class used as base class for controls
+ */
+export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
+    /** @hidden */
+    public _host: GUI3DManager;
+    private _node: Nullable<TransformNode>;
+    private _downCount = 0;
+    private _enterCount = -1;
+    private _downPointerIds: { [id: number]: boolean } = {};
+    private _isVisible = true;
+
+    /** Gets or sets the control position  in world space */
+    public get position(): Vector3 {
+        if (!this._node) {
+            return Vector3.Zero();
+        }
 
-module BABYLON.GUI {
-    /**
-     * Class used as base class for controls
-     */
-    export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
-        /** @hidden */
-        public _host: GUI3DManager;
-        private _node: Nullable<TransformNode>;
-        private _downCount = 0;
-        private _enterCount = -1;
-        private _downPointerIds:{[id:number] : boolean} = {};
-        private _isVisible = true;
-    
-        /** Gets or sets the control position  in world space */
-        public get position(): Vector3 {
-            if (!this._node) {
-                return Vector3.Zero();
-            }
+        return this._node.position;
+    }
 
-            return this._node.position;
+    public set position(value: Vector3) {
+        if (!this._node) {
+            return;
         }
 
-        public set position(value: Vector3) {
-            if (!this._node) {
-                return;
-            }
+        this._node.position = value;;
+    }
 
-            this._node.position = value;;
+    /** Gets or sets the control scaling  in world space */
+    public get scaling(): Vector3 {
+        if (!this._node) {
+            return new Vector3(1, 1, 1);
         }
 
-        /** Gets or sets the control scaling  in world space */
-        public get scaling(): Vector3 {
-            if (!this._node) {
-                return new Vector3(1, 1, 1);
-            }
+        return this._node.scaling;
+    }
 
-            return this._node.scaling;
+    public set scaling(value: Vector3) {
+        if (!this._node) {
+            return;
         }
 
-        public set scaling(value: Vector3) {
-            if (!this._node) {
-                return;
-            }
+        this._node.scaling = value;;
+    }
 
-            this._node.scaling = value;;
-        }
+    /** Callback used to start pointer enter animation */
+    public pointerEnterAnimation: () => void;
+    /** Callback used to start pointer out animation */
+    public pointerOutAnimation: () => void;
+    /** Callback used to start pointer down animation */
+    public pointerDownAnimation: () => void;
+    /** Callback used to start pointer up animation */
+    public pointerUpAnimation: () => void;
 
-        /** Callback used to start pointer enter animation */
-        public pointerEnterAnimation: () => void;
-        /** Callback used to start pointer out animation */
-        public pointerOutAnimation: () => void;
-        /** Callback used to start pointer down animation */
-        public pointerDownAnimation: () => void;
-        /** Callback used to start pointer up animation */
-        public pointerUpAnimation: () => void;
-
-        /**
-        * An event triggered when the pointer move over the control
-        */
-        public onPointerMoveObservable = new Observable<Vector3>();
-
-        /**
-         * An event triggered when the pointer move out of the control
-         */
-        public onPointerOutObservable = new Observable<Control3D>();
-
-        /**
-         * An event triggered when the pointer taps the control
-         */
-        public onPointerDownObservable = new Observable<Vector3WithInfo>();
-
-        /**
-         * An event triggered when pointer is up
-         */
-        public onPointerUpObservable = new Observable<Vector3WithInfo>();
-
-        /**
-         * An event triggered when a control is clicked on (with a mouse)
-         */
-        public onPointerClickObservable = new Observable<Vector3WithInfo>();
-
-        /**
-         * An event triggered when pointer enters the control
-         */
-        public onPointerEnterObservable = new Observable<Control3D>();
-        
-        /**
-         * Gets or sets the parent container
-         */
-        public parent: Nullable<Container3D>;
+    /**
+    * An event triggered when the pointer move over the control
+    */
+    public onPointerMoveObservable = new Observable<Vector3>();
 
-        // Behaviors
-        private _behaviors = new Array<Behavior<Control3D>>();
-
-        /**
-         * Gets the list of attached behaviors
-         * @see http://doc.babylonjs.com/features/behaviour
-         */
-        public get behaviors(): Behavior<Control3D>[] {
-            return this._behaviors;
-        }        
-
-        /**
-         * Attach a behavior to the control
-         * @see http://doc.babylonjs.com/features/behaviour
-         * @param behavior defines the behavior to attach
-         * @returns the current control
-         */
-        public addBehavior(behavior: Behavior<Control3D>): Control3D {
-            var index = this._behaviors.indexOf(behavior);
-
-            if (index !== -1) {
-                return this;
-            }
+    /**
+     * An event triggered when the pointer move out of the control
+     */
+    public onPointerOutObservable = new Observable<Control3D>();
 
-            behavior.init();
-            let scene = this._host.scene;
-            if (scene.isLoading) {
-                // We defer the attach when the scene will be loaded
-                scene.onDataLoadedObservable.addOnce(() => {
-                    behavior.attach(this);
-                });
-            } else {
-                behavior.attach(this);
-            }
-            this._behaviors.push(behavior);
+    /**
+     * An event triggered when the pointer taps the control
+     */
+    public onPointerDownObservable = new Observable<Vector3WithInfo>();
+
+    /**
+     * An event triggered when pointer is up
+     */
+    public onPointerUpObservable = new Observable<Vector3WithInfo>();
+
+    /**
+     * An event triggered when a control is clicked on (with a mouse)
+     */
+    public onPointerClickObservable = new Observable<Vector3WithInfo>();
 
+    /**
+     * An event triggered when pointer enters the control
+     */
+    public onPointerEnterObservable = new Observable<Control3D>();
+
+    /**
+     * Gets or sets the parent container
+     */
+    public parent: Nullable<Container3D>;
+
+    // Behaviors
+    private _behaviors = new Array<Behavior<Control3D>>();
+
+    /**
+     * Gets the list of attached behaviors
+     * @see http://doc.babylonjs.com/features/behaviour
+     */
+    public get behaviors(): Behavior<Control3D>[] {
+        return this._behaviors;
+    }
+
+    /**
+     * Attach a behavior to the control
+     * @see http://doc.babylonjs.com/features/behaviour
+     * @param behavior defines the behavior to attach
+     * @returns the current control
+     */
+    public addBehavior(behavior: Behavior<Control3D>): Control3D {
+        var index = this._behaviors.indexOf(behavior);
+
+        if (index !== -1) {
             return this;
         }
 
-        /**
-         * Remove an attached behavior
-         * @see http://doc.babylonjs.com/features/behaviour
-         * @param behavior defines the behavior to attach
-         * @returns the current control
-         */
-        public removeBehavior(behavior: Behavior<Control3D>): Control3D {
-            var index = this._behaviors.indexOf(behavior);
-
-            if (index === -1) {
-                return this;
-            }
+        behavior.init();
+        let scene = this._host.scene;
+        if (scene.isLoading) {
+            // We defer the attach when the scene will be loaded
+            scene.onDataLoadedObservable.addOnce(() => {
+                behavior.attach(this);
+            });
+        } else {
+            behavior.attach(this);
+        }
+        this._behaviors.push(behavior);
 
-            this._behaviors[index].detach();
-            this._behaviors.splice(index, 1);
+        return this;
+    }
 
-            return this;
-        }        
-
-        /**
-         * Gets an attached behavior by name
-         * @param name defines the name of the behavior to look for
-         * @see http://doc.babylonjs.com/features/behaviour
-         * @returns null if behavior was not found else the requested behavior
-         */
-        public getBehaviorByName(name: string): Nullable<Behavior<Control3D>> {
-            for (var behavior of this._behaviors) {
-                if (behavior.name === name) {
-                    return behavior;
-                }
-            }
+    /**
+     * Remove an attached behavior
+     * @see http://doc.babylonjs.com/features/behaviour
+     * @param behavior defines the behavior to attach
+     * @returns the current control
+     */
+    public removeBehavior(behavior: Behavior<Control3D>): Control3D {
+        var index = this._behaviors.indexOf(behavior);
 
-            return null;
-        }      
-        
-        /** Gets or sets a boolean indicating if the control is visible */
-        public get isVisible(): boolean {
-            return this._isVisible;
+        if (index === -1) {
+            return this;
         }
 
-        public set isVisible(value: boolean) {
-            if (this._isVisible === value) {
-                return;
-            }
+        this._behaviors[index].detach();
+        this._behaviors.splice(index, 1);
 
-            this._isVisible = value;
+        return this;
+    }
 
-            let mesh = this.mesh;
-            if (mesh) {
-                mesh.setEnabled(value);
+    /**
+     * Gets an attached behavior by name
+     * @param name defines the name of the behavior to look for
+     * @see http://doc.babylonjs.com/features/behaviour
+     * @returns null if behavior was not found else the requested behavior
+     */
+    public getBehaviorByName(name: string): Nullable<Behavior<Control3D>> {
+        for (var behavior of this._behaviors) {
+            if (behavior.name === name) {
+                return behavior;
             }
         }
 
-        /**
-         * Creates a new control
-         * @param name defines the control name
-         */
-        constructor(
-            /** Defines the control name */
-            public name?: string) {
-        }
+        return null;
+    }
+
+    /** Gets or sets a boolean indicating if the control is visible */
+    public get isVisible(): boolean {
+        return this._isVisible;
+    }
 
-        /**
-         * Gets a string representing the class name
-         */
-        public get typeName(): string {
-            return this._getTypeName();
+    public set isVisible(value: boolean) {
+        if (this._isVisible === value) {
+            return;
         }
 
-        protected _getTypeName(): string {
-            return "Control3D";
+        this._isVisible = value;
+
+        let mesh = this.mesh;
+        if (mesh) {
+            mesh.setEnabled(value);
         }
+    }
+
+    /**
+     * Creates a new control
+     * @param name defines the control name
+     */
+    constructor(
+        /** Defines the control name */
+        public name?: string) {
+    }
+
+    /**
+     * Gets a string representing the class name
+     */
+    public get typeName(): string {
+        return this._getTypeName();
+    }
 
-        /**
-         * Gets the transform node used by this control
-         */
-        public get node(): Nullable<TransformNode> {
-            return this._node;
+    protected _getTypeName(): string {
+        return "Control3D";
+    }
+
+    /**
+     * Gets the transform node used by this control
+     */
+    public get node(): Nullable<TransformNode> {
+        return this._node;
+    }
+
+    /**
+     * Gets the mesh used to render this control
+     */
+    public get mesh(): Nullable<AbstractMesh> {
+        if (this._node instanceof AbstractMesh) {
+            return this._node as AbstractMesh;
         }
 
-        /**
-         * Gets the mesh used to render this control
-         */
-        public get mesh(): Nullable<AbstractMesh> {
-            if (this._node instanceof AbstractMesh) {
-                return this._node as AbstractMesh;
-            }
+        return null;
+    }
 
-            return null;
+    /**
+     * Link the control as child of the given node
+     * @param node defines the node to link to. Use null to unlink the control
+     * @returns the current control
+     */
+    public linkToTransformNode(node: Nullable<TransformNode>): Control3D {
+        if (this._node) {
+            this._node.parent = node;
         }
+        return this;
+    }
 
-        /**
-         * Link the control as child of the given node
-         * @param node defines the node to link to. Use null to unlink the control
-         * @returns the current control
-         */
-        public linkToTransformNode(node: Nullable<TransformNode>): Control3D {
-            if (this._node) {
-                this._node.parent = node;
+    /** @hidden **/
+    public _prepareNode(scene: Scene): void {
+        if (!this._node) {
+            this._node = this._createNode(scene);
+
+            if (!this.node) {
+                return;
             }
-            return this;
-        }    
-
-        /** @hidden **/      
-        public _prepareNode(scene: Scene): void{
-            if (!this._node) {
-                this._node = this._createNode(scene);
-
-                if (!this.node) {
-                    return;
-                }
-                this._node!.metadata = this; // Store the control on the metadata field in order to get it when picking
-                this._node!.position = this.position;
-                this._node!.scaling = this.scaling;
-
-                let mesh = this.mesh;
-                if (mesh) {
-                    mesh.isPickable = true;
-
-                    this._affectMaterial(mesh);
-                }
+            this._node!.metadata = this; // Store the control on the metadata field in order to get it when picking
+            this._node!.position = this.position;
+            this._node!.scaling = this.scaling;
+
+            let mesh = this.mesh;
+            if (mesh) {
+                mesh.isPickable = true;
+
+                this._affectMaterial(mesh);
             }
         }
+    }
+
+    /**
+     * Node creation.
+     * Can be overriden by children
+     * @param scene defines the scene where the node must be attached
+     * @returns the attached node or null if none. Must return a Mesh or AbstractMesh if there is an atttached visible object
+     */
+    protected _createNode(scene: Scene): Nullable<TransformNode> {
+        // Do nothing by default
+        return null;
+    }
+
+    /**
+     * Affect a material to the given mesh
+     * @param mesh defines the mesh which will represent the control
+     */
+    protected _affectMaterial(mesh: AbstractMesh) {
+        mesh.material = null;
+    }
+
+    // Pointers
 
-        /**
-         * Node creation.
-         * Can be overriden by children
-         * @param scene defines the scene where the node must be attached
-         * @returns the attached node or null if none. Must return a Mesh or AbstractMesh if there is an atttached visible object
-         */
-        protected _createNode(scene: Scene): Nullable<TransformNode> {
-            // Do nothing by default
-            return null;
+    /** @hidden */
+    public _onPointerMove(target: Control3D, coordinates: Vector3): void {
+        this.onPointerMoveObservable.notifyObservers(coordinates, -1, target, this);
+    }
+
+    /** @hidden */
+    public _onPointerEnter(target: Control3D): boolean {
+        if (this._enterCount > 0) {
+            return false;
         }
 
-        /**
-         * Affect a material to the given mesh
-         * @param mesh defines the mesh which will represent the control
-         */
-        protected _affectMaterial(mesh: AbstractMesh) {
-            mesh.material = null;
+        if (this._enterCount === -1) { // -1 is for touch input, we are now sure we are with a mouse or pencil
+            this._enterCount = 0;
         }
 
-        // Pointers
+        this._enterCount++;
 
-        /** @hidden */
-        public _onPointerMove(target: Control3D, coordinates: Vector3): void {
-            this.onPointerMoveObservable.notifyObservers(coordinates, -1, target, this);
-        }
+        this.onPointerEnterObservable.notifyObservers(this, -1, target, this);
 
-        /** @hidden */
-        public _onPointerEnter(target: Control3D): boolean {
-            if (this._enterCount > 0) {
-                return false;
-            }
+        if (this.pointerEnterAnimation) {
+            this.pointerEnterAnimation();
+        }
 
-            if (this._enterCount === -1) { // -1 is for touch input, we are now sure we are with a mouse or pencil
-                this._enterCount = 0;
-            }
+        return true;
+    }
 
-            this._enterCount++;
+    /** @hidden */
+    public _onPointerOut(target: Control3D): void {
+        this._enterCount = 0;
 
-            this.onPointerEnterObservable.notifyObservers(this, -1, target, this);
+        this.onPointerOutObservable.notifyObservers(this, -1, target, this);
 
-            if (this.pointerEnterAnimation) {
-                this.pointerEnterAnimation();
-            }
+        if (this.pointerOutAnimation) {
+            this.pointerOutAnimation();
+        }
+    }
 
-            return true;
+    /** @hidden */
+    public _onPointerDown(target: Control3D, coordinates: Vector3, pointerId: number, buttonIndex: number): boolean {
+        if (this._downCount !== 0) {
+            return false;
         }
 
-        /** @hidden */
-        public _onPointerOut(target: Control3D): void {
-            this._enterCount = 0;
+        this._downCount++;
 
-            this.onPointerOutObservable.notifyObservers(this, -1, target, this);
+        this._downPointerIds[pointerId] = true;
 
-            if (this.pointerOutAnimation) {
-                this.pointerOutAnimation();
-            }            
-        }
+        this.onPointerDownObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
 
-        /** @hidden */
-        public _onPointerDown(target: Control3D, coordinates: Vector3, pointerId:number, buttonIndex: number): boolean {
-            if (this._downCount !== 0) {
-                return false;
-            }
+        if (this.pointerDownAnimation) {
+            this.pointerDownAnimation();
+        }
 
-            this._downCount++;
+        return true;
+    }
 
-            this._downPointerIds[pointerId] = true;
+    /** @hidden */
+    public _onPointerUp(target: Control3D, coordinates: Vector3, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
+        this._downCount = 0;
 
-            this.onPointerDownObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
+        delete this._downPointerIds[pointerId];
 
-            if (this.pointerDownAnimation) {
-                this.pointerDownAnimation();
-            }                 
+        if (notifyClick && (this._enterCount > 0 || this._enterCount === -1)) {
+            this.onPointerClickObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
+        }
+        this.onPointerUpObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
 
-            return true;
+        if (this.pointerUpAnimation) {
+            this.pointerUpAnimation();
         }
+    }
 
-        /** @hidden */
-        public _onPointerUp(target: Control3D, coordinates: Vector3, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
-            this._downCount = 0;
-
-            delete this._downPointerIds[pointerId];
-
-			if (notifyClick && (this._enterCount > 0 || this._enterCount === -1)) {
-				this.onPointerClickObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
-			}
-			this.onPointerUpObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);            
-
-            if (this.pointerUpAnimation) {
-                this.pointerUpAnimation();
-            }          
-        }  
-
-        /** @hidden */
-        public forcePointerUp(pointerId: Nullable<number> = null) {
-            if(pointerId !== null){
-                this._onPointerUp(this, Vector3.Zero(), pointerId, 0, true);
-            }else{
-                for(var key in this._downPointerIds){
-                    this._onPointerUp(this, Vector3.Zero(), +key as number, 0, true);
-                }
+    /** @hidden */
+    public forcePointerUp(pointerId: Nullable<number> = null) {
+        if (pointerId !== null) {
+            this._onPointerUp(this, Vector3.Zero(), pointerId, 0, true);
+        } else {
+            for (var key in this._downPointerIds) {
+                this._onPointerUp(this, Vector3.Zero(), +key as number, 0, true);
             }
         }
-        
-        /** @hidden */
-        public _processObservables(type: number, pickedPoint: Vector3, pointerId:number, buttonIndex: number): boolean {
-            if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
-                this._onPointerMove(this, pickedPoint);
-
-                var previousControlOver = this._host._lastControlOver[pointerId];
-                if (previousControlOver && previousControlOver !== this) {
-                    previousControlOver._onPointerOut(this);
-                }
-
-                if (previousControlOver !== this) {
-                    this._onPointerEnter(this);
-                }
-
-                this._host._lastControlOver[pointerId] = this;
-                return true;
-            }
+    }
+
+    /** @hidden */
+    public _processObservables(type: number, pickedPoint: Vector3, pointerId: number, buttonIndex: number): boolean {
+        if (type === PointerEventTypes.POINTERMOVE) {
+            this._onPointerMove(this, pickedPoint);
 
-            if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
-                this._onPointerDown(this, pickedPoint, pointerId, buttonIndex);
-                this._host._lastControlDown[pointerId] = this;
-                this._host._lastPickedControl = this;
-                return true;
+            var previousControlOver = this._host._lastControlOver[pointerId];
+            if (previousControlOver && previousControlOver !== this) {
+                previousControlOver._onPointerOut(this);
             }
 
-            if (type === BABYLON.PointerEventTypes.POINTERUP) {
-                if (this._host._lastControlDown[pointerId]) {
-                    this._host._lastControlDown[pointerId]._onPointerUp(this, pickedPoint, pointerId, buttonIndex, true);
-                }
-                delete this._host._lastControlDown[pointerId];
-                return true;
+            if (previousControlOver !== this) {
+                this._onPointerEnter(this);
             }
 
-            return false;
-        }        
+            this._host._lastControlOver[pointerId] = this;
+            return true;
+        }
 
-        /** @hidden */
-        public _disposeNode(): void {
-            if (this._node) {
-                this._node.dispose();
-                this._node = null;
-            }
+        if (type === PointerEventTypes.POINTERDOWN) {
+            this._onPointerDown(this, pickedPoint, pointerId, buttonIndex);
+            this._host._lastControlDown[pointerId] = this;
+            this._host._lastPickedControl = this;
+            return true;
         }
 
-        /**
-         * Releases all associated resources
-         */
-        public dispose() {
-            this.onPointerDownObservable.clear();
-            this.onPointerEnterObservable.clear();
-            this.onPointerMoveObservable.clear();
-            this.onPointerOutObservable.clear();
-            this.onPointerUpObservable.clear();
-            this.onPointerClickObservable.clear();
-
-            this._disposeNode();
-
-            // Behaviors
-            for (var behavior of this._behaviors) {
-                behavior.detach();
+        if (type === PointerEventTypes.POINTERUP) {
+            if (this._host._lastControlDown[pointerId]) {
+                this._host._lastControlDown[pointerId]._onPointerUp(this, pickedPoint, pointerId, buttonIndex, true);
             }
+            delete this._host._lastControlDown[pointerId];
+            return true;
+        }
+
+        return false;
+    }
+
+    /** @hidden */
+    public _disposeNode(): void {
+        if (this._node) {
+            this._node.dispose();
+            this._node = null;
+        }
+    }
+
+    /**
+     * Releases all associated resources
+     */
+    public dispose() {
+        this.onPointerDownObservable.clear();
+        this.onPointerEnterObservable.clear();
+        this.onPointerMoveObservable.clear();
+        this.onPointerOutObservable.clear();
+        this.onPointerUpObservable.clear();
+        this.onPointerClickObservable.clear();
+
+        this._disposeNode();
+
+        // Behaviors
+        for (var behavior of this._behaviors) {
+            behavior.detach();
         }
     }
 }

+ 48 - 48
gui/src/3D/controls/cylinderPanel.ts

@@ -1,64 +1,64 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { VolumeBasedPanel } from "./volumeBasedPanel";
+import { float, Tools, Vector3, Matrix, Tmp } from "babylonjs";
+import { Control3D } from "./control3D";
+import { Container3D } from "./container3D";
+
+/**
+ * Class used to create a container panel deployed on the surface of a cylinder
+ */
+export class CylinderPanel extends VolumeBasedPanel {
+    private _radius = 5.0;
 
-module BABYLON.GUI {
     /**
-     * Class used to create a container panel deployed on the surface of a cylinder
+     * Gets or sets the radius of the cylinder where to project controls (5 by default)
      */
-    export class CylinderPanel extends VolumeBasedPanel {
-        private _radius = 5.0;
+    public get radius(): float {
+        return this._radius;
+    }
 
-        /**
-         * Gets or sets the radius of the cylinder where to project controls (5 by default)
-         */
-        public get radius(): float {
-            return this._radius;
+    public set radius(value: float) {
+        if (this._radius === value) {
+            return;
         }
 
-        public set radius(value: float) {
-            if (this._radius === value) {
-                return;
-            }
+        this._radius = value;
 
-            this._radius = value;
-
-            Tools.SetImmediate(() => {
-                this._arrangeChildren();               
-            });
-        }              
+        Tools.SetImmediate(() => {
+            this._arrangeChildren();
+        });
+    }
 
-        protected _mapGridNode(control: Control3D, nodePosition: Vector3) {            
-            let mesh = control.mesh;
+    protected _mapGridNode(control: Control3D, nodePosition: Vector3) {
+        let mesh = control.mesh;
 
-            if (!mesh) {
-                return;
-            }
-            let newPos = this._cylindricalMapping(nodePosition);
-            control.position = newPos;
+        if (!mesh) {
+            return;
+        }
+        let newPos = this._cylindricalMapping(nodePosition);
+        control.position = newPos;
 
-            switch (this.orientation) {
-                case Container3D.FACEORIGIN_ORIENTATION:
-                    mesh.lookAt(new BABYLON.Vector3(-newPos.x, newPos.y, -newPos.z));
-                    break;
-                case Container3D.FACEORIGINREVERSED_ORIENTATION:
-                    mesh.lookAt(new BABYLON.Vector3(2 * newPos.x, newPos.y, 2 * newPos.z));
-                    break;
-                case Container3D.FACEFORWARD_ORIENTATION:
-                    break;
-                case Container3D.FACEFORWARDREVERSED_ORIENTATION:
-                    mesh.rotate(BABYLON.Axis.Y, Math.PI, BABYLON.Space.LOCAL);
-                    break;
-            }            
+        switch (this.orientation) {
+            case Container3D.FACEORIGIN_ORIENTATION:
+                mesh.lookAt(new BABYLON.Vector3(-newPos.x, newPos.y, -newPos.z));
+                break;
+            case Container3D.FACEORIGINREVERSED_ORIENTATION:
+                mesh.lookAt(new BABYLON.Vector3(2 * newPos.x, newPos.y, 2 * newPos.z));
+                break;
+            case Container3D.FACEFORWARD_ORIENTATION:
+                break;
+            case Container3D.FACEFORWARDREVERSED_ORIENTATION:
+                mesh.rotate(BABYLON.Axis.Y, Math.PI, BABYLON.Space.LOCAL);
+                break;
         }
+    }
 
-        private _cylindricalMapping(source: Vector3)
-        {
-            let newPos = new Vector3(0, source.y, this._radius);
+    private _cylindricalMapping(source: Vector3) {
+        let newPos = new Vector3(0, source.y, this._radius);
 
-            let yAngle = (source.x / this._radius);
+        let yAngle = (source.x / this._radius);
 
-            Matrix.RotationYawPitchRollToRef(yAngle, 0, 0, Tmp.Matrix[0]);
+        Matrix.RotationYawPitchRollToRef(yAngle, 0, 0, Tmp.Matrix[0]);
 
-            return Vector3.TransformNormal(newPos, Tmp.Matrix[0]);
-        }
+        return Vector3.TransformNormal(newPos, Tmp.Matrix[0]);
     }
-}
+}

+ 210 - 206
gui/src/3D/controls/holographicButton.ts

@@ -1,243 +1,247 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Button3D } from "./button3D";
+import { Mesh, StandardMaterial, Nullable, Observer, Vector3, Scene, TransformNode, MeshBuilder, Color3 } from "babylonjs";
+import { FluentMaterial } from "../materials/fluentMaterial";
+import { StackPanel } from "../../2D/controls/stackPanel";
+import { Image } from "../../2D/controls/image";
+import { TextBlock } from "../../2D/controls/textBlock";
+import { AdvancedDynamicTexture } from "../../2D/advancedDynamicTexture";
+
+/**
+ * Class used to create a holographic button in 3D
+ */
+export class HolographicButton extends Button3D {
+    private _backPlate: Mesh;
+    private _textPlate: Mesh;
+    private _frontPlate: Mesh;
+    private _text: string;
+    private _imageUrl: string;
+    private _shareMaterials = true;
+    private _frontMaterial: FluentMaterial;
+    private _backMaterial: FluentMaterial;
+    private _plateMaterial: StandardMaterial;
+    private _pickedPointObserver: Nullable<Observer<Nullable<Vector3>>>;
 
-module BABYLON.GUI {
     /**
-     * Class used to create a holographic button in 3D
+     * Gets or sets text for the button
      */
-    export class HolographicButton extends Button3D {
-        private _backPlate: Mesh;
-        private _textPlate: Mesh;
-        private _frontPlate: Mesh;
-        private _text: string;
-        private _imageUrl: string;
-        private _shareMaterials = true;
-        private _frontMaterial: FluentMaterial;
-        private _backMaterial: FluentMaterial;
-        private _plateMaterial: StandardMaterial;
-        private _pickedPointObserver: Nullable<Observer<Nullable<Vector3>>>;
-
-        /**
-         * Gets or sets text for the button
-         */
-        public get text(): string {
-            return this._text;
+    public get text(): string {
+        return this._text;
+    }
+
+    public set text(value: string) {
+        if (this._text === value) {
+            return;
         }
 
-        public set text(value: string) {
-            if (this._text === value) {
-                return;
-            }
+        this._text = value;
+        this._rebuildContent();
+    }
 
-            this._text = value;
-            this._rebuildContent();
-        }
+    /**
+     * Gets or sets the image url for the button
+     */
+    public get imageUrl(): string {
+        return this._imageUrl;
+    }
 
-        /**
-         * Gets or sets the image url for the button
-         */
-        public get imageUrl(): string {
-            return this._imageUrl;
+    public set imageUrl(value: string) {
+        if (this._imageUrl === value) {
+            return;
         }
 
-        public set imageUrl(value: string) {
-            if (this._imageUrl === value) {
-                return;
-            }
+        this._imageUrl = value;
+        this._rebuildContent();
+    }
 
-            this._imageUrl = value;
-            this._rebuildContent();
-        }        
+    /**
+     * Gets the back material used by this button
+     */
+    public get backMaterial(): FluentMaterial {
+        return this._backMaterial;
+    }
 
-        /**
-         * Gets the back material used by this button
-         */
-        public get backMaterial(): FluentMaterial {
-            return this._backMaterial;
-        }
+    /**
+     * Gets the front material used by this button
+     */
+    public get frontMaterial(): FluentMaterial {
+        return this._frontMaterial;
+    }
 
-        /**
-         * Gets the front material used by this button
-         */
-        public get frontMaterial(): FluentMaterial {
-            return this._frontMaterial;
-        }       
-        
-        /**
-         * Gets the plate material used by this button
-         */
-        public get plateMaterial(): StandardMaterial {
-            return this._plateMaterial;
-        }          
-
-        /**
-         * Gets a boolean indicating if this button shares its material with other HolographicButtons
-         */
-        public get shareMaterials(): boolean {
-            return this._shareMaterials;
-        }
+    /**
+     * Gets the plate material used by this button
+     */
+    public get plateMaterial(): StandardMaterial {
+        return this._plateMaterial;
+    }
 
-        /**
-         * Creates a new button
-         * @param name defines the control name
-         */
-        constructor(name?: string, shareMaterials = true) {
-            super(name);
-
-            this._shareMaterials = shareMaterials;
-
-            // Default animations
-            this.pointerEnterAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
-                this._frontPlate.setEnabled(true);
-            }
+    /**
+     * Gets a boolean indicating if this button shares its material with other HolographicButtons
+     */
+    public get shareMaterials(): boolean {
+        return this._shareMaterials;
+    }
 
-            this.pointerOutAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
-                this._frontPlate.setEnabled(false);
-            }                      
-        }
-    
-        protected _getTypeName(): string {
-            return "HolographicButton";
-        }        
-
-        private _rebuildContent(): void {
-            this._disposeFacadeTexture();
-
-            let panel = new StackPanel();
-            panel.isVertical = true;
-
-            if (this._imageUrl) {
-                let image = new BABYLON.GUI.Image();
-                image.source = this._imageUrl;
-                image.paddingTop = "40px";
-                image.height = "180px";
-                image.width = "100px";
-                image.paddingBottom = "40px";
-                panel.addControl(image);                
-            }
+    /**
+     * Creates a new button
+     * @param name defines the control name
+     */
+    constructor(name?: string, shareMaterials = true) {
+        super(name);
 
-            if (this._text) {
-                let text = new BABYLON.GUI.TextBlock();
-                text.text = this._text;
-                text.color = "white";
-                text.height = "30px";
-                text.fontSize = 24;
-                panel.addControl(text);
-            }
+        this._shareMaterials = shareMaterials;
 
-            if (this._frontPlate) {
-                this.content = panel;
+        // Default animations
+        this.pointerEnterAnimation = () => {
+            if (!this.mesh) {
+                return;
             }
+            this._frontPlate.setEnabled(true);
         }
 
-        // Mesh association
-        protected _createNode(scene: Scene): TransformNode {
-            this._backPlate = MeshBuilder.CreateBox(this.name + "BackMesh", {
-                width: 1.0, 
-                height: 1.0,
-                depth: 0.08
-            }, scene); 
-
-            this._frontPlate = MeshBuilder.CreateBox(this.name + "FrontMesh", {
-                width: 1.0, 
-                height: 1.0,
-                depth: 0.08
-            }, scene); 
-
-            this._frontPlate.parent = this._backPlate;
-            this._frontPlate.position.z = -0.08;
-            this._frontPlate.isPickable = false;
+        this.pointerOutAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
             this._frontPlate.setEnabled(false);
+        }
+    }
+
+    protected _getTypeName(): string {
+        return "HolographicButton";
+    }
+
+    private _rebuildContent(): void {
+        this._disposeFacadeTexture();
+
+        let panel = new StackPanel();
+        panel.isVertical = true;
 
-            this._textPlate= <Mesh>super._createNode(scene);
-            this._textPlate.parent = this._backPlate;
-            this._textPlate.position.z = -0.08;
-            this._textPlate.isPickable = false;            
-           
-            return this._backPlate;
+        if (this._imageUrl) {
+            let image = new Image();
+            image.source = this._imageUrl;
+            image.paddingTop = "40px";
+            image.height = "180px";
+            image.width = "100px";
+            image.paddingBottom = "40px";
+            panel.addControl(image);
         }
 
-        protected _applyFacade(facadeTexture: AdvancedDynamicTexture) {
-            this._plateMaterial.emissiveTexture = facadeTexture;
-            this._plateMaterial.opacityTexture = facadeTexture;
-        }   
-        
-        private _createBackMaterial(mesh: Mesh) {
-            this._backMaterial = new FluentMaterial(this.name + "Back Material", mesh.getScene());
-            this._backMaterial.renderHoverLight = true;
-            this._pickedPointObserver = this._host.onPickedPointChangedObservable.add(pickedPoint => {
-                if (pickedPoint) {
-                    this._backMaterial.hoverPosition = pickedPoint;
-                    this._backMaterial.hoverColor.a = 1.0;
-                } else {
-                    this._backMaterial.hoverColor.a = 0;
-                }
-            });
+        if (this._text) {
+            let text = new TextBlock();
+            text.text = this._text;
+            text.color = "white";
+            text.height = "30px";
+            text.fontSize = 24;
+            panel.addControl(text);
         }
 
-        private _createFrontMaterial(mesh: Mesh) {
-            this._frontMaterial = new FluentMaterial(this.name + "Front Material", mesh.getScene());
-            this._frontMaterial.innerGlowColorIntensity = 0; // No inner glow
-            this._frontMaterial.alpha = 0.5; // Additive
-            this._frontMaterial.renderBorders = true;
-        }     
-        
-        private _createPlateMaterial(mesh: Mesh) {
-            this._plateMaterial = new StandardMaterial(this.name + "Plate Material", mesh.getScene());
-            this._plateMaterial.specularColor = Color3.Black();
+        if (this._frontPlate) {
+            this.content = panel;
         }
+    }
+
+    // Mesh association
+    protected _createNode(scene: Scene): TransformNode {
+        this._backPlate = MeshBuilder.CreateBox(this.name + "BackMesh", {
+            width: 1.0,
+            height: 1.0,
+            depth: 0.08
+        }, scene);
+
+        this._frontPlate = MeshBuilder.CreateBox(this.name + "FrontMesh", {
+            width: 1.0,
+            height: 1.0,
+            depth: 0.08
+        }, scene);
+
+        this._frontPlate.parent = this._backPlate;
+        this._frontPlate.position.z = -0.08;
+        this._frontPlate.isPickable = false;
+        this._frontPlate.setEnabled(false);
+
+        this._textPlate = <Mesh>super._createNode(scene);
+        this._textPlate.parent = this._backPlate;
+        this._textPlate.position.z = -0.08;
+        this._textPlate.isPickable = false;
+
+        return this._backPlate;
+    }
+
+    protected _applyFacade(facadeTexture: AdvancedDynamicTexture) {
+        this._plateMaterial.emissiveTexture = facadeTexture;
+        this._plateMaterial.opacityTexture = facadeTexture;
+    }
 
-        protected _affectMaterial(mesh: Mesh) {
-            // Back
-            if (this._shareMaterials) {
-                if (!this._host._sharedMaterials["backFluentMaterial"]) {
-                    this._createBackMaterial(mesh);
-                    this._host._sharedMaterials["backFluentMaterial"] =  this._backMaterial;
-                } else {
-                    this._backMaterial = this._host._sharedMaterials["backFluentMaterial"] as FluentMaterial;
-                }
-
-                // Front
-                if (!this._host._sharedMaterials["frontFluentMaterial"]) {
-                    this._createFrontMaterial(mesh);
-                    this._host._sharedMaterials["frontFluentMaterial"] = this._frontMaterial;                
-                } else {
-                    this._frontMaterial = this._host._sharedMaterials["frontFluentMaterial"] as FluentMaterial;
-                }  
+    private _createBackMaterial(mesh: Mesh) {
+        this._backMaterial = new FluentMaterial(this.name + "Back Material", mesh.getScene());
+        this._backMaterial.renderHoverLight = true;
+        this._pickedPointObserver = this._host.onPickedPointChangedObservable.add(pickedPoint => {
+            if (pickedPoint) {
+                this._backMaterial.hoverPosition = pickedPoint;
+                this._backMaterial.hoverColor.a = 1.0;
             } else {
+                this._backMaterial.hoverColor.a = 0;
+            }
+        });
+    }
+
+    private _createFrontMaterial(mesh: Mesh) {
+        this._frontMaterial = new FluentMaterial(this.name + "Front Material", mesh.getScene());
+        this._frontMaterial.innerGlowColorIntensity = 0; // No inner glow
+        this._frontMaterial.alpha = 0.5; // Additive
+        this._frontMaterial.renderBorders = true;
+    }
+
+    private _createPlateMaterial(mesh: Mesh) {
+        this._plateMaterial = new StandardMaterial(this.name + "Plate Material", mesh.getScene());
+        this._plateMaterial.specularColor = Color3.Black();
+    }
+
+    protected _affectMaterial(mesh: Mesh) {
+        // Back
+        if (this._shareMaterials) {
+            if (!this._host._sharedMaterials["backFluentMaterial"]) {
                 this._createBackMaterial(mesh);
+                this._host._sharedMaterials["backFluentMaterial"] = this._backMaterial;
+            } else {
+                this._backMaterial = this._host._sharedMaterials["backFluentMaterial"] as FluentMaterial;
+            }
+
+            // Front
+            if (!this._host._sharedMaterials["frontFluentMaterial"]) {
                 this._createFrontMaterial(mesh);
+                this._host._sharedMaterials["frontFluentMaterial"] = this._frontMaterial;
+            } else {
+                this._frontMaterial = this._host._sharedMaterials["frontFluentMaterial"] as FluentMaterial;
             }
+        } else {
+            this._createBackMaterial(mesh);
+            this._createFrontMaterial(mesh);
+        }
 
-            this._createPlateMaterial(mesh);
-            this._backPlate.material =  this._backMaterial;
-            this._frontPlate.material = this._frontMaterial;
-            this._textPlate.material = this._plateMaterial;
+        this._createPlateMaterial(mesh);
+        this._backPlate.material = this._backMaterial;
+        this._frontPlate.material = this._frontMaterial;
+        this._textPlate.material = this._plateMaterial;
 
-            this._rebuildContent();
-        }
+        this._rebuildContent();
+    }
+
+    /**
+     * Releases all associated resources
+     */
+    public dispose() {
+        super.dispose(); // will dispose main mesh ie. back plate
 
-        /**
-         * Releases all associated resources
-         */
-        public dispose() {
-            super.dispose(); // will dispose main mesh ie. back plate
-            
-            if (!this.shareMaterials) {
-                this._backMaterial.dispose();
-                this._frontMaterial.dispose();
-                this._plateMaterial.dispose();
-
-                if (this._pickedPointObserver) {
-                    this._host.onPickedPointChangedObservable.remove(this._pickedPointObserver);
-                    this._pickedPointObserver = null;
-                }
+        if (!this.shareMaterials) {
+            this._backMaterial.dispose();
+            this._frontMaterial.dispose();
+            this._plateMaterial.dispose();
+
+            if (this._pickedPointObserver) {
+                this._host.onPickedPointChangedObservable.remove(this._pickedPointObserver);
+                this._pickedPointObserver = null;
             }
-        }        
+        }
     }
 }

+ 12 - 0
gui/src/3D/controls/index.ts

@@ -0,0 +1,12 @@
+export * from "./abstractButton3D";
+export * from "./button3D";
+export * from "./container3D";
+export * from "./control3D";
+export * from "./cylinderPanel";
+export * from "./holographicButton";
+export * from "./meshButton3D";
+export * from "./planePanel";
+export * from "./scatterPanel";
+export * from "./spherePanel";
+export * from "./stackPanel3D";
+export * from "./volumeBasedPanel";

+ 50 - 51
gui/src/3D/controls/meshButton3D.ts

@@ -1,68 +1,67 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Scene, TransformNode, AbstractMesh, Mesh } from "babylonjs";
+import { Button3D } from "./button3D";
+
+/**
+ * Class used to create an interactable object. It's a 3D button using a mesh coming from the current scene
+ */
+export class MeshButton3D extends Button3D {
+    /** @hidden */
+    protected _currentMesh: Mesh;
 
-module BABYLON.GUI {
     /**
-     * Class used to create an interactable object. It's a 3D button using a mesh coming from the current scene
+     * Creates a new 3D button based on a mesh
+     * @param mesh mesh to become a 3D button
+     * @param name defines the control name
      */
-    export class MeshButton3D extends Button3D {
-        /** @hidden */
-        protected _currentMesh: Mesh;
+    constructor(mesh: Mesh, name?: string) {
+        super(name);
+        this._currentMesh = mesh;
 
         /**
-         * Creates a new 3D button based on a mesh
-         * @param mesh mesh to become a 3D button
-         * @param name defines the control name
+         * Provides a default behavior on hover/out & up/down
+         * Override those function to create your own desired behavior specific to your mesh
          */
-        constructor(mesh: Mesh, name?: string) {
-            super(name);
-            this._currentMesh = mesh; 
-
-            /**
-             * Provides a default behavior on hover/out & up/down
-             * Override those function to create your own desired behavior specific to your mesh
-             */
-            this.pointerEnterAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
-                this.mesh.scaling.scaleInPlace(1.1);
+        this.pointerEnterAnimation = () => {
+            if (!this.mesh) {
+                return;
             }
+            this.mesh.scaling.scaleInPlace(1.1);
+        }
 
-            this.pointerOutAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
-                this.mesh.scaling.scaleInPlace(1.0 / 1.1);
-            }    
+        this.pointerOutAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
+            this.mesh.scaling.scaleInPlace(1.0 / 1.1);
+        }
 
-            this.pointerDownAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
-                this.mesh.scaling.scaleInPlace(0.95);
+        this.pointerDownAnimation = () => {
+            if (!this.mesh) {
+                return;
             }
+            this.mesh.scaling.scaleInPlace(0.95);
+        }
 
-            this.pointerUpAnimation = () => {
-                if (!this.mesh) {
-                    return;
-                }
-                this.mesh.scaling.scaleInPlace(1.0 / 0.95);
-            }                     
+        this.pointerUpAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
+            this.mesh.scaling.scaleInPlace(1.0 / 0.95);
         }
+    }
 
-        protected _getTypeName(): string {
-            return "MeshButton3D";
-        }        
+    protected _getTypeName(): string {
+        return "MeshButton3D";
+    }
 
-        // Mesh association
-        protected _createNode(scene: Scene): TransformNode {
-            this._currentMesh.getChildMeshes().forEach((mesh)=>{
-                mesh.metadata = this;
-            });
-            return this._currentMesh;
-        }
+    // Mesh association
+    protected _createNode(scene: Scene): TransformNode {
+        this._currentMesh.getChildMeshes().forEach((mesh) => {
+            mesh.metadata = this;
+        });
+        return this._currentMesh;
+    }
 
-        protected _affectMaterial(mesh: AbstractMesh) {
-        }
+    protected _affectMaterial(mesh: AbstractMesh) {
     }
 }

+ 29 - 28
gui/src/3D/controls/planePanel.ts

@@ -1,35 +1,36 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Tmp, Vector3 } from "babylonjs";
+import { Container3D } from "./container3D";
+import { Control3D } from "./control3D";
+import { VolumeBasedPanel } from "./volumeBasedPanel";
 
-module BABYLON.GUI {
-    /**
-     * Class used to create a container panel deployed on the surface of a plane
-     */
-    export class PlanePanel extends VolumeBasedPanel {    
-        protected _mapGridNode(control: Control3D, nodePosition: Vector3) {            
-            let mesh = control.mesh;
+/**
+ * Class used to create a container panel deployed on the surface of a plane
+ */
+export class PlanePanel extends VolumeBasedPanel {
+    protected _mapGridNode(control: Control3D, nodePosition: Vector3) {
+        let mesh = control.mesh;
 
-            if (!mesh) {
-                return;
-            }
+        if (!mesh) {
+            return;
+        }
 
-            control.position = nodePosition.clone();
-            let target = Tmp.Vector3[0];
+        control.position = nodePosition.clone();
+        let target = Tmp.Vector3[0];
 
-            target.copyFrom(nodePosition);
+        target.copyFrom(nodePosition);
 
-            switch (this.orientation) {
-                case Container3D.FACEORIGIN_ORIENTATION:
-                case Container3D.FACEFORWARD_ORIENTATION:
-                    target.addInPlace(new BABYLON.Vector3(0, 0, -1));
-                    mesh.lookAt(target);
-                    break;
-                case Container3D.FACEFORWARDREVERSED_ORIENTATION:
-                case Container3D.FACEORIGINREVERSED_ORIENTATION:
-                    target.addInPlace(new BABYLON.Vector3(0, 0, 1));
-                    mesh.lookAt(target);
-                    break;
-            }
-            
+        switch (this.orientation) {
+            case Container3D.FACEORIGIN_ORIENTATION:
+            case Container3D.FACEFORWARD_ORIENTATION:
+                target.addInPlace(new BABYLON.Vector3(0, 0, -1));
+                mesh.lookAt(target);
+                break;
+            case Container3D.FACEFORWARDREVERSED_ORIENTATION:
+            case Container3D.FACEORIGINREVERSED_ORIENTATION:
+                target.addInPlace(new BABYLON.Vector3(0, 0, 1));
+                mesh.lookAt(target);
+                break;
         }
+
     }
-}
+}

+ 91 - 95
gui/src/3D/controls/scatterPanel.ts

@@ -1,117 +1,113 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { VolumeBasedPanel } from "./volumeBasedPanel";
+import { float, Tools, Vector3, Tmp } from "babylonjs";
+import { Control3D } from "./control3D";
+import { Container3D } from "./container3D";
+
+/**
+ * Class used to create a container panel where items get randomized planar mapping
+ */
+export class ScatterPanel extends VolumeBasedPanel {
+    private _iteration = 100.0;
 
-module BABYLON.GUI {
     /**
-     * Class used to create a container panel where items get randomized planar mapping
+     * Gets or sets the number of iteration to use to scatter the controls (100 by default)
      */
-    export class ScatterPanel extends VolumeBasedPanel {    
-        private _iteration = 100.0;
-
-        /**
-         * Gets or sets the number of iteration to use to scatter the controls (100 by default)
-         */
-        public get iteration(): float {
-            return this._iteration;
+    public get iteration(): float {
+        return this._iteration;
+    }
+
+    public set iteration(value: float) {
+        if (this._iteration === value) {
+            return;
         }
 
-        public set iteration(value: float) {
-            if (this._iteration === value) {
-                return;
-            }
+        this._iteration = value;
+
+        Tools.SetImmediate(() => {
+            this._arrangeChildren();
+        });
+    }
 
-            this._iteration = value;
+    protected _mapGridNode(control: Control3D, nodePosition: Vector3) {
+        let mesh = control.mesh;
+        let newPos = this._scatterMapping(nodePosition);
 
-            Tools.SetImmediate(() => {
-                this._arrangeChildren();               
-            });
-        }    
+        if (!mesh) {
+            return;
+        }
 
-        protected _mapGridNode(control: Control3D, nodePosition: Vector3) {            
-            let mesh = control.mesh;
-            let newPos = this._scatterMapping(nodePosition);
+        switch (this.orientation) {
+            case Container3D.FACEORIGIN_ORIENTATION:
+            case Container3D.FACEFORWARD_ORIENTATION:
+                mesh.lookAt(new Vector3(0, 0, -1));
+                break;
+            case Container3D.FACEFORWARDREVERSED_ORIENTATION:
+            case Container3D.FACEORIGINREVERSED_ORIENTATION:
+                mesh.lookAt(new Vector3(0, 0, 1));
+                break;
+        }
 
-            if (!mesh) {
-                return;
-            }
+        control.position = newPos;
+    }
+
+    private _scatterMapping(source: Vector3): Vector3 {
+        source.x = (1.0 - Math.random() * 2.0) * this._cellWidth;
+        source.y = (1.0 - Math.random() * 2.0) * this._cellHeight;
 
-            switch (this.orientation) {
-                case Container3D.FACEORIGIN_ORIENTATION:
-                case Container3D.FACEFORWARD_ORIENTATION:
-                    mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
-                    break;
-                case Container3D.FACEFORWARDREVERSED_ORIENTATION:
-                case Container3D.FACEORIGINREVERSED_ORIENTATION:
-                    mesh.lookAt(new BABYLON.Vector3(0, 0, 1));
-                    break;
+        return source;
+    }
+
+    protected _finalProcessing() {
+        var meshes = [];
+        for (var child of this._children) {
+            if (!child.mesh) {
+                continue;
             }
-            
-            control.position = newPos;
+
+            meshes.push(child.mesh);
         }
 
-        private _scatterMapping(source: Vector3): Vector3
-        {
-            source.x = (1.0 - Math.random() * 2.0) * this._cellWidth;
-            source.y = (1.0 - Math.random() * 2.0) * this._cellHeight;
-
-            return source;
-        }   
-        
-        protected _finalProcessing() {
-            var meshes = [];
-            for (var child of this._children) {
-                if (!child.mesh) {
-                    continue;
-                }                
-
-                meshes.push(child.mesh);
-            }
+        for (var count = 0; count < this._iteration; count++) {
+            meshes.sort((a, b) => {
+                let distance1 = a.position.lengthSquared();
+                let distance2 = b.position.lengthSquared();
 
-            for (var count = 0; count < this._iteration; count++) {
-                meshes.sort((a, b) => {
-                    let distance1 = a.position.lengthSquared();
-                    let distance2 = b.position.lengthSquared();
+                if (distance1 < distance2) {
+                    return 1;
+                } else if (distance1 > distance2) {
+                    return -1;
+                }
 
-                    if (distance1 < distance2) {
-                        return 1;
-                    } else if (distance1 > distance2) {
-                        return -1;
-                    }
+                return 0;
+            });
 
-                    return 0;
-                });
-
-                let radiusPaddingSquared = Math.pow(this.margin, 2.0);
-                let cellSize = Math.max(this._cellWidth, this._cellHeight);
-                let difference2D = Tmp.Vector2[0];
-                let difference = Tmp.Vector3[0];
-
-                for (let i = 0; i < meshes.length - 1; i++)
-                {
-                    for (let j = i + 1; j < meshes.length; j++)
-                    {
-                        if (i != j)
-                        {
-                            meshes[j].position.subtractToRef(meshes[i].position, difference);
-
-                            // Ignore Z axis
-                            difference2D.x = difference.x;
-                            difference2D.y = difference.y;
-                            let combinedRadius = cellSize;
-                            let distance = difference2D.lengthSquared()- radiusPaddingSquared;
-                            let minSeparation = Math.min(distance, radiusPaddingSquared);
-                            distance -= minSeparation;
-
-                            if (distance < (Math.pow(combinedRadius, 2.0)))
-                            {
-                                difference2D.normalize();
-                                difference.scaleInPlace((combinedRadius - Math.sqrt(distance)) * 0.5);
-                                meshes[j].position.addInPlace(difference);
-                                meshes[i].position.subtractInPlace(difference);
-                            }
+            let radiusPaddingSquared = Math.pow(this.margin, 2.0);
+            let cellSize = Math.max(this._cellWidth, this._cellHeight);
+            let difference2D = Tmp.Vector2[0];
+            let difference = Tmp.Vector3[0];
+
+            for (let i = 0; i < meshes.length - 1; i++) {
+                for (let j = i + 1; j < meshes.length; j++) {
+                    if (i != j) {
+                        meshes[j].position.subtractToRef(meshes[i].position, difference);
+
+                        // Ignore Z axis
+                        difference2D.x = difference.x;
+                        difference2D.y = difference.y;
+                        let combinedRadius = cellSize;
+                        let distance = difference2D.lengthSquared() - radiusPaddingSquared;
+                        let minSeparation = Math.min(distance, radiusPaddingSquared);
+                        distance -= minSeparation;
+
+                        if (distance < (Math.pow(combinedRadius, 2.0))) {
+                            difference2D.normalize();
+                            difference.scaleInPlace((combinedRadius - Math.sqrt(distance)) * 0.5);
+                            meshes[j].position.addInPlace(difference);
+                            meshes[i].position.subtractInPlace(difference);
                         }
                     }
                 }
-            }        
+            }
         }
     }
 }

+ 49 - 49
gui/src/3D/controls/spherePanel.ts

@@ -1,66 +1,66 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { VolumeBasedPanel } from "./volumeBasedPanel";
+import { float, Tools, Vector3, Matrix, Tmp } from "babylonjs";
+import { Control3D } from "./control3D";
+import { Container3D } from "./container3D";
+
+/**
+ * Class used to create a container panel deployed on the surface of a sphere
+ */
+export class SpherePanel extends VolumeBasedPanel {
+    private _radius = 5.0;
 
-module BABYLON.GUI {
     /**
-     * Class used to create a container panel deployed on the surface of a sphere
+     * Gets or sets the radius of the sphere where to project controls (5 by default)
      */
-    export class SpherePanel extends VolumeBasedPanel {
-        private _radius = 5.0;
+    public get radius(): float {
+        return this._radius;
+    }
 
-        /**
-         * Gets or sets the radius of the sphere where to project controls (5 by default)
-         */
-        public get radius(): float {
-            return this._radius;
+    public set radius(value: float) {
+        if (this._radius === value) {
+            return;
         }
 
-        public set radius(value: float) {
-            if (this._radius === value) {
-                return;
-            }
+        this._radius = value;
 
-            this._radius = value;
-
-            Tools.SetImmediate(() => {
-                this._arrangeChildren();               
-            });
-        }              
+        Tools.SetImmediate(() => {
+            this._arrangeChildren();
+        });
+    }
 
-        protected _mapGridNode(control: Control3D, nodePosition: Vector3) {            
-            let mesh = control.mesh;
+    protected _mapGridNode(control: Control3D, nodePosition: Vector3) {
+        let mesh = control.mesh;
 
-            if (!mesh) {
-                return;
-            }
+        if (!mesh) {
+            return;
+        }
 
-            let newPos = this._sphericalMapping(nodePosition);
-            control.position = newPos;
+        let newPos = this._sphericalMapping(nodePosition);
+        control.position = newPos;
 
-            switch (this.orientation) {
-                case Container3D.FACEORIGIN_ORIENTATION:
-                    mesh.lookAt(new BABYLON.Vector3(-newPos.x, -newPos.y, -newPos.z));
-                    break;
-                case Container3D.FACEORIGINREVERSED_ORIENTATION:
-                    mesh.lookAt(new BABYLON.Vector3(2 * newPos.x, 2 * newPos.y, 2 * newPos.z));
-                    break;
-                case Container3D.FACEFORWARD_ORIENTATION:
-                    break;
-                case Container3D.FACEFORWARDREVERSED_ORIENTATION:
-                    mesh.rotate(BABYLON.Axis.Y, Math.PI, BABYLON.Space.LOCAL);
-                    break;
-            }           
+        switch (this.orientation) {
+            case Container3D.FACEORIGIN_ORIENTATION:
+                mesh.lookAt(new BABYLON.Vector3(-newPos.x, -newPos.y, -newPos.z));
+                break;
+            case Container3D.FACEORIGINREVERSED_ORIENTATION:
+                mesh.lookAt(new BABYLON.Vector3(2 * newPos.x, 2 * newPos.y, 2 * newPos.z));
+                break;
+            case Container3D.FACEFORWARD_ORIENTATION:
+                break;
+            case Container3D.FACEFORWARDREVERSED_ORIENTATION:
+                mesh.rotate(BABYLON.Axis.Y, Math.PI, BABYLON.Space.LOCAL);
+                break;
         }
+    }
 
-        private _sphericalMapping(source: Vector3)
-        {
-            let newPos = new Vector3(0, 0, this._radius);
+    private _sphericalMapping(source: Vector3) {
+        let newPos = new Vector3(0, 0, this._radius);
 
-            let xAngle = (source.y / this._radius);
-            let yAngle = -(source.x / this._radius);
+        let xAngle = (source.y / this._radius);
+        let yAngle = -(source.x / this._radius);
 
-            Matrix.RotationYawPitchRollToRef(yAngle, xAngle, 0, Tmp.Matrix[0]);
+        Matrix.RotationYawPitchRollToRef(yAngle, xAngle, 0, Tmp.Matrix[0]);
 
-            return Vector3.TransformNormal(newPos, Tmp.Matrix[0]);
-        }
+        return Vector3.TransformNormal(newPos, Tmp.Matrix[0]);
     }
-}
+}

+ 87 - 88
gui/src/3D/controls/stackPanel3D.ts

@@ -1,109 +1,108 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Container3D } from "./container3D";
+import { Tools, Matrix, Tmp, Vector3 } from "babylonjs";
+
+/**
+ * Class used to create a stack panel in 3D on XY plane
+ */
+export class StackPanel3D extends Container3D {
+    private _isVertical = false;
 
-module BABYLON.GUI {
     /**
-     * Class used to create a stack panel in 3D on XY plane
+     * Gets or sets a boolean indicating if the stack panel is vertical or horizontal (horizontal by default)
      */
-    export class StackPanel3D extends Container3D {
-        private _isVertical = false;
-
-        /**
-         * Gets or sets a boolean indicating if the stack panel is vertical or horizontal (horizontal by default)
-         */
-        public get isVertical(): boolean {
-            return this._isVertical;
+    public get isVertical(): boolean {
+        return this._isVertical;
+    }
+
+    public set isVertical(value: boolean) {
+        if (this._isVertical === value) {
+            return;
         }
 
-        public set isVertical(value: boolean) {
-            if (this._isVertical === value) {
-                return;
-            }
+        this._isVertical = value;
 
-            this._isVertical = value;
+        Tools.SetImmediate(() => {
+            this._arrangeChildren();
+        });
+    }
 
-            Tools.SetImmediate(() => {
-                this._arrangeChildren();               
-            });
-        }
+    /**
+     * Gets or sets the distance between elements
+     */
+    public margin = 0.1;
 
-        /**
-         * Gets or sets the distance between elements
-         */
-        public margin = 0.1;
-        
-        /**
-         * Creates new StackPanel
-         * @param isVertical 
-         */
-        public constructor(isVertical = false) {
-            super();
-
-            this._isVertical = isVertical;
-        }
+    /**
+     * Creates new StackPanel
+     * @param isVertical 
+     */
+    public constructor(isVertical = false) {
+        super();
+
+        this._isVertical = isVertical;
+    }
 
-        protected _arrangeChildren() {
-            let width = 0;
-            let height = 0;
-            let controlCount = 0;
-            let extendSizes = [];
-
-            let currentInverseWorld = Matrix.Invert(this.node!.computeWorldMatrix(true));
-
-            // Measure
-            for (var child of this._children) {
-                if (!child.mesh) {
-                    continue;
-                }
-
-                controlCount++;
-                child.mesh.computeWorldMatrix(true);
-                child.mesh.getWorldMatrix().multiplyToRef(currentInverseWorld, Tmp.Matrix[0]);
-
-                let boundingBox = child.mesh.getBoundingInfo().boundingBox;
-                let extendSize = Vector3.TransformNormal(boundingBox.extendSize, Tmp.Matrix[0]);
-                extendSizes.push(extendSize);
-
-                if (this._isVertical) {
-                    height += extendSize.y;
-                } else {
-                    width += extendSize.x;
-                }
+    protected _arrangeChildren() {
+        let width = 0;
+        let height = 0;
+        let controlCount = 0;
+        let extendSizes = [];
+
+        let currentInverseWorld = Matrix.Invert(this.node!.computeWorldMatrix(true));
+
+        // Measure
+        for (var child of this._children) {
+            if (!child.mesh) {
+                continue;
             }
 
+            controlCount++;
+            child.mesh.computeWorldMatrix(true);
+            child.mesh.getWorldMatrix().multiplyToRef(currentInverseWorld, Tmp.Matrix[0]);
+
+            let boundingBox = child.mesh.getBoundingInfo().boundingBox;
+            let extendSize = Vector3.TransformNormal(boundingBox.extendSize, Tmp.Matrix[0]);
+            extendSizes.push(extendSize);
+
             if (this._isVertical) {
-                height += (controlCount - 1) * this.margin / 2;
+                height += extendSize.y;
             } else {
-                width += (controlCount - 1) * this.margin / 2;
+                width += extendSize.x;
+            }
+        }
+
+        if (this._isVertical) {
+            height += (controlCount - 1) * this.margin / 2;
+        } else {
+            width += (controlCount - 1) * this.margin / 2;
+        }
+
+        // Arrange
+        let offset: number;
+        if (this._isVertical) {
+            offset = -height;
+        } else {
+            offset = -width;
+        }
+
+        let index = 0;
+        for (var child of this._children) {
+            if (!child.mesh) {
+                continue;
             }
+            controlCount--;
+            let extendSize = extendSizes[index++];
 
-            // Arrange
-            let offset: number;
             if (this._isVertical) {
-                offset = -height;
+                child.position.y = offset + extendSize.y;
+                child.position.x = 0;
+                offset += extendSize.y * 2;
             } else {
-                offset = -width;
+                child.position.x = offset + extendSize.x;
+                child.position.y = 0;
+                offset += extendSize.x * 2;
             }
 
-            let index = 0;
-            for (var child of this._children) {
-                if (!child.mesh) {
-                    continue;
-                }                
-                controlCount--;
-                let extendSize = extendSizes[index++];
-
-                if (this._isVertical) {
-                    child.position.y = offset + extendSize.y;
-                    child.position.x = 0;
-                    offset += extendSize.y * 2;
-                } else {
-                    child.position.x = offset + extendSize.x;
-                    child.position.y = 0;
-                    offset += extendSize.x * 2;
-                }
-
-                offset += (controlCount > 0 ? this.margin : 0)
-            }
+            offset += (controlCount > 0 ? this.margin : 0)
         }
     }
-}
+}

+ 155 - 161
gui/src/3D/controls/volumeBasedPanel.ts

@@ -1,197 +1,191 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+import { Container3D } from "./container3D";
+import { Tools, int, Matrix, Tmp, Vector3 } from "babylonjs";
+import { Control3D } from "./control3D";
+
+/**
+ * Abstract class used to create a container panel deployed on the surface of a volume
+ */
+export abstract class VolumeBasedPanel extends Container3D {
+    private _columns = 10;
+    private _rows = 0;
+    private _rowThenColum = true;
+
+    private _orientation = Container3D.FACEORIGIN_ORIENTATION;
+
+    protected _cellWidth: number;
+    protected _cellHeight: number;
+
+    /**
+     * Gets or sets the distance between elements
+     */
+    public margin = 0;
 
-module BABYLON.GUI {
     /**
-     * Abstract class used to create a container panel deployed on the surface of a volume
+     * Gets or sets the orientation to apply to all controls (BABYLON.Container3D.FaceOriginReversedOrientation by default)
+    * | Value | Type                                | Description |
+    * | ----- | ----------------------------------- | ----------- |
+    * | 0     | UNSET_ORIENTATION                   |  Control rotation will remain unchanged |
+    * | 1     | FACEORIGIN_ORIENTATION              |  Control will rotate to make it look at sphere central axis |
+    * | 2     | FACEORIGINREVERSED_ORIENTATION      |  Control will rotate to make it look back at sphere central axis |
+    * | 3     | FACEFORWARD_ORIENTATION             |  Control will rotate to look at z axis (0, 0, 1) |
+    * | 4     | FACEFORWARDREVERSED_ORIENTATION     |  Control will rotate to look at negative z axis (0, 0, -1) |
      */
-    export abstract class VolumeBasedPanel extends Container3D {
-        private _columns = 10;
-        private _rows = 0;
-        private _rowThenColum = true;
-        
-        private _orientation = Container3D.FACEORIGIN_ORIENTATION;
-
-        protected _cellWidth: number;
-        protected _cellHeight: number;
-
-        /**
-         * Gets or sets the distance between elements
-         */
-        public margin = 0;        
-
-        /**
-         * Gets or sets the orientation to apply to all controls (BABYLON.Container3D.FaceOriginReversedOrientation by default)
-        * | Value | Type                                | Description |
-        * | ----- | ----------------------------------- | ----------- |
-        * | 0     | UNSET_ORIENTATION                   |  Control rotation will remain unchanged |
-        * | 1     | FACEORIGIN_ORIENTATION              |  Control will rotate to make it look at sphere central axis |
-        * | 2     | FACEORIGINREVERSED_ORIENTATION      |  Control will rotate to make it look back at sphere central axis |
-        * | 3     | FACEFORWARD_ORIENTATION             |  Control will rotate to look at z axis (0, 0, 1) |
-        * | 4     | FACEFORWARDREVERSED_ORIENTATION     |  Control will rotate to look at negative z axis (0, 0, -1) |
-         */
-        public get orientation(): number {
-            return this._orientation;
+    public get orientation(): number {
+        return this._orientation;
+    }
+
+    public set orientation(value: number) {
+        if (this._orientation === value) {
+            return;
         }
 
-        public set orientation(value: number) {
-            if (this._orientation === value) {
-                return;
-            }
+        this._orientation = value;
 
-            this._orientation = value;
+        Tools.SetImmediate(() => {
+            this._arrangeChildren();
+        });
+    }
 
-            Tools.SetImmediate(() => {
-                this._arrangeChildren();               
-            });
-        }             
+    /**
+     * Gets or sets the number of columns requested (10 by default). 
+     * The panel will automatically compute the number of rows based on number of child controls. 
+     */
+    public get columns(): int {
+        return this._columns;
+    }
 
-        /**
-         * Gets or sets the number of columns requested (10 by default). 
-         * The panel will automatically compute the number of rows based on number of child controls. 
-         */
-        public get columns(): int {
-            return this._columns;
+    public set columns(value: int) {
+        if (this._columns === value) {
+            return;
         }
 
-        public set columns(value: int) {
-            if (this._columns === value) {
-                return;
-            }
+        this._columns = value;
+        this._rowThenColum = true;
 
-            this._columns = value;
-            this._rowThenColum = true;
-
-            Tools.SetImmediate(() => {
-                this._arrangeChildren();               
-            });
-        }     
-        
-        /**
-         * Gets or sets a the number of rows requested. 
-         * The panel will automatically compute the number of columns based on number of child controls. 
-         */
-        public get rows(): int {
-            return this._rows;
-        }
+        Tools.SetImmediate(() => {
+            this._arrangeChildren();
+        });
+    }
 
-        public set rows(value: int) {
-            if (this._rows === value) {
-                return;
-            }
+    /**
+     * Gets or sets a the number of rows requested. 
+     * The panel will automatically compute the number of columns based on number of child controls. 
+     */
+    public get rows(): int {
+        return this._rows;
+    }
 
-            this._rows = value;
-            this._rowThenColum = false;
-
-            Tools.SetImmediate(() => {
-                this._arrangeChildren();               
-            });
-        }           
-
-        /**
-         * Creates new VolumeBasedPanel
-         */
-        public constructor() {
-            super();
-        }        
-
-        protected _arrangeChildren() {
-            this._cellWidth = 0;
-            this._cellHeight = 0;
-            let rows = 0;
-            let columns = 0;
-            let controlCount = 0;
-
-            let currentInverseWorld = Matrix.Invert(this.node!.computeWorldMatrix(true));
-
-            // Measure
-            for (var child of this._children) {
-                if (!child.mesh) {
-                    continue;
-                }
+    public set rows(value: int) {
+        if (this._rows === value) {
+            return;
+        }
 
-                controlCount++;
-                child.mesh.computeWorldMatrix(true);
-             //   child.mesh.getWorldMatrix().multiplyToRef(currentInverseWorld, Tmp.Matrix[0]);
+        this._rows = value;
+        this._rowThenColum = false;
 
-                let boundingBox = child.mesh.getHierarchyBoundingVectors();
-                let extendSize = Tmp.Vector3[0];
-                let diff = Tmp.Vector3[1];
+        Tools.SetImmediate(() => {
+            this._arrangeChildren();
+        });
+    }
 
-                boundingBox.max.subtractToRef(boundingBox.min, diff);
+    /**
+     * Creates new VolumeBasedPanel
+     */
+    public constructor() {
+        super();
+    }
 
-                diff.scaleInPlace(0.5);
+    protected _arrangeChildren() {
+        this._cellWidth = 0;
+        this._cellHeight = 0;
+        let rows = 0;
+        let columns = 0;
+        let controlCount = 0;
 
-                Vector3.TransformNormalToRef(diff, currentInverseWorld, extendSize);
+        let currentInverseWorld = Matrix.Invert(this.node!.computeWorldMatrix(true));
 
-                this._cellWidth = Math.max(this._cellWidth, extendSize.x * 2);
-                this._cellHeight = Math.max(this._cellHeight, extendSize.y * 2);
+        // Measure
+        for (var child of this._children) {
+            if (!child.mesh) {
+                continue;
             }
 
-            this._cellWidth += this.margin * 2;
-            this._cellHeight += this.margin * 2;
+            controlCount++;
+            child.mesh.computeWorldMatrix(true);
+            //   child.mesh.getWorldMatrix().multiplyToRef(currentInverseWorld, Tmp.Matrix[0]);
 
-            // Arrange
-            if (this._rowThenColum) {
-                columns = this._columns;
-                rows = Math.ceil(controlCount / this._columns);
-            } else {
-                rows = this._rows;
-                columns = Math.ceil(controlCount / this._rows);
-            }
+            let boundingBox = child.mesh.getHierarchyBoundingVectors();
+            let extendSize = Tmp.Vector3[0];
+            let diff = Tmp.Vector3[1];
+
+            boundingBox.max.subtractToRef(boundingBox.min, diff);
+
+            diff.scaleInPlace(0.5);
+
+            Vector3.TransformNormalToRef(diff, currentInverseWorld, extendSize);
+
+            this._cellWidth = Math.max(this._cellWidth, extendSize.x * 2);
+            this._cellHeight = Math.max(this._cellHeight, extendSize.y * 2);
+        }
+
+        this._cellWidth += this.margin * 2;
+        this._cellHeight += this.margin * 2;
 
-            let startOffsetX = (columns * 0.5) * this._cellWidth;
-            let startOffsetY = (rows * 0.5) * this._cellHeight;
-            let nodeGrid = [];
-            let cellCounter = 0;
-
-            if (this._rowThenColum) {
-                for (var r = 0; r < rows; r++)
-                {
-                    for (var c = 0; c < columns; c++)
-                    {
-                        nodeGrid.push(new Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
-                        cellCounter++;
-                        if (cellCounter > controlCount)
-                        {
-                            break;
-                        }
+        // Arrange
+        if (this._rowThenColum) {
+            columns = this._columns;
+            rows = Math.ceil(controlCount / this._columns);
+        } else {
+            rows = this._rows;
+            columns = Math.ceil(controlCount / this._rows);
+        }
+
+        let startOffsetX = (columns * 0.5) * this._cellWidth;
+        let startOffsetY = (rows * 0.5) * this._cellHeight;
+        let nodeGrid = [];
+        let cellCounter = 0;
+
+        if (this._rowThenColum) {
+            for (var r = 0; r < rows; r++) {
+                for (var c = 0; c < columns; c++) {
+                    nodeGrid.push(new Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
+                    cellCounter++;
+                    if (cellCounter > controlCount) {
+                        break;
                     }
                 }
-            } else {
-                for (var c = 0; c < columns; c++)
-                {
-                    for (var r = 0; r < rows; r++)
-                    {
-                        nodeGrid.push(new Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
-                        cellCounter++;
-                        if (cellCounter > controlCount)
-                        {
-                            break;
-                        }
+            }
+        } else {
+            for (var c = 0; c < columns; c++) {
+                for (var r = 0; r < rows; r++) {
+                    nodeGrid.push(new Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
+                    cellCounter++;
+                    if (cellCounter > controlCount) {
+                        break;
                     }
                 }
             }
+        }
 
-            cellCounter = 0;
-            for (var child of this._children) {
-                if (!child.mesh) {
-                    continue;
-                }                
-
-                this._mapGridNode(child, nodeGrid[cellCounter]);
-
-                cellCounter++;
+        cellCounter = 0;
+        for (var child of this._children) {
+            if (!child.mesh) {
+                continue;
             }
 
-            this._finalProcessing();
+            this._mapGridNode(child, nodeGrid[cellCounter]);
+
+            cellCounter++;
         }
 
-        /** Child classes must implement this function to provide correct control positioning */
-        protected abstract _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+        this._finalProcessing();
+    }
 
-        /** Child classes can implement this function to provide additional processing */
-        protected _finalProcessing() {
+    /** Child classes must implement this function to provide correct control positioning */
+    protected abstract _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+
+    /** Child classes can implement this function to provide additional processing */
+    protected _finalProcessing() {
 
-        }
     }
-}
+}

+ 180 - 181
gui/src/3D/gui3DManager.ts

@@ -1,222 +1,221 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+import { IDisposable, Scene, Nullable, Observer, UtilityLayerRenderer, PointerInfo, Observable, Vector3, Material, AbstractMesh, Engine, HemisphericLight, PointerEventTypes } from "babylonjs";
+import { Container3D } from "./controls/container3D";
+import { Control3D } from "./controls/control3D";
+
+/**
+ * Class used to manage 3D user interface
+ * @see http://doc.babylonjs.com/how_to/gui3d
+ */
+export class GUI3DManager implements IDisposable {
+    private _scene: Scene;
+    private _sceneDisposeObserver: Nullable<Observer<Scene>>;
+    private _utilityLayer: Nullable<UtilityLayerRenderer>;
+    private _rootContainer: Container3D;
+    private _pointerObserver: Nullable<Observer<PointerInfo>>;
+    private _pointerOutObserver: Nullable<Observer<number>>;
+    /** @hidden */
+    public _lastPickedControl: Control3D;
+    /** @hidden */
+    public _lastControlOver: { [pointerId: number]: Control3D } = {};
+    /** @hidden */
+    public _lastControlDown: { [pointerId: number]: Control3D } = {};
 
+    /**
+     * Observable raised when the point picked by the pointer events changed
+     */
+    public onPickedPointChangedObservable = new Observable<Nullable<Vector3>>();
+
+    // Shared resources
+    /** @hidden */
+    public _sharedMaterials: { [key: string]: Material } = {};
+
+    /** Gets the hosting scene */
+    public get scene(): Scene {
+        return this._scene;
+    }
+
+    /** Gets associated utility layer */
+    public get utilityLayer(): Nullable<UtilityLayerRenderer> {
+        return this._utilityLayer;
+    }
 
-module BABYLON.GUI {
     /**
-     * Class used to manage 3D user interface
-     * @see http://doc.babylonjs.com/how_to/gui3d
+     * Creates a new GUI3DManager
+     * @param scene 
      */
-    export class GUI3DManager implements BABYLON.IDisposable {
-        private _scene: Scene;
-        private _sceneDisposeObserver: Nullable<Observer<Scene>>;
-        private _utilityLayer: Nullable<UtilityLayerRenderer>;
-        private _rootContainer: Container3D;
-        private _pointerObserver: Nullable<Observer<PointerInfo>>;
-        private _pointerOutObserver: Nullable<Observer<number>>;
-        /** @hidden */
-        public _lastPickedControl: Control3D;
-        /** @hidden */
-        public _lastControlOver: {[pointerId:number]: Control3D} = {};
-        /** @hidden */
-        public _lastControlDown: {[pointerId:number]: Control3D} = {};      
-
-        /**
-         * Observable raised when the point picked by the pointer events changed
-         */
-        public onPickedPointChangedObservable = new Observable<Nullable<Vector3>>();
-
-        // Shared resources
-        /** @hidden */
-        public _sharedMaterials: {[key:string]: Material} = {};     
-
-        /** Gets the hosting scene */
-        public get scene(): Scene {
-            return this._scene;
+    public constructor(scene?: Scene) {
+        this._scene = scene || Engine.LastCreatedScene!;
+        this._sceneDisposeObserver = this._scene.onDisposeObservable.add(() => {
+            this._sceneDisposeObserver = null;
+            this._utilityLayer = null;
+            this.dispose();
+        })
+
+        this._utilityLayer = new UtilityLayerRenderer(this._scene);
+        this._utilityLayer.onlyCheckPointerDownEvents = false;
+        this._utilityLayer.mainSceneTrackerPredicate = (mesh: Nullable<AbstractMesh>) => {
+            return mesh && mesh.metadata && mesh.metadata._node;
         }
 
-        /** Gets associated utility layer */
-        public get utilityLayer(): Nullable<UtilityLayerRenderer> {
-            return this._utilityLayer;
-        }
+        // Root
+        this._rootContainer = new Container3D("RootContainer");
+        this._rootContainer._host = this;
+        let utilityLayerScene = this._utilityLayer.utilityLayerScene;
 
-        /**
-         * Creates a new GUI3DManager
-         * @param scene 
-         */
-        public constructor(scene?: Scene) {
-            this._scene = scene || Engine.LastCreatedScene!;
-            this._sceneDisposeObserver = this._scene.onDisposeObservable.add(() => {
-                this._sceneDisposeObserver = null;
-                this._utilityLayer = null;
-                this.dispose();
-            })
-
-            this._utilityLayer = new UtilityLayerRenderer(this._scene);
-            this._utilityLayer.onlyCheckPointerDownEvents = false;
-            this._utilityLayer.mainSceneTrackerPredicate = (mesh: Nullable<AbstractMesh>) => {
-                return mesh && mesh.metadata && mesh.metadata._node;
-            }
+        // Events
+        this._pointerOutObserver = this._utilityLayer.onPointerOutObservable.add((pointerId) => {
+            this._handlePointerOut(pointerId, true);
+        });
 
-            // Root
-            this._rootContainer = new Container3D("RootContainer");
-            this._rootContainer._host = this;
-            let utilityLayerScene = this._utilityLayer.utilityLayerScene;
-            
-            // Events
-            this._pointerOutObserver = this._utilityLayer.onPointerOutObservable.add((pointerId) => {
-                this._handlePointerOut(pointerId, true);
-            });
-
-            this._pointerObserver = utilityLayerScene.onPointerObservable.add((pi, state) => {
-                this._doPicking(pi);
-            });
-
-            // Scene
-            this._utilityLayer.utilityLayerScene.autoClear = false;
-            this._utilityLayer.utilityLayerScene.autoClearDepthAndStencil = false;
-            new BABYLON.HemisphericLight("hemi", Vector3.Up(), this._utilityLayer.utilityLayerScene);
-        }
+        this._pointerObserver = utilityLayerScene.onPointerObservable.add((pi, state) => {
+            this._doPicking(pi);
+        });
 
-        private _handlePointerOut(pointerId: number, isPointerUp: boolean) {
-            var previousControlOver = this._lastControlOver[pointerId];
-            if (previousControlOver) {
-                previousControlOver._onPointerOut(previousControlOver);
-                delete this._lastControlOver[pointerId];
-            }               
-            
-            if (isPointerUp) {
-                if (this._lastControlDown[pointerId]) {
-                    this._lastControlDown[pointerId].forcePointerUp();
-                    delete this._lastControlDown[pointerId];
-                }
-            }        
-            
-            this.onPickedPointChangedObservable.notifyObservers(null);
+        // Scene
+        this._utilityLayer.utilityLayerScene.autoClear = false;
+        this._utilityLayer.utilityLayerScene.autoClearDepthAndStencil = false;
+        new HemisphericLight("hemi", Vector3.Up(), this._utilityLayer.utilityLayerScene);
+    }
+
+    private _handlePointerOut(pointerId: number, isPointerUp: boolean) {
+        var previousControlOver = this._lastControlOver[pointerId];
+        if (previousControlOver) {
+            previousControlOver._onPointerOut(previousControlOver);
+            delete this._lastControlOver[pointerId];
         }
 
-        private _doPicking(pi: PointerInfo): boolean {
-            if (!this._utilityLayer || !this._utilityLayer.utilityLayerScene.activeCamera) {
-                return false;                
+        if (isPointerUp) {
+            if (this._lastControlDown[pointerId]) {
+                this._lastControlDown[pointerId].forcePointerUp();
+                delete this._lastControlDown[pointerId];
             }
+        }
 
-            let pointerEvent = <PointerEvent>(pi.event);
+        this.onPickedPointChangedObservable.notifyObservers(null);
+    }
 
-            let pointerId = pointerEvent.pointerId || 0;
-            let buttonIndex = pointerEvent.button;
-            
-            let pickingInfo = pi.pickInfo;
-            if (!pickingInfo || !pickingInfo.hit) {
-                this._handlePointerOut(pointerId, pi.type === BABYLON.PointerEventTypes.POINTERUP);
-                return false;
-            }
+    private _doPicking(pi: PointerInfo): boolean {
+        if (!this._utilityLayer || !this._utilityLayer.utilityLayerScene.activeCamera) {
+            return false;
+        }
 
-            let control = <Control3D>(pickingInfo.pickedMesh!.metadata);
-            if (pickingInfo.pickedPoint) {
-                this.onPickedPointChangedObservable.notifyObservers(pickingInfo.pickedPoint);
-            }
+        let pointerEvent = <PointerEvent>(pi.event);
 
-            if (!control._processObservables(pi.type, pickingInfo.pickedPoint!, pointerId, buttonIndex)) {
+        let pointerId = pointerEvent.pointerId || 0;
+        let buttonIndex = pointerEvent.button;
 
-                if (pi.type === BABYLON.PointerEventTypes.POINTERMOVE) {
-                    if (this._lastControlOver[pointerId]) {
-                        this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
-                    }
+        let pickingInfo = pi.pickInfo;
+        if (!pickingInfo || !pickingInfo.hit) {
+            this._handlePointerOut(pointerId, pi.type === PointerEventTypes.POINTERUP);
+            return false;
+        }
 
-                    delete this._lastControlOver[pointerId];
-                }
-            }
+        let control = <Control3D>(pickingInfo.pickedMesh!.metadata);
+        if (pickingInfo.pickedPoint) {
+            this.onPickedPointChangedObservable.notifyObservers(pickingInfo.pickedPoint);
+        }
 
-            if (pi.type === BABYLON.PointerEventTypes.POINTERUP) {
-                if (this._lastControlDown[pointerEvent.pointerId]) {
-                    this._lastControlDown[pointerEvent.pointerId].forcePointerUp();
-                    delete this._lastControlDown[pointerEvent.pointerId];
-                }
+        if (!control._processObservables(pi.type, pickingInfo.pickedPoint!, pointerId, buttonIndex)) {
 
-                if (pointerEvent.pointerType === "touch") {
-                    this._handlePointerOut(pointerId, false);
+            if (pi.type === PointerEventTypes.POINTERMOVE) {
+                if (this._lastControlOver[pointerId]) {
+                    this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
                 }
-            }
 
-            return true;
+                delete this._lastControlOver[pointerId];
+            }
         }
 
-        /**
-         * Gets the root container
-         */
-        public get rootContainer(): Container3D {
-            return this._rootContainer;
-        }
+        if (pi.type === PointerEventTypes.POINTERUP) {
+            if (this._lastControlDown[pointerEvent.pointerId]) {
+                this._lastControlDown[pointerEvent.pointerId].forcePointerUp();
+                delete this._lastControlDown[pointerEvent.pointerId];
+            }
 
-        /**
-         * Gets a boolean indicating if the given control is in the root child list
-         * @param control defines the control to check
-         * @returns true if the control is in the root child list
-         */
-        public containsControl(control: Control3D): boolean {
-            return this._rootContainer.containsControl(control);
+            if (pointerEvent.pointerType === "touch") {
+                this._handlePointerOut(pointerId, false);
+            }
         }
 
-        /**
-         * Adds a control to the root child list
-         * @param control defines the control to add
-         * @returns the current manager
-         */
-        public addControl(control: Control3D): GUI3DManager {
-           this._rootContainer.addControl(control);
-           return this;
-        }
+        return true;
+    }
 
-        /**
-         * Removes a control from the root child list
-         * @param control defines the control to remove
-         * @returns the current container
-         */
-        public removeControl(control: Control3D): GUI3DManager {
-            this._rootContainer.removeControl(control);
-            return this;
-        }        
-
-        /**
-         * Releases all associated resources
-         */
-        public dispose() {
-            this._rootContainer.dispose();
-
-            for (var materialName in this._sharedMaterials) {
-                if (!this._sharedMaterials.hasOwnProperty(materialName)) {
-                    continue;
-                }
+    /**
+     * Gets the root container
+     */
+    public get rootContainer(): Container3D {
+        return this._rootContainer;
+    }
 
-                this._sharedMaterials[materialName].dispose();
-            }
+    /**
+     * Gets a boolean indicating if the given control is in the root child list
+     * @param control defines the control to check
+     * @returns true if the control is in the root child list
+     */
+    public containsControl(control: Control3D): boolean {
+        return this._rootContainer.containsControl(control);
+    }
+
+    /**
+     * Adds a control to the root child list
+     * @param control defines the control to add
+     * @returns the current manager
+     */
+    public addControl(control: Control3D): GUI3DManager {
+        this._rootContainer.addControl(control);
+        return this;
+    }
+
+    /**
+     * Removes a control from the root child list
+     * @param control defines the control to remove
+     * @returns the current container
+     */
+    public removeControl(control: Control3D): GUI3DManager {
+        this._rootContainer.removeControl(control);
+        return this;
+    }
 
-            this._sharedMaterials = {};
+    /**
+     * Releases all associated resources
+     */
+    public dispose() {
+        this._rootContainer.dispose();
 
-            if (this._pointerOutObserver && this._utilityLayer) {
-                this._utilityLayer.onPointerOutObservable.remove(this._pointerOutObserver);
-                this._pointerOutObserver = null;
+        for (var materialName in this._sharedMaterials) {
+            if (!this._sharedMaterials.hasOwnProperty(materialName)) {
+                continue;
             }
 
-            this.onPickedPointChangedObservable.clear();
+            this._sharedMaterials[materialName].dispose();
+        }
 
-            let utilityLayerScene = this._utilityLayer ? this._utilityLayer.utilityLayerScene : null;
+        this._sharedMaterials = {};
 
-            if (utilityLayerScene) {
-                if (this._pointerObserver) {
-                    utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
-                    this._pointerObserver = null;
-                }
+        if (this._pointerOutObserver && this._utilityLayer) {
+            this._utilityLayer.onPointerOutObservable.remove(this._pointerOutObserver);
+            this._pointerOutObserver = null;
+        }
+
+        this.onPickedPointChangedObservable.clear();
+
+        let utilityLayerScene = this._utilityLayer ? this._utilityLayer.utilityLayerScene : null;
+
+        if (utilityLayerScene) {
+            if (this._pointerObserver) {
+                utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
+                this._pointerObserver = null;
             }
-            if (this._scene) {
-                 if (this._sceneDisposeObserver) {
-                    this._scene.onDisposeObservable.remove(this._sceneDisposeObserver);
-                    this._sceneDisposeObserver = null;
-                }                
+        }
+        if (this._scene) {
+            if (this._sceneDisposeObserver) {
+                this._scene.onDisposeObservable.remove(this._sceneDisposeObserver);
+                this._sceneDisposeObserver = null;
             }
+        }
 
-            if (this._utilityLayer) {
-                this._utilityLayer.dispose();
-            }
+        if (this._utilityLayer) {
+            this._utilityLayer.dispose();
         }
     }
 }

+ 5 - 0
gui/src/3D/index.ts

@@ -0,0 +1,5 @@
+export * from "./controls";
+export * from "./materials";
+
+export * from "./gui3DManager";
+export * from "./vector3WithInfo";

+ 237 - 235
gui/src/3D/materials/fluentMaterial.ts

@@ -1,279 +1,281 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GUI {
-
-    /** @hidden */
-    export class FluentMaterialDefines extends MaterialDefines {
-        public INNERGLOW = false;
-        public BORDER = false;
-        public HOVERLIGHT = false;
-    
-        constructor() {
-            super();
-            this.rebuild();
-        }
+import { MaterialDefines, PushMaterial, serialize, expandToProperty, serializeAsColor3, Color3, serializeAsColor4, Color4, serializeAsVector3, Vector3, Scene, Nullable, BaseTexture, AbstractMesh, SubMesh, VertexBuffer, MaterialHelper, EffectCreationOptions, Matrix, Mesh, Tmp, SerializationHelper } from "babylonjs";
+
+import { registerShader } from "./shaders/fluent";
+
+// register shaders
+registerShader();
+
+/** @hidden */
+export class FluentMaterialDefines extends MaterialDefines {
+    public INNERGLOW = false;
+    public BORDER = false;
+    public HOVERLIGHT = false;
+
+    constructor() {
+        super();
+        this.rebuild();
     }
+}
+
+/**
+ * Class used to render controls with fluent desgin
+ */
+export class FluentMaterial extends PushMaterial {
 
     /**
-     * Class used to render controls with fluent desgin
+     * Gets or sets inner glow intensity. A value of 0 means no glow (default is 0.5)
      */
-    export class FluentMaterial extends PushMaterial {    
-
-        /**
-         * Gets or sets inner glow intensity. A value of 0 means no glow (default is 0.5)
-         */
-        @serialize()
-        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public innerGlowColorIntensity = 0.5;
-
-        /**
-         * Gets or sets the inner glow color (white by default)
-         */
-        @serializeAsColor3()
-        public innerGlowColor = new Color3(1.0, 1.0, 1.0);
-
-        /**
-         * Gets or sets alpha value (default is 1.0)
-         */
-        @serialize()
-        public alpha = 1.0;        
-
-        /**
-         * Gets or sets the albedo color (Default is Color3(0.3, 0.35, 0.4))
-         */
-        @serializeAsColor3()
-        public albedoColor = new Color3(0.3, 0.35, 0.4);
-
-        /**
-         * Gets or sets a boolean indicating if borders must be rendered (default is false)
-         */
-        @serialize()
-        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public renderBorders = false;        
-
-        /**
-         * Gets or sets border width (default is 0.5)
-         */
-        @serialize()
-        public borderWidth = 0.5;      
-        
-        /**
-         * Gets or sets a value indicating the smoothing value applied to border edges (0.02 by default)
-         */
-        @serialize()
-        public edgeSmoothingValue = 0.02;
-        
-        /**
-         * Gets or sets the minimum value that can be applied to border width (default is 0.1)
-         */
-        @serialize()
-        public borderMinValue = 0.1;      
-        
-        /**
-         * Gets or sets a boolean indicating if hover light must be rendered (default is false)
-         */
-        @serialize()
-        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public renderHoverLight = false;         
-        
-        /**
-         * Gets or sets the radius used to render the hover light (default is 0.15)
-         */
-        @serialize()
-        public hoverRadius = 1.0;            
-        
-        /**
-         * Gets or sets the color used to render the hover light (default is Color4(0.3, 0.3, 0.3, 1.0))
-         */
-        @serializeAsColor4()
-        public hoverColor = new Color4(0.3, 0.3, 0.3, 1.0);           
-        
-        /**
-         * Gets or sets the hover light position in world space (default is Vector3.Zero())
-         */
-        @serializeAsVector3()
-        public hoverPosition = Vector3.Zero();             
-        
-        /**
-         * Creates a new Fluent material
-         * @param name defines the name of the material
-         * @param scene defines the hosting scene
-         */
-        constructor(name: string, scene: Scene) {
-            super(name, scene);
-        }
+    @serialize()
+    @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+    public innerGlowColorIntensity = 0.5;
 
-        public needAlphaBlending(): boolean {
-            return this.alpha !== 1.0;
-        }
+    /**
+     * Gets or sets the inner glow color (white by default)
+     */
+    @serializeAsColor3()
+    public innerGlowColor = new Color3(1.0, 1.0, 1.0);
 
-        public needAlphaTesting(): boolean {
-            return false;
-        }
+    /**
+     * Gets or sets alpha value (default is 1.0)
+     */
+    @serialize()
+    public alpha = 1.0;
 
-        public getAlphaTestTexture(): Nullable<BaseTexture> {
-            return null;
-        } 
-        
-        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
-            if (this.isFrozen) {
-                if (this._wasPreviouslyReady && subMesh.effect) {
-                    return true;
-                }
-            }
+    /**
+     * Gets or sets the albedo color (Default is Color3(0.3, 0.35, 0.4))
+     */
+    @serializeAsColor3()
+    public albedoColor = new Color3(0.3, 0.35, 0.4);
 
-            if (!subMesh._materialDefines) {
-                subMesh._materialDefines = new FluentMaterialDefines();
-            }
+    /**
+     * Gets or sets a boolean indicating if borders must be rendered (default is false)
+     */
+    @serialize()
+    @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+    public renderBorders = false;
 
-            var scene = this.getScene();
-            var defines = <FluentMaterialDefines>subMesh._materialDefines;
-            if (!this.checkReadyOnEveryCall && subMesh.effect) {
-                if (defines._renderId === scene.getRenderId()) {
-                    return true;
-                }
-            }            
-
-            if (defines._areTexturesDirty) {
-                defines.INNERGLOW = this.innerGlowColorIntensity > 0;
-                defines.BORDER = this.renderBorders;
-                defines.HOVERLIGHT = this.renderHoverLight;
-            }
+    /**
+     * Gets or sets border width (default is 0.5)
+     */
+    @serialize()
+    public borderWidth = 0.5;
 
-            var engine = scene.getEngine();
-            // Get correct effect      
-            if (defines.isDirty) {
-                defines.markAsProcessed();
-                scene.resetCachedMaterial();
+    /**
+     * Gets or sets a value indicating the smoothing value applied to border edges (0.02 by default)
+     */
+    @serialize()
+    public edgeSmoothingValue = 0.02;
 
-                //Attributes
-                var attribs = [VertexBuffer.PositionKind];
-                attribs.push(VertexBuffer.NormalKind);
-                attribs.push(VertexBuffer.UVKind);
+    /**
+     * Gets or sets the minimum value that can be applied to border width (default is 0.1)
+     */
+    @serialize()
+    public borderMinValue = 0.1;
 
-                var shaderName = "fluent";
+    /**
+     * Gets or sets a boolean indicating if hover light must be rendered (default is false)
+     */
+    @serialize()
+    @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+    public renderHoverLight = false;
 
-                var uniforms = ["world", "viewProjection", "innerGlowColor", "albedoColor", "borderWidth", "edgeSmoothingValue", "scaleFactor", "borderMinValue",
-                                "hoverColor", "hoverPosition", "hoverRadius"
-                ];
+    /**
+     * Gets or sets the radius used to render the hover light (default is 0.15)
+     */
+    @serialize()
+    public hoverRadius = 1.0;
 
-                var samplers = new Array<String>();
-                var uniformBuffers = new Array<string>();
+    /**
+     * Gets or sets the color used to render the hover light (default is Color4(0.3, 0.3, 0.3, 1.0))
+     */
+    @serializeAsColor4()
+    public hoverColor = new Color4(0.3, 0.3, 0.3, 1.0);
 
-                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
-                    uniformsNames: uniforms,
-                    uniformBuffersNames: uniformBuffers,
-                    samplers: samplers,
-                    defines: defines,
-                    maxSimultaneousLights: 4
-                });            
-
-                var join = defines.toString();
-                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    <EffectCreationOptions>{
-                        attributes: attribs,
-                        uniformsNames: uniforms,
-                        uniformBuffersNames: uniformBuffers,
-                        samplers: samplers,
-                        defines: join,
-                        fallbacks: null,
-                        onCompiled: this.onCompiled,
-                        onError: this.onError,
-                        indexParameters: { maxSimultaneousLights: 4 }
-                    }, engine));            
-                
-            }
+    /**
+     * Gets or sets the hover light position in world space (default is Vector3.Zero())
+     */
+    @serializeAsVector3()
+    public hoverPosition = Vector3.Zero();
+
+    /**
+     * Creates a new Fluent material
+     * @param name defines the name of the material
+     * @param scene defines the hosting scene
+     */
+    constructor(name: string, scene: Scene) {
+        super(name, scene);
+    }
+
+    public needAlphaBlending(): boolean {
+        return this.alpha !== 1.0;
+    }
 
-            if (!subMesh.effect || !subMesh.effect.isReady()) {
-                return false;
+    public needAlphaTesting(): boolean {
+        return false;
+    }
+
+    public getAlphaTestTexture(): Nullable<BaseTexture> {
+        return null;
+    }
+
+    public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
+        if (this.isFrozen) {
+            if (this._wasPreviouslyReady && subMesh.effect) {
+                return true;
             }
+        }
 
-            defines._renderId = scene.getRenderId();
-            this._wasPreviouslyReady = true;
+        if (!subMesh._materialDefines) {
+            subMesh._materialDefines = new FluentMaterialDefines();
+        }
 
-            return true;
+        var scene = this.getScene();
+        var defines = <FluentMaterialDefines>subMesh._materialDefines;
+        if (!this.checkReadyOnEveryCall && subMesh.effect) {
+            if (defines._renderId === scene.getRenderId()) {
+                return true;
+            }
         }
 
-        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
-            var scene = this.getScene();
+        if (defines._areTexturesDirty) {
+            defines.INNERGLOW = this.innerGlowColorIntensity > 0;
+            defines.BORDER = this.renderBorders;
+            defines.HOVERLIGHT = this.renderHoverLight;
+        }
 
-            var defines = <FluentMaterialDefines>subMesh._materialDefines;
-            if (!defines) {
-                return;
-            }            
+        var engine = scene.getEngine();
+        // Get correct effect      
+        if (defines.isDirty) {
+            defines.markAsProcessed();
+            scene.resetCachedMaterial();
+
+            //Attributes
+            var attribs = [VertexBuffer.PositionKind];
+            attribs.push(VertexBuffer.NormalKind);
+            attribs.push(VertexBuffer.UVKind);
+
+            var shaderName = "fluent";
+
+            var uniforms = ["world", "viewProjection", "innerGlowColor", "albedoColor", "borderWidth", "edgeSmoothingValue", "scaleFactor", "borderMinValue",
+                "hoverColor", "hoverPosition", "hoverRadius"
+            ];
+
+            var samplers = new Array<String>();
+            var uniformBuffers = new Array<string>();
+
+            MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                uniformsNames: uniforms,
+                uniformBuffersNames: uniformBuffers,
+                samplers: samplers,
+                defines: defines,
+                maxSimultaneousLights: 4
+            });
+
+            var join = defines.toString();
+            subMesh.setEffect(scene.getEngine().createEffect(shaderName,
+                <EffectCreationOptions>{
+                    attributes: attribs,
+                    uniformsNames: uniforms,
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers,
+                    defines: join,
+                    fallbacks: null,
+                    onCompiled: this.onCompiled,
+                    onError: this.onError,
+                    indexParameters: { maxSimultaneousLights: 4 }
+                }, engine));
 
-            var effect = subMesh.effect;
-            if (!effect) {
-                return;
-            }
-            this._activeEffect = effect;
+        }
 
-            // Matrices        
-            this.bindOnlyWorldMatrix(world);
-            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
+        if (!subMesh.effect || !subMesh.effect.isReady()) {
+            return false;
+        }
 
+        defines._renderId = scene.getRenderId();
+        this._wasPreviouslyReady = true;
 
-            if (this._mustRebind(scene, effect)) {   
-                this._activeEffect.setColor4("albedoColor", this.albedoColor, this.alpha);
+        return true;
+    }
 
-                if (defines.INNERGLOW) {
-                    this._activeEffect.setColor4("innerGlowColor", this.innerGlowColor, this.innerGlowColorIntensity);
-                }
+    public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
+        var scene = this.getScene();
 
-                if (defines.BORDER) {
-                    this._activeEffect.setFloat("borderWidth", this.borderWidth);
-                    this._activeEffect.setFloat("edgeSmoothingValue", this.edgeSmoothingValue);
-                    this._activeEffect.setFloat("borderMinValue", this.borderMinValue);
+        var defines = <FluentMaterialDefines>subMesh._materialDefines;
+        if (!defines) {
+            return;
+        }
 
-                    mesh.getBoundingInfo().boundingBox.extendSize.multiplyToRef(mesh.scaling, Tmp.Vector3[0]);
-                    this._activeEffect.setVector3("scaleFactor", Tmp.Vector3[0]);
-                }
+        var effect = subMesh.effect;
+        if (!effect) {
+            return;
+        }
+        this._activeEffect = effect;
 
-                if (defines.HOVERLIGHT) {
-                    this._activeEffect.setDirectColor4("hoverColor", this.hoverColor);
-                    this._activeEffect.setFloat("hoverRadius", this.hoverRadius);
-                    this._activeEffect.setVector3("hoverPosition", this.hoverPosition);
-                }
-            }
+        // Matrices        
+        this.bindOnlyWorldMatrix(world);
+        this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
 
-            this._afterBind(mesh, this._activeEffect);
-        }    
 
-        public getActiveTextures(): BaseTexture[] {
-            var activeTextures = super.getActiveTextures();
+        if (this._mustRebind(scene, effect)) {
+            this._activeEffect.setColor4("albedoColor", this.albedoColor, this.alpha);
 
-            return activeTextures;
-        }        
+            if (defines.INNERGLOW) {
+                this._activeEffect.setColor4("innerGlowColor", this.innerGlowColor, this.innerGlowColorIntensity);
+            }
 
-        public hasTexture(texture: BaseTexture): boolean {
-            if (super.hasTexture(texture)) {
-                return true;
+            if (defines.BORDER) {
+                this._activeEffect.setFloat("borderWidth", this.borderWidth);
+                this._activeEffect.setFloat("edgeSmoothingValue", this.edgeSmoothingValue);
+                this._activeEffect.setFloat("borderMinValue", this.borderMinValue);
+
+                mesh.getBoundingInfo().boundingBox.extendSize.multiplyToRef(mesh.scaling, Tmp.Vector3[0]);
+                this._activeEffect.setVector3("scaleFactor", Tmp.Vector3[0]);
             }
 
-            return false;
-        }        
-        
-        public dispose(forceDisposeEffect?: boolean): void {
-            super.dispose(forceDisposeEffect);
+            if (defines.HOVERLIGHT) {
+                this._activeEffect.setDirectColor4("hoverColor", this.hoverColor);
+                this._activeEffect.setFloat("hoverRadius", this.hoverRadius);
+                this._activeEffect.setVector3("hoverPosition", this.hoverPosition);
+            }
         }
 
-        public clone(name: string): FluentMaterial {
-            return SerializationHelper.Clone(() => new FluentMaterial(name, this.getScene()), this);
-        }
+        this._afterBind(mesh, this._activeEffect);
+    }
 
-        public serialize(): any {
-            var serializationObject = SerializationHelper.Serialize(this);
-            serializationObject.customType = "BABYLON.GUI.FluentMaterial";
-            return serializationObject;
-        }
+    public getActiveTextures(): BaseTexture[] {
+        var activeTextures = super.getActiveTextures();
 
-        public getClassName(): string {
-            return "FluentMaterial";
-        }
+        return activeTextures;
+    }
 
-        // Statics
-        public static Parse(source: any, scene: Scene, rootUrl: string): FluentMaterial {
-            return SerializationHelper.Parse(() => new FluentMaterial(source.name, scene), source, scene, rootUrl);
+    public hasTexture(texture: BaseTexture): boolean {
+        if (super.hasTexture(texture)) {
+            return true;
         }
+
+        return false;
+    }
+
+    public dispose(forceDisposeEffect?: boolean): void {
+        super.dispose(forceDisposeEffect);
+    }
+
+    public clone(name: string): FluentMaterial {
+        return SerializationHelper.Clone(() => new FluentMaterial(name, this.getScene()), this);
+    }
+
+    public serialize(): any {
+        var serializationObject = SerializationHelper.Serialize(this);
+        serializationObject.customType = "BABYLON.GUI.FluentMaterial";
+        return serializationObject;
+    }
+
+    public getClassName(): string {
+        return "FluentMaterial";
+    }
+
+    // Statics
+    public static Parse(source: any, scene: Scene, rootUrl: string): FluentMaterial {
+        return SerializationHelper.Parse(() => new FluentMaterial(source.name, scene), source, scene, rootUrl);
     }
 }

+ 1 - 0
gui/src/3D/materials/index.ts

@@ -0,0 +1 @@
+export * from "./fluentMaterial";

+ 12 - 0
gui/src/3D/materials/shaders/fluent.ts

@@ -0,0 +1,12 @@
+import { Effect } from "babylonjs";
+
+const fShader = require("./fluent.fragment.fx");
+const vShader = require("./fluent.vertex.fx");
+
+export function registerShader() {
+    // register shaders
+    Effect.ShadersStore["fluentVertexShader"] = vShader;
+    Effect.ShadersStore["fluentPixelShader"] = fShader;
+}
+
+export { fShader, vShader };

+ 12 - 14
gui/src/3D/vector3WithInfo.ts

@@ -1,19 +1,17 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+import { Vector3 } from "babylonjs";
 
-module BABYLON.GUI {
+/**
+ * Class used to transport Vector3 information for pointer events
+ */
+export class Vector3WithInfo extends Vector3 {
     /**
-     * Class used to transport Vector3 information for pointer events
+     * Creates a new Vector3WithInfo
+     * @param source defines the vector3 data to transport
+     * @param buttonIndex defines the current mouse button index
      */
-    export class Vector3WithInfo extends Vector3 {        
-        /**
-         * Creates a new Vector3WithInfo
-         * @param source defines the vector3 data to transport
-         * @param buttonIndex defines the current mouse button index
-         */
-        public constructor(source: Vector3, 
-            /** defines the current mouse button index */
-            public buttonIndex: number = 0) {
-            super(source.x, source.y, source.z);
-        }
+    public constructor(source: Vector3,
+        /** defines the current mouse button index */
+        public buttonIndex: number = 0) {
+        super(source.x, source.y, source.z);
     }
 }

+ 2 - 0
gui/src/index.ts

@@ -0,0 +1,2 @@
+export * from "./2D";
+export * from "./3D";

+ 0 - 12
gui/src/tsconfig.json

@@ -1,12 +0,0 @@
-{
-  "compilerOptions": {
-    "experimentalDecorators": true,
-    "module": "commonjs",
-    "target": "es5",
-    "noImplicitAny": true,
-    "noImplicitReturns": true,
-    "noImplicitThis": true,
-    "noUnusedLocals": true,    
-    "strictNullChecks": true    
-  }
-}

+ 31 - 0
gui/tsconfig.json

@@ -0,0 +1,31 @@
+{
+    "compilerOptions": {
+        "experimentalDecorators": true,
+        "module": "commonjs",
+        "target": "es5",
+        "noImplicitAny": true,
+        "noImplicitReturns": true,
+        "noImplicitThis": true,
+        "noUnusedLocals": true,
+        "strictNullChecks": true,
+        "declaration": true,
+        "sourceMap": true,
+        "lib": [
+            "es5",
+            "dom",
+            "es2015.promise",
+            "es2015.collection",
+            "es2015.iterable"
+        ],
+        "skipDefaultLibCheck": true,
+        "skipLibCheck": true,
+        "baseUrl": "./src/",
+        "rootDir": "./src/",
+        "paths": {
+            "babylonjs": [
+                "../../dist/preview release/babylon.d.ts"
+            ]
+        },
+        "outDir": "./build"
+    }
+}

+ 76 - 0
gui/webpack.config.js

@@ -0,0 +1,76 @@
+const path = require('path');
+const webpack = require('webpack');
+const DtsBundleWebpack = require('dts-bundle-webpack');
+const CleanWebpackPlugin = require('clean-webpack-plugin');
+
+module.exports = {
+    context: __dirname,
+    entry: {
+        'babylonjs-gui': path.resolve(__dirname, './src/index.ts'),
+    },
+    output: {
+        path: path.resolve(__dirname, '../dist/preview release/gui'),
+        filename: 'babylon.gui.min.js',
+        libraryTarget: 'umd',
+        library: {
+            root: ["BABYLON", "GUI"],
+            amd: "babylonjs-gui",
+            commonjs: "babylonjs-gui"
+        },
+        umdNamedDefine: true,
+        //devtoolModuleFilenameTemplate: "[absolute-resource-path]"
+    },
+    resolve: {
+        extensions: [".js", '.ts']
+    },
+    externals: {
+        babylonjs: {
+            root: "BABYLON",
+            commonjs: "babylonjs",
+            commonjs2: "babylonjs",
+            amd: "babylonjs"
+        }
+    },
+    devtool: "source-map",
+    module: {
+        rules: [{
+            test: /\.tsx?$/,
+            loader: "ts-loader",
+            exclude: /node_modules/
+        },
+        {
+            test: /\.fx$/,
+            use: [{
+                loader: path.resolve(__dirname, '../Tools/WebpackShaderLoader/index.js')
+            }]
+        }]
+    },
+    mode: "production",
+    devServer: {
+        contentBase: path.join(__dirname, "dist"),
+        compress: false,
+        //open: true,
+        port: 9000
+    },
+    plugins: [
+        new CleanWebpackPlugin([
+            path.resolve(__dirname, './src/**/*.js'),
+            path.resolve(__dirname, './src/**/*.map')
+        ]),
+        // moved out of here due to the way gulp works...
+        /*new DtsBundleWebpack({
+            name: "babylonjs-gui",
+            main: path.resolve(__dirname, '../dist/preview release/gui/build/index.d.ts'),
+            out: path.resolve(__dirname, '../dist/preview release/gui/babylon.gui.module.d.ts'),
+            baseDir: path.resolve(__dirname, '../dist/preview release/gui/build/'),
+            headerText: "BabylonJS GUI"
+        }),*/
+        new webpack.WatchIgnorePlugin([
+            /\.js$/,
+            /\.d\.ts$/
+        ])
+    ],
+    watchOptions: {
+        ignored: [path.resolve(__dirname, './dist/**/*.*'), 'node_modules']
+    }
+}

+ 0 - 0
inspector/package.json


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác