فهرست منبع

merge with master

Benjamin Guignabert 8 سال پیش
والد
کامیت
80b485efcf
99فایلهای تغییر یافته به همراه23846 افزوده شده و 22143 حذف شده
  1. 1 0
      .gitignore
  2. 12 0
      .vscode/launch.json
  3. BIN
      Exporters/Blender/Blender2Babylon-5.2.zip
  4. 2 2
      Exporters/Blender/src/babylon-js/__init__.py
  5. 4 1
      Exporters/Blender/src/babylon-js/json_exporter.py
  6. 5 2
      Exporters/Blender/src/babylon-js/world.py
  7. 0 1109
      Playground/bootstrap/css/bootstrap-responsive.css
  8. 0 9
      Playground/bootstrap/css/bootstrap-responsive.min.css
  9. 0 6167
      Playground/bootstrap/css/bootstrap.css
  10. 0 9
      Playground/bootstrap/css/bootstrap.min.css
  11. BIN
      Playground/bootstrap/img/glyphicons-halflings-white.png
  12. BIN
      Playground/bootstrap/img/glyphicons-halflings.png
  13. 0 2280
      Playground/bootstrap/js/bootstrap.js
  14. 0 6
      Playground/bootstrap/js/bootstrap.min.js
  15. 459 0
      Playground/css/index.css
  16. 135 104
      Playground/debug.html
  17. 38 37
      Playground/frame.html
  18. 0 1
      Playground/hand.minified-1.2.js
  19. 102 70
      Playground/index-local.html
  20. 0 188
      Playground/index.css
  21. 131 110
      Playground/index.html
  22. 137 113
      Playground/index2_5.html
  23. 63 0
      Playground/js/actions.js
  24. 123 38
      Playground/index.js
  25. 0 0
      Playground/js/libs/fileSaver.js
  26. 13 13
      Playground/jszip.min.js
  27. 587 0
      Playground/js/libs/split.js
  28. 5 3
      Playground/package.json
  29. 30 30
      Playground/scripts/scripts.txt
  30. 0 146
      Playground/splitbox.css
  31. 0 116
      Playground/splitbox.js
  32. 55 0
      Playground/test.html
  33. 0 2
      Playground/xtag.min.js
  34. 21 8
      Tools/Gulp/config.json
  35. 34 1
      dist/preview release/babylon.core.js
  36. 5607 5604
      dist/preview release/babylon.d.ts
  37. 44 0
      dist/preview release/babylon.js
  38. 66 46
      dist/preview release/babylon.max.js
  39. 5607 5604
      dist/preview release/babylon.module.d.ts
  40. 45 1
      dist/preview release/babylon.noworker.js
  41. 523 0
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  42. 2378 0
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  43. 2 0
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  44. 429 0
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  45. 1665 0
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  46. 1 0
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  47. 918 0
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  48. 3804 0
      dist/preview release/loaders/babylon.glTFFileLoader.js
  49. 6 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  50. 1 4
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  51. 175 98
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  52. 25 6
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  53. 6 4
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  54. 1 0
      loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts
  55. 29 2
      loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts
  56. 26 16
      loaders/src/glTF/README.md
  57. 9 7
      loaders/src/glTF/babylon.glTFFileLoader.ts
  58. 0 72
      localDev/src/index.js
  59. 0 3
      sandbox/index-local.html
  60. 3 3
      sandbox/index.css
  61. 0 3
      sandbox/index.html
  62. 15 50
      sandbox/index.js
  63. 5 1
      src/Debug/babylon.debugLayer.ts
  64. 1 0
      src/Lights/Shadows/babylon.shadowGenerator.ts
  65. 2 2
      src/Loading/babylon.sceneLoader.ts
  66. 25 6
      src/Materials/babylon.material.ts
  67. 2 2
      src/Materials/babylon.pbrMaterial.ts
  68. 6 1
      src/Materials/babylon.standardMaterial.ts
  69. 1 1
      src/Mesh/babylon.abstractMesh.ts
  70. 11 0
      src/Mesh/babylon.geometry.ts
  71. 1 1
      src/Mesh/babylon.subMesh.ts
  72. 0 30
      src/Tools/babylon.extendedGamepad.ts
  73. 0 5
      src/Tools/babylon.filesInput.ts
  74. 9 3
      src/babylon.engine.ts
  75. 7 2
      src/babylon.scene.ts
  76. BIN
      tests/validation/LogoV3.jpg
  77. BIN
      tests/validation/ReferenceImages/Espilit.png
  78. BIN
      tests/validation/ReferenceImages/Flat2009.png
  79. BIN
      tests/validation/ReferenceImages/Heart.png
  80. BIN
      tests/validation/ReferenceImages/Hillvalley.png
  81. BIN
      tests/validation/ReferenceImages/SpaceDeK.png
  82. BIN
      tests/validation/ReferenceImages/Sponza.png
  83. BIN
      tests/validation/ReferenceImages/TheCar.png
  84. BIN
      tests/validation/ReferenceImages/Viper.png
  85. BIN
      tests/validation/ReferenceImages/WCafe.png
  86. BIN
      tests/validation/ReferenceImages/charting.png
  87. BIN
      tests/validation/ReferenceImages/csg.png
  88. BIN
      tests/validation/ReferenceImages/fog.png
  89. BIN
      tests/validation/ReferenceImages/fresnel.png
  90. BIN
      tests/validation/ReferenceImages/lines.png
  91. BIN
      tests/validation/ReferenceImages/mansion.png
  92. BIN
      tests/validation/ReferenceImages/polygon.png
  93. BIN
      tests/validation/ReferenceImages/retail.png
  94. BIN
      tests/validation/ReferenceImages/softShadows.png
  95. 114 0
      tests/validation/config.json
  96. 84 0
      tests/validation/index.css
  97. 14 0
      tests/validation/index.html
  98. BIN
      tests/validation/loading.gif
  99. 222 0
      tests/validation/validation.js

+ 1 - 0
.gitignore

@@ -165,3 +165,4 @@ node_modules
 localDev/src/*
 /dist/preview release/babylon.custom.js
 /dist/preview release/babylon.custom.max.js
+/localDev/src/index.js

+ 12 - 0
.vscode/launch.json

@@ -96,6 +96,18 @@
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
             ]
+        },
+        {
+            "name": "Launch Build Validation (Chrome)",
+            "type": "chrome",
+            "request": "launch",
+            "url": "http://localhost:1338/tests/validation/index.html",
+            "webRoot": "${workspaceRoot}/",
+            "sourceMaps": true,
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis" 
+            ]
         }
     ]
 }

BIN
Exporters/Blender/Blender2Babylon-5.2.zip


+ 2 - 2
Exporters/Blender/src/babylon-js/__init__.py

@@ -1,7 +1,7 @@
 bl_info = {
     'name': 'Babylon.js',
     'author': 'David Catuhe, Jeff Palmer',
-    'version': (5, 2, 0),
+    'version': (5, 2, 1),
     'blender': (2, 76, 0),
     'location': 'File > Export > Babylon.js (.babylon)',
     'description': 'Export Babylon.js scenes (.babylon)',
@@ -11,7 +11,7 @@ bl_info = {
 
 # allow module to be changed during a session (dev purposes)
 if "bpy" in locals():
-    print('Reloading TOB exporter')
+    print('Reloading .babylon exporter')
     import imp
     imp.reload(animation)
     imp.reload(armature)

+ 4 - 1
Exporters/Blender/src/babylon-js/json_exporter.py

@@ -66,6 +66,7 @@ class JsonExporter:
             self.materials = []
             self.multiMaterials = []
             self.sounds = []
+            self.needPhysics = False
 
             # Scene level sound
             if scene.attachedSound != '':
@@ -102,6 +103,8 @@ class JsonExporter:
                             Logger.log(self.fatalError)
                             return
 
+                        if hasattr(mesh, 'physicsImpostor'): self.needPhysics = True
+                        
                         if hasattr(mesh, 'instances'):
                             self.meshesAndNodes.append(mesh)
                         else:
@@ -161,7 +164,7 @@ class JsonExporter:
         file_handler = open(self.filepathMinusExtension + '.babylon', 'w', encoding='utf8')
         file_handler.write('{')
         file_handler.write('"producer":{"name":"Blender","version":"' + bpy.app.version_string + '","exporter_version":"' + format_exporter_version() + '","file":"' + JsonExporter.nameSpace + '.babylon"},\n')
-        self.world.to_scene_file(file_handler)
+        self.world.to_scene_file(file_handler, self.needPhysics)
 
         # Materials
         file_handler.write(',\n"materials":[')

+ 5 - 2
Exporters/Blender/src/babylon-js/world.py

@@ -31,12 +31,15 @@ class World:
 
         Logger.log('Python World class constructor completed')
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-    def to_scene_file(self, file_handler):
+    def to_scene_file(self, file_handler, needPhysics):
         write_bool(file_handler, 'autoClear', self.autoClear, True)
         write_color(file_handler, 'clearColor', self.clear_color)
         write_color(file_handler, 'ambientColor', self.ambient_color)
         write_vector(file_handler, 'gravity', self.gravity)
-
+        
+        if needPhysics:
+            write_bool(file_handler, 'physicsEnabled', True)
+            
         if hasattr(self, 'fogMode'):
             write_int(file_handler, 'fogMode', self.fogMode)
             write_color(file_handler, 'fogColor', self.fogColor)

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1109
Playground/bootstrap/css/bootstrap-responsive.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 9
Playground/bootstrap/css/bootstrap-responsive.min.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 6167
Playground/bootstrap/css/bootstrap.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 9
Playground/bootstrap/css/bootstrap.min.css


BIN
Playground/bootstrap/img/glyphicons-halflings-white.png


BIN
Playground/bootstrap/img/glyphicons-halflings.png


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 2280
Playground/bootstrap/js/bootstrap.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 6
Playground/bootstrap/js/bootstrap.min.js


+ 459 - 0
Playground/css/index.css

@@ -0,0 +1,459 @@
+@import url("https://fonts.googleapis.com/css?family=Montserrat:300,400");
+@import url("https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css");
+html,
+body {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    overflow: hidden;
+    font-family: sans-serif;
+}
+.wrapper {
+    height: calc(100% - 40px - 30px); /* nvabar top and bottom*/
+    width: 100%;
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex-direction: row;
+    flex-direction: row;
+}
+.wrapper .gutter {
+    background-color: #f7f7f7;
+    background-repeat: no-repeat;
+    background-position: 50%;
+}
+.wrapper .gutter.light {
+    background-color: #f7f7f7;
+}
+.wrapper .gutter.dark {
+    background-color: #333;
+}
+
+.wrapper .gutter:hover {
+    cursor: ew-resize;
+}
+.wrapper .gutter.gutter-vertical {
+    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=");
+}
+.wrapper .gutter.gutter-horizontal {
+    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==");
+}
+.wrapper #jsEditor {
+    padding-top:5px;
+    height: 100%;
+}
+
+.wrapper #jsEditor.light {
+    background-color: white;
+}
+.wrapper #jsEditor.dark {
+    background-color: #1e1e1e;
+}
+.wrapper #canvasZone {
+    height: 100%;
+}
+#renderCanvas {
+    width: 100%;
+    height: 100%;
+    touch-action: none;
+}
+#fpsLabel {
+    position: absolute;
+    right: 10px;
+    top: 50px;
+    cursor: default;
+    z-index:10;
+    background-color: #7283a0;
+    color:white;
+    padding:5px;
+    border-radius: 3px;
+    font-family: 'Montserrat'
+}
+.navbar {
+    height: 40px;
+    width: 100%;
+    font-family: "Montserrat";
+    font-weight: 400;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    position: relative;
+    z-index:5;
+    line-height: 40px;
+}
+.navbar.dark {
+    background-color: #333;
+    box-shadow: 0 3px 10px #000;
+}
+.navbar.light {
+    background-color: #efefef;
+    box-shadow: 0 3px 10px #999;
+}
+.navbar .title {
+    height: 40px;
+    padding-left: 10px;
+    color: #15A4FA;
+    display: inline-block;
+}
+.navbar .version {
+    height: 40px;
+    display: inline-block;
+    color: #7283a0;
+    margin-right: 20px;
+}
+.navbar .category {
+    height: 40px;
+    margin: 0 15px 0 15px;
+    display: inline-block;
+}
+.navbar .category.right {
+    position: absolute;
+    right: 0;
+    top: 0;
+}
+.button {
+    display: inline-block;
+    height: 25px;
+    line-height: 25px;
+    color: white;
+    background-color: #7283a0;
+    margin: 0 2px 0 2px;
+    padding: 0 10px 0 10px;
+    font-size: 0.85em;
+    border-radius: 3px;
+}
+
+.button i {
+    margin-left: 10px;
+}
+.button:hover {
+    cursor: pointer;
+    background-color: #15A4FA;
+}
+.navbar .button.run {
+    height: 30px;
+    line-height: 30px;
+    background-color: #15A4FA;
+    font-size: 1.0em;
+}
+.navbar .select {
+    position: relative;
+}
+.navbar .select:after {
+    font-family: 'FontAwesome', sans-serif;
+    content: "\00a0 \00a0 \00a0 \f078";
+}
+.navbar .select .toDisplay {
+    border: 1px solid #7283a0;
+    position: absolute;
+    z-index: 10;
+    left: 0;
+    top: 25px;
+    min-width: 100%;
+    display: none;
+}
+.navbar .select .toDisplay .option {
+    font-size: 0.9em;
+    height: 35px;
+    line-height: 35px;
+    padding: 0px 5px 0px 5px;
+    text-align: center;
+    border-bottom : 1px solid rgba(0,0,0,0.1);
+}
+
+.navbar .select .toDisplay .option.light:hover {
+    cursor: pointer;
+    background-color: #d9d9d9;
+}
+
+
+.navbar .select .toDisplay .option.dark {
+    background-color: #333;
+    color: white;
+}
+.navbar .select .toDisplay .option.light {
+    background-color: white;
+    color: #7283a0;
+}
+.navbar .select .toDisplay .option.dark:hover {
+    cursor: pointer;
+    background-color: #555;
+}
+
+.navbar .select .toDisplayBig {
+    border: 1px solid #7283a0;
+    border-radius: 5px;
+    position: absolute;
+    z-index: 10;
+    top: 32px;
+    width:550px;
+    max-height:350px;
+    right:0;
+    position:absolute;
+    font-size:0.8em;
+    display: none;
+    
+}
+
+.navbar .select .toDisplayBig.light {
+    background-color: white;    
+    color: #15A4FA;
+}
+
+.navbar .select .toDisplayBig.dark {
+    background-color: #333;    
+    color:white;
+}
+
+.navbar .select .toDisplayBig ul {
+    column-count: 3;        
+    padding:0;
+    margin:0;
+    list-style: none;
+}
+
+.navbar .select .toDisplayBig ul li {
+    padding:0 5px 0 5px;
+}
+
+.navbar .select .toDisplayBig ul li:hover {
+    cursor: pointer;
+}
+.navbar .select .toDisplayBig ul li.light:hover {
+    background-color: #d9d9d9;
+}
+.navbar .select .toDisplayBig ul li.dark:hover {
+    background-color: #555;
+}
+
+
+.navbar .select .toDisplayBig a {
+    text-decoration: none;
+}
+
+.navbar .select .toDisplayBig a.dark {
+    color: white;
+}
+
+.navbar .select .toDisplayBig a.light {
+    color: #7283a0;
+}
+
+
+
+.navbar .check:after {
+    font-family: 'FontAwesome', sans-serif;
+    content: "\00a0 \00a0 \00a0 \f14a";
+}
+.navbar .check.uncheck {
+    background-color: #8290aa;
+}
+.navbar .check.uncheck:after {
+    font-family: 'FontAwesome', sans-serif;
+    content: "\00a0 \00a0 \00a0 \f096";
+}
+#errorZone {
+    display:none;
+    position: absolute;
+    width: 50%;
+    left: 25%;
+    bottom: 40px;
+    background-color: #C73228;
+    padding:20px;
+    border-radius: 5px;
+    color:white;
+    font-family: 'Inconsolata';
+}
+#errorZone button {
+    position:absolute;
+    top : 3px;
+    right: 10px;
+    padding: 0;
+    cursor: pointer;
+    background: transparent;
+    border: 0;
+    -webkit-appearance: none;
+    color: #000;
+    text-shadow: 0 1px 0 #fff;
+    opacity: .4;
+    font-size: 1.8em;
+}
+
+/* Navbar bottom */
+
+.navbarBottom {
+    height:30px;
+    width:100%;
+    line-height:30px;
+    position:relative;
+    font-family: 'Montserrat';
+}
+.navbarBottom.dark {
+    background-color: #333;
+}
+.navbarBottom.light {
+    background-color: #efefef;
+}
+
+.navbarBottom #statusBar {
+    line-height:30px;
+    color: #E74C3C;
+    font-family: 'Inconsolata';
+    padding-left:20px;
+}
+
+
+.navbarBottom .links {
+    position:absolute;
+    right : 0;
+    top:-1px;
+    height:30px;
+    padding-right:20px;
+}
+.navbarBottom .links .link{
+    height:30px;
+    display:inline-block;
+    color:#999;
+    padding: 0 10px 0 10px;
+    margin : 0 5px 0 5px;
+    font-size:0.8em;
+}
+.navbarBottom .links .link.light:hover{
+    color:#999;
+    background-color:#333;
+}
+.navbarBottom .links .link.dark:hover{
+    color:#333;
+    background-color:#eee;
+}
+.navbarBottom .links .link a{
+    text-decoration: none;
+    color:#999;
+    display: inline-block;
+}
+
+/* MONACO */
+
+.monaco-editor .container:before,
+.monaco-editor .row:before {
+    content: "";
+    display: inherit;
+}
+.monaco-editor .container:after,
+.monaco-editor .row:after {
+    clear: inherit;
+}
+.monaco-editor .container {
+    width: auto;
+    margin: inherit;
+    padding: inherit;
+}
+.monaco-editor .close {
+    float: none;
+    font-size: inherit;
+    font-weight: inherit;
+    line-height: inherit;
+    color: inherit;
+    text-shadow: inherit;
+    opacity: inherit;
+    filter: inherit;
+}
+.monaco-editor .row {
+    margin: inherit;
+}
+.monaco-editor .invisible {
+    visibility: visible;
+}
+.monaco-editor .view-lines {
+    font-family: 'Inconsolata' !important;
+}
+/* Save form & co */
+
+.save-message {
+    display: none;
+    position:absolute;
+    top:40px; /* navbar top */
+    width: 100%;
+    z-index:5;
+    text-align: center;
+    font-size: 0.8em;
+    line-height: 2em;
+    cursor:pointer;
+}
+
+.save-message.light {
+    background-color: rgba(239, 239, 239, 0.9);
+    color: #7283a0;
+}
+
+.save-message.dark {
+    background-color: rgba(51, 51, 51, 0.9);
+    color: #eee;
+}
+
+.save-layer {
+    display: none;
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(120, 120, 120, .5);
+    text-align: center;
+}
+.save-layer .save-form {
+    position: absolute;
+    top: 150px;
+    left: calc(50% - 205px);
+    width: 410px;
+    height: 370px;
+    padding-top: 15px;
+    -webkit-border-radius: 6px;
+    -moz-border-radius: 6px;
+    border-radius: 6px;
+    background-color: rgba(27, 27, 27, 0.75);
+    border-color: #252525;
+    color: white;
+    font-family: "Montserrat";
+    font-size: 14px;
+}
+.save-layer .save-form .separator {
+    width: 350px;
+    border-bottom: 1px solid #999;
+    margin: auto;
+    margin-bottom: 10px;
+}
+.save-layer .save-form input,
+.save-layer .save-form textarea {
+    display:block;
+    width: 350px;
+    margin:auto;
+    margin-bottom: 20px;
+    font-family: "Montserrat";
+    padding:5px;
+}
+
+/*Media queries*/
+
+@media (max-width: 1600px) {
+    .desktopOnly {
+        display: none !important;
+    }
+}
+@media (max-width: 1375px) {
+    .desktopOnly {
+        display: none !important;
+    }
+    .desktopTabletOnly {
+        display: none !important;
+    }
+}
+@media (max-width: 975px) {
+    .title {
+        display : none !important;
+    }
+    .version {
+        display : none !important;
+    }
+}

+ 135 - 104
Playground/debug.html

@@ -1,132 +1,157 @@
 <!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>
-    <script src="https://babylonjs.azurewebsites.net/poly2tri.js"></script>    
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.js"></script>
-    <!--x-tag-->
-    <script src="xtag.min.js"></script>
-    <script src="splitbox.js"></script>
-    <link href="splitbox.css" rel="stylesheet" />
+    <!--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="jszip.min.js"></script>
-    <script src="fileSaver.js"></script>
-    <!-- Bootstrap -->
-    <link href="bootstrap/css/bootstrap.css" rel="stylesheet">
+    <script src="js/libs/jszip.min.js"></script>
+    <script src="js/libs/fileSaver.js"></script>
+    <!--Monaco-->
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
-    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
-    <!--<script src="../babylon.js"></script>-->
-    <script src="https://babylonjs.azurewebsites.net/babylon.max.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/babylon.canvas2d.js"></script>
-    
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.waterMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.lavaMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.normalMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.skyMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.triPlanarMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.terrainMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.gradientMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.furMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.gridMaterial.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.shadowOnlyMaterial.js"></script>    
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.brickProceduralTexture.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.cloudProceduralTexture.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireProceduralTexture.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.grassProceduralTexture.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.marbleProceduralTexture.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.roadProceduralTexture.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.starfieldProceduralTexture.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.woodProceduralTexture.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.asciiArtPostProcess.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.digitalRainPostProcess.js"></script>    
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.glTFFileLoader.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.objFileLoader.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.stlFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/cannon.js"></script>
+    <script src="https://www.babylonjs.com/Oimo.js"></script>
+    <script src="https://www.babylonjs.com/babylon.max.js"></script>
+    <script src="https://www.babylonjs.com/babylon.canvas2d.js"></script>
+    <script src="https://www.babylonjs.com/babylon.inspector.bundle.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.fireMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.waterMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.lavaMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.normalMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.skyMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.triPlanarMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.terrainMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.gradientMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.furMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.gridMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.shadowOnlyMaterial.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.brickProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.cloudProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.fireProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.grassProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.marbleProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.roadProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.starfieldProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.woodProceduralTexture.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.asciiArtPostProcess.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.digitalRainPostProcess.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.glTFFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.objFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.stlFileLoader.js"></script>
 
     <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
-    <link href="index.css" rel="stylesheet" />
+    <link href="css/index.css" rel="stylesheet" />
 </head>
+
 <body>
-    <div class="navbar navbar-inverse navbar-fixed-top">
-        <div class="navbar-inner" id="topbar">
-            <a class="brand largeOnly" href="#" id="mainTitle">Babylon.js Playground</a>
-            <div class="btn-group">
-                <button class="btn" id="runButton">Run</button>
-                <button class="btn" id="saveButton">Save</button>
-                <button class="btn desktopOnly" id="zipButton">Get .zip</button>
-                <button class="btn desktopOnly" id="newButton">New</button>
-                <button class="btn desktopOnly" id="clearButton">Clear</button>
-            </div>
-            <div class="btn-group desktopOnly">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentFontSize">Font: 12</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="sizeList">
-                    <li><a href="#" onclick="setFontSize(12);">12</a></li>
-                    <li><a href="#" onclick="setFontSize(14);">14</a></li>
-                    <li><a href="#" onclick="setFontSize(16);">16</a></li>
-                    <li><a href="#" onclick="setFontSize(18);">18</a></li>
-                    <li><a href="#" onclick="setFontSize(20);">20</a></li>
-                    <li><a href="#" onclick="setFontSize(22);">22</a></li>
-                </ul>
+    <div class="navbar">
+        <div class="title">
+            Babylon.js Playground
+        </div>
+        <div class="version" id="mainTitle">
+            v3.0-alpha
+        </div>
+
+        <div class="category">
+            <div class="button run" id="runButton">Run <i class="fa fa-play" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category">
+            <div class="button" id="newButton">New<i class="fa fa-file" aria-hidden="true"></i></div>
+            <div class="button" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
+        </div>
+
+        <div class="category">
+            <div class="button" id="saveButton">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
+            <div class="button" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category desktopOnly">
+            <div class="button select"><span id="currentFontSize">Font: 14</span>
+                <div class="toDisplay">
+                    <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="btn-group">
-                <label class="btn btn-sm active">
-                    <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
-                </label>
-                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
-                <button class="btn btn-sm" id="editorButton">-Editor</button>
-                <button class="btn btn-sm" id="debugButton">+Debug layer</button>
+            <div class="button select">Theme
+                <div class="toDisplay">
+                    <div class="option" id="darkTheme">Dark</div>
+                    <div class="option" id="lightTheme">Light</div>
+                </div>
             </div>
-            <div class="btn-group pull-right">
-                <button class="btn" id="fullscreenButton">Fullscreen</button>
+        </div>
+        <div class="category desktopTabletOnly">
+            <div class="button select">Settings
+                <div class="toDisplay">
+                    <div class="option" id='safemodeToggle'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
+                    <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="fullscreenButton">Fullscreen</div>
+                    <div class="option" id="metadataButton">Metadata</div>
+                </div>
             </div>
-            <div class="btn-group pull-right">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentScript">Predefined scripts</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="scriptsList"></ul>
+
+            <div class="button check uncheck" id="debugButton">Debug layer</div>
+        </div>
+
+
+
+        <div class="category right">
+            <div class="button select desktopTabletOnly"><span id="currentVersion">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="save-message" id="saveMessage">
-                This PG has no metadata. Click save to add them.
+            <div class="button select"> <span id="currentScript">Scenes</span>
+                <div class="toDisplayBig">
+                    <ul id="scriptsList">
+                    </ul>
+                </div>
             </div>
         </div>
+        <div class="save-message" id="saveMessage">
+            This PG has no metadata. Click save to add them.
+        </div>
     </div>
 
-    <x-splitbox>
+    <div class="wrapper">
         <div id="jsEditor"></div>
-        <div splitter></div>
         <div id="canvasZone">
             <canvas touch-action="none" id="renderCanvas"></canvas>
         </div>
-    </x-splitbox>
+    </div>
 
     <span class="label" id="fpsLabel">FPS</span>
 
     <div id="errorZone">
     </div>
 
-    <div class="navbar navbar-inverse navbar-fixed-bottom">
-        <div class="navbar-inner">
-            <ul class="nav pull-left">
-                <li id="statusBar"></li>
-            </ul>
-            <ul class="nav pull-right">
-                <li><a href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></li>
-                <li><a href="https://babylonjs.azurewebsites.net/sandbox">Sandbox</a></li>
-                <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
-                <li><a href="https://doc.babylonjs.com">Documentation</a></li>
-                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
-            </ul>
+    <div class="navbarBottom">
+        <div id="statusBar"></div>
+        <div class="links">
+            <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://github.com/BabylonJS/Babylon.js/wiki">Wiki</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">Playground Search</a></div>
         </div>
     </div>
 
@@ -135,21 +160,27 @@
             <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="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">
-                <button class="btn save-form-button" id="saveFormButtonOk">OK</button>
-                <button class="btn save-form-button" id="saveFormButtonCancel">Cancel</button>
+
+                <div id="saveFormButtonOk" class="button">OK</div>
+                <div id="saveFormButtonCancel" class="button">Cancel</div>
             </div>
         </div>
     </div>
 
     <script src="https://code.jquery.com/jquery.js"></script>
-    <script src="bootstrap/js/bootstrap.js"></script>
-    <script src="index.js"></script>
+
+    <script src="js/actions.js"></script>
+    <script src="js/index.js"></script>
 </body>
-</html>
+
+</html>

+ 38 - 37
Playground/frame.html

@@ -1,47 +1,47 @@
 <!DOCTYPE html>
 <html>
+
 <head>
     <title>Babylon.js Playground</title>
-    <script src="hand.minified-1.2.js"></script>
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/poly2tri.js"></script>    
-    <!-- Babylon.js -->    
-    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/babylon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/babylon.canvas2d.js"></script>
-    
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.waterMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.lavaMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.normalMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.skyMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.terrainMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.gradientMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.furMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.gridMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.shadowOnlyMaterial.min.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.woodProceduralTexture.min.js"></script>
-    
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.glTFFileLoader.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.objFileLoader.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.stlFileLoader.js"></script>
-    
+    <!-- Babylon.js -->
+    <script src="https://www.babylonjs.com/cannon.js"></script>
+    <script src="https://www.babylonjs.com/Oimo.js"></script>
+    <script src="https://www.babylonjs.com/babylon.js"></script>
+    <script src="https://www.babylonjs.com/babylon.canvas2d.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.fireMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.waterMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.lavaMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.normalMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.skyMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.triPlanarMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.terrainMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.gradientMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.furMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.gridMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.shadowOnlyMaterial.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.brickProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.cloudProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.fireProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.grassProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.marbleProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.roadProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.starfieldProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.woodProceduralTexture.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.asciiArtPostProcess.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.digitalRainPostProcess.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.glTFFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.objFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.stlFileLoader.js"></script>
+
     <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
     <link href="frame.css" rel="stylesheet" />
 </head>
+
 <body>
     <canvas touch-action="none" id="renderCanvas"></canvas>
 
@@ -53,4 +53,5 @@
     <script src="https://code.jquery.com/jquery.js"></script>
     <script src="frame.js"></script>
 </body>
-</html>
+
+</html>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
Playground/hand.minified-1.2.js


+ 102 - 70
Playground/index-local.html

@@ -1,69 +1,99 @@
 <!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>
-    <script src="http://www.babylonjs.com/poly2tri.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>
-    <!--x-tag-->
-    <script src="xtag.min.js"></script>
-    <script src="splitbox.js"></script>
-    <link href="splitbox.css" rel="stylesheet" />
     <!-- jszip -->
-    <script src="jszip.min.js"></script>
-    <script src="fileSaver.js"></script>
-    <!-- Bootstrap -->
-    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
+    <script src="js/libs/jszip.min.js"></script>
+    <script src="js/libs/fileSaver.js"></script>
+    <!--Monaco-->
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
-    <!-- Babylon.js -->    
-    
+    <!-- Babylon.js -->
     <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
     <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
-	<script src="../tools/DevLoader/BabylonLoader.js"></script>
-    <link href="index.css" rel="stylesheet" />
+    <script src="../tools/DevLoader/BabylonLoader.js"></script>
+
+    <link href="css/index.css" rel="stylesheet" />
 </head>
+
 <body>
-    <div class="navbar navbar-inverse navbar-fixed-top">
-        <div class="navbar-inner" id="topbar">
-            <a class="brand largeOnly" href="#" id="mainTitle">Babylon.js Playground</a>
-            <div class="btn-group">
-                <button class="btn" id="runButton">Run</button>
-                <button class="btn" id="saveButton">Save</button>
-                <button class="btn desktopOnly" id="zipButton">Get .zip</button>
-                <button class="btn desktopOnly" id="newButton">New</button>
-                <button class="btn desktopOnly" id="clearButton">Clear</button>
+    <div class="navbar">
+        <div class="title">
+            Babylon.js Playground
+        </div>
+        <div class="version" id="mainTitle">
+            v3.0-alpha
+        </div>
+
+        <div class="category">
+            <div class="button run" id="runButton">Run <i class="fa fa-play" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category">
+            <div class="button" id="newButton">New<i class="fa fa-file" aria-hidden="true"></i></div>
+            <div class="button" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
+        </div>
+
+        <div class="category">
+            <div class="button" id="saveButton">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
+            <div class="button" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category desktopOnly">
+            <div class="button select"><span id="currentFontSize">Font: 14</span>
+                <div class="toDisplay">
+                    <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="btn-group desktopOnly">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentFontSize">Font: 12</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="sizeList">
-                    <li><a href="#" onclick="setFontSize(12);">12</a></li>
-                    <li><a href="#" onclick="setFontSize(14);">14</a></li>
-                    <li><a href="#" onclick="setFontSize(16);">16</a></li>
-                    <li><a href="#" onclick="setFontSize(18);">18</a></li>
-                    <li><a href="#" onclick="setFontSize(20);">20</a></li>
-                    <li><a href="#" onclick="setFontSize(22);">22</a></li>
-                </ul>
+            <div class="button select">Theme
+                <div class="toDisplay">
+                    <div class="option" id="darkTheme">Dark</div>
+                    <div class="option" id="lightTheme">Light</div>
+                </div>
             </div>
-            <div class="btn-group">
-                <label class="btn btn-sm active">
-                    <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
-                </label>
-                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
-                <button class="btn btn-sm" id="editorButton">-Editor</button>
-                <button class="btn btn-sm" id="debugButton">+Debug layer</button>
+        </div>
+        <div class="category desktopTabletOnly">
+            <div class="button select">Settings
+                <div class="toDisplay">
+                    <div class="option" id='safemodeToggle'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
+                    <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="fullscreenButton">Fullscreen</div>
+                    <div class="option" id="metadataButton">Metadata</div>
+                </div>
             </div>
-            <div class="btn-group pull-right">
-                <button class="btn" id="fullscreenButton">Fullscreen</button>
+
+            <div class="button check uncheck" id="debugButton">Debug layer</div>
+        </div>
+
+
+
+        <div class="category right">
+            <div class="button select desktopTabletOnly"><span id="currentVersion">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="btn-group pull-right">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentScript">Predefined scripts</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="scriptsList"></ul>
+            <div class="button select"> <span id="currentScript">Scenes</span>
+                <div class="toDisplayBig">
+                    <ul id="scriptsList">
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="save-message" id="saveMessage">
@@ -71,31 +101,26 @@
         </div>
     </div>
 
-    <x-splitbox>
+    <div class="wrapper">
         <div id="jsEditor"></div>
-        <div splitter></div>
         <div id="canvasZone">
             <canvas touch-action="none" id="renderCanvas"></canvas>
         </div>
-    </x-splitbox>
+    </div>
 
     <span class="label" id="fpsLabel">FPS</span>
 
     <div id="errorZone">
     </div>
 
-    <div class="navbar navbar-inverse navbar-fixed-bottom">
-        <div class="navbar-inner">
-            <ul class="nav pull-left">
-                <li id="statusBar"></li>
-            </ul>
-            <ul class="nav pull-right">
-                <li><a href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></li>
-                <li><a href="http://www.babylonjs.com/sandbox">Sandbox</a></li>
-                <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
-                <li><a href="https://doc.babylonjs.com">Documentation</a></li>
-                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
-            </ul>
+    <div class="navbarBottom">
+        <div id="statusBar"></div>
+        <div class="links">
+            <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://github.com/BabylonJS/Babylon.js/wiki">Wiki</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">Playground Search</a></div>
         </div>
     </div>
 
@@ -104,24 +129,31 @@
             <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="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">
-                <button class="btn save-form-button" id="saveFormButtonOk">OK</button>
-                <button class="btn save-form-button" id="saveFormButtonCancel">Cancel</button>
+
+                <div id="saveFormButtonOk" class="button">OK</div>
+                <div id="saveFormButtonCancel" class="button">Cancel</div>
             </div>
         </div>
     </div>
 
-    <script src="http://code.jquery.com/jquery.js"></script>
-    <script src="bootstrap/js/bootstrap.min.js"></script>
+    <script src="https://code.jquery.com/jquery.js"></script>
+
+    <script src="js/actions.js"></script>
+    <script src="js/index.js"></script>
     <script>
         BABYLONDEVTOOLS.Loader.require('index.js')
             .load();
     </script>
 </body>
-</html>
+
+</html>

+ 0 - 188
Playground/index.css

@@ -1,188 +0,0 @@
-html, body {
-    overflow: hidden;
-    width: 100%;
-    height: 100%;
-    background-color: #272822;
-}
-
-x-splitbox {
-    position: absolute;
-    left: 0px;
-    top: 50px;
-    width: 100%;
-    bottom: 40px;
-    height: auto;
-}
-
-    x-splitbox > [splitter]:after {
-        display: none;
-    }
-
-
-#jsEditor {
-    min-width: 250px;
-}
-
-#canvasZone {
-    min-width: 250px;
-    height: 100%;
-}
-
-#renderCanvas {
-    width: 100%;
-    height: 100%;
-    touch-action: none;
-}
-
-ul#scriptsList {
-    overflow-y: auto;
-    height: 600px;
-    -webkit-column-count: 3;
-    -moz-column-count: 3;
-    column-count: 3;
-    padding: 10px
-}
-
-#fpsLabel {
-    position: absolute;
-    right: 10px;
-    top: 70px;
-    cursor: default;
-}
-
-#topbar {
-    padding: 5px;
-}
-
-.navbar .brand {
-    margin-left: 0px;
-}
-
-#errorZone {
-    position: absolute;
-    width: 50%;
-    left: 25%;
-    bottom: 40px;
-}
-
-#statusBar {
-    padding: 10px 15px 10px;
-    color: #999;
-}
-
-@media (max-width: 800px) {
-    .desktopOnly {
-        display: none !important;
-    }
-}
-
-@media (max-width: 1100px) {
-    .largeOnly {
-        display: none !important;
-    }
-}
-
-@media (max-width: 550px) {
-    .btn-group > .btn, .btn-group > .dropdown-menu, .btn-group > .popover {
-        font-size: 12px !important;
-    }
-}
-
-/* MONACO */
-.monaco-editor .container:before, .monaco-editor .row:before {
-    content: "";
-    display: inherit;
-}
-
-.monaco-editor .container:after, .monaco-editor .row:after {
-    clear: inherit;
-}
-
-.monaco-editor .container {
-    width: auto;
-    margin: inherit;
-    padding: inherit;
-}
-
-.monaco-editor .close {
-    float: none;
-    font-size: inherit;
-    font-weight: inherit;
-    line-height: inherit;
-    color: inherit;
-    text-shadow: inherit;
-    opacity: inherit;
-    filter: inherit;
-}
-
-.monaco-editor .row {
-    margin: inherit;
-}
-
-.monaco-editor .invisible {
-    visibility: visible;
-}
-
-
-/* Save form & co */
-
-.save-message {
-    display: none;
-    float: left;
-    width: 100%;
-    background-color: rgba(0,0,0,.5);
-    text-align: center;
-    color: white;
-    font-size: 1.1em;
-    line-height: 2em;
-}
-
-.save-layer {
-    display: none;
-    position: absolute;
-    top: 0;
-    left: 0;
-
-    width: 100%;
-    height: 100%;
-
-    background-color: rgba(120,120,120,.5);
-    text-align: center;
-}
-.save-layer .save-form {
-    position: absolute;
-    top: 150px;
-    left: calc(50% - 205px);
-
-    width: 410px;
-    height: 390px;
-    padding-top: 15px;
-    -webkit-border-radius: 6px;
-    -moz-border-radius: 6px;
-    border-radius: 6px;
-
-    background-color: rgba(27,27,27,0.75);/*#1b1b1b;*/
-    background-image: -moz-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
-    background-image: -webkit-gradient(linear,0 0,0 100%,from(rgba(34,34,34,.75)),to(rgba(17,17,17,.75)));
-    background-image: -webkit-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
-    background-image: -o-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
-    background-image: linear-gradient(to bottom,rgba(34,34,34,.75),rgba(17,17,17,.75));
-    background-repeat: repeat-x;
-    border-color: #252525;
-    color: white;
-    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
-    font-size: 14px;
-}
-.save-layer .save-form .separator {
-    width: 350px;
-    border-bottom: 1px solid #999;
-    margin: auto;
-    margin-top: -6px;
-    margin-bottom: 10px;
-}
-.save-layer .save-form .save-form-buttons {
-    margin-top: 10px;
-}
-.save-layer .save-form input, .save-layer .save-form textarea {
-    width: 350px;
-}

+ 131 - 110
Playground/index.html

@@ -1,110 +1,130 @@
 <!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>
-    <!--x-tag-->
-    <script src="xtag.min.js"></script>
-    <script src="splitbox.js"></script>
-    <link href="splitbox.css" rel="stylesheet" />
     <!-- jszip -->
-    <script src="jszip.min.js"></script>
-    <script src="fileSaver.js"></script>
-    <!-- Bootstrap -->
-    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
+    <script src="js/libs/jszip.min.js"></script>
+    <script src="js/libs/fileSaver.js"></script>
+    <!--Monaco-->
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
-    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
-    <!--<script src="../babylon.js"></script>-->
-    <script src="https://babylonjs.azurewebsites.net/babylon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/babylon.canvas2d.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/babylon.inspector.bundle.js"></script>
-    
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.waterMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.lavaMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.normalMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.skyMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.terrainMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.gradientMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.furMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.gridMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.shadowOnlyMaterial.min.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.glTFFileLoader.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.objFileLoader.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.stlFileLoader.js"></script>
-    
+    <script src="https://www.babylonjs.com/cannon.js"></script>
+    <script src="https://www.babylonjs.com/Oimo.js"></script>
+    <script src="https://www.babylonjs.com/babylon.js"></script>
+    <script src="https://www.babylonjs.com/babylon.canvas2d.js"></script>
+    <script src="https://www.babylonjs.com/babylon.inspector.bundle.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.fireMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.waterMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.lavaMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.normalMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.skyMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.triPlanarMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.terrainMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.gradientMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.furMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.gridMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.shadowOnlyMaterial.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.brickProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.cloudProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.fireProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.grassProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.marbleProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.roadProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.starfieldProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.woodProceduralTexture.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.asciiArtPostProcess.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.digitalRainPostProcess.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.glTFFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.objFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.stlFileLoader.js"></script>
+
     <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
-    <link href="index.css" rel="stylesheet" />
+    <link href="css/index.css" rel="stylesheet" />
 </head>
+
 <body>
-    <div class="navbar navbar-inverse navbar-fixed-top">
-        <div class="navbar-inner" id="topbar">
-            <a class="brand largeOnly" href="#" id="mainTitle">Babylon.js Playground</a>
-            <div class="btn-group">
-                <button class="btn" id="runButton">Run</button>
-                <button class="btn" id="saveButton">Save</button>
-                <button class="btn desktopOnly" id="zipButton">Get .zip</button>
-                <button class="btn desktopOnly" id="newButton">New</button>
-                <button class="btn desktopOnly" id="clearButton">Clear</button>
+    <div class="navbar">
+        <div class="title">
+            Babylon.js Playground
+        </div>
+        <div class="version" id="mainTitle">
+            v3.0-alpha
+        </div>
+
+        <div class="category">
+            <div class="button run" id="runButton">Run <i class="fa fa-play" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category">
+            <div class="button" id="newButton">New<i class="fa fa-file" aria-hidden="true"></i></div>
+            <div class="button" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
+        </div>
+
+        <div class="category">
+            <div class="button" id="saveButton">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
+            <div class="button" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category desktopOnly">
+            <div class="button select"><span id="currentFontSize">Font: 14</span>
+                <div class="toDisplay">
+                    <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="btn-group desktopOnly">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentFontSize">Font: 12</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="sizeList">
-                    <li><a href="#" onclick="setFontSize(12);">12</a></li>
-                    <li><a href="#" onclick="setFontSize(14);">14</a></li>
-                    <li><a href="#" onclick="setFontSize(16);">16</a></li>
-                    <li><a href="#" onclick="setFontSize(18);">18</a></li>
-                    <li><a href="#" onclick="setFontSize(20);">20</a></li>
-                    <li><a href="#" onclick="setFontSize(22);">22</a></li>
-                </ul>
+            <div class="button select">Theme
+                <div class="toDisplay">
+                    <div class="option" id="darkTheme">Dark</div>
+                    <div class="option" id="lightTheme">Light</div>
+                </div>
             </div>
-            <div class="btn-group desktopOnly">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentVersion">Version: Latest</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="versionList">
-                    <li><a href="#" onclick="setVersion('latest');">Latest</a></li>
-                    <li><a href="#" onclick="setVersion('2.5');">2.5</a></li>
-                </ul>
-            </div>            
-            <div class="btn-group">
-                <label class="btn btn-sm active">
-                    <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
-                </label>
-                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
-                <button class="btn btn-sm" id="editorButton">-Editor</button>
-                <button class="btn btn-sm" id="debugButton">+Debug layer</button>
+        </div>
+        <div class="category desktopTabletOnly">
+            <div class="button select">Settings
+                <div class="toDisplay">
+                    <div class="option" id='safemodeToggle'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
+                    <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="fullscreenButton">Fullscreen</div>
+                    <div class="option" id="metadataButton">Metadata</div>
+                </div>
             </div>
-            <div class="btn-group pull-right">
-                <button class="btn" id="fullscreenButton">Fullscreen</button>
+
+            <div class="button check uncheck" id="debugButton">Debug layer</div>
+        </div>
+
+
+
+        <div class="category right">
+            <div class="button select desktopTabletOnly"><span id="currentVersion">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="btn-group pull-right">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentScript">Predefined scripts</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="scriptsList"></ul>
+            <div class="button select"> <span id="currentScript">Scenes</span>
+                <div class="toDisplayBig">
+                    <ul id="scriptsList">
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="save-message" id="saveMessage">
@@ -112,31 +132,26 @@
         </div>
     </div>
 
-    <x-splitbox>
+    <div class="wrapper">
         <div id="jsEditor"></div>
-        <div splitter></div>
         <div id="canvasZone">
             <canvas touch-action="none" id="renderCanvas"></canvas>
         </div>
-    </x-splitbox>
+    </div>
 
     <span class="label" id="fpsLabel">FPS</span>
 
     <div id="errorZone">
     </div>
 
-    <div class="navbar navbar-inverse navbar-fixed-bottom">
-        <div class="navbar-inner">
-            <ul class="nav pull-left">
-                <li id="statusBar"></li>
-            </ul>
-            <ul class="nav pull-right">
-                <li><a href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></li>
-                <li><a href="https://babylonjs.azurewebsites.net/sandbox">Sandbox</a></li>
-                <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
-                <li><a href="https://doc.babylonjs.com">Documentation</a></li>
-                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
-            </ul>
+    <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>
 
@@ -145,21 +160,27 @@
             <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="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">
-                <button class="btn save-form-button" id="saveFormButtonOk">OK</button>
-                <button class="btn save-form-button" id="saveFormButtonCancel">Cancel</button>
+
+                <div id="saveFormButtonOk" class="button">OK</div>
+                <div id="saveFormButtonCancel" class="button">Cancel</div>
             </div>
         </div>
     </div>
 
     <script src="https://code.jquery.com/jquery.js"></script>
-    <script src="bootstrap/js/bootstrap.min.js"></script>
-    <script src="index.js"></script>
+
+    <script src="js/actions.js"></script>
+    <script src="js/index.js"></script>
 </body>
+
 </html>

+ 137 - 113
Playground/index2_5.html

@@ -1,140 +1,157 @@
 <!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>
-    <script src="https://babylonjs.azurewebsites.net/poly2tri.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>
-    <!--x-tag-->
-    <script src="xtag.min.js"></script>
-    <script src="splitbox.js"></script>
-    <link href="splitbox.css" rel="stylesheet" />
     <!-- jszip -->
-    <script src="jszip.min.js"></script>
-    <script src="fileSaver.js"></script>
-    <!-- Bootstrap -->
-    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
+    <script src="js/libs/jszip.min.js"></script>
+    <script src="js/libs/fileSaver.js"></script>
+    <!--Monaco-->
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
-    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
-    <!--<script src="../babylon.js"></script>-->
-    <script src="https://babylonjs.azurewebsites.net/versions/babylon.2.5.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/versions/babylon.2.5.canvas2d.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/babylon.inspector.bundle.js"></script>
-    
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.waterMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.lavaMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.normalMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.skyMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.terrainMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.gradientMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.furMaterial.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.gridMaterial.min.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.glTFFileLoader.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.objFileLoader.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.stlFileLoader.js"></script>
-    <link href="index.css" rel="stylesheet" />
+    <script src="https://www.babylonjs.com/cannon.js"></script>
+    <script src="https://www.babylonjs.com/Oimo.js"></script>
+    <script src="https://www.babylonjs.com/versions/babylon.2.5.js"></script>
+    <script src="https://www.babylonjs.com/versions/babylon.2.5.canvas2d.js"></script>
+    <script src="https://www.babylonjs.com/babylon.inspector.bundle.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.fireMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.waterMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.lavaMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.normalMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.skyMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.triPlanarMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.terrainMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.gradientMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.furMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.gridMaterial.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.shadowOnlyMaterial.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.brickProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.cloudProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.fireProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.grassProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.marbleProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.roadProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.starfieldProceduralTexture.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.woodProceduralTexture.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.asciiArtPostProcess.min.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.digitalRainPostProcess.min.js"></script>
+
+    <script src="https://www.babylonjs.com/lib/babylon.glTFFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.objFileLoader.js"></script>
+    <script src="https://www.babylonjs.com/lib/babylon.stlFileLoader.js"></script>
+
+    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
+    <link href="css/index.css" rel="stylesheet" />
 </head>
+
 <body>
-    <div class="navbar navbar-inverse navbar-fixed-top">
-        <div class="navbar-inner" id="topbar">
-            <a class="brand largeOnly" href="#" id="mainTitle">Babylon.js Playground</a>
-            <div class="btn-group">
-                <button class="btn" id="runButton">Run</button>
-                <button class="btn" id="saveButton">Save</button>
-                <button class="btn desktopOnly" id="zipButton">Get .zip</button>
-                <button class="btn desktopOnly" id="newButton">New</button>
-                <button class="btn desktopOnly" id="clearButton">Clear</button>
-            </div>
-            <div class="btn-group desktopOnly">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentFontSize">Font: 12</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="sizeList">
-                    <li><a href="#" onclick="setFontSize(12);">12</a></li>
-                    <li><a href="#" onclick="setFontSize(14);">14</a></li>
-                    <li><a href="#" onclick="setFontSize(16);">16</a></li>
-                    <li><a href="#" onclick="setFontSize(18);">18</a></li>
-                    <li><a href="#" onclick="setFontSize(20);">20</a></li>
-                    <li><a href="#" onclick="setFontSize(22);">22</a></li>
-                </ul>
+    <div class="navbar">
+        <div class="title">
+            Babylon.js Playground
+        </div>
+        <div class="version" id="mainTitle">
+            v3.0-alpha
+        </div>
+
+        <div class="category">
+            <div class="button run" id="runButton">Run <i class="fa fa-play" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category">
+            <div class="button" id="newButton">New<i class="fa fa-file" aria-hidden="true"></i></div>
+            <div class="button" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
+        </div>
+
+        <div class="category">
+            <div class="button" id="saveButton">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
+            <div class="button" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category desktopOnly">
+            <div class="button select"><span id="currentFontSize">Font: 14</span>
+                <div class="toDisplay">
+                    <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="btn-group desktopOnly">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentVersion">Version: Latest</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="versionList">
-                    <li><a href="#" onclick="setVersion('latest');">Latest</a></li>
-                    <li><a href="#" onclick="setVersion('2.5');">2.5</a></li>
-                </ul>
-            </div>            
-            <div class="btn-group">
-                <label class="btn btn-sm active">
-                    <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
-                </label>
-                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
-                <button class="btn btn-sm" id="editorButton">-Editor</button>
-                <button class="btn btn-sm" id="debugButton">+Debug layer</button>
+            <div class="button select">Theme
+                <div class="toDisplay">
+                    <div class="option" id="darkTheme">Dark</div>
+                    <div class="option" id="lightTheme">Light</div>
+                </div>
             </div>
-            <div class="btn-group pull-right">
-                <button class="btn" id="fullscreenButton">Fullscreen</button>
+        </div>
+        <div class="category desktopTabletOnly">
+            <div class="button select">Settings
+                <div class="toDisplay">
+                    <div class="option" id='safemodeToggle'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
+                    <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="fullscreenButton">Fullscreen</div>
+                    <div class="option" id="metadataButton">Metadata</div>
+                </div>
             </div>
-            <div class="btn-group pull-right">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentScript">Predefined scripts</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="scriptsList"></ul>
+
+            <div class="button check uncheck" id="debugButton">Debug layer</div>
+        </div>
+
+
+
+        <div class="category right">
+            <div class="button select desktopTabletOnly"><span id="currentVersion">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="save-message" id="saveMessage">
-                Be the first to fill this playground metadata!
+            <div class="button select"> <span id="currentScript">Scenes</span>
+                <div class="toDisplayBig">
+                    <ul id="scriptsList">
+                    </ul>
+                </div>
             </div>
         </div>
+        <div class="save-message" id="saveMessage">
+            This PG has no metadata. Click save to add them.
+        </div>
     </div>
 
-    <x-splitbox>
+    <div class="wrapper">
         <div id="jsEditor"></div>
-        <div splitter></div>
         <div id="canvasZone">
             <canvas touch-action="none" id="renderCanvas"></canvas>
         </div>
-    </x-splitbox>
+    </div>
 
     <span class="label" id="fpsLabel">FPS</span>
 
     <div id="errorZone">
     </div>
 
-    <div class="navbar navbar-inverse navbar-fixed-bottom">
-        <div class="navbar-inner">
-            <ul class="nav pull-left">
-                <li id="statusBar"></li>
-            </ul>
-            <ul class="nav pull-right">
-                <li><a href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></li>
-                <li><a href="https://babylonjs.azurewebsites.net/sandbox">Sandbox</a></li>
-                <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
-                <li><a href="https://doc.babylonjs.com">Documentation</a></li>
-                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
-            </ul>
+    <div class="navbarBottom">
+        <div id="statusBar"></div>
+        <div class="links">
+            <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://github.com/BabylonJS/Babylon.js/wiki">Wiki</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">Playground Search</a></div>
         </div>
     </div>
 
@@ -150,14 +167,21 @@
             <div class="separator"></div>
             <textarea id="saveFormTags" rows="4" cols="10"></textarea>
             <div class="save-form-buttons" id="saveFormButtons">
-                <button class="btn save-form-button" id="saveFormButtonOk">OK</button>
-                <button class="btn save-form-button" id="saveFormButtonCancel">Cancel</button>
+
+                <div id="saveFormButtonOk" class="button">OK</div>
+                <div id="saveFormButtonCancel" class="button">Cancel</div>
             </div>
         </div>
     </div>
 
     <script src="https://code.jquery.com/jquery.js"></script>
-    <script src="bootstrap/js/bootstrap.min.js"></script>
-    <script src="index.js"></script>
+
+    <script>
+        Split(['#jsEditor', '#canvasZone']);
+    </script>
+
+    <script src="js/actions.js"></script>
+    <script src="js/index.js"></script>
 </body>
-</html>
+
+</html>

+ 63 - 0
Playground/js/actions.js

@@ -0,0 +1,63 @@
+(function () {
+
+    var allSelect = document.querySelectorAll('.select');
+    var allToDisplay = document.querySelectorAll('.toDisplay');
+    var allToDisplayBig = document.querySelectorAll('.toDisplayBig');
+
+    var removeAllOptions = function () {
+        for (var index = 0; index < allToDisplay.length; index++) {
+            var a = allToDisplay[index];
+            if (a.style.display == 'block') {
+                a.style.display = 'none';
+            }
+        }
+        for (var index = 0; index < allToDisplayBig.length; index++) {
+            var b = allToDisplayBig[index];
+            if (b.style.display == 'block') {
+                b.style.display = 'none';
+            }
+        }
+    }
+
+    // Remove displayed options
+    window.addEventListener('click', function () {
+        removeAllOptions();
+    });
+
+    // Handle click on select elements
+    for (var index = 0; index < allSelect.length; index++) {
+        var s = allSelect[index];
+        // Get child called to display
+        s.addEventListener('click', function (e) {
+            var toDisplay = this.querySelector('.toDisplay');
+            if (toDisplay) {
+                if (toDisplay.style.display == 'block') {
+                    toDisplay.style.display = 'none';
+                } else {
+                    removeAllOptions();
+                    toDisplay.style.display = 'block';
+                }
+            }
+            toDisplay = this.querySelector('.toDisplayBig');
+            if (toDisplay) {
+                if (toDisplay.style.display == 'block') {
+                    toDisplay.style.display = 'none';
+                } else {
+                    removeAllOptions();
+                    toDisplay.style.display = 'block';
+                }
+            }
+            e.preventDefault();
+            e.stopPropagation();
+        });
+    }
+
+    document.querySelector('#safemodeToggle').addEventListener('click', function () {
+        this.classList.toggle('checked');
+        if (this.classList.contains('checked')) {
+            this.innerHTML = 'Safe mode <i class="fa fa-check-square" aria-hidden="true"></i>';
+        } else {
+            this.innerHTML = 'Safe mode <i class="fa fa-square-o" aria-hidden="true"></i>';
+        }
+    })
+})();

+ 123 - 38
Playground/index.js

@@ -1,5 +1,20 @@
-(function () {
-    var jsEditor;
+var jsEditor;
+(function () {
+    var fontSize = 14;
+
+    var splitInstance = Split(['#jsEditor', '#canvasZone']);
+
+    var elementToTheme = [
+        '.wrapper .gutter',
+        '.wrapper #jsEditor',
+        '.navbar',
+        '.navbar .select .toDisplay .option',
+        '.navbar .select .toDisplayBig',
+        '.navbar .select .toDisplayBig a',
+        '.navbar .select .toDisplayBig ul li',
+        '.navbarBottom',
+        '.navbarBottom .links .link',
+        '.save-message'];
 
     var run = function () {
         var blockEditorChange = false;
@@ -13,7 +28,7 @@
             }
 
             document.getElementById("currentScript").innerHTML = "Custom";
-            document.getElementById('safemodeToggle').checked = true;
+            document.getElementById('safemodeToggle').classList.add('checked');
         });
 
         var snippetUrl = "https://babylonjs-api2.azurewebsites.net/snippets";
@@ -90,17 +105,15 @@
                         var ul = document.getElementById("scriptsList");
                         var index;
                         for (index = 0; index < scripts.length; index++) {
-                            var li = document.createElement("li");
+                            var option = document.createElement("li");
                             var a = document.createElement("a");
-
-                            li.class = "scriptsListEntry";
                             a.href = "#";
                             a.innerHTML = (index + 1) + " - " + scripts[index];
                             a.scriptLinkIndex = index + 1;
                             a.onclick = onScriptClick;
 
-                            li.appendChild(a);
-                            ul.appendChild(li);
+                            option.appendChild(a);
+                            ul.appendChild(option);
                         }
 
                         if (!location.hash) {
@@ -119,6 +132,23 @@
                                 loadScript("scripts/basic scene.js", "Basic scene");
                             }
                         }
+
+                        // Restore theme
+                        var theme = localStorage.getItem("bjs-playground-theme") || 'light';
+                        toggleTheme(theme);
+
+                        // Remove editor if window size is less than 850px
+                        var removeEditorForSmallScreen = function () {
+                            if (mq.matches) {
+                                splitInstance.collapse(0);
+                            } else {
+                                splitInstance.setSizes([50, 50]);
+                            }
+                        }
+                        var mq = window.matchMedia("(max-width: 850px)");
+                        mq.addListener(removeEditorForSmallScreen);
+
+
                     }
                 }
             };
@@ -149,7 +179,7 @@
 
         var showError = function (errorMessage, errorEvent) {
             var errorContent =
-                '<div class="alert alert-error"><button type="button" class="close" data-dismiss="alert">&times;</button><h4>Compilation error</h4>'
+                '<div class="alert alert-error"><button type="button" class="close" data-dismiss="alert">&times;</button>';
             if (errorEvent) {
                 var regEx = /\(.+:(\d+):(\d+)\)\n/g;
 
@@ -165,10 +195,16 @@
 
             errorContent += errorMessage + '</div>';
 
+            document.getElementById("errorZone").style.display = 'block';
             document.getElementById("errorZone").innerHTML = errorContent;
+
+            // Close button error
+            document.getElementById("errorZone").querySelector('.close').addEventListener('click', function () {
+                document.getElementById("errorZone").style.display = 'none';
+            });
         }
 
-        var showNoMetadata = function() {
+        var showNoMetadata = function () {
             document.getElementById("saveFormTitle").value = '';
             document.getElementById("saveFormTitle").readOnly = false;
             document.getElementById("saveFormDescription").value = '';
@@ -177,17 +213,18 @@
             document.getElementById("saveFormTags").readOnly = false;
             document.getElementById("saveFormButtons").style.display = "block";
             document.getElementById("saveMessage").style.display = "block";
-            document.getElementById("metadataButton").style.display = "none";
+            // document.getElementById("metadataButton").style.display = "none";
         };
         showNoMetadata();
+        document.getElementById("saveMessage").style.display = "none";
 
-        var hideNoMetadata = function() {
+        var hideNoMetadata = function () {
             document.getElementById("saveFormTitle").readOnly = true;
             document.getElementById("saveFormDescription").readOnly = true;
             document.getElementById("saveFormTags").readOnly = true;
-            document.getElementById("saveFormButtons").style.display = "none";
+            document.getElementById("saveFormButtonOk").style.display = "none";
             document.getElementById("saveMessage").style.display = "none";
-            document.getElementById("metadataButton").style.display = "inline-block";
+            document.getElementById("metadataButton").style.display = "block";
         };
 
         compileAndRun = function () {
@@ -205,6 +242,7 @@
 
                 var canvas = document.getElementById("renderCanvas");
                 engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
+                document.getElementById("errorZone").style.display = 'none';
                 document.getElementById("errorZone").innerHTML = "";
                 document.getElementById("statusBar").innerHTML = "Loading assets...Please wait";
 
@@ -458,7 +496,8 @@
 
         // Fonts
         setFontSize = function (size) {
-            document.querySelector(".monaco-editor").style.fontSize = size + "px";
+            fontSize = size;
+            document.querySelector(".view-lines").style.fontSize = size + "px";
             document.getElementById("currentFontSize").innerHTML = "Font: " + size;
         };
 
@@ -473,14 +512,15 @@
             var editorButton = document.getElementById("editorButton");
             var scene = engine.scenes[0];
 
-            if (editorButton.innerHTML === "-Editor") {
-                editorButton.innerHTML = "+Editor";
-                document.getElementById("jsEditor").style.display = "none";
-                document.getElementById("canvasZone").style.flexBasis = "100%";
+            // If the editor is present
+            if (editorButton.classList.contains('checked')) {
+                editorButton.classList.remove('checked');
+                splitInstance.collapse(0);
+                editorButton.innerHTML = 'Editor <i class="fa fa-square-o" aria-hidden="true"></i>';
             } else {
-                editorButton.innerHTML = "-Editor";
-                document.getElementById("jsEditor").style.display = "block";
-                document.getElementById("canvasZone").style.flexBasis = undefined;
+                editorButton.classList.add('checked');
+                splitInstance.setSizes([50, 50]);  // Reset
+                editorButton.innerHTML = 'Editor <i class="fa fa-check-square" aria-hidden="true"></i>';
             }
             engine.resize();
 
@@ -490,30 +530,69 @@
             }
         }
 
+        /**
+         * Toggle the dark theme
+         */
+        var toggleTheme = function (theme) {
+            // Monaco
+            var vsTheme;
+            if (theme == 'dark') {
+                vsTheme = 'vs-dark'
+            } else {
+                vsTheme = 'vs'
+            }
+
+            let oldCode = jsEditor.getValue();
+            jsEditor.dispose();
+            jsEditor = monaco.editor.create(document.getElementById('jsEditor'), {
+                value: "",
+                language: "javascript",
+                lineNumbers: true,
+                tabSize: "auto",
+                insertSpaces: "auto",
+                roundedSelection: true,
+                scrollBeyondLastLine: false,
+                automaticLayout: true,
+                readOnly: false,
+                theme: vsTheme,
+                contextmenu: false
+            });
+            jsEditor.setValue(oldCode);
+            setFontSize(fontSize);
+
+            for (var index = 0; index < elementToTheme.length; index++) {
+                var obj = elementToTheme[index];
+                let domObjArr = document.querySelectorAll(obj);
+                for (var domObjIndex = 0; domObjIndex < domObjArr.length; domObjIndex++) {
+                    var domObj = domObjArr[domObjIndex];
+                    domObj.classList.remove('light');
+                    domObj.classList.remove('dark');
+                    domObj.classList.add(theme);
+                }
+            }
+
+            localStorage.setItem("bjs-playground-theme", theme);
+
+        }
+
         var toggleDebug = function () {
             var debugButton = document.getElementById("debugButton");
             var scene = engine.scenes[0];
 
-            if (debugButton.innerHTML === "+Debug layer") {
-                debugButton.innerHTML = "-Debug layer";
+            if (debugButton.classList.contains('uncheck')) {
+                debugButton.classList.remove('uncheck');
                 scene.debugLayer.show();
             } else {
-                debugButton.innerHTML = "+Debug layer";
+                debugButton.classList.add('uncheck');
                 scene.debugLayer.hide();
             }
         }
 
-        var toggleMetadata = function() {
-            var metadataButton = document.getElementById("metadataButton");
+        var toggleMetadata = function () {
+            // var metadataButton = document.getElementById("metadataButton");
             var scene = engine.scenes[0];
-
-            if (metadataButton.innerHTML === "+Meta data") {
-                metadataButton.innerHTML = "-Meta data";
-                document.getElementById("saveLayer").style.display = "block";
-            } else {
-                metadataButton.innerHTML = "+Meta data";
-                document.getElementById("saveLayer").style.display = "none";
-            }
+            // metadataButton.classList.add('checked');
+            document.getElementById("saveLayer").style.display = "block";
         }
 
         // UI
@@ -525,11 +604,17 @@
         document.getElementById("editorButton").addEventListener("click", toggleEditor);
         document.getElementById("debugButton").addEventListener("click", toggleDebug);
         document.getElementById("metadataButton").addEventListener("click", toggleMetadata);
+        document.getElementById("darkTheme").addEventListener("click", toggleTheme.bind(this, 'dark'));
+        document.getElementById("lightTheme").addEventListener("click", toggleTheme.bind(this, 'light'));
+
+        // Restore theme
+        var theme = localStorage.getItem("bjs-playground-theme") || 'light';
+        toggleTheme(theme);
 
         //Navigation Overwrites
         var exitPrompt = function (e) {
             var safeToggle = document.getElementById("safemodeToggle");
-            if (safeToggle.checked) {
+            if (safeToggle.classList.contains('checked')) {
                 e = e || window.event;
                 var message =
                     'This page is asking you to confirm that you want to leave - data you have entered may not be saved.';
@@ -609,7 +694,7 @@
         document.getElementById("saveMessage").addEventListener("click", function () {
             document.getElementById("saveMessage").style.display = "none";
         });
-        document.getElementById("mainTitle").innerHTML = "Babylon.js v" + BABYLON.Engine.Version + " Playground";
+        document.getElementById("mainTitle").innerHTML = "v" + BABYLON.Engine.Version;
 
         var previousHash = "";
 
@@ -682,7 +767,7 @@
 
                         var hash = location.hash.substr(1);
                         currentSnippetToken = hash.split("#")[0];
-                        if(!hash.split("#")[1]) hash += "#0";
+                        if (!hash.split("#")[1]) hash += "#0";
 
 
                         xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));

Playground/fileSaver.js → Playground/js/libs/fileSaver.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 13 - 13
Playground/jszip.min.js


+ 587 - 0
Playground/js/libs/split.js

@@ -0,0 +1,587 @@
+// The programming goals of Split.js are to deliver readable, understandable and
+// maintainable code, while at the same time manually optimizing for tiny minified file size,
+// browser compatibility without additional requirements, graceful fallback (IE8 is supported)
+// and very few assumptions about the user's page layout.
+//
+// Make sure all browsers handle this JS library correctly with ES5.
+// More information here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
+'use strict';
+
+// A wrapper function that does a couple things:
+//
+// 1. Doesn't pollute the global namespace. This is important for a library.
+// 2. Allows us to mount the library in different module systems, as well as
+//    directly in the browser.
+(function() {
+
+// Save the global `this` for use later. In this case, since the library only
+// runs in the browser, it will refer to `window`. Also, figure out if we're in IE8
+// or not. IE8 will still render correctly, but will be static instead of draggable.
+//
+// Save a couple long function names that are used frequently.
+// This optimization saves around 400 bytes.
+//
+// Set a float fudging global, used when dividing and setting sizes to long floats.
+// There's a chance that sometimes the sum of the floats would end up being slightly
+// larger than 100%, breaking the layout. The float fudging value is subtracted from
+// the percentage size.
+var global = this
+  , isIE8 = global.attachEvent && !global[addEventListener]
+  , document = global.document
+  , addEventListener = 'addEventListener'
+  , removeEventListener = 'removeEventListener'
+  , getBoundingClientRect = 'getBoundingClientRect'
+  , FLOAT_FUDGING = 0.5
+
+  // This library only needs two helper functions:
+  //
+  // The first determines which prefixes of CSS calc we need.
+  // We only need to do this once on startup, when this anonymous function is called.
+  // 
+  // Tests -webkit, -moz and -o prefixes. Modified from StackOverflow:
+  // http://stackoverflow.com/questions/16625140/js-feature-detection-to-detect-the-usage-of-webkit-calc-over-calc/16625167#16625167
+  , calc = (function () {
+        var el
+          , prefixes = ["", "-webkit-", "-moz-", "-o-"]
+
+        for (var i = 0; i < prefixes.length; i++) {
+            el = document.createElement('div')
+            el.style.cssText = "width:" + prefixes[i] + "calc(9px)"
+
+            if (el.style.length) {
+                return prefixes[i] + "calc"
+            }
+        }
+    })()
+
+  // The second helper function allows elements and string selectors to be used
+  // interchangeably. In either case an element is returned. This allows us to
+  // do `Split(elem1, elem2)` as well as `Split('#id1', '#id2')`.
+  , elementOrSelector = function (el) {
+        if (typeof el === 'string' || el instanceof String) {
+            return document.querySelector(el)
+        } else {
+            return el
+        }
+    }
+
+  // The main function to initialize a split. Split.js thinks about each pair
+  // of elements as an independant pair. Dragging the gutter between two elements
+  // only changes the dimensions of elements in that pair. This is key to understanding
+  // how the following functions operate, since each function is bound to a pair.
+  // 
+  // A pair object is shaped like this:
+  // 
+  // {
+  //     a: DOM element,
+  //     b: DOM element,
+  //     aMin: Number,
+  //     bMin: Number,
+  //     dragging: Boolean,
+  //     parent: DOM element,
+  //     isFirst: Boolean,
+  //     isLast: Boolean,
+  //     direction: 'horizontal' | 'vertical'
+  // }
+  //
+  // The basic sequence:
+  // 
+  // 1. Set defaults to something sane. `options` doesn't have to be passed at all.
+  // 2. Initialize a bunch of strings based on the direction we're splitting.
+  //    A lot of the behavior in the rest of the library is paramatized down to
+  //    rely on CSS strings and classes.
+  // 3. Define the dragging helper functions, and a few helpers to go with them.
+  // 4. Loop through the elements while pairing them off. Every pair gets an
+  //    `pair` object, a gutter, and special isFirst/isLast properties.
+  // 5. Actually size the pair elements, insert gutters and attach event listeners.
+  , Split = function (ids, options) {
+    var dimension
+      , i
+      , clientDimension
+      , clientAxis
+      , position
+      , gutterClass
+      , paddingA
+      , paddingB
+      , pairs = []
+
+    // 1. Set defaults to something sane. `options` doesn't have to be passed at all,
+    // so create an options object if none exists. Pixel values 10, 100 and 30 are
+    // arbitrary but feel natural.
+    options = typeof options !== 'undefined' ?  options : {}
+
+    if (typeof options.gutterSize === 'undefined') options.gutterSize = 10
+    if (typeof options.minSize === 'undefined') options.minSize = 100
+    if (typeof options.snapOffset === 'undefined') options.snapOffset = 30
+    if (typeof options.direction === 'undefined') options.direction = 'horizontal'
+    if (typeof options.elementStyle === 'undefined') options.elementStyle = function (dimension, size, gutterSize) {
+        var style = {}
+
+        if (typeof size !== 'string' && !(size instanceof String)) {
+            if (!isIE8) {
+                style[dimension] = calc + '(' + size + '% - ' + gutterSize + 'px)'
+            } else {
+                style[dimension] = size + '%'
+            }
+        } else {
+            style[dimension] = size
+        }
+
+        return style
+    }
+    if (typeof options.gutterStyle === 'undefined') options.gutterStyle = function (dimension, gutterSize) {
+        var style = {}
+
+        style[dimension] = gutterSize + 'px'
+
+        return style
+    }
+
+    // 2. Initialize a bunch of strings based on the direction we're splitting.
+    // A lot of the behavior in the rest of the library is paramatized down to
+    // rely on CSS strings and classes.
+    if (options.direction == 'horizontal') {
+        dimension = 'width'
+        clientDimension = 'clientWidth'
+        clientAxis = 'clientX'
+        position = 'left'
+        gutterClass = 'gutter gutter-horizontal'
+        paddingA = 'paddingLeft'
+        paddingB = 'paddingRight'
+        if (!options.cursor) options.cursor = 'ew-resize'
+    } else if (options.direction == 'vertical') {
+        dimension = 'height'
+        clientDimension = 'clientHeight'
+        clientAxis = 'clientY'
+        position = 'top'
+        gutterClass = 'gutter gutter-vertical'
+        paddingA = 'paddingTop'
+        paddingB = 'paddingBottom'
+        if (!options.cursor) options.cursor = 'ns-resize'
+    }
+
+    // 3. Define the dragging helper functions, and a few helpers to go with them.
+    // Each helper is bound to a pair object that contains it's metadata. This
+    // also makes it easy to store references to listeners that that will be
+    // added and removed.
+    // 
+    // Even though there are no other functions contained in them, aliasing
+    // this to self saves 50 bytes or so since it's used so frequently.
+    //
+    // The pair object saves metadata like dragging state, position and
+    // event listener references.
+    //
+    // startDragging calls `calculateSizes` to store the inital size in the pair object.
+    // It also adds event listeners for mouse/touch events,
+    // and prevents selection while dragging so avoid the selecting text.
+    var startDragging = function (e) {
+            // Alias frequently used variables to save space. 200 bytes.
+            var self = this
+              , a = self.a
+              , b = self.b
+
+            // Call the onDragStart callback.
+            if (!self.dragging && options.onDragStart) {
+                options.onDragStart()
+            }
+
+            // Don't actually drag the element. We emulate that in the drag function.
+            e.preventDefault()
+
+            // Set the dragging property of the pair object.
+            self.dragging = true
+
+            // Create two event listeners bound to the same pair object and store
+            // them in the pair object.
+            self.move = drag.bind(self)
+            self.stop = stopDragging.bind(self)
+
+            // All the binding. `window` gets the stop events in case we drag out of the elements.
+            global[addEventListener]('mouseup', self.stop)
+            global[addEventListener]('touchend', self.stop)
+            global[addEventListener]('touchcancel', self.stop)
+
+            self.parent[addEventListener]('mousemove', self.move)
+            self.parent[addEventListener]('touchmove', self.move)
+
+            // Disable selection. Disable!
+            a[addEventListener]('selectstart', noop)
+            a[addEventListener]('dragstart', noop)
+            b[addEventListener]('selectstart', noop)
+            b[addEventListener]('dragstart', noop)
+
+            a.style.userSelect = 'none'
+            a.style.webkitUserSelect = 'none'
+            a.style.MozUserSelect = 'none'
+            a.style.pointerEvents = 'none'
+
+            b.style.userSelect = 'none'
+            b.style.webkitUserSelect = 'none'
+            b.style.MozUserSelect = 'none'
+            b.style.pointerEvents = 'none'
+
+            // Set the cursor, both on the gutter and the parent element.
+            // Doing only a, b and gutter causes flickering.
+            self.gutter.style.cursor = options.cursor
+            self.parent.style.cursor = options.cursor
+
+            // Cache the initial sizes of the pair.
+            calculateSizes.call(self)
+        }
+
+      // stopDragging is very similar to startDragging in reverse.
+      , stopDragging = function () {
+            var self = this
+              , a = self.a
+              , b = self.b
+
+            if (self.dragging && options.onDragEnd) {
+                options.onDragEnd()
+            }
+
+            self.dragging = false
+
+            // Remove the stored event listeners. This is why we store them.
+            global[removeEventListener]('mouseup', self.stop)
+            global[removeEventListener]('touchend', self.stop)
+            global[removeEventListener]('touchcancel', self.stop)
+
+            self.parent[removeEventListener]('mousemove', self.move)
+            self.parent[removeEventListener]('touchmove', self.move)
+
+            // Delete them once they are removed. I think this makes a difference
+            // in memory usage with a lot of splits on one page. But I don't know for sure.
+            delete self.stop
+            delete self.move
+
+            a[removeEventListener]('selectstart', noop)
+            a[removeEventListener]('dragstart', noop)
+            b[removeEventListener]('selectstart', noop)
+            b[removeEventListener]('dragstart', noop)
+
+            a.style.userSelect = ''
+            a.style.webkitUserSelect = ''
+            a.style.MozUserSelect = ''
+            a.style.pointerEvents = ''
+
+            b.style.userSelect = ''
+            b.style.webkitUserSelect = ''
+            b.style.MozUserSelect = ''
+            b.style.pointerEvents = ''
+
+            self.gutter.style.cursor = ''
+            self.parent.style.cursor = ''
+        }
+
+      // drag, where all the magic happens. The logic is really quite simple:
+      // 
+      // 1. Ignore if the pair is not dragging.
+      // 2. Get the offset of the event.
+      // 3. Snap offset to min if within snappable range (within min + snapOffset).
+      // 4. Actually adjust each element in the pair to offset.
+      // 
+      // ---------------------------------------------------------------------
+      // |    | <- this.aMin               ||              this.bMin -> |    |
+      // |    |  | <- this.snapOffset      ||     this.snapOffset -> |  |    |
+      // |    |  |                         ||                        |  |    |
+      // |    |  |                         ||                        |  |    |
+      // ---------------------------------------------------------------------
+      // | <- this.start                                        this.size -> |
+      , drag = function (e) {
+            var offset
+
+            if (!this.dragging) return
+
+            // Get the offset of the event from the first side of the
+            // pair `this.start`. Supports touch events, but not multitouch, so only the first
+            // finger `touches[0]` is counted.
+            if ('touches' in e) {
+                offset = e.touches[0][clientAxis] - this.start
+            } else {
+                offset = e[clientAxis] - this.start
+            }
+
+            // If within snapOffset of min or max, set offset to min or max.
+            // snapOffset buffers aMin and bMin, so logic is opposite for both.
+            // Include the appropriate gutter sizes to prevent overflows.
+            if (offset <= this.aMin + options.snapOffset + this.aGutterSize) {
+                offset = this.aMin + this.aGutterSize
+            } else if (offset >= this.size - (this.bMin + options.snapOffset + this.bGutterSize)) {
+                offset = this.size - (this.bMin + this.bGutterSize)
+            }
+
+            offset = offset - FLOAT_FUDGING
+
+            // Actually adjust the size.
+            adjust.call(this, offset)
+
+            // Call the drag callback continously. Don't do anything too intensive
+            // in this callback.
+            if (options.onDrag) {
+                options.onDrag()
+            }
+        }
+
+      // Cache some important sizes when drag starts, so we don't have to do that
+      // continously:
+      // 
+      // `size`: The total size of the pair. First element + second element + first gutter + second gutter.
+      // `percentage`: The percentage between 0-100 that the pair occupies in the parent.
+      // `start`: The leading side of the first element.
+      //
+      // ------------------------------------------------ - - - - - - - - - - -
+      // |      aGutterSize -> |||                      |                     |
+      // |                     |||                      |                     |
+      // |                     |||                      |                     |
+      // |                     ||| <- bGutterSize       |                     |
+      // ------------------------------------------------ - - - - - - - - - - -
+      // | <- start                             size -> |       parentSize -> |
+      , calculateSizes = function () {
+            // Figure out the parent size minus padding.
+            var computedStyle = global.getComputedStyle(this.parent)
+              , parentSize = this.parent[clientDimension] - parseFloat(computedStyle[paddingA]) - parseFloat(computedStyle[paddingB])
+
+            this.size = this.a[getBoundingClientRect]()[dimension] + this.b[getBoundingClientRect]()[dimension] + this.aGutterSize + this.bGutterSize
+            this.percentage = Math.min(this.size / parentSize * 100, 100)
+            this.start = this.a[getBoundingClientRect]()[position]
+        }
+
+      // Actually adjust the size of elements `a` and `b` to `offset` while dragging.
+      // calc is used to allow calc(percentage + gutterpx) on the whole split instance,
+      // which allows the viewport to be resized without additional logic.
+      // Element a's size is the same as offset. b's size is total size - a size.
+      // Both sizes are calculated from the initial parent percentage, then the gutter size is subtracted.
+      , adjust = function (offset) {
+            setElementSize(this.a, (offset / this.size * this.percentage), this.aGutterSize)
+            setElementSize(this.b, (this.percentage - (offset / this.size * this.percentage)), this.bGutterSize)
+        }
+      , setElementSize = function (el, size, gutterSize) {
+            // Split.js allows setting sizes via numbers (ideally), or if you must,
+            // by string, like '300px'. This is less than ideal, because it breaks
+            // the fluid layout that `calc(% - px)` provides. You're on your own if you do that,
+            // make sure you calculate the gutter size by hand.
+            var style = options.elementStyle(dimension, size, gutterSize)
+              , props = Object.keys(style)
+
+            for (var i = 0; i < props.length; i++) {
+                el.style[props[i]] = style[props[i]]
+            }
+        }
+      , setGutterSize = function (gutter, gutterSize) {
+            var style = options.gutterStyle(dimension, gutterSize)
+              , props = Object.keys(style)
+
+            for (var i = 0; i < props.length; i++) {
+                gutter.style[props[i]] = style[props[i]]
+            }
+        }
+
+      // No-op function to prevent default. Used to prevent selection.
+      , noop = function () { return false }
+
+      // All DOM elements in the split should have a common parent. We can grab
+      // the first elements parent and hope users read the docs because the
+      // behavior will be whacky otherwise.
+      , parent = elementOrSelector(ids[0]).parentNode
+
+    // Set default options.sizes to equal percentages of the parent element.
+    if (!options.sizes) {
+        var percent = 100 / ids.length
+
+        options.sizes = []
+
+        for (i = 0; i < ids.length; i++) {
+            options.sizes.push(percent)
+        }
+    }
+
+    // Standardize minSize to an array if it isn't already. This allows minSize
+    // to be passed as a number.
+    if (!Array.isArray(options.minSize)) {
+        var minSizes = []
+
+        for (i = 0; i < ids.length; i++) {
+            minSizes.push(options.minSize)
+        }
+
+        options.minSize = minSizes
+    }
+
+    // 5. Loop through the elements while pairing them off. Every pair gets a
+    // `pair` object, a gutter, and isFirst/isLast properties.
+    //
+    // Basic logic:
+    //
+    // - Starting with the second element `i > 0`, create `pair` objects with
+    //   `a = ids[i - 1]` and `b = ids[i]`
+    // - Set gutter sizes based on the _pair_ being first/last. The first and last
+    //   pair have gutterSize / 2, since they only have one half gutter, and not two.
+    // - Create gutter elements and add event listeners.
+    // - Set the size of the elements, minus the gutter sizes.
+    //
+    // -----------------------------------------------------------------------
+    // |     i=0     |         i=1         |        i=2       |      i=3     |
+    // |             |       isFirst       |                  |     isLast   |
+    // |           pair 0                pair 1             pair 2           |
+    // |             |                     |                  |              |
+    // -----------------------------------------------------------------------
+    for (i = 0; i < ids.length; i++) {
+        var el = elementOrSelector(ids[i])
+          , isFirstPair = (i == 1)
+          , isLastPair = (i == ids.length - 1)
+          , size = options.sizes[i]
+          , gutterSize = options.gutterSize
+          , pair
+          , parentFlexDirection = window.getComputedStyle(parent).flexDirection
+          , temp
+
+        if (i > 0) {
+            // Create the pair object with it's metadata.
+            pair = {
+                a: elementOrSelector(ids[i - 1]),
+                b: el,
+                aMin: options.minSize[i - 1],
+                bMin: options.minSize[i],
+                dragging: false,
+                parent: parent,
+                isFirst: isFirstPair,
+                isLast: isLastPair,
+                direction: options.direction
+            }
+
+            // For first and last pairs, first and last gutter width is half.
+            pair.aGutterSize = options.gutterSize
+            pair.bGutterSize = options.gutterSize
+
+            if (isFirstPair) {
+                pair.aGutterSize = options.gutterSize / 2
+            }
+
+            if (isLastPair) {
+                pair.bGutterSize = options.gutterSize / 2
+            }
+
+            // if the parent has a reverse flex-direction, switch the pair elements.
+            if (parentFlexDirection === 'row-reverse' || parentFlexDirection === 'column-reverse') {
+                temp = pair.a;
+                pair.a = pair.b;
+                pair.b = temp;
+            }
+        }
+
+        // Determine the size of the current element. IE8 is supported by
+        // staticly assigning sizes without draggable gutters. Assigns a string
+        // to `size`.
+        // 
+        // IE9 and above
+        if (!isIE8) {
+            // Create gutter elements for each pair.
+            if (i > 0) {
+                var gutter = document.createElement('div')
+
+                gutter.className = gutterClass
+
+                setGutterSize(gutter, gutterSize)
+
+                gutter[addEventListener]('mousedown', startDragging.bind(pair))
+                gutter[addEventListener]('touchstart', startDragging.bind(pair))
+
+                parent.insertBefore(gutter, el)
+
+                pair.gutter = gutter
+            }
+
+            // Half-size gutters for first and last elements.
+            if (i === 0 || i == ids.length - 1) {
+                gutterSize = options.gutterSize / 2
+            }
+        }
+
+        // Set the element size to our determined size.
+        setElementSize(el, size, gutterSize)
+
+        if (i > 0) {
+            var aSize = pair.a[getBoundingClientRect]()[dimension]
+              , bSize = pair.b[getBoundingClientRect]()[dimension]
+
+            if (aSize < pair.aMin) {
+                pair.aMin = aSize
+            }
+
+            if (bSize < pair.bMin) {
+                pair.bMin = bSize
+            }
+        }
+
+        // After the first iteration, and we have a pair object, append it to the
+        // list of pairs.
+        if (i > 0) {
+            pairs.push(pair)
+        }
+    }
+
+    return {
+        setSizes: function (sizes) {
+            for (var i = 0; i < sizes.length; i++) {
+                if (i > 0) {
+                    var pair = pairs[i - 1]
+
+                    setElementSize(pair.a, sizes[i - 1], pair.aGutterSize)
+                    setElementSize(pair.b, sizes[i], pair.bGutterSize)
+                }
+            }
+        },
+        getSizes: function () {
+            var sizes = []
+
+            for (var i = 0; i < pairs.length; i++) {
+                var pair = pairs[i]
+                  , computedStyle = global.getComputedStyle(pair.parent)
+                  , parentSize = pair.parent[clientDimension] - parseFloat(computedStyle[paddingA]) - parseFloat(computedStyle[paddingB])
+
+                sizes.push((pair.a[getBoundingClientRect]()[dimension] + pair.aGutterSize) / parentSize * 100)
+
+                if (i === pairs.length - 1) {
+                    sizes.push((pair.b[getBoundingClientRect]()[dimension] + pair.bGutterSize) / parentSize * 100)
+                }
+            }
+
+            return sizes
+        },
+        collapse: function (i) {
+            var pair
+
+            if (i === pairs.length) {
+                pair = pairs[i - 1]
+
+                calculateSizes.call(pair)
+                adjust.call(pair, pair.size - pair.bGutterSize)
+            } else {
+                pair = pairs[i]
+
+                calculateSizes.call(pair)
+                adjust.call(pair, pair.aGutterSize)
+            }
+        },
+        destroy: function () {
+            for (var i = 0; i < pairs.length; i++) {
+                pairs[i].parent.removeChild(pairs[i].gutter)
+                pairs[i].a.style[dimension] = ''
+                pairs[i].b.style[dimension] = ''
+            }
+        }
+    }
+}
+
+// Play nicely with module systems, and the browser too if you include it raw.
+if (typeof exports !== 'undefined') {
+    if (typeof module !== 'undefined' && module.exports) {
+        exports = module.exports = Split
+    }
+    exports.Split = Split
+} else {
+    global.Split = Split
+}
+
+// Call our wrapper function with the current global. In this case, `window`.
+}).call(window);

+ 5 - 3
Playground/package.json

@@ -1,12 +1,14 @@
 {
   "name": "babylonjsplayground",
-  "version": "2.5.0",
+  "version": "2.6.0",
   "description": "Babylon.js is a 3D engine based on webgl and javascript",
   "main": "",
-  "repository": { "url": "https://github.com/BabylonJS/Babylon.js/" },
+  "repository": {
+    "url": "https://github.com/BabylonJS/Babylon.js/"
+  },
   "readme": "https://github.com/BabylonJS/Babylon.js/blob/master/readme.md",
   "license": "(Apache-2.0)",
   "devDependencies": {
     "monaco-editor": "^0.7.0"
   }
-}
+}

+ 30 - 30
Playground/scripts/scripts.txt

@@ -1,30 +1,30 @@
-Basic scene
-Basic elements
-Rotation and scaling
-Materials
-Cameras
-Lights
-Animations
-Sprites
-Collisions
-Intersections
-Picking
-Particles
-Environment
-Height map
-Shadows
-Import meshes
-Actions
-Drag and drop
-Fresnel
-Easing functions
-ProceduralTexture
-Basic sounds
-Sound on mesh
-SSAO rendering pipeline
-Volumetric Light Scattering
-HDR Rendering Pipeline
-Refraction and Reflection
-PBR
-Instanced bones
-Pointer events handling
+basic scene
+basic elements
+rotation and scaling
+materials
+cameras
+lights
+animations
+sprites
+collisions
+intersections
+picking
+particles
+environment
+height map
+shadows
+import meshes
+actions
+drag and drop
+fresnel
+easing functions
+proceduralTexture
+basic sounds
+sound on mesh
+ssao rendering pipeline
+volumetric Light Scattering
+hdr Rendering Pipeline
+refraction and Reflection
+pbr
+instanced bones
+pointer events handling

+ 0 - 146
Playground/splitbox.css

@@ -1,146 +0,0 @@
-x-splitbox {
-  position: relative;
-  display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
-  display: -moz-box;         /* OLD - Firefox 19- (buggy but mostly works) */
-  display: -ms-flexbox;      /* TWEENER - IE 10 */
-  display: -webkit-flex;     /* NEW - Chrome */
-  display: flex;             /* NEW, Spec - Opera 12.1, Firefox 20+ */
-  height: 100%;
-  overflow: hidden;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  -ms-box-sizing: border-box;
-  box-sizing: border-box;
-  -webkit-box-orient: horizontal;
-  -moz-box-orient: horizontal;
-  -ms-box-orient: horizontal;
-  box-orient: horizontal;
-  -webkit-flex-direction: row;
-  -moz-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-}
-
-x-splitbox[direction="column"] {
-  -webkit-box-orient: vertical;
-  -moz-box-orient: vertical;
-  -ms-box-orient: vertical;
-  box-orient: vertical;
-  -webkit-flex-direction: column;
-  -moz-flex-direction: column;
-  -ms-flex-direction: column;
-  flex-direction: column;
-}
-
-x-splitbox > *:not([splitter]) {
-  min-width: 0;
-  min-height: 0;
-  -webkit-box-flex: 1;
-  -moz-box-flex: 1;
-  -webkit-flex: 1;
-  flex: 1;
-  -ms-flex: auto;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  -ms-box-sizing: border-box;
-  box-sizing: border-box;
-}
-
-x-splitbox[dragging], x-splitbox > [splitter] {
-  -moz-user-select: -moz-none;
-  -khtml-user-select: none;
-  -webkit-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-  -webkit-user-drag: none;
-}
-
-x-splitbox > [splitter] {
-  display: block;
-  position: relative;
-  min-width: 0px !important;
-  max-width: 0px !important;
-  cursor: ew-resize;
-  background: #fff;
-  opacity: 0.6;
-}
-
-  x-splitbox > [splitter]:before {
-    content: " ";
-    display: block;
-    position: absolute;
-    width: 0.8em;
-    height: 100%;
-    opacity: 0;
-    background: inherit;
-    -webkit-box-sizing: border-box;
-    -moz-box-sizing: border-box;
-    -ms-box-sizing: border-box;
-    box-sizing: border-box;
-    -webkit-transform: translate(-50%, 0);
-    -ms-transform: translate(-50%, 0);
-    transform: translate(-50%, 0);
-  }
-
-  x-splitbox > [splitter]:after {
-    content: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMWVtIiB3aWR0aD0iMWVtIiB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0Ij48cGF0aCBmaWxsPSJyZ2JhKDAsMCwwLDAuNzUpIiBkPSJNNzU4IDIzNGwyMzIgMjc4LTIzMiAyNzgtNjYtNTQgMTg2LTIyNC0xODYtMjI0ek00NzAgNTU0di04NGg4NHY4NGgtODR6TTcyNiA0NzB2ODRoLTg2di04NGg4NnpNMjk4IDU1NHYtODRoODZ2ODRoLTg2ek0zMzIgMjg4bC0xODYgMjI0IDE4NiAyMjQtNjYgNTQtMjMyLTI3OCAyMzItMjc4eiI+PC9wYXRoPjwvc3ZnPg==');
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    height: 1em;
-    padding: 0.05em;
-    background: inherit;
-    border-radius: 100%;
-    -webkit-box-shadow: 0 1px 1px 0px rgba(0,0,0,0.4);
-    -ms-box-shadow: 0 1px 1px 0px rgba(0,0,0,0.4);
-    box-shadow: 0 1px 1px 0px rgba(0,0,0,0.4);
-    -webkit-transform: translate(-50%, -50%);
-    -ms-transform: translate(-50%, -50%);
-    transform: translate(-50%, -50%);
-  }
-
-  x-splitbox[direction="column"] > [splitter] {
-    cursor: ns-resize;
-    min-width: auto !important;
-    max-width: none !important;
-    min-height: 0px !important;
-    max-height: 0px !important;
-  }
-
-  x-splitbox[direction="column"] > [splitter]:before {
-    width: 100%;
-    height: 0.8em;
-    -webkit-transform: translate(0%, -50%);
-    -ms-transform: translate(0%, -50%);
-    transform: translate(0%, -50%);
-  }
-
-  x-splitbox[direction="column"] > [splitter]:after {
-    -webkit-box-shadow: 1px 0 1px 0px rgba(0,0,0,0.4);
-    -ms-box-shadow: 1px 0 1px 0px rgba(0,0,0,0.4);
-    box-shadow: 1px 0 1px 0px rgba(0,0,0,0.4);
-    -webkit-transform: translate(-50%, -50%) rotate(90deg);
-    -ms-transform: translate(-50%, -50%) rotate(90deg);
-    transform: translate(-50%, -50%) rotate(90deg);
-  }
-
-  x-splitbox > [splitter]:hover, x-splitbox > [splitter][dragging] {
-    opacity: 1;
-    z-index: 2;
-  }
-
-  x-splitbox > [splitter][dragging]:before {
-    opacity: 0.3;
-  }
-
-
-@media screen and (max-device-width: 415px) {
-  x-splitbox > [splitter]:before {
-    display: block;
-  }
-
-    x-splitbox[direction="column"] > [splitter] {
-      display: block;
-    }
-}
-

+ 0 - 116
Playground/splitbox.js

@@ -1,116 +0,0 @@
-(function () {
-
-    function startDrag(node, splitter, event) {
-
-        node.setAttribute('dragging', '');
-        node.xtag.splitter = splitter;
-        splitter.setAttribute('dragging', '');
-        splitter.style.zIndex = node.xtag.splitZ = (node.xtag.splitZ || 0) + 1;
-
-        var props = getProps(node);
-        var lastCoord = event[props.page] - node[props.edge];
-        var next = splitter.nextElementSibling, next = !next.hasAttribute('splitter') && next;
-        var previous = splitter.previousElementSibling, previous = !previous.hasAttribute('splitter') && previous;
-        var startingTotal = next[props.size] + previous[props.size];
-
-        setPercents(node, props);
-
-        node.xtag.drag = xtag.addEvent(node, 'move', function (e) {
-            var delta = e[props.page] - node[props.edge] - lastCoord;
-            var nextSize = next[props.size];
-            var prevSize = previous[props.size];
-            var nextMod = nextSize - delta;
-            var prevMod = prevSize + delta;
-
-            if (delta > 0) {
-                if (nextSize > 0) {
-                    if (nextMod <= 0 || prevMod >= startingTotal || prevMod > startingTotal || nextMod > startingTotal) {
-                        prevMod = startingTotal;
-                        nextMod = 0;
-                    }
-                    setMinMax(next, props, nextMod);
-                    setMinMax(previous, props, prevMod);
-                }
-            }
-
-            else if (delta < 0) {
-                if (prevSize > 0) {
-                    if (prevMod <= 0 || nextMod >= startingTotal || prevMod > startingTotal || nextMod > startingTotal) {
-                        nextMod = startingTotal;
-                        prevMod = 0;
-                    }
-                    setMinMax(next, props, nextMod);
-                    setMinMax(previous, props, prevMod);
-                }
-            }
-
-            lastCoord = e[props.page] - node[props.edge];
-        });
-    }
-
-    function getProps(node) {
-        return node.xtag.props = (node.direction == 'column') ? {
-            page: 'pageY',
-            size: 'clientHeight',
-            edge: 'clientTop',
-            parentSize: node.clientHeight
-        } : {
-            page: 'pageX',
-            size: 'clientWidth',
-            edge: 'clientLeft',
-            parentSize: node.clientWidth
-        };
-    }
-
-    function setPercents(node, props, setup) {
-        node.xtag.panels = xtag.queryChildren(node, '*:not([splitter])').map(function (el) {
-            setMinMax(el, props, el[props.size], setup);
-            return el;
-        });
-    }
-
-    function setMinMax(panel, props, value, setup) {
-        panel.style.flex = panel.style[xtag.prefix.lowercase + 'Flex'] = (setup ? '0 0 ' : '1 1 ') + (value / props.parentSize) * 100 + '%';
-    }
-
-    function stopDrag(node) {
-        if (node.xtag.drag) {
-            xtag.removeEvent(node, node.xtag.drag);
-            node.removeAttribute('dragging');
-            node.xtag.splitter.removeAttribute('dragging');
-            node.xtag.splitter = null;
-            node.xtag.drag = null;
-        }
-    }
-
-    xtag.addEvent(window, 'tapend', function (e) {
-        xtag.query(document, 'x-splitbox[dragging]').forEach(stopDrag);
-    })
-
-    xtag.register('x-splitbox', {
-        events: {
-            'tapstart:delegate(x-splitbox > [splitter])': function (e) {
-                startDrag(e.currentTarget, this, e);
-            },
-            dragstart: function (e) {
-                if (this.hasAttribute('dragging')) {
-                    e.preventDefault();
-                    return false;
-                }
-            },
-            contextmemu: function (e) {
-                e.preventDefault();
-            }
-        },
-        accessors: {
-            direction: {
-                attribute: { def: 'row' },
-                set: function (direction) {
-                    setPercents(this, getProps(this), true);
-                }
-            }
-        }
-    });
-
-})();
-

+ 55 - 0
Playground/test.html

@@ -0,0 +1,55 @@
+<div class="navbar-inner" id="topbar">
+    <a class="brand largeOnly" href="#" id="mainTitle">Babylon.js Playground</a>
+    <div class="btn-group">
+        <button class="btn" id="runButton">Run</button>
+        <button class="btn" id="saveButton">Save</button>
+        <button class="btn desktopOnly" id="zipButton">Get .zip</button>
+        <button class="btn desktopOnly" id="newButton">New</button>
+        <button class="btn desktopOnly" id="clearButton">Clear</button>
+    </div>
+    <div class="btn-group desktopOnly">
+        <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+            <span id="currentFontSize">Font: 12</span>
+            <span class="caret"></span>
+        </a>
+        <ul class="dropdown-menu" id="sizeList">
+            <li><a href="#" onclick="setFontSize(12);">12</a></li>
+            <li><a href="#" onclick="setFontSize(14);">14</a></li>
+            <li><a href="#" onclick="setFontSize(16);">16</a></li>
+            <li><a href="#" onclick="setFontSize(18);">18</a></li>
+            <li><a href="#" onclick="setFontSize(20);">20</a></li>
+            <li><a href="#" onclick="setFontSize(22);">22</a></li>
+        </ul>
+    </div>
+    <div class="btn-group desktopOnly">
+        <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+            <span id="currentVersion">Version: Latest</span>
+            <span class="caret"></span>
+        </a>
+        <ul class="dropdown-menu" id="versionList">
+            <li><a href="#" onclick="setVersion('latest');">Latest</a></li>
+            <li><a href="#" onclick="setVersion('2.5');">2.5</a></li>
+        </ul>
+    </div>
+    <div class="btn-group">
+        <label class="btn btn-sm active">
+                    <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
+                </label>
+        <button class="btn btn-sm" id="metadataButton">+Meta data</button>
+        <button class="btn btn-sm" id="editorButton">-Editor</button>
+        <button class="btn btn-sm" id="debugButton">+Debug layer</button>
+    </div>
+    <div class="btn-group pull-right">
+        <button class="btn" id="fullscreenButton">Fullscreen</button>
+    </div>
+    <div class="btn-group pull-right">
+        <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+            <span id="currentScript">Predefined scripts</span>
+            <span class="caret"></span>
+        </a>
+        <ul class="dropdown-menu" id="scriptsList"></ul>
+    </div>
+</div>
+<div class="save-message" id="saveMessage">
+    This PG has no metadata. Click save to add them.
+</div>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 2
Playground/xtag.min.js


+ 21 - 8
Tools/Gulp/config.json

@@ -510,12 +510,7 @@
             },
             {
                 "files": [
-                    "../../loaders/src/glTF/babylon.glTFFileLoader.ts"
-                ],
-                "output": "babylon.glTFFileLoader.js"
-            },
-            {
-                "files": [
+                    "../../loaders/src/glTF/babylon.glTFFileLoader.ts",
                     "../../loaders/src/glTF/1.0/babylon.glTFLoaderInterfaces.ts",
                     "../../loaders/src/glTF/1.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/1.0/babylon.glTFLoaderUtils.ts",
@@ -523,17 +518,35 @@
                     "../../loaders/src/glTF/1.0/babylon.glTFBinaryExtension.ts",
                     "../../loaders/src/glTF/1.0/babylon.glTFMaterialsCommonExtension.ts"
                 ],
-                "output": "babylon.glTF1Loader.js"
+                "output": "babylon.glTF1FileLoader.js"
+            },
+            {
+                "files": [
+                    "../../loaders/src/glTF/babylon.glTFFileLoader.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts"
+                ],
+                "output": "babylon.glTF2FileLoader.js"
             },
             {
                 "files": [
+                    "../../loaders/src/glTF/babylon.glTFFileLoader.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFLoaderInterfaces.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFLoader.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFLoaderUtils.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFLoaderExtension.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFBinaryExtension.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFMaterialsCommonExtension.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts"
                 ],
-                "output": "babylon.glTF2Loader.js"
+                "output": "babylon.glTFFileLoader.js"
             }
         ],
         "build": {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 34 - 1
dist/preview release/babylon.core.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 5607 - 5604
dist/preview release/babylon.d.ts


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 44 - 0
dist/preview release/babylon.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 66 - 46
dist/preview release/babylon.max.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 5607 - 5604
dist/preview release/babylon.module.d.ts


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 45 - 1
dist/preview release/babylon.noworker.js


+ 523 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -0,0 +1,523 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    interface IGLTFLoaderData {
+        json: Object;
+        bin: ArrayBufferView;
+    }
+    interface IGLTFLoader {
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+    }
+    class GLTFFileLoader implements ISceneLoaderPluginAsync {
+        static GLTFLoaderV1: IGLTFLoader;
+        static GLTFLoaderV2: IGLTFLoader;
+        static HomogeneousCoordinates: boolean;
+        static IncrementalLoading: boolean;
+        extensions: ISceneLoaderPluginExtensions;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): void;
+        private static _parse(data);
+        private _getLoader(loaderData);
+        private static _parseBinary(data);
+        private static _parseV1(binaryReader);
+        private static _parseV2(binaryReader);
+        private static _parseVersion(version);
+        private static _compareVersion(a, b);
+        private static _decodeBufferToText(view);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    /**
+    * Enums
+    */
+    enum EComponentType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        FLOAT = 5126,
+    }
+    enum EShaderType {
+        FRAGMENT = 35632,
+        VERTEX = 35633,
+    }
+    enum EParameterType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        INT = 5124,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+        FLOAT_VEC2 = 35664,
+        FLOAT_VEC3 = 35665,
+        FLOAT_VEC4 = 35666,
+        INT_VEC2 = 35667,
+        INT_VEC3 = 35668,
+        INT_VEC4 = 35669,
+        BOOL = 35670,
+        BOOL_VEC2 = 35671,
+        BOOL_VEC3 = 35672,
+        BOOL_VEC4 = 35673,
+        FLOAT_MAT2 = 35674,
+        FLOAT_MAT3 = 35675,
+        FLOAT_MAT4 = 35676,
+        SAMPLER_2D = 35678,
+    }
+    enum ETextureWrapMode {
+        CLAMP_TO_EDGE = 33071,
+        MIRRORED_REPEAT = 33648,
+        REPEAT = 10497,
+    }
+    enum ETextureFilterType {
+        NEAREST = 9728,
+        LINEAR = 9728,
+        NEAREST_MIPMAP_NEAREST = 9984,
+        LINEAR_MIPMAP_NEAREST = 9985,
+        NEAREST_MIPMAP_LINEAR = 9986,
+        LINEAR_MIPMAP_LINEAR = 9987,
+    }
+    enum ETextureFormat {
+        ALPHA = 6406,
+        RGB = 6407,
+        RGBA = 6408,
+        LUMINANCE = 6409,
+        LUMINANCE_ALPHA = 6410,
+    }
+    enum ECullingType {
+        FRONT = 1028,
+        BACK = 1029,
+        FRONT_AND_BACK = 1032,
+    }
+    enum EBlendingFunction {
+        ZERO = 0,
+        ONE = 1,
+        SRC_COLOR = 768,
+        ONE_MINUS_SRC_COLOR = 769,
+        DST_COLOR = 774,
+        ONE_MINUS_DST_COLOR = 775,
+        SRC_ALPHA = 770,
+        ONE_MINUS_SRC_ALPHA = 771,
+        DST_ALPHA = 772,
+        ONE_MINUS_DST_ALPHA = 773,
+        CONSTANT_COLOR = 32769,
+        ONE_MINUS_CONSTANT_COLOR = 32770,
+        CONSTANT_ALPHA = 32771,
+        ONE_MINUS_CONSTANT_ALPHA = 32772,
+        SRC_ALPHA_SATURATE = 776,
+    }
+    /**
+    * Interfaces
+    */
+    interface IGLTFProperty {
+        extensions?: Object;
+        extras?: Object;
+    }
+    interface IGLTFChildRootProperty extends IGLTFProperty {
+        name?: string;
+    }
+    interface IGLTFAccessor extends IGLTFChildRootProperty {
+        bufferView: string;
+        byteOffset: number;
+        byteStride: number;
+        count: number;
+        type: string;
+        componentType: EComponentType;
+        max?: number[];
+        min?: number[];
+        name?: string;
+    }
+    interface IGLTFBufferView extends IGLTFChildRootProperty {
+        buffer: string;
+        byteOffset: number;
+        byteLength: number;
+        target?: number;
+    }
+    interface IGLTFBuffer extends IGLTFChildRootProperty {
+        uri: string;
+        byteLength?: number;
+        type?: string;
+    }
+    interface IGLTFShader extends IGLTFChildRootProperty {
+        uri: string;
+        type: EShaderType;
+    }
+    interface IGLTFProgram extends IGLTFChildRootProperty {
+        attributes: string[];
+        fragmentShader: string;
+        vertexShader: string;
+    }
+    interface IGLTFTechniqueParameter {
+        type: number;
+        count?: number;
+        semantic?: string;
+        node?: string;
+        value?: number | boolean | string | Array<any>;
+        source?: string;
+        babylonValue?: any;
+    }
+    interface IGLTFTechniqueCommonProfile {
+        lightingModel: string;
+        texcoordBindings: Object;
+        parameters?: Array<any>;
+    }
+    interface IGLTFTechniqueStatesFunctions {
+        blendColor?: number[];
+        blendEquationSeparate?: number[];
+        blendFuncSeparate?: number[];
+        colorMask: boolean[];
+        cullFace: number[];
+    }
+    interface IGLTFTechniqueStates {
+        enable: number[];
+        functions: IGLTFTechniqueStatesFunctions;
+    }
+    interface IGLTFTechnique extends IGLTFChildRootProperty {
+        parameters: Object;
+        program: string;
+        attributes: Object;
+        uniforms: Object;
+        states: IGLTFTechniqueStates;
+    }
+    interface IGLTFMaterial extends IGLTFChildRootProperty {
+        technique?: string;
+        values: string[];
+    }
+    interface IGLTFMeshPrimitive extends IGLTFProperty {
+        attributes: Object;
+        indices: string;
+        material: string;
+        mode?: number;
+    }
+    interface IGLTFMesh extends IGLTFChildRootProperty {
+        primitives: IGLTFMeshPrimitive[];
+    }
+    interface IGLTFImage extends IGLTFChildRootProperty {
+        uri: string;
+    }
+    interface IGLTFSampler extends IGLTFChildRootProperty {
+        magFilter?: number;
+        minFilter?: number;
+        wrapS?: number;
+        wrapT?: number;
+    }
+    interface IGLTFTexture extends IGLTFChildRootProperty {
+        sampler: string;
+        source: string;
+        format?: ETextureFormat;
+        internalFormat?: ETextureFormat;
+        target?: number;
+        type?: number;
+        babylonTexture?: Texture;
+    }
+    interface IGLTFAmbienLight {
+        color?: number[];
+    }
+    interface IGLTFDirectionalLight {
+        color?: number[];
+    }
+    interface IGLTFPointLight {
+        color?: number[];
+        constantAttenuation?: number;
+        linearAttenuation?: number;
+        quadraticAttenuation?: number;
+    }
+    interface IGLTFSpotLight {
+        color?: number[];
+        constantAttenuation?: number;
+        fallOfAngle?: number;
+        fallOffExponent?: number;
+        linearAttenuation?: number;
+        quadraticAttenuation?: number;
+    }
+    interface IGLTFLight extends IGLTFChildRootProperty {
+        type: string;
+    }
+    interface IGLTFCameraOrthographic {
+        xmag: number;
+        ymag: number;
+        zfar: number;
+        znear: number;
+    }
+    interface IGLTFCameraPerspective {
+        aspectRatio: number;
+        yfov: number;
+        zfar: number;
+        znear: number;
+    }
+    interface IGLTFCamera extends IGLTFChildRootProperty {
+        type: string;
+    }
+    interface IGLTFAnimationChannelTarget {
+        id: string;
+        path: string;
+    }
+    interface IGLTFAnimationChannel {
+        sampler: string;
+        target: IGLTFAnimationChannelTarget;
+    }
+    interface IGLTFAnimationSampler {
+        input: string;
+        output: string;
+        interpolation?: string;
+    }
+    interface IGLTFAnimation extends IGLTFChildRootProperty {
+        channels?: IGLTFAnimationChannel[];
+        parameters?: Object;
+        samplers?: Object;
+    }
+    interface IGLTFNodeInstanceSkin {
+        skeletons: string[];
+        skin: string;
+        meshes: string[];
+    }
+    interface IGLTFSkins extends IGLTFChildRootProperty {
+        bindShapeMatrix: number[];
+        inverseBindMatrices: string;
+        jointNames: string[];
+        babylonSkeleton?: Skeleton;
+    }
+    interface IGLTFNode extends IGLTFChildRootProperty {
+        camera?: string;
+        children: string[];
+        skin?: string;
+        jointName?: string;
+        light?: string;
+        matrix: number[];
+        mesh?: string;
+        meshes?: string[];
+        rotation?: number[];
+        scale?: number[];
+        translation?: number[];
+        babylonNode?: Node;
+    }
+    interface IGLTFScene extends IGLTFChildRootProperty {
+        nodes: string[];
+    }
+    /**
+    * Runtime
+    */
+    interface IGLTFRuntime {
+        extensions: Object;
+        accessors: Object;
+        buffers: Object;
+        bufferViews: Object;
+        meshes: Object;
+        lights: Object;
+        cameras: Object;
+        nodes: Object;
+        images: Object;
+        textures: Object;
+        shaders: Object;
+        programs: Object;
+        samplers: Object;
+        techniques: Object;
+        materials: Object;
+        animations: Object;
+        skins: Object;
+        currentScene?: Object;
+        scenes: Object;
+        extensionsUsed: string[];
+        extensionsRequired?: string[];
+        buffersCount: number;
+        shaderscount: number;
+        scene: Scene;
+        rootUrl: string;
+        loadedBufferCount: number;
+        loadedBufferViews: {
+            [name: string]: ArrayBufferView;
+        };
+        loadedShaderCount: number;
+        importOnlyMeshes: boolean;
+        importMeshesNames?: string[];
+        dummyNodes: Node[];
+    }
+    /**
+    * Bones
+    */
+    interface INodeToRoot {
+        bone: Bone;
+        node: IGLTFNode;
+        id: string;
+    }
+    interface IJointNode {
+        node: IGLTFNode;
+        id: string;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    /**
+    * Implementation of the base glTF spec
+    */
+    class GLTFLoaderBase {
+        static CreateRuntime(parsedData: any, scene: Scene, rootUrl: string): IGLTFRuntime;
+        static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): void;
+        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): void;
+        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): void;
+        static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): void;
+        static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void;
+    }
+    /**
+    * glTF V1 Loader
+    */
+    class GLTFLoader implements IGLTFLoader {
+        static Extensions: {
+            [name: string]: GLTFLoaderExtension;
+        };
+        static RegisterExtension(extension: GLTFLoaderExtension): void;
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void, onProgress?: () => void): boolean;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void;
+        private _loadShadersAsync(gltfRuntime, onload);
+        private _loadBuffersAsync(gltfRuntime, onload, onProgress?);
+        private _createNodes(gltfRuntime);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    /**
+    * Utils functions for GLTF
+    */
+    class GLTFUtils {
+        /**
+         * Sets the given "parameter" matrix
+         * @param scene: the {BABYLON.Scene} object
+         * @param source: the source node where to pick the matrix
+         * @param parameter: the GLTF technique parameter
+         * @param uniformName: the name of the shader's uniform
+         * @param shaderMaterial: the shader material
+         */
+        static SetMatrix(scene: Scene, source: Node, parameter: IGLTFTechniqueParameter, uniformName: string, shaderMaterial: ShaderMaterial | Effect): void;
+        /**
+         * Sets the given "parameter" matrix
+         * @param shaderMaterial: the shader material
+         * @param uniform: the name of the shader's uniform
+         * @param value: the value of the uniform
+         * @param type: the uniform's type (EParameterType FLOAT, VEC2, VEC3 or VEC4)
+         */
+        static SetUniform(shaderMaterial: ShaderMaterial | Effect, uniform: string, value: any, type: number): boolean;
+        /**
+        * If the uri is a base64 string
+        * @param uri: the uri to test
+        */
+        static IsBase64(uri: string): boolean;
+        /**
+        * Decode the base64 uri
+        * @param uri: the uri to decode
+        */
+        static DecodeBase64(uri: string): ArrayBuffer;
+        /**
+        * Returns the wrap mode of the texture
+        * @param mode: the mode value
+        */
+        static GetWrapMode(mode: number): number;
+        /**
+         * Returns the byte stride giving an accessor
+         * @param accessor: the GLTF accessor objet
+         */
+        static GetByteStrideFromType(accessor: IGLTFAccessor): number;
+        /**
+         * Returns the texture filter mode giving a mode value
+         * @param mode: the filter mode value
+         */
+        static GetTextureFilterMode(mode: number): ETextureFilterType;
+        static GetBufferFromBufferView(gltfRuntime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): ArrayBufferView;
+        /**
+         * Returns a buffer from its accessor
+         * @param gltfRuntime: the GLTF runtime
+         * @param accessor: the GLTF accessor
+         */
+        static GetBufferFromAccessor(gltfRuntime: IGLTFRuntime, accessor: IGLTFAccessor): any;
+        /**
+         * Decodes a buffer view into a string
+         * @param view: the buffer view
+         */
+        static DecodeBufferToText(view: ArrayBufferView): string;
+        /**
+         * Returns the default material of gltf. Related to
+         * https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a-default-material
+         * @param scene: the Babylon.js scene
+         */
+        static GetDefaultMaterial(scene: Scene): ShaderMaterial;
+        private static _DefaultMaterial;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    abstract class GLTFLoaderExtension {
+        private _name;
+        constructor(name: string);
+        readonly name: string;
+        /**
+        * Defines an override for loading the runtime
+        * Return true to stop further extensions from loading the runtime
+        */
+        loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean;
+        /**
+         * Defines an onverride for creating gltf runtime
+         * Return true to stop further extensions from creating the runtime
+         */
+        loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): boolean;
+        /**
+        * Defines an override for loading buffers
+        * Return true to stop further extensions from loading this buffer
+        */
+        loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): boolean;
+        /**
+        * Defines an override for loading texture buffers
+        * Return true to stop further extensions from loading this texture data
+        */
+        loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
+        /**
+        * Defines an override for creating textures
+        * Return true to stop further extensions from loading this texture
+        */
+        createTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): boolean;
+        /**
+        * Defines an override for loading shader strings
+        * Return true to stop further extensions from loading this shader data
+        */
+        loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): boolean;
+        /**
+        * Defines an override for loading materials
+        * Return true to stop further extensions from loading this material
+        */
+        loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): boolean;
+        static LoadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): void;
+        static LoadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): void;
+        static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (bufferView: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): void;
+        static LoadTextureAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (texture: Texture) => void, onError: () => void): void;
+        static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderData: string) => void, onError: () => void): void;
+        static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void;
+        private static LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
+        private static CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
+        private static ApplyExtensions(func, defaultFunc);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    class GLTFBinaryExtension extends GLTFLoaderExtension {
+        private _bin;
+        constructor();
+        loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean;
+        loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
+        loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
+        loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): boolean;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    class GLTFMaterialsCommonExtension extends GLTFLoaderExtension {
+        constructor();
+        loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): boolean;
+        loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): boolean;
+        private _loadTexture(gltfRuntime, id, material, propertyPath, onError);
+    }
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2378 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


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

@@ -0,0 +1,429 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON {
+    interface IGLTFLoaderData {
+        json: Object;
+        bin: ArrayBufferView;
+    }
+    interface IGLTFLoader {
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+    }
+    class GLTFFileLoader implements ISceneLoaderPluginAsync {
+        static GLTFLoaderV1: IGLTFLoader;
+        static GLTFLoaderV2: IGLTFLoader;
+        static HomogeneousCoordinates: boolean;
+        static IncrementalLoading: boolean;
+        extensions: ISceneLoaderPluginExtensions;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): void;
+        private static _parse(data);
+        private _getLoader(loaderData);
+        private static _parseBinary(data);
+        private static _parseV1(binaryReader);
+        private static _parseV2(binaryReader);
+        private static _parseVersion(version);
+        private static _compareVersion(a, b);
+        private static _decodeBufferToText(view);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    /**
+    * Enums
+    */
+    enum EBufferViewTarget {
+        ARRAY_BUFFER = 34962,
+        ELEMENT_ARRAY_BUFFER = 34963,
+    }
+    enum EComponentType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+    }
+    enum EMeshPrimitiveMode {
+        POINTS = 0,
+        LINES = 1,
+        LINE_LOOP = 2,
+        LINE_STRIP = 3,
+        TRIANGLES = 4,
+        TRIANGLE_STRIP = 5,
+        TRIANGLE_FAN = 6,
+    }
+    enum EParameterType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        INT = 5124,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+        FLOAT_VEC2 = 35664,
+        FLOAT_VEC3 = 35665,
+        FLOAT_VEC4 = 35666,
+        INT_VEC2 = 35667,
+        INT_VEC3 = 35668,
+        INT_VEC4 = 35669,
+        BOOL = 35670,
+        BOOL_VEC2 = 35671,
+        BOOL_VEC3 = 35672,
+        BOOL_VEC4 = 35673,
+        FLOAT_MAT2 = 35674,
+        FLOAT_MAT3 = 35675,
+        FLOAT_MAT4 = 35676,
+        SAMPLER_2D = 35678,
+    }
+    enum ETextureMagFilter {
+        NEAREST = 9728,
+        LINEAR = 9729,
+    }
+    enum ETextureMinFilter {
+        NEAREST = 9728,
+        LINEAR = 9729,
+        NEAREST_MIPMAP_NEAREST = 9984,
+        LINEAR_MIPMAP_NEAREST = 9985,
+        NEAREST_MIPMAP_LINEAR = 9986,
+        LINEAR_MIPMAP_LINEAR = 9987,
+    }
+    enum ETextureFormat {
+        ALPHA = 6406,
+        RGB = 6407,
+        RGBA = 6408,
+        LUMINANCE = 6409,
+        LUMINANCE_ALPHA = 6410,
+    }
+    enum ETextureTarget {
+        TEXTURE_2D = 3553,
+    }
+    enum ETextureType {
+        UNSIGNED_BYTE = 5121,
+        UNSIGNED_SHORT_5_6_5 = 33635,
+        UNSIGNED_SHORT_4_4_4_4 = 32819,
+        UNSIGNED_SHORT_5_5_5_1 = 32820,
+    }
+    enum ETextureWrapMode {
+        CLAMP_TO_EDGE = 33071,
+        MIRRORED_REPEAT = 33648,
+        REPEAT = 10497,
+    }
+    /**
+    * Interfaces
+    */
+    interface IGLTFProperty {
+        extensions?: Object;
+        extras?: any;
+    }
+    interface IGLTFChildRootProperty extends IGLTFProperty {
+        name?: string;
+    }
+    interface IGLTFAccessorSparseIndices extends IGLTFProperty {
+        bufferView: number;
+        byteOffset?: number;
+        componentType: EComponentType;
+    }
+    interface IGLTFAccessorSparseValues extends IGLTFProperty {
+        bufferView: number;
+        byteOffset?: number;
+    }
+    interface IGLTFAccessorSparse extends IGLTFProperty {
+        count: number;
+        indices: IGLTFAccessorSparseIndices;
+        values: IGLTFAccessorSparseValues;
+    }
+    interface IGLTFAccessor extends IGLTFChildRootProperty {
+        bufferView?: number;
+        byteOffset?: number;
+        componentType: EComponentType;
+        normalized?: boolean;
+        count: number;
+        type: string;
+        max: number[];
+        min: number[];
+        sparse?: IGLTFAccessorSparse;
+    }
+    interface IGLTFAnimationChannel extends IGLTFProperty {
+        sampler: number;
+        target: IGLTFAnimationChannelTarget;
+    }
+    interface IGLTFAnimationChannelTarget extends IGLTFProperty {
+        node: number;
+        path: string;
+    }
+    interface IGLTFAnimationSampler extends IGLTFProperty {
+        input: number;
+        interpolation?: string;
+        output: number;
+    }
+    interface IGLTFAnimation extends IGLTFChildRootProperty {
+        channels: IGLTFAnimationChannel[];
+        samplers: IGLTFAnimationSampler[];
+    }
+    interface IGLTFAssetProfile extends IGLTFProperty {
+        api?: string;
+        version?: string;
+    }
+    interface IGLTFAsset extends IGLTFChildRootProperty {
+        copyright?: string;
+        generator?: string;
+        profile?: IGLTFAssetProfile;
+        version: string;
+    }
+    interface IGLTFBuffer extends IGLTFChildRootProperty {
+        uri?: string;
+        byteLength: number;
+        loadedBufferView: ArrayBufferView;
+    }
+    interface IGLTFBufferView extends IGLTFChildRootProperty {
+        buffer: number;
+        byteOffset: number;
+        byteLength: number;
+        byteStride?: number;
+        target?: EBufferViewTarget;
+    }
+    interface IGLTFCameraOrthographic extends IGLTFProperty {
+        xmag: number;
+        ymag: number;
+        zfar: number;
+        znear: number;
+    }
+    interface IGLTFCameraPerspective extends IGLTFProperty {
+        aspectRatio: number;
+        yfov: number;
+        zfar: number;
+        znear: number;
+    }
+    interface IGLTFCamera extends IGLTFChildRootProperty {
+        orthographic?: IGLTFCameraOrthographic;
+        perspective?: IGLTFCameraPerspective;
+        type: string;
+    }
+    interface IGLTFImage extends IGLTFChildRootProperty {
+        uri?: string;
+        mimeType?: string;
+        bufferView?: number;
+    }
+    interface IGLTFMaterialNormalTextureInfo extends IGLTFTextureInfo {
+        scale: number;
+    }
+    interface IGLTFMaterialOcclusionTextureInfo extends IGLTFTextureInfo {
+        strength: number;
+    }
+    interface IGLTFMaterialPbrMetallicRoughness {
+        baseColorFactor: number[];
+        baseColorTexture: IGLTFTextureInfo;
+        metallicFactor: number;
+        roughnessFactor: number;
+        metallicRoughnessTexture: IGLTFTextureInfo;
+    }
+    interface IGLTFMaterial extends IGLTFChildRootProperty {
+        pbrMetallicRoughness?: IGLTFMaterialPbrMetallicRoughness;
+        normalTexture?: IGLTFMaterialNormalTextureInfo;
+        occlusionTexture?: IGLTFMaterialOcclusionTextureInfo;
+        emissiveTexture?: IGLTFTextureInfo;
+        emissiveFactor?: number[];
+        alphaMode?: string;
+        alphaCutoff: number;
+        doubleSided?: boolean;
+        babylonMaterial?: PBRMaterial;
+    }
+    interface IGLTFMeshPrimitive extends IGLTFProperty {
+        attributes: {
+            [name: string]: number;
+        };
+        indices?: number;
+        material?: number;
+        mode?: EMeshPrimitiveMode;
+        targets?: number[];
+    }
+    interface IGLTFMesh extends IGLTFChildRootProperty {
+        primitives: IGLTFMeshPrimitive[];
+        weights?: number[];
+    }
+    interface IGLTFNode extends IGLTFChildRootProperty {
+        camera?: number;
+        children?: number[];
+        skin?: number;
+        matrix?: number[];
+        mesh?: number;
+        rotation?: number[];
+        scale?: number[];
+        translation?: number[];
+        weights?: number[];
+        babylonNode?: Node;
+    }
+    interface IGLTFSampler extends IGLTFChildRootProperty {
+        magFilter?: ETextureMagFilter;
+        minFilter?: ETextureMinFilter;
+        wrapS?: ETextureWrapMode;
+        wrapT?: ETextureWrapMode;
+    }
+    interface IGLTFScene extends IGLTFChildRootProperty {
+        nodes: number[];
+    }
+    interface IGLTFSkin extends IGLTFChildRootProperty {
+        inverseBindMatrices?: number;
+        skeleton?: number;
+        joints: number[];
+        babylonSkeleton?: Skeleton;
+    }
+    interface IGLTFTexture extends IGLTFChildRootProperty {
+        format?: ETextureFormat;
+        internalFormat?: ETextureFormat;
+        sampler: number;
+        source: number;
+        target?: ETextureTarget;
+        type?: ETextureType;
+        babylonTextures: Texture[];
+        blobURL: string;
+    }
+    interface IGLTFTextureInfo {
+        index: number;
+        texCoord?: number;
+    }
+    interface IGLTF extends IGLTFProperty {
+        accessors?: IGLTFAccessor[];
+        animations?: IGLTFAnimation[];
+        asset: IGLTFAsset;
+        buffers?: IGLTFBuffer[];
+        bufferViews?: IGLTFBufferView[];
+        cameras?: IGLTFCamera[];
+        extensionsUsed?: string[];
+        extensionsRequired?: string[];
+        glExtensionsUsed?: string[];
+        images?: IGLTFImage[];
+        materials?: IGLTFMaterial[];
+        meshes?: IGLTFMesh[];
+        nodes?: IGLTFNode[];
+        samplers?: IGLTFSampler[];
+        scene?: number;
+        scenes?: IGLTFScene[];
+        skins?: IGLTFSkin[];
+        textures?: IGLTFTexture[];
+    }
+    interface IGLTFRuntime {
+        gltf: IGLTF;
+        babylonScene: Scene;
+        rootUrl: string;
+        importOnlyMeshes: boolean;
+        importMeshesNames?: string[];
+        defaultMaterial?: PBRMaterial;
+    }
+    /**
+    * Bones
+    */
+    interface INodeToRoot {
+        bone: Bone;
+        node: IGLTFNode;
+        index: number;
+    }
+    interface IJointNode {
+        node: IGLTFNode;
+        index: number;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    /**
+    * glTF File Loader Plugin
+    */
+    class GLTFLoader implements IGLTFLoader {
+        static Extensions: {
+            [name: string]: GLTFLoaderExtension;
+        };
+        static RegisterExtension(extension: GLTFLoaderExtension): void;
+        static LoadMaterial(runtime: IGLTFRuntime, index: number): IGLTFMaterial;
+        static LoadMetallicRoughnessMaterialPropertiesAsync(runtime: IGLTFRuntime, material: IGLTFMaterial, onSuccess: () => void, onError: () => void): void;
+        static LoadCommonMaterialPropertiesAsync(runtime: IGLTFRuntime, material: IGLTFMaterial, onSuccess: () => void, onError: () => void): void;
+        static LoadAlphaProperties(runtime: IGLTFRuntime, material: IGLTFMaterial): void;
+        static LoadTextureAsync(runtime: IGLTFRuntime, textureInfo: IGLTFTextureInfo, onSuccess: (babylonTexture: Texture) => void, onError: () => void): void;
+        private static _createTextureAsync(runtime, texture, texCoord, url, onSuccess, onError);
+        /**
+        * Import meshes
+        */
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void): void;
+        /**
+        * Load scene
+        */
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void;
+        private static _loadBuffersAsync(runtime, onSuccess, onError);
+        private static _loadBufferAsync(runtime, index, onSuccess, onError);
+        private static _loadMaterialsAsync(runtime, onSuccess, onError);
+        private static _createRuntime(scene, data, rootUrl, importOnlyMeshes);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    /**
+    * Utils functions for GLTF
+    */
+    class GLTFUtils {
+        /**
+        * If the uri is a base64 string
+        * @param uri: the uri to test
+        */
+        static IsBase64(uri: string): boolean;
+        /**
+        * Decode the base64 uri
+        * @param uri: the uri to decode
+        */
+        static DecodeBase64(uri: string): ArrayBuffer;
+        /**
+        * Returns the wrap mode of the texture
+        * @param mode: the mode value
+        */
+        static GetWrapMode(mode: number): number;
+        /**
+         * Returns the byte stride giving an accessor
+         * @param accessor: the GLTF accessor objet
+         */
+        static GetByteStrideFromType(accessor: IGLTFAccessor): number;
+        /**
+         * Returns the texture filter mode giving a mode value
+         * @param mode: the filter mode value
+         */
+        static GetTextureFilterMode(mode: number): ETextureMinFilter;
+        static GetBufferFromBufferView(runtime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): ArrayBufferView;
+        /**
+         * Returns a buffer from its accessor
+         * @param runtime: the GLTF runtime
+         * @param accessor: the GLTF accessor
+         */
+        static GetBufferFromAccessor(runtime: IGLTFRuntime, accessor: IGLTFAccessor): any;
+        /**
+         * Decodes a buffer view into a string
+         * @param view: the buffer view
+         */
+        static DecodeBufferToText(view: ArrayBufferView): string;
+        /**
+         * Returns the default material of gltf.
+         * @param scene: the Babylon.js scene
+         */
+        static GetDefaultMaterial(runtime: IGLTFRuntime): PBRMaterial;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    abstract class GLTFLoaderExtension {
+        private _name;
+        constructor(name: string);
+        readonly name: string;
+        protected postCreateRuntime(runtime: IGLTFRuntime): void;
+        protected loadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): boolean;
+        static PostCreateRuntime(runtime: IGLTFRuntime): void;
+        static LoadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): void;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    class GLTFMaterialsPbrSpecularGlossinessExtension extends GLTFLoaderExtension {
+        constructor();
+        protected loadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): boolean;
+    }
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1665 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


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

@@ -3,11 +3,50 @@ declare module BABYLON {
     interface IGLTFLoaderData {
         json: Object;
         bin: ArrayBufferView;
+<<<<<<< HEAD
+=======
+    }
+    interface IGLTFLoader {
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+    }
+    class GLTFFileLoader implements ISceneLoaderPluginAsync {
+        static GLTFLoaderV1: IGLTFLoader;
+        static GLTFLoaderV2: IGLTFLoader;
+        static HomogeneousCoordinates: boolean;
+        static IncrementalLoading: boolean;
+        extensions: ISceneLoaderPluginExtensions;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): void;
+        private static _parse(data);
+        private _getLoader(loaderData);
+        private static _parseBinary(data);
+        private static _parseV1(binaryReader);
+        private static _parseV2(binaryReader);
+        private static _parseVersion(version);
+        private static _compareVersion(a, b);
+        private static _decodeBufferToText(view);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    /**
+    * Enums
+    */
+    enum EComponentType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        FLOAT = 5126,
+>>>>>>> upstream/master
     }
     interface IGLTFLoader {
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror?: () => void) => boolean;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => boolean;
     }
+<<<<<<< HEAD
     class GLTFFileLoader implements ISceneLoaderPluginAsync {
         static GLTFLoaderV1: IGLTFLoader;
         static GLTFLoaderV2: IGLTFLoader;
@@ -24,5 +63,884 @@ declare module BABYLON {
         private static _parseVersion(version);
         private static _compareVersion(a, b);
         private static _decodeBufferToText(view);
+=======
+    enum EParameterType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        INT = 5124,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+        FLOAT_VEC2 = 35664,
+        FLOAT_VEC3 = 35665,
+        FLOAT_VEC4 = 35666,
+        INT_VEC2 = 35667,
+        INT_VEC3 = 35668,
+        INT_VEC4 = 35669,
+        BOOL = 35670,
+        BOOL_VEC2 = 35671,
+        BOOL_VEC3 = 35672,
+        BOOL_VEC4 = 35673,
+        FLOAT_MAT2 = 35674,
+        FLOAT_MAT3 = 35675,
+        FLOAT_MAT4 = 35676,
+        SAMPLER_2D = 35678,
+    }
+    enum ETextureWrapMode {
+        CLAMP_TO_EDGE = 33071,
+        MIRRORED_REPEAT = 33648,
+        REPEAT = 10497,
+    }
+    enum ETextureFilterType {
+        NEAREST = 9728,
+        LINEAR = 9728,
+        NEAREST_MIPMAP_NEAREST = 9984,
+        LINEAR_MIPMAP_NEAREST = 9985,
+        NEAREST_MIPMAP_LINEAR = 9986,
+        LINEAR_MIPMAP_LINEAR = 9987,
+    }
+    enum ETextureFormat {
+        ALPHA = 6406,
+        RGB = 6407,
+        RGBA = 6408,
+        LUMINANCE = 6409,
+        LUMINANCE_ALPHA = 6410,
+    }
+    enum ECullingType {
+        FRONT = 1028,
+        BACK = 1029,
+        FRONT_AND_BACK = 1032,
+    }
+    enum EBlendingFunction {
+        ZERO = 0,
+        ONE = 1,
+        SRC_COLOR = 768,
+        ONE_MINUS_SRC_COLOR = 769,
+        DST_COLOR = 774,
+        ONE_MINUS_DST_COLOR = 775,
+        SRC_ALPHA = 770,
+        ONE_MINUS_SRC_ALPHA = 771,
+        DST_ALPHA = 772,
+        ONE_MINUS_DST_ALPHA = 773,
+        CONSTANT_COLOR = 32769,
+        ONE_MINUS_CONSTANT_COLOR = 32770,
+        CONSTANT_ALPHA = 32771,
+        ONE_MINUS_CONSTANT_ALPHA = 32772,
+        SRC_ALPHA_SATURATE = 776,
+    }
+    /**
+    * Interfaces
+    */
+    interface IGLTFProperty {
+        extensions?: Object;
+        extras?: Object;
+    }
+    interface IGLTFChildRootProperty extends IGLTFProperty {
+        name?: string;
+    }
+    interface IGLTFAccessor extends IGLTFChildRootProperty {
+        bufferView: string;
+        byteOffset: number;
+        byteStride: number;
+        count: number;
+        type: string;
+        componentType: EComponentType;
+        max?: number[];
+        min?: number[];
+        name?: string;
+    }
+    interface IGLTFBufferView extends IGLTFChildRootProperty {
+        buffer: string;
+        byteOffset: number;
+        byteLength: number;
+        target?: number;
+    }
+    interface IGLTFBuffer extends IGLTFChildRootProperty {
+        uri: string;
+        byteLength?: number;
+        type?: string;
+    }
+    interface IGLTFShader extends IGLTFChildRootProperty {
+        uri: string;
+        type: EShaderType;
+    }
+    interface IGLTFProgram extends IGLTFChildRootProperty {
+        attributes: string[];
+        fragmentShader: string;
+        vertexShader: string;
+    }
+    interface IGLTFTechniqueParameter {
+        type: number;
+        count?: number;
+        semantic?: string;
+        node?: string;
+        value?: number | boolean | string | Array<any>;
+        source?: string;
+        babylonValue?: any;
+    }
+    interface IGLTFTechniqueCommonProfile {
+        lightingModel: string;
+        texcoordBindings: Object;
+        parameters?: Array<any>;
+    }
+    interface IGLTFTechniqueStatesFunctions {
+        blendColor?: number[];
+        blendEquationSeparate?: number[];
+        blendFuncSeparate?: number[];
+        colorMask: boolean[];
+        cullFace: number[];
+    }
+    interface IGLTFTechniqueStates {
+        enable: number[];
+        functions: IGLTFTechniqueStatesFunctions;
+    }
+    interface IGLTFTechnique extends IGLTFChildRootProperty {
+        parameters: Object;
+        program: string;
+        attributes: Object;
+        uniforms: Object;
+        states: IGLTFTechniqueStates;
+    }
+    interface IGLTFMaterial extends IGLTFChildRootProperty {
+        technique?: string;
+        values: string[];
+    }
+    interface IGLTFMeshPrimitive extends IGLTFProperty {
+        attributes: Object;
+        indices: string;
+        material: string;
+        mode?: number;
+    }
+    interface IGLTFMesh extends IGLTFChildRootProperty {
+        primitives: IGLTFMeshPrimitive[];
+    }
+    interface IGLTFImage extends IGLTFChildRootProperty {
+        uri: string;
+    }
+    interface IGLTFSampler extends IGLTFChildRootProperty {
+        magFilter?: number;
+        minFilter?: number;
+        wrapS?: number;
+        wrapT?: number;
+    }
+    interface IGLTFTexture extends IGLTFChildRootProperty {
+        sampler: string;
+        source: string;
+        format?: ETextureFormat;
+        internalFormat?: ETextureFormat;
+        target?: number;
+        type?: number;
+        babylonTexture?: Texture;
+    }
+    interface IGLTFAmbienLight {
+        color?: number[];
+    }
+    interface IGLTFDirectionalLight {
+        color?: number[];
+    }
+    interface IGLTFPointLight {
+        color?: number[];
+        constantAttenuation?: number;
+        linearAttenuation?: number;
+        quadraticAttenuation?: number;
+    }
+    interface IGLTFSpotLight {
+        color?: number[];
+        constantAttenuation?: number;
+        fallOfAngle?: number;
+        fallOffExponent?: number;
+        linearAttenuation?: number;
+        quadraticAttenuation?: number;
+    }
+    interface IGLTFLight extends IGLTFChildRootProperty {
+        type: string;
+    }
+    interface IGLTFCameraOrthographic {
+        xmag: number;
+        ymag: number;
+        zfar: number;
+        znear: number;
+    }
+    interface IGLTFCameraPerspective {
+        aspectRatio: number;
+        yfov: number;
+        zfar: number;
+        znear: number;
+    }
+    interface IGLTFCamera extends IGLTFChildRootProperty {
+        type: string;
+    }
+    interface IGLTFAnimationChannelTarget {
+        id: string;
+        path: string;
+    }
+    interface IGLTFAnimationChannel {
+        sampler: string;
+        target: IGLTFAnimationChannelTarget;
+    }
+    interface IGLTFAnimationSampler {
+        input: string;
+        output: string;
+        interpolation?: string;
+    }
+    interface IGLTFAnimation extends IGLTFChildRootProperty {
+        channels?: IGLTFAnimationChannel[];
+        parameters?: Object;
+        samplers?: Object;
+    }
+    interface IGLTFNodeInstanceSkin {
+        skeletons: string[];
+        skin: string;
+        meshes: string[];
+    }
+    interface IGLTFSkins extends IGLTFChildRootProperty {
+        bindShapeMatrix: number[];
+        inverseBindMatrices: string;
+        jointNames: string[];
+        babylonSkeleton?: Skeleton;
+    }
+    interface IGLTFNode extends IGLTFChildRootProperty {
+        camera?: string;
+        children: string[];
+        skin?: string;
+        jointName?: string;
+        light?: string;
+        matrix: number[];
+        mesh?: string;
+        meshes?: string[];
+        rotation?: number[];
+        scale?: number[];
+        translation?: number[];
+        babylonNode?: Node;
+    }
+    interface IGLTFScene extends IGLTFChildRootProperty {
+        nodes: string[];
+    }
+    /**
+    * Runtime
+    */
+    interface IGLTFRuntime {
+        extensions: Object;
+        accessors: Object;
+        buffers: Object;
+        bufferViews: Object;
+        meshes: Object;
+        lights: Object;
+        cameras: Object;
+        nodes: Object;
+        images: Object;
+        textures: Object;
+        shaders: Object;
+        programs: Object;
+        samplers: Object;
+        techniques: Object;
+        materials: Object;
+        animations: Object;
+        skins: Object;
+        currentScene?: Object;
+        scenes: Object;
+        extensionsUsed: string[];
+        extensionsRequired?: string[];
+        buffersCount: number;
+        shaderscount: number;
+        scene: Scene;
+        rootUrl: string;
+        loadedBufferCount: number;
+        loadedBufferViews: {
+            [name: string]: ArrayBufferView;
+        };
+        loadedShaderCount: number;
+        importOnlyMeshes: boolean;
+        importMeshesNames?: string[];
+        dummyNodes: Node[];
+    }
+    /**
+    * Bones
+    */
+    interface INodeToRoot {
+        bone: Bone;
+        node: IGLTFNode;
+        id: string;
+    }
+    interface IJointNode {
+        node: IGLTFNode;
+        id: string;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    /**
+    * Implementation of the base glTF spec
+    */
+    class GLTFLoaderBase {
+        static CreateRuntime(parsedData: any, scene: Scene, rootUrl: string): IGLTFRuntime;
+        static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): void;
+        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): void;
+        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): void;
+        static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): void;
+        static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void;
+    }
+    /**
+    * glTF V1 Loader
+    */
+    class GLTFLoader implements IGLTFLoader {
+        static Extensions: {
+            [name: string]: GLTFLoaderExtension;
+        };
+        static RegisterExtension(extension: GLTFLoaderExtension): void;
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void, onProgress?: () => void): boolean;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void;
+        private _loadShadersAsync(gltfRuntime, onload);
+        private _loadBuffersAsync(gltfRuntime, onload, onProgress?);
+        private _createNodes(gltfRuntime);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    /**
+    * Utils functions for GLTF
+    */
+    class GLTFUtils {
+        /**
+         * Sets the given "parameter" matrix
+         * @param scene: the {BABYLON.Scene} object
+         * @param source: the source node where to pick the matrix
+         * @param parameter: the GLTF technique parameter
+         * @param uniformName: the name of the shader's uniform
+         * @param shaderMaterial: the shader material
+         */
+        static SetMatrix(scene: Scene, source: Node, parameter: IGLTFTechniqueParameter, uniformName: string, shaderMaterial: ShaderMaterial | Effect): void;
+        /**
+         * Sets the given "parameter" matrix
+         * @param shaderMaterial: the shader material
+         * @param uniform: the name of the shader's uniform
+         * @param value: the value of the uniform
+         * @param type: the uniform's type (EParameterType FLOAT, VEC2, VEC3 or VEC4)
+         */
+        static SetUniform(shaderMaterial: ShaderMaterial | Effect, uniform: string, value: any, type: number): boolean;
+        /**
+        * If the uri is a base64 string
+        * @param uri: the uri to test
+        */
+        static IsBase64(uri: string): boolean;
+        /**
+        * Decode the base64 uri
+        * @param uri: the uri to decode
+        */
+        static DecodeBase64(uri: string): ArrayBuffer;
+        /**
+        * Returns the wrap mode of the texture
+        * @param mode: the mode value
+        */
+        static GetWrapMode(mode: number): number;
+        /**
+         * Returns the byte stride giving an accessor
+         * @param accessor: the GLTF accessor objet
+         */
+        static GetByteStrideFromType(accessor: IGLTFAccessor): number;
+        /**
+         * Returns the texture filter mode giving a mode value
+         * @param mode: the filter mode value
+         */
+        static GetTextureFilterMode(mode: number): ETextureFilterType;
+        static GetBufferFromBufferView(gltfRuntime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): ArrayBufferView;
+        /**
+         * Returns a buffer from its accessor
+         * @param gltfRuntime: the GLTF runtime
+         * @param accessor: the GLTF accessor
+         */
+        static GetBufferFromAccessor(gltfRuntime: IGLTFRuntime, accessor: IGLTFAccessor): any;
+        /**
+         * Decodes a buffer view into a string
+         * @param view: the buffer view
+         */
+        static DecodeBufferToText(view: ArrayBufferView): string;
+        /**
+         * Returns the default material of gltf. Related to
+         * https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a-default-material
+         * @param scene: the Babylon.js scene
+         */
+        static GetDefaultMaterial(scene: Scene): ShaderMaterial;
+        private static _DefaultMaterial;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    abstract class GLTFLoaderExtension {
+        private _name;
+        constructor(name: string);
+        readonly name: string;
+        /**
+        * Defines an override for loading the runtime
+        * Return true to stop further extensions from loading the runtime
+        */
+        loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean;
+        /**
+         * Defines an onverride for creating gltf runtime
+         * Return true to stop further extensions from creating the runtime
+         */
+        loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): boolean;
+        /**
+        * Defines an override for loading buffers
+        * Return true to stop further extensions from loading this buffer
+        */
+        loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): boolean;
+        /**
+        * Defines an override for loading texture buffers
+        * Return true to stop further extensions from loading this texture data
+        */
+        loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
+        /**
+        * Defines an override for creating textures
+        * Return true to stop further extensions from loading this texture
+        */
+        createTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): boolean;
+        /**
+        * Defines an override for loading shader strings
+        * Return true to stop further extensions from loading this shader data
+        */
+        loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): boolean;
+        /**
+        * Defines an override for loading materials
+        * Return true to stop further extensions from loading this material
+        */
+        loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): boolean;
+        static LoadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): void;
+        static LoadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): void;
+        static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (bufferView: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): void;
+        static LoadTextureAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (texture: Texture) => void, onError: () => void): void;
+        static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderData: string) => void, onError: () => void): void;
+        static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void;
+        private static LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
+        private static CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
+        private static ApplyExtensions(func, defaultFunc);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    class GLTFBinaryExtension extends GLTFLoaderExtension {
+        private _bin;
+        constructor();
+        loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean;
+        loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
+        loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
+        loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): boolean;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF1 {
+    class GLTFMaterialsCommonExtension extends GLTFLoaderExtension {
+        constructor();
+        loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): boolean;
+        loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): boolean;
+        private _loadTexture(gltfRuntime, id, material, propertyPath, onError);
+>>>>>>> upstream/master
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    /**
+    * Enums
+    */
+    enum EBufferViewTarget {
+        ARRAY_BUFFER = 34962,
+        ELEMENT_ARRAY_BUFFER = 34963,
+    }
+    enum EComponentType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+    }
+    enum EMeshPrimitiveMode {
+        POINTS = 0,
+        LINES = 1,
+        LINE_LOOP = 2,
+        LINE_STRIP = 3,
+        TRIANGLES = 4,
+        TRIANGLE_STRIP = 5,
+        TRIANGLE_FAN = 6,
+    }
+    enum EParameterType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        INT = 5124,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+        FLOAT_VEC2 = 35664,
+        FLOAT_VEC3 = 35665,
+        FLOAT_VEC4 = 35666,
+        INT_VEC2 = 35667,
+        INT_VEC3 = 35668,
+        INT_VEC4 = 35669,
+        BOOL = 35670,
+        BOOL_VEC2 = 35671,
+        BOOL_VEC3 = 35672,
+        BOOL_VEC4 = 35673,
+        FLOAT_MAT2 = 35674,
+        FLOAT_MAT3 = 35675,
+        FLOAT_MAT4 = 35676,
+        SAMPLER_2D = 35678,
+    }
+    enum ETextureMagFilter {
+        NEAREST = 9728,
+        LINEAR = 9729,
+    }
+    enum ETextureMinFilter {
+        NEAREST = 9728,
+        LINEAR = 9729,
+        NEAREST_MIPMAP_NEAREST = 9984,
+        LINEAR_MIPMAP_NEAREST = 9985,
+        NEAREST_MIPMAP_LINEAR = 9986,
+        LINEAR_MIPMAP_LINEAR = 9987,
+    }
+    enum ETextureFormat {
+        ALPHA = 6406,
+        RGB = 6407,
+        RGBA = 6408,
+        LUMINANCE = 6409,
+        LUMINANCE_ALPHA = 6410,
+    }
+    enum ETextureTarget {
+        TEXTURE_2D = 3553,
+    }
+    enum ETextureType {
+        UNSIGNED_BYTE = 5121,
+        UNSIGNED_SHORT_5_6_5 = 33635,
+        UNSIGNED_SHORT_4_4_4_4 = 32819,
+        UNSIGNED_SHORT_5_5_5_1 = 32820,
+    }
+    enum ETextureWrapMode {
+        CLAMP_TO_EDGE = 33071,
+        MIRRORED_REPEAT = 33648,
+        REPEAT = 10497,
+    }
+    /**
+    * Interfaces
+    */
+    interface IGLTFProperty {
+        extensions?: Object;
+        extras?: any;
+    }
+    interface IGLTFChildRootProperty extends IGLTFProperty {
+        name?: string;
+    }
+    interface IGLTFAccessorSparseIndices extends IGLTFProperty {
+        bufferView: number;
+        byteOffset?: number;
+        componentType: EComponentType;
+    }
+    interface IGLTFAccessorSparseValues extends IGLTFProperty {
+        bufferView: number;
+        byteOffset?: number;
+    }
+    interface IGLTFAccessorSparse extends IGLTFProperty {
+        count: number;
+        indices: IGLTFAccessorSparseIndices;
+        values: IGLTFAccessorSparseValues;
+    }
+    interface IGLTFAccessor extends IGLTFChildRootProperty {
+        bufferView?: number;
+        byteOffset?: number;
+        componentType: EComponentType;
+        normalized?: boolean;
+        count: number;
+        type: string;
+        max: number[];
+        min: number[];
+        sparse?: IGLTFAccessorSparse;
+    }
+    interface IGLTFAnimationChannel extends IGLTFProperty {
+        sampler: number;
+        target: IGLTFAnimationChannelTarget;
+    }
+    interface IGLTFAnimationChannelTarget extends IGLTFProperty {
+        node: number;
+        path: string;
+    }
+    interface IGLTFAnimationSampler extends IGLTFProperty {
+        input: number;
+        interpolation?: string;
+        output: number;
+    }
+    interface IGLTFAnimation extends IGLTFChildRootProperty {
+        channels: IGLTFAnimationChannel[];
+        samplers: IGLTFAnimationSampler[];
+    }
+    interface IGLTFAssetProfile extends IGLTFProperty {
+        api?: string;
+        version?: string;
+    }
+    interface IGLTFAsset extends IGLTFChildRootProperty {
+        copyright?: string;
+        generator?: string;
+        profile?: IGLTFAssetProfile;
+        version: string;
+    }
+    interface IGLTFBuffer extends IGLTFChildRootProperty {
+        uri?: string;
+        byteLength: number;
+        loadedBufferView: ArrayBufferView;
+    }
+    interface IGLTFBufferView extends IGLTFChildRootProperty {
+        buffer: number;
+        byteOffset: number;
+        byteLength: number;
+        byteStride?: number;
+        target?: EBufferViewTarget;
+    }
+    interface IGLTFCameraOrthographic extends IGLTFProperty {
+        xmag: number;
+        ymag: number;
+        zfar: number;
+        znear: number;
+    }
+    interface IGLTFCameraPerspective extends IGLTFProperty {
+        aspectRatio: number;
+        yfov: number;
+        zfar: number;
+        znear: number;
+    }
+    interface IGLTFCamera extends IGLTFChildRootProperty {
+        orthographic?: IGLTFCameraOrthographic;
+        perspective?: IGLTFCameraPerspective;
+        type: string;
+    }
+    interface IGLTFImage extends IGLTFChildRootProperty {
+        uri?: string;
+        mimeType?: string;
+        bufferView?: number;
+    }
+    interface IGLTFMaterialNormalTextureInfo extends IGLTFTextureInfo {
+        scale: number;
+    }
+    interface IGLTFMaterialOcclusionTextureInfo extends IGLTFTextureInfo {
+        strength: number;
+    }
+    interface IGLTFMaterialPbrMetallicRoughness {
+        baseColorFactor: number[];
+        baseColorTexture: IGLTFTextureInfo;
+        metallicFactor: number;
+        roughnessFactor: number;
+        metallicRoughnessTexture: IGLTFTextureInfo;
+    }
+    interface IGLTFMaterial extends IGLTFChildRootProperty {
+        pbrMetallicRoughness?: IGLTFMaterialPbrMetallicRoughness;
+        normalTexture?: IGLTFMaterialNormalTextureInfo;
+        occlusionTexture?: IGLTFMaterialOcclusionTextureInfo;
+        emissiveTexture?: IGLTFTextureInfo;
+        emissiveFactor?: number[];
+        alphaMode?: string;
+        alphaCutoff: number;
+        doubleSided?: boolean;
+        babylonMaterial?: PBRMaterial;
+    }
+    interface IGLTFMeshPrimitive extends IGLTFProperty {
+        attributes: {
+            [name: string]: number;
+        };
+        indices?: number;
+        material?: number;
+        mode?: EMeshPrimitiveMode;
+        targets?: number[];
+    }
+    interface IGLTFMesh extends IGLTFChildRootProperty {
+        primitives: IGLTFMeshPrimitive[];
+        weights?: number[];
+    }
+    interface IGLTFNode extends IGLTFChildRootProperty {
+        camera?: number;
+        children?: number[];
+        skin?: number;
+        matrix?: number[];
+        mesh?: number;
+        rotation?: number[];
+        scale?: number[];
+        translation?: number[];
+        weights?: number[];
+        babylonNode?: Node;
+    }
+    interface IGLTFSampler extends IGLTFChildRootProperty {
+        magFilter?: ETextureMagFilter;
+        minFilter?: ETextureMinFilter;
+        wrapS?: ETextureWrapMode;
+        wrapT?: ETextureWrapMode;
+    }
+    interface IGLTFScene extends IGLTFChildRootProperty {
+        nodes: number[];
+    }
+    interface IGLTFSkin extends IGLTFChildRootProperty {
+        inverseBindMatrices?: number;
+        skeleton?: number;
+        joints: number[];
+        babylonSkeleton?: Skeleton;
+    }
+    interface IGLTFTexture extends IGLTFChildRootProperty {
+        format?: ETextureFormat;
+        internalFormat?: ETextureFormat;
+        sampler: number;
+        source: number;
+        target?: ETextureTarget;
+        type?: ETextureType;
+        babylonTextures: Texture[];
+        blobURL: string;
+    }
+    interface IGLTFTextureInfo {
+        index: number;
+        texCoord?: number;
+    }
+    interface IGLTF extends IGLTFProperty {
+        accessors?: IGLTFAccessor[];
+        animations?: IGLTFAnimation[];
+        asset: IGLTFAsset;
+        buffers?: IGLTFBuffer[];
+        bufferViews?: IGLTFBufferView[];
+        cameras?: IGLTFCamera[];
+        extensionsUsed?: string[];
+        extensionsRequired?: string[];
+        glExtensionsUsed?: string[];
+        images?: IGLTFImage[];
+        materials?: IGLTFMaterial[];
+        meshes?: IGLTFMesh[];
+        nodes?: IGLTFNode[];
+        samplers?: IGLTFSampler[];
+        scene?: number;
+        scenes?: IGLTFScene[];
+        skins?: IGLTFSkin[];
+        textures?: IGLTFTexture[];
+    }
+    interface IGLTFRuntime {
+        gltf: IGLTF;
+        babylonScene: Scene;
+        rootUrl: string;
+        importOnlyMeshes: boolean;
+        importMeshesNames?: string[];
+        defaultMaterial?: PBRMaterial;
+    }
+    /**
+    * Bones
+    */
+    interface INodeToRoot {
+        bone: Bone;
+        node: IGLTFNode;
+        index: number;
+    }
+    interface IJointNode {
+        node: IGLTFNode;
+        index: number;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    /**
+    * glTF File Loader Plugin
+    */
+    class GLTFLoader implements IGLTFLoader {
+        static Extensions: {
+            [name: string]: GLTFLoaderExtension;
+        };
+        static RegisterExtension(extension: GLTFLoaderExtension): void;
+        static LoadMaterial(runtime: IGLTFRuntime, index: number): IGLTFMaterial;
+        static LoadMetallicRoughnessMaterialPropertiesAsync(runtime: IGLTFRuntime, material: IGLTFMaterial, onSuccess: () => void, onError: () => void): void;
+        static LoadCommonMaterialPropertiesAsync(runtime: IGLTFRuntime, material: IGLTFMaterial, onSuccess: () => void, onError: () => void): void;
+        static LoadAlphaProperties(runtime: IGLTFRuntime, material: IGLTFMaterial): void;
+        static LoadTextureAsync(runtime: IGLTFRuntime, textureInfo: IGLTFTextureInfo, onSuccess: (babylonTexture: Texture) => void, onError: () => void): void;
+        private static _createTextureAsync(runtime, texture, texCoord, url, onSuccess, onError);
+        /**
+        * Import meshes
+        */
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void): void;
+        /**
+        * Load scene
+        */
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void;
+        private static _loadBuffersAsync(runtime, onSuccess, onError);
+        private static _loadBufferAsync(runtime, index, onSuccess, onError);
+        private static _loadMaterialsAsync(runtime, onSuccess, onError);
+        private static _createRuntime(scene, data, rootUrl, importOnlyMeshes);
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    /**
+    * Utils functions for GLTF
+    */
+    class GLTFUtils {
+        /**
+        * If the uri is a base64 string
+        * @param uri: the uri to test
+        */
+        static IsBase64(uri: string): boolean;
+        /**
+        * Decode the base64 uri
+        * @param uri: the uri to decode
+        */
+        static DecodeBase64(uri: string): ArrayBuffer;
+        /**
+        * Returns the wrap mode of the texture
+        * @param mode: the mode value
+        */
+        static GetWrapMode(mode: number): number;
+        /**
+         * Returns the byte stride giving an accessor
+         * @param accessor: the GLTF accessor objet
+         */
+        static GetByteStrideFromType(accessor: IGLTFAccessor): number;
+        /**
+         * Returns the texture filter mode giving a mode value
+         * @param mode: the filter mode value
+         */
+        static GetTextureFilterMode(mode: number): ETextureMinFilter;
+        static GetBufferFromBufferView(runtime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): ArrayBufferView;
+        /**
+         * Returns a buffer from its accessor
+         * @param runtime: the GLTF runtime
+         * @param accessor: the GLTF accessor
+         */
+        static GetBufferFromAccessor(runtime: IGLTFRuntime, accessor: IGLTFAccessor): any;
+        /**
+         * Decodes a buffer view into a string
+         * @param view: the buffer view
+         */
+        static DecodeBufferToText(view: ArrayBufferView): string;
+        /**
+         * Returns the default material of gltf.
+         * @param scene: the Babylon.js scene
+         */
+        static GetDefaultMaterial(runtime: IGLTFRuntime): PBRMaterial;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    abstract class GLTFLoaderExtension {
+        private _name;
+        constructor(name: string);
+        readonly name: string;
+        protected postCreateRuntime(runtime: IGLTFRuntime): void;
+        protected loadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): boolean;
+        static PostCreateRuntime(runtime: IGLTFRuntime): void;
+        static LoadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): void;
+    }
+}
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GLTF2 {
+    class GLTFMaterialsPbrSpecularGlossinessExtension extends GLTFLoaderExtension {
+        constructor();
+        protected loadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): boolean;
     }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 3804 - 0
dist/preview release/loaders/babylon.glTFFileLoader.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 6 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 1 - 4
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1,5 +1,4 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-/// <reference path="../../../../dist/preview release/loaders/babylon.glTFFileLoader.d.ts"/>
 
 module BABYLON.GLTF1 {
     /**
@@ -1603,7 +1602,7 @@ module BABYLON.GLTF1 {
             return true;
         }
 
-        public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): boolean {
+        public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void {
             scene.useRightHandedSystem = true;
 
             GLTFLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, gltfRuntime => {
@@ -1629,8 +1628,6 @@ module BABYLON.GLTF1 {
                     }
                 }, onError);
             }, onError);
-
-            return true;
         }
 
         private _loadShadersAsync(gltfRuntime: IGLTFRuntime, onload: () => void): void {

+ 175 - 98
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -1,5 +1,4 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-/// <reference path="../../../../dist/preview release/loaders/babylon.glTFFileLoader.d.ts"/>
 
 module BABYLON.GLTF2 {
     /**
@@ -478,7 +477,7 @@ module BABYLON.GLTF2 {
         }
 
         return material;
-    }
+    };
 
     /**
     * Imports a mesh and its geometries
@@ -788,7 +787,7 @@ module BABYLON.GLTF2 {
                 traverseNodes(runtime, i, null);
             }
         }
-    }
+    };
 
     /**
     * do stuff after buffers are loaded (e.g. hook up materials, load animations, etc.)
@@ -803,12 +802,14 @@ module BABYLON.GLTF2 {
             var skeleton = runtime.babylonScene.skeletons[i];
             runtime.babylonScene.beginAnimation(skeleton, 0, Number.MAX_VALUE, true, 1.0);
         }
-    };
 
-    var importMaterials = (runtime: IGLTFRuntime): void => {
-        if (runtime.gltf.materials) {
-            for (var i = 0; i < runtime.gltf.materials.length; i++) {
-                GLTFLoaderExtension.LoadMaterial(runtime, i);
+        // Revoke object urls created during load
+        if (runtime.gltf.textures) {
+            for (var i = 0; i < runtime.gltf.textures.length; i++) {
+                var texture = runtime.gltf.textures[i];
+                if (texture.blobURL) {
+                    URL.revokeObjectURL(texture.blobURL);
+                }
             }
         }
     };
@@ -874,22 +875,52 @@ module BABYLON.GLTF2 {
             return material;
         }
 
-        public static LoadMetallicRoughnessMaterialProperties = (runtime: IGLTFRuntime, material: IGLTFMaterial): void => {
+        public static LoadMetallicRoughnessMaterialPropertiesAsync(runtime: IGLTFRuntime, material: IGLTFMaterial, onSuccess: () => void, onError: () => void): void {
+            // Ensure metallic workflow
+            material.babylonMaterial.metallic = 1;
+            material.babylonMaterial.roughness = 1;
+
             var properties = material.pbrMetallicRoughness;
-            if (!properties) return;
+            if (!properties) {
+                onSuccess();
+                return;
+            }
+
+            //
+            // Load Factors
+            //
 
             material.babylonMaterial.albedoColor = properties.baseColorFactor ? Color3.FromArray(properties.baseColorFactor) : new Color3(1, 1, 1);
-            material.babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
-            material.babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
+            material.babylonMaterial.metallic = properties.metallicFactor || 1;
+            material.babylonMaterial.roughness = properties.roughnessFactor || 1;
+
+            //
+            // Load Textures
+            //
+
+            if (!properties.baseColorTexture && !properties.metallicRoughnessTexture) {
+                onSuccess();
+                return;
+            }
+
+            var checkSuccess = () => {
+                if ((!properties.baseColorTexture || material.babylonMaterial.albedoTexture) &&
+                    (!properties.metallicRoughnessTexture || material.babylonMaterial.metallicTexture))
+                {
+                    onSuccess();
+                }
+            };
 
             if (properties.baseColorTexture) {
                 GLTFLoader.LoadTextureAsync(runtime, properties.baseColorTexture,
                     texture => {
                         material.babylonMaterial.albedoTexture = texture;
                         GLTFLoader.LoadAlphaProperties(runtime, material);
+                        checkSuccess();
                     },
                     () => {
-                        Tools.Warn("Failed to load base color texture");
+                        Tools.Error("Failed to load base color texture");
+                        onError();
                     });
             }
 
@@ -900,21 +931,56 @@ module BABYLON.GLTF2 {
                         material.babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
                         material.babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
                         material.babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
+                        checkSuccess();
                     },
                     () => {
-                        Tools.Warn("Failed to load metallic roughness texture");
+                        Tools.Error("Failed to load metallic roughness texture");
+                        onError();
                     });
             }
         }
 
-        public static LoadCommonMaterialProperties(runtime: IGLTFRuntime, material: IGLTFMaterial): void {
+        public static LoadCommonMaterialPropertiesAsync(runtime: IGLTFRuntime, material: IGLTFMaterial, onSuccess: () => void, onError: () => void): void {
+            //
+            // Load Factors
+            //
+
+            material.babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
+            material.babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0);
+            if (material.doubleSided) {
+                material.babylonMaterial.backFaceCulling = false;
+                material.babylonMaterial.twoSidedLighting = true;
+            }
+
+            //
+            // Load Textures
+            //
+
+            if (!material.normalTexture && !material.occlusionTexture && !material.emissiveTexture) {
+                onSuccess();
+                return;
+            }
+
+            var checkSuccess = () => {
+                if ((!material.normalTexture || material.babylonMaterial.bumpTexture) &&
+                    (!material.occlusionTexture || material.babylonMaterial.ambientTexture) &&
+                    (!material.emissiveTexture || material.babylonMaterial.emissiveTexture)) {
+                    onSuccess();
+                }
+            }
+
             if (material.normalTexture) {
                 GLTFLoader.LoadTextureAsync(runtime, material.normalTexture, babylonTexture => {
                     material.babylonMaterial.bumpTexture = babylonTexture;
                     if (material.normalTexture.scale !== undefined) {
                         material.babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
-                }, () => Tools.Warn("Failed to load normal texture"));
+                    checkSuccess();
+                },
+                () => {
+                    Tools.Error("Failed to load normal texture");
+                    onError();
+                });
             }
 
             if (material.occlusionTexture) {
@@ -924,20 +990,23 @@ module BABYLON.GLTF2 {
                     if (material.occlusionTexture.strength !== undefined) {
                         material.babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
-                }, () => Tools.Warn("Failed to load occlusion texture"));
+                    checkSuccess();
+                },
+                () => {
+                    Tools.Error("Failed to load occlusion texture");
+                    onError();
+                });
             }
 
-            material.babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
-            material.babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0);
             if (material.emissiveTexture) {
                 GLTFLoader.LoadTextureAsync(runtime, material.emissiveTexture, babylonTexture => {
                     material.babylonMaterial.emissiveTexture = babylonTexture;
-                }, () => Tools.Warn("Failed to load emissive texture"));
-            }
-
-            if (material.doubleSided) {
-                material.babylonMaterial.backFaceCulling = false;
-                material.babylonMaterial.twoSidedLighting = true;
+                    checkSuccess();
+                },
+                () => {
+                    Tools.Error("Failed to load emissive texture");
+                    onError();
+                });
             }
         }
 
@@ -964,78 +1033,81 @@ module BABYLON.GLTF2 {
 
         public static LoadTextureAsync(runtime: IGLTFRuntime, textureInfo: IGLTFTextureInfo, onSuccess: (babylonTexture: Texture) => void, onError: () => void): void {
             var texture = runtime.gltf.textures[textureInfo.index];
+            var texCoord = textureInfo.texCoord || 0;
 
             if (!texture || texture.source === undefined) {
                 onError();
                 return;
             }
 
-            if (texture.babylonTexture) {
-                onSuccess(texture.babylonTexture);
+            if (texture.babylonTextures) {
+                var babylonTexture = texture.babylonTextures[texCoord];
+                if (!babylonTexture) {
+                    for (var i = 0; i < texture.babylonTextures.length; i++) {
+                        babylonTexture = texture.babylonTextures[i];
+                        if (babylonTexture) {
+                            babylonTexture = babylonTexture.clone();
+                            babylonTexture.coordinatesIndex = texCoord;
+                            break;
+                        }
+                    }
+                }
+
+                onSuccess(babylonTexture);
                 return;
             }
 
             var source = runtime.gltf.images[texture.source];
+            var sourceURL = runtime.rootUrl + source.uri;
 
-            if (source.uri === undefined) {
-                var bufferView: IGLTFBufferView = runtime.gltf.bufferViews[source.bufferView];
-                var buffer = GLTFUtils.GetBufferFromBufferView(runtime, bufferView, 0, bufferView.byteLength, EComponentType.UNSIGNED_BYTE);
-                GLTFLoader.CreateTextureAsync(runtime, textureInfo, buffer, source.mimeType, onSuccess, onError);
-            }
-            else if (GLTFUtils.IsBase64(source.uri)) {
-                GLTFLoader.CreateTextureAsync(runtime, textureInfo, new Uint8Array(GLTFUtils.DecodeBase64(source.uri)), source.mimeType, onSuccess, onError);
+            if (texture.blobURL) {
+                sourceURL = texture.blobURL;
             }
             else {
-                Tools.LoadFile(runtime.rootUrl + source.uri, data => {
-                    GLTFLoader.CreateTextureAsync(runtime, textureInfo, new Uint8Array(data), source.mimeType, onSuccess, onError);
-                }, null, null, true, onError);
-            }
-        }
-
-        public static CreateTextureAsync(runtime: IGLTFRuntime, textureInfo: IGLTFTextureInfo, buffer: ArrayBufferView, mimeType: string, onSuccess: (babylonTexture: Texture) => void, onError: () => void): void {
-            var texture = runtime.gltf.textures[textureInfo.index];
-
-            if (!texture || texture.source === undefined) {
-                onError();
-                return;
+                if (source.uri === undefined) {
+                    var bufferView = runtime.gltf.bufferViews[source.bufferView];
+                    var buffer = GLTFUtils.GetBufferFromBufferView(runtime, bufferView, 0, bufferView.byteLength, EComponentType.UNSIGNED_BYTE);
+                    texture.blobURL = URL.createObjectURL(new Blob([buffer], { type: source.mimeType }));
+                    sourceURL = texture.blobURL;
+                }
+                else if (GLTFUtils.IsBase64(source.uri)) {
+                    var decodedBuffer = new Uint8Array(GLTFUtils.DecodeBase64(source.uri));
+                    texture.blobURL = URL.createObjectURL(new Blob([decodedBuffer], { type: source.mimeType }));
+                    sourceURL = texture.blobURL;
+                }
             }
 
-            if (texture.babylonTexture) {
-                onSuccess(texture.babylonTexture);
-                return;
-            }
+            GLTFLoader._createTextureAsync(runtime, texture, texCoord, sourceURL, onSuccess, onError);
+        }
 
+        private static _createTextureAsync(runtime: IGLTFRuntime, texture: IGLTFTexture, texCoord: number, url: string, onSuccess: (babylonTexture: Texture) => void, onError: () => void): void {
             var sampler: IGLTFSampler = texture.sampler ? runtime.gltf.samplers[texture.sampler] : {};
-
-            var createMipMaps =
-                (sampler.minFilter === ETextureMinFilter.NEAREST_MIPMAP_NEAREST) ||
-                (sampler.minFilter === ETextureMinFilter.NEAREST_MIPMAP_LINEAR) ||
-                (sampler.minFilter === ETextureMinFilter.LINEAR_MIPMAP_NEAREST) ||
-                (sampler.minFilter === ETextureMinFilter.LINEAR_MIPMAP_LINEAR);
-
+            var noMipMaps = (sampler.minFilter === ETextureMinFilter.NEAREST || sampler.minFilter === ETextureMinFilter.LINEAR);
             var samplingMode = Texture.BILINEAR_SAMPLINGMODE;
 
-            var blob = new Blob([buffer], { type: mimeType });
-            var blobURL = URL.createObjectURL(blob);
-            var revokeBlobURL = () => URL.revokeObjectURL(blobURL);
-            texture.babylonTexture = new Texture(blobURL, runtime.babylonScene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
-            texture.babylonTexture.coordinatesIndex = textureInfo.texCoord === undefined ? 0 : textureInfo.texCoord;
-            texture.babylonTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);
-            texture.babylonTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);
-            texture.babylonTexture.name = texture.name;
+            var babylonTexture = new Texture(url, runtime.babylonScene, noMipMaps, true, samplingMode, () => {
+                onSuccess(babylonTexture);
+            }, onError);
+
+            babylonTexture.coordinatesIndex = texCoord;
+            babylonTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);
+            babylonTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);
+            babylonTexture.name = texture.name;
 
-            onSuccess(texture.babylonTexture);
+            // Cache the texture
+            texture.babylonTextures = texture.babylonTextures || [];
+            texture.babylonTextures[texCoord] = babylonTexture;
         }
 
         /**
         * Import meshes
         */
-        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void): boolean {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void): void {
             scene.useRightHandedSystem = true;
 
-            var runtime = this._createRuntime(scene, data, rootUrl, true);
+            var runtime = GLTFLoader._createRuntime(scene, data, rootUrl, true);
             if (!runtime) {
-                if (onError) onError();
+                onError();
                 return;
             }
 
@@ -1077,69 +1149,57 @@ module BABYLON.GLTF2 {
             }
 
             // Load buffers, materials, etc.
-            this._loadBuffersAsync(runtime, () => {
-                importMaterials(runtime);
-                postLoad(runtime);
-
-                if (!BABYLON.GLTFFileLoader.IncrementalLoading && onSuccess) {
+            GLTFLoader._loadBuffersAsync(runtime, () => {
+                GLTFLoader._loadMaterialsAsync(runtime, () => {
+                    postLoad(runtime);
                     onSuccess(meshes, null, skeletons);
-                }
+                }, onError);
             }, onError);
 
             if (BABYLON.GLTFFileLoader.IncrementalLoading && onSuccess) {
                 onSuccess(meshes, null, skeletons);
             }
-
-            return true;
         }
 
         /**
         * Load scene
         */
-        public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): boolean {
+        public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void {
             scene.useRightHandedSystem = true;
 
-            var runtime = this._createRuntime(scene, data, rootUrl, false);
+            var runtime = GLTFLoader._createRuntime(scene, data, rootUrl, false);
             if (!runtime) {
-                if (onError) onError();
-                return false;
+                onError();
+                return;
             }
 
             importScene(runtime);
 
-            this._loadBuffersAsync(runtime, () => {
-                importMaterials(runtime);
-                postLoad(runtime);
-
-                if (!BABYLON.GLTFFileLoader.IncrementalLoading) {
+            GLTFLoader._loadBuffersAsync(runtime, () => {
+                GLTFLoader._loadMaterialsAsync(runtime, () => {
+                    postLoad(runtime);
                     onSuccess();
-                }
+                }, onError);
             }, onError);
-
-            if (BABYLON.GLTFFileLoader.IncrementalLoading) {
-                onSuccess();
-            }
-
-            return true;
         }
 
-        private _loadBuffersAsync(runtime: IGLTFRuntime, onSuccess: () => void, onError: () => void): void {
+        private static _loadBuffersAsync(runtime: IGLTFRuntime, onSuccess: () => void, onError: () => void): void {
             if (runtime.gltf.buffers.length == 0) {
                 onSuccess();
                 return;
             }
 
-            var loadedCount = 0;
+            var successCount = 0;
             runtime.gltf.buffers.forEach((buffer, index) => {
                 this._loadBufferAsync(runtime, index, () => {
-                    if (++loadedCount >= runtime.gltf.buffers.length) {
+                    if (++successCount === runtime.gltf.buffers.length) {
                         onSuccess();
                     }
                 }, onError);
             });
         }
 
-        private _loadBufferAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): void {
+        private static _loadBufferAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): void {
             var buffer = runtime.gltf.buffers[index];
 
             if (buffer.uri === undefined) {
@@ -1161,7 +1221,24 @@ module BABYLON.GLTF2 {
             }
         }
 
-        private _createRuntime(scene: Scene, data: IGLTFLoaderData, rootUrl: string, importOnlyMeshes: boolean): IGLTFRuntime {
+        private static _loadMaterialsAsync(runtime: IGLTFRuntime, onSuccess: () => void, onError: () => void): void {
+            var materials = runtime.gltf.materials;
+            if (!materials) {
+                onSuccess();
+                return;
+            }
+
+            var successCount = 0;
+            for (var i = 0; i < materials.length; i++) {
+                GLTFLoaderExtension.LoadMaterialAsync(runtime, i, () => {
+                    if (++successCount === materials.length) {
+                        onSuccess();
+                    }
+                }, onError);
+            }
+        }
+
+        private static _createRuntime(scene: Scene, data: IGLTFLoaderData, rootUrl: string, importOnlyMeshes: boolean): IGLTFRuntime {
             var runtime: IGLTFRuntime = {
                 gltf: <IGLTF>data.json,
 

+ 25 - 6
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -15,7 +15,7 @@ module BABYLON.GLTF2 {
         protected postCreateRuntime(runtime: IGLTFRuntime): void {}
 
         // Return true to stop other extensions from loading materials.
-        protected loadMaterial(runtime: IGLTFRuntime, index: number): boolean { return false; }
+        protected loadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): boolean { return false; }
 
         // ---------
         // Utilities
@@ -28,19 +28,38 @@ module BABYLON.GLTF2 {
             }
         }
 
-        public static LoadMaterial(runtime: IGLTFRuntime, index: number): void {
+        public static LoadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): void {
             for (var extensionName in GLTFLoader.Extensions) {
                 var extension = GLTFLoader.Extensions[extensionName];
-                if (extension.loadMaterial(runtime, index)) {
+                if (extension.loadMaterialAsync(runtime, index, onSuccess, onError)) {
                     return;
                 }
             }
 
             var material = GLTFLoader.LoadMaterial(runtime, index);
-            if (material) {
-                GLTFLoader.LoadMetallicRoughnessMaterialProperties(runtime, material);
-                GLTFLoader.LoadCommonMaterialProperties(runtime, material);
+            if (!material) {
+                onSuccess();
+                return;
             }
+
+            var metallicRoughnessPropertiesSuccess = false;
+            var commonPropertiesSuccess = false;
+
+            var checkSuccess = () => {
+                if (metallicRoughnessPropertiesSuccess && commonPropertiesSuccess) {
+                    onSuccess();
+                }
+            }
+
+            GLTFLoader.LoadMetallicRoughnessMaterialPropertiesAsync(runtime, material, () => {
+                metallicRoughnessPropertiesSuccess = true;
+                checkSuccess();
+            }, onError);
+
+            GLTFLoader.LoadCommonMaterialPropertiesAsync(runtime, material, () => {
+                commonPropertiesSuccess = true;
+                checkSuccess();
+            }, onError);
         }
     }
 }

+ 6 - 4
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -14,6 +14,7 @@ module BABYLON.GLTF2 {
         UNSIGNED_BYTE = 5121,
         SHORT = 5122,
         UNSIGNED_SHORT = 5123,
+        UNSIGNED_INT = 5125,
         FLOAT = 5126
     }
 
@@ -53,12 +54,12 @@ module BABYLON.GLTF2 {
 
     export enum ETextureMagFilter {
         NEAREST = 9728,
-        LINEAR = 9728,
+        LINEAR = 9729,
     }
 
     export enum ETextureMinFilter {
         NEAREST = 9728,
-        LINEAR = 9728,
+        LINEAR = 9729,
         NEAREST_MIPMAP_NEAREST = 9984,
         LINEAR_MIPMAP_NEAREST = 9985,
         NEAREST_MIPMAP_LINEAR = 9986,
@@ -292,8 +293,9 @@ module BABYLON.GLTF2 {
         target?: ETextureTarget;
         type?: ETextureType;
 
-        // Babylon.js values (optimize)
-        babylonTexture?: Texture;
+        // Babylon.js values (optimize, one per coordinate index)
+        babylonTextures: Texture[];
+        blobURL: string;
     }
 
     export interface IGLTFTextureInfo {

+ 1 - 0
loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts

@@ -92,6 +92,7 @@ module BABYLON.GLTF2 {
                 case EComponentType.UNSIGNED_BYTE: return new Uint8Array(buffer, byteOffset, byteLength);
                 case EComponentType.SHORT: return new Int16Array(buffer, byteOffset, byteLength);
                 case EComponentType.UNSIGNED_SHORT: return new Uint16Array(buffer, byteOffset, byteLength);
+                case EComponentType.UNSIGNED_INT: return new Uint32Array(buffer, byteOffset, byteLength);
                 default: return new Float32Array(buffer, byteOffset, byteLength);
             }
         }

+ 29 - 2
loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts

@@ -14,25 +14,45 @@ module BABYLON.GLTF2 {
             super("KHR_materials_pbrSpecularGlossiness");
         }
 
-        protected loadMaterial(runtime: IGLTFRuntime, index: number): boolean {
+        protected loadMaterialAsync(runtime: IGLTFRuntime, index: number, onSuccess: () => void, onError: () => void): boolean {
             var material = GLTFLoader.LoadMaterial(runtime, index);
             if (!material || !material.extensions) return false;
 
             var properties: IGLTFMaterialsPbrSpecularGlossiness = material.extensions[this.name];
             if (!properties) return false;
 
+            //
+            // Load Factors
+            //
+
             material.babylonMaterial.albedoColor = properties.diffuseFactor ? Color3.FromArray(properties.diffuseFactor) : new Color3(1, 1, 1);
             material.babylonMaterial.reflectivityColor = properties.specularFactor ? Color3.FromArray(properties.specularFactor) : new Color3(1, 1, 1);
             material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
 
+            //
+            // Load Textures
+            //
+
+            var commonMaterialPropertiesSuccess = false;
+
+            var checkSuccess = () => {
+                if ((!properties.diffuseTexture || material.babylonMaterial.albedoTexture) &&
+                    (!properties.specularGlossinessTexture || material.babylonMaterial.reflectivityTexture) &&
+                    commonMaterialPropertiesSuccess) {
+                    onSuccess();
+                }
+            };
+
             if (properties.diffuseTexture) {
                 GLTFLoader.LoadTextureAsync(runtime, properties.diffuseTexture,
                     texture => {
                         material.babylonMaterial.albedoTexture = texture;
                         GLTFLoader.LoadAlphaProperties(runtime, material);
+                        checkSuccess();
                     },
                     () => {
                         Tools.Warn("Failed to load diffuse texture");
+                        onError();
                     });
             }
 
@@ -41,13 +61,20 @@ module BABYLON.GLTF2 {
                     texture => {
                         material.babylonMaterial.reflectivityTexture = texture;
                         material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
+                        checkSuccess();
                     },
                     () => {
                         Tools.Warn("Failed to load metallic roughness texture");
+                        onError();
                     });
             }
 
-            GLTFLoader.LoadCommonMaterialProperties(runtime, material);
+            GLTFLoader.LoadCommonMaterialPropertiesAsync(runtime, material,
+                () => {
+                    commonMaterialPropertiesSuccess = true;
+                    checkSuccess();
+                }, onError);
+
             return true;
         }
     }

+ 26 - 16
loaders/src/glTF/README.md

@@ -1,31 +1,38 @@
 # Babylon.js glTF File Loader
 
 # Usage
-The glTF file loader is a SceneLoader plugin. The loader supports glTF version 1.0 and 2.0 and will use the correct loader based on the glTF version string. Include the version support that you want in any combination.
+The glTF file loader is a SceneLoader plugin.
+
+## Step 1 - Include the glTF File Loader
+
+**Full Version**
+
+This loader supports both glTF 1.0 and 2.0 and will use the correct loader based on the glTF version string.
 
-Both versions:
 ```
 <script src="babylon.js"></script>
 <script src="babylon.glTFFileLoader.js"></script>
-<script src="babylon.glTF1Loader.js"></script>
-<script src="babylon.glTF2Loader.js"></script>
 ```
 
-Version 1 only:
+**Version 1 Only**
+
+This loader supports only glTF 1.0 and will fail to load glTF 2.0.
+
 ```
 <script src="babylon.js"></script>
-<script src="babylon.glTFFileLoader.js"></script>
-<script src="babylon.glTF1Loader.js"></script>
+<script src="babylon.glTF1FileLoader.js"></script>
 ```
 
-Version 2 only:
+**Version 2 Only**
+
+This loader supports only glTF 2.0 and will fail to load glTF 1.0.
+
 ```
 <script src="babylon.js"></script>
-<script src="babylon.glTFFileLoader.js"></script>
-<script src="babylon.glTF2Loader.js"></script>
+<script src="babylon.glTF2FileLoader.js"></script>
 ```
 
-And then, call the scene loader:
+## Step 2 - Call the Scene Loader
 ```
 BABYLON.SceneLoader.Load("./", "duck.gltf", engine, function (scene) { 
    // do somethings with the scene
@@ -40,18 +47,20 @@ BABYLON.SceneLoader.ImportMesh(["myMesh1", "myMesh2", "..."], "./", "duck.gltf",
 });
 ```
 
+## Step 3 (V1 Only) - Optionally Specify Flags
+
 If you want to disable incremental loading, you can set the property `IncrementalLoading` to false.
-Then, you'll be able to be called back with all geometries, shaders (V1), PBR materials (V2) loaded. Textures are always loaded asynchronously. For example, you can retrieve the real bounding infos of a mesh loaded when incremental loading is disabled.
+Then, you'll be able to be called back with all geometries and shaders loaded. Textures are always loaded asynchronously. For example, you can retrieve the real bounding infos of a mesh loaded when incremental loading is disabled.
 ```
 BABYLON.GLTFFileLoader.IncrementalLoading = false; // true by default
 ```
 
-(V1 only) In order to work with homogeneous coordinates (that can be available with some converters and exporters):
+In order to work with homogeneous coordinates (that can be available with some converters and exporters):
 ```
 BABYLON.GLTFFileLoader.HomogeneousCoordinates = true; // false by default
 ```
 
-## Supported features
+# Supported Features
 * Load scenes (SceneLoader.Load and SceneLoader.Append)
 * Support of ImportMesh function
 * Import geometries
@@ -71,8 +80,9 @@ BABYLON.GLTFFileLoader.HomogeneousCoordinates = true; // false by default
 * Handle dummy nodes (empty nodes)
 * PBR materials (V2 only)
 
-## To improve
+# Future Improvements
 * Test on more geometries
 * Test on more animated models
 * Test on more skinned models
-* Improve shaders support (glitches with samplers can appear in particular configurations)
+* Improve shaders support (V1 only) (glitches with samplers can appear in particular configurations)
+* Add support for morph targets (V2 only)

+ 9 - 7
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -7,8 +7,8 @@ module BABYLON {
     }
 
     export interface IGLTFLoader {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror?: () => void) => boolean;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => boolean;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
     }
 
     export class GLTFFileLoader implements ISceneLoaderPluginAsync {
@@ -23,21 +23,23 @@ module BABYLON {
             ".glb": { isBinary: true }
         };
 
-        public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void): boolean {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void {
             var loaderData = GLTFFileLoader._parse(data);
             var loader = this._getLoader(loaderData);
             if (!loader) {
-                return false;
+                onError();
+                return;
             }
 
-            return loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onSuccess, onError);
+            loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onSuccess, onError);
         }
 
-        public loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): boolean {
+        public loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): void {
             var loaderData = GLTFFileLoader._parse(data);
             var loader = this._getLoader(loaderData);
             if (!loader) {
-                return false;
+                onError();
+                return;
             }
 
             return loader.loadAsync(scene, loaderData, rootUrl, onSuccess, onError);

+ 0 - 72
localDev/src/index.js

@@ -1,72 +0,0 @@
-
-
-var globals = {};
-
-var createScene = function()
-{
-    // This creates a basic Babylon Scene object (non-mesh)
-    var scene = new BABYLON.Scene(engine);
-
-    // This creates and positions a free camera (non-mesh)
-    var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -5), scene);
-
-    // This targets the camera to scene origin
-    camera.setTarget(BABYLON.Vector3.Zero());
-
-    // This attaches the camera to the canvas
-    camera.attachControl(canvas, true);
-
-    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
-    var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
-
-    // Default intensity is 1. Let's dim the light a small amount
-    light.intensity = 0.7;
-
-    var material0 = new BABYLON.StandardMaterial("mat0", scene);
-    material0.diffuseColor = new BABYLON.Color3(1, 0, 0);
-    //material0.bumpTexture = new BABYLON.Texture("normalMap.jpg", scene);
-   
-    var material1 = new BABYLON.StandardMaterial("mat1", scene);
-    material1.diffuseColor = new BABYLON.Color3(0, 0, 1);
-    
-    var material2 = new BABYLON.StandardMaterial("mat2", scene);
-    material2.emissiveColor = new BABYLON.Color3(0.4, 0, 0.4);
-
-    var multimat = new BABYLON.MultiMaterial("multi", scene);
-    multimat.subMaterials.push(material0);
-    multimat.subMaterials.push(material1);
-    multimat.subMaterials.push(material2);
-
-    globals.multimat = multimat;
-
-    var sphere = BABYLON.Mesh.CreateSphere("Sphere0", 16, 3, scene);
-    sphere.material = multimat;
-
-    sphere.subMeshes = [];
-    var verticesCount = sphere.getTotalVertices();
-
-    sphere.subMeshes.push(new BABYLON.SubMesh(0, 0, verticesCount, 0, 900, sphere));
-    sphere.subMeshes.push(new BABYLON.SubMesh(1, 0, verticesCount, 900, 900, sphere));
-    sphere.subMeshes.push(new BABYLON.SubMesh(2, 0, verticesCount, 1800, 2088, sphere));
-
- //   material0.diffuseTexture = new BABYLON.Texture("/assets/textures/leopard_fur.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE); 
-
-    scene.actionManager = new BABYLON.ActionManager(scene);
-    scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyUpTrigger, function (evt) {
-        if (evt.sourceEvent.key == "t")
-        {
-            globals.multimat.subMaterials[0].diffuseColor = new BABYLON.Color3(1, 1, 1);
-            globals.multimat.subMaterials[0].diffuseTexture = new BABYLON.Texture("/assets/textures/leopard_fur.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
-        }
-        else if (evt.sourceEvent.key == "m")
-        {
-            var material0 = new BABYLON.StandardMaterial("mat0", scene);
-            material0.diffuseColor = new BABYLON.Color3(0, 1, 0);
-            material0.diffuseTexture = new BABYLON.Texture("/assets/textures/leopard_fur.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
-
-            globals.multimat.subMaterials[0] = material0; 
-        }
-    }));
-
-    return scene;
-};

+ 0 - 3
sandbox/index-local.html

@@ -36,9 +36,6 @@
                 <li id="btnFullscreen">
                     <img src="./Assets/BtnFullscreen.png" alt="Switch the scene to full screen" title="Switch the scene to full screen" />
                 </li>
-                <li id="btnCamera">
-                    <img src="./Assets/BtnCamera.png" alt="Toggle the camera" title="Toggle the camera" />
-                </li>
                 <li id="btnPerf">
                     <img src="./Assets/BtnPerf.png" alt="Display inspector" title="Display inspector" />
                 </li>

+ 3 - 3
sandbox/index.css

@@ -191,7 +191,7 @@ a {
     background-position: center;
 }
 
-#btnFullscreen , #btnCamera {
+#btnFullscreen {
     margin-top: 10px;
     margin-right: 25px;
 }
@@ -253,12 +253,12 @@ li {
     -webkit-transform: translateX(120%);
 }
 
-#btnFullscreen, #btnCamera, #btnPerf, #btnFiles {
+#btnFullscreen, #btnPerf, #btnFiles {
      -webkit-transition: -webkit-transform 0.15s ease-in-out;
      transition: transform 0.15s ease-in-out;
 }
 
-#btnFullscreen:hover, #btnCamera:hover, #btnPerf:hover, #btnFiles:hover {
+#btnFullscreen:hover, #btnPerf:hover, #btnFiles:hover {
     -webkit-transform: scale(0.9);
     transform: scale(0.9);
 }

+ 0 - 3
sandbox/index.html

@@ -32,9 +32,6 @@
                 <li id="btnFullscreen">
                     <img src="./Assets/BtnFullscreen.png" alt="Switch the scene to full screen" title="Switch the scene to full screen" />
                 </li>
-                <li id="btnCamera">
-                    <img src="./Assets/BtnCamera.png" alt="Toggle the camera" title="Toggle the camera" />
-                </li>
                 <li id="btnPerf">
                     <img src="./Assets/BtnPerf.png" alt="Display debug & performance layer" title="Display debug & performance layer" />
                 </li>

+ 15 - 50
sandbox/index.js

@@ -17,9 +17,6 @@ if (BABYLON.Engine.isSupported()) {
     var currentHelpCounter;
     var currentScene;
     var enableDebugLayer = false;
-    var enableArcRotateCamera = false;
-    var arcRotateCamera;
-    var defaultCamera;
 
     currentHelpCounter = localStorage.getItem("helpcounter");
 
@@ -50,6 +47,13 @@ if (BABYLON.Engine.isSupported()) {
         document.title = "BabylonJS - " + sceneFile.name;
         // Fix for IE, otherwise it will change the default filter for files selection after first use
         htmlInput.value = "";
+
+        // Attach camera to canvas inputs
+        if (!currentScene.activeCamera || currentScene.lights.length === 0) {     
+            currentScene.createDefaultCameraOrLight(true);
+        }
+        currentScene.activeCamera.attachControl(canvas);
+
         // In case of error during loading, meshes will be empty and clearColor is set to red
         if (currentScene.meshes.length === 0 && currentScene.clearColor.r === 1 && currentScene.clearColor.g === 0 && currentScene.clearColor.b === 0) {
             document.getElementById("logo").className = "";
@@ -71,19 +75,6 @@ if (BABYLON.Engine.isSupported()) {
                 currentScene.activeCamera.keysRight.push(69); // E
                 currentScene.activeCamera.keysRight.push(68); // D
             }
-            defaultCamera = currentScene.activeCamera;
-            var worldExtends = currentScene.getWorldExtends();
-            var worldCenter = worldExtends.min.add(worldExtends.max.subtract(worldExtends.min).scale(0.5));
-            arcRotateCamera = new BABYLON.ArcRotateCamera("arcRotateCamera", 0, 0, 10, BABYLON.Vector3.Zero(), currentScene);
-            arcRotateCamera.setPosition(new BABYLON.Vector3(worldCenter.x, worldCenter.y, worldExtends.min.z - (worldExtends.max.z - worldExtends.min.z)));
-            arcRotateCamera.setTarget(worldCenter);
-            arcRotateCamera.wheelPrecision = 100.0;
-            arcRotateCamera.minZ = 0.1;
-            arcRotateCamera.maxZ = 1000;
-            if(enableArcRotateCamera){
-                currentScene.activeCamera = arcRotateCamera;
-                currentScene.activeCamera.attachControl(canvas);
-            }
         }
     };
 
@@ -98,25 +89,14 @@ if (BABYLON.Engine.isSupported()) {
     });
     htmlInput.addEventListener('change', function (event) {
         var filestoLoad;
-            // Handling data transfer via drag'n'drop
-            if (event && event.dataTransfer && event.dataTransfer.files) {
-                filesToLoad = event.dataTransfer.files;
-            }
-            // Handling files from input files
-            if (event && event.target && event.target.files) {
-                filesToLoad = event.target.files;
-            }
-            if (filesToLoad && filesToLoad.length > 0) {
-            enableArcRotateCamera= false;
-            for (var i = 0; i < filesToLoad.length; i++) {
-                    var extension = filesToLoad[i].name.split('.').pop();
-                    if (extension === "gltf" || extension === "glb")
-                    {       
-                         enableArcRotateCamera= true;
-                         break;
-                    }
-                }
-            }
+        // Handling data transfer via drag'n'drop
+        if (event && event.dataTransfer && event.dataTransfer.files) {
+            filesToLoad = event.dataTransfer.files;
+        }
+        // Handling files from input files
+        if (event && event.target && event.target.files) {
+            filesToLoad = event.target.files;
+        }
         filesInput.loadFiles(event);
     }, false);
     btnFullScreen.addEventListener('click', function () {
@@ -134,21 +114,6 @@ if (BABYLON.Engine.isSupported()) {
             }
         }
     }, false);
-    btnCamera.addEventListener('click', function () {
-        if (currentScene) {
-            if (!enableArcRotateCamera) {
-                currentScene.activeCamera = arcRotateCamera;
-                currentScene.activeCamera.attachControl(canvas);
-                enableArcRotateCamera = true;
-            }
-            else {
-                currentScene.activeCamera = defaultCamera;
-                currentScene.activeCamera.attachControl(canvas);
-                enableArcRotateCamera = false;
-            }
-        }
-    }, false);
-
     // The help tips will be displayed only 5 times
     if (currentHelpCounter < 5) {
         help01.className = "help shown";

+ 5 - 1
src/Debug/babylon.debugLayer.ts

@@ -46,7 +46,11 @@ module BABYLON {
 
         public hide() {
             if (this._inspector) {
-                this._inspector.dispose();
+                try {
+                    this._inspector.dispose();
+                } catch (e) {
+                    // If the inspector has been removed directly from the inspector tool
+                }
                 this._inspector = null;
             }
         }

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

@@ -2,6 +2,7 @@
     export interface IShadowGenerator {
         getShadowMap(): RenderTargetTexture;
  
+        isReady(subMesh: SubMesh, useInstances: boolean): boolean;
         dispose(): void;
     }
  

+ 2 - 2
src/Loading/babylon.sceneLoader.ts

@@ -13,8 +13,8 @@
 
     export interface ISceneLoaderPluginAsync {
         extensions: string | ISceneLoaderPluginExtensions;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: any, rootUrl: string, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror?: () => void) => void;
-        loadAsync: (scene: Scene, data: string, rootUrl: string, onsuccess: () => void, onerror: () => void) => boolean;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: any, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
+        loadAsync: (scene: Scene, data: string, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
     }
 
     interface IRegisteredPlugin {

+ 25 - 6
src/Materials/babylon.material.ts

@@ -507,23 +507,42 @@
                 this._scene.materials.splice(index, 1);
             }
 
-            // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
-            if (forceDisposeEffect && this._effect) {
-                this._scene.getEngine()._releaseEffect(this._effect);
-                this._effect = null;
-            }
-
             // Remove from meshes
             for (index = 0; index < this._scene.meshes.length; index++) {
                 var mesh = this._scene.meshes[index];
 
                 if (mesh.material === this) {
                     mesh.material = null;
+                
+                    if ((<Mesh>mesh).geometry) {
+                        var geometry = (<Mesh>mesh).geometry;
+
+                        if (this.storeEffectOnSubMeshes) {
+                            for (var subMesh of mesh.subMeshes) {
+                                geometry._releaseVertexArrayObject(subMesh._materialEffect);
+                            }
+                        } else {
+                            geometry._releaseVertexArrayObject(this._effect)
+                        }
+                    }
                 }
             }
 
             this._uniformBuffer.dispose();
 
+            // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
+            if (forceDisposeEffect && this._effect) {
+                    if (this.storeEffectOnSubMeshes) {
+                        for (var subMesh of mesh.subMeshes) {
+                            this._scene.getEngine()._releaseEffect(subMesh._materialEffect); 
+                        }
+                    } else {
+                        this._scene.getEngine()._releaseEffect(this._effect);                    
+                    }
+
+                this._effect = null;
+            }
+            
             // Callback
             this.onDisposeObservable.notifyObservers(this);
 

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

@@ -1405,8 +1405,8 @@
 
                     // Colors
                     if (this._defines.METALLICWORKFLOW) {
-                        PBRMaterial._scaledReflectivity.r = this.metallic === undefined ? 1 : this.metallic;
-                        PBRMaterial._scaledReflectivity.g = this.roughness === undefined ? 1 : this.roughness;
+                        PBRMaterial._scaledReflectivity.r = (this.metallic === undefined || this.metallic === null) ? 1 : this.metallic;
+                        PBRMaterial._scaledReflectivity.g = (this.roughness === undefined || this.roughness === null) ? 1 : this.roughness;
                         this._uniformBuffer.updateColor4("vReflectivityColor", PBRMaterial._scaledReflectivity, 0);
                     }
                     else {

+ 6 - 1
src/Materials/babylon.standardMaterial.ts

@@ -1118,7 +1118,12 @@ module BABYLON {
         }
 
         public clone(name: string): StandardMaterial {
-            return SerializationHelper.Clone(() => new StandardMaterial(name, this.getScene()), this);
+            var result = SerializationHelper.Clone(() => new StandardMaterial(name, this.getScene()), this);
+
+            result.name = name;
+            result.id = name;
+
+            return result;
         }
 
         public serialize(): any {

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

@@ -419,7 +419,7 @@
             if (index === -1) {
                 return;
             }
-            this._lightSources.slice(index, 1);       
+            this._lightSources.splice(index, 1);       
         }
 
         private _markSubMeshesAsDirty(func: (defines: MaterialDefines) => void) {

+ 11 - 0
src/Mesh/babylon.geometry.ts

@@ -348,6 +348,17 @@
             return this._indexBuffer;
         }
 
+        public _releaseVertexArrayObject(effect: Effect) {
+            if (!effect) {
+                return;
+            }
+            
+            if (this._vertexArrayObjects[effect.key]) {
+                this._engine.releaseVertexArrayObject(this._vertexArrayObjects[effect.key]);
+                delete this._vertexArrayObjects[effect.key];
+            }
+        }
+
         public releaseForMesh(mesh: Mesh, shouldDispose?: boolean): void {
             var meshes = this._meshes;
             var index = meshes.indexOf(mesh);

+ 1 - 1
src/Mesh/babylon.subMesh.ts

@@ -16,7 +16,7 @@
         public _id: number;
 
         public _materialDefines: MaterialDefines;
-        private _materialEffect: Effect;
+        public _materialEffect: Effect;
         private _currentMaterial: Material;
 
         public get effect(): Effect {

+ 0 - 30
src/Tools/babylon.extendedGamepad.ts

@@ -59,12 +59,6 @@ module BABYLON {
 
         public update() {
             super.update();
-            // update this device's offset position from the attached camera, if provided
-            //if (this._poseControlledCamera && this._poseControlledCamera.deviceScaleFactor) {
-            //this.position.copyFrom(this._poseControlledCamera.position);
-            //this.rotationQuaternion.copyFrom(this._poseControlledCamera.rotationQuaternion);
-            //this.deviceScaleFactor = this._poseControlledCamera.deviceScaleFactor;
-            //}
             var pose: GamepadPose = this.vrGamepad.pose;
             this.updateFromDevice(pose);
 
@@ -85,12 +79,6 @@ module BABYLON {
 
                     this.devicePosition.scaleToRef(this.deviceScaleFactor, this._calculatedPosition);
                     this._calculatedPosition.addInPlace(this.position);
-
-                    // scale the position using the scale factor, add the device's position
-                    /*if (this._poseControlledCamera) {
-                        // this allows total positioning freedom - the device, the camera and the mesh can be individually controlled.
-                        this._calculatedPosition.addInPlace(this._poseControlledCamera.position);
-                    }*/
                 }
                 if (poseData.orientation) {
                     this.deviceRotationQuaternion.copyFromFloats(this.rawPose.orientation[0], this.rawPose.orientation[1], -this.rawPose.orientation[2], -this.rawPose.orientation[3]);
@@ -105,24 +93,6 @@ module BABYLON {
 
                     // if the camera is set, rotate to the camera's rotation
                     this.deviceRotationQuaternion.multiplyToRef(this.rotationQuaternion, this._calculatedRotation);
-
-                    /*if (this._poseControlledCamera) {
-                        Matrix.ScalingToRef(1, 1, 1, Tmp.Matrix[1]);
-                        this._calculatedRotation.toRotationMatrix(Tmp.Matrix[0]);
-                        Matrix.TranslationToRef(this._calculatedPosition.x, this._calculatedPosition.y, this._calculatedPosition.z, Tmp.Matrix[2]);
-
-                        //Matrix.Identity().multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[4]);
-                        Tmp.Matrix[1].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[5]);
-
-                        this._poseControlledCamera.getWorldMatrix().getTranslationToRef(Tmp.Vector3[0])
-
-                        Matrix.ComposeToRef(new Vector3(this.deviceScaleFactor, this.deviceScaleFactor, this.deviceScaleFactor), this._poseControlledCamera.rotationQuaternion, Tmp.Vector3[0], Tmp.Matrix[4]);
-                        Tmp.Matrix[5].multiplyToRef(Tmp.Matrix[2], Tmp.Matrix[1]);
-
-                        Tmp.Matrix[1].multiplyToRef(Tmp.Matrix[4], Tmp.Matrix[2]);
-                        Tmp.Matrix[2].decompose(Tmp.Vector3[0], this._calculatedRotation, this._calculatedPosition);
-
-                    }*/
                 }
             }
         }

+ 0 - 5
src/Tools/babylon.filesInput.ts

@@ -116,11 +116,6 @@
 
                     // Wait for textures and shaders to be ready
                     that._currentScene.executeWhenReady(() => {
-                        // Attach camera to canvas inputs
-                        if (!that._currentScene.activeCamera || that._currentScene.lights.length === 0) {     
-                            that._currentScene.createDefaultCameraOrLight();
-                        }
-                        that._currentScene.activeCamera.attachControl(that._canvas);
 
                         if (that._sceneLoadedCallback) {
                             that._sceneLoadedCallback(this._sceneFileToLoad, that._currentScene);

+ 9 - 3
src/babylon.engine.ts

@@ -3383,6 +3383,14 @@
             }
         }
 
+        public releaseEffects() {
+            for (var name in this._compiledEffects) {
+                this._gl.deleteProgram(this._compiledEffects[name]._program);
+            }
+
+            this._compiledEffects = {};
+        }
+
         // Dispose
         public dispose(): void {
             this.hideLoadingUI();
@@ -3398,9 +3406,7 @@
             Engine.audioEngine.dispose();
 
             // Release effects
-            for (var name in this._compiledEffects) {
-                this._gl.deleteProgram(this._compiledEffects[name]._program);
-            }
+            this.releaseEffects();
 
             // Unbind
             this.unbindAllAttributes();

+ 7 - 2
src/babylon.scene.ts

@@ -1458,6 +1458,8 @@
                 return false;
             }
             var index: number;
+
+            // Geometries
             for (index = 0; index < this._geometries.length; index++) {
                 var geometry = this._geometries[index];
 
@@ -1466,6 +1468,7 @@
                 }
             }
 
+            // Meshes
             for (index = 0; index < this.meshes.length; index++) {
                 var mesh = this.meshes[index];
 
@@ -3534,8 +3537,8 @@
 
                 if (createArcRotateCamera) {
                     camera = new ArcRotateCamera("default camera", 0, 0, 10, Vector3.Zero(), this);
-
                     camera.setPosition(new Vector3(worldCenter.x, worldCenter.y, worldExtends.min.z - (worldExtends.max.z - worldExtends.min.z)));
+                    camera.lowerRadiusLimit = 0.5;
                     camera.setTarget(worldCenter);
                 } else {
                     camera = new FreeCamera("default camera", Vector3.Zero(), this);
@@ -3543,7 +3546,9 @@
                     camera.position = new Vector3(worldCenter.x, worldCenter.y, worldExtends.min.z - (worldExtends.max.z - worldExtends.min.z));
                     camera.setTarget(worldCenter);
                 }
-
+                camera.minZ = 0.1;
+                var maxDist = worldExtends.max.subtract(worldExtends.min).length();
+                camera.wheelPrecision = 100.0 / maxDist;
                 this.activeCamera = camera;
             }
         }

BIN
tests/validation/LogoV3.jpg


BIN
tests/validation/ReferenceImages/Espilit.png


BIN
tests/validation/ReferenceImages/Flat2009.png


BIN
tests/validation/ReferenceImages/Heart.png


BIN
tests/validation/ReferenceImages/Hillvalley.png


BIN
tests/validation/ReferenceImages/SpaceDeK.png


BIN
tests/validation/ReferenceImages/Sponza.png


BIN
tests/validation/ReferenceImages/TheCar.png


BIN
tests/validation/ReferenceImages/Viper.png


BIN
tests/validation/ReferenceImages/WCafe.png


BIN
tests/validation/ReferenceImages/charting.png


BIN
tests/validation/ReferenceImages/csg.png


BIN
tests/validation/ReferenceImages/fog.png


BIN
tests/validation/ReferenceImages/fresnel.png


BIN
tests/validation/ReferenceImages/lines.png


BIN
tests/validation/ReferenceImages/mansion.png


BIN
tests/validation/ReferenceImages/polygon.png


BIN
tests/validation/ReferenceImages/retail.png


BIN
tests/validation/ReferenceImages/softShadows.png


+ 114 - 0
tests/validation/config.json

@@ -0,0 +1,114 @@
+{
+  "root": "https://cdn.rawgit.com/BabylonJS/Website/06ecbea7",
+  "tests": [   
+ {
+      "title": "Sponza",
+      "sceneFolder": "/Scenes/Sponza/",
+      "sceneFilename": "Sponza.babylon",
+      "referenceImage": "Sponza.png"
+    },    
+    {
+      "title": "Windows cafe",
+      "sceneFolder": "/Scenes/WCafe/",
+      "sceneFilename": "WCafe.babylon",
+      "referenceImage": "WCafe.png"
+    },
+    {
+      "title": "Espilit",
+      "sceneFolder": "/Scenes/Espilit/",
+      "sceneFilename": "Espilit.binary.babylon",
+      "referenceImage": "Espilit.png"
+    },
+    {
+      "title": "The car",
+      "sceneFolder": "/Scenes/TheCar/",
+      "sceneFilename": "TheCar.binary.babylon",
+      "referenceImage": "TheCar.png"
+    },
+    {
+      "title": "Viper",
+      "sceneFolder": "/Scenes/Viper/",
+      "sceneFilename": "Viper.babylon",
+      "referenceImage": "Viper.png"
+    },
+    {
+      "title": "Retail",
+      "sceneFolder": "/Scenes/Retail/",
+      "sceneFilename": "Retail.babylon",
+      "referenceImage": "Retail.png"
+    },
+    {
+      "title": "Hill Valley",
+      "sceneFolder": "/Scenes/hillvalley/",
+      "sceneFilename": "HillValley.incremental.babylon",
+      "referenceImage": "HillValley.png"
+    },
+    {
+      "title": "Heart",
+      "sceneFolder": "/Scenes/Heart/",
+      "sceneFilename": "Heart.babylon",
+      "referenceImage": "heart.png"
+    },
+    {
+      "title": "Mansion",
+      "sceneFolder": "/Scenes/Mansion/",
+      "sceneFilename": "Mansion.babylon",
+      "referenceImage": "Mansion.png"
+    },
+    {
+      "title": "SpaceDeK",
+      "sceneFolder": "/Scenes/SpaceDek/",
+      "sceneFilename": "SpaceDek.babylon",
+      "referenceImage": "SpaceDeK.png"
+    },
+    {
+      "title": "Flat2009",
+      "sceneFolder": "/Scenes/Flat2009/",
+      "sceneFilename": "Flat2009.babylon",
+      "referenceImage": "Flat2009.png"
+    },
+    {
+      "title": "CSG",
+      "scriptToRun": "/Demos/CSG/csg.js",
+      "functionToCall": "CreateCSGTestScene",
+      "referenceImage": "csg.png"
+    },
+    {
+      "title": "Charting",
+      "scriptToRun": "/Demos/Charting/charting.js",
+      "functionToCall": "CreateChartingTestScene",
+      "referenceImage": "charting.png"
+    },
+    {
+      "title": "Fog",
+      "scriptToRun": "/Demos/Fog/fog.js",
+      "functionToCall": "CreateFogScene",
+      "referenceImage": "fog.png"
+    },
+    {
+      "title": "Polygon",
+      "scriptToRun": "/Demos/Polygon/polygon.js",
+      "functionToCall": "CreatePolygonScene",
+      "referenceImage": "polygon.png"
+    },        
+    {
+      "title": "Soft Shadows",
+      "renderCount": 5,
+      "scriptToRun": "/Demos/SoftShadows/softShadows.js",
+      "functionToCall": "CreateSoftShadowsTestScene",
+      "referenceImage": "softShadows.png"
+    },
+    {
+      "title": "Fresnel",
+      "scriptToRun": "/Demos/Fresnel/fresnel.js",
+      "functionToCall": "CreateFresnelTestScene",
+      "referenceImage": "fresnel.png"
+    },
+    {
+      "title": "Lines",
+      "scriptToRun": "/Demos/Lines/lines.js",
+      "functionToCall": "CreateLinesTestScene",
+      "referenceImage": "lines.png"
+    }
+  ]
+}

+ 84 - 0
tests/validation/index.css

@@ -0,0 +1,84 @@
+html, body {
+    width: 100%;
+    height: 100%;
+    padding: 0;
+    margin: 0;
+    background-color: white;
+    background: url("LogoV3.jpg");
+    background-position: center center;
+    background-repeat: no-repeat;
+}
+
+.container {
+    width: calc(100% - 50px);
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: center;
+    align-items: center;
+    background: rgba(255, 255, 255, 0.6);
+    margin: auto;
+    margin-top: 10px;
+    margin-bottom: 10px;
+    outline: 2px solid black;
+    max-width: 1000px;   
+}
+
+.containerTitle {
+    width:100%;
+    order: 1;
+    display: flex;
+    background-color: rgba(0, 0, 0, 0.8);
+    height: 50px;
+}
+
+.title {
+    font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
+    font-size: 40px;
+    color: white;
+    text-align: center;
+    margin-left: 20px;
+    order: 1;
+}
+
+.result {
+    color:green;
+    font-size: 30px;
+    order: 2;
+    text-align: center;
+    margin-top: 5px;
+    margin-left: 20px;
+}
+
+.result.failed {
+    color:red;
+}
+
+.waitRing {
+    order: 3;
+    height: 40px;
+    margin-top: 5px;
+    margin-bottom: 5px;
+}
+
+.waitRing.hidden {
+    display: none;
+}
+
+.renderCanvas {
+    position:absolute;
+    transform: translateX(-600px);
+    width: 600px;
+    height: 400px;
+}
+
+.renderImage {
+    order: 1;
+    flex-basis: 50%;
+    width: 50%;
+}
+
+.resultImage {
+    width: 50%;
+    flex-basis: 50%;
+    order: 2;
+}

+ 14 - 0
tests/validation/index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<title>BabylonJS - Build validation page</title>
+	<link href="index.css" rel="stylesheet" />
+	<script src="../../Tools/DevLoader/BabylonLoader.js"></script>
+</head>
+<body>
+	<script>
+        BABYLONDEVTOOLS.Loader.require('validation.js')
+            .load();
+    </script>	
+</body>
+</html>

BIN
tests/validation/loading.gif


+ 222 - 0
tests/validation/validation.js

@@ -0,0 +1,222 @@
+"use strict";
+
+var engine;
+var canvas;
+var currentScene;
+var config;
+
+function compare(renderData, referenceCanvas) {
+    var width = referenceCanvas.width;
+    var height = referenceCanvas.height;
+    var size = width * height * 4;
+
+    var referenceContext = referenceCanvas.getContext("2d");
+
+    var referenceData = referenceContext.getImageData(0, 0, width, height);
+
+    var differencesCount = 0;
+    for (var index = 0; index < size; index += 4) {
+        if (renderData[index] === referenceData.data[index] &&
+            renderData[index + 1] === referenceData.data[index + 1] &&
+            renderData[index + 2] === referenceData.data[index + 2]) {
+            continue;
+        }
+
+        referenceData.data[index] = 255;
+        referenceData.data[index + 1] *= 0.5;
+        referenceData.data[index + 2] *= 0.5;
+        differencesCount++;
+    }
+
+    referenceContext.putImageData(referenceData, 0, 0);
+
+    return differencesCount;
+}
+
+function getRenderData(canvas, engine) {
+    var width = canvas.width;
+    var height = canvas.height;
+
+    var renderData = engine.readPixels(0, 0, width, height);
+    var numberOfChannelsByLine = width * 4;
+    var halfHeight = height / 2;
+
+    for (var i = 0; i < halfHeight; i++) {
+        for (var j = 0; j < numberOfChannelsByLine; j++) {
+            var currentCell = j + i * numberOfChannelsByLine;
+            var targetLine = height - i - 1;
+            var targetCell = j + targetLine * numberOfChannelsByLine;
+
+            var temp = renderData[currentCell];
+            renderData[currentCell] = renderData[targetCell];
+            renderData[targetCell] = temp;
+        }
+    }
+
+    return renderData;
+}
+
+function saveRenderImage(data, canvas) {
+    var width = canvas.width;
+    var height = canvas.height;
+    var screenshotCanvas = document.createElement('canvas');
+    screenshotCanvas.width = width;
+    screenshotCanvas.height = height;
+    var context = screenshotCanvas.getContext('2d');
+
+    var imageData = context.createImageData(width, height);
+    var castData = imageData.data;
+    castData.set(data);
+    context.putImageData(imageData, 0, 0);
+
+    return screenshotCanvas.toDataURL();
+}
+
+function evaluate(resultCanvas, result, renderImage, index, waitRing) {
+    var renderData = getRenderData(canvas, engine);
+
+    if (compare(renderData, resultCanvas) !== 0) {
+        result.classList.add("failed");
+        result.innerHTML = "×";
+        console.log("failed");
+    } else {
+        result.innerHTML = "✔";
+        console.log("validated");
+    }
+
+    waitRing.classList.add("hidden");
+
+    renderImage.src = saveRenderImage(renderData, canvas);
+
+    currentScene.dispose();
+
+    runTest(index + 1);
+}
+
+function processCurrentScene(test, resultCanvas, result, renderImage, index, waitRing) {
+    currentScene.executeWhenReady(function () {
+        var renderCount = test.renderCount || 1;
+
+        engine.runRenderLoop(function() {
+            currentScene.render();
+            renderCount--;
+
+            if (renderCount === 0) {
+                engine.stopRenderLoop();
+                evaluate(resultCanvas, result, renderImage, index, waitRing);
+            }
+        });
+
+    });
+}
+
+function runTest(index) {
+    if (index >= config.tests.length) {
+        return;
+    }
+
+    var test = config.tests[index];
+    var container = document.createElement("div");
+    container.id = "container#" + index;
+    container.className = "container";
+    document.body.appendChild(container);
+
+    var titleContainer = document.createElement("div");
+    titleContainer.className = "containerTitle";
+    container.appendChild(titleContainer);
+
+    var title = document.createElement("div");
+    title.className = "title";
+    titleContainer.appendChild(title);
+
+    var result = document.createElement("div");
+    result.className = "result";
+    titleContainer.appendChild(result);
+
+    var waitRing = document.createElement("img");
+    waitRing.className = "waitRing";
+    titleContainer.appendChild(waitRing);
+    waitRing.src = "loading.gif";
+
+    var resultCanvas = document.createElement("canvas");
+    resultCanvas.className = "resultImage";
+    container.appendChild(resultCanvas);
+
+    title.innerHTML = test.title;
+
+    console.log("Running " + test.title);
+
+    var resultContext = resultCanvas.getContext("2d");
+    var img = new Image();
+    img.onload = function () {
+        resultCanvas.width = img.width;
+        resultCanvas.height = img.height;
+        resultContext.drawImage(img, 0, 0);
+    }
+
+    img.src = "ReferenceImages/" + test.referenceImage;
+
+    var renderImage = new Image();
+    renderImage.className = "renderImage";
+    container.appendChild(renderImage);
+
+    location.href = "#" + container.id;
+
+    if (test.sceneFolder) {
+        BABYLON.SceneLoader.Load(config.root + test.sceneFolder, test.sceneFilename, engine, function (newScene) {
+            currentScene = newScene;
+            processCurrentScene(test, resultCanvas, result, renderImage, index, waitRing);
+        });
+    } else {
+        // Fix references
+        if (test.specificRoot) {
+            BABYLON.Tools.BaseUrl = config.root + test.specificRoot;
+        }
+
+        var request = new XMLHttpRequest();
+        request.open('GET', config.root + test.scriptToRun, true);
+
+        request.onreadystatechange = () => {
+            if (request.readyState === 4) {
+                request.onreadystatechange = null; 
+
+                var scriptToRun = request.responseText.replace(/..\/..\/assets\//g, config.root + "/Assets/");
+
+                console.log(scriptToRun);
+
+                currentScene = eval(scriptToRun + test.functionToCall + "(engine)");
+                processCurrentScene(test, resultCanvas, result, renderImage, index, waitRing);
+            }
+        };
+
+        request.send(null);
+        
+    }
+}
+
+BABYLON.SceneLoader.ShowLoadingScreen = false;
+BABYLON.Database.IDBStorageEnabled = false;
+BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental = true;
+
+canvas = document.createElement("canvas");
+canvas.className = "renderCanvas";
+document.body.appendChild(canvas);
+engine = new BABYLON.Engine(canvas, false);
+
+// Loading tests
+var xhr = new XMLHttpRequest();
+
+xhr.open("GET", "config.json", true);
+
+xhr.addEventListener("load",function() {
+    if (xhr.status === 200) {
+
+        config = JSON.parse(xhr.responseText);
+
+        // Run tests
+        runTest(0, engine);
+
+    }
+}, false);
+
+xhr.send();