sebastien 6 年之前
父节点
当前提交
8ced2e8477
共有 82 个文件被更改,包括 17598 次插入14827 次删除
  1. 5589 5506
      Playground/babylon.d.txt
  2. 383 383
      Playground/indexStable.html
  3. 14 14
      Playground/js/frame.js
  4. 78 98
      Playground/js/index.js
  5. 916 0
      Viewer/dist/4ff3a89403672639e15d.js
  6. 183 0
      Viewer/dist/e45de3ab9c569c68ab0c.js
  7. 5488 5476
      dist/preview release/babylon.d.ts
  8. 1 1
      dist/preview release/babylon.js
  9. 514 603
      dist/preview release/babylon.max.js
  10. 514 603
      dist/preview release/babylon.no-module.max.js
  11. 1 1
      dist/preview release/babylon.worker.js
  12. 514 603
      dist/preview release/es6.js
  13. 117 45
      dist/preview release/gui/babylon.gui.d.ts
  14. 585 304
      dist/preview release/gui/babylon.gui.js
  15. 1 1
      dist/preview release/gui/babylon.gui.js.map
  16. 1 1
      dist/preview release/gui/babylon.gui.min.js
  17. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  18. 249 96
      dist/preview release/gui/babylon.gui.module.d.ts
  19. 4 0
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  20. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.js.map
  21. 4 0
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  22. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js.map
  23. 8 2
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  24. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  25. 8 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  26. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js.map
  27. 8 2
      dist/preview release/loaders/babylon.glTFFileLoader.js
  28. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  29. 8 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  30. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js.map
  31. 4 2
      dist/preview release/loaders/babylonjs.loaders.d.ts
  32. 8 2
      dist/preview release/loaders/babylonjs.loaders.js
  33. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  34. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  35. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js.map
  36. 8 4
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  37. 1 4
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.js
  38. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.js.map
  39. 1 4
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  40. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js.map
  41. 1 4
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.js
  42. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.js.map
  43. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  44. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js.map
  45. 4 2
      dist/preview release/serializers/babylon.glTF2Serializer.js
  46. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.js.map
  47. 4 2
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  48. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js.map
  49. 4 2
      dist/preview release/serializers/babylonjs.serializers.d.ts
  50. 4 2
      dist/preview release/serializers/babylonjs.serializers.js
  51. 1 1
      dist/preview release/serializers/babylonjs.serializers.js.map
  52. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  53. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js.map
  54. 8 4
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  55. 916 0
      dist/preview release/viewer/4ff3a89403672639e15d.js
  56. 4 0
      dist/preview release/viewer/babylon.viewer.js
  57. 8 0
      dist/preview release/viewer/babylon.viewer.max.js
  58. 183 0
      dist/preview release/viewer/e45de3ab9c569c68ab0c.js
  59. 3 0
      dist/preview release/what's new.md
  60. 283 0
      gui/src/2D/controls/baseSlider.ts
  61. 20 1
      gui/src/2D/controls/image.ts
  62. 145 0
      gui/src/2D/controls/imageBasedSlider.ts
  63. 23 21
      gui/src/2D/controls/index.ts
  64. 77 297
      gui/src/2D/controls/slider.ts
  65. 14 0
      gui/src/2D/measure.ts
  66. 2 1
      loaders/src/glTF/2.0/glTFLoaderExtension.ts
  67. 2 1
      loaders/src/glTF/2.0/glTFLoaderInterfaces.ts
  68. 4 0
      loaders/src/glTF/glTFFileLoader.ts
  69. 6 4
      postProcessLibrary/src/digitalRain/digitalRainPostProcess.ts
  70. 1 1
      readme.md
  71. 2 1
      serializers/src/glTF/2.0/glTFExporterExtension.ts
  72. 2 1
      serializers/src/glTF/glTFFileExporter.ts
  73. 21 37
      src/Bones/babylon.bone.ts
  74. 9 15
      src/Cameras/VR/babylon.webVRCamera.ts
  75. 29 27
      src/Cameras/babylon.arcRotateCamera.ts
  76. 1 3
      src/Debug/babylon.skeletonViewer.ts
  77. 14 13
      src/Materials/Textures/babylon.texture.ts
  78. 541 598
      src/Math/babylon.math.ts
  79. 25 9
      src/babylon.scene.ts
  80. 二进制
      tests/validation/ReferenceImages/pointers.png
  81. 6 0
      tests/validation/config.json
  82. 2 2
      tests/validation/validation.js

文件差异内容过多而无法显示
+ 5589 - 5506
Playground/babylon.d.txt


+ 383 - 383
Playground/indexStable.html

@@ -1,475 +1,475 @@
 <!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>
-        <!-- Physics -->
-        <script src="https://cdn.babylonjs.com/cannon.js"></script>
-        <script src="https://cdn.babylonjs.com/Oimo.js"></script>
-        <script src="https://cdn.babylonjs.com/gltf_validator.js"></script>
-        <script src="https://cdn.babylonjs.com/earcut.min.js"></script>
-        <!-- Monaco -->
-        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
-        <!-- Babylon.js -->
-        <script src="https://cdn.babylonjs.com/babylon.max.js"></script>
-        <script src="https://cdn.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
-        <script src="https://cdn.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
-        <script src="https://cdn.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
-        <script src="https://cdn.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
-
-        <script src="https://cdn.babylonjs.com/gui/babylon.gui.min.js"></script>
-
-        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
-        <link href="css/index.css" rel="stylesheet" />
-    </head>
-
-    <body>
-        <div class="navbar navBar1600">
-            <div class="title">
-                Babylon.js Playground
-            </div>
-            <div class="version" id="mainTitle">
-            </div>
+<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>
+    <!-- Physics -->
+    <script src="https://cdn.babylonjs.com/cannon.js"></script>
+    <script src="https://cdn.babylonjs.com/Oimo.js"></script>
+    <script src="https://cdn.babylonjs.com/gltf_validator.js"></script>
+    <script src="https://cdn.babylonjs.com/earcut.min.js"></script>
+    <!-- Babylon.js -->
+    <script src="https://cdn.babylonjs.com/babylon.js"></script>
+    <script src="https://cdn.babylonjs.com/gui/babylon.gui.min.js"></script>
+    <script src="https://cdn.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+    <script src="https://cdn.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
+    <script src="https://cdn.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
+    <script src="https://cdn.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
+    <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.js"></script>
+    <script src="https://cdn.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
+
+    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
+    <!-- Monaco -->
+    <script src="node_modules/monaco-editor/min/vs/loader.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">
+        </div>
 
-            <div class="category">
-                <div class="button run" id="runButton1600">Run
-                    <i class="fa fa-play" aria-hidden="true"></i>
-                </div>
+        <div class="category">
+            <div class="button run" id="runButton1600">Run
+                <i class="fa fa-play" aria-hidden="true"></i>
             </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>
+        <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 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 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 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 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 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="far fa-square" 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="far fa-square" aria-hidden="true"></i>
+                    </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>
-
-                <div class="button uncheck" id="debugButton1600">Inspector</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('stable');">Stable</div>
+                    <div class="option" id="safemodeToggle1600">Safe mode
+                        <i class="far fa-square" 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="far fa-square" aria-hidden="true"></i>
                     </div>
-                </div>
-                <div class="button select">
-                    <span class="examplesButton">Examples</span>
                 </div>
             </div>
+
+            <div class="button uncheck" id="debugButton1600">Inspector</div>
+            <div class="button" id="metadataButton1600">Metadata</div>
         </div>
 
-        <div class="navbar navBar1475">
-            <div class="title">
-                Babylon.js Playground
+        <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('stable');">Stable</div>
+                </div>
             </div>
-            <div class="version" id="mainTitle">
+            <div class="button select">
+                <span class="examplesButton">Examples</span>
             </div>
+        </div>
+    </div>
 
-            <div class="category">
-                <div class="button run" id="runButton1475">Run
-                    <i class="fa fa-play" aria-hidden="true"></i>
-                </div>
+    <div class="navbar navBar1475">
+        <div class="title">
+            Babylon.js Playground
+        </div>
+        <div class="version" id="mainTitle">
+        </div>
+
+        <div class="category">
+            <div class="button run" id="runButton1475">Run
+                <i class="fa fa-play" aria-hidden="true"></i>
             </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>
+        <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 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 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 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 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 class="option" id='safemodeToggle1475'>Safe mode
-                            <i class="far fa-square" aria-hidden="true"></i>
-                        </div>
-                        <div class="option checked" id="editorButton1475">Editor
-                            <i class="fa fa-check-square" aria-hidden="true"></i>
+        <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 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="far fa-square" aria-hidden="true"></i>
+                    </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 class="option" id="debugButton1475">Inspector</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('stable');">Stable</div>
-                            </div>
+                    </div>
+                    <div class="option" id='safemodeToggle1475'>Safe mode
+                        <i class="far fa-square" 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="far fa-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="debugButton1475">Inspector</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('stable');">Stable</div>
                         </div>
                     </div>
                 </div>
             </div>
+        </div>
 
-            <div class="category right">
-                <div class="button select">
-                    <span class="examplesButton">Examples</span>
-                </div>
+        <div class="category right">
+            <div class="button select">
+                <span class="examplesButton">Examples</span>
             </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>
+    <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 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 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 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 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 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 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 class="option" id="safemodeToggle1030">Safe mode
-                            <i class="far fa-square" aria-hidden="true"></i>
+        <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 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="far fa-square" aria-hidden="true"></i>
+                    </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 class="option" id="debugButton1030">Inspector</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('stable');">Stable</div>
-                            </div>
+                    </div>
+                    <div class="option" id="safemodeToggle1030">Safe mode
+                        <i class="far fa-square" 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="far fa-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="debugButton1030">Inspector</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('stable');">Stable</div>
                         </div>
                     </div>
                 </div>
             </div>
+        </div>
 
-            <div class="category right">
-                <div class="button select">
-                    <span class="examplesButton">Examples</span>
-                </div>
+        <div class="category right">
+            <div class="button select">
+                <span class="examplesButton">Examples</span>
             </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>
+    </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>
                 </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>
-                        </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 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 class="option" id="safemodeToggle750">Safe mode
-                            <i class="far fa-square" 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="far fa-square" aria-hidden="true"></i>
+                    </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 class="option" id="debugButton750">Inspector</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('stable');">Stable</div>
-                            </div>
+                    </div>
+                    <div class="option" id="safemodeToggle750">Safe mode
+                        <i class="far fa-square" 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="far fa-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="debugButton750">Inspector</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('stable');">Stable</div>
                         </div>
                     </div>
                 </div>
             </div>
+        </div>
 
-            <div class="category right">
-                <div class="button select">
-                    <span class="examplesButton">Examples</span>
-                </div>
+        <div class="category right">
+            <div class="button select">
+                <span class="examplesButton">Examples</span>
             </div>
         </div>
+    </div>
 
-        <div class="wrapper">
-            <div id="jsEditor"></div>
-            <div id="canvasZone">
-                <canvas touch-action="none" id="renderCanvas"></canvas>
-            </div>
+    <div class="wrapper">
+        <div id="jsEditor"></div>
+        <div id="canvasZone">
+            <canvas touch-action="none" id="renderCanvas"></canvas>
         </div>
-        <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 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>
 
-        <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>
+    <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 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>
+                <div id="saveFormButtonOk" class="button">OK</div>
+                <div id="saveFormButtonCancel" class="button">Cancel</div>
             </div>
         </div>
+    </div>
 
-        <script src="https://code.jquery.com/jquery.js"></script>
+    <script src="https://code.jquery.com/jquery.js"></script>
 
-        <script>
-            Split(['#jsEditor', '#canvasZone']);
-        </script>
+    <script>
+        Split(['#jsEditor', '#canvasZone']);
+    </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>
+    <!-- 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);}
+        function gtag() { dataLayer.push(arguments); }
         gtag('js', new Date());
 
         gtag('config', 'UA-41767310-2');
-        </script>        
-    </body>
+    </script>
+</body>
 
-</html>
+</html>

+ 14 - 14
Playground/js/frame.js

@@ -1,5 +1,5 @@
-(function () {
-    var snippetUrl = "//babylonjs-api2.azurewebsites.net/snippets";
+(function() {
+    var snippetUrl = "https://snippet.babylonjs.com";
     var currentSnippetToken;
     var engine;
     var fpsLabel = document.getElementById("fpsLabel");
@@ -18,12 +18,12 @@
     }
 
     BABYLON.Engine.ShadersRepository = "/src/Shaders/";
-    var loadScript = function (scriptURL, title) {
+    var loadScript = function(scriptURL, title) {
         var xhr = new XMLHttpRequest();
 
         xhr.open('GET', scriptURL, true);
 
-        xhr.onreadystatechange = function () {
+        xhr.onreadystatechange = function() {
             if (xhr.readyState === 4) {
                 if (xhr.status === 200) {
                     blockEditorChange = true;
@@ -43,11 +43,11 @@
         xhr.send(null);
     };
 
-    var showError = function (error) {
+    var showError = function(error) {
         console.warn(error);
     };
 
-    compileAndRun = function (code) {
+    compileAndRun = function(code) {
         try {
 
             if (!BABYLON.Engine.isSupported()) {
@@ -67,7 +67,7 @@
             var createEngineFunction = "createDefaultEngine";
             var createSceneFunction;
 
-            var createDefaultEngine = function () {
+            var createDefaultEngine = function() {
                 return new BABYLON.Engine(canvas, true, { stencil: true });
             }
 
@@ -119,7 +119,7 @@
             }
 
             BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault = true;
-            engine.runRenderLoop(function () {
+            engine.runRenderLoop(function() {
                 if (engine.scenes.length === 0) {
                     return;
                 }
@@ -143,14 +143,14 @@
             // showError(e.message);
         }
     };
-    window.addEventListener("resize", function () {
+    window.addEventListener("resize", function() {
         if (engine) {
             engine.resize();
         }
     });
 
     // UI
-    var cleanHash = function () {
+    var cleanHash = function() {
         var splits = decodeURIComponent(location.hash.substr(1)).split("#");
 
         if (splits.length > 2) {
@@ -160,22 +160,22 @@
         location.hash = splits.join("#");
     };
 
-    var checkHash = function () {
+    var checkHash = function() {
         if (location.hash) {
             cleanHash();
 
             try {
                 var xmlHttp = new XMLHttpRequest();
-                xmlHttp.onreadystatechange = function () {
+                xmlHttp.onreadystatechange = function() {
                     if (xmlHttp.readyState === 4) {
                         if (xmlHttp.status === 200) {
-                            var snippetCode = JSON.parse(JSON.parse(xmlHttp.responseText)[0].jsonPayload).code;
+                            var snippetCode = JSON.parse(JSON.parse(xmlHttp.responseText).jsonPayload).code;
                             compileAndRun(snippetCode);
 
                             var refresh = document.getElementById("refresh");
 
                             if (refresh) {
-                                refresh.addEventListener("click", function () {
+                                refresh.addEventListener("click", function() {
                                     compileAndRun(snippetCode);
                                 });
                             }

+ 78 - 98
Playground/js/index.js

@@ -30,16 +30,16 @@ function showError(errorMessage, errorEvent) {
     document.getElementById("errorZone").innerHTML = errorContent;
 
     // Close button error
-    document.getElementById("errorZone").querySelector('.close').addEventListener('click', function () {
+    document.getElementById("errorZone").querySelector('.close').addEventListener('click', function() {
         document.getElementById("errorZone").style.display = 'none';
     });
 }
 
-(function () {
+(function() {
 
     var multipleSize = [1600, 1475, 1030, 750];
-    var setToMultipleID = function (id, thingToDo, param) {
-        multipleSize.forEach(function (size) {
+    var setToMultipleID = function(id, thingToDo, param) {
+        multipleSize.forEach(function(size) {
 
             if (thingToDo == "innerHTML") {
                 document.getElementById(id + size).innerHTML = param
@@ -76,7 +76,7 @@ function showError(errorMessage, errorEvent) {
         '.navbarBottom',
         '.navbarBottom .links .link'];
 
-    var run = function () {
+    var run = function() {
 
         // #region - Examples playgrounds
         var examplesButton = document.getElementsByClassName("examplesButton");
@@ -84,7 +84,7 @@ function showError(errorMessage, errorEvent) {
         if (examplesButton && examplesButton.length > 0) {
             var isExamplesDisplayed = false;
             for (var i = 0; i < examplesButton.length; i++) {
-                examplesButton[i].parentElement.onclick = function () {
+                examplesButton[i].parentElement.onclick = function() {
                     isExamplesDisplayed = !isExamplesDisplayed;
                     if (isExamplesDisplayed) {
                         document.getElementById("exampleList").style.display = "block";
@@ -102,7 +102,7 @@ function showError(errorMessage, errorEvent) {
         var filterBar = document.getElementById("filterBar");
         if (filterBar) {
             var filterBarClear = document.getElementById("filterBarClear");
-            var filter = function () {
+            var filter = function() {
                 var filterText = filterBar.value.toLowerCase();
                 if (filterText == "") filterBarClear.style.display = "none";
                 else filterBarClear.style.display = "inline-block";
@@ -132,10 +132,10 @@ function showError(errorMessage, errorEvent) {
                 if (displayCount == 0) document.getElementById("noResultsContainer").style.display = "block";
                 else document.getElementById("noResultsContainer").style.display = "none";
             }
-            filterBar.oninput = function () {
+            filterBar.oninput = function() {
                 filter();
             }
-            filterBarClear.onclick = function () {
+            filterBarClear.onclick = function() {
                 filterBar.value = "";
                 filter();
             }
@@ -144,7 +144,7 @@ function showError(errorMessage, errorEvent) {
 
         var blockEditorChange = false;
 
-        var markDirty = function () {
+        var markDirty = function() {
             if (blockEditorChange) {
                 return;
             }
@@ -155,11 +155,11 @@ function showError(errorMessage, errorEvent) {
             setToMultipleID('safemodeToggle', 'innerHTML', 'Safe mode <i class="fa fa-check-square" aria-hidden="true"></i>');
         }
 
-        jsEditor.onKeyUp(function (evt) {
+        jsEditor.onKeyUp(function(evt) {
             markDirty();
         });
 
-        var snippetUrl = "//babylonjs-api2.azurewebsites.net/snippets";
+        var snippetV3Url = "https://snippet.babylonjs.com"
         var currentSnippetToken;
         var currentSnippetTitle = null;
         var currentSnippetDescription = null;
@@ -176,7 +176,7 @@ function showError(errorMessage, errorEvent) {
             setToMultipleID("currentVersion", "innerHTML", "Version: Latest");
         }
 
-        var checkTypescriptSupport = function (xhr) {
+        var checkTypescriptSupport = function(xhr) {
             var filename = location.pathname.substring(location.pathname.lastIndexOf('/') + 1);
             if (xhr.responseText.indexOf("class Playground") !== -1) {// Typescript content
                 if (!filename) {
@@ -197,12 +197,12 @@ function showError(errorMessage, errorEvent) {
             return true;
         }
 
-        var loadScript = function (scriptURL, title) {
+        var loadScript = function(scriptURL, title) {
             var xhr = new XMLHttpRequest();
 
             xhr.open('GET', scriptURL, true);
 
-            xhr.onreadystatechange = function () {
+            xhr.onreadystatechange = function() {
                 if (xhr.readyState === 4) {
                     if (xhr.status === 200) {
 
@@ -227,20 +227,7 @@ function showError(errorMessage, errorEvent) {
             xhr.send(null);
         };
 
-        var loadScriptFromIndex = function (index) {
-            if (index === 0) {
-                index = 1;
-            }
-
-            var script = scripts[index - 1].trim();
-            loadScript("scripts/" + script + ".js", script);
-        }
-
-        var onScriptClick = function (evt) {
-            loadScriptFromIndex(evt.target.scriptLinkIndex);
-        };
-
-        var loadScriptsList = function () {
+        var loadScriptsList = function() {
 
             var exampleList = document.getElementById("exampleList");
 
@@ -253,7 +240,7 @@ function showError(errorMessage, errorEvent) {
                 xhr.open('GET', 'https://raw.githubusercontent.com/BabylonJS/Documentation/master/examples/list_ts.json', true);
             }
 
-            xhr.onreadystatechange = function () {
+            xhr.onreadystatechange = function() {
                 if (xhr.readyState === 4) {
                     if (xhr.status === 200) {
                         scripts = JSON.parse(xhr.response)["examples"];
@@ -344,8 +331,6 @@ function showError(errorMessage, errorEvent) {
                                 var query = queryString.replace("?", "");
                                 index = parseInt(query);
                                 if (!isNaN(index)) {
-                                    // Old examples
-                                    //loadScriptFromIndex(index);
                                     var newPG = "";
                                     switch (index) {
                                         case 1: newPG = "#TAZ2CB#0"; break; // Basic scene
@@ -400,7 +385,7 @@ function showError(errorMessage, errorEvent) {
                         toggleTheme(theme);
 
                         // Remove editor if window size is less than 850px
-                        var removeEditorForSmallScreen = function () {
+                        var removeEditorForSmallScreen = function() {
                             if (mq.matches) {
                                 splitInstance.collapse(0);
                             } else {
@@ -416,7 +401,7 @@ function showError(errorMessage, errorEvent) {
             xhr.send(null);
         }
 
-        var createNewScript = function () {
+        var createNewScript = function() {
             // check if checked is on
             let iCanClear = checkSafeMode("Are you sure you want to create a new playground?");
             if (!iCanClear) return;
@@ -436,7 +421,7 @@ function showError(errorMessage, errorEvent) {
             compileAndRun();
         }
 
-        var clear = function () {
+        var clear = function() {
             // check if checked is on
             let iCanClear = checkSafeMode("Are you sure you want to clear the playground?");
             if (!iCanClear) return;
@@ -447,7 +432,7 @@ function showError(errorMessage, errorEvent) {
             jsEditor.focus();
         }
 
-        var checkSafeMode = function (message) {
+        var checkSafeMode = function(message) {
             var safeToggle = document.getElementById("safemodeToggle1600");
             if (safeToggle.classList.contains('checked')) {
                 let confirm = window.confirm(message);
@@ -462,7 +447,7 @@ function showError(errorMessage, errorEvent) {
             }
         }
 
-        var showNoMetadata = function () {
+        var showNoMetadata = function() {
             if (currentSnippetTitle) {
                 document.getElementById("saveFormTitle").value = currentSnippetTitle;
                 document.getElementById("saveFormTitle").readOnly = true;
@@ -492,7 +477,7 @@ function showError(errorMessage, errorEvent) {
         };
         showNoMetadata();
 
-        var hideNoMetadata = function () {
+        var hideNoMetadata = function() {
             document.getElementById("saveFormTitle").readOnly = true;
             document.getElementById("saveFormDescription").readOnly = true;
             document.getElementById("saveFormTags").readOnly = true;
@@ -500,7 +485,7 @@ function showError(errorMessage, errorEvent) {
             setToMultipleID("metadataButton", "display", "inline-block");
         };
 
-        compileAndRun = function () {
+        compileAndRun = function() {
             try {
                 var waitRing = document.getElementById("waitDiv");
                 if (waitRing) {
@@ -553,8 +538,8 @@ function showError(errorMessage, errorEvent) {
                 var createEngineFunction = "createDefaultEngine";
                 var createSceneFunction;
 
-                getRunCode(jsEditor, function (code) {
-                    var createDefaultEngine = function () {
+                getRunCode(jsEditor, function(code) {
+                    var createDefaultEngine = function() {
                         return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
                     }
 
@@ -598,7 +583,7 @@ function showError(errorMessage, errorEvent) {
                         eval("scene = " + createSceneFunction + "()");
 
                         // if scene returns a promise avoid checks
-                        if(scene.then){
+                        if (scene.then) {
                             checkCamera = false
                             checkSceneCount = false
                         }
@@ -619,7 +604,7 @@ function showError(errorMessage, errorEvent) {
 
                     }
 
-                    engine.runRenderLoop(function () {
+                    engine.runRenderLoop(function() {
                         if (engine.scenes.length === 0) {
                             return;
                         }
@@ -637,7 +622,7 @@ function showError(errorMessage, errorEvent) {
                         fpsLabel.style.right = document.body.clientWidth - (jsEditor.domElement.clientWidth + canvas.clientWidth) + "px";
                         fpsLabel.innerHTML = engine.getFps().toFixed() + " fps";
                     });
-    
+
                     if (checkSceneCount && engine.scenes.length === 0) {
 
                         showError("You must at least create a scene.", null);
@@ -647,20 +632,20 @@ function showError(errorMessage, errorEvent) {
                     if (checkCamera && engine.scenes[0].activeCamera == null) {
                         showError("You must at least create a camera.", null);
                         return;
-                    }else if(scene.then){
-                        scene.then(function (){
+                    } else if (scene.then) {
+                        scene.then(function() {
                             document.getElementById("statusBar").innerHTML = "";
                         });
-                    }else{
-                        engine.scenes[0].executeWhenReady(function () {
+                    } else {
+                        engine.scenes[0].executeWhenReady(function() {
                             document.getElementById("statusBar").innerHTML = "";
                         });
-                    }           
+                    }
 
                     if (scene) {
                         if (showInspector) {
                             scene.debugLayer.show({ initialTab: initialTabIndex });
-                            scene.executeWhenReady(function () {
+                            scene.executeWhenReady(function() {
                                 scene.debugLayer._inspector.refresh();
                             })
                         } else if (showDebugLayer) {
@@ -676,7 +661,7 @@ function showError(errorMessage, errorEvent) {
             }
         };
         window.addEventListener("resize",
-            function () {
+            function() {
                 if (engine) {
                     engine.resize();
                 }
@@ -686,7 +671,7 @@ function showError(errorMessage, errorEvent) {
         loadScriptsList();
 
         // Zip
-        var addContentToZip = function (zip, name, url, replace, buffer, then) {
+        var addContentToZip = function(zip, name, url, replace, buffer, then) {
             if (url.substring(0, 5) == "http:" || url.substring(0, 5) == "blob:" || url.substring(0, 6) == "https:") {
                 then();
                 return;
@@ -700,7 +685,7 @@ function showError(errorMessage, errorEvent) {
                 xhr.responseType = "arraybuffer";
             }
 
-            xhr.onreadystatechange = function () {
+            xhr.onreadystatechange = function() {
                 if (xhr.readyState === 4) {
                     if (xhr.status === 200) {
                         var text;
@@ -728,7 +713,7 @@ function showError(errorMessage, errorEvent) {
             xhr.send(null);
         }
 
-        var addTexturesToZip = function (zip, index, textures, folder, then) {
+        var addTexturesToZip = function(zip, index, textures, folder, then) {
 
             if (index === textures.length) {
                 then();
@@ -775,7 +760,7 @@ function showError(errorMessage, errorEvent) {
                     url,
                     null,
                     true,
-                    function () {
+                    function() {
                         addTexturesToZip(zip, index + 1, textures, folder, then);
                     });
             }
@@ -784,7 +769,7 @@ function showError(errorMessage, errorEvent) {
             }
         }
 
-        var addImportedFilesToZip = function (zip, index, importedFiles, folder, then) {
+        var addImportedFilesToZip = function(zip, index, importedFiles, folder, then) {
             if (index === importedFiles.length) {
                 then();
                 return;
@@ -802,12 +787,12 @@ function showError(errorMessage, errorEvent) {
                 url,
                 null,
                 true,
-                function () {
+                function() {
                     addImportedFilesToZip(zip, index + 1, importedFiles, folder, then);
                 });
         }
 
-        var getZip = function () {
+        var getZip = function() {
             if (engine.scenes.length === 0) {
                 return;
             }
@@ -831,17 +816,17 @@ function showError(errorMessage, errorEvent) {
                 "zipContent/index.html",
                 zipCode,
                 false,
-                function () {
+                function() {
                     addTexturesToZip(zip,
                         0,
                         textures,
                         null,
-                        function () {
+                        function() {
                             addImportedFilesToZip(zip,
                                 0,
                                 importedFiles,
                                 null,
-                                function () {
+                                function() {
                                     var blob = zip.generate({ type: "blob" });
                                     saveAs(blob, "sample.zip");
                                     document.getElementById("statusBar").innerHTML = "";
@@ -851,7 +836,7 @@ function showError(errorMessage, errorEvent) {
         }
 
         // Versions
-        setVersion = function (version) {
+        setVersion = function(version) {
             switch (version) {
                 case "stable":
                     location.href = "indexStable.html" + location.hash;
@@ -863,35 +848,35 @@ function showError(errorMessage, errorEvent) {
         }
 
         // Fonts
-        setFontSize = function (size) {
+        setFontSize = function(size) {
             fontSize = size;
             jsEditor.updateOptions({ fontSize: size });
             setToMultipleID("currentFontSize", "innerHTML", "Font: " + size);
         };
 
         // Fullscreen
-        document.getElementById("renderCanvas").addEventListener("webkitfullscreenchange", function () {
+        document.getElementById("renderCanvas").addEventListener("webkitfullscreenchange", function() {
             if (document.webkitIsFullScreen) goFullPage();
             else exitFullPage();
         }, false);
 
-        var goFullPage = function () {
+        var goFullPage = function() {
             var canvasElement = document.getElementById("renderCanvas");
             canvasElement.style.position = "absolute";
             canvasElement.style.top = 0;
             canvasElement.style.left = 0;
             canvasElement.style.zIndex = 100;
         }
-        var exitFullPage = function () {
+        var exitFullPage = function() {
             document.getElementById("renderCanvas").style.position = "relative";
             document.getElementById("renderCanvas").style.zIndex = 0;
         }
-        var goFullscreen = function () {
+        var goFullscreen = function() {
             if (engine) {
                 engine.switchFullscreen(true);
             }
         }
-        var editorGoFullscreen = function () {
+        var editorGoFullscreen = function() {
             var editorDiv = document.getElementById("jsEditor");
             if (editorDiv.requestFullscreen) {
                 editorDiv.requestFullscreen();
@@ -903,7 +888,7 @@ function showError(errorMessage, errorEvent) {
 
         }
 
-        var toggleEditor = function () {
+        var toggleEditor = function() {
             var editorButton = document.getElementById("editorButton1600");
             var scene = engine.scenes[0];
 
@@ -928,7 +913,7 @@ function showError(errorMessage, errorEvent) {
         /**
          * Toggle the dark theme
          */
-        var toggleTheme = function (theme) {
+        var toggleTheme = function(theme) {
             // Monaco
             var vsTheme;
             if (theme == 'dark') {
@@ -963,7 +948,7 @@ function showError(errorMessage, errorEvent) {
             jsEditor.setValue(oldCode);
             setFontSize(fontSize);
 
-            jsEditor.onKeyUp(function (evt) {
+            jsEditor.onKeyUp(function(evt) {
                 markDirty();
             });
 
@@ -981,7 +966,7 @@ function showError(errorMessage, errorEvent) {
             localStorage.setItem("bjs-playground-theme", theme);
         }
 
-        var toggleDebug = function () {
+        var toggleDebug = function() {
             // Always showing the debug layer, because you can close it by itself
             var scene = engine.scenes[0];
             if (document.getElementsByClassName("insp-right-panel")[0]) {
@@ -993,16 +978,16 @@ function showError(errorMessage, errorEvent) {
             }
         }
 
-        var toggleMetadata = function () {
+        var toggleMetadata = function() {
             var scene = engine.scenes[0];
             document.getElementById("saveLayer").style.display = "block";
         }
 
-        var formatCode = function () {
+        var formatCode = function() {
             jsEditor.getAction('editor.action.format').run();
         }
 
-        var toggleMinimap = function () {
+        var toggleMinimap = function() {
             var minimapToggle = document.getElementById("minimapToggle1600");
             if (minimapToggle.classList.contains('checked')) {
                 jsEditor.updateOptions({ minimap: { enabled: false } });
@@ -1016,7 +1001,7 @@ function showError(errorMessage, errorEvent) {
 
 
         //Navigation Overwrites
-        var exitPrompt = function (e) {
+        var exitPrompt = function(e) {
             var safeToggle = document.getElementById("safemodeToggle1600");
             if (safeToggle.classList.contains('checked')) {
                 e = e || window.event;
@@ -1032,7 +1017,7 @@ function showError(errorMessage, errorEvent) {
         window.onbeforeunload = exitPrompt;
 
         // Snippet
-        var save = function () {
+        var save = function() {
 
             // Retrieve title if necessary
             if (document.getElementById("saveLayer")) {
@@ -1042,9 +1027,9 @@ function showError(errorMessage, errorEvent) {
             }
 
             var xmlHttp = new XMLHttpRequest();
-            xmlHttp.onreadystatechange = function () {
+            xmlHttp.onreadystatechange = function() {
                 if (xmlHttp.readyState === 4) {
-                    if (xmlHttp.status === 201) {
+                    if (xmlHttp.status === 200) {
                         var baseUrl = location.href.replace(location.hash, "").replace(location.search, "");
                         var snippet = JSON.parse(xmlHttp.responseText);
                         var newUrl = baseUrl + "#" + snippet.id;
@@ -1062,13 +1047,13 @@ function showError(errorMessage, errorEvent) {
                 }
             }
 
-            xmlHttp.open("POST", snippetUrl + (currentSnippetToken ? "/" + currentSnippetToken : ""), true);
+            xmlHttp.open("POST", snippetV3Url + (currentSnippetToken ? "/" + currentSnippetToken : ""), true);
             xmlHttp.setRequestHeader("Content-Type", "application/json");
 
             var dataToSend = {
-                payload: {
+                payload: JSON.stringify({
                     code: jsEditor.getValue()
-                },
+                }),
                 name: currentSnippetTitle,
                 description: currentSnippetDescription,
                 tags: currentSnippetTags
@@ -1077,7 +1062,7 @@ function showError(errorMessage, errorEvent) {
             xmlHttp.send(JSON.stringify(dataToSend));
         }
 
-        var askForSave = function () {
+        var askForSave = function() {
             if (currentSnippetTitle == null
                 || currentSnippetDescription == null
                 || currentSnippetTags == null) {
@@ -1088,18 +1073,18 @@ function showError(errorMessage, errorEvent) {
                 save();
             }
         };
-        document.getElementById("saveFormButtonOk").addEventListener("click", function () {
+        document.getElementById("saveFormButtonOk").addEventListener("click", function() {
             document.getElementById("saveLayer").style.display = "none";
             save();
         });
-        document.getElementById("saveFormButtonCancel").addEventListener("click", function () {
+        document.getElementById("saveFormButtonCancel").addEventListener("click", function() {
             document.getElementById("saveLayer").style.display = "none";
         });
         document.getElementById("mainTitle").innerHTML = "v" + BABYLON.Engine.Version;
 
         var previousHash = "";
 
-        var cleanHash = function () {
+        var cleanHash = function() {
             var splits = decodeURIComponent(location.hash.substr(1)).split("#");
 
             if (splits.length > 2) {
@@ -1109,7 +1094,7 @@ function showError(errorMessage, errorEvent) {
             location.hash = splits.join("#");
         }
 
-        var checkHash = function (firstTime) {
+        var checkHash = function(firstTime) {
             if (location.hash) {
                 if (previousHash !== location.hash) {
                     cleanHash();
@@ -1118,7 +1103,7 @@ function showError(errorMessage, errorEvent) {
 
                     try {
                         var xmlHttp = new XMLHttpRequest();
-                        xmlHttp.onreadystatechange = function () {
+                        xmlHttp.onreadystatechange = function() {
                             if (xmlHttp.readyState === 4) {
                                 if (xmlHttp.status === 200) {
 
@@ -1126,7 +1111,7 @@ function showError(errorMessage, errorEvent) {
                                         return;
                                     }
 
-                                    var snippet = JSON.parse(xmlHttp.responseText)[0];
+                                    var snippet = JSON.parse(xmlHttp.responseText);
 
                                     blockEditorChange = true;
                                     jsEditor.setValue(JSON.parse(snippet.jsonPayload).code.toString());
@@ -1166,11 +1151,6 @@ function showError(errorMessage, errorEvent) {
                                     compileAndRun();
 
                                     // setToMultipleID("currentScript", "innerHTML", "Custom");
-                                } else if (firstTime) {
-                                    location.href = location.href.replace(location.hash, "");
-                                    if (scripts) {
-                                        loadScriptFromIndex(0);
-                                    }
                                 }
                             }
                         };
@@ -1180,7 +1160,7 @@ function showError(errorMessage, errorEvent) {
                         if (!hash.split("#")[1]) hash += "#0";
 
 
-                        xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));
+                        xmlHttp.open("GET", snippetV3Url + "/" + hash.replace("#", "/"));
                         xmlHttp.send();
                     } catch (e) {
 
@@ -1209,7 +1189,7 @@ function showError(errorMessage, errorEvent) {
         setToMultipleID("darkTheme", "click", toggleTheme.bind(this, 'dark'));
         setToMultipleID("lightTheme", "click", toggleTheme.bind(this, 'light'));
         // Safe mode
-        setToMultipleID("safemodeToggle", 'click', function () {
+        setToMultipleID("safemodeToggle", 'click', function() {
             document.getElementById("safemodeToggle1600").classList.toggle('checked');
             if (document.getElementById("safemodeToggle1600").classList.contains('checked')) {
                 setToMultipleID("safemodeToggle", "innerHTML", 'Safe mode <i class="fa fa-check-square" aria-hidden="true"></i>');
@@ -1245,11 +1225,11 @@ function showError(errorMessage, errorEvent) {
 
     xhr.open('GET', "babylon.d.txt", true);
 
-    xhr.onreadystatechange = function () {
+    xhr.onreadystatechange = function() {
         if (xhr.readyState === 4) {
             if (xhr.status === 200) {
                 require.config({ paths: { 'vs': 'node_modules/monaco-editor/min/vs' } });
-                require(['vs/editor/editor.main'], function () {
+                require(['vs/editor/editor.main'], function() {
                     if (monacoMode === "javascript") {
                         monaco.languages.typescript.javascriptDefaults.addExtraLib(xhr.responseText, 'babylon.d.ts');
                     } else {

文件差异内容过多而无法显示
+ 916 - 0
Viewer/dist/4ff3a89403672639e15d.js


文件差异内容过多而无法显示
+ 183 - 0
Viewer/dist/e45de3ab9c569c68ab0c.js


文件差异内容过多而无法显示
+ 5488 - 5476
dist/preview release/babylon.d.ts


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/babylon.js


文件差异内容过多而无法显示
+ 514 - 603
dist/preview release/babylon.max.js


文件差异内容过多而无法显示
+ 514 - 603
dist/preview release/babylon.no-module.max.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/babylon.worker.js


文件差异内容过多而无法显示
+ 514 - 603
dist/preview release/es6.js


+ 117 - 45
dist/preview release/gui/babylon.gui.d.ts

@@ -338,6 +338,14 @@ declare module BABYLON.GUI {
                 */
             copyFrom(other: Measure): void;
             /**
+                * Copy from a group of 4 floats
+                * @param left defines left coordinate
+                * @param top defines top coordinate
+                * @param width defines width dimension
+                * @param height defines height dimension
+                */
+            copyFromFloats(left: number, top: number, width: number, height: number): void;
+            /**
                 * Check equality between this measure and another one
                 * @param other defines the other measures
                 * @returns true if both measures are equals
@@ -1310,6 +1318,14 @@ declare module BABYLON.GUI {
     export class Image extends Control {
             name?: string | undefined;
             /**
+                * BABYLON.Observable notified when the content is loaded
+                */
+            onImageLoadedObservable: BABYLON.Observable<Image>;
+            /**
+                * Gets a boolean indicating that the content is loaded
+                */
+            readonly isLoaded: boolean;
+            /**
                 * Gets or sets the left coordinate in the source image
                 */
             sourceLeft: number;
@@ -1365,6 +1381,7 @@ declare module BABYLON.GUI {
             /** Force the control to synchronize with its content */
             synchronizeSizeWithContent(): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+            dispose(): void;
             /** STRETCH_NONE */
             static readonly STRETCH_NONE: number;
             /** STRETCH_FILL */
@@ -1994,51 +2011,6 @@ declare module BABYLON.GUI {
     }
 }
 declare module BABYLON.GUI {
-    /**
-        * Class used to create slider controls
-        */
-    export class Slider extends Control {
-            name?: string | undefined;
-            /** BABYLON.Observable raised when the sldier value changes */
-            onValueChangedObservable: BABYLON.Observable<number>;
-            /** Gets or sets border color */
-            borderColor: string;
-            /** Gets or sets background color */
-            background: string;
-            /** Gets or sets main bar offset */
-            barOffset: string | number;
-            /** Gets main bar offset in pixels*/
-            readonly barOffsetInPixels: number;
-            /** Gets or sets thumb width */
-            thumbWidth: string | number;
-            /** Gets thumb width in pixels */
-            readonly thumbWidthInPixels: number;
-            /** Gets or sets minimum value */
-            minimum: number;
-            /** Gets or sets maximum value */
-            maximum: number;
-            /** Gets or sets current value */
-            value: number;
-            /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
-            isVertical: boolean;
-            /** Gets or sets a boolean indicating if the thumb should be round or square */
-            isThumbCircle: boolean;
-            /** Gets or sets a value indicating if the thumb can go over main bar extends */
-            isThumbClamped: boolean;
-            /**
-                * Creates a new Slider
-                * @param name defines the control name
-                */
-            constructor(name?: string | undefined);
-            protected _getTypeName(): string;
-            protected _getThumbThickness(type: string, backgroundLength: number): number;
-            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-            _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
-            _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
-            _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
-    }
-}
-declare module BABYLON.GUI {
     /** Class used to create rectangle container */
     export class Rectangle extends Container {
             name?: string | undefined;
@@ -2092,6 +2064,106 @@ declare module BABYLON.GUI {
 }
 declare module BABYLON.GUI {
     /**
+        * Class used to create slider controls
+        */
+    export class BaseSlider extends Control {
+            name?: string | undefined;
+            protected _thumbWidth: ValueAndUnit;
+            protected _barOffset: ValueAndUnit;
+            protected _effectiveBarOffset: number;
+            protected _renderLeft: number;
+            protected _renderTop: number;
+            protected _renderWidth: number;
+            protected _renderHeight: number;
+            protected _backgroundBoxLength: number;
+            protected _backgroundBoxThickness: number;
+            protected _effectiveThumbThickness: number;
+            /** BABYLON.Observable raised when the sldier value changes */
+            onValueChangedObservable: BABYLON.Observable<number>;
+            /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
+            barOffset: string | number;
+            /** Gets main bar offset in pixels*/
+            readonly barOffsetInPixels: number;
+            /** Gets or sets thumb width */
+            thumbWidth: string | number;
+            /** Gets thumb width in pixels */
+            readonly thumbWidthInPixels: number;
+            /** Gets or sets minimum value */
+            minimum: number;
+            /** Gets or sets maximum value */
+            maximum: number;
+            /** Gets or sets current value */
+            value: number;
+            /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
+            isVertical: boolean;
+            /** Gets or sets a value indicating if the thumb can go over main bar extends */
+            isThumbClamped: boolean;
+            /**
+                * Creates a new BaseSlider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            protected _getThumbPosition(): number;
+            protected _getThumbThickness(type: string): number;
+            protected _prepareRenderingData(type: string): void;
+            _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
+            _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+            _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
+        * Class used to create slider controls
+        */
+    export class Slider extends BaseSlider {
+            name?: string | undefined;
+            /** Gets or sets a boolean indicating if the thumb must be rendered */
+            displayThumb: boolean;
+            /** Gets or sets border color */
+            borderColor: string;
+            /** Gets or sets background color */
+            background: string;
+            /** Gets or sets a boolean indicating if the thumb should be round or square */
+            isThumbCircle: boolean;
+            /**
+                * Creates a new Slider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
+        * Class used to create slider controls based on images
+        */
+    export class ImageBasedSlider extends BaseSlider {
+            name?: string | undefined;
+            /**
+                * Gets or sets the image used to render the background
+                */
+            backgroundImage: Image;
+            /**
+                * Gets or sets the image used to render the value bar
+                */
+            valueBarImage: Image;
+            /**
+                * Gets or sets the image used to render the thumb
+                */
+            thumbImage: Image;
+            /**
+                * Creates a new ImageBasedSlider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
       * Forcing an export so that this code will execute
       * @hidden
       */

文件差异内容过多而无法显示
+ 585 - 304
dist/preview release/gui/babylon.gui.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


+ 249 - 96
dist/preview release/gui/babylon.gui.module.d.ts

@@ -42,9 +42,11 @@ declare module 'babylonjs-gui/2D/controls' {
     export * from "babylonjs-gui/2D/controls/selector";
     export * from "babylonjs-gui/2D/controls/textBlock";
     export * from "babylonjs-gui/2D/controls/virtualKeyboard";
-    export * from "babylonjs-gui/2D/controls/slider";
     export * from "babylonjs-gui/2D/controls/rectangle";
     export * from "babylonjs-gui/2D/controls/displayGrid";
+    export * from "babylonjs-gui/2D/controls/baseSlider";
+    export * from "babylonjs-gui/2D/controls/slider";
+    export * from "babylonjs-gui/2D/controls/imageBasedSlider";
     export * from "babylonjs-gui/2D/controls/statics";
 }
 
@@ -392,6 +394,14 @@ declare module 'babylonjs-gui/2D/measure' {
                 */
             copyFrom(other: Measure): void;
             /**
+                * Copy from a group of 4 floats
+                * @param left defines left coordinate
+                * @param top defines top coordinate
+                * @param width defines width dimension
+                * @param height defines height dimension
+                */
+            copyFromFloats(left: number, top: number, width: number, height: number): void;
+            /**
                 * Check equality between this measure and another one
                 * @param other defines the other measures
                 * @returns true if both measures are equals
@@ -1430,7 +1440,7 @@ declare module 'babylonjs-gui/2D/controls/grid' {
 
 declare module 'babylonjs-gui/2D/controls/image' {
     import { Control } from "babylonjs-gui/2D/controls/control";
-    import { Nullable } from "babylonjs";
+    import { Nullable, Observable } from "babylonjs";
     import { Measure } from "babylonjs-gui/2D/measure";
     /**
         * Class used to create 2D images
@@ -1438,6 +1448,14 @@ declare module 'babylonjs-gui/2D/controls/image' {
     export class Image extends Control {
             name?: string | undefined;
             /**
+                * Observable notified when the content is loaded
+                */
+            onImageLoadedObservable: Observable<Image>;
+            /**
+                * Gets a boolean indicating that the content is loaded
+                */
+            readonly isLoaded: boolean;
+            /**
                 * Gets or sets the left coordinate in the source image
                 */
             sourceLeft: number;
@@ -1493,6 +1511,7 @@ declare module 'babylonjs-gui/2D/controls/image' {
             /** Force the control to synchronize with its content */
             synchronizeSizeWithContent(): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+            dispose(): void;
             /** STRETCH_NONE */
             static readonly STRETCH_NONE: number;
             /** STRETCH_FILL */
@@ -2158,55 +2177,6 @@ declare module 'babylonjs-gui/2D/controls/virtualKeyboard' {
     }
 }
 
-declare module 'babylonjs-gui/2D/controls/slider' {
-    import { Control } from "babylonjs-gui/2D/controls/control";
-    import { Observable, Vector2 } from "babylonjs";
-    import { Measure } from "babylonjs-gui/2D/measure";
-    /**
-        * Class used to create slider controls
-        */
-    export class Slider extends Control {
-            name?: string | undefined;
-            /** Observable raised when the sldier value changes */
-            onValueChangedObservable: Observable<number>;
-            /** Gets or sets border color */
-            borderColor: string;
-            /** Gets or sets background color */
-            background: string;
-            /** Gets or sets main bar offset */
-            barOffset: string | number;
-            /** Gets main bar offset in pixels*/
-            readonly barOffsetInPixels: number;
-            /** Gets or sets thumb width */
-            thumbWidth: string | number;
-            /** Gets thumb width in pixels */
-            readonly thumbWidthInPixels: number;
-            /** Gets or sets minimum value */
-            minimum: number;
-            /** Gets or sets maximum value */
-            maximum: number;
-            /** Gets or sets current value */
-            value: number;
-            /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
-            isVertical: boolean;
-            /** Gets or sets a boolean indicating if the thumb should be round or square */
-            isThumbCircle: boolean;
-            /** Gets or sets a value indicating if the thumb can go over main bar extends */
-            isThumbClamped: boolean;
-            /**
-                * Creates a new Slider
-                * @param name defines the control name
-                */
-            constructor(name?: string | undefined);
-            protected _getTypeName(): string;
-            protected _getThumbThickness(type: string, backgroundLength: number): number;
-            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-            _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-            _onPointerMove(target: Control, coordinates: Vector2): void;
-            _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
-    }
-}
-
 declare module 'babylonjs-gui/2D/controls/rectangle' {
     import { Container } from "babylonjs-gui/2D/controls/container";
     import { Measure } from "babylonjs-gui/2D/measure";
@@ -2265,6 +2235,117 @@ declare module 'babylonjs-gui/2D/controls/displayGrid' {
     }
 }
 
+declare module 'babylonjs-gui/2D/controls/baseSlider' {
+    import { Control } from "babylonjs-gui/2D/controls/control";
+    import { ValueAndUnit } from "babylonjs-gui/2D/valueAndUnit";
+    import { Observable, Vector2 } from "babylonjs";
+    /**
+        * Class used to create slider controls
+        */
+    export class BaseSlider extends Control {
+            name?: string | undefined;
+            protected _thumbWidth: ValueAndUnit;
+            protected _barOffset: ValueAndUnit;
+            protected _effectiveBarOffset: number;
+            protected _renderLeft: number;
+            protected _renderTop: number;
+            protected _renderWidth: number;
+            protected _renderHeight: number;
+            protected _backgroundBoxLength: number;
+            protected _backgroundBoxThickness: number;
+            protected _effectiveThumbThickness: number;
+            /** Observable raised when the sldier value changes */
+            onValueChangedObservable: Observable<number>;
+            /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
+            barOffset: string | number;
+            /** Gets main bar offset in pixels*/
+            readonly barOffsetInPixels: number;
+            /** Gets or sets thumb width */
+            thumbWidth: string | number;
+            /** Gets thumb width in pixels */
+            readonly thumbWidthInPixels: number;
+            /** Gets or sets minimum value */
+            minimum: number;
+            /** Gets or sets maximum value */
+            maximum: number;
+            /** Gets or sets current value */
+            value: number;
+            /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
+            isVertical: boolean;
+            /** Gets or sets a value indicating if the thumb can go over main bar extends */
+            isThumbClamped: boolean;
+            /**
+                * Creates a new BaseSlider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            protected _getThumbPosition(): number;
+            protected _getThumbThickness(type: string): number;
+            protected _prepareRenderingData(type: string): void;
+            _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
+            _onPointerMove(target: Control, coordinates: Vector2): void;
+            _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
+    }
+}
+
+declare module 'babylonjs-gui/2D/controls/slider' {
+    import { Measure } from "babylonjs-gui/2D/measure";
+    import { BaseSlider } from "babylonjs-gui/2D/controls/baseSlider";
+    /**
+        * Class used to create slider controls
+        */
+    export class Slider extends BaseSlider {
+            name?: string | undefined;
+            /** Gets or sets a boolean indicating if the thumb must be rendered */
+            displayThumb: boolean;
+            /** Gets or sets border color */
+            borderColor: string;
+            /** Gets or sets background color */
+            background: string;
+            /** Gets or sets a boolean indicating if the thumb should be round or square */
+            isThumbCircle: boolean;
+            /**
+                * Creates a new Slider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+    }
+}
+
+declare module 'babylonjs-gui/2D/controls/imageBasedSlider' {
+    import { BaseSlider } from "babylonjs-gui/2D/controls/baseSlider";
+    import { Measure } from "babylonjs-gui/2D/measure";
+    import { Image } from "babylonjs-gui/2D/controls/image";
+    /**
+        * Class used to create slider controls based on images
+        */
+    export class ImageBasedSlider extends BaseSlider {
+            name?: string | undefined;
+            /**
+                * Gets or sets the image used to render the background
+                */
+            backgroundImage: Image;
+            /**
+                * Gets or sets the image used to render the value bar
+                */
+            valueBarImage: Image;
+            /**
+                * Gets or sets the image used to render the thumb
+                */
+            thumbImage: Image;
+            /**
+                * Creates a new ImageBasedSlider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+    }
+}
+
 declare module 'babylonjs-gui/2D/controls/statics' {
     /**
       * Forcing an export so that this code will execute
@@ -3183,6 +3264,14 @@ declare module BABYLON.GUI {
                 */
             copyFrom(other: Measure): void;
             /**
+                * Copy from a group of 4 floats
+                * @param left defines left coordinate
+                * @param top defines top coordinate
+                * @param width defines width dimension
+                * @param height defines height dimension
+                */
+            copyFromFloats(left: number, top: number, width: number, height: number): void;
+            /**
                 * Check equality between this measure and another one
                 * @param other defines the other measures
                 * @returns true if both measures are equals
@@ -4155,6 +4244,14 @@ declare module BABYLON.GUI {
     export class Image extends Control {
             name?: string | undefined;
             /**
+                * BABYLON.Observable notified when the content is loaded
+                */
+            onImageLoadedObservable: BABYLON.Observable<Image>;
+            /**
+                * Gets a boolean indicating that the content is loaded
+                */
+            readonly isLoaded: boolean;
+            /**
                 * Gets or sets the left coordinate in the source image
                 */
             sourceLeft: number;
@@ -4210,6 +4307,7 @@ declare module BABYLON.GUI {
             /** Force the control to synchronize with its content */
             synchronizeSizeWithContent(): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+            dispose(): void;
             /** STRETCH_NONE */
             static readonly STRETCH_NONE: number;
             /** STRETCH_FILL */
@@ -4839,51 +4937,6 @@ declare module BABYLON.GUI {
     }
 }
 declare module BABYLON.GUI {
-    /**
-        * Class used to create slider controls
-        */
-    export class Slider extends Control {
-            name?: string | undefined;
-            /** BABYLON.Observable raised when the sldier value changes */
-            onValueChangedObservable: BABYLON.Observable<number>;
-            /** Gets or sets border color */
-            borderColor: string;
-            /** Gets or sets background color */
-            background: string;
-            /** Gets or sets main bar offset */
-            barOffset: string | number;
-            /** Gets main bar offset in pixels*/
-            readonly barOffsetInPixels: number;
-            /** Gets or sets thumb width */
-            thumbWidth: string | number;
-            /** Gets thumb width in pixels */
-            readonly thumbWidthInPixels: number;
-            /** Gets or sets minimum value */
-            minimum: number;
-            /** Gets or sets maximum value */
-            maximum: number;
-            /** Gets or sets current value */
-            value: number;
-            /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
-            isVertical: boolean;
-            /** Gets or sets a boolean indicating if the thumb should be round or square */
-            isThumbCircle: boolean;
-            /** Gets or sets a value indicating if the thumb can go over main bar extends */
-            isThumbClamped: boolean;
-            /**
-                * Creates a new Slider
-                * @param name defines the control name
-                */
-            constructor(name?: string | undefined);
-            protected _getTypeName(): string;
-            protected _getThumbThickness(type: string, backgroundLength: number): number;
-            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-            _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
-            _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
-            _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
-    }
-}
-declare module BABYLON.GUI {
     /** Class used to create rectangle container */
     export class Rectangle extends Container {
             name?: string | undefined;
@@ -4937,6 +4990,106 @@ declare module BABYLON.GUI {
 }
 declare module BABYLON.GUI {
     /**
+        * Class used to create slider controls
+        */
+    export class BaseSlider extends Control {
+            name?: string | undefined;
+            protected _thumbWidth: ValueAndUnit;
+            protected _barOffset: ValueAndUnit;
+            protected _effectiveBarOffset: number;
+            protected _renderLeft: number;
+            protected _renderTop: number;
+            protected _renderWidth: number;
+            protected _renderHeight: number;
+            protected _backgroundBoxLength: number;
+            protected _backgroundBoxThickness: number;
+            protected _effectiveThumbThickness: number;
+            /** BABYLON.Observable raised when the sldier value changes */
+            onValueChangedObservable: BABYLON.Observable<number>;
+            /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
+            barOffset: string | number;
+            /** Gets main bar offset in pixels*/
+            readonly barOffsetInPixels: number;
+            /** Gets or sets thumb width */
+            thumbWidth: string | number;
+            /** Gets thumb width in pixels */
+            readonly thumbWidthInPixels: number;
+            /** Gets or sets minimum value */
+            minimum: number;
+            /** Gets or sets maximum value */
+            maximum: number;
+            /** Gets or sets current value */
+            value: number;
+            /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
+            isVertical: boolean;
+            /** Gets or sets a value indicating if the thumb can go over main bar extends */
+            isThumbClamped: boolean;
+            /**
+                * Creates a new BaseSlider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            protected _getThumbPosition(): number;
+            protected _getThumbThickness(type: string): number;
+            protected _prepareRenderingData(type: string): void;
+            _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
+            _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+            _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
+        * Class used to create slider controls
+        */
+    export class Slider extends BaseSlider {
+            name?: string | undefined;
+            /** Gets or sets a boolean indicating if the thumb must be rendered */
+            displayThumb: boolean;
+            /** Gets or sets border color */
+            borderColor: string;
+            /** Gets or sets background color */
+            background: string;
+            /** Gets or sets a boolean indicating if the thumb should be round or square */
+            isThumbCircle: boolean;
+            /**
+                * Creates a new Slider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
+        * Class used to create slider controls based on images
+        */
+    export class ImageBasedSlider extends BaseSlider {
+            name?: string | undefined;
+            /**
+                * Gets or sets the image used to render the background
+                */
+            backgroundImage: Image;
+            /**
+                * Gets or sets the image used to render the value bar
+                */
+            valueBarImage: Image;
+            /**
+                * Gets or sets the image used to render the thumb
+                */
+            thumbImage: Image;
+            /**
+                * Creates a new ImageBasedSlider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
       * Forcing an export so that this code will execute
       * @hidden
       */

+ 4 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -2942,6 +2942,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this._endPerformanceCounter("Validate JSON");
             _this.onValidatedObservable.notifyObservers(result);
             _this.onValidatedObservable.clear();
+        }, function (reason) {
+            _this._endPerformanceCounter("Validate JSON");
+            babylonjs_1.Tools.Warn("Failed to validate: " + reason);
+            _this.onValidatedObservable.clear();
         });
     };
     GLTFFileLoader.prototype._getLoader = function (loaderData) {

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.js.map


+ 4 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.min.js

@@ -2942,6 +2942,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this._endPerformanceCounter("Validate JSON");
             _this.onValidatedObservable.notifyObservers(result);
             _this.onValidatedObservable.clear();
+        }, function (reason) {
+            _this._endPerformanceCounter("Validate JSON");
+            babylonjs_1.Tools.Warn("Failed to validate: " + reason);
+            _this.onValidatedObservable.clear();
         });
     };
     GLTFFileLoader.prototype._getLoader = function (loaderData) {

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js.map


+ 8 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -3136,7 +3136,8 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto = 0;
+/** @hidden */
+exports.__IGLTFLoaderExtensionV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -3151,7 +3152,8 @@ exports.toto = 0;
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto1 = 0;
+/** @hidden */
+exports.__IGLTFLoaderInterfacesV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -3686,6 +3688,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this._endPerformanceCounter("Validate JSON");
             _this.onValidatedObservable.notifyObservers(result);
             _this.onValidatedObservable.clear();
+        }, function (reason) {
+            _this._endPerformanceCounter("Validate JSON");
+            babylonjs_1.Tools.Warn("Failed to validate: " + reason);
+            _this.onValidatedObservable.clear();
         });
     };
     GLTFFileLoader.prototype._getLoader = function (loaderData) {

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js.map


+ 8 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js

@@ -3136,7 +3136,8 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto = 0;
+/** @hidden */
+exports.__IGLTFLoaderExtensionV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -3151,7 +3152,8 @@ exports.toto = 0;
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto1 = 0;
+/** @hidden */
+exports.__IGLTFLoaderInterfacesV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -3686,6 +3688,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this._endPerformanceCounter("Validate JSON");
             _this.onValidatedObservable.notifyObservers(result);
             _this.onValidatedObservable.clear();
+        }, function (reason) {
+            _this._endPerformanceCounter("Validate JSON");
+            babylonjs_1.Tools.Warn("Failed to validate: " + reason);
+            _this.onValidatedObservable.clear();
         });
     };
     GLTFFileLoader.prototype._getLoader = function (loaderData) {

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js.map


+ 8 - 2
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -5412,7 +5412,8 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto = 0;
+/** @hidden */
+exports.__IGLTFLoaderExtensionV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -5427,7 +5428,8 @@ exports.toto = 0;
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto1 = 0;
+/** @hidden */
+exports.__IGLTFLoaderInterfacesV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -5962,6 +5964,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this._endPerformanceCounter("Validate JSON");
             _this.onValidatedObservable.notifyObservers(result);
             _this.onValidatedObservable.clear();
+        }, function (reason) {
+            _this._endPerformanceCounter("Validate JSON");
+            babylonjs_1.Tools.Warn("Failed to validate: " + reason);
+            _this.onValidatedObservable.clear();
         });
     };
     GLTFFileLoader.prototype._getLoader = function (loaderData) {

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js.map


+ 8 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js

@@ -5412,7 +5412,8 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto = 0;
+/** @hidden */
+exports.__IGLTFLoaderExtensionV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -5427,7 +5428,8 @@ exports.toto = 0;
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto1 = 0;
+/** @hidden */
+exports.__IGLTFLoaderInterfacesV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -5962,6 +5964,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this._endPerformanceCounter("Validate JSON");
             _this.onValidatedObservable.notifyObservers(result);
             _this.onValidatedObservable.clear();
+        }, function (reason) {
+            _this._endPerformanceCounter("Validate JSON");
+            babylonjs_1.Tools.Warn("Failed to validate: " + reason);
+            _this.onValidatedObservable.clear();
         });
     };
     GLTFFileLoader.prototype._getLoader = function (loaderData) {

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js.map


+ 4 - 2
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -1142,7 +1142,8 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var toto: number;
+    /** @hidden */
+    export var __IGLTFLoaderExtensionV2: number;
     /**
         * Interface for a glTF loader extension.
         */
@@ -1234,7 +1235,8 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var toto1: number;
+    /** @hidden */
+    export var __IGLTFLoaderInterfacesV2: number;
     /**
         * Loader interface with an index field.
         */

+ 8 - 2
dist/preview release/loaders/babylonjs.loaders.js

@@ -6485,7 +6485,8 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto = 0;
+/** @hidden */
+exports.__IGLTFLoaderExtensionV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -6500,7 +6501,8 @@ exports.toto = 0;
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto1 = 0;
+/** @hidden */
+exports.__IGLTFLoaderInterfacesV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -7035,6 +7037,10 @@ var GLTFFileLoader = /** @class */ (function () {
             _this._endPerformanceCounter("Validate JSON");
             _this.onValidatedObservable.notifyObservers(result);
             _this.onValidatedObservable.clear();
+        }, function (reason) {
+            _this._endPerformanceCounter("Validate JSON");
+            babylonjs_1.Tools.Warn("Failed to validate: " + reason);
+            _this.onValidatedObservable.clear();
         });
     };
     GLTFFileLoader.prototype._getLoader = function (loaderData) {

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js.map


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js.map


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

@@ -1218,7 +1218,8 @@ declare module 'babylonjs-loaders/src/glTF/2.0/glTFLoaderExtension' {
     import { IDisposable, Nullable, Mesh, Camera, Geometry, Material, BaseTexture, AnimationGroup } from "babylonjs";
     import { ISceneV2, INodeV2, ICameraV2, IMeshPrimitiveV2, IMaterialV2, ITextureInfoV2, IAnimationV2 } from "babylonjs-loaders/src/glTF/2.0/glTFLoaderInterfaces";
     import { IGLTFLoaderExtension } from "babylonjs-loaders/src/glTF/glTFFileLoader";
-    export var toto: number;
+    /** @hidden */
+    export var __IGLTFLoaderExtensionV2: number;
     /**
         * Interface for a glTF loader extension.
         */
@@ -1313,7 +1314,8 @@ declare module 'babylonjs-loaders/src/glTF/2.0/glTFLoaderExtension' {
 declare module 'babylonjs-loaders/src/glTF/2.0/glTFLoaderInterfaces' {
     import { VertexBuffer, Buffer, AnimationGroup, Material, AbstractMesh, Mesh, Bone, Skeleton } from "babylonjs";
     import { AnimationSamplerInterpolation, ITexture, ITextureInfo, IGLTF, ISampler, IScene, ISkin, IMesh, IMeshPrimitive, INode, IAccessor, IAnimationChannel, IAnimationSampler, IAnimation, IBuffer, IBufferView, ICamera, IImage, IMaterialNormalTextureInfo, IMaterialOcclusionTextureInfo, IMaterialPbrMetallicRoughness, IMaterial } from "babylonjs-gltf2interface";
-    export var toto1: number;
+    /** @hidden */
+    export var __IGLTFLoaderInterfacesV2: number;
     /**
         * Loader interface with an index field.
         */
@@ -2903,7 +2905,8 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var toto: number;
+    /** @hidden */
+    export var __IGLTFLoaderExtensionV2: number;
     /**
         * Interface for a glTF loader extension.
         */
@@ -2995,7 +2998,8 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var toto1: number;
+    /** @hidden */
+    export var __IGLTFLoaderInterfacesV2: number;
     /**
         * Loader interface with an index field.
         */

+ 1 - 4
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.js

@@ -376,10 +376,7 @@ var DigitalRainPostProcess = /** @class */ (function (_super) {
         var textureSize = _this._digitalRainFontTexture.getSize();
         var alpha = 0.0;
         var cosTimeZeroOne = 0.0;
-        var matrix = new babylonjs_1.Matrix();
-        for (var i = 0; i < 16; i++) {
-            matrix.m[i] = Math.random();
-        }
+        var matrix = babylonjs_1.Matrix.FromValues(Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random());
         _this.onApply = function (effect) {
             effect.setTexture("digitalRainFont", _this._digitalRainFontTexture);
             effect.setFloat4("digitalRainFontInfos", _this._digitalRainFontTexture.charSize, characterSet.length, textureSize.width, textureSize.height);

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.js.map


+ 1 - 4
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js

@@ -376,10 +376,7 @@ var DigitalRainPostProcess = /** @class */ (function (_super) {
         var textureSize = _this._digitalRainFontTexture.getSize();
         var alpha = 0.0;
         var cosTimeZeroOne = 0.0;
-        var matrix = new babylonjs_1.Matrix();
-        for (var i = 0; i < 16; i++) {
-            matrix.m[i] = Math.random();
-        }
+        var matrix = babylonjs_1.Matrix.FromValues(Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random());
         _this.onApply = function (effect) {
             effect.setTexture("digitalRainFont", _this._digitalRainFontTexture);
             effect.setFloat4("digitalRainFontInfos", _this._digitalRainFontTexture.charSize, characterSet.length, textureSize.width, textureSize.height);

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js.map


+ 1 - 4
dist/preview release/postProcessesLibrary/babylonjs.postProcess.js

@@ -608,10 +608,7 @@ var DigitalRainPostProcess = /** @class */ (function (_super) {
         var textureSize = _this._digitalRainFontTexture.getSize();
         var alpha = 0.0;
         var cosTimeZeroOne = 0.0;
-        var matrix = new babylonjs_1.Matrix();
-        for (var i = 0; i < 16; i++) {
-            matrix.m[i] = Math.random();
-        }
+        var matrix = babylonjs_1.Matrix.FromValues(Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random());
         _this.onApply = function (effect) {
             effect.setTexture("digitalRainFont", _this._digitalRainFontTexture);
             effect.setFloat4("digitalRainFontInfos", _this._digitalRainFontTexture.charSize, characterSet.length, textureSize.width, textureSize.height);

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.js.map


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js.map


+ 4 - 2
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -2255,7 +2255,8 @@ exports._BinaryWriter = _BinaryWriter;
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto2 = 0;
+/** @hidden */
+exports.__IGLTFExporterExtensionV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -3682,7 +3683,8 @@ __export(__webpack_require__(/*! ./glTFUtilities */ "./src/glTF/2.0/glTFUtilitie
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto3 = 0;
+/** @hidden */
+exports.__IGLTFExporterExtension = 0; // I am here to allow dts to be created
 
 
 /***/ }),

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.js.map


+ 4 - 2
dist/preview release/serializers/babylon.glTF2Serializer.min.js

@@ -2255,7 +2255,8 @@ exports._BinaryWriter = _BinaryWriter;
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto2 = 0;
+/** @hidden */
+exports.__IGLTFExporterExtensionV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -3682,7 +3683,8 @@ __export(__webpack_require__(/*! ./glTFUtilities */ "./src/glTF/2.0/glTFUtilitie
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto3 = 0;
+/** @hidden */
+exports.__IGLTFExporterExtension = 0; // I am here to allow dts to be created
 
 
 /***/ }),

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js.map


+ 4 - 2
dist/preview release/serializers/babylonjs.serializers.d.ts

@@ -9,7 +9,8 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var toto3: number;
+    /** @hidden */
+    export var __IGLTFExporterExtension: number;
     /**
         * Interface for extending the exporter
         * @hidden
@@ -286,7 +287,8 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var toto2: number;
+    /** @hidden */
+    export var __IGLTFExporterExtensionV2: number;
     /**
         * Interface for a glTF exporter extension
         * @hidden

+ 4 - 2
dist/preview release/serializers/babylonjs.serializers.js

@@ -2382,7 +2382,8 @@ exports._BinaryWriter = _BinaryWriter;
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto2 = 0;
+/** @hidden */
+exports.__IGLTFExporterExtensionV2 = 0; // I am here to allow dts to be created
 
 
 /***/ }),
@@ -3809,7 +3810,8 @@ __export(__webpack_require__(/*! ./glTFUtilities */ "./src/glTF/2.0/glTFUtilitie
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.toto3 = 0;
+/** @hidden */
+exports.__IGLTFExporterExtension = 0; // I am here to allow dts to be created
 
 
 /***/ }),

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.js.map


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js.map


+ 8 - 4
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -26,7 +26,8 @@ declare module 'babylonjs-serializers/src/OBJ/objSerializer' {
 }
 
 declare module 'babylonjs-serializers/src/glTF/glTFFileExporter' {
-    export var toto3: number;
+    /** @hidden */
+    export var __IGLTFExporterExtension: number;
     /**
         * Interface for extending the exporter
         * @hidden
@@ -330,7 +331,8 @@ declare module 'babylonjs-serializers/src/glTF/2.0/glTFExporterExtension' {
     import { ImageMimeType, IMeshPrimitive } from "babylonjs-gltf2interface";
     import { _BinaryWriter } from "babylonjs-serializers/src/glTF/2.0/glTFExporter";
     import { IGLTFExporterExtension } from "babylonjs-serializers/src/glTF/glTFFileExporter";
-    export var toto2: number;
+    /** @hidden */
+    export var __IGLTFExporterExtensionV2: number;
     /**
         * Interface for a glTF exporter extension
         * @hidden
@@ -607,7 +609,8 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var toto3: number;
+    /** @hidden */
+    export var __IGLTFExporterExtension: number;
     /**
         * Interface for extending the exporter
         * @hidden
@@ -884,7 +887,8 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var toto2: number;
+    /** @hidden */
+    export var __IGLTFExporterExtensionV2: number;
     /**
         * Interface for a glTF exporter extension
         * @hidden

文件差异内容过多而无法显示
+ 916 - 0
dist/preview release/viewer/4ff3a89403672639e15d.js


文件差异内容过多而无法显示
+ 4 - 0
dist/preview release/viewer/babylon.viewer.js


文件差异内容过多而无法显示
+ 8 - 0
dist/preview release/viewer/babylon.viewer.max.js


文件差异内容过多而无法显示
+ 183 - 0
dist/preview release/viewer/e45de3ab9c569c68ab0c.js


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

@@ -17,6 +17,7 @@
 ### GUI
 
 - Added `button.image` and `button.textBlock` to simplify access to button internal parts ([Deltakosh](https://github.com/deltakosh))
+- Added `sldier.displayThumb` to show/hide slider's thumb ([Deltakosh](https://github.com/deltakosh))
 
 ### Core Engine
 
@@ -34,6 +35,7 @@
   - Added an option `useClonedMeshhMap` in the `Scene` constructor options. When set to true, each `Mesh` will have and will keep up-to-date a map of cloned meshes. This is to avoid browsing all the meshes of the scene to retrieve the ones that have the current mesh as source mesh. Disabled by default
   - Added `blockfreeActiveMeshesAndRenderingGroups` property in the `Scene`, following the same model as `blockMaterialDirtyMechanism`. This is to avoid calling `Scene.freeActiveMeshes` and `Scene.freeRenderingGroups` for each disposed mesh when we dispose several meshes in a row. One have to set `blockfreeActiveMeshesAndRenderingGroups` to `true` just before disposing the meshes, and set it back to `false` just after
   - Prevented code from doing useless and possible time consuming computation when disposing the `ShaderMaterial` of a `LinesMesh`
+  - Make a better use of the `isIdentity` cached value wihtin a `Matrix`
 - Align `BoundingBox` and `BoundingSphere` API and behavior for clarity and simplicity. As a consequence, the `BoundingBox`'s method `setWorldMatrix` has been removed and the underlying world matrix cannot be modified but by calling `reConstruct` or `update`. ([barroij](https://github.com/barroij))
 
 ### glTF Loader
@@ -66,3 +68,4 @@
 - `Database.openAsync` was renamed by `Database.open` ([Deltakosh](https://github.com/deltakosh))
 - `scene.database` was renamed to `scene.offlineProvider` ([Deltakosh](https://github.com/deltakosh))
 - `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `Readonly<Matrix>` ([barroij](https://github.com/barroij))
+- `Matrix`'s accessor `m` and method `toArray` and `asArray` now returns a `Readonly<Float32Array>` as the matrix underlying array is not supposed to be modified manually from the outside of the class ([barroij](https://github.com/barroij))

+ 283 - 0
gui/src/2D/controls/baseSlider.ts

@@ -0,0 +1,283 @@
+import { Control } from "./control";
+import { ValueAndUnit } from "../valueAndUnit";
+import { Observable, Vector2 } from "babylonjs";
+
+/**
+ * Class used to create slider controls
+ */
+export class BaseSlider extends Control {
+    protected _thumbWidth = new ValueAndUnit(20, ValueAndUnit.UNITMODE_PIXEL, false);
+    private _minimum = 0;
+    private _maximum = 100;
+    private _value = 50;
+    private _isVertical = false;
+    protected _barOffset = new ValueAndUnit(5, ValueAndUnit.UNITMODE_PIXEL, false);
+    private _isThumbClamped = false;
+
+    // Shared rendering info
+    protected _effectiveBarOffset = 0;
+    protected _renderLeft: number;
+    protected _renderTop: number;
+    protected _renderWidth: number;
+    protected _renderHeight: number;
+    protected _backgroundBoxLength: number;
+    protected _backgroundBoxThickness: number;
+    protected _effectiveThumbThickness: number;
+
+    /** Observable raised when the sldier value changes */
+    public onValueChangedObservable = new Observable<number>();
+
+    /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
+    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;
+        }
+
+        if (this._barOffset.fromString(value)) {
+            this._markAsDirty();
+        }
+    }
+
+    /** Gets or sets thumb width */
+    public get thumbWidth(): string | number {
+        return this._thumbWidth.toString(this._host);
+    }
+
+    /** Gets thumb width in pixels */
+    public get thumbWidthInPixels(): number {
+        return this._thumbWidth.getValueInPixel(this._host, this._cachedParentMeasure.width);
+    }
+
+    public set thumbWidth(value: string | number) {
+        if (this._thumbWidth.toString(this._host) === value) {
+            return;
+        }
+
+        if (this._thumbWidth.fromString(value)) {
+            this._markAsDirty();
+        }
+    }
+
+    /** Gets or sets minimum value */
+    public get minimum(): number {
+        return this._minimum;
+    }
+
+    public set minimum(value: number) {
+        if (this._minimum === value) {
+            return;
+        }
+
+        this._minimum = value;
+        this._markAsDirty();
+
+        this.value = Math.max(Math.min(this.value, this._maximum), this._minimum);
+    }
+
+    /** Gets or sets maximum value */
+    public get maximum(): number {
+        return this._maximum;
+    }
+
+    public set maximum(value: number) {
+        if (this._maximum === value) {
+            return;
+        }
+
+        this._maximum = value;
+        this._markAsDirty();
+
+        this.value = Math.max(Math.min(this.value, this._maximum), this._minimum);
+    }
+
+    /** Gets or sets current value */
+    public get value(): number {
+        return this._value;
+    }
+
+    public set value(value: number) {
+        value = Math.max(Math.min(value, this._maximum), this._minimum);
+
+        if (this._value === value) {
+            return;
+        }
+
+        this._value = value;
+        this._markAsDirty();
+        this.onValueChangedObservable.notifyObservers(this._value);
+    }
+
+    /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
+    public get isVertical(): boolean {
+        return this._isVertical;
+    }
+
+    public set isVertical(value: boolean) {
+        if (this._isVertical === value) {
+            return;
+        }
+
+        this._isVertical = value;
+        this._markAsDirty();
+    }
+
+    /** Gets or sets a value indicating if the thumb can go over main bar extends */
+    public get isThumbClamped(): boolean {
+        return this._isThumbClamped;
+    }
+
+    public set isThumbClamped(value: boolean) {
+        if (this._isThumbClamped === value) {
+            return;
+        }
+
+        this._isThumbClamped = value;
+        this._markAsDirty();
+    }
+
+    /**
+     * Creates a new BaseSlider
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
+
+        this.isPointerBlocker = true;
+    }
+
+    protected _getTypeName(): string {
+        return "BaseSlider";
+    }
+
+    protected _getThumbPosition() {
+        if (this.isVertical) {
+            return ((this.maximum - this.value) / (this.maximum - this.minimum)) * this._backgroundBoxLength;
+        }
+
+        return ((this.value - this.minimum) / (this.maximum - this.minimum)) * this._backgroundBoxLength;
+    }
+
+    protected _getThumbThickness(type: string): number {
+        var thumbThickness = 0;
+        switch (type) {
+            case "circle":
+                if (this._thumbWidth.isPixel) {
+                    thumbThickness = Math.max(this._thumbWidth.getValue(this._host), this._backgroundBoxThickness);
+                }
+                else {
+                    thumbThickness = this._backgroundBoxThickness * this._thumbWidth.getValue(this._host);
+                }
+                break;
+            case "rectangle":
+                if (this._thumbWidth.isPixel) {
+                    thumbThickness = Math.min(this._thumbWidth.getValue(this._host), this._backgroundBoxThickness);
+                }
+                else {
+                    thumbThickness = this._backgroundBoxThickness * this._thumbWidth.getValue(this._host);
+                }
+        }
+        return thumbThickness;
+    }
+
+    protected _prepareRenderingData(type: string) {
+        // Main bar
+        this._effectiveBarOffset = 0;
+        this._renderLeft = this._currentMeasure.left;
+        this._renderTop = this._currentMeasure.top;
+        this._renderWidth = this._currentMeasure.width;
+        this._renderHeight = this._currentMeasure.height;
+
+        this._backgroundBoxLength = Math.max(this._currentMeasure.width, this._currentMeasure.height);
+        this._backgroundBoxThickness = Math.min(this._currentMeasure.width, this._currentMeasure.height);
+        this._effectiveThumbThickness = this._getThumbThickness(type);
+
+        this._backgroundBoxLength -= this._effectiveThumbThickness;
+        //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) {
+            this._effectiveBarOffset = Math.min(this._barOffset.getValue(this._host), this._backgroundBoxThickness);
+        }
+        else {
+            this._effectiveBarOffset = this._backgroundBoxThickness * this._barOffset.getValue(this._host);
+        }
+
+        this._backgroundBoxThickness -= (this._effectiveBarOffset * 2);
+
+        if (this.isVertical) {
+            this._renderLeft += this._effectiveBarOffset;
+            if (!this.isThumbClamped) {
+                this._renderTop += (this._effectiveThumbThickness / 2);
+            }
+
+            this._renderHeight = this._backgroundBoxLength;
+            this._renderWidth = this._backgroundBoxThickness;
+
+        }
+        else {
+            this._renderTop += this._effectiveBarOffset;
+            if (!this.isThumbClamped) {
+                this._renderLeft += (this._effectiveThumbThickness / 2);
+            }
+            this._renderHeight = this._backgroundBoxThickness;
+            this._renderWidth = this._backgroundBoxLength;
+        }
+    }
+
+    // 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);
+        }
+    }
+
+    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
+        if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
+            return false;
+        }
+
+        this._pointerIsDown = true;
+
+        this._updateValueFromPointer(coordinates.x, coordinates.y);
+        this._host._capturingControl[pointerId] = this;
+
+        return true;
+    }
+
+    public _onPointerMove(target: Control, coordinates: Vector2): void {
+        if (this._pointerIsDown) {
+            this._updateValueFromPointer(coordinates.x, coordinates.y);
+        }
+
+        super._onPointerMove(target, coordinates);
+    }
+
+    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);
+    }
+}

+ 20 - 1
gui/src/2D/controls/image.ts

@@ -1,5 +1,5 @@
 import { Control } from "./control";
-import { Nullable, Tools } from "babylonjs";
+import { Nullable, Tools, Observable } from "babylonjs";
 import { Measure } from "../measure";
 
 /**
@@ -24,6 +24,18 @@ export class Image extends Control {
     private _cellId: number = -1;
 
     /**
+     * Observable notified when the content is loaded
+     */
+    public onImageLoadedObservable = new Observable<Image>();
+
+    /**
+     * Gets a boolean indicating that the content is loaded
+     */
+    public get isLoaded(): boolean {
+        return this._loaded;
+    }
+
+    /**
      * Gets or sets the left coordinate in the source image
      */
     public get sourceLeft(): number {
@@ -155,6 +167,8 @@ export class Image extends Control {
             this.synchronizeSizeWithContent();
         }
 
+        this.onImageLoadedObservable.notifyObservers(this);
+
         this._markAsDirty();
     }
 
@@ -321,6 +335,11 @@ export class Image extends Control {
         context.restore();
     }
 
+    public dispose() {
+        super.dispose();
+        this.onImageLoadedObservable.clear();
+    }
+
     // Static
     /** STRETCH_NONE */
     public static readonly STRETCH_NONE = 0;

+ 145 - 0
gui/src/2D/controls/imageBasedSlider.ts

@@ -0,0 +1,145 @@
+import { BaseSlider } from "./baseSlider";
+import { Measure } from "../measure";
+import { Image } from "./image";
+
+/**
+ * Class used to create slider controls based on images
+ */
+export class ImageBasedSlider extends BaseSlider {
+    private _backgroundImage: Image;
+    private _thumbImage: Image;
+    private _valueBarImage: Image;
+
+    private _tempMeasure = new Measure(0, 0, 0, 0);
+
+    /**
+     * Gets or sets the image used to render the background
+     */
+    public get backgroundImage(): Image {
+        return this._backgroundImage;
+    }
+
+    public set backgroundImage(value: Image) {
+        if (this._backgroundImage === value) {
+            return;
+        }
+
+        this._backgroundImage = value;
+
+        if (value && !value.isLoaded) {
+            value.onImageLoadedObservable.addOnce(() => this._markAsDirty());
+        }
+
+        this._markAsDirty();
+    }
+
+    /**
+     * Gets or sets the image used to render the value bar
+     */
+    public get valueBarImage(): Image {
+        return this._valueBarImage;
+    }
+
+    public set valueBarImage(value: Image) {
+        if (this._valueBarImage === value) {
+            return;
+        }
+
+        this._valueBarImage = value;
+
+        if (value && !value.isLoaded) {
+            value.onImageLoadedObservable.addOnce(() => this._markAsDirty());
+        }
+
+        this._markAsDirty();
+    }
+
+    /**
+     * Gets or sets the image used to render the thumb
+     */
+    public get thumbImage(): Image {
+        return this._thumbImage;
+    }
+
+    public set thumbImage(value: Image) {
+        if (this._thumbImage === value) {
+            return;
+        }
+
+        this._thumbImage = value;
+
+        if (value && !value.isLoaded) {
+            value.onImageLoadedObservable.addOnce(() => this._markAsDirty());
+        }
+
+        this._markAsDirty();
+    }
+
+    /**
+     * Creates a new ImageBasedSlider
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
+    }
+
+    protected _getTypeName(): string {
+        return "ImageBasedSlider";
+    }
+
+    public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        context.save();
+
+        this._applyStates(context);
+        if (this._processMeasures(parentMeasure, context)) {
+
+            this._prepareRenderingData("rectangle");
+            const thumbPosition = this._getThumbPosition();
+            var left = this._renderLeft;
+            var top = this._renderTop;
+            var width = this._renderWidth;
+            var height = this._renderHeight;
+
+            // Background
+            if (this._backgroundImage) {
+                this._tempMeasure.copyFromFloats(left, top, width, height);
+                if (this.isThumbClamped) {
+                    if (this.isVertical) {
+                        this._tempMeasure.height += this._effectiveThumbThickness;
+                    } else {
+                        this._tempMeasure.width += this._effectiveThumbThickness;
+                    }
+
+                }
+                this._backgroundImage._draw(this._tempMeasure, context);
+            }
+
+            // Bar
+            if (this._valueBarImage) {
+                if (this.isVertical) {
+                    this._tempMeasure.copyFromFloats(left, top + thumbPosition, width, height - thumbPosition);
+                    if (this.isThumbClamped) {
+                        this._tempMeasure.copyFromFloats(left, top + thumbPosition, width, this._currentMeasure.height - thumbPosition);
+                    } else {
+                        this._tempMeasure.copyFromFloats(left, top + thumbPosition, width, height - thumbPosition);
+                    }
+                } else {
+                    this._tempMeasure.copyFromFloats(left, top, thumbPosition, height);
+                }
+                this._valueBarImage._draw(this._tempMeasure, context);
+            }
+
+            // Thumb
+            if (this._thumbImage) {
+                if (this.isVertical) {
+                    this._tempMeasure.copyFromFloats(left - this._effectiveBarOffset, this._currentMeasure.top + thumbPosition, this._currentMeasure.width, this._effectiveThumbThickness);
+                } else {
+                    this._tempMeasure.copyFromFloats(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, this._effectiveThumbThickness, this._currentMeasure.height);
+                }
+                this._thumbImage._draw(this._tempMeasure, context);
+            }
+        }
+
+        context.restore();
+    }
+}

+ 23 - 21
gui/src/2D/controls/index.ts

@@ -1,22 +1,24 @@
-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 "./inputPassword";
-export * from "./line";
-export * from "./multiLine";
-export * from "./radioButton";
-export * from "./stackPanel";
-export * from "./selector";
-export * from "./textBlock";
-export * from "./virtualKeyboard";
-export * from "./slider";
-export * from "./rectangle";
-export * from "./displayGrid";
-
+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 "./inputPassword";
+export * from "./line";
+export * from "./multiLine";
+export * from "./radioButton";
+export * from "./stackPanel";
+export * from "./selector";
+export * from "./textBlock";
+export * from "./virtualKeyboard";
+export * from "./rectangle";
+export * from "./displayGrid";
+export * from "./baseSlider";
+export * from "./slider";
+export * from "./imageBasedSlider";
+
 export * from "./statics";

+ 77 - 297
gui/src/2D/controls/slider.ts

@@ -1,25 +1,28 @@
-import { Control } from "./control";
-import { ValueAndUnit } from "../valueAndUnit";
-import { Observable, Vector2 } from "babylonjs";
 import { Measure } from "../measure";
+import { BaseSlider } from "./baseSlider";
 
 /**
  * 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;
+export class Slider extends BaseSlider {
     private _background = "black";
     private _borderColor = "white";
-    private _barOffset = new ValueAndUnit(5, ValueAndUnit.UNITMODE_PIXEL, false);
     private _isThumbCircle = false;
-    private _isThumbClamped = false;
+    private _displayThumb = true;
 
-    /** Observable raised when the sldier value changes */
-    public onValueChangedObservable = new Observable<number>();
+    /** Gets or sets a boolean indicating if the thumb must be rendered */
+    public get displayThumb(): boolean {
+        return this._displayThumb;
+    }
+
+    public set displayThumb(value: boolean) {
+        if (this._displayThumb === value) {
+            return;
+        }
+
+        this._displayThumb = value;
+        this._markAsDirty();
+    }
 
     /** Gets or sets border color */
     public get borderColor(): string {
@@ -49,109 +52,6 @@ export class Slider extends Control {
         this._markAsDirty();
     }
 
-    /** 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;
-        }
-
-        if (this._barOffset.fromString(value)) {
-            this._markAsDirty();
-        }
-    }
-
-    /** Gets or sets thumb width */
-    public get thumbWidth(): string | number {
-        return this._thumbWidth.toString(this._host);
-    }
-
-    /** Gets thumb width in pixels */
-    public get thumbWidthInPixels(): number {
-        return this._thumbWidth.getValueInPixel(this._host, this._cachedParentMeasure.width);
-    }
-
-    public set thumbWidth(value: string | number) {
-        if (this._thumbWidth.toString(this._host) === value) {
-            return;
-        }
-
-        if (this._thumbWidth.fromString(value)) {
-            this._markAsDirty();
-        }
-    }
-
-    /** Gets or sets minimum value */
-    public get minimum(): number {
-        return this._minimum;
-    }
-
-    public set minimum(value: number) {
-        if (this._minimum === value) {
-            return;
-        }
-
-        this._minimum = value;
-        this._markAsDirty();
-
-        this.value = Math.max(Math.min(this.value, this._maximum), this._minimum);
-    }
-
-    /** Gets or sets maximum value */
-    public get maximum(): number {
-        return this._maximum;
-    }
-
-    public set maximum(value: number) {
-        if (this._maximum === value) {
-            return;
-        }
-
-        this._maximum = value;
-        this._markAsDirty();
-
-        this.value = Math.max(Math.min(this.value, this._maximum), this._minimum);
-    }
-
-    /** Gets or sets current value */
-    public get value(): number {
-        return this._value;
-    }
-
-    public set value(value: number) {
-        value = Math.max(Math.min(value, this._maximum), this._minimum);
-
-        if (this._value === value) {
-            return;
-        }
-
-        this._value = value;
-        this._markAsDirty();
-        this.onValueChangedObservable.notifyObservers(this._value);
-    }
-
-    /**Gets or sets a boolean indicating if the slider should be vertical or horizontal */
-    public get isVertical(): boolean {
-        return this._isVertical;
-    }
-
-    public set isVertical(value: boolean) {
-        if (this._isVertical === value) {
-            return;
-        }
-
-        this._isVertical = value;
-        this._markAsDirty();
-    }
-
     /** Gets or sets a boolean indicating if the thumb should be round or square */
     public get isThumbCircle(): boolean {
         return this._isThumbCircle;
@@ -166,122 +66,44 @@ export class Slider extends Control {
         this._markAsDirty();
     }
 
-    /** Gets or sets a value indicating if the thumb can go over main bar extends */
-    public get isThumbClamped(): boolean {
-        return this._isThumbClamped;
-    }
-
-    public set isThumbClamped(value: boolean) {
-        if (this._isThumbClamped === value) {
-            return;
-        }
-
-        this._isThumbClamped = value;
-        this._markAsDirty();
-    }
-
     /**
      * Creates a new Slider
      * @param name defines the control name
      */
     constructor(public name?: string) {
         super(name);
-
-        this.isPointerBlocker = true;
     }
 
     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);
-                }
-        }
-        return thumbThickness;
-    }
-
     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;
+            this._prepareRenderingData(this.isThumbCircle ? "circle" : "rectangle");
+            var left = this._renderLeft;
+            var top = this._renderTop;
+            var width = this._renderWidth;
+            var height = this._renderHeight;
 
             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);
-            }
-
-            backgroundBoxThickness -= (effectiveBarOffset * 2);
-
-            if (this._isVertical) {
-                left += effectiveBarOffset;
-                if (!this.isThumbClamped) {
-                    top += (effectiveThumbThickness / 2);
-                }
-
-                height = backgroundBoxLength;
-                width = backgroundBoxThickness;
-
-            }
-            else {
-                top += effectiveBarOffset;
-                if (!this.isThumbClamped) {
-                    left += (effectiveThumbThickness / 2);
-                }
-                height = backgroundBoxThickness;
-                width = backgroundBoxLength;
-            }
-
             if (this.isThumbClamped && this.isThumbCircle) {
-                if (this._isVertical) {
-                    top += (effectiveThumbThickness / 2);
+                if (this.isVertical) {
+                    top += (this._effectiveThumbThickness / 2);
                 }
                 else {
-                    left += (effectiveThumbThickness / 2);
+                    left += (this._effectiveThumbThickness / 2);
                 }
 
-                radius = backgroundBoxThickness / 2;
+                radius = this._backgroundBoxThickness / 2;
             }
             else {
-                radius = (effectiveThumbThickness - effectiveBarOffset) / 2;
+                radius = (this._effectiveThumbThickness - this._effectiveBarOffset) / 2;
             }
 
             if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
@@ -291,19 +113,19 @@ export class Slider extends Control {
                 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;
+            const thumbPosition = this._getThumbPosition();
             context.fillStyle = this._background;
 
-            if (this._isVertical) {
+            if (this.isVertical) {
                 if (this.isThumbClamped) {
                     if (this.isThumbCircle) {
                         context.beginPath();
-                        context.arc(left + backgroundBoxThickness / 2, top, radius, Math.PI, 2 * Math.PI);
+                        context.arc(left + this._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.fillRect(left, top, width, height + this._effectiveThumbThickness);
                     }
                 }
                 else {
@@ -314,12 +136,12 @@ export class Slider extends Control {
                 if (this.isThumbClamped) {
                     if (this.isThumbCircle) {
                         context.beginPath();
-                        context.arc(left + backgroundBoxLength, top + (backgroundBoxThickness / 2), radius, 0, 2 * Math.PI);
+                        context.arc(left + this._backgroundBoxLength, top + (this._backgroundBoxThickness / 2), radius, 0, 2 * Math.PI);
                         context.fill();
                         context.fillRect(left, top, width, height);
                     }
                     else {
-                        context.fillRect(left, top, width + effectiveThumbThickness, height);
+                        context.fillRect(left, top, width + this._effectiveThumbThickness, height);
                     }
                 }
                 else {
@@ -333,12 +155,13 @@ export class Slider extends Control {
                 context.shadowOffsetY = 0;
             }
 
+            // Value bar
             context.fillStyle = this.color;
-            if (this._isVertical) {
+            if (this.isVertical) {
                 if (this.isThumbClamped) {
                     if (this.isThumbCircle) {
                         context.beginPath();
-                        context.arc(left + backgroundBoxThickness / 2, top + backgroundBoxLength, radius, 0, 2 * Math.PI);
+                        context.arc(left + this._backgroundBoxThickness / 2, top + this._backgroundBoxLength, radius, 0, 2 * Math.PI);
                         context.fill();
                         context.fillRect(left, top + thumbPosition, width, height - thumbPosition);
                     }
@@ -354,7 +177,7 @@ export class Slider extends Control {
                 if (this.isThumbClamped) {
                     if (this.isThumbCircle) {
                         context.beginPath();
-                        context.arc(left, top + backgroundBoxThickness / 2, radius, 0, 2 * Math.PI);
+                        context.arc(left, top + this._backgroundBoxThickness / 2, radius, 0, 2 * Math.PI);
                         context.fill();
                         context.fillRect(left, top, thumbPosition, height);
                     }
@@ -367,96 +190,53 @@ export class Slider extends Control {
                 }
             }
 
-            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();
+            // Thumb
+            if (this.displayThumb) {
                 if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
-                    context.shadowBlur = 0;
-                    context.shadowOffsetX = 0;
-                    context.shadowOffsetY = 0;
-                }
-                context.strokeStyle = this._borderColor;
-                context.stroke();
-            }
-            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);
+                    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 + this._backgroundBoxThickness / 2, top + thumbPosition, radius, 0, 2 * Math.PI);
+                    }
+                    else {
+                        context.arc(left + thumbPosition, top + (this._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();
                 }
                 else {
-                    context.strokeRect(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, effectiveThumbThickness, this._currentMeasure.height);
+                    if (this.isVertical) {
+                        context.fillRect(left - this._effectiveBarOffset, this._currentMeasure.top + thumbPosition, this._currentMeasure.width, this._effectiveThumbThickness);
+                    }
+                    else {
+                        context.fillRect(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, this._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 - this._effectiveBarOffset, this._currentMeasure.top + thumbPosition, this._currentMeasure.width, this._effectiveThumbThickness);
+                    }
+                    else {
+                        context.strokeRect(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, this._effectiveThumbThickness, this._currentMeasure.height);
+                    }
                 }
             }
         }
         context.restore();
     }
-
-    // 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);
-        }
-    }
-
-    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
-        if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
-            return false;
-        }
-
-        this._pointerIsDown = true;
-
-        this._updateValueFromPointer(coordinates.x, coordinates.y);
-        this._host._capturingControl[pointerId] = this;
-
-        return true;
-    }
-
-    public _onPointerMove(target: Control, coordinates: Vector2): void {
-        if (this._pointerIsDown) {
-            this._updateValueFromPointer(coordinates.x, coordinates.y);
-        }
-
-        super._onPointerMove(target, coordinates);
-    }
-
-    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);
-    }
 }

+ 14 - 0
gui/src/2D/measure.ts

@@ -34,6 +34,20 @@ export class Measure {
     }
 
     /**
+     * Copy from a group of 4 floats
+     * @param left defines left coordinate
+     * @param top defines top coordinate
+     * @param width defines width dimension
+     * @param height defines height dimension
+     */
+    public copyFromFloats(left: number, top: number, width: number, height: number): void {
+        this.left = left;
+        this.top = top;
+        this.width = width;
+        this.height = height;
+    }
+
+    /**
      * Check equality between this measure and another one
      * @param other defines the other measures
      * @returns true if both measures are equals

+ 2 - 1
loaders/src/glTF/2.0/glTFLoaderExtension.ts

@@ -2,7 +2,8 @@
 import { ISceneV2, INodeV2, ICameraV2, IMeshPrimitiveV2, IMaterialV2, ITextureInfoV2, IAnimationV2 } from "./glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "../glTFFileLoader";
 
-export var toto = 0;
+/** @hidden */
+export var __IGLTFLoaderExtensionV2 = 0; // I am here to allow dts to be created
 
 /**
  * Interface for a glTF loader extension.

+ 2 - 1
loaders/src/glTF/2.0/glTFLoaderInterfaces.ts

@@ -1,7 +1,8 @@
 import { VertexBuffer, Buffer, AnimationGroup, Material, AbstractMesh, Mesh, Bone, Skeleton } from "babylonjs";
 import { AnimationSamplerInterpolation, ITexture, ITextureInfo, IGLTF, ISampler, IScene, ISkin, IMesh, IMeshPrimitive, INode, IAccessor, IAnimationChannel, IAnimationSampler, IAnimation, IBuffer, IBufferView, ICamera, IImage, IMaterialNormalTextureInfo, IMaterialOcclusionTextureInfo, IMaterialPbrMetallicRoughness, IMaterial } from "babylonjs-gltf2interface";
 
-export var toto1 = 0;
+/** @hidden */
+export var __IGLTFLoaderInterfacesV2 = 0; // I am here to allow dts to be created
 
 /**
  * Loader interface with an index field.

+ 4 - 0
loaders/src/glTF/glTFFileLoader.ts

@@ -593,6 +593,10 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
 
             this.onValidatedObservable.notifyObservers(result);
             this.onValidatedObservable.clear();
+        }, (reason) => {
+            this._endPerformanceCounter("Validate JSON");
+             Tools.Warn(`Failed to validate: ${reason}`);
+            this.onValidatedObservable.clear();
         });
     }
 

+ 6 - 4
postProcessLibrary/src/digitalRain/digitalRainPostProcess.ts

@@ -246,10 +246,12 @@ export class DigitalRainPostProcess extends PostProcess {
 
         var alpha = 0.0;
         var cosTimeZeroOne = 0.0;
-        var matrix = new Matrix();
-        for (let i = 0; i < 16; i++) {
-            matrix.m[i] = Math.random();
-        }
+        var matrix = Matrix.FromValues(
+            Math.random(), Math.random(), Math.random(), Math.random(),
+            Math.random(), Math.random(), Math.random(), Math.random(),
+            Math.random(), Math.random(), Math.random(), Math.random(),
+            Math.random(), Math.random(), Math.random(), Math.random()
+        );
 
         this.onApply = (effect: Effect) => {
             effect.setTexture("digitalRainFont", this._digitalRainFontTexture);

+ 1 - 1
readme.md

@@ -118,7 +118,7 @@ If you want to contribute, please read our [contribution guidelines](https://git
 - 3DS Max [exporter](https://github.com/BabylonJS/Exporters/tree/master/3ds%20Max) can be used to generate a .babylon file from 3DS Max
 - Maya [exporter](https://github.com/BabylonJS/Exporters/tree/master/Maya) can be used to generate a .babylon file from 3DS Max
 - Blender [exporter](https://github.com/BabylonJS/Exporters/tree/master/Blender) can be used to generate a .babylon file from Blender 3d
-- Unity 5 [exporter](https://github.com/BabylonJS/Exporters/tree/master/Unity%205) can be used to export your geometries from Unity 5 scene editor(animations are supported)
+- Unity 5[ (deprecated) exporter](https://github.com/BabylonJS/Exporters/tree/master/Unity) can be used to export your geometries from Unity 5 scene editor(animations are supported)
 - [glTF Tools](https://github.com/KhronosGroup/glTF#gltf-tools) by KhronosGroup
 
 ## Features

+ 2 - 1
serializers/src/glTF/2.0/glTFExporterExtension.ts

@@ -5,7 +5,8 @@ import { ImageMimeType, IMeshPrimitive } from "babylonjs-gltf2interface";
 import { _BinaryWriter } from "./glTFExporter";
 import { IGLTFExporterExtension } from "../glTFFileExporter";
 
-export var toto2 = 0;
+/** @hidden */
+export var __IGLTFExporterExtensionV2 = 0; // I am here to allow dts to be created
 
 /**
  * Interface for a glTF exporter extension

+ 2 - 1
serializers/src/glTF/glTFFileExporter.ts

@@ -1,4 +1,5 @@
-export var toto3 = 0;
+/** @hidden */
+export var __IGLTFExporterExtension = 0; // I am here to allow dts to be created
 
 /**
  * Interface for extending the exporter

+ 21 - 37
src/Bones/babylon.bone.ts

@@ -413,9 +413,9 @@ module BABYLON {
             var lm = this.getLocalMatrix();
 
             if (space == Space.LOCAL) {
-                lm.m[12] += vec.x;
-                lm.m[13] += vec.y;
-                lm.m[14] += vec.z;
+                lm.addAtIndex(12, vec.x);
+                lm.addAtIndex(13, vec.y);
+                lm.addAtIndex(14, vec.z);
             } else {
                 var wm: Nullable<Matrix> = null;
 
@@ -437,17 +437,13 @@ module BABYLON {
                     }
                 }
 
-                tmat.m[12] = 0;
-                tmat.m[13] = 0;
-                tmat.m[14] = 0;
-
+                tmat.setTranslationFromFloats(0, 0, 0);
                 tmat.invert();
                 Vector3.TransformCoordinatesToRef(vec, tmat, tvec);
 
-                lm.m[12] += tvec.x;
-                lm.m[13] += tvec.y;
-                lm.m[14] += tvec.z;
-
+                lm.addAtIndex(12, tvec.x);
+                lm.addAtIndex(13, tvec.y);
+                lm.addAtIndex(14, tvec.z);
             }
 
             this._markAsDirtyAndDecompose();
@@ -463,9 +459,7 @@ module BABYLON {
             var lm = this.getLocalMatrix();
 
             if (space == Space.LOCAL) {
-                lm.m[12] = position.x;
-                lm.m[13] = position.y;
-                lm.m[14] = position.z;
+                lm.setTranslationFromFloats(position.x, position.y, position.z);
             } else {
                 var wm: Nullable<Matrix> = null;
 
@@ -490,11 +484,7 @@ module BABYLON {
 
                 tmat.invert();
                 Vector3.TransformCoordinatesToRef(position, tmat, vec);
-
-                lm.m[12] = vec.x;
-                lm.m[13] = vec.y;
-                lm.m[14] = vec.z;
-
+                lm.setTranslationFromFloats(vec.x, vec.y, vec.z);
             }
 
             this._markAsDirtyAndDecompose();
@@ -530,9 +520,9 @@ module BABYLON {
             for (var child of this.children) {
                 var cm = child.getLocalMatrix();
                 cm.multiplyToRef(scaleMat, cm);
-                cm.m[12] *= x;
-                cm.m[13] *= y;
-                cm.m[14] *= z;
+                cm.multiplyAtIndex(12, x);
+                cm.multiplyAtIndex(13, y);
+                cm.multiplyAtIndex(14, z);
 
                 child._markAsDirtyAndDecompose();
             }
@@ -612,12 +602,8 @@ module BABYLON {
          */
         public rotate(axis: Vector3, amount: number, space = Space.LOCAL, mesh?: AbstractMesh): void {
             var rmat = Bone._tmpMats[0];
-            rmat.m[12] = 0;
-            rmat.m[13] = 0;
-            rmat.m[14] = 0;
-
+            rmat.setTranslationFromFloats(0, 0, 0);
             Matrix.RotationAxisToRef(axis, amount, rmat);
-
             this._rotateWithMatrix(rmat, space, mesh);
         }
 
@@ -751,9 +737,7 @@ module BABYLON {
                 }
             }
 
-            lmat.m[12] = lx;
-            lmat.m[13] = ly;
-            lmat.m[14] = lz;
+            lmat.setTranslationFromFloats(lx, ly, lz);
 
             this.computeAbsoluteTransforms();
             this._markAsDirtyAndDecompose();
@@ -775,7 +759,7 @@ module BABYLON {
                 return false;
             }
 
-            scaleMatrix.m[0] *= this._scalingDeterminant;
+            scaleMatrix.multiplyAtIndex(0, this._scalingDeterminant);
             rotMatInv.multiplyToRef(scaleMatrix, rotMatInv);
 
             return true;
@@ -986,9 +970,9 @@ module BABYLON {
                     mat.copyFrom(amat);
                 }
 
-                mat.m[0] *= this._scalingDeterminant;
-                mat.m[1] *= this._scalingDeterminant;
-                mat.m[2] *= this._scalingDeterminant;
+                mat.multiplyAtIndex(0, this._scalingDeterminant);
+                mat.multiplyAtIndex(1, this._scalingDeterminant);
+                mat.multiplyAtIndex(2, this._scalingDeterminant);
 
                 mat.decompose(undefined, result, undefined);
             }
@@ -1028,9 +1012,9 @@ module BABYLON {
                     mat.copyFrom(amat);
                 }
 
-                mat.m[0] *= this._scalingDeterminant;
-                mat.m[1] *= this._scalingDeterminant;
-                mat.m[2] *= this._scalingDeterminant;
+                mat.multiplyAtIndex(0, this._scalingDeterminant);
+                mat.multiplyAtIndex(1, this._scalingDeterminant);
+                mat.multiplyAtIndex(2, this._scalingDeterminant);
 
                 mat.getRotationMatrixToRef(result);
             }

+ 9 - 15
src/Cameras/VR/babylon.webVRCamera.ts

@@ -256,7 +256,7 @@ module BABYLON {
             });
 
             if (typeof (VRFrameData) !== "undefined") {
-                this._frameData = new VRFrameData();
+                this._frameData = new VRFrameData();
             }
 
             /**
@@ -320,11 +320,9 @@ module BABYLON {
                     this._standingMatrix = new Matrix();
                     Matrix.FromFloat32ArrayToRefScaled(result.vrDisplay.stageParameters.sittingToStandingTransform, 0, 1, this._standingMatrix);
                     if (!this.getScene().useRightHandedSystem) {
-                        [2, 6, 8, 9, 14].forEach((num) => {
-                            if (this._standingMatrix) {
-                                this._standingMatrix.m[num] *= -1;
-                            }
-                        });
+                        if (this._standingMatrix) {
+                            this._standingMatrix.toggleModelMatrixHandInPlace();
+                        }
                     }
                     callback(true);
                 }
@@ -634,9 +632,7 @@ module BABYLON {
             Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
 
             if (!this.getScene().useRightHandedSystem) {
-                [2, 6, 8, 9, 14].forEach((num) => {
-                    this._webvrViewMatrix.m[num] *= -1;
-                });
+                this._webvrViewMatrix.toggleModelMatrixHandInPlace();
             }
 
             // update the camera rotation matrix
@@ -651,9 +647,9 @@ module BABYLON {
                 this._webvrViewMatrix.invert();
                 // scale the position, if set
                 if (parentCamera.deviceScaleFactor) {
-                    this._webvrViewMatrix.m[12] *= parentCamera.deviceScaleFactor;
-                    this._webvrViewMatrix.m[13] *= parentCamera.deviceScaleFactor;
-                    this._webvrViewMatrix.m[14] *= parentCamera.deviceScaleFactor;
+                    this._webvrViewMatrix.multiplyAtIndex(12, parentCamera.deviceScaleFactor);
+                    this._webvrViewMatrix.multiplyAtIndex(13, parentCamera.deviceScaleFactor);
+                    this._webvrViewMatrix.multiplyAtIndex(14, parentCamera.deviceScaleFactor);
                 }
 
                 this._webvrViewMatrix.invert();
@@ -686,9 +682,7 @@ module BABYLON {
 
             //babylon compatible matrix
             if (!this.getScene().useRightHandedSystem) {
-                [8, 9, 10, 11].forEach((num) => {
-                    this._projectionMatrix.m[num] *= -1;
-                });
+                this._projectionMatrix.toggleProjectionMatrixHandInPlace();
             }
 
             return this._projectionMatrix;

+ 29 - 27
src/Cameras/babylon.arcRotateCamera.ts

@@ -155,7 +155,7 @@ module BABYLON {
         public get angularSensibilityX(): number {
             var pointers = <ArcRotateCameraPointersInput>this.inputs.attached["pointers"];
             if (pointers) {
-                return pointers.angularSensibilityX;
+                return pointers.angularSensibilityX;
             }
 
             return 0;
@@ -174,7 +174,7 @@ module BABYLON {
         public get angularSensibilityY(): number {
             var pointers = <ArcRotateCameraPointersInput>this.inputs.attached["pointers"];
             if (pointers) {
-                return pointers.angularSensibilityY;
+                return pointers.angularSensibilityY;
             }
 
             return 0;
@@ -193,7 +193,7 @@ module BABYLON {
         public get pinchPrecision(): number {
             var pointers = <ArcRotateCameraPointersInput>this.inputs.attached["pointers"];
             if (pointers) {
-                return pointers.pinchPrecision;
+                return pointers.pinchPrecision;
             }
 
             return 0;
@@ -214,7 +214,7 @@ module BABYLON {
         public get pinchDeltaPercentage(): number {
             var pointers = <ArcRotateCameraPointersInput>this.inputs.attached["pointers"];
             if (pointers) {
-                return pointers.pinchDeltaPercentage;
+                return pointers.pinchDeltaPercentage;
             }
 
             return 0;
@@ -233,7 +233,7 @@ module BABYLON {
         public get panningSensibility(): number {
             var pointers = <ArcRotateCameraPointersInput>this.inputs.attached["pointers"];
             if (pointers) {
-                return pointers.panningSensibility;
+                return pointers.panningSensibility;
             }
 
             return 0;
@@ -252,7 +252,7 @@ module BABYLON {
         public get keysUp(): number[] {
             var keyboard = <ArcRotateCameraKeyboardMoveInput>this.inputs.attached["keyboard"];
             if (keyboard) {
-                return keyboard.keysUp;
+                return keyboard.keysUp;
             }
 
             return [];
@@ -261,7 +261,7 @@ module BABYLON {
         public set keysUp(value: number[]) {
             var keyboard = <ArcRotateCameraKeyboardMoveInput>this.inputs.attached["keyboard"];
             if (keyboard) {
-                keyboard.keysUp = value;
+                keyboard.keysUp = value;
             }
         }
 
@@ -271,7 +271,7 @@ module BABYLON {
         public get keysDown(): number[] {
             var keyboard = <ArcRotateCameraKeyboardMoveInput>this.inputs.attached["keyboard"];
             if (keyboard) {
-                return keyboard.keysDown;
+                return keyboard.keysDown;
             }
 
             return [];
@@ -280,7 +280,7 @@ module BABYLON {
         public set keysDown(value: number[]) {
             var keyboard = <ArcRotateCameraKeyboardMoveInput>this.inputs.attached["keyboard"];
             if (keyboard) {
-                keyboard.keysDown = value;
+                keyboard.keysDown = value;
             }
         }
 
@@ -290,7 +290,7 @@ module BABYLON {
         public get keysLeft(): number[] {
             var keyboard = <ArcRotateCameraKeyboardMoveInput>this.inputs.attached["keyboard"];
             if (keyboard) {
-                return keyboard.keysLeft;
+                return keyboard.keysLeft;
             }
 
             return [];
@@ -299,7 +299,7 @@ module BABYLON {
         public set keysLeft(value: number[]) {
             var keyboard = <ArcRotateCameraKeyboardMoveInput>this.inputs.attached["keyboard"];
             if (keyboard) {
-                keyboard.keysLeft = value;
+                keyboard.keysLeft = value;
             }
         }
 
@@ -309,7 +309,7 @@ module BABYLON {
         public get keysRight(): number[] {
             var keyboard = <ArcRotateCameraKeyboardMoveInput>this.inputs.attached["keyboard"];
             if (keyboard) {
-                return keyboard.keysRight;
+                return keyboard.keysRight;
             }
 
             return [];
@@ -318,7 +318,7 @@ module BABYLON {
         public set keysRight(value: number[]) {
             var keyboard = <ArcRotateCameraKeyboardMoveInput>this.inputs.attached["keyboard"];
             if (keyboard) {
-                keyboard.keysRight = value;
+                keyboard.keysRight = value;
             }
         }
 
@@ -328,7 +328,7 @@ module BABYLON {
         public get wheelPrecision(): number {
             var mousewheel = <ArcRotateCameraMouseWheelInput>this.inputs.attached["mousewheel"];
             if (mousewheel) {
-                return mousewheel.wheelPrecision;
+                return mousewheel.wheelPrecision;
             }
 
             return 0;
@@ -337,7 +337,7 @@ module BABYLON {
         public set wheelPrecision(value: number) {
             var mousewheel = <ArcRotateCameraMouseWheelInput>this.inputs.attached["mousewheel"];
             if (mousewheel) {
-                mousewheel.wheelPrecision = value;
+                mousewheel.wheelPrecision = value;
             }
         }
 
@@ -349,7 +349,7 @@ module BABYLON {
         public get wheelDeltaPercentage(): number {
             var mousewheel = <ArcRotateCameraMouseWheelInput>this.inputs.attached["mousewheel"];
             if (mousewheel) {
-                return mousewheel.wheelDeltaPercentage;
+                return mousewheel.wheelDeltaPercentage;
             }
 
             return 0;
@@ -358,7 +358,7 @@ module BABYLON {
         public set wheelDeltaPercentage(value: number) {
             var mousewheel = <ArcRotateCameraMouseWheelInput>this.inputs.attached["mousewheel"];
             if (mousewheel) {
-                mousewheel.wheelDeltaPercentage = value;
+                mousewheel.wheelDeltaPercentage = value;
             }
         }
 
@@ -660,7 +660,7 @@ module BABYLON {
         /** @hidden */
         public _isSynchronizedViewMatrix(): boolean {
             if (!super._isSynchronizedViewMatrix()) {
-                return false;
+                return false;
             }
 
             return this._cache._target.equals(this._getTargetPosition())
@@ -728,13 +728,13 @@ module BABYLON {
                 this.inertialBetaOffset *= this.inertia;
                 this.inertialRadiusOffset *= this.inertia;
                 if (Math.abs(this.inertialAlphaOffset) < Epsilon) {
-                    this.inertialAlphaOffset = 0;
+                    this.inertialAlphaOffset = 0;
                 }
                 if (Math.abs(this.inertialBetaOffset) < Epsilon) {
-                    this.inertialBetaOffset = 0;
+                    this.inertialBetaOffset = 0;
                 }
                 if (Math.abs(this.inertialRadiusOffset) < this.speed * Epsilon) {
-                    this.inertialRadiusOffset = 0;
+                    this.inertialRadiusOffset = 0;
                 }
             }
 
@@ -771,10 +771,10 @@ module BABYLON {
                 this.inertialPanningY *= this.panningInertia;
 
                 if (Math.abs(this.inertialPanningX) < this.speed * Epsilon) {
-                    this.inertialPanningX = 0;
+                    this.inertialPanningX = 0;
                 }
                 if (Math.abs(this.inertialPanningY) < this.speed * Epsilon) {
-                    this.inertialPanningY = 0;
+                    this.inertialPanningY = 0;
                 }
             }
 
@@ -814,9 +814,11 @@ module BABYLON {
 
             if (this.lowerRadiusLimit !== null && this.radius < this.lowerRadiusLimit) {
                 this.radius = this.lowerRadiusLimit;
+                this.inertialRadiusOffset = 0;
             }
             if (this.upperRadiusLimit !== null && this.radius > this.upperRadiusLimit) {
                 this.radius = this.upperRadiusLimit;
+                this.inertialRadiusOffset = 0;
             }
         }
 
@@ -925,8 +927,8 @@ module BABYLON {
 
                 this._computeViewMatrix(this.position, target, up);
 
-                this._viewMatrix.m[12] += this.targetScreenOffset.x;
-                this._viewMatrix.m[13] += this.targetScreenOffset.y;
+                this._viewMatrix.addAtIndex(12, this.targetScreenOffset.x);
+                this._viewMatrix.addAtIndex(13, this.targetScreenOffset.y);
             }
             this._currentTarget = target;
             return this._viewMatrix;
@@ -970,8 +972,8 @@ module BABYLON {
             }
 
             this._computeViewMatrix(this.position, target, up);
-            this._viewMatrix.m[12] += this.targetScreenOffset.x;
-            this._viewMatrix.m[13] += this.targetScreenOffset.y;
+            this._viewMatrix.addAtIndex(12, this.targetScreenOffset.x);
+            this._viewMatrix.addAtIndex(13, this.targetScreenOffset.y);
 
             this._collisionTriggered = false;
         }

+ 1 - 3
src/Debug/babylon.skeletonViewer.ts

@@ -65,9 +65,7 @@ module BABYLON.Debug {
             if (x !== 0 || y !== 0 || z !== 0) {
                 var tmat2 = Tmp.Matrix[1];
                 BABYLON.Matrix.IdentityToRef(tmat2);
-                tmat2.m[12] = x;
-                tmat2.m[13] = y;
-                tmat2.m[14] = z;
+                tmat2.setTranslationFromFloats(x, y, z);
                 tmat2.multiplyToRef(tmat, tmat);
             }
 

+ 14 - 13
src/Materials/Textures/babylon.texture.ts

@@ -430,10 +430,13 @@ module BABYLON {
             this._t1.subtractInPlace(this._t0);
             this._t2.subtractInPlace(this._t0);
 
-            Matrix.IdentityToRef(this._cachedTextureMatrix);
-            this._cachedTextureMatrix.m[0] = this._t1.x; this._cachedTextureMatrix.m[1] = this._t1.y; this._cachedTextureMatrix.m[2] = this._t1.z;
-            this._cachedTextureMatrix.m[4] = this._t2.x; this._cachedTextureMatrix.m[5] = this._t2.y; this._cachedTextureMatrix.m[6] = this._t2.z;
-            this._cachedTextureMatrix.m[8] = this._t0.x; this._cachedTextureMatrix.m[9] = this._t0.y; this._cachedTextureMatrix.m[10] = this._t0.z;
+            Matrix.FromValuesToRef(
+                this._t1.x, this._t1.y, this._t1.z, 0.0,
+                this._t2.x, this._t2.y, this._t2.z, 0.0,
+                this._t0.x, this._t0.y, this._t0.z, 0.0,
+                       0.0,        0.0,        0.0, 1.0,
+                this._cachedTextureMatrix
+            );
 
             let scene = this.getScene();
 
@@ -497,15 +500,13 @@ module BABYLON {
                     (<any>this._cachedTextureMatrix)[13] = this.vOffset;
                     break;
                 case Texture.PROJECTION_MODE:
-                    Matrix.IdentityToRef(this._projectionModeMatrix);
-
-                    this._projectionModeMatrix.m[0] = 0.5;
-                    this._projectionModeMatrix.m[5] = -0.5;
-                    this._projectionModeMatrix.m[10] = 0.0;
-                    this._projectionModeMatrix.m[12] = 0.5;
-                    this._projectionModeMatrix.m[13] = 0.5;
-                    this._projectionModeMatrix.m[14] = 1.0;
-                    this._projectionModeMatrix.m[15] = 1.0;
+                    Matrix.FromValuesToRef(
+                        0.5,  0.0, 0.0, 0.0,
+                        0.0, -0.5, 0.0, 0.0,
+                        0.0,  0.0, 0.0, 0.0,
+                        0.5,  0.5, 1.0, 1.0,
+                        this._projectionModeMatrix
+                    );
 
                     let projectionMatrix = scene.getProjectionMatrix();
                     this._cachedProjectionMatrixId = projectionMatrix.updateFlag;

文件差异内容过多而无法显示
+ 541 - 598
src/Math/babylon.math.ts


+ 25 - 9
src/babylon.scene.ts

@@ -1748,12 +1748,19 @@ module BABYLON {
          * The pickResult parameter can be obtained from a scene.pick or scene.pickWithRay
          * @param pickResult pickingInfo of the object wished to simulate pointer event on
          * @param pointerEventInit pointer event state to be used when simulating the pointer event (eg. pointer id for multitouch)
+         * @param doubleTap indicates that the pointer up event should be considered as part of a double click (false by default)
          * @returns the current scene
          */
-        public simulatePointerUp(pickResult: PickingInfo, pointerEventInit?: PointerEventInit): Scene {
+        public simulatePointerUp(pickResult: PickingInfo, pointerEventInit?: PointerEventInit, doubleTap?: boolean): Scene {
             let evt = new PointerEvent("pointerup", pointerEventInit);
             let clickInfo = new ClickInfo();
 
+            if (doubleTap) {
+                clickInfo.doubleClick = true;
+            } else {
+                clickInfo.singleClick = true;
+            }
+
             if (this._checkPrePointerObservable(pickResult, evt, PointerEventTypes.POINTERUP)) {
                 return this;
             }
@@ -1802,7 +1809,7 @@ module BABYLON {
                 this._pickedDownMesh.actionManager.processTrigger(ActionManager.OnPickOutTrigger, ActionEvent.CreateNew(this._pickedDownMesh, evt));
             }
 
-            let type = PointerEventTypes.POINTERUP;
+            let type = 0;
             if (this.onPointerObservable.hasObservers()) {
                 if (!clickInfo.ignore && !clickInfo.hasSwiped) {
                     if (clickInfo.singleClick && this.onPointerObservable.hasSpecificMask(PointerEventTypes.POINTERTAP)) {
@@ -1811,10 +1818,20 @@ module BABYLON {
                     else if (clickInfo.doubleClick && this.onPointerObservable.hasSpecificMask(PointerEventTypes.POINTERDOUBLETAP)) {
                         type = PointerEventTypes.POINTERDOUBLETAP;
                     }
+                    if (type) {
+                        let pi = new PointerInfo(type, evt, pickResult);
+                        this._setRayOnPointerInfo(pi);
+                        this.onPointerObservable.notifyObservers(pi, type);
+                    }
+                }
+
+                if (!clickInfo.ignore) {
+                    type = PointerEventTypes.POINTERUP;
+
+                    let pi = new PointerInfo(type, evt, pickResult);
+                    this._setRayOnPointerInfo(pi);
+                    this.onPointerObservable.notifyObservers(pi, type);
                 }
-                let pi = new PointerInfo(type, evt, pickResult);
-                this._setRayOnPointerInfo(pi);
-                this.onPointerObservable.notifyObservers(pi, type);
             }
 
             if (this.onPointerUp && !clickInfo.ignore) {
@@ -1981,8 +1998,9 @@ module BABYLON {
                     }
                 }
 
-                clickInfo.ignore = needToIgnoreNext;
-                cb(clickInfo, this._currentPickResult);
+                if (!needToIgnoreNext) {
+                    cb(clickInfo, this._currentPickResult);
+                }
             };
 
             this._onPointerMove = (evt: PointerEvent) => {
@@ -2080,8 +2098,6 @@ module BABYLON {
                                     }
                                 }
                             }
-                        }
-                        else {
                             if (this._checkPrePointerObservable(null, evt, PointerEventTypes.POINTERUP)) {
                                 return;
                             }

二进制
tests/validation/ReferenceImages/pointers.png


+ 6 - 0
tests/validation/config.json

@@ -2,6 +2,12 @@
   "root": "https://rawgit.com/BabylonJS/Website/master",
   "tests": [
     {
+      "title": "Pointers",
+      "playgroundId": "#1GLEJK#5",
+      "referenceImage": "pointers.png",
+      "excludeFromAutomaticTesting": true
+    },
+    {
       "title": "LineEdgesRenderer",
       "playgroundId": "#T90MQ4#1",
       "renderCount": 50,

+ 2 - 2
tests/validation/validation.js

@@ -232,7 +232,7 @@ function runTest(index, done) {
             return;
         }
 
-        var snippetUrl = "//babylonjs-api2.azurewebsites.net/snippets";
+        var snippetUrl = "https://snippet.babylonjs.com";
         var pgRoot = "/Playground"
 
         var retryTime = 500;
@@ -258,7 +258,7 @@ function runTest(index, done) {
                 if (xmlHttp.readyState === 4) {
                     try {
                         xmlHttp.onreadystatechange = null;
-                        var snippet = JSON.parse(xmlHttp.responseText)[0];
+                        var snippet = JSON.parse(xmlHttp.responseText);
                         var code = JSON.parse(snippet.jsonPayload).code.toString();
                         code = code.replace(/\/textures\//g, pgRoot + "/textures/");
                         code = code.replace(/"textures\//g, "\"" + pgRoot + "/textures/");