Selaa lähdekoodia

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

Trevor Baron 6 vuotta sitten
vanhempi
commit
0b92379813
100 muutettua tiedostoa jossa 54571 lisäystä ja 21561 poistoa
  1. 4 0
      .gitignore
  2. 7283 7071
      Playground/babylon.d.txt
  3. 3 2
      Playground/css/index.css
  4. 372 371
      Playground/index-local.html
  5. 7 30
      Playground/js/index.js
  6. 3 587
      Playground/js/libs/split.js
  7. 30 28
      Tools/DevLoader/BabylonLoader.js
  8. 4 2
      Tools/Gulp/config.json
  9. 3 4
      Tools/Gulp/gulpfile.js
  10. 3 5
      Tools/Gulp/package.json
  11. 7197 7055
      dist/preview release/babylon.d.ts
  12. 1 1
      dist/preview release/babylon.js
  13. 575 247
      dist/preview release/babylon.max.js
  14. 575 247
      dist/preview release/babylon.no-module.max.js
  15. 1 1
      dist/preview release/babylon.worker.js
  16. 575 247
      dist/preview release/es6.js
  17. 1 1
      dist/preview release/glTF2Interface/package.json
  18. 71 3
      dist/preview release/gui/babylon.gui.d.ts
  19. 1 1
      dist/preview release/gui/babylon.gui.js
  20. 1 1
      dist/preview release/gui/babylon.gui.min.js
  21. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  22. 142 6
      dist/preview release/gui/babylon.gui.module.d.ts
  23. 2 2
      dist/preview release/gui/package.json
  24. 36120 1
      dist/preview release/inspector/babylon.inspector.bundle.js
  25. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js.map
  26. 11 1038
      dist/preview release/inspector/babylon.inspector.d.ts
  27. 27 2366
      dist/preview release/inspector/babylon.inspector.module.d.ts
  28. 5 5
      dist/preview release/inspector/package.json
  29. 1 1
      dist/preview release/inspector/readme.md
  30. 8 0
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  31. 58 35
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  32. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  33. 8 0
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  34. 58 35
      dist/preview release/loaders/babylon.glTFFileLoader.js
  35. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  36. 8 0
      dist/preview release/loaders/babylonjs.loaders.d.ts
  37. 58 35
      dist/preview release/loaders/babylonjs.loaders.js
  38. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  39. 8 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  40. 3 3
      dist/preview release/loaders/package.json
  41. 2 2
      dist/preview release/materialsLibrary/babylon.gridMaterial.js
  42. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.min.js
  43. 2 2
      dist/preview release/materialsLibrary/babylonjs.materials.js
  44. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  45. 2 2
      dist/preview release/materialsLibrary/package.json
  46. 2 2
      dist/preview release/postProcessesLibrary/package.json
  47. 2 2
      dist/preview release/proceduralTexturesLibrary/package.json
  48. 3 3
      dist/preview release/serializers/package.json
  49. 5 19
      dist/preview release/viewer/babylon.viewer.d.ts
  50. 1 1
      dist/preview release/viewer/babylon.viewer.js
  51. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  52. 5 22
      dist/preview release/viewer/babylon.viewer.module.d.ts
  53. 10 2
      dist/preview release/what's new.md
  54. 71 20
      gui/src/2D/advancedDynamicTexture.ts
  55. 22 10
      gui/src/2D/controls/colorpicker.ts
  56. 29 2
      gui/src/2D/controls/container.ts
  57. 75 1
      gui/src/2D/controls/control.ts
  58. 59 11
      gui/src/2D/controls/grid.ts
  59. 25 23
      gui/src/2D/controls/inputText.ts
  60. 3 1
      gui/src/2D/valueAndUnit.ts
  61. 8 0
      gui/src/3D/controls/control3D.ts
  62. 1 0
      gui/src/3D/gui3DManager.ts
  63. 1 11
      gui/webpack.config.js
  64. 5 4
      inspector/index.html
  65. 26 15
      inspector/package.json
  66. 0 156
      inspector/sass/_detailPanel.scss
  67. 0 18
      inspector/sass/_resizeBar.scss
  68. 0 19
      inspector/sass/_searchbar.scss
  69. 0 74
      inspector/sass/_slider.scss
  70. 0 92
      inspector/sass/_tabPanel.scss
  71. 0 60
      inspector/sass/_tabbar.scss
  72. 0 31
      inspector/sass/_toolbar.scss
  73. 0 14
      inspector/sass/_tooltip.scss
  74. 0 73
      inspector/sass/_tree.scss
  75. 0 16
      inspector/sass/_treeTool.scss
  76. 0 28
      inspector/sass/defines.scss
  77. 0 105
      inspector/sass/main.scss
  78. 0 51
      inspector/sass/tabs/_consoleTab.scss
  79. 0 92
      inspector/sass/tabs/_gltfTab.scss
  80. 0 53
      inspector/sass/tabs/_shaderTab.scss
  81. 0 52
      inspector/sass/tabs/_statsTab.scss
  82. 0 80
      inspector/sass/tabs/_toolsTab.scss
  83. BIN
      inspector/screens/tab_mesh.jpg
  84. BIN
      inspector/screens/tools.jpg
  85. 0 441
      inspector/src/Inspector.ts
  86. 0 43
      inspector/src/adapters/Adapter.ts
  87. 0 56
      inspector/src/adapters/CameraAdapter.ts
  88. 0 48
      inspector/src/adapters/GUIAdapter.ts
  89. 0 51
      inspector/src/adapters/LightAdapter.ts
  90. 0 37
      inspector/src/adapters/MaterialAdapter.ts
  91. 0 116
      inspector/src/adapters/MeshAdapter.ts
  92. 0 59
      inspector/src/adapters/PhysicsImpostorAdapter.ts
  93. 0 52
      inspector/src/adapters/SoundAdapter.ts
  94. 0 40
      inspector/src/adapters/TextureAdapter.ts
  95. 0 9
      inspector/src/adapters/index.ts
  96. 753 0
      inspector/src/components/actionTabs/actionTabs.scss
  97. 133 0
      inspector/src/components/actionTabs/actionTabsComponent.tsx
  98. 59 0
      inspector/src/components/actionTabs/lineContainerComponent.tsx
  99. 31 0
      inspector/src/components/actionTabs/lines/booleanLineComponent.tsx
  100. 0 0
      inspector/src/components/actionTabs/lines/buttonLineComponent.tsx

+ 4 - 0
.gitignore

@@ -189,3 +189,7 @@ Viewer/tests/Lib/**/*.js
 Viewer/tests/commons/**/*.js
 .sass-cache/
 gui/dist/
+/Viewer/tests/tsc
+/Viewer/tests/tsc.cmd
+/Viewer/tests/tsserver
+/Viewer/tests/tsserver.cmd

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7283 - 7071
Playground/babylon.d.txt


+ 3 - 2
Playground/css/index.css

@@ -246,6 +246,8 @@ body {
     width: 100%;
     height: 100%;
     touch-action: none;
+    display: block;
+    font-size: 0;
 }
 #fpsLabel {
     position: absolute;
@@ -472,7 +474,6 @@ body {
     padding:20px;
     border-radius: 5px;
     color:white;
-    font-family: 'Inconsolata';
 }
 #errorZone button {
     position:absolute;
@@ -508,7 +509,7 @@ body {
 .navbarBottom #statusBar {
     line-height:30px;
     color: #E74C3C;
-    font-family: 'Inconsolata';
+    font-size: 14px;
     padding-left:20px;
 }
 

+ 372 - 371
Playground/index-local.html

@@ -1,456 +1,457 @@
 <!DOCTYPE html>
 <html>
 
-    <head>
-        <title>Babylon.js Playground</title>
-        <meta charset='utf-8' />
-        <meta name="viewport" content="width=device-width, user-scalable=no">
-        <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>
-        <!-- Dependencies -->
-        <script src="../dist/preview%20release/ammo.js"></script>
-        <script src="../dist/preview%20release/cannon.js"></script>
-        <script src="../dist/preview%20release/Oimo.js"></script>
-        <script src="../dist/preview%20release/gltf_validator.js"></script>
-        <script src="../dist/preview%20release/earcut.min.js"></script>
-        <!-- Monaco -->
-
-        <!-- Babylon.js -->
-        <script src="../tools/DevLoader/BabylonLoader.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>
+<head>
+    <title>Babylon.js Playground</title>
+    <meta charset='utf-8' />
+    <meta name="viewport" content="width=device-width, user-scalable=no">
+    <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>
+    <!-- Dependencies -->
+    <script src="../dist/preview%20release/cannon.js"></script>
+    <script src="../dist/preview%20release/Oimo.js"></script>
+    <script src="../dist/preview%20release/ammo.js"></script>
+    <script src="../dist/preview%20release/gltf_validator.js"></script>
+    <script src="../dist/preview%20release/earcut.min.js"></script>
+    <!-- Monaco -->
+
+    <!-- Babylon.js -->
+    <script src="../tools/DevLoader/BabylonLoader.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>
 
 
-            <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>
-                        <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 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" 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 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 uncheck" id="debugButton1600">Inspector</div>
-                <div class="button" id="metadataButton1600">Metadata</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('2.5');">2.5</div>
-                    </div>
-                </div>
-                <div class="button select">
-                    <span class="examplesButton">Examples</span>
+
+        <div class="category right">
+            <div class="button select">
+                <span id="currentVersion1600">Version: Latest</span>
+                <div class="toDisplay">
+                    <div class="option" onclick="setVersion('latest');">Latest</div>
+                    <div class="option" onclick="setVersion('2.5');">2.5</div>
                 </div>
             </div>
+            <div class="button select">
+                <span class="examplesButton">Examples</span>
+            </div>
         </div>
+    </div>
 
-        <div class="navbar navBar1475">
-            <div class="title">
-                Babylon.js Playground
-            </div>
-            <div class="version" id="mainTitle">
-            </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 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 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 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>
-                        <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('2.5');">2.5</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('2.5');">2.5</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 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 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>
-                        <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('2.5');">2.5</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('2.5');">2.5</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>
-                        <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 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="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('2.5');">2.5</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('2.5');">2.5</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 id="waitDiv">
-            <span id="waitTitle">Babylon.js Playground
-                <BR>
-                <BR>
-                <BR>
-            </span>
-            <img src="waitlogo.png" id="waitLogo" />
-        </div>
-
-        <script src="https://code.jquery.com/jquery.js"></script>
-
-        <script src="js/actions.js"></script>
-        <script src="js/pbt.js"></script>
-        <script>
-            BABYLONDEVTOOLS.Loader
-                .require('node_modules/monaco-editor/min/vs/loader.js')
-                .require('js/index.js')
-                .load(function () {
-                    BABYLON.DracoCompression.Configuration.decoder = {
-                        wasmUrl: "../dist/preview%20release/draco_wasm_wrapper_gltf.js",
-                        wasmBinaryUrl: "../dist/preview%20release/draco_decoder_gltf.wasm",
-                        fallbackUrl: "../dist/preview%20release/draco_decoder_gltf.js"
-                    };
-                });
-        </script>
-    </body>
-
-</html>
+    </div>
+
+    <div id="waitDiv">
+        <span id="waitTitle">Babylon.js Playground
+            <BR>
+            <BR>
+            <BR>
+        </span>
+        <img src="waitlogo.png" id="waitLogo" />
+    </div>
+
+    <script src="https://code.jquery.com/jquery.js"></script>
+
+    <script src="js/actions.js"></script>
+    <script src="js/pbt.js"></script>
+    <script>
+        BABYLONDEVTOOLS.Loader
+            .require('node_modules/monaco-editor/min/vs/loader.js')
+            .require('js/index.js')
+            .load(function() {
+                BABYLON.DracoCompression.Configuration.decoder = {
+                    wasmUrl: "../dist/preview%20release/draco_wasm_wrapper_gltf.js",
+                    wasmBinaryUrl: "../dist/preview%20release/draco_decoder_gltf.wasm",
+                    fallbackUrl: "../dist/preview%20release/draco_decoder_gltf.js"
+                };
+            });
+    </script>
+</body>
+
+</html>

+ 7 - 30
Playground/js/index.js

@@ -498,29 +498,11 @@ function showError(errorMessage, errorEvent) {
                 }
 
                 var showInspector = false;
-                var showDebugLayer = false;
-                var initialTabIndex = 0;
                 showBJSPGMenu();
                 jsEditor.updateOptions({ readOnly: false });
 
-                if (document.getElementsByClassName('insp-wrapper').length > 0) {
-                    for (var i = 0; i < engine.scenes.length; i++) {
-                        if (engine.scenes[i]._debugLayer) {
-                            //TODO: once inspector is updated on netlify, use getActiveTabIndex instead of the following loop
-                            //initialTabIndex = engine.scenes[i]._debugLayer._inspector.getActiveTabIndex();
-                            var tabs = engine.scenes[i]._debugLayer._inspector._tabbar._tabs;
-                            for (var j = 0; j < tabs.length; j++) {
-                                if (tabs[j].isActive()) {
-                                    initialTabIndex = j;
-                                    break;
-                                }
-                            }
-                            break;
-                        }
-                    }
+                if (BABYLON.Engine.LastCreatedScene && BABYLON.Engine.LastCreatedScene.debugLayer.isVisible()) {
                     showInspector = true;
-                } else if (document.getElementById('DebugLayer')) {
-                    showDebugLayer = true;
                 }
 
                 if (engine) {
@@ -644,12 +626,9 @@ function showError(errorMessage, errorEvent) {
 
                     if (scene) {
                         if (showInspector) {
-                            scene.debugLayer.show({ initialTab: initialTabIndex });
-                            scene.executeWhenReady(function() {
-                                scene.debugLayer._inspector.refresh();
-                            })
-                        } else if (showDebugLayer) {
-                            scene.debugLayer.show();
+                            if (!scene.debugLayer.isVisible()) {
+                                scene.debugLayer.show({ embedMode: true });
+                            }
                         }
                     }
                 });
@@ -905,8 +884,7 @@ function showError(errorMessage, errorEvent) {
             engine.resize();
 
             if (scene.debugLayer.isVisible()) {
-                scene.debugLayer.hide();  // Because when you close it with the cross, it doesn't call hide(), so you have to do it in code
-                scene.debugLayer.show();
+                scene.debugLayer.show({ embedMode: true });
             }
         }
 
@@ -969,12 +947,11 @@ function showError(errorMessage, errorEvent) {
         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]) {
+            if (scene.debugLayer.isVisible()) {
                 scene.debugLayer.hide();
             }
             else {
-                scene.debugLayer.hide(); // Because when you close it with the cross, it doesn't call hide(), so you have to do it in code
-                scene.debugLayer.show();
+                scene.debugLayer.show({ embedMode: true });
             }
         }
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 587
Playground/js/libs/split.js


+ 30 - 28
Tools/DevLoader/BabylonLoader.js

@@ -1,12 +1,12 @@
 // Old Fashion Way for IE 11 Devs. Yes, that still exists ;-)
 
 var BABYLONDEVTOOLS;
-(function (BABYLONDEVTOOLS) {
+(function(BABYLONDEVTOOLS) {
 
-    var getJson = function (url, callback, errorCallback) {
+    var getJson = function(url, callback, errorCallback) {
         var xhr = new XMLHttpRequest();
         xhr.open('GET', url);
-        xhr.onload = function () {
+        xhr.onload = function() {
             if (this.status >= 200 && this.status < 300) {
                 var data = JSON.parse(xhr.response);
                 callback(data)
@@ -17,7 +17,7 @@ var BABYLONDEVTOOLS;
                 });
             }
         };
-        xhr.onerror = function () {
+        xhr.onerror = function() {
             errorCallback({
                 status: this.status,
                 statusText: xhr.statusText
@@ -26,11 +26,12 @@ var BABYLONDEVTOOLS;
         xhr.send();
     }
 
-    var Loader = (function () {
+    var Loader = (function() {
         var queue;
         var callback;
         var dependencies;
         var useDist;
+        var testMode;
         var min;
         var babylonJSPath;
 
@@ -43,10 +44,10 @@ var BABYLONDEVTOOLS;
             babylonJSPath = '';
         }
 
-        Loader.prototype.debugShortcut = function (engine) {
+        Loader.prototype.debugShortcut = function(engine) {
             // Add inspector shortcut
             var map = {};
-            var onkey = function (e) {
+            var onkey = function(e) {
                 e = e || event; // to deal with IE
                 map[e.keyCode] = e.type == 'keydown';
                 if (map[17] && map[16] && map[18] && map[73]) {
@@ -69,12 +70,12 @@ var BABYLONDEVTOOLS;
             document.addEventListener("keyup", onkey);
         }
 
-        Loader.prototype.root = function (newBabylonJSPath) {
+        Loader.prototype.root = function(newBabylonJSPath) {
             babylonJSPath = newBabylonJSPath;
             return this;
         }
 
-        Loader.prototype.require = function (newDependencies) {
+        Loader.prototype.require = function(newDependencies) {
             if (typeof newDependencies === 'string') {
                 dependencies.push(newDependencies);
             }
@@ -86,17 +87,22 @@ var BABYLONDEVTOOLS;
             return this;
         }
 
-        Loader.prototype.onReady = function (newCallback) {
+        Loader.prototype.onReady = function(newCallback) {
             callback = newCallback;
             return this;
         }
 
-        Loader.prototype.useDist = function () {
+        Loader.prototype.testMode = function() {
+            testMode = true;
+            return this;
+        }
+
+        Loader.prototype.useDist = function() {
             useDist = true;
             return this;
         }
 
-        Loader.prototype.dequeue = function () {
+        Loader.prototype.dequeue = function() {
             if (queue.length == 0) {
                 console.log('Scripts loaded');
                 BABYLON.Engine.ShadersRepository = "/src/Shaders/";
@@ -114,17 +120,17 @@ var BABYLONDEVTOOLS;
             script.src = url;
 
             var self = this;
-            script.onload = function () {
+            script.onload = function() {
                 self.dequeue();
             };
             head.appendChild(script);
         }
 
-        Loader.prototype.loadScript = function (url) {
+        Loader.prototype.loadScript = function(url) {
             queue.push(url);
         }
 
-        Loader.prototype.loadCss = function (url) {
+        Loader.prototype.loadCss = function(url) {
             var head = document.getElementsByTagName('head')[0];
 
             var style = document.createElement('link');
@@ -134,13 +140,13 @@ var BABYLONDEVTOOLS;
             document.head.appendChild(style);
         }
 
-        Loader.prototype.loadScripts = function (urls) {
+        Loader.prototype.loadScripts = function(urls) {
             for (var i = 0; i < urls.length; i++) {
                 this.loadScript(urls[i]);
             }
         }
 
-        Loader.prototype.loadLibrary = function (library, module) {
+        Loader.prototype.loadLibrary = function(library, module) {
             if (library.preventLoadLibrary) {
                 return;
             }
@@ -189,7 +195,7 @@ var BABYLONDEVTOOLS;
                 }
             }
             else {
-                if (module.build.distOutputDirectory)
+                if (module.build.distOutputDirectory && (!testMode || !module.build.ignoreInTestMode))
                     this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output);
             }
 
@@ -201,13 +207,13 @@ var BABYLONDEVTOOLS;
             }
         }
 
-        Loader.prototype.loadModule = function (module) {
+        Loader.prototype.loadModule = function(module) {
             for (var i = 0; i < module.libraries.length; i++) {
                 this.loadLibrary(module.libraries[i], module);
             }
         }
 
-        Loader.prototype.processDependency = function (settings, dependency, filesToLoad) {
+        Loader.prototype.processDependency = function(settings, dependency, filesToLoad) {
             if (dependency.dependUpon) {
                 for (var i = 0; i < dependency.dependUpon.length; i++) {
                     var dependencyName = dependency.dependUpon[i];
@@ -225,7 +231,7 @@ var BABYLONDEVTOOLS;
             }
         }
 
-        Loader.prototype.loadBJSScripts = function (settings) {
+        Loader.prototype.loadBJSScripts = function(settings) {
             var loadModules = true;
 
             // Main bjs files
@@ -262,17 +268,13 @@ var BABYLONDEVTOOLS;
             }
         }
 
-        Loader.prototype.load = function (newCallback) {
+        Loader.prototype.load = function(newCallback) {
             var self = this;
             if (newCallback) {
                 callback = newCallback;
             }
             getJson('/Tools/Gulp/config.json',
-                function (data) {
-                    if (!min) {
-                        self.loadScript('/dist/preview release/split.js');
-                    }
-
+                function(data) {
                     self.loadBJSScripts(data);
                     if (dependencies) {
                         self.loadScripts(dependencies);
@@ -280,7 +282,7 @@ var BABYLONDEVTOOLS;
 
                     self.dequeue();
                 },
-                function (reason) {
+                function(reason) {
                     console.error(reason);
                 }
             );

+ 4 - 2
Tools/Gulp/config.json

@@ -1964,7 +1964,7 @@
                 "main": "../../dist/preview release/gui/build/index.d.ts",
                 "out": "../babylon.gui.module.d.ts",
                 "baseDir": "../../dist/preview release/gui/build/",
-                "headerText": "BabylonJS GUI"
+                "headerText": "Babylon.js GUI"
             },
             "processDeclaration": {
                 "filename": "babylon.gui.module.d.ts",
@@ -1988,10 +1988,12 @@
                 "webpack": "../../inspector/webpack.config.js",
                 "bundle": "true",
                 "extendsRoot": true,
+                "babylonIncluded": false,
                 "useOutputForDebugging": true
             }
         ],
         "build": {
+            "ignoreInTestMode": true,
             "srcOutputDirectory": "../../inspector/src/",
             "distOutputDirectory": "/inspector/",
             "dtsBundle": {
@@ -1999,7 +2001,7 @@
                 "main": "../../dist/preview release/inspector/build/index.d.ts",
                 "out": "../babylon.inspector.module.d.ts",
                 "baseDir": "../../dist/preview release/inspector/build/",
-                "headerText": "BabylonJS Inspector"
+                "headerText": "Babylon.js Inspector"
             },
             "processDeclaration": {
                 "filename": "babylon.inspector.module.d.ts",

+ 3 - 4
Tools/Gulp/gulpfile.js

@@ -274,7 +274,7 @@ gulp.task("build", gulp.series("shaders", function build() {
 * TsLint all typescript files from the src directory.
 */
 gulp.task("typescript-tsLint", function() {
-    const dtsFilter = filter(['**', '!**/*.d.ts'], {restore: false});
+    const dtsFilter = filter(['**', '!**/*.d.ts'], { restore: false });
     return gulp.src(config.typescript)
         .pipe(dtsFilter)
         .pipe(gulpTslint({
@@ -348,7 +348,7 @@ gulp.task("tsLint", gulp.series("typescript-tsLint", "typescript-libraries-tsLin
 * Compiles all typescript files and creating a js and a declaration file.
 */
 gulp.task("typescript-compile", function() {
-    const dtsFilter = filter(['**', '!**/*.d.ts'], {restore: false});
+    const dtsFilter = filter(['**', '!**/*.d.ts'], { restore: false });
     var tsResult = gulp.src(config.typescript)
         .pipe(dtsFilter)
         .pipe(sourcemaps.init())
@@ -686,7 +686,6 @@ var buildExternalLibrary = function(library, settings, watch) {
                         cb();
                     }))
                     .pipe(rename(function(path) {
-                        console.log(path.basename);
                         //path.extname === ".js"
                         path.basename = path.basename.replace(".min", "")
                     })).pipe(gulp.dest(outputDirectory));
@@ -883,7 +882,7 @@ gulp.task("netlify-cleanup", function() {
 
 // this is needed for the modules for the declaration files.
 gulp.task("modules-compile", function() {
-    const dtsFilter = filter(['**', '!**/*.d.ts'], {restore: false});
+    const dtsFilter = filter(['**', '!**/*.d.ts'], { restore: false });
     var tsResult = gulp.src(config.typescript)
         .pipe(dtsFilter)
         .pipe(sourcemaps.init())

+ 3 - 5
Tools/Gulp/package.json

@@ -49,13 +49,11 @@
         "typedoc": "^0.12.0",
         "typescript": "~3.0.1",
         "webpack": "^4.16.3",
-        "webpack-stream": "5.0.0"
+        "webpack-stream": "5.0.0",
+        "dts-bundle": "^0.7.3",
+        "gulp-clean": "^0.4.0"
     },
     "scripts": {
         "install": "cd ../../gui && npm install && cd ../Tools/Gulp/ &&  cd ../../inspector && npm install && cd ../Tools/Gulp/ && npm --prefix ../../Playground/ install ../../Playground/ && npm --prefix ../../tests/unit/ install ../../tests/unit/ && npm --prefix ../../Viewer/tests/ install ../../Viewer/tests/ && cd ../../Viewer && npm install && cd ../Tools/Gulp/ && gulp deployLocalDev"
-    },
-    "dependencies": {
-        "dts-bundle": "^0.7.3",
-        "gulp-clean": "^0.4.0"
     }
 }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7197 - 7055
dist/preview release/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/babylon.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 575 - 247
dist/preview release/babylon.max.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 575 - 247
dist/preview release/babylon.no-module.max.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/babylon.worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 575 - 247
dist/preview release/es6.js


+ 1 - 1
dist/preview release/glTF2Interface/package.json

@@ -1,7 +1,7 @@
 {
     "name": "babylonjs-gltf2interface",
     "description": "A typescript declaration of babylon's gltf2 inteface.",
-    "version": "4.0.0-alpha.6",
+    "version": "4.0.0-alpha.7",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

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

@@ -1,4 +1,4 @@
-/*BabylonJS GUI*/
+/*Babylon.js GUI*/
 // Dependencies for this module:
 //   ../../../../Tools/Gulp/babylonjs
 declare module BABYLON.GUI {
@@ -60,11 +60,17 @@ declare module BABYLON.GUI {
             _layerToDispose: BABYLON.Nullable<BABYLON.Layer>;
             /** @hidden */
             _linkedControls: Control[];
+            /** @hidden */
+            _needRedraw: boolean;
             /**
                 * BABYLON.Observable event triggered each time an clipboard event is received from the rendering canvas
                 */
             onClipboardObservable: BABYLON.Observable<BABYLON.ClipboardInfo>;
             /**
+                * BABYLON.Observable event triggered each time a pointer down is intercepted by a control
+                */
+            onControlPickedObservable: BABYLON.Observable<Control>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -106,6 +112,19 @@ declare module BABYLON.GUI {
                 */
             readonly rootContainer: Container;
             /**
+                * Returns an array containing the root container.
+                * This is mostly used to let the Inspector introspects the ADT
+                * @returns an array containing the rootContainer
+                */
+            getChildren(): Array<Container>;
+            /**
+                * Will return all controls that are inside this texture
+                * @param directDescendantsOnly defines if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered
+                * @param predicate defines an optional predicate that will be called on every evaluated child, the predicate must return true for a given child to be part of the result, otherwise it will be ignored
+                * @return all child controls
+                */
+            getDescendants(directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): Control[];
+            /**
                 * Gets or sets the current focused control
                 */
             focusedControl: BABYLON.Nullable<IFocusableControl>;
@@ -128,6 +147,11 @@ declare module BABYLON.GUI {
              */
             constructor(name: string, width: number | undefined, height: number | undefined, scene: BABYLON.Nullable<BABYLON.Scene>, generateMipMaps?: boolean, samplingMode?: number);
             /**
+                * Get the current class name of the texture useful for serialization or dynamic coding.
+                * @returns "AdvancedDynamicTexture"
+                */
+            getClassName(): string;
+            /**
                 * Function used to execute a function on all controls
                 * @param func defines the function to execute
                 * @param container defines the container where controls belong. If null the root container will be used
@@ -171,6 +195,8 @@ declare module BABYLON.GUI {
             /** @hidden */
             _changeCursor(cursor: string): void;
             /** @hidden */
+            _registerLastControlDown(control: Control, pointerId: number): void;
+            /** @hidden */
             _cleanControlAfterRemovalFromList(list: {
                     [pointerId: number]: Control;
             }, control: Control): void;
@@ -818,6 +844,8 @@ declare module BABYLON.GUI {
             /** @hidden */
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
             /** @hidden */
+            _getDescendants(results: Control[], directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): void;
+            /** @hidden */
             _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
             /** @hidden */
             protected _clipForChildren(context: CanvasRenderingContext2D): void;
@@ -879,6 +907,14 @@ declare module BABYLON.GUI {
             protected _disabledColor: string;
             /** @hidden */
             _tag: any;
+            /**
+                * Gets or sets the unique id of the node. Please note that this number will be updated when the control is added to a container
+                */
+            uniqueId: number;
+            /**
+                * Gets or sets an object used to store user defined information for the node
+                */
+            metadata: any;
             /** Gets or sets a boolean indicating if the control can be hit with pointer events */
             isHitTestVisible: boolean;
             /** Gets or sets a boolean indicating if the control can block pointer events */
@@ -904,6 +940,11 @@ declare module BABYLON.GUI {
             /** Gets the control type name */
             readonly typeName: string;
             /**
+                * Get the current class name of the control.
+                * @returns current class name
+                */
+            getClassName(): string;
+            /**
              * An event triggered when the pointer move over the control.
              */
             onPointerMoveObservable: BABYLON.Observable<BABYLON.Vector2>;
@@ -947,6 +988,10 @@ declare module BABYLON.GUI {
             };
             /** Gets or sets alpha value for the control (1 means opaque and 0 means entirely transparent) */
             alpha: number;
+            /**
+                * Gets or sets a boolean indicating that we want to highlight the control (mostly for debugging purpose)
+                */
+            isHighlighted: boolean;
             /** Gets or sets a value indicating the scale factor on X axis (1 by default)
                 * @see http://doc.babylonjs.com/how_to/gui#rotation-and-scaling
              */
@@ -1158,6 +1203,15 @@ declare module BABYLON.GUI {
                 * @param scene defines the hosting scene
                 */
             moveToVector3(position: BABYLON.Vector3, scene: BABYLON.Scene): void;
+            /** @hidden */
+            _getDescendants(results: Control[], directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): void;
+            /**
+                * Will return all controls that have this control as ascendant
+                * @param directDescendantsOnly defines if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered
+                * @param predicate defines an optional predicate that will be called on every evaluated child, the predicate must return true for a given child to be part of the result, otherwise it will be ignored
+                * @return all child controls
+                */
+            getDescendants(directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): Control[];
             /**
                 * Link current control with a target mesh
                 * @param mesh defines the mesh to link with
@@ -1179,6 +1233,10 @@ declare module BABYLON.GUI {
             /** @hidden */
             protected _transform(context: CanvasRenderingContext2D): void;
             /** @hidden */
+            _renderHighlight(context: CanvasRenderingContext2D): void;
+            /** @hidden */
+            protected _renderHighlightSpecific(context: CanvasRenderingContext2D): void;
+            /** @hidden */
             protected _applyStates(context: CanvasRenderingContext2D): void;
             /** @hidden */
             protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): boolean;
@@ -1357,7 +1415,10 @@ declare module BABYLON.GUI {
                 */
             constructor(name?: string | undefined);
             protected _getTypeName(): string;
+            protected _getGridDefinitions(definitionCallback: (lefts: number[], tops: number[], widths: number[], heights: number[]) => void): void;
             protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+            _flagDescendantsAsMatrixDirty(): void;
+            protected _renderHighlightSpecific(context: CanvasRenderingContext2D): void;
             /** Releases associated resources */
             dispose(): void;
     }
@@ -1473,9 +1534,11 @@ declare module BABYLON.GUI {
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
-            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            /** Gets or sets the text highlighter transparency; default: 0.4 */
             highligherOpacity: number;
-            /** Gets and sets the text hightlight color */
+            /** Gets or sets a boolean indicating whether to select complete text by default on input focus */
+            onFocusSelectAll: boolean;
+            /** Gets or sets the text hightlight color */
             textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;
@@ -2450,6 +2513,11 @@ declare module BABYLON.GUI {
                 * Gets a string representing the class name
                 */
             readonly typeName: string;
+            /**
+                * Get the current class name of the control.
+                * @returns current class name
+                */
+            getClassName(): string;
             protected _getTypeName(): string;
             /**
                 * Gets the transform node used by this control

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/gui/babylon.gui.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


+ 142 - 6
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1,4 +1,4 @@
-/*BabylonJS GUI*/
+/*Babylon.js GUI*/
 // Dependencies for this module:
 //   ../../../../Tools/Gulp/babylonjs
 
@@ -105,11 +105,17 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
             _layerToDispose: Nullable<Layer>;
             /** @hidden */
             _linkedControls: Control[];
+            /** @hidden */
+            _needRedraw: boolean;
             /**
                 * Observable event triggered each time an clipboard event is received from the rendering canvas
                 */
             onClipboardObservable: Observable<ClipboardInfo>;
             /**
+                * Observable event triggered each time a pointer down is intercepted by a control
+                */
+            onControlPickedObservable: Observable<Control>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -151,6 +157,19 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
                 */
             readonly rootContainer: Container;
             /**
+                * Returns an array containing the root container.
+                * This is mostly used to let the Inspector introspects the ADT
+                * @returns an array containing the rootContainer
+                */
+            getChildren(): Array<Container>;
+            /**
+                * Will return all controls that are inside this texture
+                * @param directDescendantsOnly defines if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered
+                * @param predicate defines an optional predicate that will be called on every evaluated child, the predicate must return true for a given child to be part of the result, otherwise it will be ignored
+                * @return all child controls
+                */
+            getDescendants(directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): Control[];
+            /**
                 * Gets or sets the current focused control
                 */
             focusedControl: Nullable<IFocusableControl>;
@@ -173,6 +192,11 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
              */
             constructor(name: string, width: number | undefined, height: number | undefined, scene: Nullable<Scene>, generateMipMaps?: boolean, samplingMode?: number);
             /**
+                * Get the current class name of the texture useful for serialization or dynamic coding.
+                * @returns "AdvancedDynamicTexture"
+                */
+            getClassName(): string;
+            /**
                 * Function used to execute a function on all controls
                 * @param func defines the function to execute
                 * @param container defines the container where controls belong. If null the root container will be used
@@ -216,6 +240,8 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
             /** @hidden */
             _changeCursor(cursor: string): void;
             /** @hidden */
+            _registerLastControlDown(control: Control, pointerId: number): void;
+            /** @hidden */
             _cleanControlAfterRemovalFromList(list: {
                     [pointerId: number]: Control;
             }, control: Control): void;
@@ -917,6 +943,8 @@ declare module 'babylonjs-gui/2D/controls/container' {
             /** @hidden */
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
             /** @hidden */
+            _getDescendants(results: Control[], directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): void;
+            /** @hidden */
             _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
             /** @hidden */
             protected _clipForChildren(context: CanvasRenderingContext2D): void;
@@ -986,6 +1014,14 @@ declare module 'babylonjs-gui/2D/controls/control' {
             protected _disabledColor: string;
             /** @hidden */
             _tag: any;
+            /**
+                * Gets or sets the unique id of the node. Please note that this number will be updated when the control is added to a container
+                */
+            uniqueId: number;
+            /**
+                * Gets or sets an object used to store user defined information for the node
+                */
+            metadata: any;
             /** Gets or sets a boolean indicating if the control can be hit with pointer events */
             isHitTestVisible: boolean;
             /** Gets or sets a boolean indicating if the control can block pointer events */
@@ -1011,6 +1047,11 @@ declare module 'babylonjs-gui/2D/controls/control' {
             /** Gets the control type name */
             readonly typeName: string;
             /**
+                * Get the current class name of the control.
+                * @returns current class name
+                */
+            getClassName(): string;
+            /**
              * An event triggered when the pointer move over the control.
              */
             onPointerMoveObservable: Observable<Vector2>;
@@ -1054,6 +1095,10 @@ declare module 'babylonjs-gui/2D/controls/control' {
             };
             /** Gets or sets alpha value for the control (1 means opaque and 0 means entirely transparent) */
             alpha: number;
+            /**
+                * Gets or sets a boolean indicating that we want to highlight the control (mostly for debugging purpose)
+                */
+            isHighlighted: boolean;
             /** Gets or sets a value indicating the scale factor on X axis (1 by default)
                 * @see http://doc.babylonjs.com/how_to/gui#rotation-and-scaling
              */
@@ -1265,6 +1310,15 @@ declare module 'babylonjs-gui/2D/controls/control' {
                 * @param scene defines the hosting scene
                 */
             moveToVector3(position: Vector3, scene: Scene): void;
+            /** @hidden */
+            _getDescendants(results: Control[], directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): void;
+            /**
+                * Will return all controls that have this control as ascendant
+                * @param directDescendantsOnly defines if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered
+                * @param predicate defines an optional predicate that will be called on every evaluated child, the predicate must return true for a given child to be part of the result, otherwise it will be ignored
+                * @return all child controls
+                */
+            getDescendants(directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): Control[];
             /**
                 * Link current control with a target mesh
                 * @param mesh defines the mesh to link with
@@ -1286,6 +1340,10 @@ declare module 'babylonjs-gui/2D/controls/control' {
             /** @hidden */
             protected _transform(context: CanvasRenderingContext2D): void;
             /** @hidden */
+            _renderHighlight(context: CanvasRenderingContext2D): void;
+            /** @hidden */
+            protected _renderHighlightSpecific(context: CanvasRenderingContext2D): void;
+            /** @hidden */
             protected _applyStates(context: CanvasRenderingContext2D): void;
             /** @hidden */
             protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): boolean;
@@ -1472,7 +1530,10 @@ declare module 'babylonjs-gui/2D/controls/grid' {
                 */
             constructor(name?: string | undefined);
             protected _getTypeName(): string;
+            protected _getGridDefinitions(definitionCallback: (lefts: number[], tops: number[], widths: number[], heights: number[]) => void): void;
             protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+            _flagDescendantsAsMatrixDirty(): void;
+            protected _renderHighlightSpecific(context: CanvasRenderingContext2D): void;
             /** Releases associated resources */
             dispose(): void;
     }
@@ -1598,9 +1659,11 @@ declare module 'babylonjs-gui/2D/controls/inputText' {
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
-            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            /** Gets or sets the text highlighter transparency; default: 0.4 */
             highligherOpacity: number;
-            /** Gets and sets the text hightlight color */
+            /** Gets or sets a boolean indicating whether to select complete text by default on input focus */
+            onFocusSelectAll: boolean;
+            /** Gets or sets the text hightlight color */
             textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;
@@ -2640,6 +2703,11 @@ declare module 'babylonjs-gui/3D/controls/control3D' {
                 * Gets a string representing the class name
                 */
             readonly typeName: string;
+            /**
+                * Get the current class name of the control.
+                * @returns current class name
+                */
+            getClassName(): string;
             protected _getTypeName(): string;
             /**
                 * Gets the transform node used by this control
@@ -2983,7 +3051,7 @@ declare module 'babylonjs-gui/3D/materials/fluentMaterial' {
 }
 
 
-/*BabylonJS GUI*/
+/*Babylon.js GUI*/
 // Dependencies for this module:
 //   ../../../../Tools/Gulp/babylonjs
 declare module BABYLON.GUI {
@@ -3045,11 +3113,17 @@ declare module BABYLON.GUI {
             _layerToDispose: BABYLON.Nullable<BABYLON.Layer>;
             /** @hidden */
             _linkedControls: Control[];
+            /** @hidden */
+            _needRedraw: boolean;
             /**
                 * BABYLON.Observable event triggered each time an clipboard event is received from the rendering canvas
                 */
             onClipboardObservable: BABYLON.Observable<BABYLON.ClipboardInfo>;
             /**
+                * BABYLON.Observable event triggered each time a pointer down is intercepted by a control
+                */
+            onControlPickedObservable: BABYLON.Observable<Control>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -3091,6 +3165,19 @@ declare module BABYLON.GUI {
                 */
             readonly rootContainer: Container;
             /**
+                * Returns an array containing the root container.
+                * This is mostly used to let the Inspector introspects the ADT
+                * @returns an array containing the rootContainer
+                */
+            getChildren(): Array<Container>;
+            /**
+                * Will return all controls that are inside this texture
+                * @param directDescendantsOnly defines if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered
+                * @param predicate defines an optional predicate that will be called on every evaluated child, the predicate must return true for a given child to be part of the result, otherwise it will be ignored
+                * @return all child controls
+                */
+            getDescendants(directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): Control[];
+            /**
                 * Gets or sets the current focused control
                 */
             focusedControl: BABYLON.Nullable<IFocusableControl>;
@@ -3113,6 +3200,11 @@ declare module BABYLON.GUI {
              */
             constructor(name: string, width: number | undefined, height: number | undefined, scene: BABYLON.Nullable<BABYLON.Scene>, generateMipMaps?: boolean, samplingMode?: number);
             /**
+                * Get the current class name of the texture useful for serialization or dynamic coding.
+                * @returns "AdvancedDynamicTexture"
+                */
+            getClassName(): string;
+            /**
                 * Function used to execute a function on all controls
                 * @param func defines the function to execute
                 * @param container defines the container where controls belong. If null the root container will be used
@@ -3156,6 +3248,8 @@ declare module BABYLON.GUI {
             /** @hidden */
             _changeCursor(cursor: string): void;
             /** @hidden */
+            _registerLastControlDown(control: Control, pointerId: number): void;
+            /** @hidden */
             _cleanControlAfterRemovalFromList(list: {
                     [pointerId: number]: Control;
             }, control: Control): void;
@@ -3803,6 +3897,8 @@ declare module BABYLON.GUI {
             /** @hidden */
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
             /** @hidden */
+            _getDescendants(results: Control[], directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): void;
+            /** @hidden */
             _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
             /** @hidden */
             protected _clipForChildren(context: CanvasRenderingContext2D): void;
@@ -3864,6 +3960,14 @@ declare module BABYLON.GUI {
             protected _disabledColor: string;
             /** @hidden */
             _tag: any;
+            /**
+                * Gets or sets the unique id of the node. Please note that this number will be updated when the control is added to a container
+                */
+            uniqueId: number;
+            /**
+                * Gets or sets an object used to store user defined information for the node
+                */
+            metadata: any;
             /** Gets or sets a boolean indicating if the control can be hit with pointer events */
             isHitTestVisible: boolean;
             /** Gets or sets a boolean indicating if the control can block pointer events */
@@ -3889,6 +3993,11 @@ declare module BABYLON.GUI {
             /** Gets the control type name */
             readonly typeName: string;
             /**
+                * Get the current class name of the control.
+                * @returns current class name
+                */
+            getClassName(): string;
+            /**
              * An event triggered when the pointer move over the control.
              */
             onPointerMoveObservable: BABYLON.Observable<BABYLON.Vector2>;
@@ -3932,6 +4041,10 @@ declare module BABYLON.GUI {
             };
             /** Gets or sets alpha value for the control (1 means opaque and 0 means entirely transparent) */
             alpha: number;
+            /**
+                * Gets or sets a boolean indicating that we want to highlight the control (mostly for debugging purpose)
+                */
+            isHighlighted: boolean;
             /** Gets or sets a value indicating the scale factor on X axis (1 by default)
                 * @see http://doc.babylonjs.com/how_to/gui#rotation-and-scaling
              */
@@ -4143,6 +4256,15 @@ declare module BABYLON.GUI {
                 * @param scene defines the hosting scene
                 */
             moveToVector3(position: BABYLON.Vector3, scene: BABYLON.Scene): void;
+            /** @hidden */
+            _getDescendants(results: Control[], directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): void;
+            /**
+                * Will return all controls that have this control as ascendant
+                * @param directDescendantsOnly defines if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered
+                * @param predicate defines an optional predicate that will be called on every evaluated child, the predicate must return true for a given child to be part of the result, otherwise it will be ignored
+                * @return all child controls
+                */
+            getDescendants(directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): Control[];
             /**
                 * Link current control with a target mesh
                 * @param mesh defines the mesh to link with
@@ -4164,6 +4286,10 @@ declare module BABYLON.GUI {
             /** @hidden */
             protected _transform(context: CanvasRenderingContext2D): void;
             /** @hidden */
+            _renderHighlight(context: CanvasRenderingContext2D): void;
+            /** @hidden */
+            protected _renderHighlightSpecific(context: CanvasRenderingContext2D): void;
+            /** @hidden */
             protected _applyStates(context: CanvasRenderingContext2D): void;
             /** @hidden */
             protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): boolean;
@@ -4342,7 +4468,10 @@ declare module BABYLON.GUI {
                 */
             constructor(name?: string | undefined);
             protected _getTypeName(): string;
+            protected _getGridDefinitions(definitionCallback: (lefts: number[], tops: number[], widths: number[], heights: number[]) => void): void;
             protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+            _flagDescendantsAsMatrixDirty(): void;
+            protected _renderHighlightSpecific(context: CanvasRenderingContext2D): void;
             /** Releases associated resources */
             dispose(): void;
     }
@@ -4458,9 +4587,11 @@ declare module BABYLON.GUI {
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
-            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            /** Gets or sets the text highlighter transparency; default: 0.4 */
             highligherOpacity: number;
-            /** Gets and sets the text hightlight color */
+            /** Gets or sets a boolean indicating whether to select complete text by default on input focus */
+            onFocusSelectAll: boolean;
+            /** Gets or sets the text hightlight color */
             textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;
@@ -5435,6 +5566,11 @@ declare module BABYLON.GUI {
                 * Gets a string representing the class name
                 */
             readonly typeName: string;
+            /**
+                * Get the current class name of the control.
+                * @returns current class name
+                */
+            getClassName(): string;
             protected _getTypeName(): string;
             /**
                 * Gets the transform node used by this control

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-gui",
     "description": "The Babylon.js GUI library is an extension you can use to generate interactive user interface. It is build on top of the DynamicTexture.",
-    "version": "4.0.0-alpha.6",
+    "version": "4.0.0-alpha.7",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.6"
+        "babylonjs": "4.0.0-alpha.7"
     },
     "engines": {
         "node": "*"

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 36120 - 1
dist/preview release/inspector/babylon.inspector.bundle.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js.map


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 11 - 1038
dist/preview release/inspector/babylon.inspector.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 27 - 2366
dist/preview release/inspector/babylon.inspector.module.d.ts


+ 5 - 5
dist/preview release/inspector/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "4.0.0-alpha.6",
+    "version": "4.0.0-alpha.7",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,10 +28,10 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.6",
-        "babylonjs-gui": "4.0.0-alpha.6",
-        "babylonjs-loaders": "4.0.0-alpha.6",
-        "babylonjs-serializers": "4.0.0-alpha.6"
+        "babylonjs": "4.0.0-alpha.7",
+        "babylonjs-gui": "4.0.0-alpha.7",
+        "babylonjs-loaders": "4.0.0-alpha.7",
+        "babylonjs-serializers": "4.0.0-alpha.7"
     },
     "engines": {
         "node": "*"

+ 1 - 1
dist/preview release/inspector/readme.md

@@ -1,7 +1,7 @@
 Babylon.js inspector module
 =====================
 
-For usage documentation please visit http://doc.babylonjs.com/how_to/debug_layer and search "inspector".
+For usage documentation please visit http://doc.babylonjs.com/how_to/debug_layer.
 
 # Installation instructions
 

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

@@ -758,6 +758,14 @@ declare module BABYLON.GLTF2 {
          */
         loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress;
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        static AddPointerMetadata(babylonObject: {
+            metadata: any;
+        }, pointer: string): void;
         private static _GetTextureWrapMode;
         private static _GetTextureSamplingMode;
         private static _GetTypedArray;

+ 58 - 35
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -941,11 +941,11 @@ var BABYLON;
                     _this._extensionsOnLoading();
                     var promises = new Array();
                     if (nodes) {
-                        promises.push(_this.loadSceneAsync("#/nodes", { nodes: nodes, index: -1 }));
+                        promises.push(_this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 }));
                     }
                     else {
-                        var scene = ArrayItem.Get("#/scene", _this.gltf.scenes, _this.gltf.scene || 0);
-                        promises.push(_this.loadSceneAsync("#/scenes/" + scene.index, scene));
+                        var scene = ArrayItem.Get("/scene", _this.gltf.scenes, _this.gltf.scene || 0);
+                        promises.push(_this.loadSceneAsync("/scenes/" + scene.index, scene));
                     }
                     if (_this._parent.compileMaterials) {
                         promises.push(_this._compileMaterialsAsync());
@@ -1109,7 +1109,7 @@ var BABYLON;
                     for (var _i = 0, _a = scene.nodes; _i < _a.length; _i++) {
                         var index = _a[_i];
                         var node = ArrayItem.Get(context + "/nodes/" + index, this.gltf.nodes, index);
-                        promises.push(this.loadNodeAsync("#/nodes/" + node.index, node, function (babylonMesh) {
+                        promises.push(this.loadNodeAsync("/nodes/" + node.index, node, function (babylonMesh) {
                             babylonMesh.parent = _this._rootBabylonMesh;
                         }));
                     }
@@ -1217,17 +1217,18 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (node.name || ""));
                 var loadNode = function (babylonTransformNode) {
+                    GLTFLoader.AddPointerMetadata(babylonTransformNode, context);
                     GLTFLoader._LoadTransform(node, babylonTransformNode);
                     if (node.camera != undefined) {
                         var camera = ArrayItem.Get(context + "/camera", _this.gltf.cameras, node.camera);
-                        promises.push(_this.loadCameraAsync("#/cameras/" + camera.index, camera, function (babylonCamera) {
+                        promises.push(_this.loadCameraAsync("/cameras/" + camera.index, camera, function (babylonCamera) {
                             babylonCamera.parent = babylonTransformNode;
                         }));
                     }
                     if (node.children) {
                         var _loop_1 = function (index) {
                             var childNode = ArrayItem.Get(context + "/children/" + index, _this.gltf.nodes, index);
-                            promises.push(_this.loadNodeAsync("#/nodes/" + node.index, childNode, function (childBabylonMesh) {
+                            promises.push(_this.loadNodeAsync("/nodes/" + childNode.index, childNode, function (childBabylonMesh) {
                                 // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)
                                 if (childNode.skin != undefined) {
                                     childBabylonMesh.parent = _this._rootBabylonMesh;
@@ -1250,7 +1251,7 @@ var BABYLON;
                 }
                 else {
                     var mesh = ArrayItem.Get(context + "/mesh", this.gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh.index, node, mesh, loadNode));
+                    promises.push(this._loadMeshAsync("/meshes/" + mesh.index, node, mesh, loadNode));
                 }
                 this.logClose();
                 return Promise.all(promises).then(function () {
@@ -1291,7 +1292,7 @@ var BABYLON;
                 }
                 if (node.skin != undefined) {
                     var skin = ArrayItem.Get(context + "/skin", this.gltf.skins, node.skin);
-                    promises.push(this._loadSkinAsync("#/skins/" + skin.index, node, skin));
+                    promises.push(this._loadSkinAsync("/skins/" + skin.index, node, skin));
                 }
                 assign(node._babylonTransformNode);
                 this.logClose();
@@ -1331,7 +1332,7 @@ var BABYLON;
                     }
                     else {
                         var material = ArrayItem.Get(context + "/material", this.gltf.materials, primitive.material);
-                        promises.push(this._loadMaterialAsync("#/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
+                        promises.push(this._loadMaterialAsync("/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
                             babylonMesh_1.material = babylonMaterial;
                         }));
                     }
@@ -1344,6 +1345,7 @@ var BABYLON;
                     }
                     babylonAbstractMesh = babylonMesh_1;
                 }
+                GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context);
                 this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh);
                 assign(babylonAbstractMesh);
                 this.logClose();
@@ -1368,7 +1370,7 @@ var BABYLON;
                 }
                 else {
                     var accessor = ArrayItem.Get(context + "/indices", this.gltf.accessors, primitive.indices);
-                    promises.push(this._loadIndicesAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(this._loadIndicesAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         babylonGeometry.setIndices(data);
                     }));
                 }
@@ -1381,7 +1383,7 @@ var BABYLON;
                         babylonMesh._delayInfo.push(kind);
                     }
                     var accessor = ArrayItem.Get(context + "/attributes/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadVertexAccessorAsync("#/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
+                    promises.push(_this._loadVertexAccessorAsync("/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
                         babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);
                     }));
                     if (callback) {
@@ -1445,7 +1447,7 @@ var BABYLON;
                         return;
                     }
                     var accessor = ArrayItem.Get(context + "/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(_this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         setData(babylonVertexBuffer, data);
                     }));
                 };
@@ -1558,7 +1560,7 @@ var BABYLON;
                     return Promise.resolve(null);
                 }
                 var accessor = ArrayItem.Get(context + "/inverseBindMatrices", this.gltf.accessors, skin.inverseBindMatrices);
-                return this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor);
+                return this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor);
             };
             GLTFLoader.prototype._updateBoneMatrices = function (babylonSkeleton, inverseBindMatricesData) {
                 for (var _i = 0, _a = babylonSkeleton.bones; _i < _a.length; _i++) {
@@ -1627,8 +1629,9 @@ var BABYLON;
                         throw new Error(context + ": Invalid camera type (" + camera.type + ")");
                     }
                 }
-                assign(babylonCamera);
+                GLTFLoader.AddPointerMetadata(babylonCamera, context);
                 this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
+                assign(babylonCamera);
                 return Promise.all(promises).then(function () {
                     return babylonCamera;
                 });
@@ -1641,7 +1644,7 @@ var BABYLON;
                 var promises = new Array();
                 for (var index = 0; index < animations.length; index++) {
                     var animation = animations[index];
-                    promises.push(this.loadAnimationAsync("#/animations/" + animation.index, animation));
+                    promises.push(this.loadAnimationAsync("/animations/" + animation.index, animation));
                 }
                 return Promise.all(promises).then(function () { });
             };
@@ -1844,8 +1847,8 @@ var BABYLON;
                 var inputAccessor = ArrayItem.Get(context + "/input", this.gltf.accessors, sampler.input);
                 var outputAccessor = ArrayItem.Get(context + "/output", this.gltf.accessors, sampler.output);
                 sampler._data = Promise.all([
-                    this._loadFloatAccessorAsync("#/accessors/" + inputAccessor.index, inputAccessor),
-                    this._loadFloatAccessorAsync("#/accessors/" + outputAccessor.index, outputAccessor)
+                    this._loadFloatAccessorAsync("/accessors/" + inputAccessor.index, inputAccessor),
+                    this._loadFloatAccessorAsync("/accessors/" + outputAccessor.index, outputAccessor)
                 ]).then(function (_a) {
                     var inputData = _a[0], outputData = _a[1];
                     return {
@@ -1877,7 +1880,7 @@ var BABYLON;
                     return bufferView._data;
                 }
                 var buffer = ArrayItem.Get(context + "/buffer", this.gltf.buffers, bufferView.buffer);
-                bufferView._data = this._loadBufferAsync("#/buffers/" + buffer.index, buffer).then(function (data) {
+                bufferView._data = this._loadBufferAsync("/buffers/" + buffer.index, buffer).then(function (data) {
                     try {
                         return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                     }
@@ -1900,7 +1903,7 @@ var BABYLON;
                     return accessor._data;
                 }
                 var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
                 });
                 return accessor._data;
@@ -1921,7 +1924,7 @@ var BABYLON;
                 }
                 else {
                     var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                    accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                    accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                         return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
                     });
                 }
@@ -1931,8 +1934,8 @@ var BABYLON;
                         var indicesBufferView = ArrayItem.Get(context + "/sparse/indices/bufferView", _this.gltf.bufferViews, sparse_1.indices.bufferView);
                         var valuesBufferView = ArrayItem.Get(context + "/sparse/values/bufferView", _this.gltf.bufferViews, sparse_1.values.bufferView);
                         return Promise.all([
-                            _this.loadBufferViewAsync("#/bufferViews/" + indicesBufferView.index, indicesBufferView),
-                            _this.loadBufferViewAsync("#/bufferViews/" + valuesBufferView.index, valuesBufferView)
+                            _this.loadBufferViewAsync("/bufferViews/" + indicesBufferView.index, indicesBufferView),
+                            _this.loadBufferViewAsync("/bufferViews/" + valuesBufferView.index, valuesBufferView)
                         ]).then(function (_a) {
                             var indicesData = _a[0], valuesData = _a[1];
                             var indices = GLTFLoader._GetTypedArray(context + "/sparse/indices", sparse_1.indices.componentType, indicesData, sparse_1.indices.byteOffset, sparse_1.count);
@@ -1955,7 +1958,7 @@ var BABYLON;
                 if (bufferView._babylonBuffer) {
                     return bufferView._babylonBuffer;
                 }
-                bufferView._babylonBuffer = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                bufferView._babylonBuffer = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return new BABYLON.Buffer(_this.babylonScene.getEngine(), data, false);
                 });
                 return bufferView._babylonBuffer;
@@ -1966,14 +1969,14 @@ var BABYLON;
                     return accessor._babylonVertexBuffer;
                 }
                 if (accessor.sparse) {
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
                 // HACK: If byte offset is not a multiple of component type byte length then load as a float array instead of using Babylon buffers.
                 else if (accessor.byteOffset && accessor.byteOffset % BABYLON.VertexBuffer.GetTypeByteLength(accessor.componentType) !== 0) {
                     BABYLON.Tools.Warn("Accessor byte offset is not a multiple of component type byte length");
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
@@ -2003,11 +2006,13 @@ var BABYLON;
                     babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor;
                     if (properties.baseColorTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Base Color)";
                             babylonMaterial.albedoTexture = texture;
                         }));
                     }
                     if (properties.metallicRoughnessTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/metallicRoughnessTexture", properties.metallicRoughnessTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Metallic Roughness)";
                             babylonMaterial.metallicTexture = texture;
                         }));
                         babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
@@ -2035,6 +2040,7 @@ var BABYLON;
                         promise: this.loadMaterialPropertiesAsync(context, material, babylonMaterial)
                     };
                     material._data[babylonDrawMode] = babylonData;
+                    GLTFLoader.AddPointerMetadata(babylonMaterial, context);
                     this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
                     this.logClose();
                 }
@@ -2075,7 +2081,8 @@ var BABYLON;
                     return extensionPromise;
                 }
                 var name = material.name || "material" + material.index;
-                return this._createDefaultMaterial(name, babylonDrawMode);
+                var babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode);
+                return babylonMaterial;
             };
             /**
              * Loads properties from a glTF material into a Babylon material.
@@ -2116,6 +2123,7 @@ var BABYLON;
                 }
                 if (material.normalTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/normalTexture", material.normalTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Normal)";
                         babylonMaterial.bumpTexture = texture;
                     }));
                     babylonMaterial.invertNormalMapX = !this.babylonScene.useRightHandedSystem;
@@ -2126,6 +2134,7 @@ var BABYLON;
                 }
                 if (material.occlusionTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/occlusionTexture", material.occlusionTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Occlusion)";
                         babylonMaterial.ambientTexture = texture;
                     }));
                     babylonMaterial.useAmbientInGrayScale = true;
@@ -2135,6 +2144,7 @@ var BABYLON;
                 }
                 if (material.emissiveTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/emissiveTexture", material.emissiveTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Emissive)";
                         babylonMaterial.emissiveTexture = texture;
                     }));
                 }
@@ -2186,6 +2196,7 @@ var BABYLON;
              * @returns A promise that resolves with the loaded Babylon texture when the load is complete
              */
             GLTFLoader.prototype.loadTextureInfoAsync = function (context, textureInfo, assign) {
+                var _this = this;
                 if (assign === void 0) { assign = function () { }; }
                 var extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);
                 if (extensionPromise) {
@@ -2193,8 +2204,10 @@ var BABYLON;
                 }
                 this.logOpen("" + context);
                 var texture = ArrayItem.Get(context + "/index", this.gltf.textures, textureInfo.index);
-                var promise = this._loadTextureAsync("#/textures/" + textureInfo.index, texture, function (babylonTexture) {
+                var promise = this._loadTextureAsync("/textures/" + textureInfo.index, texture, function (babylonTexture) {
                     babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
+                    GLTFLoader.AddPointerMetadata(babylonTexture, context);
+                    _this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                     assign(babylonTexture);
                 });
                 this.logClose();
@@ -2206,7 +2219,7 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (texture.name || ""));
                 var sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(context + "/sampler", this.gltf.samplers, texture.sampler));
-                var samplerData = this._loadSampler("#/samplers/" + sampler.index, sampler);
+                var samplerData = this._loadSampler("/samplers/" + sampler.index, sampler);
                 var deferred = new BABYLON.Deferred();
                 var babylonTexture = new BABYLON.Texture(null, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, function () {
                     if (!_this._disposed) {
@@ -2218,17 +2231,15 @@ var BABYLON;
                     }
                 });
                 promises.push(deferred.promise);
-                babylonTexture.name = texture.name || "texture" + texture.index;
                 babylonTexture.wrapU = samplerData.wrapU;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
-                promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
+                promises.push(this.loadImageAsync("/images/" + image.index, image).then(function (data) {
                     var name = image.uri || _this._fileName + "#image" + image.index;
                     var dataUrl = "data:" + _this._uniqueRootUrl + name;
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);
-                this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                 this.logClose();
                 return Promise.all(promises).then(function () {
                     return babylonTexture;
@@ -2259,7 +2270,7 @@ var BABYLON;
                     }
                     else {
                         var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, image.bufferView);
-                        image._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView);
+                        image._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView);
                     }
                     this.logClose();
                 }
@@ -2339,6 +2350,17 @@ var BABYLON;
                 }
                 this._progressCallback(new BABYLON.SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
+            /**
+             * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+             * @param babylonObject the Babylon object with metadata
+             * @param pointer the JSON pointer
+             */
+            GLTFLoader.AddPointerMetadata = function (babylonObject, pointer) {
+                var metadata = (babylonObject.metadata = babylonObject.metadata || {});
+                var gltf = (metadata.gltf = metadata.gltf || {});
+                var pointers = (gltf.pointers = gltf.pointers || []);
+                pointers.push(pointer);
+            };
             GLTFLoader._GetTextureWrapMode = function (context, mode) {
                 // Set defaults if undefined
                 mode = mode == undefined ? 10497 /* REPEAT */ : mode;
@@ -3367,14 +3389,14 @@ var BABYLON;
                         babylonMaterial.microSurface = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor;
                         if (properties.diffuseTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/diffuseTexture", properties.diffuseTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Diffuse)";
                                 babylonMaterial.albedoTexture = texture;
-                                return Promise.resolve();
                             }));
                         }
                         if (properties.specularGlossinessTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/specularGlossinessTexture", properties.specularGlossinessTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Specular Glossiness)";
                                 babylonMaterial.reflectivityTexture = texture;
-                                return Promise.resolve();
                             }));
                             babylonMaterial.reflectivityTexture.hasAlpha = true;
                             babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
@@ -3442,8 +3464,8 @@ var BABYLON;
                             }
                             if (properties.baseColorTexture) {
                                 promises.push(this._loader.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                                    texture.name = babylonMaterial.name + " (Base Color)";
                                     babylonMaterial.albedoTexture = texture;
-                                    return Promise.resolve();
                                 }));
                             }
                         }
@@ -3539,6 +3561,7 @@ var BABYLON;
                                 babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;
                                 babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range;
                                 babylonLight.parent = babylonMesh;
+                                GLTF2.GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);
                                 assign(babylonMesh);
                             });
                         });

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


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

@@ -1320,6 +1320,14 @@ declare module BABYLON.GLTF2 {
          */
         loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress;
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        static AddPointerMetadata(babylonObject: {
+            metadata: any;
+        }, pointer: string): void;
         private static _GetTextureWrapMode;
         private static _GetTextureSamplingMode;
         private static _GetTypedArray;

+ 58 - 35
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3149,11 +3149,11 @@ var BABYLON;
                     _this._extensionsOnLoading();
                     var promises = new Array();
                     if (nodes) {
-                        promises.push(_this.loadSceneAsync("#/nodes", { nodes: nodes, index: -1 }));
+                        promises.push(_this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 }));
                     }
                     else {
-                        var scene = ArrayItem.Get("#/scene", _this.gltf.scenes, _this.gltf.scene || 0);
-                        promises.push(_this.loadSceneAsync("#/scenes/" + scene.index, scene));
+                        var scene = ArrayItem.Get("/scene", _this.gltf.scenes, _this.gltf.scene || 0);
+                        promises.push(_this.loadSceneAsync("/scenes/" + scene.index, scene));
                     }
                     if (_this._parent.compileMaterials) {
                         promises.push(_this._compileMaterialsAsync());
@@ -3317,7 +3317,7 @@ var BABYLON;
                     for (var _i = 0, _a = scene.nodes; _i < _a.length; _i++) {
                         var index = _a[_i];
                         var node = ArrayItem.Get(context + "/nodes/" + index, this.gltf.nodes, index);
-                        promises.push(this.loadNodeAsync("#/nodes/" + node.index, node, function (babylonMesh) {
+                        promises.push(this.loadNodeAsync("/nodes/" + node.index, node, function (babylonMesh) {
                             babylonMesh.parent = _this._rootBabylonMesh;
                         }));
                     }
@@ -3425,17 +3425,18 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (node.name || ""));
                 var loadNode = function (babylonTransformNode) {
+                    GLTFLoader.AddPointerMetadata(babylonTransformNode, context);
                     GLTFLoader._LoadTransform(node, babylonTransformNode);
                     if (node.camera != undefined) {
                         var camera = ArrayItem.Get(context + "/camera", _this.gltf.cameras, node.camera);
-                        promises.push(_this.loadCameraAsync("#/cameras/" + camera.index, camera, function (babylonCamera) {
+                        promises.push(_this.loadCameraAsync("/cameras/" + camera.index, camera, function (babylonCamera) {
                             babylonCamera.parent = babylonTransformNode;
                         }));
                     }
                     if (node.children) {
                         var _loop_1 = function (index) {
                             var childNode = ArrayItem.Get(context + "/children/" + index, _this.gltf.nodes, index);
-                            promises.push(_this.loadNodeAsync("#/nodes/" + node.index, childNode, function (childBabylonMesh) {
+                            promises.push(_this.loadNodeAsync("/nodes/" + childNode.index, childNode, function (childBabylonMesh) {
                                 // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)
                                 if (childNode.skin != undefined) {
                                     childBabylonMesh.parent = _this._rootBabylonMesh;
@@ -3458,7 +3459,7 @@ var BABYLON;
                 }
                 else {
                     var mesh = ArrayItem.Get(context + "/mesh", this.gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh.index, node, mesh, loadNode));
+                    promises.push(this._loadMeshAsync("/meshes/" + mesh.index, node, mesh, loadNode));
                 }
                 this.logClose();
                 return Promise.all(promises).then(function () {
@@ -3499,7 +3500,7 @@ var BABYLON;
                 }
                 if (node.skin != undefined) {
                     var skin = ArrayItem.Get(context + "/skin", this.gltf.skins, node.skin);
-                    promises.push(this._loadSkinAsync("#/skins/" + skin.index, node, skin));
+                    promises.push(this._loadSkinAsync("/skins/" + skin.index, node, skin));
                 }
                 assign(node._babylonTransformNode);
                 this.logClose();
@@ -3539,7 +3540,7 @@ var BABYLON;
                     }
                     else {
                         var material = ArrayItem.Get(context + "/material", this.gltf.materials, primitive.material);
-                        promises.push(this._loadMaterialAsync("#/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
+                        promises.push(this._loadMaterialAsync("/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
                             babylonMesh_1.material = babylonMaterial;
                         }));
                     }
@@ -3552,6 +3553,7 @@ var BABYLON;
                     }
                     babylonAbstractMesh = babylonMesh_1;
                 }
+                GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context);
                 this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh);
                 assign(babylonAbstractMesh);
                 this.logClose();
@@ -3576,7 +3578,7 @@ var BABYLON;
                 }
                 else {
                     var accessor = ArrayItem.Get(context + "/indices", this.gltf.accessors, primitive.indices);
-                    promises.push(this._loadIndicesAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(this._loadIndicesAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         babylonGeometry.setIndices(data);
                     }));
                 }
@@ -3589,7 +3591,7 @@ var BABYLON;
                         babylonMesh._delayInfo.push(kind);
                     }
                     var accessor = ArrayItem.Get(context + "/attributes/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadVertexAccessorAsync("#/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
+                    promises.push(_this._loadVertexAccessorAsync("/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
                         babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);
                     }));
                     if (callback) {
@@ -3653,7 +3655,7 @@ var BABYLON;
                         return;
                     }
                     var accessor = ArrayItem.Get(context + "/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(_this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         setData(babylonVertexBuffer, data);
                     }));
                 };
@@ -3766,7 +3768,7 @@ var BABYLON;
                     return Promise.resolve(null);
                 }
                 var accessor = ArrayItem.Get(context + "/inverseBindMatrices", this.gltf.accessors, skin.inverseBindMatrices);
-                return this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor);
+                return this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor);
             };
             GLTFLoader.prototype._updateBoneMatrices = function (babylonSkeleton, inverseBindMatricesData) {
                 for (var _i = 0, _a = babylonSkeleton.bones; _i < _a.length; _i++) {
@@ -3835,8 +3837,9 @@ var BABYLON;
                         throw new Error(context + ": Invalid camera type (" + camera.type + ")");
                     }
                 }
-                assign(babylonCamera);
+                GLTFLoader.AddPointerMetadata(babylonCamera, context);
                 this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
+                assign(babylonCamera);
                 return Promise.all(promises).then(function () {
                     return babylonCamera;
                 });
@@ -3849,7 +3852,7 @@ var BABYLON;
                 var promises = new Array();
                 for (var index = 0; index < animations.length; index++) {
                     var animation = animations[index];
-                    promises.push(this.loadAnimationAsync("#/animations/" + animation.index, animation));
+                    promises.push(this.loadAnimationAsync("/animations/" + animation.index, animation));
                 }
                 return Promise.all(promises).then(function () { });
             };
@@ -4052,8 +4055,8 @@ var BABYLON;
                 var inputAccessor = ArrayItem.Get(context + "/input", this.gltf.accessors, sampler.input);
                 var outputAccessor = ArrayItem.Get(context + "/output", this.gltf.accessors, sampler.output);
                 sampler._data = Promise.all([
-                    this._loadFloatAccessorAsync("#/accessors/" + inputAccessor.index, inputAccessor),
-                    this._loadFloatAccessorAsync("#/accessors/" + outputAccessor.index, outputAccessor)
+                    this._loadFloatAccessorAsync("/accessors/" + inputAccessor.index, inputAccessor),
+                    this._loadFloatAccessorAsync("/accessors/" + outputAccessor.index, outputAccessor)
                 ]).then(function (_a) {
                     var inputData = _a[0], outputData = _a[1];
                     return {
@@ -4085,7 +4088,7 @@ var BABYLON;
                     return bufferView._data;
                 }
                 var buffer = ArrayItem.Get(context + "/buffer", this.gltf.buffers, bufferView.buffer);
-                bufferView._data = this._loadBufferAsync("#/buffers/" + buffer.index, buffer).then(function (data) {
+                bufferView._data = this._loadBufferAsync("/buffers/" + buffer.index, buffer).then(function (data) {
                     try {
                         return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                     }
@@ -4108,7 +4111,7 @@ var BABYLON;
                     return accessor._data;
                 }
                 var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
                 });
                 return accessor._data;
@@ -4129,7 +4132,7 @@ var BABYLON;
                 }
                 else {
                     var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                    accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                    accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                         return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
                     });
                 }
@@ -4139,8 +4142,8 @@ var BABYLON;
                         var indicesBufferView = ArrayItem.Get(context + "/sparse/indices/bufferView", _this.gltf.bufferViews, sparse_1.indices.bufferView);
                         var valuesBufferView = ArrayItem.Get(context + "/sparse/values/bufferView", _this.gltf.bufferViews, sparse_1.values.bufferView);
                         return Promise.all([
-                            _this.loadBufferViewAsync("#/bufferViews/" + indicesBufferView.index, indicesBufferView),
-                            _this.loadBufferViewAsync("#/bufferViews/" + valuesBufferView.index, valuesBufferView)
+                            _this.loadBufferViewAsync("/bufferViews/" + indicesBufferView.index, indicesBufferView),
+                            _this.loadBufferViewAsync("/bufferViews/" + valuesBufferView.index, valuesBufferView)
                         ]).then(function (_a) {
                             var indicesData = _a[0], valuesData = _a[1];
                             var indices = GLTFLoader._GetTypedArray(context + "/sparse/indices", sparse_1.indices.componentType, indicesData, sparse_1.indices.byteOffset, sparse_1.count);
@@ -4163,7 +4166,7 @@ var BABYLON;
                 if (bufferView._babylonBuffer) {
                     return bufferView._babylonBuffer;
                 }
-                bufferView._babylonBuffer = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                bufferView._babylonBuffer = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return new BABYLON.Buffer(_this.babylonScene.getEngine(), data, false);
                 });
                 return bufferView._babylonBuffer;
@@ -4174,14 +4177,14 @@ var BABYLON;
                     return accessor._babylonVertexBuffer;
                 }
                 if (accessor.sparse) {
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
                 // HACK: If byte offset is not a multiple of component type byte length then load as a float array instead of using Babylon buffers.
                 else if (accessor.byteOffset && accessor.byteOffset % BABYLON.VertexBuffer.GetTypeByteLength(accessor.componentType) !== 0) {
                     BABYLON.Tools.Warn("Accessor byte offset is not a multiple of component type byte length");
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
@@ -4211,11 +4214,13 @@ var BABYLON;
                     babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor;
                     if (properties.baseColorTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Base Color)";
                             babylonMaterial.albedoTexture = texture;
                         }));
                     }
                     if (properties.metallicRoughnessTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/metallicRoughnessTexture", properties.metallicRoughnessTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Metallic Roughness)";
                             babylonMaterial.metallicTexture = texture;
                         }));
                         babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
@@ -4243,6 +4248,7 @@ var BABYLON;
                         promise: this.loadMaterialPropertiesAsync(context, material, babylonMaterial)
                     };
                     material._data[babylonDrawMode] = babylonData;
+                    GLTFLoader.AddPointerMetadata(babylonMaterial, context);
                     this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
                     this.logClose();
                 }
@@ -4283,7 +4289,8 @@ var BABYLON;
                     return extensionPromise;
                 }
                 var name = material.name || "material" + material.index;
-                return this._createDefaultMaterial(name, babylonDrawMode);
+                var babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode);
+                return babylonMaterial;
             };
             /**
              * Loads properties from a glTF material into a Babylon material.
@@ -4324,6 +4331,7 @@ var BABYLON;
                 }
                 if (material.normalTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/normalTexture", material.normalTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Normal)";
                         babylonMaterial.bumpTexture = texture;
                     }));
                     babylonMaterial.invertNormalMapX = !this.babylonScene.useRightHandedSystem;
@@ -4334,6 +4342,7 @@ var BABYLON;
                 }
                 if (material.occlusionTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/occlusionTexture", material.occlusionTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Occlusion)";
                         babylonMaterial.ambientTexture = texture;
                     }));
                     babylonMaterial.useAmbientInGrayScale = true;
@@ -4343,6 +4352,7 @@ var BABYLON;
                 }
                 if (material.emissiveTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/emissiveTexture", material.emissiveTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Emissive)";
                         babylonMaterial.emissiveTexture = texture;
                     }));
                 }
@@ -4394,6 +4404,7 @@ var BABYLON;
              * @returns A promise that resolves with the loaded Babylon texture when the load is complete
              */
             GLTFLoader.prototype.loadTextureInfoAsync = function (context, textureInfo, assign) {
+                var _this = this;
                 if (assign === void 0) { assign = function () { }; }
                 var extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);
                 if (extensionPromise) {
@@ -4401,8 +4412,10 @@ var BABYLON;
                 }
                 this.logOpen("" + context);
                 var texture = ArrayItem.Get(context + "/index", this.gltf.textures, textureInfo.index);
-                var promise = this._loadTextureAsync("#/textures/" + textureInfo.index, texture, function (babylonTexture) {
+                var promise = this._loadTextureAsync("/textures/" + textureInfo.index, texture, function (babylonTexture) {
                     babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
+                    GLTFLoader.AddPointerMetadata(babylonTexture, context);
+                    _this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                     assign(babylonTexture);
                 });
                 this.logClose();
@@ -4414,7 +4427,7 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (texture.name || ""));
                 var sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(context + "/sampler", this.gltf.samplers, texture.sampler));
-                var samplerData = this._loadSampler("#/samplers/" + sampler.index, sampler);
+                var samplerData = this._loadSampler("/samplers/" + sampler.index, sampler);
                 var deferred = new BABYLON.Deferred();
                 var babylonTexture = new BABYLON.Texture(null, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, function () {
                     if (!_this._disposed) {
@@ -4426,17 +4439,15 @@ var BABYLON;
                     }
                 });
                 promises.push(deferred.promise);
-                babylonTexture.name = texture.name || "texture" + texture.index;
                 babylonTexture.wrapU = samplerData.wrapU;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
-                promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
+                promises.push(this.loadImageAsync("/images/" + image.index, image).then(function (data) {
                     var name = image.uri || _this._fileName + "#image" + image.index;
                     var dataUrl = "data:" + _this._uniqueRootUrl + name;
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);
-                this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                 this.logClose();
                 return Promise.all(promises).then(function () {
                     return babylonTexture;
@@ -4467,7 +4478,7 @@ var BABYLON;
                     }
                     else {
                         var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, image.bufferView);
-                        image._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView);
+                        image._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView);
                     }
                     this.logClose();
                 }
@@ -4547,6 +4558,17 @@ var BABYLON;
                 }
                 this._progressCallback(new BABYLON.SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
+            /**
+             * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+             * @param babylonObject the Babylon object with metadata
+             * @param pointer the JSON pointer
+             */
+            GLTFLoader.AddPointerMetadata = function (babylonObject, pointer) {
+                var metadata = (babylonObject.metadata = babylonObject.metadata || {});
+                var gltf = (metadata.gltf = metadata.gltf || {});
+                var pointers = (gltf.pointers = gltf.pointers || []);
+                pointers.push(pointer);
+            };
             GLTFLoader._GetTextureWrapMode = function (context, mode) {
                 // Set defaults if undefined
                 mode = mode == undefined ? 10497 /* REPEAT */ : mode;
@@ -5575,14 +5597,14 @@ var BABYLON;
                         babylonMaterial.microSurface = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor;
                         if (properties.diffuseTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/diffuseTexture", properties.diffuseTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Diffuse)";
                                 babylonMaterial.albedoTexture = texture;
-                                return Promise.resolve();
                             }));
                         }
                         if (properties.specularGlossinessTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/specularGlossinessTexture", properties.specularGlossinessTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Specular Glossiness)";
                                 babylonMaterial.reflectivityTexture = texture;
-                                return Promise.resolve();
                             }));
                             babylonMaterial.reflectivityTexture.hasAlpha = true;
                             babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
@@ -5650,8 +5672,8 @@ var BABYLON;
                             }
                             if (properties.baseColorTexture) {
                                 promises.push(this._loader.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                                    texture.name = babylonMaterial.name + " (Base Color)";
                                     babylonMaterial.albedoTexture = texture;
-                                    return Promise.resolve();
                                 }));
                             }
                         }
@@ -5747,6 +5769,7 @@ var BABYLON;
                                 babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;
                                 babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range;
                                 babylonLight.parent = babylonMesh;
+                                GLTF2.GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);
                                 assign(babylonMesh);
                             });
                         });

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


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

@@ -1450,6 +1450,14 @@ declare module BABYLON.GLTF2 {
          */
         loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress;
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        static AddPointerMetadata(babylonObject: {
+            metadata: any;
+        }, pointer: string): void;
         private static _GetTextureWrapMode;
         private static _GetTextureSamplingMode;
         private static _GetTypedArray;

+ 58 - 35
dist/preview release/loaders/babylonjs.loaders.js

@@ -4211,11 +4211,11 @@ var BABYLON;
                     _this._extensionsOnLoading();
                     var promises = new Array();
                     if (nodes) {
-                        promises.push(_this.loadSceneAsync("#/nodes", { nodes: nodes, index: -1 }));
+                        promises.push(_this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 }));
                     }
                     else {
-                        var scene = ArrayItem.Get("#/scene", _this.gltf.scenes, _this.gltf.scene || 0);
-                        promises.push(_this.loadSceneAsync("#/scenes/" + scene.index, scene));
+                        var scene = ArrayItem.Get("/scene", _this.gltf.scenes, _this.gltf.scene || 0);
+                        promises.push(_this.loadSceneAsync("/scenes/" + scene.index, scene));
                     }
                     if (_this._parent.compileMaterials) {
                         promises.push(_this._compileMaterialsAsync());
@@ -4379,7 +4379,7 @@ var BABYLON;
                     for (var _i = 0, _a = scene.nodes; _i < _a.length; _i++) {
                         var index = _a[_i];
                         var node = ArrayItem.Get(context + "/nodes/" + index, this.gltf.nodes, index);
-                        promises.push(this.loadNodeAsync("#/nodes/" + node.index, node, function (babylonMesh) {
+                        promises.push(this.loadNodeAsync("/nodes/" + node.index, node, function (babylonMesh) {
                             babylonMesh.parent = _this._rootBabylonMesh;
                         }));
                     }
@@ -4487,17 +4487,18 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (node.name || ""));
                 var loadNode = function (babylonTransformNode) {
+                    GLTFLoader.AddPointerMetadata(babylonTransformNode, context);
                     GLTFLoader._LoadTransform(node, babylonTransformNode);
                     if (node.camera != undefined) {
                         var camera = ArrayItem.Get(context + "/camera", _this.gltf.cameras, node.camera);
-                        promises.push(_this.loadCameraAsync("#/cameras/" + camera.index, camera, function (babylonCamera) {
+                        promises.push(_this.loadCameraAsync("/cameras/" + camera.index, camera, function (babylonCamera) {
                             babylonCamera.parent = babylonTransformNode;
                         }));
                     }
                     if (node.children) {
                         var _loop_1 = function (index) {
                             var childNode = ArrayItem.Get(context + "/children/" + index, _this.gltf.nodes, index);
-                            promises.push(_this.loadNodeAsync("#/nodes/" + node.index, childNode, function (childBabylonMesh) {
+                            promises.push(_this.loadNodeAsync("/nodes/" + childNode.index, childNode, function (childBabylonMesh) {
                                 // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)
                                 if (childNode.skin != undefined) {
                                     childBabylonMesh.parent = _this._rootBabylonMesh;
@@ -4520,7 +4521,7 @@ var BABYLON;
                 }
                 else {
                     var mesh = ArrayItem.Get(context + "/mesh", this.gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh.index, node, mesh, loadNode));
+                    promises.push(this._loadMeshAsync("/meshes/" + mesh.index, node, mesh, loadNode));
                 }
                 this.logClose();
                 return Promise.all(promises).then(function () {
@@ -4561,7 +4562,7 @@ var BABYLON;
                 }
                 if (node.skin != undefined) {
                     var skin = ArrayItem.Get(context + "/skin", this.gltf.skins, node.skin);
-                    promises.push(this._loadSkinAsync("#/skins/" + skin.index, node, skin));
+                    promises.push(this._loadSkinAsync("/skins/" + skin.index, node, skin));
                 }
                 assign(node._babylonTransformNode);
                 this.logClose();
@@ -4601,7 +4602,7 @@ var BABYLON;
                     }
                     else {
                         var material = ArrayItem.Get(context + "/material", this.gltf.materials, primitive.material);
-                        promises.push(this._loadMaterialAsync("#/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
+                        promises.push(this._loadMaterialAsync("/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
                             babylonMesh_1.material = babylonMaterial;
                         }));
                     }
@@ -4614,6 +4615,7 @@ var BABYLON;
                     }
                     babylonAbstractMesh = babylonMesh_1;
                 }
+                GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context);
                 this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh);
                 assign(babylonAbstractMesh);
                 this.logClose();
@@ -4638,7 +4640,7 @@ var BABYLON;
                 }
                 else {
                     var accessor = ArrayItem.Get(context + "/indices", this.gltf.accessors, primitive.indices);
-                    promises.push(this._loadIndicesAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(this._loadIndicesAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         babylonGeometry.setIndices(data);
                     }));
                 }
@@ -4651,7 +4653,7 @@ var BABYLON;
                         babylonMesh._delayInfo.push(kind);
                     }
                     var accessor = ArrayItem.Get(context + "/attributes/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadVertexAccessorAsync("#/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
+                    promises.push(_this._loadVertexAccessorAsync("/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
                         babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);
                     }));
                     if (callback) {
@@ -4715,7 +4717,7 @@ var BABYLON;
                         return;
                     }
                     var accessor = ArrayItem.Get(context + "/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(_this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         setData(babylonVertexBuffer, data);
                     }));
                 };
@@ -4828,7 +4830,7 @@ var BABYLON;
                     return Promise.resolve(null);
                 }
                 var accessor = ArrayItem.Get(context + "/inverseBindMatrices", this.gltf.accessors, skin.inverseBindMatrices);
-                return this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor);
+                return this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor);
             };
             GLTFLoader.prototype._updateBoneMatrices = function (babylonSkeleton, inverseBindMatricesData) {
                 for (var _i = 0, _a = babylonSkeleton.bones; _i < _a.length; _i++) {
@@ -4897,8 +4899,9 @@ var BABYLON;
                         throw new Error(context + ": Invalid camera type (" + camera.type + ")");
                     }
                 }
-                assign(babylonCamera);
+                GLTFLoader.AddPointerMetadata(babylonCamera, context);
                 this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
+                assign(babylonCamera);
                 return Promise.all(promises).then(function () {
                     return babylonCamera;
                 });
@@ -4911,7 +4914,7 @@ var BABYLON;
                 var promises = new Array();
                 for (var index = 0; index < animations.length; index++) {
                     var animation = animations[index];
-                    promises.push(this.loadAnimationAsync("#/animations/" + animation.index, animation));
+                    promises.push(this.loadAnimationAsync("/animations/" + animation.index, animation));
                 }
                 return Promise.all(promises).then(function () { });
             };
@@ -5114,8 +5117,8 @@ var BABYLON;
                 var inputAccessor = ArrayItem.Get(context + "/input", this.gltf.accessors, sampler.input);
                 var outputAccessor = ArrayItem.Get(context + "/output", this.gltf.accessors, sampler.output);
                 sampler._data = Promise.all([
-                    this._loadFloatAccessorAsync("#/accessors/" + inputAccessor.index, inputAccessor),
-                    this._loadFloatAccessorAsync("#/accessors/" + outputAccessor.index, outputAccessor)
+                    this._loadFloatAccessorAsync("/accessors/" + inputAccessor.index, inputAccessor),
+                    this._loadFloatAccessorAsync("/accessors/" + outputAccessor.index, outputAccessor)
                 ]).then(function (_a) {
                     var inputData = _a[0], outputData = _a[1];
                     return {
@@ -5147,7 +5150,7 @@ var BABYLON;
                     return bufferView._data;
                 }
                 var buffer = ArrayItem.Get(context + "/buffer", this.gltf.buffers, bufferView.buffer);
-                bufferView._data = this._loadBufferAsync("#/buffers/" + buffer.index, buffer).then(function (data) {
+                bufferView._data = this._loadBufferAsync("/buffers/" + buffer.index, buffer).then(function (data) {
                     try {
                         return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                     }
@@ -5170,7 +5173,7 @@ var BABYLON;
                     return accessor._data;
                 }
                 var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
                 });
                 return accessor._data;
@@ -5191,7 +5194,7 @@ var BABYLON;
                 }
                 else {
                     var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                    accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                    accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                         return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
                     });
                 }
@@ -5201,8 +5204,8 @@ var BABYLON;
                         var indicesBufferView = ArrayItem.Get(context + "/sparse/indices/bufferView", _this.gltf.bufferViews, sparse_1.indices.bufferView);
                         var valuesBufferView = ArrayItem.Get(context + "/sparse/values/bufferView", _this.gltf.bufferViews, sparse_1.values.bufferView);
                         return Promise.all([
-                            _this.loadBufferViewAsync("#/bufferViews/" + indicesBufferView.index, indicesBufferView),
-                            _this.loadBufferViewAsync("#/bufferViews/" + valuesBufferView.index, valuesBufferView)
+                            _this.loadBufferViewAsync("/bufferViews/" + indicesBufferView.index, indicesBufferView),
+                            _this.loadBufferViewAsync("/bufferViews/" + valuesBufferView.index, valuesBufferView)
                         ]).then(function (_a) {
                             var indicesData = _a[0], valuesData = _a[1];
                             var indices = GLTFLoader._GetTypedArray(context + "/sparse/indices", sparse_1.indices.componentType, indicesData, sparse_1.indices.byteOffset, sparse_1.count);
@@ -5225,7 +5228,7 @@ var BABYLON;
                 if (bufferView._babylonBuffer) {
                     return bufferView._babylonBuffer;
                 }
-                bufferView._babylonBuffer = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                bufferView._babylonBuffer = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return new BABYLON.Buffer(_this.babylonScene.getEngine(), data, false);
                 });
                 return bufferView._babylonBuffer;
@@ -5236,14 +5239,14 @@ var BABYLON;
                     return accessor._babylonVertexBuffer;
                 }
                 if (accessor.sparse) {
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
                 // HACK: If byte offset is not a multiple of component type byte length then load as a float array instead of using Babylon buffers.
                 else if (accessor.byteOffset && accessor.byteOffset % BABYLON.VertexBuffer.GetTypeByteLength(accessor.componentType) !== 0) {
                     BABYLON.Tools.Warn("Accessor byte offset is not a multiple of component type byte length");
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
@@ -5273,11 +5276,13 @@ var BABYLON;
                     babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor;
                     if (properties.baseColorTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Base Color)";
                             babylonMaterial.albedoTexture = texture;
                         }));
                     }
                     if (properties.metallicRoughnessTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/metallicRoughnessTexture", properties.metallicRoughnessTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Metallic Roughness)";
                             babylonMaterial.metallicTexture = texture;
                         }));
                         babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
@@ -5305,6 +5310,7 @@ var BABYLON;
                         promise: this.loadMaterialPropertiesAsync(context, material, babylonMaterial)
                     };
                     material._data[babylonDrawMode] = babylonData;
+                    GLTFLoader.AddPointerMetadata(babylonMaterial, context);
                     this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
                     this.logClose();
                 }
@@ -5345,7 +5351,8 @@ var BABYLON;
                     return extensionPromise;
                 }
                 var name = material.name || "material" + material.index;
-                return this._createDefaultMaterial(name, babylonDrawMode);
+                var babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode);
+                return babylonMaterial;
             };
             /**
              * Loads properties from a glTF material into a Babylon material.
@@ -5386,6 +5393,7 @@ var BABYLON;
                 }
                 if (material.normalTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/normalTexture", material.normalTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Normal)";
                         babylonMaterial.bumpTexture = texture;
                     }));
                     babylonMaterial.invertNormalMapX = !this.babylonScene.useRightHandedSystem;
@@ -5396,6 +5404,7 @@ var BABYLON;
                 }
                 if (material.occlusionTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/occlusionTexture", material.occlusionTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Occlusion)";
                         babylonMaterial.ambientTexture = texture;
                     }));
                     babylonMaterial.useAmbientInGrayScale = true;
@@ -5405,6 +5414,7 @@ var BABYLON;
                 }
                 if (material.emissiveTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/emissiveTexture", material.emissiveTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Emissive)";
                         babylonMaterial.emissiveTexture = texture;
                     }));
                 }
@@ -5456,6 +5466,7 @@ var BABYLON;
              * @returns A promise that resolves with the loaded Babylon texture when the load is complete
              */
             GLTFLoader.prototype.loadTextureInfoAsync = function (context, textureInfo, assign) {
+                var _this = this;
                 if (assign === void 0) { assign = function () { }; }
                 var extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);
                 if (extensionPromise) {
@@ -5463,8 +5474,10 @@ var BABYLON;
                 }
                 this.logOpen("" + context);
                 var texture = ArrayItem.Get(context + "/index", this.gltf.textures, textureInfo.index);
-                var promise = this._loadTextureAsync("#/textures/" + textureInfo.index, texture, function (babylonTexture) {
+                var promise = this._loadTextureAsync("/textures/" + textureInfo.index, texture, function (babylonTexture) {
                     babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
+                    GLTFLoader.AddPointerMetadata(babylonTexture, context);
+                    _this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                     assign(babylonTexture);
                 });
                 this.logClose();
@@ -5476,7 +5489,7 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (texture.name || ""));
                 var sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(context + "/sampler", this.gltf.samplers, texture.sampler));
-                var samplerData = this._loadSampler("#/samplers/" + sampler.index, sampler);
+                var samplerData = this._loadSampler("/samplers/" + sampler.index, sampler);
                 var deferred = new BABYLON.Deferred();
                 var babylonTexture = new BABYLON.Texture(null, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, function () {
                     if (!_this._disposed) {
@@ -5488,17 +5501,15 @@ var BABYLON;
                     }
                 });
                 promises.push(deferred.promise);
-                babylonTexture.name = texture.name || "texture" + texture.index;
                 babylonTexture.wrapU = samplerData.wrapU;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
-                promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
+                promises.push(this.loadImageAsync("/images/" + image.index, image).then(function (data) {
                     var name = image.uri || _this._fileName + "#image" + image.index;
                     var dataUrl = "data:" + _this._uniqueRootUrl + name;
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);
-                this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                 this.logClose();
                 return Promise.all(promises).then(function () {
                     return babylonTexture;
@@ -5529,7 +5540,7 @@ var BABYLON;
                     }
                     else {
                         var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, image.bufferView);
-                        image._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView);
+                        image._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView);
                     }
                     this.logClose();
                 }
@@ -5609,6 +5620,17 @@ var BABYLON;
                 }
                 this._progressCallback(new BABYLON.SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
+            /**
+             * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+             * @param babylonObject the Babylon object with metadata
+             * @param pointer the JSON pointer
+             */
+            GLTFLoader.AddPointerMetadata = function (babylonObject, pointer) {
+                var metadata = (babylonObject.metadata = babylonObject.metadata || {});
+                var gltf = (metadata.gltf = metadata.gltf || {});
+                var pointers = (gltf.pointers = gltf.pointers || []);
+                pointers.push(pointer);
+            };
             GLTFLoader._GetTextureWrapMode = function (context, mode) {
                 // Set defaults if undefined
                 mode = mode == undefined ? 10497 /* REPEAT */ : mode;
@@ -6637,14 +6659,14 @@ var BABYLON;
                         babylonMaterial.microSurface = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor;
                         if (properties.diffuseTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/diffuseTexture", properties.diffuseTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Diffuse)";
                                 babylonMaterial.albedoTexture = texture;
-                                return Promise.resolve();
                             }));
                         }
                         if (properties.specularGlossinessTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/specularGlossinessTexture", properties.specularGlossinessTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Specular Glossiness)";
                                 babylonMaterial.reflectivityTexture = texture;
-                                return Promise.resolve();
                             }));
                             babylonMaterial.reflectivityTexture.hasAlpha = true;
                             babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
@@ -6712,8 +6734,8 @@ var BABYLON;
                             }
                             if (properties.baseColorTexture) {
                                 promises.push(this._loader.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                                    texture.name = babylonMaterial.name + " (Base Color)";
                                     babylonMaterial.albedoTexture = texture;
-                                    return Promise.resolve();
                                 }));
                             }
                         }
@@ -6809,6 +6831,7 @@ var BABYLON;
                                 babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;
                                 babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range;
                                 babylonLight.parent = babylonMesh;
+                                GLTF2.GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);
                                 assign(babylonMesh);
                             });
                         });

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


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

@@ -1457,6 +1457,14 @@ declare module BABYLON.GLTF2 {
          */
         loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress;
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        static AddPointerMetadata(babylonObject: {
+            metadata: any;
+        }, pointer: string): void;
         private static _GetTextureWrapMode;
         private static _GetTextureSamplingMode;
         private static _GetTypedArray;

+ 3 - 3
dist/preview release/loaders/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-loaders",
     "description": "The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.",
-    "version": "4.0.0-alpha.6",
+    "version": "4.0.0-alpha.7",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,8 +27,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "4.0.0-alpha.6",
-        "babylonjs": "4.0.0-alpha.6"
+        "babylonjs-gltf2interface": "4.0.0-alpha.7",
+        "babylonjs": "4.0.0-alpha.7"
     },
     "engines": {
         "node": "*"

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2 - 2
dist/preview release/materialsLibrary/babylon.gridMaterial.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gridMaterial.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2 - 2
dist/preview release/materialsLibrary/babylonjs.materials.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 2 - 2
dist/preview release/materialsLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-materials",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.6",
+    "version": "4.0.0-alpha.7",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.6"
+        "babylonjs": "4.0.0-alpha.7"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/postProcessesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-post-process",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.6",
+    "version": "4.0.0-alpha.7",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.6"
+        "babylonjs": "4.0.0-alpha.7"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/proceduralTexturesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-procedural-textures",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.6",
+    "version": "4.0.0-alpha.7",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.6"
+        "babylonjs": "4.0.0-alpha.7"
     },
     "engines": {
         "node": "*"

+ 3 - 3
dist/preview release/serializers/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-serializers",
     "description": "The Babylon.js serializers library is an extension you can use to serialize Babylon scenes.",
-    "version": "4.0.0-alpha.6",
+    "version": "4.0.0-alpha.7",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,8 +27,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.6",
-        "babylonjs-gltf2interface": "4.0.0-alpha.6"
+        "babylonjs": "4.0.0-alpha.7",
+        "babylonjs-gltf2interface": "4.0.0-alpha.7"
     },
     "engines": {
         "node": "*"

+ 5 - 19
dist/preview release/viewer/babylon.viewer.d.ts

@@ -168,11 +168,11 @@ declare module BabylonViewer {
                 * Mainly used for help and errors
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 */
-            showOverlayScreen(subScreen: string): Promise<Template> | Promise<string>;
+            showOverlayScreen(subScreen: string): Promise<string> | Promise<Template>;
             /**
                 * Hide the overlay screen.
                 */
-            hideOverlayScreen(): Promise<Template> | Promise<string>;
+            hideOverlayScreen(): Promise<string> | Promise<Template>;
             /**
                 * show the viewer (in case it was hidden)
                 *
@@ -189,11 +189,11 @@ declare module BabylonViewer {
                 * Show the loading screen.
                 * The loading screen can be configured using the configuration object
                 */
-            showLoadingScreen(): Promise<Template> | Promise<string>;
+            showLoadingScreen(): Promise<string> | Promise<Template>;
             /**
                 * Hide the loading screen
                 */
-            hideLoadingScreen(): Promise<Template> | Promise<string>;
+            hideLoadingScreen(): Promise<string> | Promise<Template>;
             dispose(): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
     }
@@ -924,7 +924,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1558,20 +1558,6 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -200,11 +200,11 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * Mainly used for help and errors
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 */
-            showOverlayScreen(subScreen: string): Promise<Template> | Promise<string>;
+            showOverlayScreen(subScreen: string): Promise<string> | Promise<Template>;
             /**
                 * Hide the overlay screen.
                 */
-            hideOverlayScreen(): Promise<Template> | Promise<string>;
+            hideOverlayScreen(): Promise<string> | Promise<Template>;
             /**
                 * show the viewer (in case it was hidden)
                 *
@@ -221,11 +221,11 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * Show the loading screen.
                 * The loading screen can be configured using the configuration object
                 */
-            showLoadingScreen(): Promise<Template> | Promise<string>;
+            showLoadingScreen(): Promise<string> | Promise<Template>;
             /**
                 * Hide the loading screen
                 */
-            hideLoadingScreen(): Promise<Template> | Promise<string>;
+            hideLoadingScreen(): Promise<string> | Promise<Template>;
             dispose(): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
     }
@@ -985,14 +985,13 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
-    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1663,22 +1662,6 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
-declare module 'babylonjs-viewer/optimizer/custom/extended' {
-    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';

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

@@ -2,6 +2,7 @@
 
 ## Major updates
 
+- [Inspector v2.0](https://doc.babylonjs.com/features/playground_debuglayer). [Dev log](https://medium.com/@babylonjs/dev-log-creating-the-new-inspector-b15c50900205) ([Deltakosh](https://github.com/deltakosh))
 - Added support for [parallel shader compilation](https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/) ([Deltakosh](https://github.com/deltakosh))
 - Added FlyCamera for free navigation in 3D space, with a limited set of settings ([Phuein](https://github.com/phuein)) [@NEED DEMO]
 - Added [Object Based Motion Blur](http://doc.babylonjs.com/how_to/using_motionblurpostprocess) post-process ([julien-moreau](https://github.com/julien-moreau))
@@ -60,7 +61,11 @@
 - Added opacity texture support to `GridMaterial` ([Deltakosh](https://github.com/deltakosh))
 - Added support for deserializing morph target animations in animation groups
 - AssetContainer dispose method ([TrevorDev](https://github.com/TrevorDev))
-
+- Loading texture with KTX will fallback to non-KTX loader if KTX loader fails ([TrevorDev](https://github.com/TrevorDev))
+- `Layer` are now supported in `RenderTargetTexture` ([Sebavan](https://github.com/Sebavan))
+- Make onscreen joystick's canvas public ([TrevorDev](https://github.com/TrevorDev))
+- Added `Tools.CustomRequestHeaders`, `Tools.UseCustomRequestHeaders`, `Tools.InjectCustomRequestHeaders` to send Custom Request Headers alongside XMLHttpRequest's i.e. when loading files (Tools.Loadfile) from resources requiring special headers like 'Authorization' ([susares](https://github.com/susares))
+- Added `.serialize` and `.Parse` functions in `ReflectionProbe` to retrieve reflection probes when parsing a previously serialized material ([julien-moreau](https://github.com/julien-moreau))
 ### glTF Loader
 
 - Added support for mesh instancing for improved performance when multiple nodes point to the same mesh ([bghgary](https://github.com/bghgary))
@@ -77,12 +82,14 @@
 - Removed bones from rootNodes where they should never have been ([Deltakosh](https://github.com/deltakosh))
 - Refocusing on input gui with pointer events ([TrevorDev](https://github.com/TrevorDev))
 - Gizmo scaling not consistent when camera is parented ([TrevorDev](https://github.com/TrevorDev))
-- Context loss causing unexpected results with dynamic textures ([TrevorDev](https://github.com/TrevorDev))
+- Context loss causing unexpected results with dynamic textures, geometries with the same name and reflectionTextures ([TrevorDev](https://github.com/TrevorDev))
 - CreateScreenshotUsingRenderTarget stretches mirror textures when setting both width and height ([TrevorDev](https://github.com/TrevorDev))
 - VR helper only updating vr cameras position when entering vr, rotation was missing ([TrevorDev](https://github.com/TrevorDev))
 - Fix VR controllers after gltfLoader transformNode change ([TrevorDev](https://github.com/TrevorDev))
 - Bounding Box fixedDragMeshScreenSize stopped working and allow rotating through bounding box ([TrevorDev](https://github.com/TrevorDev))
 - VR helper would rotate non vr camera while in VR ([TrevorDev](https://github.com/TrevorDev))
+- PointerDragBahavior using Mesh as base type, causing type-checking problems with AbstractMesh ([Poolminer](https://github.com/Poolminer/))
+- TransformNode lookAt not working in world space when node's parent has rotation ([TrevorDev](https://github.com/TrevorDev))
 
 ### Core Engine
 - Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))
@@ -94,6 +101,7 @@
 - Add missing effect layer to asset container ([TrevorDev](https://github.com/TrevorDev))
 - Fixed effect layer compatibility with multi materials ([Sebavan](https://github.com/Sebavan))
 - Added a `DeepImmutable<T>` type to specifiy that a referenced object should be considered recursively immutable, meaning that all its properties are `readonly` and that if a property is a reference to an object, this object is also recursively immutable. ([barroij](https://github.com/barroij))
+- Fixed `VideoTexture` poster property when autoplay is turned off.
 
 ### Viewer
 

+ 71 - 20
gui/src/2D/advancedDynamicTexture.ts

@@ -68,6 +68,10 @@ export class AdvancedDynamicTexture extends DynamicTexture {
     private _blockNextFocusCheck = false;
     private _renderScale = 1;
     private _rootCanvas: Nullable<HTMLCanvasElement>;
+
+    /** @hidden */
+    public _needRedraw = false;
+
     /**
      * Define type to string to ensure compatibility across browsers
      * Safari doesn't support DataTransfer constructor
@@ -80,6 +84,11 @@ export class AdvancedDynamicTexture extends DynamicTexture {
     public onClipboardObservable = new Observable<ClipboardInfo>();
 
     /**
+     * Observable event triggered each time a pointer down is intercepted by a control
+     */
+    public onControlPickedObservable = new Observable<Control>();
+
+    /**
      * Gets or sets a boolean defining if alpha is stored as premultiplied
      */
     public premulAlpha = false;
@@ -204,6 +213,25 @@ export class AdvancedDynamicTexture extends DynamicTexture {
     }
 
     /**
+     * Returns an array containing the root container.
+     * This is mostly used to let the Inspector introspects the ADT
+     * @returns an array containing the rootContainer
+     */
+    public getChildren(): Array<Container> {
+        return [this._rootContainer];
+    }
+
+    /**
+     * Will return all controls that are inside this texture
+     * @param directDescendantsOnly defines if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered
+     * @param predicate defines an optional predicate that will be called on every evaluated child, the predicate must return true for a given child to be part of the result, otherwise it will be ignored
+     * @return all child controls
+     */
+    public getDescendants(directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): Control[] {
+        return this._rootContainer.getDescendants(directDescendantsOnly, predicate);
+    }
+
+    /**
      * Gets or sets the current focused control
      */
     public get focusedControl(): Nullable<IFocusableControl> {
@@ -256,15 +284,15 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         this._clipboardData = value;
     }
 
-     /**
-     * Creates a new AdvancedDynamicTexture
-     * @param name defines the name of the texture
-     * @param width defines the width of the texture
-     * @param height defines the height of the texture
-     * @param scene defines the hosting scene
-     * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
-     * @param samplingMode defines the texture sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
-     */
+    /**
+    * Creates a new AdvancedDynamicTexture
+    * @param name defines the name of the texture
+    * @param width defines the width of the texture
+    * @param height defines the height of the texture
+    * @param scene defines the hosting scene
+    * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
+    * @param samplingMode defines the texture sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
+    */
     constructor(name: string, width = 0, height = 0, scene: Nullable<Scene>, generateMipMaps = false, samplingMode = Texture.NEAREST_SAMPLINGMODE) {
         super(name, { width: width, height: height }, scene, generateMipMaps, samplingMode, Engine.TEXTUREFORMAT_RGBA);
 
@@ -302,6 +330,14 @@ export class AdvancedDynamicTexture extends DynamicTexture {
     }
 
     /**
+     * Get the current class name of the texture useful for serialization or dynamic coding.
+     * @returns "AdvancedDynamicTexture"
+     */
+    public getClassName(): string {
+        return "AdvancedDynamicTexture";
+    }
+
+    /**
      * Function used to execute a function on all controls
      * @param func defines the function to execute
      * @param container defines the container where controls belong. If null the root container will be used
@@ -401,6 +437,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
 
         this._rootContainer.dispose();
         this.onClipboardObservable.clear();
+        this.onControlPickedObservable.clear();
 
         super.dispose();
     }
@@ -540,6 +577,11 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         context.strokeStyle = "white";
         var measure = new Measure(0, 0, renderWidth, renderHeight);
         this._rootContainer._draw(measure, context);
+
+        if (this._needRedraw) { // We need to redraw as some elements dynamically adapt to their content
+            this._needRedraw = false;
+            this._render();
+        }
     }
 
     /** @hidden */
@@ -549,6 +591,13 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         }
     }
 
+    /** @hidden */
+    public _registerLastControlDown(control: Control, pointerId: number) {
+        this._lastControlDown[pointerId] = control;
+
+        this.onControlPickedObservable.notifyObservers(control);
+    }
+
     private _doPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): void {
         var scene = this.getScene();
 
@@ -560,8 +609,10 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         var textureSize = this.getSize();
 
         if (this._isFullscreen) {
-            x = x * (textureSize.width / engine.getRenderWidth());
-            y = y * (textureSize.height / engine.getRenderHeight());
+            let camera = scene.cameraToUseForPointers || scene.activeCamera;
+            let viewport = camera!.viewport;
+            x = x * (textureSize.width / (engine.getRenderWidth() * viewport.width));
+            y = y * (textureSize.height / (engine.getRenderHeight() * viewport.height));
         }
 
         if (this._capturingControl[pointerId]) {
@@ -617,7 +668,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
             if (pi.type !== PointerEventTypes.POINTERMOVE
                 && pi.type !== PointerEventTypes.POINTERUP
                 && pi.type !== PointerEventTypes.POINTERDOWN) {
-                    return;
+                return;
             }
 
             if (!scene) {
@@ -630,9 +681,9 @@ export class AdvancedDynamicTexture extends DynamicTexture {
                 return;
             }
             let engine = scene.getEngine();
-            let viewport = camera.viewport;
-            let x = (scene.pointerX / engine.getHardwareScalingLevel() - viewport.x * engine.getRenderWidth()) / viewport.width;
-            let y = (scene.pointerY / engine.getHardwareScalingLevel() - viewport.y * engine.getRenderHeight()) / viewport.height;
+            let viewport = camera.viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
+            let x = scene.pointerX / engine.getHardwareScalingLevel() - viewport.x;
+            let y = scene.pointerY / engine.getHardwareScalingLevel() - (engine.getRenderHeight() - viewport.y - viewport.height);
 
             this._shouldBlockPointer = false;
             // Do picking modifies _shouldBlockPointer
@@ -653,7 +704,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         this.onClipboardObservable.notifyObservers(ev);
         evt.preventDefault();
     }
-     /** @hidden */
+    /** @hidden */
     private onClipboardCut = (evt: ClipboardEvent) => {
         let ev = new ClipboardInfo(ClipboardEventTypes.CUT, evt);
         this.onClipboardObservable.notifyObservers(ev);
@@ -666,9 +717,9 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         evt.preventDefault();
     }
 
-   /**
-    * Register the clipboard Events onto the canvas
-    */
+    /**
+     * Register the clipboard Events onto the canvas
+     */
     public registerClipboardEvents(): void {
         self.addEventListener("copy", this.onClipboardCopy, false);
         self.addEventListener("cut", this.onClipboardCut, false);
@@ -679,7 +730,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
      */
     public unRegisterClipboardEvents(): void {
         self.removeEventListener("copy", this.onClipboardCopy);
-        self.removeEventListener("cut",  this.onClipboardCut);
+        self.removeEventListener("cut", this.onClipboardCut);
         self.removeEventListener("paste", this.onClipboardPaste);
     }
 

+ 22 - 10
gui/src/2D/controls/colorpicker.ts

@@ -353,22 +353,22 @@ export class ColorPicker extends Control {
         this.value = this._tmpColor;
     }
 
-    private _isPointOnSquare(coordinates: Vector2): boolean {
+    private _isPointOnSquare(x: number, y: number): boolean {
         this._updateSquareProps();
 
         var left = this._squareLeft;
         var top = this._squareTop;
         var size = this._squareSize;
 
-        if (coordinates.x >= left && coordinates.x <= left + size &&
-            coordinates.y >= top && coordinates.y <= top + size) {
+        if (x >= left && x <= left + size &&
+            y >= top && y <= top + size) {
             return true;
         }
 
         return false;
     }
 
-    private _isPointOnWheel(coordinates: Vector2): boolean {
+    private _isPointOnWheel(x: number, y: number): boolean {
         var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * .5;
         var centerX = radius + this._currentMeasure.left;
         var centerY = radius + this._currentMeasure.top;
@@ -377,8 +377,8 @@ export class ColorPicker extends Control {
         var radiusSq = radius * radius;
         var innerRadiusSq = innerRadius * innerRadius;
 
-        var dx = coordinates.x - centerX;
-        var dy = coordinates.y - centerY;
+        var dx = x - centerX;
+        var dy = y - centerY;
 
         var distSq = dx * dx + dy * dy;
 
@@ -399,21 +399,33 @@ export class ColorPicker extends Control {
         this._pointerStartedOnSquare = false;
         this._pointerStartedOnWheel = false;
 
-        if (this._isPointOnSquare(coordinates)) {
+        // Invert transform
+        this._invertTransformMatrix.transformCoordinates(coordinates.x, coordinates.y, this._transformedPosition);
+
+        let x = this._transformedPosition.x;
+        let y = this._transformedPosition.y;
+
+        if (this._isPointOnSquare(x, y)) {
             this._pointerStartedOnSquare = true;
-        } else if (this._isPointOnWheel(coordinates)) {
+        } else if (this._isPointOnWheel(x, y)) {
             this._pointerStartedOnWheel = true;
         }
 
-        this._updateValueFromPointer(coordinates.x, coordinates.y);
+        this._updateValueFromPointer(x, y);
         this._host._capturingControl[pointerId] = this;
 
         return true;
     }
 
     public _onPointerMove(target: Control, coordinates: Vector2): void {
+        // Invert transform
+        this._invertTransformMatrix.transformCoordinates(coordinates.x, coordinates.y, this._transformedPosition);
+
+        let x = this._transformedPosition.x;
+        let y = this._transformedPosition.y;
+
         if (this._pointerIsDown) {
-            this._updateValueFromPointer(coordinates.x, coordinates.y);
+            this._updateValueFromPointer(x, y);
         }
 
         super._onPointerMove(target, coordinates);

+ 29 - 2
gui/src/2D/controls/container.ts

@@ -270,6 +270,7 @@ export class Container extends Control {
             }
 
             this._localDraw(context);
+            this._renderHighlight(context);
 
             if (this.clipChildren) {
                 this._clipForChildren(context);
@@ -283,6 +284,7 @@ export class Container extends Control {
                     child._tempParentMeasure.copyFrom(this._measureForChildren);
 
                     child._draw(this._measureForChildren, context);
+                    child._renderHighlight(context);
 
                     if (child.onAfterDrawObservable.hasObservers()) {
                         child.onAfterDrawObservable.notifyObservers(child);
@@ -298,10 +300,16 @@ export class Container extends Control {
             }
 
             if (this.adaptWidthToChildren && computedWidth >= 0) {
-                this.width = computedWidth + "px";
+                if (this.width !== computedWidth + "px") {
+                    this.width = computedWidth + "px";
+                    this._host._needRedraw = true;
+                }
             }
             if (this.adaptHeightToChildren && computedHeight >= 0) {
-                this.height = computedHeight + "px";
+                if (this.height !== computedHeight + "px") {
+                    this.height = computedHeight + "px";
+                    this._host._needRedraw = true;
+                }
             }
         }
         context.restore();
@@ -312,6 +320,25 @@ export class Container extends Control {
     }
 
     /** @hidden */
+    public _getDescendants(results: Control[], directDescendantsOnly: boolean = false, predicate?: (control: Control) => boolean): void {
+        if (!this.children) {
+            return;
+        }
+
+        for (var index = 0; index < this.children.length; index++) {
+            var item = this.children[index];
+
+            if (!predicate || predicate(item)) {
+                results.push(item);
+            }
+
+            if (!directDescendantsOnly) {
+                item._getDescendants(results, false, predicate);
+            }
+        }
+    }
+
+    /** @hidden */
     public _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean {
         if (!this.isVisible || this.notRenderable) {
             return false;

+ 75 - 1
gui/src/2D/controls/control.ts

@@ -73,6 +73,7 @@ export class Control {
     private _cachedOffsetX: number;
     private _cachedOffsetY: number;
     private _isVisible = true;
+    private _isHighlighted = false;
     /** @hidden */
     public _linkedMesh: Nullable<AbstractMesh>;
     private _fontSet = false;
@@ -86,6 +87,16 @@ export class Control {
     /** @hidden */
     public _tag: any;
 
+    /**
+     * Gets or sets the unique id of the node. Please note that this number will be updated when the control is added to a container
+     */
+    public uniqueId: number;
+
+    /**
+     * Gets or sets an object used to store user defined information for the node
+     */
+    public metadata: any = null;
+
     /** Gets or sets a boolean indicating if the control can be hit with pointer events */
     public isHitTestVisible = true;
     /** Gets or sets a boolean indicating if the control can block pointer events */
@@ -121,6 +132,14 @@ export class Control {
     }
 
     /**
+     * Get the current class name of the control.
+     * @returns current class name
+     */
+    public getClassName(): string {
+        return this._getTypeName();
+    }
+
+    /**
     * An event triggered when the pointer move over the control.
     */
     public onPointerMoveObservable = new Observable<Vector2>();
@@ -188,6 +207,22 @@ export class Control {
         this._markAsDirty();
     }
 
+    /**
+     * Gets or sets a boolean indicating that we want to highlight the control (mostly for debugging purpose)
+     */
+    public get isHighlighted(): boolean {
+        return this._isHighlighted;
+    }
+
+    public set isHighlighted(value: boolean) {
+        if (this._isHighlighted === value) {
+            return;
+        }
+
+        this._isHighlighted = value;
+        this._markAsDirty();
+    }
+
     /** Gets or sets a value indicating the scale factor on X axis (1 by default)
      * @see http://doc.babylonjs.com/how_to/gui#rotation-and-scaling
     */
@@ -847,6 +882,25 @@ export class Control {
         this.notRenderable = false;
     }
 
+    /** @hidden */
+    public _getDescendants(results: Control[], directDescendantsOnly: boolean = false, predicate?: (control: Control) => boolean): void {
+        // Do nothing by default
+    }
+
+    /**
+     * Will return all controls that have this control as ascendant
+     * @param directDescendantsOnly defines if true only direct descendants of 'this' will be considered, if false direct and also indirect (children of children, an so on in a recursive manner) descendants of 'this' will be considered
+     * @param predicate defines an optional predicate that will be called on every evaluated child, the predicate must return true for a given child to be part of the result, otherwise it will be ignored
+     * @return all child controls
+     */
+    public getDescendants(directDescendantsOnly?: boolean, predicate?: (control: Control) => boolean): Control[] {
+        var results = new Array<Control>();
+
+        this._getDescendants(results, directDescendantsOnly, predicate);
+
+        return results;
+    }
+
     /**
      * Link current control with a target mesh
      * @param mesh defines the mesh to link with
@@ -941,6 +995,9 @@ export class Control {
     public _link(root: Nullable<Container>, host: AdvancedDynamicTexture): void {
         this._root = root;
         this._host = host;
+        if (this._host) {
+            this.uniqueId = this._host.getScene()!.getUniqueId();
+        }
     }
 
     /** @hidden */
@@ -977,6 +1034,23 @@ export class Control {
     }
 
     /** @hidden */
+    public _renderHighlight(context: CanvasRenderingContext2D): void {
+        if (!this.isHighlighted) {
+            return;
+        }
+
+        context.strokeStyle = "#4affff";
+        context.lineWidth = 2;
+
+        this._renderHighlightSpecific(context);
+    }
+
+    /** @hidden */
+    protected _renderHighlightSpecific(context: CanvasRenderingContext2D): void {
+        context.strokeRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+    }
+
+    /** @hidden */
     protected _applyStates(context: CanvasRenderingContext2D): void {
         if (this._isFontSizeInPercentage) {
             this._fontSet = true;
@@ -1373,7 +1447,7 @@ export class Control {
 
         if (type === PointerEventTypes.POINTERDOWN) {
             this._onPointerDown(this, this._dummyVector2, pointerId, buttonIndex);
-            this._host._lastControlDown[pointerId] = this;
+            this._host._registerLastControlDown(this, pointerId);
             this._host._lastPickedControl = this;
             return true;
         }

+ 59 - 11
gui/src/2D/controls/grid.ts

@@ -286,7 +286,7 @@ export class Grid extends Container {
         return "Grid";
     }
 
-    protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+    protected _getGridDefinitions(definitionCallback: (lefts: number[], tops: number[], widths: number[], heights: number[]) => void) {
         let widths = [];
         let heights = [];
         let lefts = [];
@@ -352,23 +352,71 @@ export class Grid extends Container {
             index++;
         }
 
-        // Setting child sizes
+        definitionCallback(lefts, tops, widths, heights);
+    }
+
+    protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        this._getGridDefinitions((lefts: number[], tops: number[], widths: number[], heights: number[]) => {
+            // Setting child sizes
+            for (var key in this._cells) {
+                if (!this._cells.hasOwnProperty(key)) {
+                    continue;
+                }
+                let split = key.split(":");
+                let x = parseInt(split[0]);
+                let y = parseInt(split[1]);
+                let cell = this._cells[key];
+
+                cell.left = lefts[y] + "px";
+                cell.top = tops[x] + "px";
+                cell.width = widths[y] + "px";
+                cell.height = heights[x] + "px";
+            }
+        });
+
+        super._additionalProcessing(parentMeasure, context);
+    }
+
+    public _flagDescendantsAsMatrixDirty(): void {
         for (var key in this._cells) {
             if (!this._cells.hasOwnProperty(key)) {
                 continue;
             }
-            let split = key.split(":");
-            let x = parseInt(split[0]);
-            let y = parseInt(split[1]);
-            let cell = this._cells[key];
 
-            cell.left = lefts[y] + "px";
-            cell.top = tops[x] + "px";
-            cell.width = widths[y] + "px";
-            cell.height = heights[x] + "px";
+            let child = this._cells[key];
+            child._markMatrixAsDirty();
         }
+    }
 
-        super._additionalProcessing(parentMeasure, context);
+    protected _renderHighlightSpecific(context: CanvasRenderingContext2D): void {
+        if (!this.isHighlighted) {
+            return;
+        }
+
+        super._renderHighlightSpecific(context);
+
+        this._getGridDefinitions((lefts: number[], tops: number[], widths: number[], heights: number[]) => {
+
+            // Columns
+            for (var index = 0; index < lefts.length; index++) {
+                const left = this._currentMeasure.left + lefts[index] + widths[index];
+                context.beginPath();
+                context.moveTo(left, this._currentMeasure.top);
+                context.lineTo(left, this._currentMeasure.top + this._currentMeasure.height);
+                context.stroke();
+            }
+
+            // Rows
+            for (var index = 0; index < tops.length; index++) {
+                const top = this._currentMeasure.top + tops[index] + heights[index];
+                context.beginPath();
+                context.moveTo(this._currentMeasure.left, top);
+                context.lineTo(this._currentMeasure.left + this._currentMeasure.width, top);
+                context.stroke();
+            }
+        });
+
+        context.restore();
     }
 
     /** Releases associated resources */

+ 25 - 23
gui/src/2D/controls/inputText.ts

@@ -268,10 +268,12 @@ export class InputText extends Control implements IFocusableControl {
     }
 
     public set text(value: string) {
-        if (this._text === value) {
+        let valueAsString = value.toString(); // Forcing convertion
+
+        if (this._text === valueAsString) {
             return;
         }
-        this._text = value;
+        this._text = valueAsString;
         this._markAsDirty();
 
         this.onTextChangedObservable.notifyObservers(this);
@@ -352,21 +354,21 @@ export class InputText extends Control implements IFocusableControl {
 
         this._onClipboardObserver = this._host.onClipboardObservable.add((clipboardInfo) => {
             // process clipboard event, can be configured.
-             switch (clipboardInfo.type){
-                 case ClipboardEventTypes.COPY:
-                         this._onCopyText(clipboardInfo.event);
-                         this.onTextCopyObservable.notifyObservers(this);
-                         break;
-                 case ClipboardEventTypes.CUT:
-                         this._onCutText(clipboardInfo.event);
-                         this.onTextCutObservable.notifyObservers(this);
-                         break;
-                 case ClipboardEventTypes.PASTE:
-                         this._onPasteText(clipboardInfo.event);
-                         this.onTextPasteObservable.notifyObservers(this);
-                         break;
-                 default: return;
-              }
+            switch (clipboardInfo.type) {
+                case ClipboardEventTypes.COPY:
+                    this._onCopyText(clipboardInfo.event);
+                    this.onTextCopyObservable.notifyObservers(this);
+                    break;
+                case ClipboardEventTypes.CUT:
+                    this._onCutText(clipboardInfo.event);
+                    this.onTextCutObservable.notifyObservers(this);
+                    break;
+                case ClipboardEventTypes.PASTE:
+                    this._onPasteText(clipboardInfo.event);
+                    this.onTextPasteObservable.notifyObservers(this);
+                    break;
+                default: return;
+            }
         });
 
         let scene = this._host.getScene();
@@ -433,7 +435,7 @@ export class InputText extends Control implements IFocusableControl {
                     if (this._isTextHighlightOn) {
                         this.text = this._text.slice(0, this._startHighlightIndex) + this._text.slice(this._endHighlightIndex);
                         this._isTextHighlightOn = false;
-                        this._cursorOffset =  this.text.length - this._startHighlightIndex;
+                        this._cursorOffset = this.text.length - this._startHighlightIndex;
                         this._blinkIsEven = false;
                         if (evt) {
                             evt.preventDefault();
@@ -468,7 +470,7 @@ export class InputText extends Control implements IFocusableControl {
                     }
                     return;
                 }
-                if (this._text && this._text.length > 0  && this._cursorOffset > 0) {
+                if (this._text && this._text.length > 0 && this._cursorOffset > 0) {
                     let deletePosition = this._text.length - this._cursorOffset;
                     this.text = this._text.slice(0, deletePosition) + this._text.slice(deletePosition + 1);
                     this._cursorOffset--;
@@ -561,7 +563,7 @@ export class InputText extends Control implements IFocusableControl {
         this._endHighlightIndex = this._startHighlightIndex;
         for (let rWord = /\w+/g, left = 1, right = 1; this._startHighlightIndex > 0 && this._endHighlightIndex < this._text.length && (left || right);) {
             right = (this._text[this._endHighlightIndex].search(rWord) !== -1) ? ++this._endHighlightIndex : 0;
-            left =  (this._text[this._startHighlightIndex - 1 ].search(rWord) !== -1) ? --this._startHighlightIndex : 0;
+            left = (this._text[this._startHighlightIndex - 1].search(rWord) !== -1) ? --this._startHighlightIndex : 0;
         }
         this.onTextHighlightObservable.notifyObservers(this);
         this._isTextHighlightOn = true;
@@ -598,7 +600,7 @@ export class InputText extends Control implements IFocusableControl {
         try {
             ev.clipboardData.setData("text/plain", this._highlightedText);
         }
-        catch {} //pass
+        catch { } //pass
         this._host.clipboardData = this._highlightedText;
     }
     /** @hidden */
@@ -648,7 +650,7 @@ export class InputText extends Control implements IFocusableControl {
             // Background
             if (this._isFocused) {
                 if (this._focusedBackground) {
-                    context.fillStyle = this._isEnabled ?  this._focusedBackground : this._disabledColor;
+                    context.fillStyle = this._isEnabled ? this._focusedBackground : this._disabledColor;
 
                     context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
                 }
@@ -760,7 +762,7 @@ export class InputText extends Control implements IFocusableControl {
                     this._markAsDirty();
                 }, 500);
 
-                 //show the highlighted text
+                //show the highlighted text
                 if (this._isTextHighlightOn) {
                     clearTimeout(this._blinkTimeout);
                     let highlightCursorOffsetWidth = context.measureText(this.text.substring(this._startHighlightIndex)).width;

+ 3 - 1
gui/src/2D/valueAndUnit.ts

@@ -5,6 +5,7 @@ import { AdvancedDynamicTexture } from "./advancedDynamicTexture";
  */
 export class ValueAndUnit {
     private _value = 1;
+    private _originalUnit: number;
     /**
      * Gets or sets a value indicating that this value will not scale accordingly with adaptive scaling property
      * @see http://doc.babylonjs.com/how_to/gui#adaptive-scaling
@@ -23,6 +24,7 @@ export class ValueAndUnit {
         /** defines a boolean indicating if the value can be negative */
         public negativeValueAllowed = true) {
         this._value = value;
+        this._originalUnit = unit;
     }
 
     /** Gets a boolean indicating if the value is a percentage */
@@ -116,7 +118,7 @@ export class ValueAndUnit {
         }
 
         var sourceValue = parseFloat(match[1]);
-        var sourceUnit = this.unit;
+        var sourceUnit = this._originalUnit;
 
         if (!this.negativeValueAllowed) {
             if (sourceValue < 0) {

+ 8 - 0
gui/src/3D/controls/control3D.ts

@@ -201,6 +201,14 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
         return this._getTypeName();
     }
 
+    /**
+     * Get the current class name of the control.
+     * @returns current class name
+     */
+    public getClassName(): string {
+        return this._getTypeName();
+    }
+
     protected _getTypeName(): string {
         return "Control3D";
     }

+ 1 - 0
gui/src/3D/gui3DManager.ts

@@ -53,6 +53,7 @@ export class GUI3DManager implements IDisposable {
 
         this._utilityLayer = new UtilityLayerRenderer(this._scene);
         this._utilityLayer.onlyCheckPointerDownEvents = false;
+        this._utilityLayer.pickUtilitySceneFirst = false;
         this._utilityLayer.mainSceneTrackerPredicate = (mesh: Nullable<AbstractMesh>) => {
             return mesh && mesh.metadata && mesh.metadata._node;
         };

+ 1 - 11
gui/webpack.config.js

@@ -1,6 +1,5 @@
 const path = require('path');
 const webpack = require('webpack');
-const DtsBundleWebpack = require('dts-bundle-webpack');
 const CleanWebpackPlugin = require('clean-webpack-plugin');
 
 module.exports = {
@@ -17,8 +16,7 @@ module.exports = {
             amd: "babylonjs-gui",
             commonjs: "babylonjs-gui"
         },
-        umdNamedDefine: true,
-        //devtoolModuleFilenameTemplate: "[absolute-resource-path]"
+        umdNamedDefine: true
     },
     resolve: {
         extensions: [".js", '.ts']
@@ -57,14 +55,6 @@ module.exports = {
             path.resolve(__dirname, './src/**/*.js'),
             path.resolve(__dirname, './src/**/*.map')
         ]),
-        // moved out of here due to the way gulp works...
-        /*new DtsBundleWebpack({
-            name: "babylonjs-gui",
-            main: path.resolve(__dirname, '../dist/preview release/gui/build/index.d.ts'),
-            out: path.resolve(__dirname, '../dist/preview release/gui/babylon.gui.module.d.ts'),
-            baseDir: path.resolve(__dirname, '../dist/preview release/gui/build/'),
-            headerText: "BabylonJS GUI"
-        }),*/
         new webpack.WatchIgnorePlugin([
             /\.js$/,
             /\.d\.ts$/

+ 5 - 4
inspector/index.html

@@ -17,18 +17,19 @@
             padding: 0;
             margin: 0
         }
-        
+
         #wrapper {
             width: 100%;
             height: 100%;
             display: flex;
             overflow: hidden;
         }
-        
+
         canvas {
             width: 100%;
+            height: 100%;
         }
-        
+
         #inspector {
             width: 25%;
         }
@@ -46,7 +47,7 @@
 
     <!--Starting the game-->
     <script>
-        BABYLONDEVTOOLS.Loader.require("test/index.js").load(function () {
+        BABYLONDEVTOOLS.Loader.require("test/index.js").load(function() {
             new Test('game-canvas');
         });
     </script>

+ 26 - 15
inspector/package.json

@@ -1,6 +1,6 @@
 {
     "name": "babylonjs-inspector",
-    "version": "1.0.0",
+    "version": "2.0.0",
     "description": "",
     "scripts": {
         "start:server": "webpack-dev-server",
@@ -24,19 +24,30 @@
     },
     "homepage": "https://github.com/BabylonJS/Babylon.js#readme",
     "devDependencies": {
-        "@types/node": "^10.5.3",
-        "clean-webpack-plugin": "^0.1.19",
-        "css-loader": "^1.0.0",
-        "dts-bundle-webpack": "^1.0.0",
-        "mini-css-extract-plugin": "^0.4.1",
-        "node-sass": "^4.9.2",
-        "sass-loader": "^7.0.3",
-        "style-loader": "^0.21.0",
+        "@fortawesome/fontawesome-svg-core": "~1.2.8",
+        "@fortawesome/free-regular-svg-icons": "~5.4.1",
+        "@fortawesome/free-solid-svg-icons": "~5.4.1",
+        "@fortawesome/react-fontawesome": "~0.1.3",
+        "@types/react": "~16.4.18",
+        "@types/react-dom": "~16.0.9",
+        "clean-webpack-plugin": "~0.1.19",
+        "css-loader": "~1.0.0",
+        "dts-bundle": "~0.7.3",
+        "file-loader": "~2.0.0",
+        "gulp": "~4.0.0",
+        "gulp-webserver": "~0.9.1",
+        "mini-css-extract-plugin": "~0.4.4",
+        "node-sass": "~4.10.0",
+        "re-resizable": "~4.9.1",
+        "react": "~16.5.2",
+        "react-dom": "~16.5.2",
+        "sass-loader": "~7.1.0",
+        "split.js": "^1.5.9",
+        "style-loader": "~0.23.1",
         "ts-loader": "^4.0.0",
-        "typescript": "~3.0.1",
-        "webpack": "^4.16.2",
-        "webpack-cli": "^3.1.0",
-        "webpack-dev-server": "^3.1.5"
-    },
-    "dependencies": {}
+        "typescript": "~3.1.3",
+        "webpack": "~4.21.0",
+        "webpack-cli": "~3.1.2",
+        "webpack-stream": "5.0.0"
+    }
 }

+ 0 - 156
inspector/sass/_detailPanel.scss

@@ -1,156 +0,0 @@
-// The main class of the detail panel
-.insp-details {
-  background-color: $background;
-  overflow-y: auto;
-  overflow-x: auto;
-  color:$color;
-  font-family: $font;
-
-  .details {
-      padding-left: 5px;
-  }
-
-  // Common defintion between header row and detail row
-  .base-row {      
-    display:flex;
-    width:100%;
-
-    .base-property {
-        padding: 2px 0 2px 0;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-        overflow: hidden;
-    }
-    // Property name
-    .prop-name {
-        @extend .property-name;
-        @extend .base-property;
-        width:35%;
-    }
-    // property value
-    .prop-value {
-        @extend .base-property;
-        width:59%;
-        padding-left:5px;
-        &.clickable {
-            cursor:pointer;
-            &:hover {
-                background-color:$background-lighter2;
-            }
-            &:after {
-                font-family: $font-family-icons;
-                content: "\00a0 \00a0 \00a0 \f105"; // 4 space before + angle-right
-                font-weight: 900; // To display solid font family
-            }
-        }   
-    }
-    
-    // input {
-    //     border:0;
-    //     font-family: $font;
-    //     background-color: $background-lighter;
-    //     color:$color;
-    //     // Remove blue border on focus
-    //     &:focus {
-    //         outline:none;
-    //     }
-    // }
-  }
-  
-  // A line of details composed of name, type, value, id, flagId
-  .row {
-    @extend .base-row;
-    &:nth-child(even) {
-        background-color:$background-lighter;
-    }
-    &.unfolded {          
-        .prop-value.clickable:after {
-            font-family: $font-family-icons;
-            content: "\00a0 \00a0 \00a0 \f107"; // 4 space before + angle-down
-            font-weight: 900; // To display solid font family
-        }
-    }
-  }
-
-  
-  // Name, type, value, Id, FlagId
-  .header-row {
-    @extend .base-row;
-    background-color: $background-lighter; 
-    color           : $color;
-    width           : 100%;
-    max-width       : 100%;
-    
-    // Special definition for text color: the color is the default one
-    // All header columns
-    & > * {
-        color:$color !important;
-        padding:5px 0 5px 5px !important;
-        cursor: pointer;
-        &:hover {
-            background-color:$background-lighter2;
-        }
-    }
-
-    .header-col {
-        display:flex;
-        justify-content: space-between;
-        align-items: center;
-
-        .sort-direction {
-            margin-right:5px;
-        }
-    }
-  }
-  
-  // A div used to view a property in the property line (color, texture...)
-  .element-viewer {
-      position:relative;
-      width:10px;
-      height:10px;
-      display:inline-block;
-      margin-left:5px;
-  }
-
-  // The div displaying a color
-  .color-element {
-      @extend .element-viewer;
-      width: 20px;
-      height: 15px;
-  }
-
-  // The div displaying a texture element
-  .texture-element {
-      @extend .element-viewer;
-      color:$color-top;
-      margin-left:10px; 
-
-      .texture-viewer {
-          
-          color:$color;
-          position:absolute;
-          z-index:10;
-          bottom:0;
-          right:0;
-          display:block;
-          width:150px;
-          height:150px;
-          border: 1px solid $background-lighter3;
-          background-color: $background;
-          transform: translateX(100%) translateY(100%);
-          
-          display: none;
-          flex-direction: column;
-          justify-content: flex-start;
-          align-items: center;
-
-          .texture-viewer-img {
-              margin:10px 0 10px 0;
-              max-width:110px;
-              max-height:110px;
-          }
-      }
-  }
-   
-
-}

+ 0 - 18
inspector/sass/_resizeBar.scss

@@ -1,18 +0,0 @@
-.c2di-resize-bar-v {
-  height:100%;
-  width:$resizebar-width;
-  background-color: $background;
-  cursor: col-resize;
-  flex-shrink: 0;
-  border-left:1px solid $background-lighter;
-  border-right:1px solid $background-lighter;
-}
-.c2di-resize-bar-h {
-  width:100%;
-  height:$resizebar-width;
-  background-color: $background;
-  cursor: row-resize;
-  flex-shrink: 0;
-  border-top: 1px solid $background-lighter;
-  border-bottom: 1px solid $background-lighter;
-}

+ 0 - 19
inspector/sass/_searchbar.scss

@@ -1,19 +0,0 @@
-.searchbar {
-    
-    border       : 1px solid $background-lighter;
-    margin-bottom: 5px;
-    display      : flex;
-    align-items  : center;
-    color:darken($color, 10%);
-    
-    input {
-        background-color: $background;
-        border          : none;
-        width           : 100%;
-        outline         : none;
-        font-family     : $font;
-        color           : darken($color, 10%);
-        padding         : 3px 0 3px 10px;
-        margin          : 6px 0 6px 0;
-    }
-}

+ 0 - 74
inspector/sass/_slider.scss

@@ -1,74 +0,0 @@
-$thumb-height: 15px;
-
-input[type="range"] { 
-  margin: auto;
-  -webkit-appearance: none;
-  position: relative;
-  overflow: hidden;
-  height: $thumb-height;
-  width: 50%;
-  cursor: pointer;
-  border-radius: 0; /* iOS */
-}
-
-::-webkit-slider-runnable-track {
-  background: #ddd;
-}
-
-/*
-* 1. Set to 0 height and width, and remove border for a slider without a thumb
-*/
-::-webkit-slider-thumb {
-  -webkit-appearance: none;
-  width: 20px; /* 1 */
-  height: $thumb-height; /* 1 */
-  background: #fff;
-  box-shadow: -100vw 0 0 100vw dodgerblue;
-  border: 0px solid #999; /* 1 */
-}
-
-::-moz-range-track {
-  height: $thumb-height;
-  background: #ddd;
-}
-
-::-moz-range-thumb {
-  background: #fff;
-  height: $thumb-height;
-  width: 20px;
-  border: 0px solid #999;
-  border-radius: 0 !important;
-  box-shadow: -100vw 0 0 100vw dodgerblue;
-  box-sizing: border-box;
-}
-
-::-ms-fill-lower { 
-  background: dodgerblue;
-}
-
-::-ms-thumb { 
-  background: #fff;
-  border: 0px solid #999;
-  height: $thumb-height;
-  width: 20px;
-  box-sizing: border-box;
-}
-
-::-ms-ticks-after { 
-  display: none; 
-}
-
-::-ms-ticks-before { 
-  display: none; 
-}
-
-::-ms-track { 
-  background: #ddd;
-  color: transparent;
-  height: $thumb-height;
-  border: none;
-}
-
-::-ms-tooltip { 
-  display: none;
-}

+ 0 - 92
inspector/sass/_tabPanel.scss

@@ -1,92 +0,0 @@
-.tab-panel {
-    height:100%;
-
-    &.searchable {
-        height:calc(100% - #{$searchbar-height} - 10px);   
-    }  
-
-    .texture-image {
-        max-height:400px;
-    }
-    
-    .scene-actions {
-        overflow-y: auto;
-        padding-left: 5px;
-        
-        // Action title : Textures/Options/Viewer
-        .actions-title {
-            font-size     : 1.1em;
-            padding-bottom: 10px;
-            border-bottom : 1px solid $color-bot;
-            margin        : 10px 0 10px 0;
-        }
-
-        .defaut-action {            
-            height     : 20px;
-            line-height: 20px;
-            width      : 100%;
-            cursor     : pointer;   
-            
-            &:hover {
-                background-color:$background-lighter;
-            }
-            &:active {                
-                background-color: $background-lighter2;
-            }
-        }
-
-        // Radio button
-        .action-radio {
-            @extend .defaut-action;
-            &:before {
-                width      : 1em;
-                height     : 1em;
-                line-height: 1em;
-                display    : inline-block;
-                font-family: $font-family-icons;
-                content    : "\f111";
-                margin-right:10px;
-            }
-            // radio button active
-            &.active {
-                &:before {
-                    width      : 1em;
-                    height     : 1em;
-                    line-height: 1em;
-                    display    : inline-block;
-                    font-family: $font-family-icons;
-                    content    : "\f192";
-                    color      : $color-bot;
-                    margin-right:10px;
-                }
-            }
-        }
-
-        // Check button
-        .action {             
-            @extend .defaut-action;
-            &:before {
-                width      : 1em;
-                height     : 1em;
-                line-height: 1em;
-                display    : inline-block;
-                font-family: $font-family-icons;
-                content    : "\f0c8";
-                margin-right:10px;
-            }
-                
-            &.active {
-                &:before {
-                    width      : 1em;
-                    height     : 1em;
-                    line-height: 1em;
-                    display    : inline-block;
-                    font-family: $font-family-icons;
-                    content    : "\f14a";
-                    color      : $color-bot;
-                    margin-right:10px;
-                }
-            }
-        }
-    }
-}

+ 0 - 60
inspector/sass/_tabbar.scss

@@ -1,60 +0,0 @@
-.tabbar {
-    height:$tabbar-height;
-    
-    display:flex;
-    align-items: center;
-    border-bottom: 1px solid $background-lighter2;
-    width:100%;
-    overflow-x:auto;
-    overflow-y:hidden;
-    box-sizing: border-box;
-    
-    .tab {
-        height:calc(#{$tabbar-height} - 2px);
-        width:auto;
-        padding: 0 10px 0 10px;
-        color:$color;
-        line-height: $tabbar-height;
-        text-align: center;
-        cursor: pointer;
-        margin: 0 5px 0 5px;
-        box-sizing: border-box;
-       
-        // Hover on it
-        &:hover {
-            border-bottom: 1px solid $color-top;
-            background-color: $background-lighter;
-        }
-        // Clic on it
-        &:active {
-            background-color: $background-lighter2;
-        }
-        // tab selected
-        &.active {
-            border-bottom: 1px solid $color-top;
-        }
-    }
-
-    .more-tabs {
-        width           : $tabbar-height;
-        height          : $tabbar-height;
-        display         : flex;
-        justify-content : center;
-        align-items     : center;
-        cursor          : pointer;
-        position        : relative;
-        border-right    : 1px solid $background-lighter2;
-        &:hover {
-            background-color: $background-lighter2;
-        }
-        &:active {
-            color:$color-top;
-            background-color: $background-lighter3;
-        }
-        // This tool is activated
-        &.active {
-            color:$color-top;
-        }
-
-    }
-}

+ 0 - 31
inspector/sass/_toolbar.scss

@@ -1,31 +0,0 @@
-/**
- * The toolbar contains : 
- * - a refresh tool - refresh the whole panel
- * - a popup tool - Open the inspector in a new panel
- * ...
- */   
-.toolbar {   
-    display:flex;
-     
-    .tool {
-        width          : $tabbar-height;
-        height         : $tabbar-height;
-        display        : flex;
-        justify-content: center;
-        align-items    : center;
-        cursor         : pointer;
-        position       : relative;
-        border-right   : 1px solid $background-lighter2;
-        &:hover {
-            background-color: $background-lighter2;
-        }
-        &:active {
-            color:$color-top;
-            background-color: $background-lighter3;
-        }
-        // This tool is activated
-        &.active {
-            color:$color-top;
-        }
-    }
-}

+ 0 - 14
inspector/sass/_tooltip.scss

@@ -1,14 +0,0 @@
-// Tooltip used when hovering on divisions
-
-.tooltip {
-    position        : absolute;
-    top             : $tabbar-height;
-    right           : 0;
-    color           : $color-top;
-    display         : none;
-    z-index         : 4;
-    font-family     : $font;  
-    padding         : 2px;
-    background-color: $background;
-    border          : 1px solid $background-lighter3;
-}

+ 0 - 73
inspector/sass/_tree.scss

@@ -1,73 +0,0 @@
-
-// Color for a property type
-.property-type {
-  color:$color-bot;
-}
-
-.property-name {
-  color:$color-top;
-}
-
-.insp-tree {
-  overflow-y: auto;
-  overflow-x: hidden;
-  height    : calc(50% - #{$tabbar-height} - #{$searchbar-height});
-  
-    
-    .line {
-        padding:3px;
-        cursor:pointer;
-        // Hover
-        &:hover {
-            background-color:$background-lighter;
-        }
-        // Line active (selected)
-        &.active {
-            background-color:$background-lighter3;
-            .line-content {
-                background-color:$background;
-            }
-        }
-        // > before title names
-        &.unfolded:before{            
-            width      : 1em;
-            height     : 1em;
-            line-height: 1em;
-            display    : inline-block;
-            font-family: $font-family-icons;
-            content    : "\f107";
-            font-weight: 900;          
-        }
-        &.folded:before{            
-            width      : 1em;
-            height     : 1em;
-            line-height: 1em;
-            display    : inline-block;
-            font-family: $font-family-icons;
-            content    : "\f105";
-            font-weight: 900;
-        }
-        
-        &.unfolded.transformNode > span:first-of-type{
-            color:$color-top;
-        }
-        &.folded.transformNode > span:first-of-type{ 
-            color:$color-top;
-        }
-
-        // Sub lines
-        .line-content {
-            padding-left:15px;
-            &:hover { 
-                background-color:$background;
-            }
-            .line:hover:first-child {            
-                background-color:$background-lighter2;
-            }
-            
-        }
-    }
-    .line_invisible {
-        display: none;
-    }
-}

+ 0 - 16
inspector/sass/_treeTool.scss

@@ -1,16 +0,0 @@
-/**
- * A tool contained in the tree panel (available for each item of the tree)
- */
-.treeTool {
-    margin : 3px 8px 3px 3px;
-    cursor:pointer;
-    position:relative;
-   
-    &:hover {        
-        color:$color-bot;
-    }
-    
-    &.active {
-        color:$color-bot;
-    }
-}

+ 0 - 28
inspector/sass/defines.scss

@@ -1,28 +0,0 @@
-// @import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);
-@import url(https://use.fontawesome.com/releases/v5.0.13/css/all.css);
-@import url(https://fonts.googleapis.com/css?family=Inconsolata);
-
-$font               : 'Inconsolata', sans-serif;
-
-// ------------- //
-// If you update these colors, you should also 
-// replace them in the class Inspector as well, 
-// as it's used for custom themes
-// ------------- //
-
-$color              : #ccc;
-$background         : #242424;
-$background-active  : #2c2c2c;
-$color-top          : #f29766;
-$color-bot          : #5db0d7;
-$color-error        : #fa371d;
-
-$background-lighter : lighten($color: $background, $amount         : 3%);
-$background-lighter2: lighten($color: $background-lighter, $amount : 5%);
-$background-lighter3: lighten($color: $background-lighter2, $amount: 5%);
-
-$resizebar-width    : 10px;
-$tabbar-height      : 50px;
-$searchbar-height   : 30px;
-
-$font-family-icons  : 'Font Awesome 5 Free', sans-serif;

+ 0 - 105
inspector/sass/main.scss

@@ -1,105 +0,0 @@
-
-
-.insp-wrapper {
-  // Import variables, color and font files
-  @import "defines";
-
-  // Style for resize bar
-  .gutter {
-    background-color: $background-lighter;
-    &.gutter-vertical:not(.blocked) {
-      cursor        : ns-resize;
-    }
-    &.gutter-horizontal:not(.blocked) {
-      cursor        : ew-resize;
-    }
-  }
-
-  user-select: none; 
-  display:flex;
-  font-size:0.9em;
-  font-family     : $font;
-  background-color: $background;
-
-  // The panel containing the two subpanel : tree and details
-  .insp-right-panel {
-    width: 750px;
-    overflow-y: auto;
-
-    &.popupmode {
-      width:100% !important;
-    }
-    
-    display:flex; 
-    flex-direction: column;
-    flex-shrink: 0;
-
-    // The tree panel
-    .top-panel {
-      width:100%;
-      height:100%;
-      position:relative;
-      background-color: $background;
-      color           : $color;
-      font-size       : 1em;
-      
-      // The div that will contain the tab div
-      .tab-panel-content {
-        width:100%;
-        height:calc(100% - #{$tabbar-height});   
-      }   
-
-      // The div displaying all invisible tabs (when the tabbar width is small)
-      .more-tabs-panel {
-          position:absolute;
-          z-index:10;
-          top:$tabbar-height;
-          right:0;
-          width:100px;
-          display:none;
-          flex-direction: column;
-          align-items: center;
-          justify-content: center;
-          border: 1px solid $background-lighter3;
-          background-color: $background;
-
-          .invisible-tab {
-            height     : 25px;
-            width      : 100%;
-            line-height: 25px;
-            text-align : center;
-            background-color: $background-lighter;
-            cursor:pointer;
-
-            // Hover on it
-            &:hover {
-              background-color: $background-lighter2;
-            }
-            // Clic on it
-            &:active {
-              background-color: $background-lighter3;
-            }
-          }
-
-      }
-    }
-  }
-
-  @import 'tooltip';
-
-  // All tools used on object in the tree
-  @import 'treeTool';
-  @import "tabPanel";
-  @import "tabs/shaderTab";
-  @import "tabs/consoleTab";
-  @import "tabs/statsTab";
-  @import "tabs/gltfTab";
-  @import "tabs/toolsTab";
-
-  @import "tree";
-  @import "detailPanel";
-  @import "tabbar";
-  @import "toolbar";
-  @import "searchbar";
-  @import "slider";
-}

+ 0 - 51
inspector/sass/tabs/_consoleTab.scss

@@ -1,51 +0,0 @@
-.tab-panel {
-
-    .console-panel {
-        min-height              : 100px;
-        user-select             : text;
-        box-sizing              : border-box;
-        padding                 : 0 15px;    
-        
-        .console-panel-title {
-            height              : 25px;
-            border-bottom       : 1px solid $background-lighter2;
-            text-transform      : uppercase;
-            line-height         : 25px;
-            margin-bottom       : 10px; 
-        }
-        
-        .console-panel-content {            
-            overflow-y              : auto;
-            overflow-x              : hidden;    
-            height                  : calc(100% - 30px);
-        }  
-
-        .defaut-line {
-            word-wrap: break-word;
-            padding: 3px 0 3px 5px;
-        }
-
-        .caller {
-            padding: 3px 0 3px 0;
-            color:darken($color-bot, 10%);
-        }
-
-        .log {  
-            @extend .defaut-line;
-            color:white;
-        }   
-        
-        .warn {
-            @extend .defaut-line;
-            color:orange;
-        }
-        .error {
-            @extend .defaut-line;
-            color:orangered; 
-        }
-        .object {
-            @extend .defaut-line;
-            color:$color-bot;
-        }
-    }
-}

+ 0 - 92
inspector/sass/tabs/_gltfTab.scss

@@ -1,92 +0,0 @@
-.tab-panel {
-    .gltf-actions {
-        overflow-y: auto;
-        padding-left: 5px;
-
-        .gltf-title {
-            font-size     : 1.1em;
-            padding-bottom: 10px;
-            border-bottom : 1px solid $color-bot;
-            margin        : 10px 0 10px 0;
-        }
-
-        .gltf-action {
-            height     : 20px;
-            line-height: 20px;
-            width      : 100%;
-            cursor     : pointer;
-            white-space: nowrap;
-
-            &:hover {
-                background-color: $background-lighter;
-            }
-        }
-
-        .gltf-icon {
-            width      : 1em;
-            height     : 1em;
-            line-height: 1em;
-            display    : inline-block;
-            font-family: $font-family-icons;
-            margin-right:10px;
-        }
-
-        .gltf-checkbox {
-            @extend .gltf-action;
-            &:before {
-                width      : 1em;
-                height     : 1em;
-                line-height: 1em;
-                display    : inline-block;
-                font-family: $font-family-icons;
-                content    : "\f0c8";
-                margin-right:10px;
-            }
-
-            &.active {
-                &:before {
-                    width      : 1em;
-                    height     : 1em;
-                    line-height: 1em;
-                    display    : inline-block;
-                    font-family: $font-family-icons;
-                    content    : "\f14a";
-                    color      : $color-bot;
-                    margin-right:10px;
-                }
-            }
-        }
-
-        .gltf-input {
-            background-color: $background-lighter;
-            border          : none;
-            outline         : none;
-            font-family     : $font;
-            color           : darken($color, 10%);
-            padding         : 5px;
-            margin          : 0px 6px 0px 0;
-
-            &:hover {
-                background-color:$background-lighter2;
-            }
-        }
-
-        .gltf-button {
-            background-color: $background-lighter;
-            border          : none;
-            outline         : none;
-            font-family     : $font;
-            color           : $color;
-            padding         : 5px 10px;
-            margin          : 0px 6px 0px 0;
-
-            &:hover {
-                background-color:$background-lighter2;
-            }
-
-            &:active {
-                background-color:$background-lighter3;
-            }
-        }
-    }
-}

+ 0 - 53
inspector/sass/tabs/_shaderTab.scss

@@ -1,53 +0,0 @@
-.tab-panel {
-
-    .shader-tree-panel {
-        height                  : 30px;
-        
-        // The combo box listing all shaders
-        select {
-            height              : 30px;
-            background-color    : transparent;
-            color               : #ccc;
-            height              : 30px;
-            width               : 100%;
-            max-width           : 300px;
-            padding-left        : 15px;
-            border              : 1px solid $background-lighter;
-            outline             : 1px solid $background-lighter3;
-            option {
-                padding         : 5px;
-                color           : darken($color: $color, $amount: 30%)
-            }
-        }
-        
-    }
-
-    .shader-panel {
-        min-height              : 100px;
-        user-select             : text;
-        box-sizing              : border-box;
-        padding                 : 0 15px;
-        
-        // Shader code style - the syntax highlightinh is done by highlight.js, loaded dynamically
-        pre {
-            margin              : 0;
-            white-space         : pre-wrap;
-            code {
-                // to cancel the background color from zenburn theme of highlight js
-                background-color: $background !important;
-                padding         : 0;
-                margin          : 0;                    
-            }            
-        }
-        
-        .shader-panel-title {
-            height              : 25px;
-            border-bottom       : 1px solid $background-lighter2;
-            text-transform      : uppercase;
-            line-height         : 25px;
-            margin-bottom       : 10px;
-        }
-        
-        
-    }
-}

+ 0 - 52
inspector/sass/tabs/_statsTab.scss

@@ -1,52 +0,0 @@
-.tab-panel {
-
-    &.stats-panel {
-        overflow-y      : auto;
-    }
-    
-    .stats-fps {
-        font-weight:600;
-        color:$color-top;
-    }
-
-    .stat-title1 {        
-        font-size       : 1.1em;
-        padding         : 10px;
-    }
-
-    .stat-title2 {
-        margin          : 10px 0 10px 0;
-        font-size       : 1.05em; 
-        border-bottom   : 1px solid $color-bot;
-        box-sizing      : border-box;
-    }
-
-    .stat-label {
-        display         : inline-block;
-        width           : 80%;
-        padding         : 2px;
-        background-color: $background-lighter;
-        border-bottom   : 1px solid $background;
-        border-top      : 1px solid $background;
-        height          : 30px;
-        line-height     : 30px;
-        box-sizing      : border-box;
-        
-    }
-    .stat-value {
-        display         : inline-block;
-        width           : 20%;
-        padding         : 2px;
-        background-color: $background-lighter;
-        border-top      : 1px solid $background;
-        border-bottom   : 1px solid $background;
-        height          : 30px;
-        line-height     : 30px;
-        box-sizing      : border-box;
-    }
-
-    .stat-infos {
-        width           : 100%;
-        padding         : 4px;
-    }
-}

+ 0 - 80
inspector/sass/tabs/_toolsTab.scss

@@ -1,80 +0,0 @@
-.tab-panel {
-
-    &.tools-panel {
-        overflow-y      : auto;
-    }
-
-    .tool-title1 {        
-        font-size       : 1.1em;
-        padding         : 10px;
-    }
-
-    .tool-title2 {
-        margin          : 10px 0 10px 0;
-        font-size       : 1.05em; 
-        border-bottom   : 1px solid $color-bot;
-        box-sizing      : border-box;
-    }
-
-    .tool-label {
-        background-color: $background-lighter;
-        border          : none;
-        outline         : none;
-        font-family     : $font;
-        color           : darken($color, 10%);
-        padding         : 5px;
-        margin          : 0px 6px 0px 0;
-    }
-
-    .tool-label-line {
-        @extend .tool-label;
-        width           : 100%;
-    }
-
-    .tool-label-error {
-        @extend .tool-label;
-        color           : $color-error;
-        width           : 100%;
-        background-color: none;
-    }
-
-    .tool-value {
-        display         : inline-block;
-        width           : 25%;
-        padding         : 2px;
-        background-color: $background-lighter;
-        border-top      : 1px solid $background;
-        border-bottom   : 1px solid $background;
-        height          : 30px;
-        line-height     : 30px;
-        box-sizing      : border-box;
-    }
-
-    .tool-infos {
-        width           : 100%;
-        padding         : 4px;
-    }
-
-    .tool-input {
-        background-color: $background-lighter;
-        border          : none;
-        outline         : none;
-        font-family     : $font;
-        color           : $color;
-        padding         : 5px 10px;
-        margin          : 0px 6px 0px 0;
-        width           : 100%;
-        border-top      : 1px solid $background;
-        border-bottom   : 1px solid $background;
-        text-align: left;
-
-        &:hover {
-            background-color:$background-lighter2;
-            cursor: pointer;
-        }
-
-        &:active {
-            background-color:$background-lighter3;
-        }
-    }
-}

BIN
inspector/screens/tab_mesh.jpg


BIN
inspector/screens/tools.jpg


+ 0 - 441
inspector/src/Inspector.ts

@@ -1,441 +0,0 @@
-import { AbstractMesh, Nullable, Scene, Tools, Observable } from "babylonjs";
-import "../sass/main.scss";
-import { Helpers } from "./helpers/Helpers";
-import { loadGUIProperties } from "./properties_gui";
-import { Scheduler } from "./scheduler/Scheduler";
-import { TabBar } from "./tabs/TabBar";
-
-import * as Split from "Split";
-
-export class Inspector {
-
-    private _c2diwrapper: HTMLElement;
-    // private _detailsPanel: DetailPanel;
-    /** The panel displayed at the top of the inspector */
-    private _topPanel: HTMLElement;
-    /** The div containing the content of the active tab */
-    private _tabPanel: HTMLElement;
-    /** The panel containing the list if items */
-    // private _treePanel   : HTMLElement;
-    private _tabbar: TabBar;
-    private _scene: Scene;
-    /** The HTML document relative to this inspector (the window or the popup depending on its mode) */
-    public static DOCUMENT: HTMLDocument;
-    /** The HTML window. In popup mode, it's the popup itself. Otherwise, it's the current tab */
-    public static WINDOW: Window;
-    /** True if the inspector is built as a popup tab */
-    private _popupMode: boolean = false;
-    /** The original canvas style, before applying the inspector*/
-    private _canvasStyle: any;
-
-    private _initialTab: number | string;
-
-    private _parentElement: Nullable<HTMLElement>;
-
-    public onGUILoaded: Observable<any>;
-
-    public static GUIObject: any; // should be typeof "babylonjs-gui";
-
-    /** The inspector is created with the given engine.
-     * If the parameter 'popup' is false, the inspector is created as a right panel on the main window.
-     * If the parameter 'popup' is true, the inspector is created in another popup.
-     */
-    constructor(scene: Scene, popup?: boolean, initialTab: number | string = 0, parentElement: Nullable<HTMLElement> = null, newColors?: {
-        backgroundColor?: string,
-        backgroundColorLighter?: string,
-        backgroundColorLighter2?: string,
-        backgroundColorLighter3?: string,
-        color?: string,
-        colorTop?: string,
-        colorBot?: string
-    }) {
-
-        this.onGUILoaded = new Observable();
-
-        import("babylonjs-gui").then((GUI) => {
-            // Load GUI library if not already done
-            if (!GUI || (typeof GUI !== "undefined" && Object.keys(GUI).indexOf("default") !== -1)) {
-                Tools.LoadScript("https://preview.babylonjs.com/gui/babylon.gui.min.js", () => {
-                    Inspector.GUIObject = (<any>BABYLON).GUI;
-                    this.onGUILoaded.notifyObservers(Inspector.GUIObject);
-                    //Load properties of GUI objects now as GUI has to be declared before
-                    loadGUIProperties(Inspector.GUIObject);
-                }, () => {
-                    console.warn('Error : loading "babylon.gui.min.js". Please add script https://preview.babylonjs.com/gui/babylon.min.gui.js to the HTML file.');
-                });
-            }
-            else {
-                Inspector.GUIObject = GUI;
-                this.onGUILoaded.notifyObservers(Inspector.GUIObject);
-                //Load properties of GUI objects now as GUI has to be declared before
-                loadGUIProperties(Inspector.GUIObject);
-            }
-        });
-        //get Tabbar initialTab
-        this._initialTab = initialTab;
-
-        //get parentElement of our Inspector
-        this._parentElement = parentElement;
-
-        // get canvas parent only if needed.
-        this._scene = scene;
-
-        // Save HTML document and window
-        Inspector.DOCUMENT = window.document;
-        Inspector.WINDOW = window;
-
-        // POPUP MODE
-        if (popup) {
-            // Build the inspector in the given parent
-            this.openPopup(true); // set to true in order to NOT dispose the inspector (done in openPopup), as it's not existing yet
-        } else {
-            // Get canvas and its DOM parent
-            let canvas = <HTMLElement>this._scene.getEngine().getRenderingCanvas();
-            let canvasParent = canvas.parentElement;
-
-            // get canvas style
-            let canvasComputedStyle = Inspector.WINDOW.getComputedStyle(canvas);
-
-            this._canvasStyle = {
-                width: Helpers.Css(canvas, 'width'),
-                height: Helpers.Css(canvas, 'height'),
-
-                position: canvasComputedStyle.position,
-                top: canvasComputedStyle.top,
-                bottom: canvasComputedStyle.bottom,
-                left: canvasComputedStyle.left,
-                right: canvasComputedStyle.right,
-
-                padding: canvasComputedStyle.padding,
-                paddingBottom: canvasComputedStyle.paddingBottom,
-                paddingLeft: canvasComputedStyle.paddingLeft,
-                paddingTop: canvasComputedStyle.paddingTop,
-                paddingRight: canvasComputedStyle.paddingRight,
-
-                margin: canvasComputedStyle.margin,
-                marginBottom: canvasComputedStyle.marginBottom,
-                marginLeft: canvasComputedStyle.marginLeft,
-                marginTop: canvasComputedStyle.marginTop,
-                marginRight: canvasComputedStyle.marginRight
-
-            };
-
-            if (this._parentElement) {
-                // Build the inspector wrapper
-                this._c2diwrapper = Helpers.CreateDiv('insp-wrapper', this._parentElement);
-                this._c2diwrapper.style.width = '100%';
-                this._c2diwrapper.style.height = '100%';
-                this._c2diwrapper.style.paddingLeft = '5px';
-
-                // add inspector
-                let inspector = Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
-                inspector.style.width = '100%';
-                inspector.style.height = '100%';
-                // and build it in the popup
-                this._buildInspector(inspector);
-            } else {
-                // Create c2di wrapper
-                this._c2diwrapper = Helpers.CreateDiv('insp-wrapper');
-
-                // copy style from canvas to wrapper
-                for (let prop in this._canvasStyle) {
-                    (<any>this._c2diwrapper.style)[prop] = this._canvasStyle[prop];
-                }
-
-                if (!canvasComputedStyle.width || !canvasComputedStyle.height || !canvasComputedStyle.left) {
-                    return;
-                }
-
-                // Convert wrapper size in % (because getComputedStyle returns px only)
-                let widthPx = parseFloat(canvasComputedStyle.width.substr(0, canvasComputedStyle.width.length - 2)) || 0;
-                let heightPx = parseFloat(canvasComputedStyle.height.substr(0, canvasComputedStyle.height.length - 2)) || 0;
-
-                // If the canvas position is absolute, restrain the wrapper width to the window width + left positionning
-                if (canvasComputedStyle.position === "absolute" || canvasComputedStyle.position === "relative") {
-                    // compute only left as it takes predominance if right is also specified (and it will be for the wrapper)
-                    let leftPx = parseFloat(canvasComputedStyle.left.substr(0, canvasComputedStyle.left.length - 2)) || 0;
-                    if (widthPx + leftPx >= Inspector.WINDOW.innerWidth) {
-                        this._c2diwrapper.style.maxWidth = `${widthPx - leftPx}px`;
-                    }
-                }
-
-                // Check if the parent of the canvas is the body page. If yes, the size ratio is computed
-                let parent = this._getRelativeParent(canvas);
-
-                let parentWidthPx = parent.clientWidth;
-                let parentHeightPx = parent.clientHeight;
-
-                let pWidth = widthPx / parentWidthPx * 100;
-                let pheight = heightPx / parentHeightPx * 100;
-
-                this._c2diwrapper.style.width = pWidth + "%";
-                this._c2diwrapper.style.height = pheight + "%";
-
-                // reset canvas style
-                canvas.style.position = "static";
-                canvas.style.width = "100%";
-                canvas.style.height = "100%";
-                canvas.style.paddingBottom = "0";
-                canvas.style.paddingLeft = "0";
-                canvas.style.paddingTop = "0";
-                canvas.style.paddingRight = "0";
-
-                canvas.style.margin = "0";
-                canvas.style.marginBottom = "0";
-                canvas.style.marginLeft = "0";
-                canvas.style.marginTop = "0";
-                canvas.style.marginRight = "0";
-
-                // Replace canvas with the wrapper...
-                if (canvasParent) {
-                    canvasParent.replaceChild(this._c2diwrapper, canvas);
-                }
-                // ... and add canvas to the wrapper
-                this._c2diwrapper.appendChild(canvas);
-
-                // add inspector
-                let inspector = Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
-
-                // Add split bar
-                if (!this._parentElement) {
-                    Split([canvas, inspector], {
-                        direction: 'horizontal',
-                        sizes: [75, 25],
-                        onDrag: () => {
-                            Helpers.SEND_EVENT('resize');
-                            if (this._tabbar) {
-                                this._tabbar.updateWidth();
-                            }
-                        }
-                    });
-                }
-
-                // Build the inspector
-                this._buildInspector(inspector);
-            }
-            // Send resize event to the window
-            Helpers.SEND_EVENT('resize');
-            this._tabbar.updateWidth();
-        }
-
-        /*
-        * Refresh the inspector if the browser is not edge
-        *   Why not ?! Condition commented on 180525
-        *   To be tested
-        */
-        // if (!Helpers.IsBrowserEdge()) {
-        this.refresh();
-        // }
-
-        // Check custom css colors
-        if (newColors) {
-
-            let bColor = newColors.backgroundColor || '#242424';
-            let bColorl1 = newColors.backgroundColorLighter || '#2c2c2c';
-            let bColorl2 = newColors.backgroundColorLighter2 || '#383838';
-            let bColorl3 = newColors.backgroundColorLighter3 || '#454545';
-
-            let color = newColors.color || '#ccc';
-            let colorTop = newColors.colorTop || '#f29766';
-            let colorBot = newColors.colorBot || '#5db0d7';
-
-            let styles = Inspector.DOCUMENT.querySelectorAll('style');
-            for (let s = 0; s < styles.length; s++) {
-                let style = styles[s];
-
-                if (style.innerHTML.indexOf('insp-wrapper') != -1) {
-
-                    styles[s].innerHTML = styles[s].innerHTML
-                        .replace(/#242424/g, bColor) // background color
-                        .replace(/#2c2c2c/g, bColorl1) // background-lighter
-                        .replace(/#383838/g, bColorl2) // background-lighter2
-                        .replace(/#454545/g, bColorl3) // background-lighter3
-                        .replace(/#ccc/g, color) // color
-                        .replace(/#f29766/g, colorTop) // color-top
-                        .replace(/#5db0d7/g, colorBot); // color-bot
-                }
-            }
-        }
-    }
-
-    /**
-     * If the given element has a position 'asbolute' or 'relative',
-     * returns the first parent of the given element that has a position 'relative' or 'absolute'.
-     * If the given element has no position, returns the first parent
-     *
-     */
-    private _getRelativeParent(elem: HTMLElement, lookForAbsoluteOrRelative?: boolean): HTMLElement {
-        // If the elem has no parent, returns himself
-        if (!elem.parentElement) {
-            return elem;
-        }
-        let computedStyle = Inspector.WINDOW.getComputedStyle(elem);
-        // looking for the first element absolute or relative
-        if (lookForAbsoluteOrRelative) {
-            // if found, return this one
-            if (computedStyle.position === "relative" || computedStyle.position === "absolute") {
-                return elem;
-            } else {
-                // otherwise keep looking
-                return this._getRelativeParent(elem.parentElement, true);
-            }
-        }
-        // looking for the relative parent of the element
-        else {
-            if (computedStyle.position == "static") {
-                return elem.parentElement;
-            } else {
-                // the elem has a position relative or absolute, look for the closest relative/absolute parent
-                return this._getRelativeParent(elem.parentElement, true);
-            }
-        }
-    }
-
-    /** Build the inspector panel in the given HTML element */
-    private _buildInspector(parent: HTMLElement) {
-        // tabbar
-        this._tabbar = new TabBar(this, this._initialTab);
-
-        // Top panel
-        this._topPanel = Helpers.CreateDiv('top-panel', parent);
-        // Add tabbar
-        this._topPanel.appendChild(this._tabbar.toHtml());
-        this._tabbar.updateWidth();
-
-        // Tab panel
-        this._tabPanel = Helpers.CreateDiv('tab-panel-content', this._topPanel);
-
-    }
-
-    public get scene(): Scene {
-        return this._scene;
-    }
-    public get popupMode(): boolean {
-        return this._popupMode;
-    }
-
-    /**
-     * Filter the list of item present in the tree.
-     * All item returned should have the given filter contained in the item id.
-    */
-    public filterItem(filter: string) {
-        let tab = this._tabbar.getActiveTab();
-
-        if (tab) {
-            tab.filter(filter);
-        }
-    }
-
-    /** Display the mesh tab on the given object */
-    public displayObjectDetails(mesh: AbstractMesh) {
-        this._tabbar.switchMeshTab(mesh);
-    }
-
-    /** Clean the whole tree of item and rebuilds it */
-    public refresh() {
-        // Clean top panel
-        Helpers.CleanDiv(this._tabPanel);
-
-        // Get the active tab and its items
-        let activeTab = this._tabbar.getActiveTab();
-
-        if (!activeTab) {
-            return;
-        }
-        activeTab.update();
-        this._tabPanel.appendChild(activeTab.getPanel());
-        Helpers.SEND_EVENT('resize');
-
-    }
-
-    /** Remove the inspector panel when it's built as a right panel:
-     * remove the right panel and remove the wrapper
-     */
-    public dispose() {
-        if (!this._popupMode) {
-            let activeTab = this._tabbar.getActiveTab();
-            if (activeTab) {
-                activeTab.dispose();
-            }
-
-            // Get canvas
-            let canvas = <HTMLElement>this._scene.getEngine().getRenderingCanvas();
-
-            // restore canvas style
-            for (let prop in this._canvasStyle) {
-                (<any>canvas.style)[prop] = this._canvasStyle[prop];
-            }
-            // Get parent of the wrapper
-            if (canvas.parentElement) {
-                let canvasParent = canvas.parentElement.parentElement;
-
-                if (canvasParent) {
-                    canvasParent.insertBefore(canvas, this._c2diwrapper);
-                    // Remove wrapper
-                    Helpers.CleanDiv(this._c2diwrapper);
-                    this._c2diwrapper.remove();
-                    // Send resize event to the window
-                    Helpers.SEND_EVENT('resize');
-                }
-            }
-        }
-        Scheduler.getInstance().dispose();
-    }
-
-    /** Open the inspector in a new popup
-     * Set 'firstTime' to true if there is no inspector created beforehands
-     */
-    public openPopup(firstTime?: boolean) {
-
-        // Create popup
-        let popup = window.open('', 'js INSPECTOR', 'toolbar=no,resizable=yes,menubar=no,width=750,height=1000');
-        if (!popup) {
-            alert("Please update your browser to open the js inspector in an external view.");
-            return;
-        }
-        popup.document.title = "js INSPECTOR";
-        // Get the inspector style
-        let styles = Inspector.DOCUMENT.querySelectorAll('style');
-        for (let s = 0; s < styles.length; s++) {
-            popup.document.body.appendChild(styles[s].cloneNode(true));
-        }
-        let links = document.querySelectorAll('link');
-        for (let l = 0; l < links.length; l++) {
-            let link = popup.document.createElement("link");
-            link.rel = "stylesheet";
-            link.href = (links[l] as HTMLLinkElement).href;
-
-            if (popup.document.head) {
-                popup.document.head.appendChild(link);
-            }
-        }
-        // Dispose the right panel if existing
-        if (!firstTime) {
-            this.dispose();
-        }
-        // set the mode as popup
-        this._popupMode = true;
-        // Save the HTML document
-        Inspector.DOCUMENT = popup.document;
-        Inspector.WINDOW = popup;
-        // Build the inspector wrapper
-        this._c2diwrapper = Helpers.CreateDiv('insp-wrapper', popup.document.body);
-        // add inspector
-        let inspector = Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
-        inspector.classList.add('popupmode');
-        // and build it in the popup
-        this._buildInspector(inspector);
-        // Rebuild it
-        this.refresh();
-
-        popup.addEventListener('resize', () => {
-            if (this._tabbar) {
-                this._tabbar.updateWidth();
-            }
-        });
-    }
-
-    public getActiveTabIndex(): number {
-        return this._tabbar.getActiveTabIndex();
-    }
-}

+ 0 - 43
inspector/src/adapters/Adapter.ts

@@ -1,43 +0,0 @@
-import { Geometry } from "babylonjs";
-import { PropertyLine } from "../details/PropertyLine";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-
-export abstract class Adapter {
-
-    protected _obj: any;
-    // a unique name for this adapter, to retrieve its own key in the local storage
-    private static _name: string = Geometry.RandomId();
-
-    constructor(obj: any) {
-        this._obj = obj;
-    }
-
-    /** Returns the name displayed in the tree */
-    public abstract id(): string;
-
-    /** Returns the type of this object - displayed in the tree */
-    public abstract type(): string;
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public abstract getProperties(): Array<PropertyLine>;
-
-    /** Returns true if the given object correspond to this  */
-    public correspondsTo(obj: any) {
-        return obj === this._obj;
-    }
-
-    /** Returns the adapter unique name */
-    public get name(): string {
-        return Adapter._name;
-    }
-
-    /**
-     * Returns the actual object used for this adapter
-     */
-    public get object(): any {
-        return this._obj;
-    }
-
-    /** Returns the list of tools available for this adapter */
-    public abstract getTools(): Array<AbstractTreeTool>;
-}

+ 0 - 56
inspector/src/adapters/CameraAdapter.ts

@@ -1,56 +0,0 @@
-import { Camera } from "babylonjs";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-import { PropertyLine } from "../details/PropertyLine";
-import { Helpers } from "../helpers/Helpers";
-import { CameraPOV, ICameraPOV } from "../treetools/CameraPOV";
-import { Adapter } from "./Adapter";
-
-export class CameraAdapter
-    extends Adapter
-    implements ICameraPOV {
-
-    constructor(obj: Camera) {
-        super(obj);
-    }
-
-    /** Returns the name displayed in the tree */
-    public id(): string {
-        let str = '';
-        if (this._obj.name) {
-            str = this._obj.name;
-        } // otherwise nothing displayed
-        return str;
-    }
-
-    /** Returns the type of this object - displayed in the tree */
-    public type(): string {
-        return Helpers.GET_TYPE(this._obj);
-    }
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public getProperties(): Array<PropertyLine> {
-        return Helpers.GetAllLinesProperties(this._obj);
-    }
-
-    public getTools(): Array<AbstractTreeTool> {
-        let tools = [];
-        tools.push(new CameraPOV(this));
-        return tools;
-    }
-
-    // Set the point of view of the chosen camera
-    public setPOV() {
-        (this._obj as Camera).getScene().switchActiveCamera(this._obj);
-    }
-
-    // Return the name of the current active camera
-    public getCurrentActiveCamera() {
-        let activeCamera = (this._obj as Camera).getScene().activeCamera;
-        if (activeCamera != null) {
-            return activeCamera.name;
-        } else {
-            return "0";
-        }
-    }
-
-}

+ 0 - 48
inspector/src/adapters/GUIAdapter.ts

@@ -1,48 +0,0 @@
-
-import { PropertyLine } from "../details/PropertyLine";
-import { Helpers } from "../helpers/Helpers";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-import { Checkbox, IToolVisible } from "../treetools/Checkbox";
-import { Adapter } from "./Adapter";
-
-export class GUIAdapter
-    extends Adapter
-    implements IToolVisible {
-
-    constructor(obj: any) {
-        super(obj);
-    }
-
-    /** Returns the name displayed in the tree */
-    public id(): string {
-        let str = '';
-        if (this._obj.name) {
-            str = this._obj.name;
-        } // otherwise nothing displayed
-        return str;
-    }
-
-    /** Returns the type of this object - displayed in the tree */
-    public type(): string {
-        return Helpers.GET_TYPE(this._obj);
-    }
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public getProperties(): Array<PropertyLine> {
-        return Helpers.GetAllLinesProperties(this._obj);
-    }
-
-    public getTools(): Array<AbstractTreeTool> {
-        let tools = [];
-        tools.push(new Checkbox(this));
-        return tools;
-    }
-
-    public setVisible(b: boolean) {
-        (this._obj).isVisible = b;
-    }
-
-    public isVisible(): boolean {
-        return (this._obj).isVisible;
-    }
-}

+ 0 - 51
inspector/src/adapters/LightAdapter.ts

@@ -1,51 +0,0 @@
-import { PropertyLine } from "../details/PropertyLine";
-import { Helpers } from "../helpers/Helpers";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-import { Checkbox, IToolVisible } from "../treetools/Checkbox";
-import { Adapter } from "./Adapter";
-
-export class LightAdapter
-    extends Adapter
-    implements IToolVisible {
-
-    constructor(obj: BABYLON.Light) {
-        super(obj);
-    }
-
-    /** Returns the name displayed in the tree */
-    public id(): string {
-        let str = '';
-        if (this._obj.name) {
-            str = this._obj.name;
-        } // otherwise nothing displayed
-        return str;
-    }
-
-    /** Returns the type of this object - displayed in the tree */
-    public type(): string {
-        return Helpers.GET_TYPE(this._obj);
-    }
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public getProperties(): Array<PropertyLine> {
-        return Helpers.GetAllLinesProperties(this._obj);
-    }
-
-    public getTools(): Array<AbstractTreeTool> {
-        let tools = [];
-        tools.push(new Checkbox(this));
-        return tools;
-    }
-
-    public setVisible(b: boolean) {
-        this._obj.setEnabled(b);
-    }
-    public isVisible(): boolean {
-        return this._obj.isEnabled();
-    }
-
-    /** Returns some information about this mesh */
-    // public getInfo() : string {
-    //     return `${(this._obj as BABYLON.AbstractMesh).getTotalVertices()} vertices`;
-    // }
-}

+ 0 - 37
inspector/src/adapters/MaterialAdapter.ts

@@ -1,37 +0,0 @@
-import { Material } from "babylonjs";
-import { PropertyLine } from "../details/PropertyLine";
-import { Helpers } from "../helpers/Helpers";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-import { Adapter } from "./Adapter";
-
-export class MaterialAdapter
-    extends Adapter {
-
-    constructor(obj: Material) {
-        super(obj);
-    }
-
-    /** Returns the name displayed in the tree */
-    public id(): string {
-        let str = '';
-        if (this._obj.name) {
-            str = this._obj.name;
-        } // otherwise nothing displayed
-        return str;
-    }
-
-    /** Returns the type of this object - displayed in the tree */
-    public type(): string {
-        return Helpers.GET_TYPE(this._obj);
-    }
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public getProperties(): Array<PropertyLine> {
-        return Helpers.GetAllLinesProperties(this._obj);
-    }
-
-    /** No tools for a material adapter */
-    public getTools(): Array<AbstractTreeTool> {
-        return [];
-    }
-}

+ 0 - 116
inspector/src/adapters/MeshAdapter.ts

@@ -1,116 +0,0 @@
-import { AbstractMesh, Debug, Node, Nullable, Observer, Scene, TransformNode, Vector3 } from "babylonjs";
-import { PropertyLine } from "../details/PropertyLine";
-import { Helpers } from "../helpers/Helpers";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-import { BoundingBox, IToolBoundingBox } from "../treetools/BoundingBox";
-import { Checkbox, IToolVisible } from "../treetools/Checkbox";
-import { DebugArea, IToolDebug } from "../treetools/DebugArea";
-import { Info, IToolInfo } from "../treetools/Info";
-import { Adapter } from "./Adapter";
-
-export class MeshAdapter
-    extends Adapter
-    implements IToolVisible, IToolDebug, IToolBoundingBox, IToolInfo {
-
-    /** Keep track of the axis of the actual object */
-    private _axesViewer: Nullable<any>;
-    private onBeforeRenderObserver: Nullable<Observer<Scene>>;
-
-    constructor(mesh: Node) {
-        super(mesh);
-    }
-
-    /** Returns the name displayed in the tree */
-    public id(): string {
-        let str = '';
-        if (this._obj.name) {
-            str = this._obj.name;
-        } // otherwise nothing displayed
-        return str;
-    }
-
-    /** Returns the type of this object - displayed in the tree */
-    public type(): string {
-        return Helpers.GET_TYPE(this._obj);
-    }
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public getProperties(): Array<PropertyLine> {
-        return Helpers.GetAllLinesProperties(this._obj);
-    }
-
-    public getTools(): Array<AbstractTreeTool> {
-        let tools = [];
-        tools.push(new Checkbox(this));
-        tools.push(new DebugArea(this));
-        if (this._obj instanceof AbstractMesh) {
-            if ((this._obj as AbstractMesh).getTotalVertices() > 0) {
-                tools.push(new BoundingBox(this));
-            }
-        }
-
-        tools.push(new Info(this));
-        return tools;
-    }
-
-    public setVisible(b: boolean) {
-        this._obj.setEnabled(b);
-        this._obj.isVisible = b;
-    }
-    public isVisible(): boolean {
-        return this._obj.isEnabled() && (this._obj.isVisible === undefined || this._obj.isVisible);
-    }
-    public isBoxVisible(): boolean {
-        return (this._obj as AbstractMesh).showBoundingBox;
-    }
-    public setBoxVisible(b: boolean) {
-        return (this._obj as AbstractMesh).showBoundingBox = b;
-    }
-
-    public debug(enable: boolean) {
-        // Draw axis the first time
-        if (!this._axesViewer) {
-            this._drawAxis();
-        }
-        // Display or hide axis
-        if (!enable && this._axesViewer) {
-            let mesh = this._obj as AbstractMesh;
-            mesh.getScene().onBeforeRenderObservable.remove(this.onBeforeRenderObserver);
-            this._axesViewer.dispose();
-            this._axesViewer = null;
-        }
-    }
-
-    /** Returns some information about this mesh */
-    public getInfo(): string {
-        if (this._obj instanceof AbstractMesh) {
-            return `${(this._obj as AbstractMesh).getTotalVertices()} vertices`;
-        }
-        return '0 vertices';
-    }
-
-    /** Draw X, Y and Z axis for the actual object if this adapter.
-     * Should be called only one time as it will fill this._axis
-     */
-    private _drawAxis() {
-        this._obj.computeWorldMatrix();
-
-        // Axis
-        var x = new Vector3(1, 0, 0);
-        var y = new Vector3(0, 1, 0);
-        var z = new Vector3(0, 0, 1);
-
-        this._axesViewer = new Debug.AxesViewer(this._obj.getScene());
-
-        let mesh = this._obj as TransformNode;
-        this.onBeforeRenderObserver = mesh.getScene().onBeforeRenderObservable.add(() => {
-            let matrix = mesh.getWorldMatrix();
-            let extend = new Vector3(1, 1, 1);
-            if (mesh instanceof AbstractMesh) {
-                extend = mesh.getBoundingInfo().boundingBox.extendSizeWorld;
-            }
-            this._axesViewer!.scaleLines = Math.max(extend.x, extend.y, extend.z) * 2;
-            this._axesViewer!.update(this._obj.position, Vector3.TransformNormal(x, matrix), Vector3.TransformNormal(y, matrix), Vector3.TransformNormal(z, matrix));
-        });
-    }
-}

+ 0 - 59
inspector/src/adapters/PhysicsImpostorAdapter.ts

@@ -1,59 +0,0 @@
-import { AbstractMesh, PhysicsImpostor } from "babylonjs";
-import { PropertyLine } from "../details/PropertyLine";
-import { Helpers } from "../helpers/Helpers";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-import { Checkbox, IToolVisible } from "../treetools/Checkbox";
-import { Adapter } from "./Adapter";
-
-export class PhysicsImpostorAdapter
-    extends Adapter
-    implements IToolVisible {
-
-    private _viewer: any;
-    private _isVisible = false;
-
-    constructor(obj: PhysicsImpostor, viewer: any) {
-        super(obj);
-        this._viewer = viewer;
-    }
-
-    /** Returns the name displayed in the tree */
-    public id(): string {
-        let str = '';
-        let physicsImposter = (<PhysicsImpostor>this._obj);
-        if (physicsImposter && physicsImposter.object) {
-            str = (<AbstractMesh>physicsImposter.object).name || "";
-        } // otherwise nothing displayed
-        return str;
-    }
-
-    /** Returns the type of this object - displayed in the tree */
-    public type(): string {
-        return Helpers.GET_TYPE(this._obj);
-    }
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public getProperties(): Array<PropertyLine> {
-        return Helpers.GetAllLinesProperties(this._obj);
-    }
-
-    public getTools(): Array<AbstractTreeTool> {
-        let tools = [];
-        tools.push(new Checkbox(this));
-        return tools;
-    }
-
-    public setVisible(b: boolean) {
-        this._isVisible = b;
-        if (b) {
-            this._viewer.showImpostor(this._obj);
-        } else {
-            this._viewer.hideImpostor(this._obj);
-        }
-    }
-
-    public isVisible(): boolean {
-        return this._isVisible;
-    }
-
-}

+ 0 - 52
inspector/src/adapters/SoundAdapter.ts

@@ -1,52 +0,0 @@
-import { Sound } from "babylonjs";
-import { PropertyLine } from "../details/PropertyLine";
-import { Helpers } from "../helpers/Helpers";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-import { ISoundInteractions, SoundInteractions } from "../treetools/SoundInteractions";
-import { Adapter } from "./Adapter";
-
-export class SoundAdapter
-    extends Adapter
-    implements ISoundInteractions {
-
-    constructor(obj: Sound) {
-        super(obj);
-    }
-
-    /** Returns the name displayed in the tree */
-    public id(): string {
-        let str = '';
-        if (this._obj.name) {
-            str = this._obj.name;
-        } // otherwise nothing displayed
-        return str;
-    }
-
-    /** Returns the type of this object - displayed in the tree */
-    public type(): string {
-        return Helpers.GET_TYPE(this._obj);
-    }
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public getProperties(): Array<PropertyLine> {
-        return Helpers.GetAllLinesProperties(this._obj);
-    }
-
-    public getTools(): Array<AbstractTreeTool> {
-        let tools = [];
-        tools.push(new SoundInteractions(this));
-        return tools;
-    }
-
-    public setPlaying(callback: Function) {
-        if ((this._obj as Sound).isPlaying) {
-            (this._obj as Sound).pause();
-        }
-        else {
-            (this._obj as Sound).play();
-        }
-        (this._obj as Sound).onEndedObservable.addOnce(() => {
-            callback();
-        });
-    }
-}

+ 0 - 40
inspector/src/adapters/TextureAdapter.ts

@@ -1,40 +0,0 @@
-import { Adapter } from "./Adapter";
-import { BaseTexture } from "babylonjs";
-import { Helpers } from "../helpers/Helpers";
-import { PropertyLine } from "../details/PropertyLine";
-import { AbstractTreeTool } from "../treetools/AbstractTreeTool";
-
-export class TextureAdapter
-    extends Adapter {
-
-    constructor(obj: BaseTexture) {
-        super(obj);
-    }
-
-    /** Returns the name displayed in the tree */
-    public id(): string {
-        let str = '';
-        if (this._obj.name) {
-            str = this._obj.name;
-        } // otherwise nothing displayed
-        return str;
-    }
-
-    /** Returns the type of this object - displayed in the tree */
-    public type(): string {
-        return Helpers.GET_TYPE(this._obj);
-    }
-
-    /** Returns the list of properties to be displayed for this adapter */
-    public getProperties(): Array<PropertyLine> {
-        // Not used in this tab
-        return [];
-    }
-
-    public getTools(): Array<AbstractTreeTool> {
-        let tools = new Array<AbstractTreeTool>();
-        // tools.push(new CameraPOV(this));
-        return tools;
-    }
-
-}

+ 0 - 9
inspector/src/adapters/index.ts

@@ -1,9 +0,0 @@
-export * from './Adapter';
-export * from './CameraAdapter';
-export * from './GUIAdapter';
-export * from './LightAdapter';
-export * from './MaterialAdapter';
-export * from './MeshAdapter';
-export * from './PhysicsImpostorAdapter';
-export * from './SoundAdapter';
-export * from './TextureAdapter';

+ 753 - 0
inspector/src/components/actionTabs/actionTabs.scss

@@ -0,0 +1,753 @@
+#inspector-host {
+    position: absolute;
+    right: 0px;
+    top:0px;
+    bottom: 0px;
+}
+
+#actionTabs {
+    background: #333333;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    display: grid;
+    grid-template-rows: auto 1fr;
+    font: 14px "Arial";    
+    overflow: hidden;
+
+    #header {
+        height: 30px;
+        font-size: 16px;
+        color: white;
+        background: #222222;
+        grid-row: 1;
+        text-align: center;
+        display: grid;
+        grid-template-columns: 30px 1fr 50px;        
+        -webkit-user-select: none; 
+        -moz-user-select: none;   
+        -ms-user-select: none;    
+        user-select: none;                
+
+        #logo {
+            grid-column: 1; 
+            width: 24px;
+            height: 24px;
+            display: flex;
+            align-self: center;   
+            justify-self: center;
+        }        
+
+        #back {
+            grid-column: 1; 
+            display: grid;
+            align-self: center;   
+            justify-self: center;
+            cursor: pointer;
+        }              
+
+        #title {
+            grid-column: 2; 
+            display: grid;
+            align-items: center;   
+            text-align: center;
+        }
+
+        #commands {
+            grid-column: 3; 
+            display: grid;
+            align-items: center;  
+            grid-template-columns: 1fr 1fr;   
+            
+            .expand {
+                grid-column: 1;
+                display: grid;
+                align-items: center;   
+                justify-items: center;
+                cursor: pointer;     
+            }
+
+            .close {
+                grid-column: 2;
+                display: grid;
+                align-items: center;   
+                justify-items: center;
+                cursor: pointer;     
+            }        
+        }
+    }
+
+    .tabs {
+        display: grid;
+        grid-row: 2;
+        grid-template-rows: 40px 1fr;
+        font: 14px "Arial";
+        overflow: hidden;
+
+        .labels {
+            grid-row: 1;
+            display: flex;
+            align-items: center;
+            justify-items: center;
+            border-bottom: 1px solid #ffffff; 
+            margin: 0;
+            padding: 0;         
+
+            .label {
+                font-size: 24px;
+                color: white;
+                width: 40px;
+                display: flex;
+                align-content: center;
+                justify-content: center;
+                border: 1px solid transparent;            
+                border-bottom: none;    
+                background: #333333;
+                padding: 5px;  
+                height: 28px;
+                cursor: pointer;
+
+                &.active {
+                    border-color: #ffffff;  
+                    border-bottom: 2px solid transparent;           
+                    margin-bottom: -2px;
+                }
+            }
+        }
+
+        .panes {
+            grid-row: 2;
+
+            display: grid;
+            grid-template-rows: 1fr;
+
+            overflow: hidden;
+
+            .infoMessage {
+                opacity: 0.5;
+                color: white;
+                margin: 15px 5px 0px 5px;
+                                
+            }
+
+            .pane {
+                color: white;
+
+                overflow-x: hidden;
+                overflow-y: auto;
+
+                -webkit-user-select: none; 
+                -moz-user-select: none;   
+                -ms-user-select: none;    
+                user-select: none;     
+                
+                .textureLinkLine {
+                    display: grid;
+                    grid-template-columns: auto 1fr;
+
+                    .debug {
+                        grid-column: 1;
+                        margin-left: 5px;
+                        display: grid;
+                        align-items: center; 
+                        justify-items: center;                          
+                        cursor: pointer;
+                        opacity: 0.5;
+
+                        &.selected {
+                            opacity: 1.0;
+                        }
+                    }
+
+                    .textLine {
+                        grid-column: 2;
+                    }
+                }
+
+                .messageLine {
+                    text-align: center;
+                    font-size: 12px;
+                    font-style: italic;
+                    opacity: 0.6;
+                }
+
+                .textLine {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 1fr auto;
+
+                    .label {
+                        grid-column: 1;
+                        display: flex;
+                        align-items: center;
+                    }
+
+                    .link-value {
+                        grid-column: 2;
+                        white-space: nowrap;
+                        text-overflow: ellipsis;
+                        overflow: hidden;
+                        text-align: end;
+                        opacity: 0.8;
+                        margin:5px;
+                        margin-top: 6px;
+                        max-width: 200px;
+                        text-decoration: underline;
+                        cursor: pointer;
+                    }
+
+                    .value {
+                        grid-column: 2;
+                        white-space: nowrap;
+                        text-overflow: ellipsis;
+                        overflow: hidden;
+                        text-align: end;
+                        opacity: 0.8;
+                        margin:5px;
+                        margin-top: 6px;
+                        max-width: 200px;
+
+                        &.check {
+                            color: green;
+                        }
+
+                        &.uncheck {
+                            color: red;
+                        }  
+                    }
+                }
+
+                .textInputLine {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 1fr 120px;
+
+                    .label {
+                        grid-column: 1;
+                        display: flex;
+                        align-items: center;
+                    }
+
+                    .value {                        
+                        display: flex;
+                        align-items: center;
+                        grid-column: 2;
+                        
+                        input {
+                            width: 110px;
+                        }
+                    }
+                }
+
+                .buttonLine {
+                    height: 30px;
+                    display: grid;
+                    align-items: center;
+                    justify-items: stretch;
+
+                    input[type="file"] {
+                        display: none;
+                    }
+
+                    .file-upload {
+                        background: transparent;
+                        border: 1px solid rgb(51, 122, 183);
+                        margin: 0px 10px;
+                        color:white;
+                        padding: 4px 5px;
+                        opacity: 0.9;
+                        cursor: pointer;
+                        text-align: center;
+                    }
+
+                    .file-upload:hover {
+                        opacity: 1.0;
+                    }
+
+                    .file-upload:active {
+                        transform: scale(0.98);
+                        transform-origin: 0.5 0.5;
+                    }
+
+                    button {
+                        background: #222222;
+                        border: 0px;
+                        color:white;
+                        padding: 4px 5px;
+                        opacity: 0.9;
+                        width: 100%;
+                        height: 28px;
+                    }
+
+                    button:hover {
+                        opacity: 1.0;
+                    }
+
+                    button:active {
+                        background: #282828;
+                    }   
+                    
+                    button:focus {
+                        border: 0px;
+                        outline: 0px;
+                    }  
+                }
+
+                .radioLine {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 1fr 30px;
+
+                    .label {
+                        grid-column: 1;
+                        display: flex;
+                        align-items: center;
+                    }
+
+                    .radioContainer {
+                        display: flex;
+                        align-items: center;
+
+                        .radio {
+                            grid-column: 2;                        
+                            display: none;
+
+                            &:checked + label:before {
+                                border-color: rgb(51, 122, 183);
+                            }
+                            &:checked + label:after {
+                                transform: scale(1);
+                            }                        
+                        }
+
+                        .labelForRadio {
+                            display: inline-block;
+                            height: 14px;
+                            position: relative;
+                            padding: 0 24px;
+                            margin-bottom: 0;
+                            cursor: pointer;
+                            vertical-align: bottom;
+                            &:before, &:after {
+                                position: absolute;            
+                                content: '';  
+                                border-radius: 50%;
+                                transition: all .3s ease;
+                                transition-property: transform, border-color;
+                            }
+                            &:before {
+                                left: 0px;
+                                top: 0;
+                                width: 16px;
+                                height: 16px;
+                                border: 2px solid white;
+                            }
+                            &:after {
+                                top: 6px;
+                                left: 6px;
+                                width: 8px;
+                                height: 8px;
+                                transform: scale(0);
+                                background:rgb(51, 122, 183);
+                            }
+                        }
+                    }
+                }
+
+                .vector3Line {
+                    padding-left: 5px;                    
+                    display: grid;
+
+                    .firstLine {
+                        display: grid;
+                        grid-template-columns: 1fr auto 20px;
+                        height: 30px;
+
+                        .label {
+                            grid-column: 1;
+                            display: flex;
+                            align-items: center;
+                        }
+
+                        .vector {
+                            grid-column: 2;
+                            display: flex;
+                            align-items: center;
+                            text-align: right;
+                            opacity: 0.8;
+                        }
+
+                        .expand {
+                            grid-column: 3;
+                            display: grid;
+                            align-items: center;
+                            justify-items: center;
+                            cursor: pointer;
+                        }
+                    }
+
+                    .secondLine {
+                        display: grid;
+                        padding-right: 5px;  
+                        border-left: 1px solid rgb(51, 122, 183);
+
+                        .numeric {
+                            display: grid;
+                            grid-template-columns: 1fr auto;
+                        }
+
+                        .numeric-label {
+                            text-align: right;
+                            grid-column: 1;
+                            display: flex;
+                            align-items: center;                            
+                            justify-self: right;
+                            margin-right: 10px;                          
+                        }
+
+                        .numeric-value {
+                            width: 120px;
+                            grid-column: 2;
+                            display: flex;
+                            align-items: center;  
+                            border: 1px solid  rgb(51, 122, 183);
+                        }                        
+                    }
+                }
+
+                .checkBoxLine {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 1fr auto;
+
+
+                    .label {
+                        grid-column: 1;
+                        display: flex;
+                        align-items: center;
+                    }
+
+                    .checkBox {
+                        grid-column: 2;
+                        
+                        display: flex;
+                        align-items: center;
+
+                        .lbl {
+                            position: relative;
+                            display: block;
+                            height: 14px;
+                            width: 34px;
+                            margin-right: 5px;
+                            background: #898989;
+                            border-radius: 100px;
+                            cursor: pointer;
+                            transition: all 0.3s ease;
+                        }
+
+                        .lbl:after {
+                            position: absolute;
+                            left: 3px;
+                            top: 2px;
+                            display: block;
+                            width: 10px;
+                            height: 10px;
+                            border-radius: 100px;
+                            background: #fff;
+                            box-shadow: 0px 3px 3px rgba(0,0,0,0.05);
+                            content: '';
+                            transition: all 0.15s ease;
+                        }
+
+                        .lbl:active:after { 
+                            transform: scale(1.15, 0.85); 
+                        }
+
+                        .cbx:checked ~ label { 
+                            background: rgb(51, 122, 183);
+                        }
+
+                        .cbx:checked ~ label:after {
+                            left: 20px;
+                            background: rgb(22, 73, 117);
+                        }
+
+                        .hidden { 
+                            display: none; 
+                        }               
+                    }                    
+                }                   
+
+                .textureLine {                   
+                    display: grid;
+                    grid-template-rows: 30px auto;
+
+                    .control {
+                        margin-top: 2px;
+                        grid-row: 1;
+                        display: grid;
+                        grid-template-columns: 1fr 40px 40px 40px 40px 40px 1fr;
+
+                        .red {
+                            grid-column: 2;
+                        }
+
+                        .green {
+                            grid-column: 3;
+                        }
+
+                        .blue {
+                            grid-column: 4;
+                        }
+
+                        .alpha {
+                            grid-column: 5;
+                        }                        
+
+                        .all {
+                            grid-column: 6;
+                        }                        
+                    }
+
+                    .control3D {
+                        margin-top: 2px;
+                        grid-row: 1;
+                        display: grid;
+                        grid-template-columns: 1fr 40px 40px 40px 40px 40px 40px 1fr;
+
+                        .px {
+                            grid-column: 2;
+                        }
+
+                        .nx {
+                            grid-column: 3;
+                        }
+
+                        .py {
+                            grid-column: 4;
+                        }
+
+                        .ny {
+                            grid-column: 5;
+                        }   
+
+                        .pz {
+                            grid-column: 6;
+                        }
+
+                        .nz {
+                            grid-column: 7;
+                        }                     
+                    }                    
+
+                    .command {
+                        border: 0px;
+                        background:transparent;
+                        color: white;
+                    }
+
+                    .selected {
+                        border: 1px solid rgb(51, 122, 183);
+                    }
+
+                    .preview {
+                        grid-row: 2;
+                        display: grid;
+                        align-self: center;
+                        justify-self: center;
+                        height: 256px;
+                        width: 256px;
+                        margin-top: 5px;
+                        margin-bottom: 5px;
+                    }
+                }
+
+                .gltf-extension-property {
+                    margin-left: 30px;
+                    border-left: 1px solid rgb(51, 122, 183);
+                }
+
+                .floatLine {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 1fr 120px;
+
+
+                    .label {
+                        grid-column: 1;
+                        display: flex;
+                        align-items: center;
+                    }
+
+                    .value {
+                        grid-column: 2;
+                        
+                        display: flex;
+                        align-items: center;
+                        
+                        input {
+                            width: 110px;
+                        }
+                    }
+                }
+
+                .sliderLine {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 1fr auto;
+
+                    .label {
+                        grid-column: 1;
+                        display: flex;
+                        align-items: center;
+                    }
+
+                    .slider {
+                        grid-column: 2;
+                        margin-right: 5px;
+                        
+                        display: flex;
+                        align-items: center;
+
+                        .range {
+                            -webkit-appearance: none;
+                            width: 120px;
+                            height: 6px;
+                            background: #d3d3d3;
+                            border-radius: 5px;
+                            outline: none;
+                            opacity: 0.7;
+                            -webkit-transition: .2s;
+                            transition: opacity .2s;
+                        }
+                        
+                        .range:hover {
+                            opacity: 1;
+                        }
+                        
+                        .range::-webkit-slider-thumb {
+                            -webkit-appearance: none;
+                            appearance: none;
+                            width: 14px;
+                            height: 14px;
+                            border-radius: 50%;
+                            background: rgb(51, 122, 183);
+                            cursor: pointer;
+                        }
+                        
+                        .range::-moz-range-thumb {
+                            width: 14px;
+                            height: 14px;
+                            border-radius: 50%;
+                            background: rgb(51, 122, 183);
+                            cursor: pointer;
+                        }
+                    }                    
+                }       
+                
+                .color3Line {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 1fr auto;
+
+
+                    .label {
+                        grid-column: 1;
+                        display: flex;
+                        align-items: center;
+                    }
+
+                    .color3 {
+                        grid-column: 2;
+                        
+                        display: flex;
+                        align-items: center;   
+
+                        input[type="color"] {
+                            -webkit-appearance: none;
+                            border: none;
+                            padding: 0;
+                            width: 20px;
+                            height: 20px;
+                        }
+                        input[type="color"]::-webkit-color-swatch-wrapper {
+                            padding: 0;
+                        }
+                        input[type="color"]::-webkit-color-swatch {
+                            border: none;
+                        }
+                        
+                        input {
+                            margin-right: 5px;
+                        }
+                    }                    
+                }     
+                
+                .listLine {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 1fr auto;
+
+
+                    .label {
+                        grid-column: 1;
+                        display: flex;
+                        align-items: center;
+                    }
+
+                    .options {
+                        grid-column: 2;
+                        
+                        display: flex;
+                        align-items: center;   
+                        margin-right: 5px;
+                    }                    
+                }                   
+
+                .paneContainer {
+                    margin-top: 3px;
+                    
+                    .header {
+                        display: grid;
+                        grid-template-columns: 1fr auto;
+                        background: #555555;    
+                        height: 30px;   
+                        padding-right: 5px;                        
+                        cursor: pointer;
+                        
+                        .title {
+                            margin-left: 5px;
+                            grid-column: 1;
+                            display: flex;
+                            align-items: center;
+                        }
+
+                        .collapse {
+                            grid-column: 2;
+                            display: flex;
+                            align-items: center;  
+                            justify-items: center;
+                            transform-origin: center;
+
+                            &.closed {
+                                transform: rotate(180deg);
+                            }
+                        }                        
+                    }
+
+                    .paneList > div:not(:last-child) {
+                        border-bottom: 0.5px solid rgba(255, 255, 255, 0.1);
+                    }
+                }
+            }
+        }
+    }
+}

+ 133 - 0
inspector/src/components/actionTabs/actionTabsComponent.tsx

@@ -0,0 +1,133 @@
+import * as React from "react";
+import { Observer, Scene, Nullable } from "babylonjs";
+import { TabsComponent } from "./tabsComponent";
+import { faFileAlt, faWrench, faBug, faChartBar } from '@fortawesome/free-solid-svg-icons';
+import { StatisticsTabComponent } from "./tabs/statisticsTabComponent";
+import { DebugTabComponent } from "./tabs/debugTabComponent";
+import Resizable from "re-resizable";
+import { PropertyGridTabComponent } from "./tabs/propertyGridTabComponent";
+import { HeaderComponent } from "../headerComponent";
+import { ToolsTabComponent } from "./tabs/toolsTabComponent";
+import { GlobalState } from "components/globalState";
+
+require("./actionTabs.scss");
+
+interface IActionTabsComponentProps {
+    scene: Scene,
+    noCommands?: boolean,
+    noHeader?: boolean,
+    noExpand?: boolean,
+    popupMode?: boolean,
+    onPopup?: () => void,
+    onClose?: () => void,
+    globalState: GlobalState
+}
+
+export class ActionTabsComponent extends React.Component<IActionTabsComponentProps, { selectedEntity: any, selectedIndex: number }> {
+    private _onSelectionChangeObserver: Nullable<Observer<any>>;
+    private _onTabChangedObserver: Nullable<Observer<any>>;
+    private _once = true;
+
+    constructor(props: IActionTabsComponentProps) {
+        super(props);
+
+        let initialIndex = 0;
+
+        const validationResutls = this.props.globalState.validationResults;
+        if (validationResutls) {
+            if (validationResutls.issues.numErrors || validationResutls.issues.numWarnings) {
+                initialIndex = 3;
+            }
+        }
+
+        this.state = { selectedEntity: null, selectedIndex: initialIndex }
+    }
+
+    componentWillMount() {
+        this._onSelectionChangeObserver = this.props.globalState.onSelectionChangedObservable.add((entity) => {
+            this.setState({ selectedEntity: entity, selectedIndex: 0 });
+        });
+
+        this._onTabChangedObserver = this.props.globalState.onTabChangedObservable.add(index => {
+            this.setState({ selectedIndex: index });
+        });
+    }
+
+    componentWillUnmount() {
+        if (this._onSelectionChangeObserver) {
+            this.props.globalState.onSelectionChangedObservable.remove(this._onSelectionChangeObserver);
+        }
+
+        if (this._onTabChangedObserver) {
+            this.props.globalState.onTabChangedObservable.remove(this._onTabChangedObserver);
+        }
+    }
+
+    changeSelectedTab(index: number) {
+        this.props.globalState.onTabChangedObservable.notifyObservers(index);
+    }
+
+    renderContent() {
+        return (
+            <TabsComponent selectedIndex={this.state.selectedIndex} onSelectedIndexChange={(value) => this.changeSelectedTab(value)}>
+                <PropertyGridTabComponent
+                    title="Properties" icon={faFileAlt} scene={this.props.scene} selectedEntity={this.state.selectedEntity}
+                    onSelectionChangedObservable={this.props.globalState.onSelectionChangedObservable}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />
+                <DebugTabComponent title="Debug" icon={faBug} scene={this.props.scene} />
+                <StatisticsTabComponent title="Statistics" icon={faChartBar} scene={this.props.scene} />
+                <ToolsTabComponent title="Tools" icon={faWrench} scene={this.props.scene} globalState={this.props.globalState} />
+            </TabsComponent>
+        )
+    }
+
+    onClose() {
+        if (!this.props.onClose) {
+            return;
+        }
+        this.props.onClose();
+    }
+
+    onPopup() {
+        if (!this.props.onPopup) {
+            return;
+        }
+        this.props.onPopup();
+    }
+
+    render() {
+        if (this.props.popupMode) {
+            return (
+                <div id="actionTabs">
+                    {
+                        !this.props.noHeader &&
+                        <HeaderComponent title="INSPECTOR" handleBack={true} noCommands={this.props.noCommands} onClose={() => this.onClose()} onPopup={() => this.onPopup()} onSelectionChangedObservable={this.props.globalState.onSelectionChangedObservable} />
+                    }
+                    {this.renderContent()}
+                </div>
+            );
+        }
+
+        if (this._once) {
+            this._once = false;
+            // A bit hacky but no other way to force the initial width to 300px and not auto
+            setTimeout(() => {
+                const element = document.getElementById("actionTabs");
+                if (!element) {
+                    return;
+                }
+                element.style.width = "300px";
+            }, 150);
+        }
+
+        return (
+            <Resizable id="actionTabs" minWidth={300} maxWidth={600} size={{ height: "100%" }} minHeight="100%" enable={{ top: false, right: false, bottom: false, left: true, topRight: false, bottomRight: false, bottomLeft: false, topLeft: false }}>
+                {
+                    !this.props.noHeader &&
+                    <HeaderComponent title="INSPECTOR" handleBack={true} noExpand={this.props.noExpand} noCommands={this.props.noCommands} onClose={() => this.onClose()} onPopup={() => this.onPopup()} onSelectionChangedObservable={this.props.globalState.onSelectionChangedObservable} />
+                }
+                {this.renderContent()}
+            </Resizable>
+        );
+    }
+}

+ 59 - 0
inspector/src/components/actionTabs/lineContainerComponent.tsx

@@ -0,0 +1,59 @@
+import * as React from "react";
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
+
+interface ILineContainerComponentProps {
+    title: string,
+    children: any[] | any,
+    closed?: boolean
+}
+
+export class LineContainerComponent extends React.Component<ILineContainerComponentProps, { isExpanded: boolean }> {
+    constructor(props: ILineContainerComponentProps) {
+        super(props);
+
+        this.state = { isExpanded: !this.props.closed };
+    }
+
+    switchExpandedState(): void {
+        this.setState({ isExpanded: !this.state.isExpanded });
+    }
+
+    renderHeader() {
+        const className = this.state.isExpanded ? "collapse" : "collapse closed";
+
+        return (
+            <div className="header" onClick={() => this.switchExpandedState()}>
+                <div className="title">
+                    {this.props.title}
+                </div>
+                <div className={className}>
+                    <FontAwesomeIcon icon={faChevronDown} />
+                </div>
+            </div>
+        )
+    }
+
+    render() {
+        if (!this.state.isExpanded) {
+            return (
+                <div className="paneContainer">
+                    {
+                        this.renderHeader()
+                    }
+                </div>
+            )
+        }
+
+        return (
+            <div className="paneContainer">
+                {
+                    this.renderHeader()
+                }
+                <div className="paneList">
+                    {this.props.children}
+                </div >
+            </div>
+        );
+    }
+}

+ 31 - 0
inspector/src/components/actionTabs/lines/booleanLineComponent.tsx

@@ -0,0 +1,31 @@
+import * as React from "react";
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faCheck, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
+
+export interface IBooleanLineComponentProps {
+    label: string,
+    value: boolean
+}
+
+export class BooleanLineComponent extends React.Component<IBooleanLineComponentProps> {
+    constructor(props: IBooleanLineComponentProps) {
+        super(props);
+    }
+
+    render() {
+
+        const check = this.props.value ? <FontAwesomeIcon icon={faCheck} /> : <FontAwesomeIcon icon={faTimesCircle} />
+        const className = this.props.value ? "value check" : "value uncheck";
+
+        return (
+            <div className="textLine">
+                <div className="label">
+                    {this.props.label}
+                </div>
+                <div className={className}>
+                    {check}
+                </div>
+            </div>
+        );
+    }
+}

+ 0 - 0
inspector/src/components/actionTabs/lines/buttonLineComponent.tsx


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä