Просмотр исходного кода

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

David Rousset 7 лет назад
Родитель
Сommit
b9512a97db
100 измененных файлов с 21596 добавлено и 22350 удалено
  1. 8525 8613
      Playground/babylon.d.txt
  2. 1 1
      Playground/debug.html
  3. 0 892
      Playground/examples/list.json
  4. 1 1
      Playground/index-local.html
  5. 1 1
      Playground/index.html
  6. 1 1
      Playground/indexStable.html
  7. 43 3
      Playground/js/index.js
  8. 7 3
      Tools/Gulp/config.json
  9. 1 1
      Tools/Gulp/gulpfile.js
  10. 1 2
      Viewer/src/configuration/types/default.ts
  11. 14 8
      Viewer/src/managers/sceneManager.ts
  12. 5 1
      Viewer/src/model/viewerModel.ts
  13. 14 2
      Viewer/tests/unit/src/viewer/sceneManager.ts
  14. 1 1
      Viewer/tsconfig.json
  15. 9422 9391
      dist/preview release/babylon.d.ts
  16. 47 47
      dist/preview release/babylon.js
  17. 98 21
      dist/preview release/babylon.max.js
  18. 98 21
      dist/preview release/babylon.no-module.max.js
  19. 29 29
      dist/preview release/babylon.worker.js
  20. 98 21
      dist/preview release/es6.js
  21. 0 0
      dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts
  22. 0 0
      dist/preview release/glTF2Interface/package.json
  23. 31 0
      dist/preview release/gui/babylon.gui.d.ts
  24. 166 10
      dist/preview release/gui/babylon.gui.js
  25. 2 2
      dist/preview release/gui/babylon.gui.min.js
  26. 31 0
      dist/preview release/gui/babylon.gui.module.d.ts
  27. 5 5
      dist/preview release/inspector/babylon.inspector.bundle.js
  28. 7 4
      dist/preview release/inspector/babylon.inspector.d.ts
  29. 98 65
      dist/preview release/inspector/babylon.inspector.js
  30. 4 4
      dist/preview release/inspector/babylon.inspector.min.js
  31. 39 98
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  32. 110 53
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  33. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  34. 49 195
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  35. 299 296
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  36. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  37. 49 210
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  38. 302 314
      dist/preview release/loaders/babylon.glTFFileLoader.js
  39. 4 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  40. 18 15
      dist/preview release/loaders/babylon.stlFileLoader.js
  41. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.min.js
  42. 49 210
      dist/preview release/loaders/babylonjs.loaders.d.ts
  43. 319 328
      dist/preview release/loaders/babylonjs.loaders.js
  44. 4 4
      dist/preview release/loaders/babylonjs.loaders.min.js
  45. 49 210
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  46. 1 0
      dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.d.ts
  47. 21 2
      dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.js
  48. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js
  49. 9 3
      dist/preview release/proceduralTexturesLibrary/babylon.grassProceduralTexture.js
  50. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js
  51. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.d.ts
  52. 3 3
      dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.js
  53. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.min.js
  54. 2 1
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.d.ts
  55. 33 8
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js
  56. 1 1
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js
  57. 2 1
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.module.d.ts
  58. 2 2
      dist/preview release/serializers/babylon.glTF2Serializer.d.ts
  59. 22 69
      dist/preview release/serializers/babylon.glTF2Serializer.js
  60. 2 2
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  61. 2 2
      dist/preview release/serializers/babylonjs.serializers.d.ts
  62. 17 64
      dist/preview release/serializers/babylonjs.serializers.js
  63. 2 2
      dist/preview release/serializers/babylonjs.serializers.min.js
  64. 2 2
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  65. 1 1
      dist/preview release/viewer/babylon.viewer.d.ts
  66. 44 44
      dist/preview release/viewer/babylon.viewer.js
  67. 437 361
      dist/preview release/viewer/babylon.viewer.max.js
  68. 1 1
      dist/preview release/viewer/babylon.viewer.module.d.ts
  69. 10 2
      dist/preview release/what's new.md
  70. 29 0
      gui/src/3D/controls/planePanel.ts
  71. 117 0
      gui/src/3D/controls/scatterPanel.ts
  72. 20 10
      gui/src/3D/controls/volumeBasedPanel.ts
  73. 3 0
      gui/src/3D/gui3DManager.ts
  74. 1 1
      inspector/src/Inspector.ts
  75. 5 5
      inspector/src/details/Property.ts
  76. 0 2
      inspector/src/details/PropertyLine.ts
  77. 2 2
      inspector/src/helpers/Helpers.ts
  78. 2 2
      inspector/src/tabs/ConsoleTab.ts
  79. 106 58
      inspector/src/tabs/GLTFTab.ts
  80. 1 1
      inspector/test/index.js
  81. 31 26
      loaders/src/STL/babylon.stlFileLoader.ts
  82. 3 20
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  83. 1 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  84. 1 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts
  85. 68 57
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  86. 155 228
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  87. 1 1
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  88. 137 139
      loaders/src/glTF/babylon.glTFFileLoader.ts
  89. 21 1
      proceduralTexturesLibrary/src/fire/babylon.fireProceduralTexture.ts
  90. 12 1
      proceduralTexturesLibrary/src/grass/babylon.grassProceduralTexture.ts
  91. 2 2
      proceduralTexturesLibrary/src/perlinNoise/babylon.perlinNoiseProceduralTexture.ts
  92. 2 1
      sandbox/index.js
  93. 1 1
      serializers/src/glTF/2.0/babylon.glTFAnimation.ts
  94. 1 1
      serializers/src/glTF/2.0/babylon.glTFData.ts
  95. 1 1
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  96. 32 84
      serializers/src/glTF/2.0/babylon.glTFMaterial.ts
  97. 1 1
      serializers/src/glTF/2.0/babylon.glTFUtilities.ts
  98. 101 0
      src/Behaviors/Mesh/babylon.multiPointerScaleBehavior.ts
  99. 74 37
      src/Behaviors/Mesh/babylon.pointerDragBehavior.ts
  100. 0 0
      src/Behaviors/Mesh/babylon.sixDofDragBehavior.ts

Разница между файлами не показана из-за своего большого размера
+ 8525 - 8613
Playground/babylon.d.txt


+ 1 - 1
Playground/debug.html

@@ -439,7 +439,7 @@
         </div>
         <div class="horizontalSeparator"></div>
         <input id="filterBar" type="text" placeholder="Filter examples...">
-        <img id="filterBarClear" src="http://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+        <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
     </div>
 
     <span class="label" id="fpsLabel">FPS</span>

+ 0 - 892
Playground/examples/list.json

@@ -1,892 +0,0 @@
-{
-    "examples": [
-        {
-            "title": "Animations",
-            "samples": [
-                {
-                    "title": "Bones 101",
-                    "doc": "https://doc.babylonjs.com/How_To/How_to_use_Bones_and_Skeletons",
-                    "icon": "icons/bones.jpg",
-                    "description": "Create complex animations by using skeletons and bones",
-                    "PGID": "#QY1WYT#0"
-                },                
-                {
-                    "title": "Animation blending",
-                    "doc": "https://doc.babylonjs.com/babylon101/Animations#animation-blending",
-                    "icon": "icons/animation_blending.jpg",
-                    "description": "Blend multiple animations together to move from on animation clip to another",
-                    "PGID": "#BCU1XR#0"
-                },
-                {
-                    "title": "Animation weights",
-                    "doc": "https://doc.babylonjs.com/babylon101/animations#animation-weights",
-                    "icon": "icons/animation_weight.jpg",
-                    "description": "Use weights to blend multiple animations together",
-                    "PGID": "#LL5BIQ#0"
-                },                
-                {
-                    "title": "Animation 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/animations",
-                    "icon": "icons/animations.png", 
-                    "description": "How to add animations",
-                    "PGID": "#QYFDDP#1"
-                },
-                {
-                    "title": "Easing functions",
-                    "doc": "https://doc.babylonjs.com/babylon101/animations#easing-functions",
-                    "icon": "icons/easing_functions.png", 
-                    "description": "Create animations with different easing functions",
-                    "PGID": "#8ZNVGR#0"
-                },
-                {
-                    "title": "Instanced bones",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons",
-                    "icon": "icons/instanced_bones.png", 
-                    "description": "Animated skeletons of people walking",
-                    "PGID": "#0K8EYN#0"
-                },
-                {
-                    "title": "Morph targets",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_morphtargets",
-                    "icon": "icons/morph_targets.jpg", 
-                    "description": "Morph a mesh between multiple targets",
-                    "PGID": "#2JDN66#0"
-                }                         
-            ]
-        },
-        {
-            "title": "Cameras",
-            "samples": [
-                {
-                    "title": "Cameras 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/cameras",
-                    "icon": "icons/cameras.png", 
-                    "description": "Types of cameras in babylonjs",
-                    "PGID": "#1A3M5C#0"
-                },
-                {
-                    "title": "Device orientation camera",
-                    "doc": "https://doc.babylonjs.com/babylon101/cameras#device-orientation-camera",
-                    "icon": "icons/deviceOrientationCamera.jpg",
-                    "description": "Camera that reacts to events such as a mobile device being tilted forward or back",
-                    "PGID": "#12WBC#185"
-                }
-            ]
-        },
-        {
-            "title": "GUI",
-            "samples": [
-                {
-                    "title": "GUI",
-                    "doc": "https://doc.babylonjs.com/how_to/gui",
-                    "icon": "icons/gui.png", 
-                    "description": "Babylons graphical user interface provides sliders, buttons, etc.",
-                    "PGID": "#3VMTI9#0"
-                }
-            ]
-        },
-        {
-            "title": "Interactions & events",
-            "samples": [
-                {
-                    "title": "Picking",
-                    "doc": "https://doc.babylonjs.com/babylon101/picking_collisions",
-                    "icon": "icons/picking.png", 
-                    "description": "Use mouse or touch to pick meshes on the screen",
-                    "PGID": "#NU4F6Y#0"
-                },
-                {
-                    "title": "Actions",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_actions",
-                    "icon": "icons/actions.png", 
-                    "description": "Actions are a simple way to add interactions in your scenes",
-                    "PGID": "#J19GYK#0"
-                },
-                {
-                    "title": "Drag and drop",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_actions",
-                    "icon": "icons/drag_and_drop.png", 
-                    "description": "Move meshes around a scene with a mouse",
-                    "PGID": "#UZ23UH#0"
-                },
-                {
-                    "title": "Pointer events handling",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_actions",
-                    "icon": "icons/pointer_events_handling.png", 
-                    "description": "Handle pointer input",
-                    "PGID": "#C245A1#0"
-                }
-            ]
-        },
-        {
-            "title": "Lights",
-            "samples": [
-                {
-                    "title": "Light projected texture",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#projection-texture",
-                    "icon": "icons/projected_texture.jpg",
-                    "description": "Project a texture from a spot light",
-                    "PGID": "#CQNGRK#0"
-                }, 
-                {
-                    "title": "Lights 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights",
-                    "icon": "icons/lights.png", 
-                    "description": "Add lights to a scene",
-                    "PGID": "#AQRDKW#0"
-                }, 
-                {
-                    "title": "Simultaneous lights",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights",
-                    "icon": "icons/sim_lights.jpg", 
-                    "description": "Use multiple lights on a single mesh",
-                    "PGID": "#ZU5TKG#0"
-                },
-                {
-                    "title": "Point light",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#the-point-light",
-                    "icon": "icons/pointLight.jpg",
-                    "description": "Light emitting from a single point",
-                    "PGID": "#20OAV9#0"
-                },
-                {
-                    "title": "Directional light",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#the-directional-light",
-                    "icon": "icons/directionalLight.jpg",
-                    "description": "The light is emitted from everywhere in the specified direction, and has an infinite range",
-                    "PGID": "#20OAV9#1"
-                },
-                {
-                    "title": "Spot lgiht",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#the-spot-light",
-                    "icon": "icons/spotLight.jpg",
-                    "description": "Defines a cone of light pointing in a direction",
-                    "PGID": "#20OAV9#3"
-                },
-                {
-                    "title": "Hemispheric light",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#the-hemispheric-light",
-                    "icon": "icons/hemLight.jpg",
-                    "description": "Simulate an ambient environment light",
-                    "PGID": "#20OAV9#5"
-                }      
-            ]
-        },
-        {
-            "title": "Loaders",
-            "samples": [
-                {
-                    "title": "Cornell box",
-                    "doc": "https://doc.babylonjs.com/how_to/load_from_any_file_type",
-                    "icon": "icons/cornell.jpg",
-                    "description": "Load a glTF file and setup the environment",
-                    "PGID": "#J5E230#54"
-                },
-                {
-                    "title": "Import meshes",
-                    "doc": "https://doc.babylonjs.com/how_to/load_from_any_file_type",
-                    "icon": "icons/import_meshes.png", 
-                    "description": "Load a mesh from a file and add it to the scene",
-                    "PGID": "#UKNERM#0"
-                },
-                {
-                    "title": "Load glTF model",
-                    "doc": "https://doc.babylonjs.com/how_to/load_from_any_file_type",
-                    "icon": "icons/load_gltf.jpg", 
-                    "description": "Show how to easily load a glTF model",
-                    "PGID": "#PN1NNI#0"
-                },
-                {
-                    "title": "Assets manager",
-                    "doc": "http://localhost:8080/How_To/How_to_use_AssetsManager",
-                    "icon": "icons/assets_manager.jpg", 
-                    "description": "Use AssetsManager to load multiple assets in a centralized way",
-                    "PGID": "#Y7XMAR#0"
-                },
-                {
-                    "title": "Asset container",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_assetcontainer",
-                    "icon": "icons/assetContainer.jpg",
-                    "description": "To add and remove assets from a scene an AssetContainer can be used.",
-                    "PGID": "#17MXFZ#0"
-                }                 
-            ]
-        },         
-        {
-            "title": "Materials",
-            "samples": [   
-                {
-                    "title": "MultiMaterial",
-                    "doc": "https://doc.babylonjs.com/how_to/multi_materials",
-                    "icon": "icons/multi_material.jpg",
-                    "description": "Apply multiple materials to a single mesh using MultiMaterial class",
-                    "PGID": "#2Q4S2S#0"
-                },                   
-                {
-                    "title": "ShaderMaterial",
-                    "doc": "https://doc.babylonjs.com/how_to/shader_material",
-                    "icon": "icons/custom_shader.jpg",
-                    "description": "Use ShaderMaterial to create advanced effects",
-                    "PGID": "#ATDL99#0"
-                },                 
-                {
-                    "title": "X-ray material with Fresnel",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_fresnelparameters",
-                    "icon": "icons/xRayFresnel.jpg",
-                    "description": "Use fresnel parameters to simulate an x-ray effect",
-                    "PGID": "#GK7FK#0"
-                },                         
-                {
-                    "title": "Materials",
-                    "doc": "https://doc.babylonjs.com/babylon101/materials",
-                    "icon": "icons/materials.png", 
-                    "description": "Create and add materials to a mesh",
-                    "PGID": "#DXARSP#0"
-                },
-                {
-                    "title": "PBR",
-                    "doc": "https://doc.babylonjs.com/how_to/physically_based_rendering",
-                    "icon": "icons/pbr.png", 
-                    "description": "Physically based rendering materials",
-                    "PGID": "#8MGKWK#0"
-                },
-                {
-                    "title": "Glossiness and roughness",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.standardmaterial",
-                    "icon": "icons/glossinessAndRoughness.jpg",
-                    "description": "Demonstration of glossiness and rouphness features of standard material",
-                    "PGID": "#RNBKQ#8"
-                },
-                {
-                    "title": "Cell Shading",
-                    "doc": "https://doc.babylonjs.com/extensions/cell",
-                    "icon": "icons/cell_shading.jpg", 
-                    "description": "Cell shading material",
-                    "PGID": "#0ZB1A3#1"
-                },
-                {
-                    "title": "Fur",
-                    "doc": "https://doc.babylonjs.com/extensions/fur",
-                    "icon": "icons/fur.jpg", 
-                    "description": "Fur material",
-                    "PGID": "#VABI8A#0"
-                },
-                {
-                    "title": "Fire",
-                    "doc": "https://doc.babylonjs.com/extensions/Fire",
-                    "icon": "icons/fire.jpg", 
-                    "description": "Fire material",
-                    "PGID": "#LR4YHT#0"
-                },
-                {
-                    "title": "Water",
-                    "doc": "https://doc.babylonjs.com/extensions/water",
-                    "icon": "icons/water.jpg", 
-                    "description": "Water material",
-                    "PGID": "#L76FB1#0"
-                }                      
-            ]
-        },         
-        {
-            "title": "Meshes",
-            "samples": [   
-                {
-                    "title": "Render lines",
-                    "doc": "http://localhost:8080/babylon101/Parametric_Shapes#lines",
-                    "icon": "icons/lines.jpg",
-                    "description": "Use LinesMesh to render lines in 3D",
-                    "PGID": "#SVZL1I#0"
-                },                 
-                {
-                    "title": "Displacement map (CPU)",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.mesh.html#applydisplacementmap",
-                    "icon": "icons/displacement.jpg",
-                    "description": "Update mesh geometry using a displacement map (CPU)",
-                    "PGID": "#04JDPF#0"
-                },                   
-                {
-                    "title": "Constructive solid geometries",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.csg.html",
-                    "icon": "icons/csg.jpg",
-                    "description": "Use boolean operations on meshes using CSG",
-                    "PGID": "#T6NP3F#0"
-                },                  
-                {
-                    "title": "Raycast on height map",
-                    "doc": "https://doc.babylonjs.com/babylon101/raycasts",
-                    "icon": "icons/heightMapRaycast.jpg",
-                    "description": "Raycast to find positions on a heightmap",
-                    "PGID": "#QM57B#0"
-                },                  
-                {
-                    "title": "Basic scene",
-                    "doc": "https://doc.babylonjs.com/features/scene",
-                    "icon": "icons/basic_scene.png", 
-                    "description": "Ball and plane",
-                    "PGID": "#TAZ2CB#0"
-                },
-                {
-                    "title": "Basic elements",
-                    "doc": "https://doc.babylonjs.com/how_to/set_shapes",
-                    "icon": "icons/basic_elements.png", 
-                    "description": "Ball, box, plane, line, etc",
-                    "PGID": "#A1210C#0"
-                },
-                {
-                    "title": "Rotation and scaling",
-                    "doc": "https://doc.babylonjs.com/how_to/rotate",
-                    "icon": "icons/rotation_and_scaling.png", 
-                    "description": "Position mesh layout in space",
-                    "PGID": "#CURCZC#0"
-                },
-                {
-                    "title": "Curved lines",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_path3d",
-                    "icon": "icons/path3D.jpg",
-                    "description": "Use Path3D to create a curved line",
-                    "PGID": "#7SQDY#1"
-                },
-                {
-                    "title": "Rotating mesh to look at a target",
-                    "doc": "https://doc.babylonjs.com/babylon101/position",
-                    "icon": "icons/meshLook.jpg",
-                    "description": "Make a mesh face towards where the pointer hit a plane",
-                    "PGID": "#23M0G6#1"
-                },        
-                {
-                    "title": "Height map",
-                    "doc": "https://doc.babylonjs.com/babylon101/height_map",
-                    "icon": "icons/height_map.png", 
-                    "description": "Use a height map to extrude a plane to create mountains",
-                    "PGID": "#95PXRY#0"
-                },        
-                {
-                    "title": "Extrude polygon",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.meshbuilder#extrudepolygon",
-                    "icon": "icons/extrude_polygon.jpg", 
-                    "description": "Use MeshBuilder to generate geometry from extruded data",
-                    "PGID": "#TFLTJJ#0"
-                },        
-                {
-                    "title": "Polygon mesh",
-                    "doc": "https://doc.babylonjs.com/how_to/polygonmeshbuilder",
-                    "icon": "icons/polygon_mesh.jpg", 
-                    "description": "Use PolygonMeshBuilder to create meshes from polygon data",
-                    "PGID": "#0TQAQU#0"
-                },                     
-                {
-                    "title": "Look at",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.abstractmesh#lookat",
-                    "icon": "icons/look_at.jpg", 
-                    "description": "Use lookAt() function to align meshes on a specific target",
-                    "PGID": "#N2K3ZN#0"
-                },        
-                {
-                    "title": "Ribbons",
-                    "doc": "https://doc.babylonjs.com/how_to/ribbon_tutorial",
-                    "icon": "icons/ribbons.jpg", 
-                    "description": "Use ribbons to create complex meshes",
-                    "PGID": "#29BR2V#1"
-                },        
-                {
-                    "title": "Decals",
-                    "doc": "https://doc.babylonjs.com/how_to/decals",
-                    "icon": "icons/decals.jpg", 
-                    "description": "Create decals to apply additional textures to a portion of a mesh",
-                    "PGID": "#EEUVTY#0"
-                }                                    
-            ]
-        },
-        {
-            "title": "Optimizations",
-            "samples": [
-                {
-                    "title": "Level of detail",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_lod",
-                    "icon": "icons/lod.jpg",
-                    "description": "Use various meshes based on distance to optimize rendering speed",
-                    "PGID": "#7HMHAU#0"
-                },
-                {
-                    "title": "Hardware instancing",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_instances",
-                    "icon": "icons/instances.jpg",
-                    "description": "Use hardware instancing to duplicate meshes at no cost",
-                    "PGID": "#YB006J#0"
-                },
-                {
-                    "title": "Octrees",
-                    "doc": "https://doc.babylonjs.com/how_to/optimizing_your_scene_with_octrees",
-                    "icon": "icons/octree.jpg",
-                    "description": "Use octrees to boost mesh selections when dealing with thousands of objects",
-                    "PGID": "#3YFJ5R#0"
-                }
-            ]
-        },        
-        {
-            "title": "Particles",
-            "samples": [
-                {
-                    "title": "Particles and mirrors",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles",
-                    "icon": "icons/particle_mirror.jpg",
-                    "description": "Use particles with a mirror",
-                    "PGID": "#65MUMZ#1"
-                },                  
-                {
-                    "title": "Particles with custom shader",
-                    "doc": "https://doc.babylonjs.com/how_to/customise#custom-effects",
-                    "icon": "icons/custom_particles.jpg",
-                    "description": "Use custom shader to display CPU particles",
-                    "PGID": "#807QEP#0"
-                },                
-                {
-                    "title": "GPU particles",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles#gpu-particles",
-                    "icon": "icons/gpu_particles.jpg",
-                    "description": "Use GPU only to create a massive number of particles",
-                    "PGID": "#PU4WYI#14"
-                },
-                {
-                    "title": "Particles 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles",
-                    "icon": "icons/particles.png", 
-                    "description": "Create a particle system and attach it to a moving object",
-                    "PGID": "#EF9X5R#0"
-                },                           
-                {
-                    "title": "Low lying fog",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles",
-                    "icon": "icons/lying_fog.jpg",
-                    "description": "Use particle to simulate volumetric fog",
-                    "PGID": "#BHNVUE#1"
-                },                           
-                {
-                    "title": "Particle editor",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles",
-                    "icon": "icons/particle_editor.jpg",
-                    "description": "Online editor to play with particle parameters",
-                    "PGID": "#NNL67B#1"
-                },
-                {
-                    "title": "A lot of triangles with SPS",
-                    "doc": "https://doc.babylonjs.com/how_to/solid_particle_system",
-                    "icon": "icons/solidParticleSystem.jpg",
-                    "description": "Use solid particle system to create a colorful cube",
-                    "PGID": "#2FPT1A#5"
-                },
-                {
-                    "title": "Solid Particle System facet collision",
-                    "doc": "https://doc.babylonjs.com/how_to/solid_particle_system",
-                    "icon": "icons/facets.jpg", 
-                    "description": "Use SPS facets to simulate complex mesh collisions",
-                    "PGID": "#6UZDJ9#0"
-                },
-                {
-                    "title": "Solid Particle System collisions",
-                    "doc": "https://doc.babylonjs.com/how_to/solid_particle_system",
-                    "icon": "icons/sps_collisions.jpg", 
-                    "description": "Use basic geometry to simulate SPS collisions",
-                    "PGID": "#2V1C4Z#0"
-                },
-                {
-                    "title": "Solid Particle System and shadows",
-                    "doc": "https://doc.babylonjs.com/how_to/solid_particle_system",
-                    "icon": "icons/sps_shadows.jpg", 
-                    "description": "Animate SPS with realtime shadows",
-                    "PGID": "#ML2LR9#0"
-                }                        
-            ]
-        },        
-        {
-            "title": "Collisions & intersections",
-            "samples": [
-                {
-                    "title": "Collisions",
-                    "doc": "https://doc.babylonjs.com/babylon101/cameras,_mesh_collisions_and_gravity",
-                    "icon": "icons/collisions.png", 
-                    "description": "Handle basic collisions to avoid a camera going through a box",
-                    "PGID": "#U8MEB0#0"
-                },
-                {
-                    "title": "Intersections",
-                    "doc": "https://doc.babylonjs.com/babylon101/intersect_collisions_-_mesh",
-                    "icon": "icons/intersections.png", 
-                    "description": "Detect when meshes intersect each other",
-                    "PGID": "#KQV9SA#0"
-                }
-            ]
-        },              
-        {
-            "title": "Physics",
-            "samples": [
-                {
-                    "title": "Physics",
-                    "doc": "https://doc.babylonjs.com/how_to/using_the_physics_engine",
-                    "icon": "icons/physics.png", 
-                    "description": "How to use physic engines within Babylon",
-                    "PGID": "#7149G4#0"
-                },
-                {
-                    "title": "Cloth",
-                    "doc": "https://doc.babylonjs.com/how_to/using_the_physics_engine",
-                    "icon": "icons/cloth.jpg", 
-                    "description": "Use physic engine to simulate cloth",
-                    "PGID": "#7N1BRU#0"
-                }
-            ]
-        },                
-        {
-            "title": "Shadows",
-            "samples": [
-                {
-                    "title": "Contact hardening",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows#contact-hardening-shadow-webgl2-only",
-                    "icon": "icons/pcss.jpg",
-                    "description": "Shadows will get softer when they are further away from the object casting them",
-                    "PGID": "#EYEPRI#3"
-                },
-                {
-                    "title": "Self shadowing #1",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows#exponential-shadow-map",
-                    "icon": "icons/self_shadows1.jpg",
-                    "description": "Use shadow exponential mode to enable self shadowing on a rotating object",
-                    "PGID": "#F4XWU2#0"
-                },                
-                {
-                    "title": "Self shadowing #2",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows#close-exponential-shadow-map",
-                    "icon": "icons/self_shadows2.jpg",
-                    "description": "Use shadow close exponential mode to enable self shadowing on animated object",
-                    "PGID": "#4GAHX6#1"
-                },
-                {
-                    "title": "Shadows 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/shadows.png", 
-                    "description": "Setup a scene with lights and meshes to cast different types of shadows",
-                    "PGID": "#IFYDRS#0"
-                },
-                {
-                    "title": "Shadow on transparent textures",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/trasnparent_shadow.jpg",
-                    "description": "Create realistic shadows from a transparent texture",
-                    "PGID": "#2DT16W#2"
-                },
-                {
-                    "title": "Point light shadows",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/point_shadows.jpg", 
-                    "description": "Use point light to cast shadows",
-                    "PGID": "#4MC650#0"
-                },
-                {
-                    "title": "Multi directional lights with soft shadows",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/multi_shadows.jpg", 
-                    "description": "Use multiple directional lights to cast soft shadows",
-                    "PGID": "#KWS7KD#0"
-                },
-                {
-                    "title": "Different shadow filters",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/shadow_filters.jpg", 
-                    "description": "Demonstrate different kind of shadows",
-                    "PGID": "#43T193#0"
-                }                                  
-            ]
-        },            
-        {            
-            "title": "Audio",
-            "samples": [
-                {
-                    "title": "Basic sounds",
-                    "doc": "https://doc.babylonjs.com/how_to/playing_sounds_and_music",
-                    "icon": "icons/basic_sounds.png", 
-                    "description": "Playing sounds with babylon",
-                    "PGID": "#DXAEUY#0"
-                },
-                {
-                    "title": "Sound on mesh",
-                    "doc": "https://doc.babylonjs.com/how_to/playing_sounds_and_music",
-                    "icon": "icons/sound_on_mesh.png", 
-                    "description": "Attach a sound to a mesh which will be modified by the objects position",
-                    "PGID": "#EDVU95#0"
-                },
-                {
-                    "title": "Audio analyzer #1",
-                    "doc": "https://doc.babylonjs.com/how_to/playing_sounds_and_music#using-the-analyser",
-                    "icon": "icons/analyzer.jpg", 
-                    "description": "Analyze audio frequencies in realtime",
-                    "PGID": "#TUR5GH#0"
-                },
-                {
-                    "title": "PBR with music analyzer #2",
-                    "doc": "https://doc.babylonjs.com/how_to/playing_sounds_and_music#using-the-analyser",
-                    "icon": "icons/musicAnalyzer.jpg",
-                    "description": "Visualize audio frequencies in realtime",
-                    "PGID": "#2JOSXE#21"
-                }
-            ]
-        },    
-        {
-            "title": "Special FX",
-            "samples": [
-                {
-                    "title": "Fog",
-                    "doc": "https://doc.babylonjs.com/babylon101/Environment#fog",
-                    "icon": "icons/fog.jpg",
-                    "description": "Simulate fog in your scene",
-                    "PGID": "#LR6389#0"
-                },                    
-                {
-                    "title": "Convolution post-process",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.convolutionpostprocess",
-                    "icon": "icons/convolution.jpg",
-                    "description": "Apply emboss filter to the scene using the ConvolutionPostProcess",
-                    "PGID": "#B0RH9H#0"
-                },                  
-                {
-                    "title": "Lens flares",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_lens_flares",
-                    "icon": "icons/lens_flares.jpg",
-                    "description": "Simulate lens flares on the camera",
-                    "PGID": "#ZEB7H6#0"
-                },                 
-                {
-                    "title": "Glass wubble ball",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.abstractmesh#getverticesdata",
-                    "icon": "icons/glassWubbleBall.jpg",
-                    "description": "Warped ball effect",
-                    "PGID": "#CXOLW#3"
-                },                
-                {
-                    "title": "Color curves",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_postprocesses#imageprocessing",
-                    "icon": "icons/color_curves.jpg",
-                    "description": "Apply color curves to your rendering",
-                    "PGID": "#HI65FJ#0"
-                },     
-                {
-                    "title": "Default rendering pipeline",
-                    "doc": "https://doc.babylonjs.com/how_to/using_default_rendering_pipeline",
-                    "icon": "icons/default_pipeline.jpg",
-                    "description": "Bloom, FXAA, sharpen, grain, vignette, chromatic aberration and DoF with one single object",
-                    "PGID": "#Y3C0HQ#146"
-                },                      
-                {
-                    "title": "Depth of field",
-                    "doc": "https://doc.babylonjs.com/how_to/using_default_rendering_pipeline#depth-of-field",
-                    "icon": "icons/dof.jpg",
-                    "description": "Apply depth of field effect",
-                    "PGID": "#8F5HYV#9"
-                },                           
-                {
-                    "title": "Glow layer",
-                    "doc": "https://doc.babylonjs.com/how_to/glow_layer",
-                    "icon": "icons/glow.jpg",
-                    "description": "Generates glow around emissive objects",
-                    "PGID": "#6ZVKE3#0"
-                },
-                {
-                    "title": "Sprites",
-                    "doc": "https://doc.babylonjs.com/babylon101/sprites",
-                    "icon": "icons/sprites.png", 
-                    "description": "Load and display sprites",
-                    "PGID": "#9RI8CG#0"
-                },
-                {
-                    "title": "Environment",
-                    "doc": "https://doc.babylonjs.com/babylon101/environment",
-                    "icon": "icons/environment.png", 
-                    "description": "Adding a skybox and fog",
-                    "PGID": "#7G0IQW#0"
-                },
-                {
-                    "title": "Fresnel",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_fresnelparameters",
-                    "icon": "icons/fresnel.png", 
-                    "description": "Renders spheres to simulate a fresnel lens",
-                    "PGID": "#AQZJ4C#0"
-                },
-                {
-                    "title": "SSAO rendering pipeline",
-                    "doc": "https://doc.babylonjs.com/how_to/using_the_ssao_rendering_pipeline",
-                    "icon": "icons/ssao_1.png", 
-                    "description": "Screen space ambient occlusion",
-                    "PGID": "#N96NXC#0"
-                },
-                {
-                    "title": "SSAO rendering pipeline (WebGL2)",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.ssao2renderingpipeline",
-                    "icon": "icons/ssao_2.png", 
-                    "description": "Screen space ambient occlusion with WebGL2",
-                    "PGID": "#7D2QDD#0"
-                },
-                {
-                    "title": "Volumetric Light Scattering",
-                    "doc": "https://doc.babylonjs.com/how_to/using_the_volumetric_lightscattering_post-process",
-                    "icon": "icons/volumetric_light_scattering.png", 
-                    "description": "Simulates light scattering due to light hitting the atmosphere",
-                    "PGID": "#V2DAKC#0"
-                },
-                {
-                    "title": "Refraction and Reflection",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_fresnelparameters",
-                    "icon": "icons/refraction_and_reflection.png", 
-                    "description": "Simulate how light would reflect and refract with a sphere",
-                    "PGID": "#XH85A9#0"
-                },
-                {
-                    "title": "Portals",
-                    "doc": "https://doc.babylonjs.com/resources/shaderintro",
-                    "icon": "icons/portals.jpg",
-                    "description": "Portal effect created using custom shaders",
-                    "PGID": "#EEOWP#7"
-                },
-                {
-                    "title": "Warp speed !",
-                    "doc": "https://doc.babylonjs.com/how_to/shader_material",
-                    "icon": "icons/warpSpeed.jpg",
-                    "description": "Fly though stars using a custom shader texture",
-                    "PGID": "#1WBBW0#1"
-                },
-                {
-                    "title": "Hypnotizing infinite loader",
-                    "doc": "https://doc.babylonjs.com/babylon101/position",
-                    "icon": "icons/infiniteLoader.jpg",
-                    "description": "Visually apealing loading animation",
-                    "PGID": "#VUJG1#1"
-                },            
-                {
-                    "title": "Realtime refraction",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_reflection_probes",
-                    "icon": "icons/refraction.jpg", 
-                    "description": "use reflection probes to simulate realtime refraction",
-                    "PGID": "#RRYXWN#0"
-                },
-                {
-                    "title": "Realtime reflection",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_reflection_probes",
-                    "icon": "icons/reflection.jpg", 
-                    "description": "use reflection probes to simulate realtime reflection",
-                    "PGID": "#SF5RCN#0"
-                },                
-                {
-                    "title": "Motion blur",
-                    "doc": "https://doc.babylonjs.com/how_to/using_standard_rendering_pipeline#setting-up-the-motion-blur",
-                    "icon": "icons/motion_blur.jpg", 
-                    "description": "Use the standard rendering pipeline to simulate motion blur",
-                    "PGID": "#ZMAJZB#0"
-                },
-                {
-                    "title": "Highlight layer",
-                    "doc": "https://doc.babylonjs.com/how_to/highlight_layer",
-                    "icon": "icons/highlights.jpg", 
-                    "description": "Highlight a mesh",
-                    "PGID": "#7EESGZ#0"
-                },
-                {
-                    "title": "Lens effects",
-                    "doc": "https://doc.babylonjs.com/how_to/using_depth-of-field_and_other_lens_effects",
-                    "icon": "icons/lens_effect.jpg", 
-                    "description": "Create photographic effect with the LensRenderingPipeline",
-                    "PGID": "#B7JHWD#0"
-                }                           
-            ]
-        },
-        {
-            "title": "Textures",
-            "samples": [   
-                {
-                    "title": "Saving dynamic texture on disk",
-                    "doc": "https://doc.babylonjs.com/how_to/dynamictexture",
-                    "icon": "icons/savingDynamicTexture.jpg",
-                    "description": "Save a texture generated at runtime using DynamicTexture",
-                    "PGID": "#CA4SM#1"
-                },                
-                {
-                    "title": "360 videos",
-                    "doc": "https://doc.babylonjs.com/how_to/360videodome",
-                    "icon": "icons/360.jpg",
-                    "description": "Easily display and control 360 videos",
-                    "PGID": "#1E9JQ8#7"
-                },                
-                {
-                    "title": "ProceduralTexture",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_procedural_textures",
-                    "icon": "icons/procedural_texture.png", 
-                    "description": "Use procedual textures for wood, grass, marble, fire, etc.",
-                    "PGID": "#B2ZXG6#0"
-                },
-                {
-                    "title": "Local cubemaps",
-                    "doc": "https://doc.babylonjs.com/how_to/reflect#cubetexture",
-                    "icon": "icons/local_cubemap.jpg",
-                    "description": "Improve cubemaps with local mode",
-                    "PGID": "#RNASML#4"
-                },                 
-                {
-                    "title": "Starfield procedural texture",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_procedural_textures",
-                    "icon": "icons/starfield.jpg", 
-                    "description": "Use the starfield procedual texture to simulate space",
-                    "PGID": "#ZQWE4G#0"
-                },
-                {
-                    "title": "Equirectangular map as reflection texture",
-                    "doc": "https://doc.babylonjs.com/how_to/reflect",
-                    "icon": "icons/equMapOnReflectionTexture.jpg",
-                    "description": "Using Equirectangular maps as a reflection texture",
-                    "PGID": "#23IQHK#2"
-                },
-                {
-                    "title": "Mirrors",
-                    "doc": "https://doc.babylonjs.com/how_to/reflect",
-                    "icon": "icons/mirrors.jpg",
-                    "description": "Shows how to use mirrors in babylon",
-                    "PGID": "#2EP7UB#0"
-                },
-                {
-                    "title": "Custom render targets",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.rendertargettexture",
-                    "icon": "icons/custom_rendertarget.jpg",
-                    "description": "Use render target textures to generate procedural data",
-                    "PGID": "#CJWDJR#0"
-                },
-                {
-                    "title": "Bump texture",
-                    "doc": "https://doc.babylonjs.com/how_to/more_materials#bump-map",
-                    "icon": "icons/bump.jpg",
-                    "description": "Use normal map to simulate bump",
-                    "PGID": "#RK0W5S#0"
-                }                              
-            ]
-        },
-        {
-            "title": "VR",
-            "samples": [
-                {
-                    "title": "WebVR",
-                    "doc": "https://doc.babylonjs.com/how_to/webvr_helper",
-                    "icon": "icons/webvr.png", 
-                    "description": "View a basic mesh and interact with a gui in WebVR",
-                    "PGID": "#TAFSN0#2"
-                } 
-            ]
-        },
-        {
-            "title": "Misc.",
-            "samples": [
-                {
-                    "title": "Charting",
-                    "doc": "https://doc.babylonjs.com/babylon101/",
-                    "icon": "icons/charting.jpg", 
-                    "description": "Creates a 3D charting presentation",
-                    "PGID": "#8PY6X5#1"
-                } 
-            ]
-        }         
-    ]
-}

+ 1 - 1
Playground/index-local.html

@@ -381,7 +381,7 @@
             </div>
             <div class="horizontalSeparator"></div>
             <input id="filterBar" type="text" placeholder="Filter examples...">
-            <img id="filterBarClear" src="http://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
         </div>
 
         <span class="label" id="fpsLabel">FPS</span>

+ 1 - 1
Playground/index.html

@@ -416,7 +416,7 @@
             </div>
             <div class="horizontalSeparator"></div>
             <input id="filterBar" type="text" placeholder="Filter examples...">
-            <img id="filterBarClear" src="http://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
         </div>
 
         <span class="label" id="fpsLabel">FPS</span>

+ 1 - 1
Playground/indexStable.html

@@ -407,7 +407,7 @@
             </div>
             <div class="horizontalSeparator"></div>
             <input id="filterBar" type="text" placeholder="Filter examples...">
-            <img id="filterBarClear" src="http://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
         </div>
 
         <span class="label" id="fpsLabel">FPS</span>

+ 43 - 3
Playground/js/index.js

@@ -191,7 +191,7 @@
         var loadScriptsList = function () {
             var xhr = new XMLHttpRequest();
 
-            xhr.open('GET', 'examples/list.json', true);
+            xhr.open('GET', 'https://raw.githubusercontent.com/BabylonJS/Documentation/master/examples/list.json', true);
 
             xhr.onreadystatechange = function () {
                 if (xhr.readyState === 4) {
@@ -223,7 +223,7 @@
                                 example.id = ii;
 
                                 var exampleImg = document.createElement("img");
-                                exampleImg.src = scripts[i].samples[ii].icon.replace("icons", "http://doc.babylonjs.com/examples/icons");
+                                exampleImg.src = scripts[i].samples[ii].icon.replace("icons", "https://doc.babylonjs.com/examples/icons");
                                 exampleImg.setAttribute("onClick", "document.getElementById('PGLink_" + scripts[i].samples[ii].PGID + "').click();");
 
                                 var exampleContent = document.createElement("div");
@@ -282,7 +282,47 @@
                                 var query = queryString.replace("?", "");
                                 index = parseInt(query);
                                 if (!isNaN(index)) {
-                                    loadScriptFromIndex(index);
+                                    // Old examples
+                                    //loadScriptFromIndex(index);
+                                    var newPG = "";
+                                    switch(index) {
+                                        case 1 : newPG = "#TAZ2CB#0"; break; // Basic scene
+                                        case 2 : newPG = "#A1210C#0"; break; // Basic elements
+                                        case 3 : newPG = "#CURCZC#0"; break; // Rotation and scaling
+                                        case 4 : newPG = "#DXARSP#0"; break; // Materials
+                                        case 5 : newPG = "#1A3M5C#0"; break; // Cameras
+                                        case 6 : newPG = "#AQRDKW#0"; break; // Lights
+                                        case 7 : newPG = "#QYFDDP#1"; break; // Animations
+                                        case 8 : newPG = "#9RI8CG#0"; break; // Sprites
+                                        case 9 : newPG = "#U8MEB0#0"; break; // Collisions
+                                        case 10 : newPG = "#KQV9SA#0"; break; // Intersections
+                                        case 11 : newPG = "#NU4F6Y#0"; break; // Picking
+                                        case 12 : newPG = "#EF9X5R#0"; break; // Particles
+                                        case 13 : newPG = "#7G0IQW#0"; break; // Environment
+                                        case 14 : newPG = "#95PXRY#0"; break; // Height map
+                                        case 15 : newPG = "#IFYDRS#0"; break; // Shadows
+                                        case 16 : newPG = "#AQZJ4C#0"; break; // Import meshes
+                                        case 17 : newPG = "#J19GYK#0"; break; // Actions
+                                        case 18 : newPG = "#UZ23UH#0"; break; // Drag and drop
+                                        case 19 : newPG = "#AQZJ4C#0"; break; // Fresnel
+                                        case 20 : newPG = "#8ZNVGR#0"; break; // Easing functions
+                                        case 21 : newPG = "#B2ZXG6#0"; break; // Procedural texture
+                                        case 22 : newPG = "#DXAEUY#0"; break; // Basic sounds
+                                        case 23 : newPG = "#EDVU95#0"; break; // Sound on mesh
+                                        case 24 : newPG = "#N96NXC#0"; break; // SSAO rendering pipeline
+                                        case 25 : newPG = "#7D2QDD#0"; break; // SSAO 2
+                                        case 26 : newPG = "#V2DAKC#0"; break; // Volumetric light scattering
+                                        case 27 : newPG = "#XH85A9#0"; break; // Refraction and reflection
+                                        case 28 : newPG = "#8MGKWK#0"; break; // PBR
+                                        case 29 : newPG = "#0K8EYN#0"; break; // Instanced bones
+                                        case 30 : newPG = "#C245A1#0"; break; // Pointer events handling
+                                        case 31 : newPG = "#TAFSN0#2"; break; // WebVR
+                                        case 32 : newPG = "#3VMTI9#0"; break; // GUI
+                                        case 33 : newPG = "#7149G4#0"; break; // Physics
+                                        
+                                        default: newPG = ""; break;
+                                    }
+                                    window.location.href = location.protocol + "//" + location.host + location.pathname + "#" + newPG;
                                 } else if (query.indexOf("=") === -1) {
                                     loadScript("scripts/" + query + ".js", query);
                                 } else {

+ 7 - 3
Tools/Gulp/config.json

@@ -14,7 +14,7 @@
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
             "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
-            "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"
+            "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"
         ],
         "outputCustomConfigurationsDirectory": "../../dist/preview release/customConfigurations",
         "srcOutputDirectory": "../../src/",
@@ -313,7 +313,9 @@
         },
         "meshBehaviors": {
             "files": [
-                "../../src/Behaviors/Mesh/babylon.pointerDragBehavior.js"
+                "../../src/Behaviors/Mesh/babylon.pointerDragBehavior.js",
+                "../../src/Behaviors/Mesh/babylon.multiPointerScaleBehavior.js",
+                "../../src/Behaviors/Mesh/babylon.sixDofDragBehavior.js"
             ],
             "dependUpon": [
                 "behaviors"
@@ -1755,6 +1757,8 @@
                     "../../gui/src/3D/controls/stackPanel3D.ts",
                     "../../gui/src/3D/controls/volumeBasedPanel.ts",
                     "../../gui/src/3D/controls/spherePanel.ts",
+                    "../../gui/src/3D/controls/planePanel.ts",
+                    "../../gui/src/3D/controls/scatterPanel.ts",
                     "../../gui/src/3D/controls/cylinderPanel.ts"
                 ],
                 "shaderFiles": [
@@ -1895,7 +1899,7 @@
                             "addBabylonDeclaration": [
                                 "babylon.d.ts",
                                 "loaders/babylonjs.loaders.d.ts",
-                                "gltf2Interface/babylon.glTF2Interface.d.ts"
+                                "glTF2Interface/babylon.glTF2Interface.d.ts"
                             ]
                         }
                     ],

+ 1 - 1
Tools/Gulp/gulpfile.js

@@ -906,7 +906,7 @@ gulp.task("typedoc-generate", function () {
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
             "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
-            "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"])
+            "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"])
         .pipe(typedoc({
             // TypeScript options (see typescript docs)
             mode: "modules",

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

@@ -95,8 +95,7 @@ export let defaultConfiguration: ViewerConfiguration = {
             bouncing: {
                 type: 1
             }
-        },
-        wheelPrecision: 200,
+        }
     },
     skybox: {
     },

+ 14 - 8
Viewer/src/managers/sceneManager.ts

@@ -71,7 +71,7 @@ export class SceneManager {
     /**
      * Babylon's environment helper of this viewer
      */
-    public environmentHelper: EnvironmentHelper;
+    public environmentHelper?: EnvironmentHelper;
 
     private _animationBlendingEnabled: boolean = true;
 
@@ -447,7 +447,7 @@ export class SceneManager {
                 }
             }
 
-            if (newConfiguration.lab.environmentMainColor) {
+            if (this.environmentHelper && newConfiguration.lab.environmentMainColor) {
                 let mainColor = new Color3().copyFrom(newConfiguration.lab.environmentMainColor as Color3);
                 this.environmentHelper.setMainColor(mainColor);
             }
@@ -814,9 +814,6 @@ export class SceneManager {
         const sceneDiagonalLenght = sceneDiagonal.length();
         if (isFinite(sceneDiagonalLenght))
             this.camera.upperRadiusLimit = sceneDiagonalLenght * 4;
-        else {
-            this.camera.upperRadiusLimit = 10;
-        }
 
         // sanity check!
         if (this.scene.imageProcessingConfiguration) {
@@ -844,6 +841,12 @@ export class SceneManager {
         this.camera.beta = (this._globalConfiguration.camera && this._globalConfiguration.camera.beta) || this.camera.beta;
         this.camera.radius = (this._globalConfiguration.camera && this._globalConfiguration.camera.radius) || this.camera.radius;
 
+        const sceneDiagonalLenght = sizeVec.length();
+        if (isFinite(sceneDiagonalLenght))
+            this.camera.upperRadiusLimit = sceneDiagonalLenght * 4;
+
+        if (this._configurationContainer.configuration)
+            this._configureEnvironment(this._configurationContainer.configuration.skybox, this._configurationContainer.configuration.ground);
         /*this.scene.lights.filter(light => light instanceof ShadowLight).forEach(light => {
             // casting ais safe, due to the constraints tested before
             (<ShadowLight>light).setDirectionToTarget(center);
@@ -960,7 +963,10 @@ export class SceneManager {
                     this.environmentHelper.dispose();
                     this.environmentHelper = this.scene.createDefaultEnvironment(options)!;
                 } else {
-                    this.environmentHelper.updateOptions(options)!;
+                    //this.environmentHelper.updateOptions(options)!;
+                    // update doesn't change the size of the skybox and ground, so we have to recreate!
+                    this.environmentHelper.dispose();
+                    this.environmentHelper = this.scene.createDefaultEnvironment(options)!;
                 }
             }
 
@@ -1013,7 +1019,7 @@ export class SceneManager {
 
         this.onEnvironmentConfiguredObservable.notifyObservers({
             sceneManager: this,
-            object: this.environmentHelper,
+            object: this.environmentHelper!,
             newConfiguration: {
                 skybox: skyboxConifguration,
                 ground: groundConfiguration
@@ -1223,7 +1229,7 @@ export class SceneManager {
     }
 
     private _updateGroundMirrorRenderList(model?: ViewerModel, resetList?: boolean) {
-        if (this.environmentHelper.groundMirror && this.environmentHelper.groundMirror.renderList) {
+        if (this.environmentHelper && this.environmentHelper.groundMirror && this.environmentHelper.groundMirror.renderList) {
             let focusMeshes = model ? model.meshes : this.scene.meshes;
             let renderList = this.environmentHelper.groundMirror.renderList;
             if (resetList) {

+ 5 - 1
Viewer/src/model/viewerModel.ts

@@ -242,12 +242,16 @@ export class ViewerModel implements IDisposable {
         if (this.skeletons.length) {
             this.skeletons.forEach((skeleton, idx) => {
                 let ag = new AnimationGroup("animation-" + idx);
+                let add = false;
                 skeleton.getAnimatables().forEach(a => {
                     if (a.animations[0]) {
                         ag.addTargetedAnimation(a.animations[0], a);
+                        add = true;
                     }
                 });
-                this.addAnimationGroup(ag);
+                if (add) {
+                    this.addAnimationGroup(ag);
+                }
             });
         }
 

+ 14 - 2
Viewer/tests/unit/src/viewer/sceneManager.ts

@@ -146,6 +146,12 @@ describe(name, function () {
         });
 
         viewer.onInitDoneObservable.add(() => {
+            if (!viewer.sceneManager.environmentHelper) {
+                assert.fail();
+                viewer.dispose();
+                done();
+                return;
+            }
             // ground should be defined, and mirror should be enabled
             assert.isDefined(viewer.sceneManager.environmentHelper.ground);
 
@@ -177,6 +183,12 @@ describe(name, function () {
         });
 
         viewer.onInitDoneObservable.add(() => {
+            if (!viewer.sceneManager.environmentHelper) {
+                assert.fail();
+                viewer.dispose();
+                done();
+                return;
+            }
             // ground should be defined, and mirror should be enabled
             assert.isDefined(viewer.sceneManager.environmentHelper.groundMaterial);
             assert.isDefined(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
@@ -184,7 +196,7 @@ describe(name, function () {
             viewer.sceneManager.groundMirrorEnabled = false;
 
             assert.isDefined(viewer.sceneManager.environmentHelper.groundMaterial);
-            assert.isNull(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
+            assert.isNotOk(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
 
             viewer.sceneManager.groundMirrorEnabled = true;
 
@@ -198,7 +210,7 @@ describe(name, function () {
             });
 
             assert.isDefined(viewer.sceneManager.environmentHelper.groundMaterial);
-            assert.isNull(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
+            assert.isNotOk(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
             assert.isTrue(viewer.sceneManager.groundMirrorEnabled);
 
             viewer.dispose();

+ 1 - 1
Viewer/tsconfig.json

@@ -9,7 +9,7 @@
         "strictNullChecks": true,
         "noImplicitAny": false,
         "noFallthroughCasesInSwitch": true,
-        "inlineSourceMap": true,
+        "sourceMap": true,
         "lib": [
             "es5",
             "dom",

Разница между файлами не показана из-за своего большого размера
+ 9422 - 9391
dist/preview release/babylon.d.ts


Разница между файлами не показана из-за своего большого размера
+ 47 - 47
dist/preview release/babylon.js


Разница между файлами не показана из-за своего большого размера
+ 98 - 21
dist/preview release/babylon.max.js


Разница между файлами не показана из-за своего большого размера
+ 98 - 21
dist/preview release/babylon.no-module.max.js


Разница между файлами не показана из-за своего большого размера
+ 29 - 29
dist/preview release/babylon.worker.js


Разница между файлами не показана из-за своего большого размера
+ 98 - 21
dist/preview release/es6.js


dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts → dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts


dist/preview release/gltf2Interface/package.json → dist/preview release/glTF2Interface/package.json


+ 31 - 0
dist/preview release/gui/babylon.gui.d.ts

@@ -2491,6 +2491,8 @@ declare module BABYLON.GUI {
         private _rows;
         private _rowThenColum;
         private _orientation;
+        protected _cellWidth: number;
+        protected _cellHeight: number;
         /**
          * Gets or sets the distance between elements
          */
@@ -2523,6 +2525,8 @@ declare module BABYLON.GUI {
         protected _arrangeChildren(): void;
         /** Child classes must implement this function to provide correct control positioning */
         protected abstract _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+        /** Child classes can implement this function to provide additional processing */
+        protected _finalProcessing(): void;
     }
 }
 
@@ -2545,6 +2549,33 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     /**
+     * Class used to create a container panel deployed on the surface of a plane
+     */
+    class PlanePanel extends VolumeBasedPanel {
+        protected _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a container panel where items get randomized planar mapping
+     */
+    class ScatterPanel extends VolumeBasedPanel {
+        private _iteration;
+        /**
+         * Gets or sets the number of iteration to use to scatter the controls (100 by default)
+         */
+        iteration: float;
+        protected _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+        private _scatterMapping(source);
+        protected _finalProcessing(): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
+    /**
      * Class used to create a container panel deployed on the surface of a cylinder
      */
     class CylinderPanel extends VolumeBasedPanel {

+ 166 - 10
dist/preview release/gui/babylon.gui.js

@@ -6827,6 +6827,9 @@ var BABYLON;
                 });
                 this._utilityLayer = new BABYLON.UtilityLayerRenderer(this._scene);
                 this._utilityLayer.onlyCheckPointerDownEvents = false;
+                this._utilityLayer.mainSceneTrackerPredicate = function (mesh) {
+                    return mesh && mesh.metadata && mesh.metadata._node;
+                };
                 // Root
                 this._rootContainer = new GUI.Container3D("RootContainer");
                 this._rootContainer._host = this;
@@ -8427,8 +8430,8 @@ var BABYLON;
                 configurable: true
             });
             VolumeBasedPanel.prototype._arrangeChildren = function () {
-                var cellWidth = 0;
-                var cellHeight = 0;
+                this._cellWidth = 0;
+                this._cellHeight = 0;
                 var rows = 0;
                 var columns = 0;
                 var controlCount = 0;
@@ -8444,11 +8447,11 @@ var BABYLON;
                     child.mesh.getWorldMatrix().multiplyToRef(currentInverseWorld, BABYLON.Tmp.Matrix[0]);
                     var boundingBox = child.mesh.getBoundingInfo().boundingBox;
                     var extendSize = BABYLON.Vector3.TransformNormal(boundingBox.extendSize, BABYLON.Tmp.Matrix[0]);
-                    cellWidth = Math.max(cellWidth, extendSize.x * 2);
-                    cellHeight = Math.max(cellHeight, extendSize.y * 2);
+                    this._cellWidth = Math.max(this._cellWidth, extendSize.x * 2);
+                    this._cellHeight = Math.max(this._cellHeight, extendSize.y * 2);
                 }
-                cellWidth += this.margin * 2;
-                cellHeight += this.margin * 2;
+                this._cellWidth += this.margin * 2;
+                this._cellHeight += this.margin * 2;
                 // Arrange
                 if (this._rowThenColum) {
                     columns = this._columns;
@@ -8458,14 +8461,14 @@ var BABYLON;
                     rows = this._rows;
                     columns = Math.ceil(controlCount / this._rows);
                 }
-                var startOffsetX = (columns * 0.5) * cellWidth;
-                var startOffsetY = (rows * 0.5) * cellHeight;
+                var startOffsetX = (columns * 0.5) * this._cellWidth;
+                var startOffsetY = (rows * 0.5) * this._cellHeight;
                 var nodeGrid = [];
                 var cellCounter = 0;
                 if (this._rowThenColum) {
                     for (var r = 0; r < rows; r++) {
                         for (var c = 0; c < columns; c++) {
-                            nodeGrid.push(new BABYLON.Vector3((c * cellWidth) - startOffsetX + cellWidth / 2, (r * cellHeight) - startOffsetY + cellHeight / 2, 0));
+                            nodeGrid.push(new BABYLON.Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
                             cellCounter++;
                             if (cellCounter > controlCount) {
                                 break;
@@ -8476,7 +8479,7 @@ var BABYLON;
                 else {
                     for (var c = 0; c < columns; c++) {
                         for (var r = 0; r < rows; r++) {
-                            nodeGrid.push(new BABYLON.Vector3((c * cellWidth) - startOffsetX + cellWidth / 2, (r * cellHeight) - startOffsetY + cellHeight / 2, 0));
+                            nodeGrid.push(new BABYLON.Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
                             cellCounter++;
                             if (cellCounter > controlCount) {
                                 break;
@@ -8493,6 +8496,10 @@ var BABYLON;
                     this._mapGridNode(child, nodeGrid[cellCounter]);
                     cellCounter++;
                 }
+                this._finalProcessing();
+            };
+            /** Child classes can implement this function to provide additional processing */
+            VolumeBasedPanel.prototype._finalProcessing = function () {
             };
             return VolumeBasedPanel;
         }(GUI.Container3D));
@@ -8578,6 +8585,155 @@ var BABYLON;
     var GUI;
     (function (GUI) {
         /**
+         * Class used to create a container panel deployed on the surface of a plane
+         */
+        var PlanePanel = /** @class */ (function (_super) {
+            __extends(PlanePanel, _super);
+            function PlanePanel() {
+                return _super !== null && _super.apply(this, arguments) || this;
+            }
+            PlanePanel.prototype._mapGridNode = function (control, nodePosition) {
+                var mesh = control.mesh;
+                if (!mesh) {
+                    return;
+                }
+                switch (this.orientation) {
+                    case GUI.Container3D.FACEORIGIN_ORIENTATION:
+                    case GUI.Container3D.FACEFORWARD_ORIENTATION:
+                        mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
+                        break;
+                    case GUI.Container3D.FACEFORWARDREVERSED_ORIENTATION:
+                    case GUI.Container3D.FACEORIGINREVERSED_ORIENTATION:
+                        mesh.lookAt(new BABYLON.Vector3(0, 0, 1));
+                        break;
+                }
+                control.position = nodePosition.clone();
+            };
+            return PlanePanel;
+        }(GUI.VolumeBasedPanel));
+        GUI.PlanePanel = PlanePanel;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        /**
+         * Class used to create a container panel where items get randomized planar mapping
+         */
+        var ScatterPanel = /** @class */ (function (_super) {
+            __extends(ScatterPanel, _super);
+            function ScatterPanel() {
+                var _this = _super !== null && _super.apply(this, arguments) || this;
+                _this._iteration = 100.0;
+                return _this;
+            }
+            Object.defineProperty(ScatterPanel.prototype, "iteration", {
+                /**
+                 * Gets or sets the number of iteration to use to scatter the controls (100 by default)
+                 */
+                get: function () {
+                    return this._iteration;
+                },
+                set: function (value) {
+                    var _this = this;
+                    if (this._iteration === value) {
+                        return;
+                    }
+                    this._iteration = value;
+                    BABYLON.Tools.SetImmediate(function () {
+                        _this._arrangeChildren();
+                    });
+                },
+                enumerable: true,
+                configurable: true
+            });
+            ScatterPanel.prototype._mapGridNode = function (control, nodePosition) {
+                var mesh = control.mesh;
+                var newPos = this._scatterMapping(nodePosition);
+                if (!mesh) {
+                    return;
+                }
+                switch (this.orientation) {
+                    case GUI.Container3D.FACEORIGIN_ORIENTATION:
+                    case GUI.Container3D.FACEFORWARD_ORIENTATION:
+                        mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
+                        break;
+                    case GUI.Container3D.FACEFORWARDREVERSED_ORIENTATION:
+                    case GUI.Container3D.FACEORIGINREVERSED_ORIENTATION:
+                        mesh.lookAt(new BABYLON.Vector3(0, 0, 1));
+                        break;
+                }
+                control.position = newPos;
+            };
+            ScatterPanel.prototype._scatterMapping = function (source) {
+                source.x = (1.0 - Math.random() * 2.0) * this._cellWidth;
+                source.y = (1.0 - Math.random() * 2.0) * this._cellHeight;
+                return source;
+            };
+            ScatterPanel.prototype._finalProcessing = function () {
+                var meshes = [];
+                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                    var child = _a[_i];
+                    if (!child.mesh) {
+                        continue;
+                    }
+                    meshes.push(child.mesh);
+                }
+                for (var count = 0; count < this._iteration; count++) {
+                    meshes.sort(function (a, b) {
+                        var distance1 = a.position.lengthSquared();
+                        var distance2 = b.position.lengthSquared();
+                        if (distance1 < distance2) {
+                            return 1;
+                        }
+                        else if (distance1 > distance2) {
+                            return -1;
+                        }
+                        return 0;
+                    });
+                    var radiusPaddingSquared = Math.pow(this.margin, 2.0);
+                    var cellSize = Math.max(this._cellWidth, this._cellHeight);
+                    var difference2D = BABYLON.Tmp.Vector2[0];
+                    var difference = BABYLON.Tmp.Vector3[0];
+                    for (var i = 0; i < meshes.length - 1; i++) {
+                        for (var j = i + 1; j < meshes.length; j++) {
+                            if (i != j) {
+                                meshes[j].position.subtractToRef(meshes[i].position, difference);
+                                // Ignore Z axis
+                                difference2D.x = difference.x;
+                                difference2D.y = difference.y;
+                                var combinedRadius = cellSize;
+                                var distance = difference2D.lengthSquared() - radiusPaddingSquared;
+                                var minSeparation = Math.min(distance, radiusPaddingSquared);
+                                distance -= minSeparation;
+                                if (distance < (Math.pow(combinedRadius, 2.0))) {
+                                    difference2D.normalize();
+                                    difference.scaleInPlace((combinedRadius - Math.sqrt(distance)) * 0.5);
+                                    meshes[j].position.addInPlace(difference);
+                                    meshes[i].position.subtractInPlace(difference);
+                                }
+                            }
+                        }
+                    }
+                }
+            };
+            return ScatterPanel;
+        }(GUI.VolumeBasedPanel));
+        GUI.ScatterPanel = ScatterPanel;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        /**
          * Class used to create a container panel deployed on the surface of a cylinder
          */
         var CylinderPanel = /** @class */ (function (_super) {

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/gui/babylon.gui.min.js


+ 31 - 0
dist/preview release/gui/babylon.gui.module.d.ts

@@ -2496,6 +2496,8 @@ declare module BABYLON.GUI {
         private _rows;
         private _rowThenColum;
         private _orientation;
+        protected _cellWidth: number;
+        protected _cellHeight: number;
         /**
          * Gets or sets the distance between elements
          */
@@ -2528,6 +2530,8 @@ declare module BABYLON.GUI {
         protected _arrangeChildren(): void;
         /** Child classes must implement this function to provide correct control positioning */
         protected abstract _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+        /** Child classes can implement this function to provide additional processing */
+        protected _finalProcessing(): void;
     }
 }
 
@@ -2550,6 +2554,33 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     /**
+     * Class used to create a container panel deployed on the surface of a plane
+     */
+    class PlanePanel extends VolumeBasedPanel {
+        protected _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a container panel where items get randomized planar mapping
+     */
+    class ScatterPanel extends VolumeBasedPanel {
+        private _iteration;
+        /**
+         * Gets or sets the number of iteration to use to scatter the controls (100 by default)
+         */
+        iteration: float;
+        protected _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+        private _scatterMapping(source);
+        protected _finalProcessing(): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
+    /**
      * Class used to create a container panel deployed on the surface of a cylinder
      */
     class CylinderPanel extends VolumeBasedPanel {

Разница между файлами не показана из-за своего большого размера
+ 5 - 5
dist/preview release/inspector/babylon.inspector.bundle.js


+ 7 - 4
dist/preview release/inspector/babylon.inspector.d.ts

@@ -473,7 +473,7 @@ declare module INSPECTOR {
         private _obj;
         /** The obj parent  */
         private _parentObj;
-        constructor(prop: string, obj: any, parentObj?: PropertyLine);
+        constructor(prop: string, obj: any, parentObj?: any);
         readonly name: string;
         value: any;
         readonly type: string;
@@ -1034,7 +1034,7 @@ declare module INSPECTOR {
 declare function Split(elements: HTMLElement[], options: any): any;
 declare module INSPECTOR {
     class GLTFTab extends Tab {
-        private static _LoaderExtensionSettings;
+        private static _LoaderDefaults;
         private _inspector;
         private _actions;
         private _detailsPanel;
@@ -1045,9 +1045,12 @@ declare module INSPECTOR {
         constructor(tabbar: TabBar, inspector: Inspector);
         dispose(): void;
         private _addImport();
-        private _getLoaderExtensionOverridesAsync();
-        private _updateLoaderExtensionDetails(settings);
+        private static _EnumeratePublic(obj, callback);
+        private _getLoaderDefaultsAsync();
+        private _openDetailsPanel();
         private _closeDetailsPanel();
+        private _showLoaderDefaults(defaults);
+        private _showLoaderExtensionDefaults(defaults);
         private _addExport();
         private static _IsSkyBox(transformNode);
     }

+ 98 - 65
dist/preview release/inspector/babylon.inspector.js

@@ -17,7 +17,7 @@ var INSPECTOR;
                     //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
                     INSPECTOR.loadGUIProperties();
                 }, function () {
-                    console.warn("Please add script https://preview.babylonjs.com/gui/babylon.gui.js to the HTML file");
+                    console.warn('Error : loading "babylon.gui.js". Please add script https://preview.babylonjs.com/gui/babylon.gui.js to the HTML file.');
                 });
             }
             else {
@@ -1381,7 +1381,7 @@ var INSPECTOR;
             set: function (newValue) {
                 if (newValue != undefined && this._obj[this._property] != undefined) {
                     if (this._obj instanceof BABYLON.Scene) {
-                        this._obj.debugLayer.onGlobalPropertyChangeCallback({
+                        this._obj.debugLayer.onPropertyChangedObservable.notifyObservers({
                             object: this._obj,
                             property: this._property,
                             value: newValue,
@@ -1392,7 +1392,7 @@ var INSPECTOR;
                         if (this._parentObj != null) {
                             // Object that have "children" properties : Color, Vector, imageProcessingConfiguration
                             if (this._parentObj instanceof BABYLON.Scene) {
-                                this._parentObj.debugLayer.onGlobalPropertyChangeCallback({
+                                this._parentObj.debugLayer.onPropertyChangedObservable.notifyObservers({
                                     object: this._parentObj,
                                     property: this._property,
                                     value: newValue,
@@ -1400,7 +1400,7 @@ var INSPECTOR;
                                 });
                             }
                             else {
-                                this._parentObj.getScene().debugLayer.onGlobalPropertyChangeCallback({
+                                this._parentObj.getScene().debugLayer.onPropertyChangedObservable.notifyObservers({
                                     object: this._parentObj,
                                     property: this._property,
                                     value: newValue,
@@ -1409,7 +1409,7 @@ var INSPECTOR;
                             }
                         }
                         else {
-                            this._obj.getScene().debugLayer.onGlobalPropertyChangeCallback({
+                            this._obj.getScene().debugLayer.onPropertyChangedObservable.notifyObservers({
                                 object: this._obj,
                                 property: this._property,
                                 value: newValue,
@@ -1703,11 +1703,9 @@ var INSPECTOR;
          * Dispose all viewer element (color, texture...)
          */
         PropertyLine.prototype.dispose = function () {
-            // console.log('delete properties', this.name);
             INSPECTOR.Scheduler.getInstance().remove(this);
             for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
                 var child = _a[_i];
-                // console.log('delete properties', child.name);
                 INSPECTOR.Scheduler.getInstance().remove(child);
             }
             for (var _b = 0, _c = this._elements; _b < _c.length; _b++) {
@@ -2580,10 +2578,10 @@ var INSPECTOR;
                         style.textContent = elem;
                     });
                 }, undefined, undefined, undefined, function () {
-                    console.log("erreur");
+                    console.log('Error : LoadFile "glsl.min.js"');
                 });
             }, undefined, undefined, undefined, function () {
-                console.log("erreur");
+                console.log('Error : LoadFile "highlight.min.js"');
             });
         };
         Helpers.IsSystemName = function (name) {
@@ -3659,9 +3657,9 @@ var INSPECTOR;
         };
         ConsoleTab.prototype._message = function (type, message, caller) {
             var callerLine = INSPECTOR.Helpers.CreateDiv('caller', this._consolePanelContent);
-            callerLine.textContent = caller;
+            callerLine.textContent = caller.replace(' ', '\u00A0');
             var line = INSPECTOR.Helpers.CreateDiv(type, this._consolePanelContent);
-            line.textContent += message;
+            line.textContent = message.replace(' ', '\u00A0');
             this._consolePanelContent.scrollTop = this._consolePanelContent.scrollHeight;
         };
         ConsoleTab.prototype._addConsoleLog = function () {
@@ -4085,7 +4083,7 @@ var INSPECTOR;
     INSPECTOR.StatsTab = StatsTab;
 })(INSPECTOR || (INSPECTOR = {}));
 
-/// <reference path="../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 /// <reference path="../../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts"/>
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts"/>
 var __extends = (this && this.__extends) || (function () {
@@ -4100,7 +4098,6 @@ var __extends = (this && this.__extends) || (function () {
 })();
 var INSPECTOR;
 (function (INSPECTOR) {
-    ;
     var GLTFTab = /** @class */ (function (_super) {
         __extends(GLTFTab, _super);
         function GLTFTab(tabbar, inspector) {
@@ -4129,14 +4126,19 @@ var INSPECTOR;
         });
         /** @hidden */
         GLTFTab._Initialize = function () {
-            // Must register with OnPluginActivatedObservable as early as possible to
-            // override the default settings for each extension.
+            // Must register with OnPluginActivatedObservable as early as possible to override the loader defaults.
             BABYLON.SceneLoader.OnPluginActivatedObservable.add(function (loader) {
-                if (loader.name === "gltf" && GLTFTab._LoaderExtensionSettings) {
+                if (loader.name === "gltf" && GLTFTab._LoaderDefaults) {
+                    var defaults_1 = GLTFTab._LoaderDefaults;
+                    for (var key in defaults_1) {
+                        if (key !== "extensions") {
+                            loader[key] = GLTFTab._LoaderDefaults[key];
+                        }
+                    }
                     loader.onExtensionLoadedObservable.add(function (extension) {
-                        var settings = GLTFTab._LoaderExtensionSettings[extension.name];
-                        for (var settingName in settings) {
-                            extension[settingName] = settings[settingName];
+                        var extensionDefaults = defaults_1.extensions[extension.name];
+                        for (var key in extensionDefaults) {
+                            extension[key] = extensionDefaults[key];
                         }
                     });
                 }
@@ -4149,69 +4151,83 @@ var INSPECTOR;
         };
         GLTFTab.prototype._addImport = function () {
             var _this = this;
-            var importActions = INSPECTOR.Helpers.CreateDiv(null, this._actions);
-            this._getLoaderExtensionOverridesAsync().then(function (loaderExtensionSettings) {
-                var title = INSPECTOR.Helpers.CreateDiv('gltf-title', importActions);
-                title.textContent = 'Import';
-                var extensionActions = INSPECTOR.Helpers.CreateDiv('gltf-actions', importActions);
-                var extensionsTitle = INSPECTOR.Helpers.CreateDiv('gltf-title', extensionActions);
+            var importTitle = INSPECTOR.Helpers.CreateDiv('gltf-title', this._actions);
+            importTitle.textContent = 'Import';
+            var importActions = INSPECTOR.Helpers.CreateDiv('gltf-actions', this._actions);
+            this._getLoaderDefaultsAsync().then(function (defaults) {
+                importTitle.addEventListener('click', function (event) {
+                    _this._showLoaderDefaults(defaults);
+                    event.stopPropagation();
+                });
+                importActions.addEventListener('click', function (event) {
+                    _this._showLoaderDefaults(defaults);
+                    event.stopPropagation();
+                });
+                var extensionsTitle = INSPECTOR.Helpers.CreateDiv('gltf-title', importActions);
                 extensionsTitle.textContent = "Extensions";
                 var _loop_1 = function (extensionName) {
-                    var settings = loaderExtensionSettings[extensionName];
-                    var extensionAction = INSPECTOR.Helpers.CreateDiv('gltf-action', extensionActions);
+                    var extensionDefaults = defaults.extensions[extensionName];
+                    var extensionAction = INSPECTOR.Helpers.CreateDiv('gltf-action', importActions);
                     extensionAction.addEventListener('click', function (event) {
-                        if (_this._updateLoaderExtensionDetails(settings)) {
+                        if (_this._showLoaderExtensionDefaults(extensionDefaults)) {
                             event.stopPropagation();
                         }
                     });
                     var checkbox = INSPECTOR.Helpers.CreateElement('span', 'gltf-checkbox', extensionAction);
-                    if (settings.enabled) {
+                    if (extensionDefaults.enabled) {
                         checkbox.classList.add('action', 'active');
                     }
                     checkbox.addEventListener('click', function () {
                         checkbox.classList.toggle('active');
-                        settings.enabled = checkbox.classList.contains('active');
+                        extensionDefaults.enabled = checkbox.classList.contains('active');
                     });
                     var label = INSPECTOR.Helpers.CreateElement('span', null, extensionAction);
                     label.textContent = extensionName;
                 };
-                for (var extensionName in loaderExtensionSettings) {
+                for (var extensionName in defaults.extensions) {
                     _loop_1(extensionName);
                 }
             });
         };
-        GLTFTab.prototype._getLoaderExtensionOverridesAsync = function () {
-            if (GLTFTab._LoaderExtensionSettings) {
-                return Promise.resolve(GLTFTab._LoaderExtensionSettings);
+        GLTFTab._EnumeratePublic = function (obj, callback) {
+            for (var key in obj) {
+                if (key !== "name" && key[0] !== '_') {
+                    var value = obj[key];
+                    var type = typeof value;
+                    if (type !== "object" && type !== "function" && type !== "undefined") {
+                        callback(key, value);
+                    }
+                }
+            }
+        };
+        GLTFTab.prototype._getLoaderDefaultsAsync = function () {
+            if (GLTFTab._LoaderDefaults) {
+                return Promise.resolve(GLTFTab._LoaderDefaults);
             }
-            var loaderExtensionSettings = {};
+            var defaults = {
+                extensions: {}
+            };
             var engine = new BABYLON.NullEngine();
             var scene = new BABYLON.Scene(engine);
-            var loader = new BABYLON.GLTF2.GLTFLoader();
+            var loader = new BABYLON.GLTFFileLoader();
+            GLTFTab._EnumeratePublic(loader, function (key, value) {
+                defaults[key] = value;
+            });
             loader.onExtensionLoadedObservable.add(function (extension) {
-                loaderExtensionSettings[extension.name] = {};
-                var settings = loaderExtensionSettings[extension.name];
-                for (var _i = 0, _a = Object.keys(extension); _i < _a.length; _i++) {
-                    var key = _a[_i];
-                    if (key !== "name" && key[0] !== '_') {
-                        var value = extension[key];
-                        if (typeof value !== "object") {
-                            settings[key] = value;
-                        }
-                    }
-                }
+                var extensionDefaults = {};
+                GLTFTab._EnumeratePublic(extension, function (key, value) {
+                    extensionDefaults[key] = value;
+                });
+                defaults.extensions[extension.name] = extensionDefaults;
             });
-            var data = { json: {}, bin: null };
+            var data = '{ "asset": { "version": "2.0" } }';
             return loader.importMeshAsync([], scene, data, "").then(function () {
                 scene.dispose();
                 engine.dispose();
-                return (GLTFTab._LoaderExtensionSettings = loaderExtensionSettings);
+                return (GLTFTab._LoaderDefaults = defaults);
             });
         };
-        GLTFTab.prototype._updateLoaderExtensionDetails = function (settings) {
-            if (Object.keys(settings).length === 1) {
-                return false;
-            }
+        GLTFTab.prototype._openDetailsPanel = function () {
             if (!this._detailsPanel) {
                 this._detailsPanel = new INSPECTOR.DetailPanel();
                 this._panel.appendChild(this._detailsPanel.toHtml());
@@ -4222,14 +4238,7 @@ var INSPECTOR;
                 });
             }
             this._detailsPanel.clean();
-            var details = new Array();
-            for (var key in settings) {
-                if (key !== "enabled") {
-                    details.push(new INSPECTOR.PropertyLine(new INSPECTOR.Property(key, settings)));
-                }
-            }
-            this._detailsPanel.details = details;
-            return true;
+            return this._detailsPanel;
         };
         GLTFTab.prototype._closeDetailsPanel = function () {
             if (this._detailsPanel) {
@@ -4242,11 +4251,35 @@ var INSPECTOR;
                 delete this._split;
             }
         };
+        GLTFTab.prototype._showLoaderDefaults = function (defaults) {
+            var detailsPanel = this._openDetailsPanel();
+            var details = new Array();
+            for (var key in defaults) {
+                if (key !== "extensions") {
+                    details.push(new INSPECTOR.PropertyLine(new INSPECTOR.Property(key, defaults, this._inspector.scene)));
+                }
+            }
+            detailsPanel.details = details;
+        };
+        GLTFTab.prototype._showLoaderExtensionDefaults = function (defaults) {
+            if (Object.keys(defaults).length === 1) {
+                return false;
+            }
+            var detailsPanel = this._openDetailsPanel();
+            var details = new Array();
+            for (var key in defaults) {
+                if (key !== "enabled") {
+                    details.push(new INSPECTOR.PropertyLine(new INSPECTOR.Property(key, defaults, this._inspector.scene)));
+                }
+            }
+            detailsPanel.details = details;
+            return true;
+        };
         GLTFTab.prototype._addExport = function () {
             var _this = this;
-            var exportActions = INSPECTOR.Helpers.CreateDiv(null, this._actions);
-            var title = INSPECTOR.Helpers.CreateDiv('gltf-title', exportActions);
-            title.textContent = 'Export';
+            var exportTitle = INSPECTOR.Helpers.CreateDiv('gltf-title', this._actions);
+            exportTitle.textContent = 'Export';
+            var exportActions = INSPECTOR.Helpers.CreateDiv('gltf-actions', this._actions);
             var name = INSPECTOR.Helpers.CreateInput('gltf-input', exportActions);
             name.placeholder = "File name...";
             var button = INSPECTOR.Helpers.CreateElement('button', 'gltf-button', exportActions);
@@ -4271,7 +4304,7 @@ var INSPECTOR;
             }
             return false;
         };
-        GLTFTab._LoaderExtensionSettings = null;
+        GLTFTab._LoaderDefaults = null;
         return GLTFTab;
     }(INSPECTOR.Tab));
     INSPECTOR.GLTFTab = GLTFTab;

Разница между файлами не показана из-за своего большого размера
+ 4 - 4
dist/preview release/inspector/babylon.inspector.min.js


+ 39 - 98
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -73,89 +73,15 @@ declare module BABYLON {
          */
         COMPLETE = 2,
     }
-    /**
-     * Loader interface.
-     */
+    /** @hidden */
     interface IGLTFLoader extends IDisposable {
-        /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-         * Loader state or null if the loader is not active.
-         */
-        state: Nullable<GLTFLoaderState>;
-        /**
-         * Imports meshes from the given data and adds them to the scene.
-         */
+        readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Loads all objects from the given data and adds them to the scene.
-         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
     /**
@@ -163,9 +89,9 @@ declare module BABYLON {
      */
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
         /** @hidden */
-        static _CreateGLTFLoaderV1: () => IGLTFLoader;
+        static _CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
         /** @hidden */
-        static _CreateGLTFLoaderV2: () => IGLTFLoader;
+        static _CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
         /**
          * Raised when the asset has been parsed
          */
@@ -261,7 +187,7 @@ declare module BABYLON {
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
-        readonly onCompleteObservable: Observable<GLTFFileLoader>;
+        readonly onCompleteObservable: Observable<void>;
         private _onCompleteObserver;
         /**
          * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
@@ -270,7 +196,7 @@ declare module BABYLON {
         /**
          * Observable raised after the loader is disposed.
          */
-        readonly onDisposeObservable: Observable<GLTFFileLoader>;
+        readonly onDisposeObservable: Observable<void>;
         private _onDisposeObserver;
         /**
          * Callback raised after the loader is disposed.
@@ -295,6 +221,14 @@ declare module BABYLON {
          * The loader state or null if the loader is not active.
          */
         readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Defines if the loader logging is enabled.
+         */
+        loggingEnabled: boolean;
+        /**
+         * Defines if the loader should capture performance counters.
+         */
+        capturePerformanceCounters: boolean;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -308,6 +242,8 @@ declare module BABYLON {
          * Disposes the loader, releases resources during load, and cancels any outstanding requests.
          */
         dispose(): void;
+        /** @hidden */
+        _clear(): void;
         /**
          * Imports one or more meshes from the loaded glTF data and adds them to the scene
          * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
@@ -358,12 +294,32 @@ declare module BABYLON {
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
         private _parse(data);
         private _getLoader(loaderData);
-        private static _parseBinary(data);
-        private static _parseV1(binaryReader);
-        private static _parseV2(binaryReader);
+        private _parseBinary(data);
+        private _parseV1(binaryReader);
+        private _parseV2(binaryReader);
         private static _parseVersion(version);
         private static _compareVersion(a, b);
         private static _decodeBufferToText(buffer);
+        private static readonly _logSpaces;
+        private _logIndentLevel;
+        private _loggingEnabled;
+        /** @hidden */
+        _log: (message: string) => void;
+        /** @hidden */
+        _logOpen(message: string): void;
+        /** @hidden */
+        _logClose(): void;
+        private _logEnabled(message);
+        private _logDisabled(message);
+        private _capturePerformanceCounters;
+        /** @hidden */
+        _startPerformanceCounter: (counterName: string) => void;
+        /** @hidden */
+        _endPerformanceCounter: (counterName: string) => void;
+        private _startPerformanceCounterEnabled(counterName);
+        private _startPerformanceCounterDisabled(counterName);
+        private _endPerformanceCounterEnabled(counterName);
+        private _endPerformanceCounterDisabled(counterName);
     }
 }
 
@@ -760,21 +716,6 @@ declare module BABYLON.GLTF1 {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        compileMaterials: boolean;
-        useClipPlane: boolean;
-        compileShadowGenerators: boolean;
-        transparencyAsCoverage: boolean;
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
-        readonly onTextureLoadedObservable: Observable<BaseTexture>;
-        readonly onMaterialLoadedObservable: Observable<Material>;
-        readonly onCameraLoadedObservable: Observable<Camera>;
-        readonly onCompleteObservable: Observable<IGLTFLoader>;
-        readonly onDisposeObservable: Observable<IGLTFLoader>;
-        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);

+ 110 - 53
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -139,6 +139,15 @@ var BABYLON;
                 ".gltf": { isBinary: false },
                 ".glb": { isBinary: true }
             };
+            this._logIndentLevel = 0;
+            this._loggingEnabled = false;
+            /** @hidden */
+            this._log = this._logDisabled;
+            this._capturePerformanceCounters = false;
+            /** @hidden */
+            this._startPerformanceCounter = this._startPerformanceCounterDisabled;
+            /** @hidden */
+            this._endPerformanceCounter = this._endPerformanceCounterDisabled;
         }
         Object.defineProperty(GLTFFileLoader.prototype, "onParsed", {
             /**
@@ -266,6 +275,52 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(GLTFFileLoader.prototype, "loggingEnabled", {
+            /**
+             * Defines if the loader logging is enabled.
+             */
+            get: function () {
+                return this._loggingEnabled;
+            },
+            set: function (value) {
+                if (this._loggingEnabled === value) {
+                    return;
+                }
+                this._loggingEnabled = value;
+                if (this._loggingEnabled) {
+                    this._log = this._logEnabled;
+                }
+                else {
+                    this._log = this._logDisabled;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(GLTFFileLoader.prototype, "capturePerformanceCounters", {
+            /**
+             * Defines if the loader should capture performance counters.
+             */
+            get: function () {
+                return this._capturePerformanceCounters;
+            },
+            set: function (value) {
+                if (this._capturePerformanceCounters === value) {
+                    return;
+                }
+                this._capturePerformanceCounters = value;
+                if (this._capturePerformanceCounters) {
+                    this._startPerformanceCounter = this._startPerformanceCounterEnabled;
+                    this._endPerformanceCounter = this._endPerformanceCounterEnabled;
+                }
+                else {
+                    this._startPerformanceCounter = this._startPerformanceCounterDisabled;
+                    this._endPerformanceCounter = this._endPerformanceCounterDisabled;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes the loader, releases resources during load, and cancels any outstanding requests.
          */
@@ -274,6 +329,12 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this._clear();
+            this.onDisposeObservable.notifyObservers(undefined);
+            this.onDisposeObservable.clear();
+        };
+        /** @hidden */
+        GLTFFileLoader.prototype._clear = function () {
             this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
@@ -281,8 +342,6 @@ var BABYLON;
             this.onCameraLoadedObservable.clear();
             this.onCompleteObservable.clear();
             this.onExtensionLoadedObservable.clear();
-            this.onDisposeObservable.notifyObservers(this);
-            this.onDisposeObservable.clear();
         };
         /**
          * Imports one or more meshes from the loaded glTF data and adds them to the scene
@@ -357,11 +416,15 @@ var BABYLON;
             return new GLTFFileLoader();
         };
         GLTFFileLoader.prototype._parse = function (data) {
+            this._startPerformanceCounter("Parse");
             var parsedData;
             if (data instanceof ArrayBuffer) {
-                parsedData = GLTFFileLoader._parseBinary(data);
+                this._log("Parsing binary");
+                parsedData = this._parseBinary(data);
             }
             else {
+                this._log("Parsing JSON");
+                this._log("JSON length: " + data.length);
                 parsedData = {
                     json: JSON.parse(data),
                     bin: null
@@ -369,12 +432,14 @@ var BABYLON;
             }
             this.onParsedObservable.notifyObservers(parsedData);
             this.onParsedObservable.clear();
+            this._endPerformanceCounter("Parse");
             return parsedData;
         };
         GLTFFileLoader.prototype._getLoader = function (loaderData) {
-            var _this = this;
-            var loaderVersion = { major: 2, minor: 0 };
             var asset = loaderData.json.asset || {};
+            this._log("Asset version: " + asset.version);
+            asset.minVersion && this._log("Asset minimum version: " + asset.minVersion);
+            asset.generator && this._log("Asset generator: " + asset.generator);
             var version = GLTFFileLoader._parseVersion(asset.version);
             if (!version) {
                 throw new Error("Invalid version: " + asset.version);
@@ -384,7 +449,7 @@ var BABYLON;
                 if (!minVersion) {
                     throw new Error("Invalid minimum version: " + asset.minVersion);
                 }
-                if (GLTFFileLoader._compareVersion(minVersion, loaderVersion) > 0) {
+                if (GLTFFileLoader._compareVersion(minVersion, { major: 2, minor: 0 }) > 0) {
                     throw new Error("Incompatible minimum version: " + asset.minVersion);
                 }
             }
@@ -396,48 +461,29 @@ var BABYLON;
             if (!createLoader) {
                 throw new Error("Unsupported version: " + asset.version);
             }
-            var loader = createLoader();
-            loader.coordinateSystemMode = this.coordinateSystemMode;
-            loader.animationStartMode = this.animationStartMode;
-            loader.compileMaterials = this.compileMaterials;
-            loader.useClipPlane = this.useClipPlane;
-            loader.compileShadowGenerators = this.compileShadowGenerators;
-            loader.transparencyAsCoverage = this.transparencyAsCoverage;
-            loader._normalizeAnimationGroupsToBeginAtZero = this._normalizeAnimationGroupsToBeginAtZero;
-            loader.preprocessUrlAsync = this.preprocessUrlAsync;
-            loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
-            loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
-            loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
-            loader.onCameraLoadedObservable.add(function (camera) { return _this.onCameraLoadedObservable.notifyObservers(camera); });
-            loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
-            loader.onCompleteObservable.add(function () {
-                _this.onMeshLoadedObservable.clear();
-                _this.onTextureLoadedObservable.clear();
-                _this.onMaterialLoadedObservable.clear();
-                _this.onCameraLoadedObservable.clear();
-                _this.onExtensionLoadedObservable.clear();
-                _this.onCompleteObservable.notifyObservers(_this);
-                _this.onCompleteObservable.clear();
-            });
-            return loader;
+            return createLoader(this);
         };
-        GLTFFileLoader._parseBinary = function (data) {
+        GLTFFileLoader.prototype._parseBinary = function (data) {
             var Binary = {
                 Magic: 0x46546C67
             };
+            this._log("Binary length: " + data.byteLength);
             var binaryReader = new BinaryReader(data);
             var magic = binaryReader.readUint32();
             if (magic !== Binary.Magic) {
                 throw new Error("Unexpected magic: " + magic);
             }
             var version = binaryReader.readUint32();
+            if (this.loggingEnabled) {
+                this._log("Binary version: " + version);
+            }
             switch (version) {
-                case 1: return GLTFFileLoader._parseV1(binaryReader);
-                case 2: return GLTFFileLoader._parseV2(binaryReader);
+                case 1: return this._parseV1(binaryReader);
+                case 2: return this._parseV2(binaryReader);
             }
             throw new Error("Unsupported version: " + version);
         };
-        GLTFFileLoader._parseV1 = function (binaryReader) {
+        GLTFFileLoader.prototype._parseV1 = function (binaryReader) {
             var ContentFormat = {
                 JSON: 0
             };
@@ -464,7 +510,7 @@ var BABYLON;
                 bin: body
             };
         };
-        GLTFFileLoader._parseV2 = function (binaryReader) {
+        GLTFFileLoader.prototype._parseV2 = function (binaryReader) {
             var ChunkFormat = {
                 JSON: 0x4E4F534A,
                 BIN: 0x004E4942
@@ -540,6 +586,31 @@ var BABYLON;
             }
             return result;
         };
+        /** @hidden */
+        GLTFFileLoader.prototype._logOpen = function (message) {
+            this._log(message);
+            this._logIndentLevel++;
+        };
+        /** @hidden */
+        GLTFFileLoader.prototype._logClose = function () {
+            --this._logIndentLevel;
+        };
+        GLTFFileLoader.prototype._logEnabled = function (message) {
+            var spaces = GLTFFileLoader._logSpaces.substr(0, this._logIndentLevel * 2);
+            BABYLON.Tools.Log("" + spaces + message);
+        };
+        GLTFFileLoader.prototype._logDisabled = function (message) {
+        };
+        GLTFFileLoader.prototype._startPerformanceCounterEnabled = function (counterName) {
+            BABYLON.Tools.StartPerformanceCounter(counterName);
+        };
+        GLTFFileLoader.prototype._startPerformanceCounterDisabled = function (counterName) {
+        };
+        GLTFFileLoader.prototype._endPerformanceCounterEnabled = function (counterName) {
+            BABYLON.Tools.EndPerformanceCounter(counterName);
+        };
+        GLTFFileLoader.prototype._endPerformanceCounterDisabled = function (counterName) {
+        };
         // #endregion
         // #region V1 options
         /**
@@ -555,6 +626,7 @@ var BABYLON;
          * @hidden
          */
         GLTFFileLoader.HomogeneousCoordinates = false;
+        GLTFFileLoader._logSpaces = "                                ";
         return GLTFFileLoader;
     }());
     BABYLON.GLTFFileLoader = GLTFFileLoader;
@@ -1978,22 +2050,6 @@ var BABYLON;
         */
         var GLTFLoader = /** @class */ (function () {
             function GLTFLoader() {
-                // #region Stubs for IGLTFLoader interface
-                this.coordinateSystemMode = BABYLON.GLTFLoaderCoordinateSystemMode.AUTO;
-                this.animationStartMode = BABYLON.GLTFLoaderAnimationStartMode.FIRST;
-                this.compileMaterials = false;
-                this.useClipPlane = false;
-                this.compileShadowGenerators = false;
-                this.transparencyAsCoverage = false;
-                this._normalizeAnimationGroupsToBeginAtZero = true;
-                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
-                this.onMeshLoadedObservable = new BABYLON.Observable();
-                this.onTextureLoadedObservable = new BABYLON.Observable();
-                this.onMaterialLoadedObservable = new BABYLON.Observable();
-                this.onCameraLoadedObservable = new BABYLON.Observable();
-                this.onCompleteObservable = new BABYLON.Observable();
-                this.onDisposeObservable = new BABYLON.Observable();
-                this.onExtensionLoadedObservable = new BABYLON.Observable();
                 this.state = null;
             }
             GLTFLoader.RegisterExtension = function (extension) {
@@ -2003,8 +2059,9 @@ var BABYLON;
                 }
                 GLTFLoader.Extensions[extension.name] = extension;
             };
-            GLTFLoader.prototype.dispose = function () { };
-            // #endregion
+            GLTFLoader.prototype.dispose = function () {
+                // do nothing
+            };
             GLTFLoader.prototype._importMeshAsync = function (meshesNames, scene, data, rootUrl, onSuccess, onProgress, onError) {
                 var _this = this;
                 scene.useRightHandedSystem = true;

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 49 - 195
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -73,89 +73,15 @@ declare module BABYLON {
          */
         COMPLETE = 2,
     }
-    /**
-     * Loader interface.
-     */
+    /** @hidden */
     interface IGLTFLoader extends IDisposable {
-        /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-         * Loader state or null if the loader is not active.
-         */
-        state: Nullable<GLTFLoaderState>;
-        /**
-         * Imports meshes from the given data and adds them to the scene.
-         */
+        readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Loads all objects from the given data and adds them to the scene.
-         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
     /**
@@ -163,9 +89,9 @@ declare module BABYLON {
      */
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
         /** @hidden */
-        static _CreateGLTFLoaderV1: () => IGLTFLoader;
+        static _CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
         /** @hidden */
-        static _CreateGLTFLoaderV2: () => IGLTFLoader;
+        static _CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
         /**
          * Raised when the asset has been parsed
          */
@@ -261,7 +187,7 @@ declare module BABYLON {
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
-        readonly onCompleteObservable: Observable<GLTFFileLoader>;
+        readonly onCompleteObservable: Observable<void>;
         private _onCompleteObserver;
         /**
          * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
@@ -270,7 +196,7 @@ declare module BABYLON {
         /**
          * Observable raised after the loader is disposed.
          */
-        readonly onDisposeObservable: Observable<GLTFFileLoader>;
+        readonly onDisposeObservable: Observable<void>;
         private _onDisposeObserver;
         /**
          * Callback raised after the loader is disposed.
@@ -295,6 +221,14 @@ declare module BABYLON {
          * The loader state or null if the loader is not active.
          */
         readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Defines if the loader logging is enabled.
+         */
+        loggingEnabled: boolean;
+        /**
+         * Defines if the loader should capture performance counters.
+         */
+        capturePerformanceCounters: boolean;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -308,6 +242,8 @@ declare module BABYLON {
          * Disposes the loader, releases resources during load, and cancels any outstanding requests.
          */
         dispose(): void;
+        /** @hidden */
+        _clear(): void;
         /**
          * Imports one or more meshes from the loaded glTF data and adds them to the scene
          * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
@@ -358,12 +294,32 @@ declare module BABYLON {
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
         private _parse(data);
         private _getLoader(loaderData);
-        private static _parseBinary(data);
-        private static _parseV1(binaryReader);
-        private static _parseV2(binaryReader);
+        private _parseBinary(data);
+        private _parseV1(binaryReader);
+        private _parseV2(binaryReader);
         private static _parseVersion(version);
         private static _compareVersion(a, b);
         private static _decodeBufferToText(buffer);
+        private static readonly _logSpaces;
+        private _logIndentLevel;
+        private _loggingEnabled;
+        /** @hidden */
+        _log: (message: string) => void;
+        /** @hidden */
+        _logOpen(message: string): void;
+        /** @hidden */
+        _logClose(): void;
+        private _logEnabled(message);
+        private _logDisabled(message);
+        private _capturePerformanceCounters;
+        /** @hidden */
+        _startPerformanceCounter: (counterName: string) => void;
+        /** @hidden */
+        _endPerformanceCounter: (counterName: string) => void;
+        private _startPerformanceCounterEnabled(counterName);
+        private _startPerformanceCounterDisabled(counterName);
+        private _endPerformanceCounterEnabled(counterName);
+        private _endPerformanceCounterDisabled(counterName);
     }
 }
 
@@ -484,18 +440,13 @@ declare module BABYLON.GLTF2 {
  * Defines the module used to import/export glTF 2.0 assets
  */
 declare module BABYLON.GLTF2 {
-    /**
-     * Loader for loading a glTF 2.0 asset
-     */
+    /** @hidden */
     class GLTFLoader implements IGLTFLoader {
-        /** @hidden */
+        _parent: GLTFFileLoader;
         _gltf: _ILoaderGLTF;
-        /** @hidden */
         _babylonScene: Scene;
-        /** @hidden */
+        _readyPromise: Promise<void>;
         _completePromises: Promise<void>[];
-        /** @hidden */
-        _onReadyObservable: Observable<IGLTFLoader>;
         private _disposed;
         private _state;
         private _extensions;
@@ -507,102 +458,19 @@ declare module BABYLON.GLTF2 {
         private _requests;
         private static _ExtensionNames;
         private static _ExtensionFactories;
-        /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        readonly onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        readonly onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        readonly onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        readonly onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        readonly onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
          * Loader state or null if the loader is not active.
          */
         readonly state: Nullable<GLTFLoaderState>;
-        /**
-         * Disposes the loader, releases resources during load, and cancels any outstanding requests.
-         */
+        constructor(parent: GLTFFileLoader);
         dispose(): void;
-        /**
-         * Imports one or more meshes from the loaded glTF data and adds them to the scene
-         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-         * @param scene the scene the meshes should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise containg the loaded meshes, particles, skeletons and animations
-         */
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Imports all objects from the loaded glTF data and adds them to the scene
-         * @param scene the scene the objects should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise which completes when objects have been loaded to the scene
-         */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         private _loadAsync(nodes);
         private _loadData(data);
@@ -610,15 +478,12 @@ declare module BABYLON.GLTF2 {
         private _loadExtensions();
         private _checkExtensions();
         private _createRootNode();
-        private _loadNodesAsync(nodes);
-        /** @hidden */
         _loadSceneAsync(context: string, scene: _ILoaderScene): Promise<void>;
         private _forEachPrimitive(node, callback);
         private _getMeshes();
         private _getSkeletons();
         private _getAnimationGroups();
         private _startAnimations();
-        /** @hidden */
         _loadNodeAsync(context: string, node: _ILoaderNode): Promise<void>;
         private _loadMeshAsync(context, node, mesh, babylonMesh);
         private _loadPrimitiveAsync(context, node, mesh, primitive, babylonMesh);
@@ -639,31 +504,22 @@ declare module BABYLON.GLTF2 {
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
-        /** @hidden */
         _loadBufferViewAsync(context: string, bufferView: _ILoaderBufferView): Promise<ArrayBufferView>;
         private _loadIndicesAccessorAsync(context, accessor);
         private _loadFloatAccessorAsync(context, accessor);
-        /** @hidden */
         _loadVertexBufferViewAsync(context: string, bufferView: _ILoaderBufferView, kind: string): Promise<Buffer>;
         private _loadVertexAccessorAsync(context, accessor, kind);
         private _getDefaultMaterial(drawMode);
         private _loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial);
-        /** @hidden */
         _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void>;
-        /** @hidden */
         _createMaterial(name: string, drawMode: number): PBRMaterial;
-        /** @hidden */
         _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void>;
-        /** @hidden */
         _loadMaterialAlphaProperties(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): void;
-        /** @hidden */
         _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void>;
         private _loadSampler(context, sampler);
         private _loadImageAsync(context, image);
-        /** @hidden */
         _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress();
-        /** @hidden */
         static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T;
         private static _GetTextureWrapMode(context, mode);
         private static _GetTextureSamplingMode(context, magFilter?, minFilter?);
@@ -673,8 +529,6 @@ declare module BABYLON.GLTF2 {
         private static _GetDrawMode(context, mode);
         private _compileMaterialsAsync();
         private _compileShadowGeneratorsAsync();
-        private _clear();
-        /** @hidden */
         _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>): Nullable<Promise<T>>;
     }
 }
@@ -804,12 +658,12 @@ declare module BABYLON.GLTF2.Extensions {
          * Dispose the loader to cancel the loading of the next level of LODs.
          */
         onMaterialLODsLoadedObservable: Observable<number>;
-        private _loadingNodeLOD;
-        private _loadNodeSignals;
-        private _loadNodePromises;
-        private _loadingMaterialLOD;
-        private _loadMaterialSignals;
-        private _loadMaterialPromises;
+        private _nodeIndexLOD;
+        private _nodeSignalLODs;
+        private _nodePromiseLODs;
+        private _materialIndexLOD;
+        private _materialSignalLODs;
+        private _materialPromiseLODs;
         constructor(loader: GLTFLoader);
         dispose(): void;
         protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>>;

Разница между файлами не показана из-за своего большого размера
+ 299 - 296
dist/preview release/loaders/babylon.glTF2FileLoader.js


Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 49 - 210
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -73,89 +73,15 @@ declare module BABYLON {
          */
         COMPLETE = 2,
     }
-    /**
-     * Loader interface.
-     */
+    /** @hidden */
     interface IGLTFLoader extends IDisposable {
-        /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-         * Loader state or null if the loader is not active.
-         */
-        state: Nullable<GLTFLoaderState>;
-        /**
-         * Imports meshes from the given data and adds them to the scene.
-         */
+        readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Loads all objects from the given data and adds them to the scene.
-         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
     /**
@@ -163,9 +89,9 @@ declare module BABYLON {
      */
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
         /** @hidden */
-        static _CreateGLTFLoaderV1: () => IGLTFLoader;
+        static _CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
         /** @hidden */
-        static _CreateGLTFLoaderV2: () => IGLTFLoader;
+        static _CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
         /**
          * Raised when the asset has been parsed
          */
@@ -261,7 +187,7 @@ declare module BABYLON {
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
-        readonly onCompleteObservable: Observable<GLTFFileLoader>;
+        readonly onCompleteObservable: Observable<void>;
         private _onCompleteObserver;
         /**
          * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
@@ -270,7 +196,7 @@ declare module BABYLON {
         /**
          * Observable raised after the loader is disposed.
          */
-        readonly onDisposeObservable: Observable<GLTFFileLoader>;
+        readonly onDisposeObservable: Observable<void>;
         private _onDisposeObserver;
         /**
          * Callback raised after the loader is disposed.
@@ -295,6 +221,14 @@ declare module BABYLON {
          * The loader state or null if the loader is not active.
          */
         readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Defines if the loader logging is enabled.
+         */
+        loggingEnabled: boolean;
+        /**
+         * Defines if the loader should capture performance counters.
+         */
+        capturePerformanceCounters: boolean;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -308,6 +242,8 @@ declare module BABYLON {
          * Disposes the loader, releases resources during load, and cancels any outstanding requests.
          */
         dispose(): void;
+        /** @hidden */
+        _clear(): void;
         /**
          * Imports one or more meshes from the loaded glTF data and adds them to the scene
          * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
@@ -358,12 +294,32 @@ declare module BABYLON {
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
         private _parse(data);
         private _getLoader(loaderData);
-        private static _parseBinary(data);
-        private static _parseV1(binaryReader);
-        private static _parseV2(binaryReader);
+        private _parseBinary(data);
+        private _parseV1(binaryReader);
+        private _parseV2(binaryReader);
         private static _parseVersion(version);
         private static _compareVersion(a, b);
         private static _decodeBufferToText(buffer);
+        private static readonly _logSpaces;
+        private _logIndentLevel;
+        private _loggingEnabled;
+        /** @hidden */
+        _log: (message: string) => void;
+        /** @hidden */
+        _logOpen(message: string): void;
+        /** @hidden */
+        _logClose(): void;
+        private _logEnabled(message);
+        private _logDisabled(message);
+        private _capturePerformanceCounters;
+        /** @hidden */
+        _startPerformanceCounter: (counterName: string) => void;
+        /** @hidden */
+        _endPerformanceCounter: (counterName: string) => void;
+        private _startPerformanceCounterEnabled(counterName);
+        private _startPerformanceCounterDisabled(counterName);
+        private _endPerformanceCounterEnabled(counterName);
+        private _endPerformanceCounterDisabled(counterName);
     }
 }
 
@@ -760,21 +716,6 @@ declare module BABYLON.GLTF1 {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        compileMaterials: boolean;
-        useClipPlane: boolean;
-        compileShadowGenerators: boolean;
-        transparencyAsCoverage: boolean;
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
-        readonly onTextureLoadedObservable: Observable<BaseTexture>;
-        readonly onMaterialLoadedObservable: Observable<Material>;
-        readonly onCameraLoadedObservable: Observable<Camera>;
-        readonly onCompleteObservable: Observable<IGLTFLoader>;
-        readonly onDisposeObservable: Observable<IGLTFLoader>;
-        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1061,18 +1002,13 @@ declare module BABYLON.GLTF2 {
  * Defines the module used to import/export glTF 2.0 assets
  */
 declare module BABYLON.GLTF2 {
-    /**
-     * Loader for loading a glTF 2.0 asset
-     */
+    /** @hidden */
     class GLTFLoader implements IGLTFLoader {
-        /** @hidden */
+        _parent: GLTFFileLoader;
         _gltf: _ILoaderGLTF;
-        /** @hidden */
         _babylonScene: Scene;
-        /** @hidden */
+        _readyPromise: Promise<void>;
         _completePromises: Promise<void>[];
-        /** @hidden */
-        _onReadyObservable: Observable<IGLTFLoader>;
         private _disposed;
         private _state;
         private _extensions;
@@ -1084,102 +1020,19 @@ declare module BABYLON.GLTF2 {
         private _requests;
         private static _ExtensionNames;
         private static _ExtensionFactories;
-        /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        readonly onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        readonly onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        readonly onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        readonly onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        readonly onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
          * Loader state or null if the loader is not active.
          */
         readonly state: Nullable<GLTFLoaderState>;
-        /**
-         * Disposes the loader, releases resources during load, and cancels any outstanding requests.
-         */
+        constructor(parent: GLTFFileLoader);
         dispose(): void;
-        /**
-         * Imports one or more meshes from the loaded glTF data and adds them to the scene
-         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-         * @param scene the scene the meshes should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise containg the loaded meshes, particles, skeletons and animations
-         */
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Imports all objects from the loaded glTF data and adds them to the scene
-         * @param scene the scene the objects should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise which completes when objects have been loaded to the scene
-         */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         private _loadAsync(nodes);
         private _loadData(data);
@@ -1187,15 +1040,12 @@ declare module BABYLON.GLTF2 {
         private _loadExtensions();
         private _checkExtensions();
         private _createRootNode();
-        private _loadNodesAsync(nodes);
-        /** @hidden */
         _loadSceneAsync(context: string, scene: _ILoaderScene): Promise<void>;
         private _forEachPrimitive(node, callback);
         private _getMeshes();
         private _getSkeletons();
         private _getAnimationGroups();
         private _startAnimations();
-        /** @hidden */
         _loadNodeAsync(context: string, node: _ILoaderNode): Promise<void>;
         private _loadMeshAsync(context, node, mesh, babylonMesh);
         private _loadPrimitiveAsync(context, node, mesh, primitive, babylonMesh);
@@ -1216,31 +1066,22 @@ declare module BABYLON.GLTF2 {
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
-        /** @hidden */
         _loadBufferViewAsync(context: string, bufferView: _ILoaderBufferView): Promise<ArrayBufferView>;
         private _loadIndicesAccessorAsync(context, accessor);
         private _loadFloatAccessorAsync(context, accessor);
-        /** @hidden */
         _loadVertexBufferViewAsync(context: string, bufferView: _ILoaderBufferView, kind: string): Promise<Buffer>;
         private _loadVertexAccessorAsync(context, accessor, kind);
         private _getDefaultMaterial(drawMode);
         private _loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial);
-        /** @hidden */
         _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void>;
-        /** @hidden */
         _createMaterial(name: string, drawMode: number): PBRMaterial;
-        /** @hidden */
         _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void>;
-        /** @hidden */
         _loadMaterialAlphaProperties(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): void;
-        /** @hidden */
         _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void>;
         private _loadSampler(context, sampler);
         private _loadImageAsync(context, image);
-        /** @hidden */
         _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress();
-        /** @hidden */
         static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T;
         private static _GetTextureWrapMode(context, mode);
         private static _GetTextureSamplingMode(context, magFilter?, minFilter?);
@@ -1250,8 +1091,6 @@ declare module BABYLON.GLTF2 {
         private static _GetDrawMode(context, mode);
         private _compileMaterialsAsync();
         private _compileShadowGeneratorsAsync();
-        private _clear();
-        /** @hidden */
         _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>): Nullable<Promise<T>>;
     }
 }
@@ -1381,12 +1220,12 @@ declare module BABYLON.GLTF2.Extensions {
          * Dispose the loader to cancel the loading of the next level of LODs.
          */
         onMaterialLODsLoadedObservable: Observable<number>;
-        private _loadingNodeLOD;
-        private _loadNodeSignals;
-        private _loadNodePromises;
-        private _loadingMaterialLOD;
-        private _loadMaterialSignals;
-        private _loadMaterialPromises;
+        private _nodeIndexLOD;
+        private _nodeSignalLODs;
+        private _nodePromiseLODs;
+        private _materialIndexLOD;
+        private _materialSignalLODs;
+        private _materialPromiseLODs;
         constructor(loader: GLTFLoader);
         dispose(): void;
         protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>>;

Разница между файлами не показана из-за своего большого размера
+ 302 - 314
dist/preview release/loaders/babylon.glTFFileLoader.js


Разница между файлами не показана из-за своего большого размера
+ 4 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 18 - 15
dist/preview release/loaders/babylon.stlFileLoader.js

@@ -16,23 +16,26 @@ var BABYLON;
         }
         STLFileLoader.prototype.importMesh = function (meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons) {
             var matches;
-            if (this.isBinary(data)) {
-                // binary .stl
-                var babylonMesh = new BABYLON.Mesh("stlmesh", scene);
-                this.parseBinary(babylonMesh, data);
-                if (meshes) {
-                    meshes.push(babylonMesh);
+            if (typeof data !== "string") {
+                if (this.isBinary(data)) {
+                    // binary .stl
+                    var babylonMesh = new BABYLON.Mesh("stlmesh", scene);
+                    this.parseBinary(babylonMesh, data);
+                    if (meshes) {
+                        meshes.push(babylonMesh);
+                    }
+                    return true;
                 }
-                return true;
-            }
-            // ASCII .stl
-            // convert to string
-            var array_buffer = new Uint8Array(data);
-            var str = '';
-            for (var i = 0; i < data.byteLength; i++) {
-                str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian
+                // ASCII .stl
+                // convert to string
+                var array_buffer = new Uint8Array(data);
+                var str = '';
+                for (var i = 0; i < data.byteLength; i++) {
+                    str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian
+                }
+                data = str;
             }
-            data = str;
+            //if arrived here, data is a string, containing the STLA data.
             while (matches = this.solidPattern.exec(data)) {
                 var meshName = matches[1];
                 var meshNameFromEnd = matches[3];

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylon.stlFileLoader.min.js


+ 49 - 210
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -169,89 +169,15 @@ declare module BABYLON {
          */
         COMPLETE = 2,
     }
-    /**
-     * Loader interface.
-     */
+    /** @hidden */
     interface IGLTFLoader extends IDisposable {
-        /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-         * Loader state or null if the loader is not active.
-         */
-        state: Nullable<GLTFLoaderState>;
-        /**
-         * Imports meshes from the given data and adds them to the scene.
-         */
+        readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Loads all objects from the given data and adds them to the scene.
-         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
     /**
@@ -259,9 +185,9 @@ declare module BABYLON {
      */
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
         /** @hidden */
-        static _CreateGLTFLoaderV1: () => IGLTFLoader;
+        static _CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
         /** @hidden */
-        static _CreateGLTFLoaderV2: () => IGLTFLoader;
+        static _CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
         /**
          * Raised when the asset has been parsed
          */
@@ -357,7 +283,7 @@ declare module BABYLON {
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
-        readonly onCompleteObservable: Observable<GLTFFileLoader>;
+        readonly onCompleteObservable: Observable<void>;
         private _onCompleteObserver;
         /**
          * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
@@ -366,7 +292,7 @@ declare module BABYLON {
         /**
          * Observable raised after the loader is disposed.
          */
-        readonly onDisposeObservable: Observable<GLTFFileLoader>;
+        readonly onDisposeObservable: Observable<void>;
         private _onDisposeObserver;
         /**
          * Callback raised after the loader is disposed.
@@ -391,6 +317,14 @@ declare module BABYLON {
          * The loader state or null if the loader is not active.
          */
         readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Defines if the loader logging is enabled.
+         */
+        loggingEnabled: boolean;
+        /**
+         * Defines if the loader should capture performance counters.
+         */
+        capturePerformanceCounters: boolean;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -404,6 +338,8 @@ declare module BABYLON {
          * Disposes the loader, releases resources during load, and cancels any outstanding requests.
          */
         dispose(): void;
+        /** @hidden */
+        _clear(): void;
         /**
          * Imports one or more meshes from the loaded glTF data and adds them to the scene
          * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
@@ -454,12 +390,32 @@ declare module BABYLON {
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
         private _parse(data);
         private _getLoader(loaderData);
-        private static _parseBinary(data);
-        private static _parseV1(binaryReader);
-        private static _parseV2(binaryReader);
+        private _parseBinary(data);
+        private _parseV1(binaryReader);
+        private _parseV2(binaryReader);
         private static _parseVersion(version);
         private static _compareVersion(a, b);
         private static _decodeBufferToText(buffer);
+        private static readonly _logSpaces;
+        private _logIndentLevel;
+        private _loggingEnabled;
+        /** @hidden */
+        _log: (message: string) => void;
+        /** @hidden */
+        _logOpen(message: string): void;
+        /** @hidden */
+        _logClose(): void;
+        private _logEnabled(message);
+        private _logDisabled(message);
+        private _capturePerformanceCounters;
+        /** @hidden */
+        _startPerformanceCounter: (counterName: string) => void;
+        /** @hidden */
+        _endPerformanceCounter: (counterName: string) => void;
+        private _startPerformanceCounterEnabled(counterName);
+        private _startPerformanceCounterDisabled(counterName);
+        private _endPerformanceCounterEnabled(counterName);
+        private _endPerformanceCounterDisabled(counterName);
     }
 }
 
@@ -856,21 +812,6 @@ declare module BABYLON.GLTF1 {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        compileMaterials: boolean;
-        useClipPlane: boolean;
-        compileShadowGenerators: boolean;
-        transparencyAsCoverage: boolean;
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
-        readonly onTextureLoadedObservable: Observable<BaseTexture>;
-        readonly onMaterialLoadedObservable: Observable<Material>;
-        readonly onCameraLoadedObservable: Observable<Camera>;
-        readonly onCompleteObservable: Observable<IGLTFLoader>;
-        readonly onDisposeObservable: Observable<IGLTFLoader>;
-        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1157,18 +1098,13 @@ declare module BABYLON.GLTF2 {
  * Defines the module used to import/export glTF 2.0 assets
  */
 declare module BABYLON.GLTF2 {
-    /**
-     * Loader for loading a glTF 2.0 asset
-     */
+    /** @hidden */
     class GLTFLoader implements IGLTFLoader {
-        /** @hidden */
+        _parent: GLTFFileLoader;
         _gltf: _ILoaderGLTF;
-        /** @hidden */
         _babylonScene: Scene;
-        /** @hidden */
+        _readyPromise: Promise<void>;
         _completePromises: Promise<void>[];
-        /** @hidden */
-        _onReadyObservable: Observable<IGLTFLoader>;
         private _disposed;
         private _state;
         private _extensions;
@@ -1180,102 +1116,19 @@ declare module BABYLON.GLTF2 {
         private _requests;
         private static _ExtensionNames;
         private static _ExtensionFactories;
-        /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        readonly onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        readonly onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        readonly onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        readonly onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        readonly onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
          * Loader state or null if the loader is not active.
          */
         readonly state: Nullable<GLTFLoaderState>;
-        /**
-         * Disposes the loader, releases resources during load, and cancels any outstanding requests.
-         */
+        constructor(parent: GLTFFileLoader);
         dispose(): void;
-        /**
-         * Imports one or more meshes from the loaded glTF data and adds them to the scene
-         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-         * @param scene the scene the meshes should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise containg the loaded meshes, particles, skeletons and animations
-         */
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Imports all objects from the loaded glTF data and adds them to the scene
-         * @param scene the scene the objects should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise which completes when objects have been loaded to the scene
-         */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         private _loadAsync(nodes);
         private _loadData(data);
@@ -1283,15 +1136,12 @@ declare module BABYLON.GLTF2 {
         private _loadExtensions();
         private _checkExtensions();
         private _createRootNode();
-        private _loadNodesAsync(nodes);
-        /** @hidden */
         _loadSceneAsync(context: string, scene: _ILoaderScene): Promise<void>;
         private _forEachPrimitive(node, callback);
         private _getMeshes();
         private _getSkeletons();
         private _getAnimationGroups();
         private _startAnimations();
-        /** @hidden */
         _loadNodeAsync(context: string, node: _ILoaderNode): Promise<void>;
         private _loadMeshAsync(context, node, mesh, babylonMesh);
         private _loadPrimitiveAsync(context, node, mesh, primitive, babylonMesh);
@@ -1312,31 +1162,22 @@ declare module BABYLON.GLTF2 {
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
-        /** @hidden */
         _loadBufferViewAsync(context: string, bufferView: _ILoaderBufferView): Promise<ArrayBufferView>;
         private _loadIndicesAccessorAsync(context, accessor);
         private _loadFloatAccessorAsync(context, accessor);
-        /** @hidden */
         _loadVertexBufferViewAsync(context: string, bufferView: _ILoaderBufferView, kind: string): Promise<Buffer>;
         private _loadVertexAccessorAsync(context, accessor, kind);
         private _getDefaultMaterial(drawMode);
         private _loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial);
-        /** @hidden */
         _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void>;
-        /** @hidden */
         _createMaterial(name: string, drawMode: number): PBRMaterial;
-        /** @hidden */
         _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void>;
-        /** @hidden */
         _loadMaterialAlphaProperties(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): void;
-        /** @hidden */
         _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void>;
         private _loadSampler(context, sampler);
         private _loadImageAsync(context, image);
-        /** @hidden */
         _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress();
-        /** @hidden */
         static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T;
         private static _GetTextureWrapMode(context, mode);
         private static _GetTextureSamplingMode(context, magFilter?, minFilter?);
@@ -1346,8 +1187,6 @@ declare module BABYLON.GLTF2 {
         private static _GetDrawMode(context, mode);
         private _compileMaterialsAsync();
         private _compileShadowGeneratorsAsync();
-        private _clear();
-        /** @hidden */
         _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>): Nullable<Promise<T>>;
     }
 }
@@ -1477,12 +1316,12 @@ declare module BABYLON.GLTF2.Extensions {
          * Dispose the loader to cancel the loading of the next level of LODs.
          */
         onMaterialLODsLoadedObservable: Observable<number>;
-        private _loadingNodeLOD;
-        private _loadNodeSignals;
-        private _loadNodePromises;
-        private _loadingMaterialLOD;
-        private _loadMaterialSignals;
-        private _loadMaterialPromises;
+        private _nodeIndexLOD;
+        private _nodeSignalLODs;
+        private _nodePromiseLODs;
+        private _materialIndexLOD;
+        private _materialSignalLODs;
+        private _materialPromiseLODs;
         constructor(loader: GLTFLoader);
         dispose(): void;
         protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>>;

Разница между файлами не показана из-за своего большого размера
+ 319 - 328
dist/preview release/loaders/babylonjs.loaders.js


Разница между файлами не показана из-за своего большого размера
+ 4 - 4
dist/preview release/loaders/babylonjs.loaders.min.js


+ 49 - 210
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -176,89 +176,15 @@ declare module BABYLON {
          */
         COMPLETE = 2,
     }
-    /**
-     * Loader interface.
-     */
+    /** @hidden */
     interface IGLTFLoader extends IDisposable {
-        /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-         * Loader state or null if the loader is not active.
-         */
-        state: Nullable<GLTFLoaderState>;
-        /**
-         * Imports meshes from the given data and adds them to the scene.
-         */
+        readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Loads all objects from the given data and adds them to the scene.
-         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
     /**
@@ -266,9 +192,9 @@ declare module BABYLON {
      */
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
         /** @hidden */
-        static _CreateGLTFLoaderV1: () => IGLTFLoader;
+        static _CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
         /** @hidden */
-        static _CreateGLTFLoaderV2: () => IGLTFLoader;
+        static _CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
         /**
          * Raised when the asset has been parsed
          */
@@ -364,7 +290,7 @@ declare module BABYLON {
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
-        readonly onCompleteObservable: Observable<GLTFFileLoader>;
+        readonly onCompleteObservable: Observable<void>;
         private _onCompleteObserver;
         /**
          * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
@@ -373,7 +299,7 @@ declare module BABYLON {
         /**
          * Observable raised after the loader is disposed.
          */
-        readonly onDisposeObservable: Observable<GLTFFileLoader>;
+        readonly onDisposeObservable: Observable<void>;
         private _onDisposeObserver;
         /**
          * Callback raised after the loader is disposed.
@@ -398,6 +324,14 @@ declare module BABYLON {
          * The loader state or null if the loader is not active.
          */
         readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Defines if the loader logging is enabled.
+         */
+        loggingEnabled: boolean;
+        /**
+         * Defines if the loader should capture performance counters.
+         */
+        capturePerformanceCounters: boolean;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -411,6 +345,8 @@ declare module BABYLON {
          * Disposes the loader, releases resources during load, and cancels any outstanding requests.
          */
         dispose(): void;
+        /** @hidden */
+        _clear(): void;
         /**
          * Imports one or more meshes from the loaded glTF data and adds them to the scene
          * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
@@ -461,12 +397,32 @@ declare module BABYLON {
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
         private _parse(data);
         private _getLoader(loaderData);
-        private static _parseBinary(data);
-        private static _parseV1(binaryReader);
-        private static _parseV2(binaryReader);
+        private _parseBinary(data);
+        private _parseV1(binaryReader);
+        private _parseV2(binaryReader);
         private static _parseVersion(version);
         private static _compareVersion(a, b);
         private static _decodeBufferToText(buffer);
+        private static readonly _logSpaces;
+        private _logIndentLevel;
+        private _loggingEnabled;
+        /** @hidden */
+        _log: (message: string) => void;
+        /** @hidden */
+        _logOpen(message: string): void;
+        /** @hidden */
+        _logClose(): void;
+        private _logEnabled(message);
+        private _logDisabled(message);
+        private _capturePerformanceCounters;
+        /** @hidden */
+        _startPerformanceCounter: (counterName: string) => void;
+        /** @hidden */
+        _endPerformanceCounter: (counterName: string) => void;
+        private _startPerformanceCounterEnabled(counterName);
+        private _startPerformanceCounterDisabled(counterName);
+        private _endPerformanceCounterEnabled(counterName);
+        private _endPerformanceCounterDisabled(counterName);
     }
 }
 
@@ -863,21 +819,6 @@ declare module BABYLON.GLTF1 {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        compileMaterials: boolean;
-        useClipPlane: boolean;
-        compileShadowGenerators: boolean;
-        transparencyAsCoverage: boolean;
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
-        readonly onTextureLoadedObservable: Observable<BaseTexture>;
-        readonly onMaterialLoadedObservable: Observable<Material>;
-        readonly onCameraLoadedObservable: Observable<Camera>;
-        readonly onCompleteObservable: Observable<IGLTFLoader>;
-        readonly onDisposeObservable: Observable<IGLTFLoader>;
-        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1164,18 +1105,13 @@ declare module BABYLON.GLTF2 {
  * Defines the module used to import/export glTF 2.0 assets
  */
 declare module BABYLON.GLTF2 {
-    /**
-     * Loader for loading a glTF 2.0 asset
-     */
+    /** @hidden */
     class GLTFLoader implements IGLTFLoader {
-        /** @hidden */
+        _parent: GLTFFileLoader;
         _gltf: _ILoaderGLTF;
-        /** @hidden */
         _babylonScene: Scene;
-        /** @hidden */
+        _readyPromise: Promise<void>;
         _completePromises: Promise<void>[];
-        /** @hidden */
-        _onReadyObservable: Observable<IGLTFLoader>;
         private _disposed;
         private _state;
         private _extensions;
@@ -1187,102 +1123,19 @@ declare module BABYLON.GLTF2 {
         private _requests;
         private static _ExtensionNames;
         private static _ExtensionFactories;
-        /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage.
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        readonly onTextureLoadedObservable: Observable<BaseTexture>;
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        readonly onMaterialLoadedObservable: Observable<Material>;
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        readonly onCameraLoadedObservable: Observable<Camera>;
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        readonly onCompleteObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        readonly onDisposeObservable: Observable<IGLTFLoader>;
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
          * Loader state or null if the loader is not active.
          */
         readonly state: Nullable<GLTFLoaderState>;
-        /**
-         * Disposes the loader, releases resources during load, and cancels any outstanding requests.
-         */
+        constructor(parent: GLTFFileLoader);
         dispose(): void;
-        /**
-         * Imports one or more meshes from the loaded glTF data and adds them to the scene
-         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-         * @param scene the scene the meshes should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise containg the loaded meshes, particles, skeletons and animations
-         */
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        /**
-         * Imports all objects from the loaded glTF data and adds them to the scene
-         * @param scene the scene the objects should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise which completes when objects have been loaded to the scene
-         */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         private _loadAsync(nodes);
         private _loadData(data);
@@ -1290,15 +1143,12 @@ declare module BABYLON.GLTF2 {
         private _loadExtensions();
         private _checkExtensions();
         private _createRootNode();
-        private _loadNodesAsync(nodes);
-        /** @hidden */
         _loadSceneAsync(context: string, scene: _ILoaderScene): Promise<void>;
         private _forEachPrimitive(node, callback);
         private _getMeshes();
         private _getSkeletons();
         private _getAnimationGroups();
         private _startAnimations();
-        /** @hidden */
         _loadNodeAsync(context: string, node: _ILoaderNode): Promise<void>;
         private _loadMeshAsync(context, node, mesh, babylonMesh);
         private _loadPrimitiveAsync(context, node, mesh, primitive, babylonMesh);
@@ -1319,31 +1169,22 @@ declare module BABYLON.GLTF2 {
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
-        /** @hidden */
         _loadBufferViewAsync(context: string, bufferView: _ILoaderBufferView): Promise<ArrayBufferView>;
         private _loadIndicesAccessorAsync(context, accessor);
         private _loadFloatAccessorAsync(context, accessor);
-        /** @hidden */
         _loadVertexBufferViewAsync(context: string, bufferView: _ILoaderBufferView, kind: string): Promise<Buffer>;
         private _loadVertexAccessorAsync(context, accessor, kind);
         private _getDefaultMaterial(drawMode);
         private _loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial);
-        /** @hidden */
         _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void>;
-        /** @hidden */
         _createMaterial(name: string, drawMode: number): PBRMaterial;
-        /** @hidden */
         _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void>;
-        /** @hidden */
         _loadMaterialAlphaProperties(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): void;
-        /** @hidden */
         _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void>;
         private _loadSampler(context, sampler);
         private _loadImageAsync(context, image);
-        /** @hidden */
         _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress();
-        /** @hidden */
         static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T;
         private static _GetTextureWrapMode(context, mode);
         private static _GetTextureSamplingMode(context, magFilter?, minFilter?);
@@ -1353,8 +1194,6 @@ declare module BABYLON.GLTF2 {
         private static _GetDrawMode(context, mode);
         private _compileMaterialsAsync();
         private _compileShadowGeneratorsAsync();
-        private _clear();
-        /** @hidden */
         _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>): Nullable<Promise<T>>;
     }
 }
@@ -1484,12 +1323,12 @@ declare module BABYLON.GLTF2.Extensions {
          * Dispose the loader to cancel the loading of the next level of LODs.
          */
         onMaterialLODsLoadedObservable: Observable<number>;
-        private _loadingNodeLOD;
-        private _loadNodeSignals;
-        private _loadNodePromises;
-        private _loadingMaterialLOD;
-        private _loadMaterialSignals;
-        private _loadMaterialPromises;
+        private _nodeIndexLOD;
+        private _nodeSignalLODs;
+        private _nodePromiseLODs;
+        private _materialIndexLOD;
+        private _materialSignalLODs;
+        private _materialPromiseLODs;
         constructor(loader: GLTFLoader);
         dispose(): void;
         protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>>;

+ 1 - 0
dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.d.ts

@@ -13,6 +13,7 @@ declare module BABYLON {
         static readonly GreenFireColors: Color3[];
         static readonly RedFireColors: Color3[];
         static readonly BlueFireColors: Color3[];
+        autoGenerateTime: boolean;
         fireColors: Color3[];
         time: number;
         speed: Vector2;

+ 21 - 2
dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.js

@@ -104,6 +104,16 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(FireProceduralTexture.prototype, "autoGenerateTime", {
+            get: function () {
+                return this._autoGenerateTime;
+            },
+            set: function (value) {
+                this._autoGenerateTime = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(FireProceduralTexture.prototype, "fireColors", {
             get: function () {
                 return this._fireColors;
@@ -155,6 +165,10 @@ var BABYLON;
         FireProceduralTexture.prototype.serialize = function () {
             var serializationObject = BABYLON.SerializationHelper.Serialize(this, _super.prototype.serialize.call(this));
             serializationObject.customType = "BABYLON.FireProceduralTexture";
+            serializationObject.fireColors = [];
+            for (var i = 0; i < this._fireColors.length; i++) {
+                serializationObject.fireColors.push(this._fireColors[i].asArray());
+            }
             return serializationObject;
         };
         /**
@@ -166,11 +180,16 @@ var BABYLON;
          */
         FireProceduralTexture.Parse = function (parsedTexture, scene, rootUrl) {
             var texture = BABYLON.SerializationHelper.Parse(function () { return new FireProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps); }, parsedTexture, scene, rootUrl);
+            var colors = [];
+            for (var i = 0; i < parsedTexture.fireColors.length; i++) {
+                colors.push(BABYLON.Color3.FromArray(parsedTexture.fireColors[i]));
+            }
+            texture.fireColors = colors;
             return texture;
         };
         __decorate([
-            BABYLON.serializeAsColor3()
-        ], FireProceduralTexture.prototype, "fireColors", null);
+            BABYLON.serialize()
+        ], FireProceduralTexture.prototype, "autoGenerateTime", null);
         __decorate([
             BABYLON.serialize()
         ], FireProceduralTexture.prototype, "time", null);

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js


+ 9 - 3
dist/preview release/proceduralTexturesLibrary/babylon.grassProceduralTexture.js

@@ -65,6 +65,10 @@ var BABYLON;
         GrassProceduralTexture.prototype.serialize = function () {
             var serializationObject = BABYLON.SerializationHelper.Serialize(this, _super.prototype.serialize.call(this));
             serializationObject.customType = "BABYLON.GrassProceduralTexture";
+            serializationObject.grassColors = [];
+            for (var i = 0; i < this._grassColors.length; i++) {
+                serializationObject.grassColors.push(this._grassColors[i].asArray());
+            }
             return serializationObject;
         };
         /**
@@ -76,13 +80,15 @@ var BABYLON;
          */
         GrassProceduralTexture.Parse = function (parsedTexture, scene, rootUrl) {
             var texture = BABYLON.SerializationHelper.Parse(function () { return new GrassProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps); }, parsedTexture, scene, rootUrl);
+            var colors = [];
+            for (var i = 0; i < parsedTexture.grassColors.length; i++) {
+                colors.push(BABYLON.Color3.FromArray(parsedTexture.grassColors[i]));
+            }
+            texture.grassColors = colors;
             return texture;
         };
         __decorate([
             BABYLON.serializeAsColor3()
-        ], GrassProceduralTexture.prototype, "grassColors", null);
-        __decorate([
-            BABYLON.serializeAsColor3()
         ], GrassProceduralTexture.prototype, "groundColor", null);
         return GrassProceduralTexture;
     }(BABYLON.ProceduralTexture));

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js


+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.d.ts

@@ -2,7 +2,7 @@
 declare module BABYLON {
     class PerlinNoiseProceduralTexture extends ProceduralTexture {
         time: number;
-        speed: number;
+        timeScale: number;
         translationSpeed: number;
         private _currentTranslation;
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean);

+ 3 - 3
dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.js

@@ -22,7 +22,7 @@ var BABYLON;
         function PerlinNoiseProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
             var _this = _super.call(this, name, size, "perlinNoiseProceduralTexture", scene, fallbackTexture, generateMipMaps) || this;
             _this.time = 0.0;
-            _this.speed = 1.0;
+            _this.timeScale = 1.0;
             _this.translationSpeed = 1.0;
             _this._currentTranslation = 0;
             _this.updateShaderUniforms();
@@ -36,7 +36,7 @@ var BABYLON;
             }
             var deltaTime = scene.getEngine().getDeltaTime();
             this.time += deltaTime;
-            this.setFloat("time", this.time * this.speed / 1000);
+            this.setFloat("time", this.time * this.timeScale / 1000);
             this._currentTranslation += deltaTime * this.translationSpeed / 1000.0;
             this.setFloat("translationSpeed", this._currentTranslation);
         };
@@ -72,7 +72,7 @@ var BABYLON;
         ], PerlinNoiseProceduralTexture.prototype, "time", void 0);
         __decorate([
             BABYLON.serialize()
-        ], PerlinNoiseProceduralTexture.prototype, "speed", void 0);
+        ], PerlinNoiseProceduralTexture.prototype, "timeScale", void 0);
         __decorate([
             BABYLON.serialize()
         ], PerlinNoiseProceduralTexture.prototype, "translationSpeed", void 0);

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylon.perlinNoiseProceduralTexture.min.js


+ 2 - 1
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.d.ts

@@ -38,6 +38,7 @@ declare module BABYLON {
         static readonly GreenFireColors: Color3[];
         static readonly RedFireColors: Color3[];
         static readonly BlueFireColors: Color3[];
+        autoGenerateTime: boolean;
         fireColors: Color3[];
         time: number;
         speed: Vector2;
@@ -261,7 +262,7 @@ declare module BABYLON {
 declare module BABYLON {
     class PerlinNoiseProceduralTexture extends ProceduralTexture {
         time: number;
-        speed: number;
+        timeScale: number;
         translationSpeed: number;
         private _currentTranslation;
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean);

+ 33 - 8
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js

@@ -190,6 +190,16 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(FireProceduralTexture.prototype, "autoGenerateTime", {
+            get: function () {
+                return this._autoGenerateTime;
+            },
+            set: function (value) {
+                this._autoGenerateTime = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(FireProceduralTexture.prototype, "fireColors", {
             get: function () {
                 return this._fireColors;
@@ -241,6 +251,10 @@ var BABYLON;
         FireProceduralTexture.prototype.serialize = function () {
             var serializationObject = BABYLON.SerializationHelper.Serialize(this, _super.prototype.serialize.call(this));
             serializationObject.customType = "BABYLON.FireProceduralTexture";
+            serializationObject.fireColors = [];
+            for (var i = 0; i < this._fireColors.length; i++) {
+                serializationObject.fireColors.push(this._fireColors[i].asArray());
+            }
             return serializationObject;
         };
         /**
@@ -252,11 +266,16 @@ var BABYLON;
          */
         FireProceduralTexture.Parse = function (parsedTexture, scene, rootUrl) {
             var texture = BABYLON.SerializationHelper.Parse(function () { return new FireProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps); }, parsedTexture, scene, rootUrl);
+            var colors = [];
+            for (var i = 0; i < parsedTexture.fireColors.length; i++) {
+                colors.push(BABYLON.Color3.FromArray(parsedTexture.fireColors[i]));
+            }
+            texture.fireColors = colors;
             return texture;
         };
         __decorate([
-            BABYLON.serializeAsColor3()
-        ], FireProceduralTexture.prototype, "fireColors", null);
+            BABYLON.serialize()
+        ], FireProceduralTexture.prototype, "autoGenerateTime", null);
         __decorate([
             BABYLON.serialize()
         ], FireProceduralTexture.prototype, "time", null);
@@ -403,6 +422,10 @@ var BABYLON;
         GrassProceduralTexture.prototype.serialize = function () {
             var serializationObject = BABYLON.SerializationHelper.Serialize(this, _super.prototype.serialize.call(this));
             serializationObject.customType = "BABYLON.GrassProceduralTexture";
+            serializationObject.grassColors = [];
+            for (var i = 0; i < this._grassColors.length; i++) {
+                serializationObject.grassColors.push(this._grassColors[i].asArray());
+            }
             return serializationObject;
         };
         /**
@@ -414,13 +437,15 @@ var BABYLON;
          */
         GrassProceduralTexture.Parse = function (parsedTexture, scene, rootUrl) {
             var texture = BABYLON.SerializationHelper.Parse(function () { return new GrassProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps); }, parsedTexture, scene, rootUrl);
+            var colors = [];
+            for (var i = 0; i < parsedTexture.grassColors.length; i++) {
+                colors.push(BABYLON.Color3.FromArray(parsedTexture.grassColors[i]));
+            }
+            texture.grassColors = colors;
             return texture;
         };
         __decorate([
             BABYLON.serializeAsColor3()
-        ], GrassProceduralTexture.prototype, "grassColors", null);
-        __decorate([
-            BABYLON.serializeAsColor3()
         ], GrassProceduralTexture.prototype, "groundColor", null);
         return GrassProceduralTexture;
     }(BABYLON.ProceduralTexture));
@@ -1000,7 +1025,7 @@ var BABYLON;
         function PerlinNoiseProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
             var _this = _super.call(this, name, size, "perlinNoiseProceduralTexture", scene, fallbackTexture, generateMipMaps) || this;
             _this.time = 0.0;
-            _this.speed = 1.0;
+            _this.timeScale = 1.0;
             _this.translationSpeed = 1.0;
             _this._currentTranslation = 0;
             _this.updateShaderUniforms();
@@ -1014,7 +1039,7 @@ var BABYLON;
             }
             var deltaTime = scene.getEngine().getDeltaTime();
             this.time += deltaTime;
-            this.setFloat("time", this.time * this.speed / 1000);
+            this.setFloat("time", this.time * this.timeScale / 1000);
             this._currentTranslation += deltaTime * this.translationSpeed / 1000.0;
             this.setFloat("translationSpeed", this._currentTranslation);
         };
@@ -1050,7 +1075,7 @@ var BABYLON;
         ], PerlinNoiseProceduralTexture.prototype, "time", void 0);
         __decorate([
             BABYLON.serialize()
-        ], PerlinNoiseProceduralTexture.prototype, "speed", void 0);
+        ], PerlinNoiseProceduralTexture.prototype, "timeScale", void 0);
         __decorate([
             BABYLON.serialize()
         ], PerlinNoiseProceduralTexture.prototype, "translationSpeed", void 0);

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js


+ 2 - 1
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.module.d.ts

@@ -43,6 +43,7 @@ declare module BABYLON {
         static readonly GreenFireColors: Color3[];
         static readonly RedFireColors: Color3[];
         static readonly BlueFireColors: Color3[];
+        autoGenerateTime: boolean;
         fireColors: Color3[];
         time: number;
         speed: Vector2;
@@ -266,7 +267,7 @@ declare module BABYLON {
 declare module BABYLON {
     class PerlinNoiseProceduralTexture extends ProceduralTexture {
         time: number;
-        speed: number;
+        timeScale: number;
         translationSpeed: number;
         private _currentTranslation;
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean);

+ 2 - 2
dist/preview release/serializers/babylon.glTF2Serializer.d.ts

@@ -457,7 +457,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonMaterial Babylon Material
          * @returns The Babylon alpha mode value
          */
-        static _GetAlphaMode(babylonMaterial: Material): Nullable<MaterialAlphaMode>;
+        static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
         /**
          * Converts a Babylon Standard Material to a glTF Material
          * @param babylonStandardMaterial BJS Standard Material
@@ -482,7 +482,7 @@ declare module BABYLON.GLTF2 {
          * @param useAlpha Specifies if alpha should be preserved or not
          * @returns Promise with texture
          */
-        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<Texture>;
+        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<BaseTexture>;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material

+ 22 - 69
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -46,7 +46,7 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.glTFSerializer.js.map
 
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 var BABYLON;
 (function (BABYLON) {
     var GLTF2;
@@ -1245,7 +1245,7 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.glTFExporter.js.map
 
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 var BABYLON;
 (function (BABYLON) {
     /**
@@ -1304,7 +1304,7 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.glTFData.js.map
 
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 var BABYLON;
 (function (BABYLON) {
     var GLTF2;
@@ -1472,64 +1472,14 @@ var BABYLON;
              * @returns The Babylon alpha mode value
              */
             _GLTFMaterial._GetAlphaMode = function (babylonMaterial) {
-                if (babylonMaterial instanceof BABYLON.StandardMaterial) {
-                    var babylonStandardMaterial = babylonMaterial;
-                    if ((babylonStandardMaterial.alpha !== 1.0) ||
-                        (babylonStandardMaterial.diffuseTexture != null && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
-                        (babylonStandardMaterial.opacityTexture != null)) {
-                        return "BLEND" /* BLEND */;
-                    }
-                    else {
-                        return "OPAQUE" /* OPAQUE */;
-                    }
-                }
-                else if (babylonMaterial instanceof BABYLON.PBRMetallicRoughnessMaterial) {
-                    var babylonPBRMetallicRoughness = babylonMaterial;
-                    switch (babylonPBRMetallicRoughness.transparencyMode) {
-                        case BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE: {
-                            return "OPAQUE" /* OPAQUE */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND: {
-                            return "BLEND" /* BLEND */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST: {
-                            return "MASK" /* MASK */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
-                            BABYLON.Tools.Warn(babylonMaterial.name + ": GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
-                            return "BLEND" /* BLEND */;
-                        }
-                        default: {
-                            BABYLON.Tools.Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
-                            return null;
-                        }
-                    }
+                if (babylonMaterial.needAlphaBlending()) {
+                    return "BLEND" /* BLEND */;
                 }
-                else if (babylonMaterial instanceof BABYLON.PBRMaterial) {
-                    var babylonPBRMaterial = babylonMaterial;
-                    switch (babylonPBRMaterial.transparencyMode) {
-                        case BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE: {
-                            return "OPAQUE" /* OPAQUE */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND: {
-                            return "BLEND" /* BLEND */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST: {
-                            return "MASK" /* MASK */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
-                            BABYLON.Tools.Warn(babylonMaterial.name + ": GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
-                            return "BLEND" /* BLEND */;
-                        }
-                        default: {
-                            BABYLON.Tools.Error("Unsupported alpha mode " + babylonPBRMaterial.transparencyMode);
-                            return null;
-                        }
-                    }
+                else if (babylonMaterial.needAlphaTesting) {
+                    return "MASK" /* MASK */;
                 }
                 else {
-                    BABYLON.Tools.Error("Unsupported Babylon material type");
-                    return null;
+                    return "OPAQUE" /* OPAQUE */;
                 }
             };
             /**
@@ -1640,19 +1590,22 @@ var BABYLON;
                         resolve(texture);
                     }
                     else {
-                        var scene = texture.getScene();
-                        if (scene) {
-                            var proceduralTexture_1 = new BABYLON.ProceduralTexture('texture', texture.getSize(), 'setAlphaToOne', scene);
-                            if (proceduralTexture_1) {
+                        if (texture instanceof BABYLON.Texture) {
+                            var scene = texture.getScene();
+                            if (scene) {
+                                var proceduralTexture_1 = new BABYLON.ProceduralTexture('texture', texture.getSize(), 'setAlphaToOne', scene);
                                 proceduralTexture_1.setTexture('textureSampler', texture);
-                                proceduralTexture_1.onLoadObservable.add(function () { resolve(proceduralTexture_1); });
+                                proceduralTexture_1.onGenerated = function () {
+                                    resolve(proceduralTexture_1);
+                                };
                             }
                             else {
-                                reject("Cannot create procedural texture for " + texture.name + "!");
+                                reject("Scene not available for texture " + texture.name);
                             }
                         }
                         else {
-                            reject("Scene not available for texture " + texture.name);
+                            BABYLON.Tools.Warn("Removing alpha for " + texture.textureType + " not supported");
+                            resolve(texture);
                         }
                     }
                 });
@@ -1801,7 +1754,7 @@ var BABYLON;
                 var resizedTexture1;
                 var resizedTexture2;
                 if (texture1Size.width < texture2Size.width) {
-                    if (texture1) {
+                    if (texture1 && texture1 instanceof BABYLON.Texture) {
                         resizedTexture1 = BABYLON.TextureTools.CreateResizedCopy(texture1, texture2Size.width, texture2Size.height, true);
                     }
                     else {
@@ -1810,7 +1763,7 @@ var BABYLON;
                     resizedTexture2 = texture2;
                 }
                 else if (texture1Size.width > texture2Size.width) {
-                    if (texture2) {
+                    if (texture2 && texture2 instanceof BABYLON.Texture) {
                         resizedTexture2 = BABYLON.TextureTools.CreateResizedCopy(texture2, texture1Size.width, texture1Size.height, true);
                     }
                     else {
@@ -2410,7 +2363,7 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.glTFMaterial.js.map
 
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 var BABYLON;
 (function (BABYLON) {
     var GLTF2;
@@ -3066,7 +3019,7 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.glTFAnimation.js.map
 
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 var BABYLON;
 (function (BABYLON) {
     var GLTF2;

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/serializers/babylon.glTF2Serializer.min.js


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

@@ -465,7 +465,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonMaterial Babylon Material
          * @returns The Babylon alpha mode value
          */
-        static _GetAlphaMode(babylonMaterial: Material): Nullable<MaterialAlphaMode>;
+        static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
         /**
          * Converts a Babylon Standard Material to a glTF Material
          * @param babylonStandardMaterial BJS Standard Material
@@ -490,7 +490,7 @@ declare module BABYLON.GLTF2 {
          * @param useAlpha Specifies if alpha should be preserved or not
          * @returns Promise with texture
          */
-        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<Texture>;
+        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<BaseTexture>;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material

+ 17 - 64
dist/preview release/serializers/babylonjs.serializers.js

@@ -1622,64 +1622,14 @@ var BABYLON;
              * @returns The Babylon alpha mode value
              */
             _GLTFMaterial._GetAlphaMode = function (babylonMaterial) {
-                if (babylonMaterial instanceof BABYLON.StandardMaterial) {
-                    var babylonStandardMaterial = babylonMaterial;
-                    if ((babylonStandardMaterial.alpha !== 1.0) ||
-                        (babylonStandardMaterial.diffuseTexture != null && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
-                        (babylonStandardMaterial.opacityTexture != null)) {
-                        return "BLEND" /* BLEND */;
-                    }
-                    else {
-                        return "OPAQUE" /* OPAQUE */;
-                    }
-                }
-                else if (babylonMaterial instanceof BABYLON.PBRMetallicRoughnessMaterial) {
-                    var babylonPBRMetallicRoughness = babylonMaterial;
-                    switch (babylonPBRMetallicRoughness.transparencyMode) {
-                        case BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE: {
-                            return "OPAQUE" /* OPAQUE */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND: {
-                            return "BLEND" /* BLEND */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST: {
-                            return "MASK" /* MASK */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
-                            BABYLON.Tools.Warn(babylonMaterial.name + ": GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
-                            return "BLEND" /* BLEND */;
-                        }
-                        default: {
-                            BABYLON.Tools.Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
-                            return null;
-                        }
-                    }
+                if (babylonMaterial.needAlphaBlending()) {
+                    return "BLEND" /* BLEND */;
                 }
-                else if (babylonMaterial instanceof BABYLON.PBRMaterial) {
-                    var babylonPBRMaterial = babylonMaterial;
-                    switch (babylonPBRMaterial.transparencyMode) {
-                        case BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE: {
-                            return "OPAQUE" /* OPAQUE */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND: {
-                            return "BLEND" /* BLEND */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST: {
-                            return "MASK" /* MASK */;
-                        }
-                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
-                            BABYLON.Tools.Warn(babylonMaterial.name + ": GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
-                            return "BLEND" /* BLEND */;
-                        }
-                        default: {
-                            BABYLON.Tools.Error("Unsupported alpha mode " + babylonPBRMaterial.transparencyMode);
-                            return null;
-                        }
-                    }
+                else if (babylonMaterial.needAlphaTesting) {
+                    return "MASK" /* MASK */;
                 }
                 else {
-                    BABYLON.Tools.Error("Unsupported Babylon material type");
-                    return null;
+                    return "OPAQUE" /* OPAQUE */;
                 }
             };
             /**
@@ -1790,19 +1740,22 @@ var BABYLON;
                         resolve(texture);
                     }
                     else {
-                        var scene = texture.getScene();
-                        if (scene) {
-                            var proceduralTexture_1 = new BABYLON.ProceduralTexture('texture', texture.getSize(), 'setAlphaToOne', scene);
-                            if (proceduralTexture_1) {
+                        if (texture instanceof BABYLON.Texture) {
+                            var scene = texture.getScene();
+                            if (scene) {
+                                var proceduralTexture_1 = new BABYLON.ProceduralTexture('texture', texture.getSize(), 'setAlphaToOne', scene);
                                 proceduralTexture_1.setTexture('textureSampler', texture);
-                                proceduralTexture_1.onLoadObservable.add(function () { resolve(proceduralTexture_1); });
+                                proceduralTexture_1.onGenerated = function () {
+                                    resolve(proceduralTexture_1);
+                                };
                             }
                             else {
-                                reject("Cannot create procedural texture for " + texture.name + "!");
+                                reject("Scene not available for texture " + texture.name);
                             }
                         }
                         else {
-                            reject("Scene not available for texture " + texture.name);
+                            BABYLON.Tools.Warn("Removing alpha for " + texture.textureType + " not supported");
+                            resolve(texture);
                         }
                     }
                 });
@@ -1951,7 +1904,7 @@ var BABYLON;
                 var resizedTexture1;
                 var resizedTexture2;
                 if (texture1Size.width < texture2Size.width) {
-                    if (texture1) {
+                    if (texture1 && texture1 instanceof BABYLON.Texture) {
                         resizedTexture1 = BABYLON.TextureTools.CreateResizedCopy(texture1, texture2Size.width, texture2Size.height, true);
                     }
                     else {
@@ -1960,7 +1913,7 @@ var BABYLON;
                     resizedTexture2 = texture2;
                 }
                 else if (texture1Size.width > texture2Size.width) {
-                    if (texture2) {
+                    if (texture2 && texture2 instanceof BABYLON.Texture) {
                         resizedTexture2 = BABYLON.TextureTools.CreateResizedCopy(texture2, texture1Size.width, texture1Size.height, true);
                     }
                     else {

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/serializers/babylonjs.serializers.min.js


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

@@ -472,7 +472,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonMaterial Babylon Material
          * @returns The Babylon alpha mode value
          */
-        static _GetAlphaMode(babylonMaterial: Material): Nullable<MaterialAlphaMode>;
+        static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
         /**
          * Converts a Babylon Standard Material to a glTF Material
          * @param babylonStandardMaterial BJS Standard Material
@@ -497,7 +497,7 @@ declare module BABYLON.GLTF2 {
          * @param useAlpha Specifies if alpha should be preserved or not
          * @returns Promise with texture
          */
-        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<Texture>;
+        static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<BaseTexture>;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material

+ 1 - 1
dist/preview release/viewer/babylon.viewer.d.ts

@@ -1286,7 +1286,7 @@ declare module BabylonViewer {
             /**
                 * Babylon's environment helper of this viewer
                 */
-            environmentHelper: BABYLON.EnvironmentHelper;
+            environmentHelper?: BABYLON.EnvironmentHelper;
             protected _defaultHighpTextureType: number;
             protected _shadowGeneratorBias: number;
             protected _defaultPipelineTextureType: number;

Разница между файлами не показана из-за своего большого размера
+ 44 - 44
dist/preview release/viewer/babylon.viewer.js


Разница между файлами не показана из-за своего большого размера
+ 437 - 361
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -1286,7 +1286,7 @@ declare module 'babylonjs-viewer/managers/sceneManager' {
             /**
                 * Babylon's environment helper of this viewer
                 */
-            environmentHelper: EnvironmentHelper;
+            environmentHelper?: EnvironmentHelper;
             protected _defaultHighpTextureType: number;
             protected _shadowGeneratorBias: number;
             protected _defaultPipelineTextureType: number;

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

@@ -27,18 +27,20 @@
 - Get a root mesh from an asset container, load a mesh from a file with a single string url ([TrevorDev](https://github.com/TrevorDev))
 - UtilityLayer class to render another scene as a layer on top of an existing scene ([TrevorDev](https://github.com/TrevorDev))
 - AnimationGroup has now onAnimationGroupEnd observable ([RaananW](https://github.com/RaananW))
-- Pointer drag behavior to enable drag and drop with mouse or 6dof controller on a mesh ([TrevorDev](https://github.com/TrevorDev))
+- PointerDragBehavior, SixDofDragBehavior and MultiPointerScaleBehavior to enable drag and drop/scaling with mouse or 6dof controller on a mesh ([TrevorDev](https://github.com/TrevorDev))
 - Gizmo and GizmoManager classes used to manipulate meshes in a scene. Position, rotation, scale, and bounding box gizmos ([TrevorDev](https://github.com/TrevorDev))
 - Added a new `mesh.ignoreNonUniformScaling` to turn off non uniform scaling compensation ([Deltakosh](https://github.com/deltakosh))
 - AssetsManager tasks will only run when their state is INIT. It is now possible to remove a task from the assets manager ([RaananW](https://github.com/RaananW))
-- Sprite isVisible field ([TrevorDev](https://github.com/TrevorDev))
+- Added sprite isVisible field ([TrevorDev](https://github.com/TrevorDev))
 - Added support for `minScaleX`, `minScaleY`, `maxScaleX`, `maxScaleY` for particles ([Deltakosh](https://github.com/deltakosh))
+- Added support for `radiusRange` for sphere particle emitter ([Deltakosh](https://github.com/deltakosh))
 
 ### glTF Loader
 
 - Added support for KHR_texture_transform ([bghgary](http://www.github.com/bghgary))
 - Added `onNodeLODsLoadedObservable` and `onMaterialLODsLoadedObservable` to MSFT_lod loader extension ([bghgary](http://www.github.com/bghgary))
 - Added glTF loader settings to the GLTF tab in the debug layer ([bghgary](http://www.github.com/bghgary))
+- Added debug logging and performance counters ([bghgary](http://www.github.com/bghgary))
 
 ### Viewer
 
@@ -83,6 +85,12 @@
 - It wasn't possible to disable camera behavior(s) using configuration  [#4348](https://github.com/BabylonJS/Babylon.js/issues/4348) ([RaananW](https://github.com/RaananW))
 - Animation blending was always set to true, ignoring configuration [#4412](https://github.com/BabylonJS/Babylon.js/issues/4412) ([RaananW](https://github.com/RaananW))
 - Animation navbar now updates correctly when a new model is loaded [#4441](https://github.com/BabylonJS/Babylon.js/issues/4441) ([RaananW](https://github.com/RaananW))
+- Non-normalized meshes didn't center and focus correctly ([RaananW](https://github.com/RaananW))
+- Meshes with skeletons could have incorrect animations ([RaananW](https://github.com/RaananW))
+
+### Loaders
+
+- STL Loader only supported binary downloads and no data: urls [#4473](https://github.com/BabylonJS/Babylon.js/issues/4473) ([RaananW](https://github.com/RaananW))
 
 ## Breaking changes
 

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

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

+ 117 - 0
gui/src/3D/controls/scatterPanel.ts

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

+ 20 - 10
gui/src/3D/controls/volumeBasedPanel.ts

@@ -11,6 +11,9 @@ module BABYLON.GUI {
         
         private _orientation = Container3D.FACEORIGIN_ORIENTATION;
 
+        protected _cellWidth: number;
+        protected _cellHeight: number;
+
         /**
          * Gets or sets the distance between elements
          */
@@ -92,8 +95,8 @@ module BABYLON.GUI {
         }        
 
         protected _arrangeChildren() {
-            let cellWidth = 0;
-            let cellHeight = 0;
+            this._cellWidth = 0;
+            this._cellHeight = 0;
             let rows = 0;
             let columns = 0;
             let controlCount = 0;
@@ -113,12 +116,12 @@ module BABYLON.GUI {
                 let boundingBox = child.mesh.getBoundingInfo().boundingBox;
                 let extendSize = Vector3.TransformNormal(boundingBox.extendSize, Tmp.Matrix[0]);
 
-                cellWidth = Math.max(cellWidth, extendSize.x * 2);
-                cellHeight = Math.max(cellHeight, extendSize.y * 2);
+                this._cellWidth = Math.max(this._cellWidth, extendSize.x * 2);
+                this._cellHeight = Math.max(this._cellHeight, extendSize.y * 2);
             }
 
-            cellWidth += this.margin * 2;
-            cellHeight += this.margin * 2;
+            this._cellWidth += this.margin * 2;
+            this._cellHeight += this.margin * 2;
 
             // Arrange
             if (this._rowThenColum) {
@@ -129,8 +132,8 @@ module BABYLON.GUI {
                 columns = Math.ceil(controlCount / this._rows);
             }
 
-            let startOffsetX = (columns * 0.5) * cellWidth;
-            let startOffsetY = (rows * 0.5) * cellHeight;
+            let startOffsetX = (columns * 0.5) * this._cellWidth;
+            let startOffsetY = (rows * 0.5) * this._cellHeight;
             let nodeGrid = [];
             let cellCounter = 0;
 
@@ -139,7 +142,7 @@ module BABYLON.GUI {
                 {
                     for (var c = 0; c < columns; c++)
                     {
-                        nodeGrid.push(new Vector3((c * cellWidth) - startOffsetX + cellWidth / 2, (r * cellHeight) - startOffsetY + cellHeight / 2, 0));
+                        nodeGrid.push(new Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
                         cellCounter++;
                         if (cellCounter > controlCount)
                         {
@@ -152,7 +155,7 @@ module BABYLON.GUI {
                 {
                     for (var r = 0; r < rows; r++)
                     {
-                        nodeGrid.push(new Vector3((c * cellWidth) - startOffsetX + cellWidth / 2, (r * cellHeight) - startOffsetY + cellHeight / 2, 0));
+                        nodeGrid.push(new Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
                         cellCounter++;
                         if (cellCounter > controlCount)
                         {
@@ -172,9 +175,16 @@ module BABYLON.GUI {
 
                 cellCounter++;
             }
+
+            this._finalProcessing();
         }
 
         /** Child classes must implement this function to provide correct control positioning */
         protected abstract _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+
+        /** Child classes can implement this function to provide additional processing */
+        protected _finalProcessing() {
+
+        }
     }
 }

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

@@ -53,6 +53,9 @@ module BABYLON.GUI {
 
             this._utilityLayer = new UtilityLayerRenderer(this._scene);
             this._utilityLayer.onlyCheckPointerDownEvents = false;
+            this._utilityLayer.mainSceneTrackerPredicate = (mesh: Nullable<AbstractMesh>) => {
+                return mesh && mesh.metadata && mesh.metadata._node;
+            }
 
             // Root
             this._rootContainer = new Container3D("RootContainer");

+ 1 - 1
inspector/src/Inspector.ts

@@ -44,7 +44,7 @@ module INSPECTOR {
                     //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
                     loadGUIProperties();
                 }, () => {
-                    console.warn("Please add script https://preview.babylonjs.com/gui/babylon.gui.js to the HTML file")
+                    console.warn('Error : loading "babylon.gui.js". Please add script https://preview.babylonjs.com/gui/babylon.gui.js to the HTML file.');
                 });
             }
             else {

+ 5 - 5
inspector/src/details/Property.ts

@@ -12,7 +12,7 @@ module INSPECTOR {
         /** The obj parent  */
         private _parentObj: any;
 
-        constructor(prop: string, obj: any, parentObj?: PropertyLine) {
+        constructor(prop: string, obj: any, parentObj?: any) {
             this._property = prop;
             this._obj = obj;
             this._parentObj = parentObj || null;
@@ -28,7 +28,7 @@ module INSPECTOR {
         public set value(newValue: any) {
             if (newValue != undefined && this._obj[this._property] != undefined) {
                 if (this._obj instanceof BABYLON.Scene) {
-                    (<BABYLON.Scene>this._obj).debugLayer.onGlobalPropertyChangeCallback({
+                    (<BABYLON.Scene>this._obj).debugLayer.onPropertyChangedObservable.notifyObservers({
                         object: this._obj,
                         property: this._property,
                         value: newValue,
@@ -40,7 +40,7 @@ module INSPECTOR {
                         // Object that have "children" properties : Color, Vector, imageProcessingConfiguration
 
                         if (this._parentObj instanceof BABYLON.Scene) {
-                            (<BABYLON.Scene>this._parentObj).debugLayer.onGlobalPropertyChangeCallback({
+                            (<BABYLON.Scene>this._parentObj).debugLayer.onPropertyChangedObservable.notifyObservers({
                                 object: this._parentObj,
                                 property: this._property,
                                 value: newValue,
@@ -48,7 +48,7 @@ module INSPECTOR {
                             });
                         }
                         else {
-                            this._parentObj.getScene().debugLayer.onGlobalPropertyChangeCallback({
+                            this._parentObj.getScene().debugLayer.onPropertyChangedObservable.notifyObservers({
                                 object: this._parentObj,
                                 property: this._property,
                                 value: newValue,
@@ -57,7 +57,7 @@ module INSPECTOR {
                         }
                     }
                     else {
-                        this._obj.getScene().debugLayer.onGlobalPropertyChangeCallback({
+                        this._obj.getScene().debugLayer.onPropertyChangedObservable.notifyObservers({
                             object: this._obj,
                             property: this._property,
                             value: newValue,

+ 0 - 2
inspector/src/details/PropertyLine.ts

@@ -293,10 +293,8 @@ module INSPECTOR {
          * Dispose all viewer element (color, texture...)
          */
         public dispose() {
-            // console.log('delete properties', this.name);
             Scheduler.getInstance().remove(this);
             for (let child of this._children) {
-                // console.log('delete properties', child.name);
                 Scheduler.getInstance().remove(child);
             }
             for (let elem of this._elements) {

+ 2 - 2
inspector/src/helpers/Helpers.ts

@@ -172,11 +172,11 @@ module INSPECTOR {
                         style.textContent = elem as string;
                     });
                 }, undefined, undefined, undefined, () => {
-                    console.log("erreur");
+                    console.log('Error : LoadFile "glsl.min.js"');
                 });
 
             }, undefined, undefined, undefined, () => {
-                console.log("erreur");
+                console.log('Error : LoadFile "highlight.min.js"')
             });
 
         }

+ 2 - 2
inspector/src/tabs/ConsoleTab.ts

@@ -92,10 +92,10 @@ module INSPECTOR {
 
         private _message(type:string, message:any, caller:string) {
             let callerLine = Helpers.CreateDiv('caller', this._consolePanelContent);
-            callerLine.textContent = caller;
+            callerLine.textContent = caller.replace(' ', '\u00A0');
 
             let line = Helpers.CreateDiv(type, this._consolePanelContent); 
-            line.textContent += message ; 
+            line.textContent = message.replace(' ', '\u00A0');
 
             this._consolePanelContent.scrollTop = this._consolePanelContent.scrollHeight; 
         }

+ 106 - 58
inspector/src/tabs/GLTFTab.ts

@@ -1,18 +1,23 @@
-/// <reference path="../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 /// <reference path="../../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts"/>
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts"/>
 
 declare function Split(elements: HTMLElement[], options: any): any;
 
 module INSPECTOR {
-    interface ILoaderExtensionSettings {
+    interface ILoaderDefaults {
         [extensionName: string]: {
-            [settingName: string]: any
+            [key: string]: any
+        },
+        extensions: {
+            [extensionName: string]: {
+                [key: string]: any
+            }
         }
-    };
+    }
 
     export class GLTFTab extends Tab {
-        private static _LoaderExtensionSettings: ILoaderExtensionSettings | null = null;
+        private static _LoaderDefaults: ILoaderDefaults | null = null;
 
         private _inspector: Inspector;
         private _actions: HTMLDivElement;
@@ -25,14 +30,20 @@ module INSPECTOR {
 
         /** @hidden */
         public static _Initialize(): void {
-            // Must register with OnPluginActivatedObservable as early as possible to
-            // override the default settings for each extension.
+            // Must register with OnPluginActivatedObservable as early as possible to override the loader defaults.
             BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
-                if (loader.name === "gltf" && GLTFTab._LoaderExtensionSettings) {
+                if (loader.name === "gltf" && GLTFTab._LoaderDefaults) {
+                    const defaults = GLTFTab._LoaderDefaults;
+                    for (const key in defaults) {
+                        if (key !== "extensions") {
+                            (loader as any)[key] = GLTFTab._LoaderDefaults[key];
+                        }
+                    }
+
                     loader.onExtensionLoadedObservable.add(extension => {
-                        const settings = GLTFTab._LoaderExtensionSettings![extension.name];
-                        for (const settingName in settings) {
-                            (extension as any)[settingName] = settings[settingName];
+                        const extensionDefaults = defaults.extensions[extension.name];
+                        for (const key in extensionDefaults) {
+                            (extension as any)[key] = extensionDefaults[key];
                         }
                     });
                 }
@@ -65,36 +76,44 @@ module INSPECTOR {
         }
 
         private _addImport() {
-            const importActions = Helpers.CreateDiv(null, this._actions) as HTMLDivElement;
+            const importTitle = Helpers.CreateDiv('gltf-title', this._actions);
+            importTitle.textContent = 'Import';
+
+            const importActions = Helpers.CreateDiv('gltf-actions', this._actions) as HTMLDivElement;
 
-            this._getLoaderExtensionOverridesAsync().then(loaderExtensionSettings => {
-                const title = Helpers.CreateDiv('gltf-title', importActions);
-                title.textContent = 'Import';
+            this._getLoaderDefaultsAsync().then(defaults => {
+                importTitle.addEventListener('click', event => {
+                    this._showLoaderDefaults(defaults);
+                    event.stopPropagation();
+                });
 
-                const extensionActions = Helpers.CreateDiv('gltf-actions', importActions) as HTMLDivElement;
+                importActions.addEventListener('click', event => {
+                    this._showLoaderDefaults(defaults);
+                    event.stopPropagation();
+                });
 
-                const extensionsTitle = Helpers.CreateDiv('gltf-title', extensionActions) as HTMLDivElement;
+                const extensionsTitle = Helpers.CreateDiv('gltf-title', importActions) as HTMLDivElement;
                 extensionsTitle.textContent = "Extensions";
 
-                for (const extensionName in loaderExtensionSettings) {
-                    const settings = loaderExtensionSettings[extensionName];
+                for (const extensionName in defaults.extensions) {
+                    const extensionDefaults = defaults.extensions[extensionName];
 
-                    const extensionAction = Helpers.CreateDiv('gltf-action', extensionActions);
+                    const extensionAction = Helpers.CreateDiv('gltf-action', importActions);
                     extensionAction.addEventListener('click', event => {
-                        if (this._updateLoaderExtensionDetails(settings)) {
+                        if (this._showLoaderExtensionDefaults(extensionDefaults)) {
                             event.stopPropagation();
                         }
                     });
 
                     const checkbox = Helpers.CreateElement('span', 'gltf-checkbox', extensionAction);
 
-                    if (settings.enabled) {
+                    if (extensionDefaults.enabled) {
                         checkbox.classList.add('action', 'active');
                     }
 
                     checkbox.addEventListener('click', () => {
                         checkbox.classList.toggle('active');
-                        settings.enabled = checkbox.classList.contains('active');
+                        extensionDefaults.enabled = checkbox.classList.contains('active');
                     });
 
                     const label = Helpers.CreateElement('span', null, extensionAction);
@@ -103,43 +122,53 @@ module INSPECTOR {
             });
         }
 
-        private _getLoaderExtensionOverridesAsync(): Promise<ILoaderExtensionSettings> {
-            if (GLTFTab._LoaderExtensionSettings) {
-                return Promise.resolve(GLTFTab._LoaderExtensionSettings);
+        private static _EnumeratePublic(obj: any, callback: (key: string, value: any) => void): void {
+            for (const key in obj) {
+                if (key !== "name" && key[0] !== '_') {
+                    const value = obj[key];
+                    const type = typeof value;
+                    if (type !== "object" && type !== "function" && type !== "undefined") {
+                        callback(key, value);
+                    }
+                }
             }
+        }
 
-            const loaderExtensionSettings: ILoaderExtensionSettings = {};
+        private _getLoaderDefaultsAsync(): Promise<ILoaderDefaults> {
+            if (GLTFTab._LoaderDefaults) {
+                return Promise.resolve(GLTFTab._LoaderDefaults);
+            }
+
+            const defaults: ILoaderDefaults = {
+                extensions: {}
+            };
 
             const engine = new BABYLON.NullEngine();
             const scene = new BABYLON.Scene(engine);
-            const loader = new BABYLON.GLTF2.GLTFLoader();
+
+            const loader = new BABYLON.GLTFFileLoader();
+            GLTFTab._EnumeratePublic(loader, (key, value) => {
+                defaults[key] = value;
+            });
+
             loader.onExtensionLoadedObservable.add(extension => {
-                loaderExtensionSettings[extension.name] = {};
-                const settings = loaderExtensionSettings[extension.name];
-                for (const key of Object.keys(extension)) {
-                    if (key !== "name" && key[0] !== '_') {
-                        const value = (extension as any)[key];
-                        if (typeof value !== "object") {
-                            settings[key] = value;
-                        }
-                    }
-                }
+                const extensionDefaults: any = {};
+                GLTFTab._EnumeratePublic(extension, (key, value) => {
+                    extensionDefaults[key] = value;
+                });
+                defaults.extensions[extension.name] = extensionDefaults;
             });
 
-            const data = { json: {}, bin: null };
+            const data = '{ "asset": { "version": "2.0" } }';
             return loader.importMeshAsync([], scene, data, "").then(() => {
                 scene.dispose();
                 engine.dispose();
 
-                return (GLTFTab._LoaderExtensionSettings = loaderExtensionSettings);
+                return (GLTFTab._LoaderDefaults = defaults);
             });
         }
 
-        private _updateLoaderExtensionDetails(settings: { [settingName: string]: any }): boolean {
-            if (Object.keys(settings).length === 1) {
-                return false;
-            }
-
+        private _openDetailsPanel(): DetailPanel {
             if (!this._detailsPanel) {
                 this._detailsPanel = new DetailPanel();
                 this._panel.appendChild(this._detailsPanel.toHtml());
@@ -152,16 +181,7 @@ module INSPECTOR {
             }
 
             this._detailsPanel.clean();
-
-            const details = new Array<PropertyLine>();
-            for (const key in settings) {
-                if (key !== "enabled") {
-                    details.push(new PropertyLine(new Property(key, settings)));
-                }
-            }
-            this._detailsPanel.details = details;
-
-            return true;
+            return this._detailsPanel;
         }
 
         private _closeDetailsPanel(): void {
@@ -177,11 +197,39 @@ module INSPECTOR {
             }
         }
 
+        private _showLoaderDefaults(defaults: { [key: string]: any }): void {
+            var detailsPanel = this._openDetailsPanel();
+            const details = new Array<PropertyLine>();
+            for (const key in defaults) {
+                if (key !== "extensions") {
+                    details.push(new PropertyLine(new Property(key, defaults, this._inspector.scene)));
+                }
+            }
+            detailsPanel.details = details;
+        }
+
+        private _showLoaderExtensionDefaults(defaults: { [key: string]: any }): boolean {
+            if (Object.keys(defaults).length === 1) {
+                return false;
+            }
+
+            var detailsPanel = this._openDetailsPanel();
+            const details = new Array<PropertyLine>();
+            for (const key in defaults) {
+                if (key !== "enabled") {
+                    details.push(new PropertyLine(new Property(key, defaults, this._inspector.scene)));
+                }
+            }
+            detailsPanel.details = details;
+
+            return true;
+        }
+
         private _addExport() {
-            const exportActions = Helpers.CreateDiv(null, this._actions) as HTMLDivElement;
+            const exportTitle = Helpers.CreateDiv('gltf-title', this._actions);
+            exportTitle.textContent = 'Export';
 
-            const title = Helpers.CreateDiv('gltf-title', exportActions);
-            title.textContent = 'Export';
+            const exportActions = Helpers.CreateDiv('gltf-actions', this._actions) as HTMLDivElement;
 
             const name = Helpers.CreateInput('gltf-input', exportActions);
             name.placeholder = "File name...";

+ 1 - 1
inspector/test/index.js

@@ -85,7 +85,7 @@ var Test = (function () {
         scene.createDefaultCameraOrLight(true);
         scene.activeCamera.attachControl(canvas);
         scene.debugLayer.show();
-        scene.debugLayer.onGlobalPropertyChange.push((result) => {
+        scene.debugLayer.onPropertyChangedObservable.add((result) => {
             console.log(result.object);
             console.log("Property : " + result.property);
             console.log("New value : " + result.value);

+ 31 - 26
loaders/src/STL/babylon.stlFileLoader.ts

@@ -15,31 +15,36 @@ module BABYLON {
         // force data to come in as an ArrayBuffer
         // we'll convert to string if it looks like it's an ASCII .stl
         public extensions: ISceneLoaderPluginExtensions = {
-            ".stl": {isBinary: true},
+            ".stl": { isBinary: true },
         };
 
         public importMesh(meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: Nullable<AbstractMesh[]>, particleSystems: Nullable<ParticleSystem[]>, skeletons: Nullable<Skeleton[]>): boolean {
             var matches;
 
-            if (this.isBinary(data)) {
-                // binary .stl
-                var babylonMesh = new Mesh("stlmesh", scene);
-                this.parseBinary(babylonMesh, data);
-                if (meshes) {
-                    meshes.push(babylonMesh);
+            if (typeof data !== "string") {
+
+                if (this.isBinary(data)) {
+                    // binary .stl
+                    var babylonMesh = new Mesh("stlmesh", scene);
+                    this.parseBinary(babylonMesh, data);
+                    if (meshes) {
+                        meshes.push(babylonMesh);
+                    }
+                    return true;
                 }
-                return true;
-            }
 
-            // ASCII .stl
+                // ASCII .stl
 
-            // convert to string
-            var array_buffer = new Uint8Array(data);
-            var str = '';
-            for (var i = 0; i < data.byteLength; i++) {
-                str += String.fromCharCode( array_buffer[ i ] ); // implicitly assumes little-endian
+                // convert to string
+                var array_buffer = new Uint8Array(data);
+                var str = '';
+                for (var i = 0; i < data.byteLength; i++) {
+                    str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian
+                }
+                data = str;
             }
-            data = str;
+
+            //if arrived here, data is a string, containing the STLA data.
 
             while (matches = this.solidPattern.exec(data)) {
                 var meshName = matches[1];
@@ -93,13 +98,13 @@ module BABYLON {
             return container;
         }
 
-        private isBinary (data: any) {
+        private isBinary(data: any) {
 
             // check if file size is correct for binary stl
             var faceSize, nFaces, reader;
             reader = new DataView(data);
             faceSize = (32 / 8 * 3) + ((32 / 8 * 3) * 3) + (16 / 8);
-            nFaces = reader.getUint32( 80, true );
+            nFaces = reader.getUint32(80, true);
 
             if (80 + (32 / 8) + (nFaces * faceSize) === reader.byteLength) {
                 return true;
@@ -107,8 +112,8 @@ module BABYLON {
 
             // check characters higher than ASCII to confirm binary
             var fileLength = reader.byteLength;
-            for (var index=0; index < fileLength; index++) {
-                if (reader.getUint8( index ) > 127) {
+            for (var index = 0; index < fileLength; index++) {
+                if (reader.getUint8(index) > 127) {
                     return true;
                 }
             }
@@ -134,9 +139,9 @@ module BABYLON {
             for (var face = 0; face < faces; face++) {
 
                 var start = dataOffset + face * faceLength;
-                var normalX = reader.getFloat32( start, true );
-                var normalY = reader.getFloat32( start + 4, true );
-                var normalZ = reader.getFloat32( start + 8, true );
+                var normalX = reader.getFloat32(start, true);
+                var normalY = reader.getFloat32(start + 4, true);
+                var normalZ = reader.getFloat32(start + 8, true);
 
 
                 for (var i = 1; i <= 3; i++) {
@@ -144,9 +149,9 @@ module BABYLON {
                     var vertexstart = start + i * 12;
 
                     // ordering is intentional to match ascii import
-                    positions[offset] = reader.getFloat32( vertexstart, true );
-                    positions[offset + 2] = reader.getFloat32( vertexstart + 4, true );
-                    positions[offset + 1] = reader.getFloat32( vertexstart + 8, true );
+                    positions[offset] = reader.getFloat32(vertexstart, true);
+                    positions[offset + 2] = reader.getFloat32(vertexstart + 4, true);
+                    positions[offset + 1] = reader.getFloat32(vertexstart + 8, true);
 
                     normals[offset] = normalX;
                     normals[offset + 2] = normalY;

+ 3 - 20
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1562,28 +1562,11 @@ module BABYLON.GLTF1 {
             GLTFLoader.Extensions[extension.name] = extension;
         }
 
-        // #region Stubs for IGLTFLoader interface
-        public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
-        public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
-        public compileMaterials = false;
-        public useClipPlane = false;
-        public compileShadowGenerators = false;
-        public transparencyAsCoverage = false;
-        public _normalizeAnimationGroupsToBeginAtZero = true;
-        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
-
-        public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
-        public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
-        public readonly onMaterialLoadedObservable = new Observable<Material>();
-        public readonly onCameraLoadedObservable = new Observable<Camera>();
-        public readonly onCompleteObservable = new Observable<IGLTFLoader>();
-        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
-        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
-
         public state: Nullable<GLTFLoaderState> = null;
 
-        public dispose(): void {}
-        // #endregion
+        public dispose(): void {
+            // do nothing
+        }
 
         private _importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], skeletons: Skeleton[]) => void, onProgress?: (event: SceneLoaderProgressEvent) => void, onError?: (message: string) => void): boolean {
             scene.useRightHandedSystem = true;

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

@@ -30,7 +30,7 @@ module BABYLON.GLTF2.Extensions {
                     promises.push(this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                     promises.push(this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));
 
-                    this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+                    this._loader._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
 
                     babylonData = {
                         material: babylonMaterial,

+ 1 - 1
loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts

@@ -20,7 +20,7 @@ module BABYLON.GLTF2.Extensions {
 
                     const promise = this._loadUnlitPropertiesAsync(context, material, babylonMaterial);
 
-                    this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+                    this._loader._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
 
                     babylonData = {
                         material: babylonMaterial,

+ 68 - 57
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -32,28 +32,52 @@ module BABYLON.GLTF2.Extensions {
          */
         public onMaterialLODsLoadedObservable = new Observable<number>();
 
-        private _loadingNodeLOD: Nullable<_ILoaderNode> = null;
-        private _loadNodeSignals: { [nodeIndex: number]: Deferred<void> } = {};
-        private _loadNodePromises = new Array<Array<Promise<void>>>();
+        private _nodeIndexLOD: Nullable<number> = null;
+        private _nodeSignalLODs = new Array<Deferred<void>>();
+        private _nodePromiseLODs = new Array<Array<Promise<void>>>();
 
-        private _loadingMaterialLOD: Nullable<_ILoaderMaterial> = null;
-        private _loadMaterialSignals: { [materialIndex: number]: Deferred<void> } = {};
-        private _loadMaterialPromises = new Array<Array<Promise<void>>>();
+        private _materialIndexLOD: Nullable<number> = null;
+        private _materialSignalLODs = new Array<Deferred<void>>();
+        private _materialPromiseLODs = new Array<Array<Promise<void>>>();
 
         constructor(loader: GLTFLoader) {
             super(loader);
 
-            this._loader._onReadyObservable.addOnce(() => {
-                for (let indexLOD = 0; indexLOD < this._loadNodePromises.length; indexLOD++) {
-                    Promise.all(this._loadNodePromises[indexLOD]).then(() => {
+            this._loader._readyPromise.then(() => {
+                for (let indexLOD = 0; indexLOD < this._nodePromiseLODs.length; indexLOD++) {
+                    const promise = Promise.all(this._nodePromiseLODs[indexLOD]).then(() => {
+                        if (indexLOD !== 0) {
+                            this._loader._parent._endPerformanceCounter(`Node LOD ${indexLOD}`);
+                        }
+
+                        this._loader._parent._log(`Loaded node LOD ${indexLOD}`);
                         this.onNodeLODsLoadedObservable.notifyObservers(indexLOD);
+
+                        if (indexLOD !== this._nodePromiseLODs.length - 1) {
+                            this._loader._parent._startPerformanceCounter(`Node LOD ${indexLOD + 1}`);
+                            this._nodeSignalLODs[indexLOD].resolve();
+                        }
                     });
+
+                    this._loader._completePromises.push(promise);
                 }
 
-                for (let indexLOD = 0; indexLOD < this._loadMaterialPromises.length; indexLOD++) {
-                    Promise.all(this._loadMaterialPromises[indexLOD]).then(() => {
+                for (let indexLOD = 0; indexLOD < this._materialPromiseLODs.length; indexLOD++) {
+                    const promise = Promise.all(this._materialPromiseLODs[indexLOD]).then(() => {
+                        if (indexLOD !== 0) {
+                            this._loader._parent._endPerformanceCounter(`Material LOD ${indexLOD}`);
+                        }
+
+                        this._loader._parent._log(`Loaded material LOD ${indexLOD}`);
                         this.onMaterialLODsLoadedObservable.notifyObservers(indexLOD);
+
+                        if (indexLOD !== this._materialPromiseLODs.length - 1) {
+                            this._loader._parent._startPerformanceCounter(`Material LOD ${indexLOD + 1}`);
+                            this._materialSignalLODs[indexLOD].resolve();
+                        }
                     });
+
+                    this._loader._completePromises.push(promise);
                 }
             });
         }
@@ -61,10 +85,13 @@ module BABYLON.GLTF2.Extensions {
         public dispose() {
             super.dispose();
 
-            this._loadingNodeLOD = null;
-            this._loadNodeSignals = {};
-            this._loadingMaterialLOD = null;
-            this._loadMaterialSignals = {};
+            this._nodeIndexLOD = null;
+            this._nodeSignalLODs.length = 0;
+            this._nodePromiseLODs.length = 0;
+
+            this._materialIndexLOD = null;
+            this._materialSignalLODs.length = 0;
+            this._materialPromiseLODs.length = 0;
 
             this.onMaterialLODsLoadedObservable.clear();
             this.onNodeLODsLoadedObservable.clear();
@@ -75,15 +102,14 @@ module BABYLON.GLTF2.Extensions {
                 let firstPromise: Promise<void>;
 
                 const nodeLODs = this._getLODs(extensionContext, node, this._loader._gltf.nodes, extension.ids);
+                this._loader._parent._logOpen(`${extensionContext}`);
+
                 for (let indexLOD = 0; indexLOD < nodeLODs.length; indexLOD++) {
                     const nodeLOD = nodeLODs[indexLOD];
 
                     if (indexLOD !== 0) {
-                        this._loadingNodeLOD = nodeLOD;
-
-                        if (!this._loadNodeSignals[nodeLOD._index]) {
-                            this._loadNodeSignals[nodeLOD._index] = new Deferred<void>();
-                        }
+                        this._nodeIndexLOD = indexLOD;
+                        this._nodeSignalLODs[indexLOD] = this._nodeSignalLODs[indexLOD] || new Deferred();
                     }
 
                     const promise = this._loader._loadNodeAsync(`#/nodes/${nodeLOD._index}`, nodeLOD).then(() => {
@@ -94,36 +120,27 @@ module BABYLON.GLTF2.Extensions {
                                 delete previousNodeLOD._babylonMesh;
                             }
                         }
-
-                        if (indexLOD !== nodeLODs.length - 1) {
-                            const nodeIndex = nodeLODs[indexLOD + 1]._index;
-
-                            if (this._loadNodeSignals[nodeIndex]) {
-                                this._loadNodeSignals[nodeIndex].resolve();
-                                delete this._loadNodeSignals[nodeIndex];
-                            }
-                        }
                     });
 
                     if (indexLOD === 0) {
                         firstPromise = promise;
                     }
                     else {
-                        this._loader._completePromises.push(promise);
-                        this._loadingNodeLOD = null;
+                        this._nodeIndexLOD = null;
                     }
 
-                    this._loadNodePromises[indexLOD] = this._loadNodePromises[indexLOD] || [];
-                    this._loadNodePromises[indexLOD].push(promise);
+                    this._nodePromiseLODs[indexLOD] = this._nodePromiseLODs[indexLOD] || [];
+                    this._nodePromiseLODs[indexLOD].push(promise);
                 }
 
+                this._loader._parent._logClose();
                 return firstPromise!;
             });
         }
 
         protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             // Don't load material LODs if already loading a node LOD.
-            if (this._loadingNodeLOD) {
+            if (this._nodeIndexLOD) {
                 return null;
             }
 
@@ -131,15 +148,13 @@ module BABYLON.GLTF2.Extensions {
                 let firstPromise: Promise<void>;
 
                 const materialLODs = this._getLODs(extensionContext, material, this._loader._gltf.materials, extension.ids);
+                this._loader._parent._logOpen(`${extensionContext}`);
+
                 for (let indexLOD = 0; indexLOD < materialLODs.length; indexLOD++) {
                     const materialLOD = materialLODs[indexLOD];
 
                     if (indexLOD !== 0) {
-                        this._loadingMaterialLOD = materialLOD;
-
-                        if (!this._loadMaterialSignals[materialLOD._index]) {
-                            this._loadMaterialSignals[materialLOD._index] = new Deferred<void>();
-                        }
+                        this._materialIndexLOD = indexLOD;
                     }
 
                     const promise = this._loader._loadMaterialAsync(`#/materials/${materialLOD._index}`, materialLOD, mesh, babylonMesh, babylonDrawMode, indexLOD === 0 ? assign : () => {}).then(() => {
@@ -153,43 +168,39 @@ module BABYLON.GLTF2.Extensions {
                                 delete previousBabylonDataLOD[babylonDrawMode];
                             }
                         }
-
-                        if (indexLOD !== materialLODs.length - 1) {
-                            const materialIndex = materialLODs[indexLOD + 1]._index;
-                            if (this._loadMaterialSignals[materialIndex]) {
-                                this._loadMaterialSignals[materialIndex].resolve();
-                                delete this._loadMaterialSignals[materialIndex];
-                            }
-                        }
                     });
 
                     if (indexLOD === 0) {
                         firstPromise = promise;
                     }
                     else {
-                        this._loader._completePromises.push(promise);
-                        this._loadingMaterialLOD = null;
+                        this._materialIndexLOD = null;
                     }
 
-                    this._loadMaterialPromises[indexLOD] = this._loadMaterialPromises[indexLOD] || [];
-                    this._loadMaterialPromises[indexLOD].push(promise);
+                    this._materialPromiseLODs[indexLOD] = this._materialPromiseLODs[indexLOD] || [];
+                    this._materialPromiseLODs[indexLOD].push(promise);
                 }
 
+                this._loader._parent._logClose();
                 return firstPromise!;
             });
         }
 
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>> {
             // Defer the loading of uris if loading a material or node LOD.
-            if (this._loadingMaterialLOD) {
-                const index = this._loadingMaterialLOD._index;
-                return this._loadMaterialSignals[index].promise.then(() => {
+            if (this._materialIndexLOD !== null) {
+                this._loader._parent._log(`deferred`);
+                const previousIndexLOD = this._materialIndexLOD - 1;
+                this._materialSignalLODs[previousIndexLOD] = this._materialSignalLODs[previousIndexLOD] || new Deferred<void>();
+                return this._materialSignalLODs[previousIndexLOD].promise.then(() => {
                     return this._loader._loadUriAsync(context, uri);
                 });
             }
-            else if (this._loadingNodeLOD) {
-                const index = this._loadingNodeLOD._index;
-                return this._loadNodeSignals[index].promise.then(() => {
+            else if (this._nodeIndexLOD !== null) {
+                this._loader._parent._log(`deferred`);
+                const previousIndexLOD = this._nodeIndexLOD - 1;
+                this._nodeSignalLODs[previousIndexLOD] = this._nodeSignalLODs[previousIndexLOD] || new Deferred<void>();
+                return this._nodeSignalLODs[this._nodeIndexLOD - 1].promise.then(() => {
                     return this._loader._loadUriAsync(context, uri);
                 });
             }

+ 155 - 228
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -20,22 +20,14 @@ module BABYLON.GLTF2 {
         }
     }
 
-    /**
-     * Loader for loading a glTF 2.0 asset
-     */
+    /** @hidden */
     export class GLTFLoader implements IGLTFLoader {
-        /** @hidden */
+        public _parent: GLTFFileLoader;
         public _gltf: _ILoaderGLTF;
-
-        /** @hidden */
         public _babylonScene: Scene;
-
-        /** @hidden */
+        public _readyPromise: Promise<void>;
         public _completePromises = new Array<Promise<void>>();
 
-        /** @hidden */
-        public _onReadyObservable = new Observable<IGLTFLoader>();
-
         private _disposed = false;
         private _state: Nullable<GLTFLoaderState> = null;
         private _extensions: { [name: string]: GLTFLoaderExtension } = {};
@@ -49,7 +41,6 @@ module BABYLON.GLTF2 {
         private static _ExtensionNames = new Array<string>();
         private static _ExtensionFactories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
 
-        /** @hidden */
         public static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void {
             if (GLTFLoader._ExtensionFactories[name]) {
                 Tools.Error(`Extension with the name '${name}' already exists`);
@@ -63,93 +54,16 @@ module BABYLON.GLTF2 {
         }
 
         /**
-         * Mode that determines the coordinate system to use.
-         */
-        public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
-
-        /**
-         * Mode that determines what animations will start.
-         */
-        public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
-
-        /**
-         * Defines if the loader should compile materials.
-         */
-        public compileMaterials = false;
-
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        public useClipPlane = false;
-
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        public compileShadowGenerators = false;
-
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage. 
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        public transparencyAsCoverage = false;
-
-        /** @hidden */
-        public _normalizeAnimationGroupsToBeginAtZero = true;
-
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
-
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
-
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
-
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        public readonly onMaterialLoadedObservable = new Observable<Material>();
-
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        public readonly onCameraLoadedObservable = new Observable<Camera>();
-
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        public readonly onCompleteObservable = new Observable<IGLTFLoader>();
-
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
-
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
-
-        /**
          * Loader state or null if the loader is not active.
          */
         public get state(): Nullable<GLTFLoaderState> {
             return this._state;
         }
 
-        /**
-         * Disposes the loader, releases resources during load, and cancels any outstanding requests.
-         */
+        constructor(parent: GLTFFileLoader) {
+            this._parent = parent;
+        }
+
         public dispose(): void {
             if (this._disposed) {
                 return;
@@ -157,21 +71,29 @@ module BABYLON.GLTF2 {
 
             this._disposed = true;
 
-            this.onDisposeObservable.notifyObservers(this);
-            this.onDisposeObservable.clear();
+            for (const request of this._requests) {
+                request.abort();
+            }
+
+            this._requests.length = 0;
 
-            this._clear();
+            delete this._gltf;
+            delete this._babylonScene;
+            delete this._readyPromise;
+            this._completePromises.length = 0;
+
+            for (const name in this._extensions) {
+                this._extensions[name].dispose();
+            }
+
+            this._extensions = {};
+
+            delete this._rootBabylonMesh;
+            delete this._progressCallback;
+
+            this._parent._clear();
         }
 
-        /**
-         * Imports one or more meshes from the loaded glTF data and adds them to the scene
-         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-         * @param scene the scene the meshes should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise containg the loaded meshes, particles, skeletons and animations
-         */
         public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             return Promise.resolve().then(() => {
                 this._babylonScene = scene;
@@ -179,14 +101,14 @@ module BABYLON.GLTF2 {
                 this._progressCallback = onProgress;
                 this._loadData(data);
 
-                let nodes: Nullable<Array<_ILoaderNode>> = null;
+                let nodes: Nullable<Array<number>> = null;
 
                 if (meshesNames) {
-                    const nodeMap: { [name: string]: _ILoaderNode } = {};
+                    const nodeMap: { [name: string]: number } = {};
                     if (this._gltf.nodes) {
                         for (const node of this._gltf.nodes) {
                             if (node.name) {
-                                nodeMap[node.name] = node;
+                                nodeMap[node.name] = node._index;
                             }
                         }
                     }
@@ -194,7 +116,7 @@ module BABYLON.GLTF2 {
                     const names = (meshesNames instanceof Array) ? meshesNames : [meshesNames];
                     nodes = names.map(name => {
                         const node = nodeMap[name];
-                        if (!node) {
+                        if (node === undefined) {
                             throw new Error(`Failed to find node '${name}'`);
                         }
 
@@ -213,14 +135,6 @@ module BABYLON.GLTF2 {
             });
         }
 
-        /**
-         * Imports all objects from the loaded glTF data and adds them to the scene
-         * @param scene the scene the objects should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise which completes when objects have been loaded to the scene
-         */
         public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
             return Promise.resolve().then(() => {
                 this._babylonScene = scene;
@@ -231,9 +145,16 @@ module BABYLON.GLTF2 {
             });
         }
 
-        private _loadAsync(nodes: Nullable<Array<_ILoaderNode>>): Promise<void> {
+        private _loadAsync(nodes: Nullable<Array<number>>): Promise<void> {
             return Promise.resolve().then(() => {
+                this._parent._startPerformanceCounter("Loading => Ready");
+                this._parent._startPerformanceCounter("Loading => Complete");
+
                 this._state = GLTFLoaderState.LOADING;
+                this._parent._log("Loading");
+
+                const readyDeferred = new Deferred<void>();
+                this._readyPromise = readyDeferred.promise;
 
                 this._loadExtensions();
                 this._checkExtensions();
@@ -241,28 +162,33 @@ module BABYLON.GLTF2 {
                 const promises = new Array<Promise<void>>();
 
                 if (nodes) {
-                    promises.push(this._loadNodesAsync(nodes));
+                    promises.push(this._loadSceneAsync("#/nodes", { nodes: nodes, _index: -1 }));
                 }
                 else {
                     const scene = GLTFLoader._GetProperty(`#/scene`, this._gltf.scenes, this._gltf.scene || 0);
                     promises.push(this._loadSceneAsync(`#/scenes/${scene._index}`, scene));
                 }
 
-                if (this.compileMaterials) {
+                if (this._parent.compileMaterials) {
                     promises.push(this._compileMaterialsAsync());
                 }
 
-                if (this.compileShadowGenerators) {
+                if (this._parent.compileShadowGenerators) {
                     promises.push(this._compileShadowGeneratorsAsync());
                 }
 
                 const resultPromise = Promise.all(promises).then(() => {
                     this._state = GLTFLoaderState.READY;
-                    this._onReadyObservable.notifyObservers(this);
+                    this._parent._log("Ready");
+
+                    readyDeferred.resolve();
+
                     this._startAnimations();
                 });
 
                 resultPromise.then(() => {
+                    this._parent._endPerformanceCounter("Loading => Ready");
+
                     if (this._rootBabylonMesh) {
                         this._rootBabylonMesh.setEnabled(true);
                     }
@@ -270,13 +196,17 @@ module BABYLON.GLTF2 {
                     Tools.SetImmediate(() => {
                         if (!this._disposed) {
                             Promise.all(this._completePromises).then(() => {
+                                this._parent._endPerformanceCounter("Loading => Complete");
+
                                 this._state = GLTFLoaderState.COMPLETE;
-                                this.onCompleteObservable.notifyObservers(this);
-                                this.onCompleteObservable.clear();
-                                this._clear();
+                                this._parent._log("Complete");
+
+                                this._parent.onCompleteObservable.notifyObservers(undefined);
+                                this._parent.onCompleteObservable.clear();
+                                this.dispose();
                             }).catch(error => {
                                 Tools.Error(`glTF Loader: ${error.message}`);
-                                this._clear();
+                                this.dispose();
                             });
                         }
                     });
@@ -286,7 +216,7 @@ module BABYLON.GLTF2 {
             }).catch(error => {
                 if (!this._disposed) {
                     Tools.Error(`glTF Loader: ${error.message}`);
-                    this._clear();
+                    this.dispose();
                     throw error;
                 }
             });
@@ -350,10 +280,10 @@ module BABYLON.GLTF2 {
                 const extension = GLTFLoader._ExtensionFactories[name](this);
                 this._extensions[name] = extension;
 
-                this.onExtensionLoadedObservable.notifyObservers(extension);
+                this._parent.onExtensionLoadedObservable.notifyObservers(extension);
             }
 
-            this.onExtensionLoadedObservable.clear();
+            this._parent.onExtensionLoadedObservable.clear();
         }
 
         private _checkExtensions(): void {
@@ -372,7 +302,7 @@ module BABYLON.GLTF2 {
             this._rootBabylonMesh.setEnabled(false);
 
             const rootNode = { _babylonMesh: this._rootBabylonMesh } as _ILoaderNode;
-            switch (this.coordinateSystemMode) {
+            switch (this._parent.coordinateSystemMode) {
                 case GLTFLoaderCoordinateSystemMode.AUTO: {
                     if (!this._babylonScene.useRightHandedSystem) {
                         rootNode.rotation = [0, 1, 0, 0];
@@ -386,27 +316,14 @@ module BABYLON.GLTF2 {
                     break;
                 }
                 default: {
-                    throw new Error(`Invalid coordinate system mode (${this.coordinateSystemMode})`);
+                    throw new Error(`Invalid coordinate system mode (${this._parent.coordinateSystemMode})`);
                 }
             }
 
-            this.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh);
+            this._parent.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh);
             return rootNode;
         }
 
-        private _loadNodesAsync(nodes: _ILoaderNode[]): Promise<void> {
-            const promises = new Array<Promise<void>>();
-
-            for (let node of nodes) {
-                promises.push(this._loadNodeAsync(`#/nodes/${node._index}`, node));
-            }
-
-            promises.push(this._loadAnimationsAsync());
-
-            return Promise.all(promises).then(() => {});
-        }
-
-        /** @hidden */
         public _loadSceneAsync(context: string, scene: _ILoaderScene): Promise<void> {
             const promise = GLTFLoaderExtension._LoadSceneAsync(this, context, scene);
             if (promise) {
@@ -415,13 +332,19 @@ module BABYLON.GLTF2 {
 
             const promises = new Array<Promise<void>>();
 
-            for (let index of scene.nodes) {
-                const node = GLTFLoader._GetProperty(`${context}/nodes/${index}`, this._gltf.nodes, index);
-                promises.push(this._loadNodeAsync(`#/nodes/${node._index}`, node));
+            this._parent._logOpen(`${context} ${scene.name || ""}`);
+
+            if (scene.nodes) {
+                for (let index of scene.nodes) {
+                    const node = GLTFLoader._GetProperty(`${context}/nodes/${index}`, this._gltf.nodes, index);
+                    promises.push(this._loadNodeAsync(`#/nodes/${node._index}`, node));
+                }
             }
 
             promises.push(this._loadAnimationsAsync());
 
+            this._parent._logClose();
+
             return Promise.all(promises).then(() => {});
         }
 
@@ -491,7 +414,7 @@ module BABYLON.GLTF2 {
         }
 
         private _startAnimations(): void {
-            switch (this.animationStartMode) {
+            switch (this._parent.animationStartMode) {
                 case GLTFLoaderAnimationStartMode.NONE: {
                     // do nothing
                     break;
@@ -511,13 +434,12 @@ module BABYLON.GLTF2 {
                     break;
                 }
                 default: {
-                    Tools.Error(`Invalid animation start mode (${this.animationStartMode})`);
+                    Tools.Error(`Invalid animation start mode (${this._parent.animationStartMode})`);
                     return;
                 }
             }
         }
 
-        /** @hidden */
         public _loadNodeAsync(context: string, node: _ILoaderNode): Promise<void> {
             const promise = GLTFLoaderExtension._LoadNodeAsync(this, context, node);
             if (promise) {
@@ -530,6 +452,8 @@ module BABYLON.GLTF2 {
 
             const promises = new Array<Promise<void>>();
 
+            this._parent._logOpen(`${context} ${node.name || ""}`);
+
             const babylonMesh = new Mesh(node.name || `node${node._index}`, this._babylonScene, node._parent ? node._parent._babylonMesh : null);
             node._babylonMesh = babylonMesh;
 
@@ -552,7 +476,9 @@ module BABYLON.GLTF2 {
                 }
             }
 
-            this.onMeshLoadedObservable.notifyObservers(babylonMesh);
+            this._parent.onMeshLoadedObservable.notifyObservers(babylonMesh);
+
+            this._parent._logClose();
 
             return Promise.all(promises).then(() => {});
         }
@@ -560,6 +486,8 @@ module BABYLON.GLTF2 {
         private _loadMeshAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, babylonMesh: Mesh): Promise<void> {
             const promises = new Array<Promise<void>>();
 
+            this._parent._logOpen(`${context} ${mesh.name || ""}`);
+
             const primitives = mesh.primitives;
             if (!primitives || primitives.length === 0) {
                 throw new Error(`${context}: Primitives are missing`);
@@ -576,7 +504,7 @@ module BABYLON.GLTF2 {
                     const primitiveBabylonMesh = new Mesh(`${mesh.name || babylonMesh.name}_${primitive._index}`, this._babylonScene, babylonMesh);
                     node._primitiveBabylonMeshes.push(primitiveBabylonMesh);
                     promises.push(this._loadPrimitiveAsync(`${context}/primitives/${primitive._index}`, node, mesh, primitive, primitiveBabylonMesh));
-                    this.onMeshLoadedObservable.notifyObservers(babylonMesh);
+                    this._parent.onMeshLoadedObservable.notifyObservers(babylonMesh);
                 }
             }
 
@@ -585,6 +513,8 @@ module BABYLON.GLTF2 {
                 promises.push(this._loadSkinAsync(`#/skins/${skin._index}`, node, mesh, skin));
             }
 
+            this._parent._logClose();
+
             return Promise.all(promises).then(() => {
                 this._forEachPrimitive(node, babylonMesh => {
                     babylonMesh._refreshBoundingInfo(true);
@@ -595,6 +525,8 @@ module BABYLON.GLTF2 {
         private _loadPrimitiveAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<void> {
             const promises = new Array<Promise<void>>();
 
+            this._parent._logOpen(`${context}`);
+
             this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
             promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then(babylonGeometry => {
                 return this._loadMorphTargetsAsync(context, primitive, babylonMesh, babylonGeometry).then(() => {
@@ -613,6 +545,8 @@ module BABYLON.GLTF2 {
                 }));
             }
 
+            this._parent._logClose();
+
             return Promise.all(promises).then(() => {});
         }
 
@@ -920,7 +854,7 @@ module BABYLON.GLTF2 {
                 }
             }
 
-            this.onCameraLoadedObservable.notifyObservers(babylonCamera);
+            this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
         }
 
         private _loadAnimationsAsync(): Promise<void> {
@@ -953,7 +887,7 @@ module BABYLON.GLTF2 {
             }
 
             return Promise.all(promises).then(() => {
-                babylonAnimationGroup.normalize(this._normalizeAnimationGroupsToBeginAtZero ? 0 : null);
+                babylonAnimationGroup.normalize(this._parent._normalizeAnimationGroupsToBeginAtZero ? 0 : null);
             });
         }
 
@@ -1161,7 +1095,6 @@ module BABYLON.GLTF2 {
             return buffer._data;
         }
 
-        /** @hidden */
         public _loadBufferViewAsync(context: string, bufferView: _ILoaderBufferView): Promise<ArrayBufferView> {
             if (bufferView._data) {
                 return bufferView._data;
@@ -1255,7 +1188,6 @@ module BABYLON.GLTF2 {
             return accessor._data as Promise<Float32Array>;
         }
 
-        /** @hidden */
         public _loadVertexBufferViewAsync(context: string, bufferView: _ILoaderBufferView, kind: string): Promise<Buffer> {
             if (bufferView._babylonBuffer) {
                 return bufferView._babylonBuffer;
@@ -1297,7 +1229,7 @@ module BABYLON.GLTF2 {
                 babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE;
                 babylonMaterial.metallic = 1;
                 babylonMaterial.roughness = 1;
-                this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+                this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
             }
 
             return babylonMaterial;
@@ -1345,7 +1277,6 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
         }
 
-        /** @hidden */
         public _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void> {
             const promise = GLTFLoaderExtension._LoadMaterialAsync(this, context, material, mesh, babylonMesh, babylonDrawMode, assign);
             if (promise) {
@@ -1357,13 +1288,15 @@ module BABYLON.GLTF2 {
             if (!babylonData) {
                 const promises = new Array<Promise<void>>();
 
+                this._parent._logOpen(`${context} ${material.name || ""}`);
+
                 const name = material.name || `material_${material._index}`;
                 const babylonMaterial = this._createMaterial(name, babylonDrawMode);
 
                 promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                 promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
 
-                this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+                this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
 
                 babylonData = {
                     material: babylonMaterial,
@@ -1372,6 +1305,8 @@ module BABYLON.GLTF2 {
                 };
 
                 material._babylonData[babylonDrawMode] = babylonData;
+
+                this._parent._logClose();
             }
 
             babylonData.meshes.push(babylonMesh);
@@ -1380,18 +1315,16 @@ module BABYLON.GLTF2 {
             return babylonData.loaded;
         }
 
-        /** @hidden */
         public _createMaterial(name: string, drawMode: number): PBRMaterial {
             const babylonMaterial = new PBRMaterial(name, this._babylonScene);
             babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
             babylonMaterial.fillMode = drawMode;
             babylonMaterial.enableSpecularAntiAliasing = true;
-            babylonMaterial.useRadianceOverAlpha = !this.transparencyAsCoverage;
-            babylonMaterial.useSpecularOverAlpha = !this.transparencyAsCoverage;
+            babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage;
+            babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage;
             return babylonMaterial;
         }
 
-        /** @hidden */
         public _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
             const promises = new Array<Promise<void>>();
 
@@ -1433,7 +1366,6 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
         }
 
-        /** @hidden */
         public _loadMaterialAlphaProperties(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): void {
             const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE;
             switch (alphaMode) {
@@ -1463,18 +1395,21 @@ module BABYLON.GLTF2 {
             }
         }
 
-        /** @hidden */
         public _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void> {
             const promise = GLTFLoaderExtension._LoadTextureAsync(this, context, textureInfo, assign);
             if (promise) {
                 return promise;
             }
 
+            this._parent._logOpen(`${context}`);
+
             const texture = GLTFLoader._GetProperty(`${context}/index`, this._gltf.textures, textureInfo.index);
             context = `#/textures/${textureInfo.index}`;
 
             const promises = new Array<Promise<void>>();
 
+            this._parent._logOpen(`${context} ${texture.name || ""}`);
+
             const sampler = (texture.sampler == undefined ? this._defaultSampler : GLTFLoader._GetProperty(`${context}/sampler`, this._gltf.samplers, texture.sampler));
             const samplerData = this._loadSampler(`#/samplers/${sampler._index}`, sampler);
 
@@ -1502,7 +1437,10 @@ module BABYLON.GLTF2 {
             }));
 
             assign(babylonTexture);
-            this.onTextureLoadedObservable.notifyObservers(babylonTexture);
+            this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
+
+            this._parent._logClose();
+            this._parent._logClose();
 
             return Promise.all(promises).then(() => {});
         }
@@ -1521,27 +1459,28 @@ module BABYLON.GLTF2 {
         }
 
         private _loadImageAsync(context: string, image: _ILoaderImage): Promise<Blob> {
-            if (image._blob) {
-                return image._blob;
-            }
+            if (!image._blob) {
+                this._parent._logOpen(`${context} ${image.name || ""}`);
 
-            let promise: Promise<ArrayBufferView>;
-            if (image.uri) {
-                promise = this._loadUriAsync(context, image.uri);
-            }
-            else {
-                const bufferView = GLTFLoader._GetProperty(`${context}/bufferView`, this._gltf.bufferViews, image.bufferView);
-                promise = this._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView);
-            }
+                let promise: Promise<ArrayBufferView>;
+                if (image.uri) {
+                    promise = this._loadUriAsync(context, image.uri);
+                }
+                else {
+                    const bufferView = GLTFLoader._GetProperty(`${context}/bufferView`, this._gltf.bufferViews, image.bufferView);
+                    promise = this._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView);
+                }
 
-            image._blob = promise.then(data => {
-                return new Blob([data], { type: image.mimeType });
-            });
+                image._blob = promise.then(data => {
+                    return new Blob([data], { type: image.mimeType });
+                });
+
+                this._parent._logClose();
+            }
 
             return image._blob;
         }
 
-        /** @hidden */
         public _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView> {
             const promise = GLTFLoaderExtension._LoadUriAsync(this, context, uri);
             if (promise) {
@@ -1553,28 +1492,37 @@ module BABYLON.GLTF2 {
             }
 
             if (Tools.IsBase64(uri)) {
-                return Promise.resolve(new Uint8Array(Tools.DecodeBase64(uri)));
+                const data = new Uint8Array(Tools.DecodeBase64(uri));
+                this._parent._log(`Decoded ${uri.substr(0, 64)}... (${data.length} bytes)`);
+                return Promise.resolve(data);
             }
 
-            return this.preprocessUrlAsync(this._rootUrl + uri).then(url => {
+            this._parent._log(`Loading ${uri}`);
+
+            return this._parent.preprocessUrlAsync(this._rootUrl + uri).then(url => {
                 return new Promise<ArrayBufferView>((resolve, reject) => {
                     if (!this._disposed) {
-                        const request = Tools.LoadFile(url, data => {
+                        const request = Tools.LoadFile(url, fileData => {
                             if (!this._disposed) {
-                                resolve(new Uint8Array(data as ArrayBuffer));
+                                const data = new Uint8Array(fileData as ArrayBuffer);
+                                this._parent._log(`Loaded ${uri} (${data.length} bytes)`);
+                                resolve(data);
                             }
                         }, event => {
                             if (!this._disposed) {
-                                try {
-                                    if (request && this._state === GLTFLoaderState.LOADING) {
-                                        request._lengthComputable = event.lengthComputable;
-                                        request._loaded = event.loaded;
-                                        request._total = event.total;
+                                if (request) {
+                                    request._lengthComputable = event.lengthComputable;
+                                    request._loaded = event.loaded;
+                                    request._total = event.total;
+                                }
+
+                                if (this._state === GLTFLoaderState.LOADING) {
+                                    try {
                                         this._onProgress();
                                     }
-                                }
-                                catch (e) {
-                                    reject(e);
+                                    catch (e) {
+                                        reject(e);
+                                    }
                                 }
                             }
                         }, this._babylonScene.database, true, (request, exception) => {
@@ -1610,7 +1558,6 @@ module BABYLON.GLTF2 {
             this._progressCallback(new SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
         }
 
-        /** @hidden */
         public static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T {
             if (!array || index == undefined || !array[index]) {
                 throw new Error(`${context}: Failed to find index (${index})`);
@@ -1727,6 +1674,8 @@ module BABYLON.GLTF2 {
         }
 
         private _compileMaterialsAsync(): Promise<void> {
+            this._parent._startPerformanceCounter("Compile materials");
+
             const promises = new Array<Promise<void>>();
 
             if (this._gltf.materials) {
@@ -1740,7 +1689,7 @@ module BABYLON.GLTF2 {
 
                                 const babylonMaterial = babylonData.material;
                                 promises.push(babylonMaterial.forceCompilationAsync(babylonMesh));
-                                if (this.useClipPlane) {
+                                if (this._parent.useClipPlane) {
                                     promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true }));
                                 }
                             }
@@ -1749,10 +1698,14 @@ module BABYLON.GLTF2 {
                 }
             }
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => {
+                this._parent._endPerformanceCounter("Compile materials");
+            });
         }
 
         private _compileShadowGeneratorsAsync(): Promise<void> {
+            this._parent._startPerformanceCounter("Compile shadow generators");
+
             const promises = new Array<Promise<void>>();
 
             const lights = this._babylonScene.lights;
@@ -1763,38 +1716,12 @@ module BABYLON.GLTF2 {
                 }
             }
 
-            return Promise.all(promises).then(() => {});
-        }
-
-        private _clear(): void {
-            for (const request of this._requests) {
-                request.abort();
-            }
-
-            this._requests.length = 0;
-
-            delete this._gltf;
-            delete this._babylonScene;
-            this._completePromises.length = 0;
-            this._onReadyObservable.clear();
-
-            for (const name in this._extensions) {
-                this._extensions[name].dispose();
-            }
-
-            this._extensions = {};
-
-            delete this._rootBabylonMesh;
-            delete this._progressCallback;
-
-            this.onMeshLoadedObservable.clear();
-            this.onTextureLoadedObservable.clear();
-            this.onMaterialLoadedObservable.clear();
-            this.onCameraLoadedObservable.clear();
+            return Promise.all(promises).then(() => {
+                this._parent._endPerformanceCounter("Compile shadow generators");
+            });
         }
 
-        /** @hidden */
-        public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>) {
+        public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>): Nullable<Promise<T>> {
             for (const name of GLTFLoader._ExtensionNames) {
                 const extension = this._extensions[name];
                 if (extension.enabled) {
@@ -1809,5 +1736,5 @@ module BABYLON.GLTF2 {
         }
     }
 
-    GLTFFileLoader._CreateGLTFLoaderV2 = () => new GLTFLoader();
+    GLTFFileLoader._CreateGLTFLoaderV2 = parent => new GLTFLoader(parent);
 }

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

@@ -1,5 +1,5 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 module BABYLON.GLTF2 {
     /** @hidden */

+ 137 - 139
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -86,101 +86,10 @@ module BABYLON {
         COMPLETE
     }
 
-    /**
-     * Loader interface.
-     */
+    /** @hidden */
     export interface IGLTFLoader extends IDisposable {
-        /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage. 
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        onTextureLoadedObservable: Observable<BaseTexture>;
-
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        onMaterialLoadedObservable: Observable<Material>;
-
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        onCameraLoadedObservable: Observable<Camera>;
-
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        onCompleteObservable: Observable<IGLTFLoader>;
-
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        onDisposeObservable: Observable<IGLTFLoader>;
-
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-
-        /**
-         * Loader state or null if the loader is not active.
-         */
-        state: Nullable<GLTFLoaderState>;
-
-        /**
-         * Imports meshes from the given data and adds them to the scene.
-         */
+        readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
-
-        /**
-         * Loads all objects from the given data and adds them to the scene.
-         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
 
@@ -189,10 +98,10 @@ module BABYLON {
      */
     export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
         /** @hidden */
-        public static _CreateGLTFLoaderV1: () => IGLTFLoader;
+        public static _CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
 
         /** @hidden */
-        public static _CreateGLTFLoaderV2: () => IGLTFLoader;
+        public static _CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
 
         // #region Common options
 
@@ -349,9 +258,9 @@ module BABYLON {
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
-        public readonly onCompleteObservable = new Observable<GLTFFileLoader>();
+        public readonly onCompleteObservable = new Observable<void>();
 
-        private _onCompleteObserver: Nullable<Observer<GLTFFileLoader>>;
+        private _onCompleteObserver: Nullable<Observer<void>>;
 
         /**
          * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
@@ -366,9 +275,9 @@ module BABYLON {
         /**
          * Observable raised after the loader is disposed.
          */
-        public readonly onDisposeObservable = new Observable<GLTFFileLoader>();
+        public readonly onDisposeObservable = new Observable<void>();
 
-        private _onDisposeObserver: Nullable<Observer<GLTFFileLoader>>;
+        private _onDisposeObserver: Nullable<Observer<void>>;
 
         /**
          * Callback raised after the loader is disposed.
@@ -417,6 +326,52 @@ module BABYLON {
             return this._loader ? this._loader.state : null;
         }
 
+        /**
+         * Defines if the loader logging is enabled.
+         */
+        public get loggingEnabled(): boolean {
+            return this._loggingEnabled;
+        }
+
+        public set loggingEnabled(value: boolean) {
+            if (this._loggingEnabled === value) {
+                return;
+            }
+
+            this._loggingEnabled = value;
+
+            if (this._loggingEnabled) {
+                this._log = this._logEnabled;
+            }
+            else {
+                this._log = this._logDisabled;
+            }
+        }
+
+        /**
+         * Defines if the loader should capture performance counters.
+         */
+        public get capturePerformanceCounters(): boolean {
+            return this._capturePerformanceCounters;
+        }
+
+        public set capturePerformanceCounters(value: boolean) {
+            if (this._capturePerformanceCounters === value) {
+                return;
+            }
+
+            this._capturePerformanceCounters = value;
+
+            if (this._capturePerformanceCounters) {
+                this._startPerformanceCounter = this._startPerformanceCounterEnabled;
+                this._endPerformanceCounter = this._endPerformanceCounterEnabled;
+            }
+            else {
+                this._startPerformanceCounter = this._startPerformanceCounterDisabled;
+                this._endPerformanceCounter = this._endPerformanceCounterDisabled;
+            }
+        }
+
         // #endregion
 
         private _loader: Nullable<IGLTFLoader> = null;
@@ -443,6 +398,14 @@ module BABYLON {
                 this._loader = null;
             }
 
+            this._clear();
+
+            this.onDisposeObservable.notifyObservers(undefined);
+            this.onDisposeObservable.clear();
+        }
+
+        /** @hidden */
+        public _clear(): void {
             this.preprocessUrlAsync = url => Promise.resolve(url);
 
             this.onMeshLoadedObservable.clear();
@@ -451,9 +414,6 @@ module BABYLON {
             this.onCameraLoadedObservable.clear();
             this.onCompleteObservable.clear();
             this.onExtensionLoadedObservable.clear();
-
-            this.onDisposeObservable.notifyObservers(this);
-            this.onDisposeObservable.clear();
         }
 
         /**
@@ -536,11 +496,17 @@ module BABYLON {
         }
 
         private _parse(data: string | ArrayBuffer): IGLTFLoaderData {
+            this._startPerformanceCounter("Parse");
+
             let parsedData: IGLTFLoaderData;
             if (data instanceof ArrayBuffer) {
-                parsedData = GLTFFileLoader._parseBinary(data);
+                this._log(`Parsing binary`);
+                parsedData = this._parseBinary(data);
             }
             else {
+                this._log(`Parsing JSON`);
+                this._log(`JSON length: ${data.length}`);
+
                 parsedData = {
                     json: JSON.parse(data),
                     bin: null
@@ -550,14 +516,17 @@ module BABYLON {
             this.onParsedObservable.notifyObservers(parsedData);
             this.onParsedObservable.clear();
 
+            this._endPerformanceCounter("Parse");
             return parsedData;
         }
 
         private _getLoader(loaderData: IGLTFLoaderData): IGLTFLoader {
-            const loaderVersion = { major: 2, minor: 0 };
-
             const asset = (<any>loaderData.json).asset || {};
 
+            this._log(`Asset version: ${asset.version}`);
+            asset.minVersion && this._log(`Asset minimum version: ${asset.minVersion}`);
+            asset.generator && this._log(`Asset generator: ${asset.generator}`);
+
             const version = GLTFFileLoader._parseVersion(asset.version);
             if (!version) {
                 throw new Error("Invalid version: " + asset.version);
@@ -569,12 +538,12 @@ module BABYLON {
                     throw new Error("Invalid minimum version: " + asset.minVersion);
                 }
 
-                if (GLTFFileLoader._compareVersion(minVersion, loaderVersion) > 0) {
+                if (GLTFFileLoader._compareVersion(minVersion, { major: 2, minor: 0 }) > 0) {
                     throw new Error("Incompatible minimum version: " + asset.minVersion);
                 }
             }
 
-            const createLoaders: { [key: number]: () => IGLTFLoader } = {
+            const createLoaders: { [key: number]: (parent: GLTFFileLoader) => IGLTFLoader } = {
                 1: GLTFFileLoader._CreateGLTFLoaderV1,
                 2: GLTFFileLoader._CreateGLTFLoaderV2
             };
@@ -584,40 +553,16 @@ module BABYLON {
                 throw new Error("Unsupported version: " + asset.version);
             }
 
-            const loader = createLoader();
-            loader.coordinateSystemMode = this.coordinateSystemMode;
-            loader.animationStartMode = this.animationStartMode;
-            loader.compileMaterials = this.compileMaterials;
-            loader.useClipPlane = this.useClipPlane;
-            loader.compileShadowGenerators = this.compileShadowGenerators;
-            loader.transparencyAsCoverage = this.transparencyAsCoverage;
-            loader._normalizeAnimationGroupsToBeginAtZero = this._normalizeAnimationGroupsToBeginAtZero;
-            loader.preprocessUrlAsync = this.preprocessUrlAsync;
-            loader.onMeshLoadedObservable.add(mesh => this.onMeshLoadedObservable.notifyObservers(mesh));
-            loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
-            loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));
-            loader.onCameraLoadedObservable.add(camera => this.onCameraLoadedObservable.notifyObservers(camera));
-            loader.onExtensionLoadedObservable.add(extension => this.onExtensionLoadedObservable.notifyObservers(extension));
-
-            loader.onCompleteObservable.add(() => {
-                this.onMeshLoadedObservable.clear();
-                this.onTextureLoadedObservable.clear();
-                this.onMaterialLoadedObservable.clear();
-                this.onCameraLoadedObservable.clear();
-                this.onExtensionLoadedObservable.clear();
-
-                this.onCompleteObservable.notifyObservers(this);
-                this.onCompleteObservable.clear();
-            });
-
-            return loader;
+            return createLoader(this);
         }
 
-        private static _parseBinary(data: ArrayBuffer): IGLTFLoaderData {
+        private _parseBinary(data: ArrayBuffer): IGLTFLoaderData {
             const Binary = {
                 Magic: 0x46546C67
             };
 
+            this._log(`Binary length: ${data.byteLength}`);
+
             const binaryReader = new BinaryReader(data);
 
             const magic = binaryReader.readUint32();
@@ -626,15 +571,20 @@ module BABYLON {
             }
 
             const version = binaryReader.readUint32();
+
+            if (this.loggingEnabled) {
+                this._log(`Binary version: ${version}`);
+            }
+
             switch (version) {
-                case 1: return GLTFFileLoader._parseV1(binaryReader);
-                case 2: return GLTFFileLoader._parseV2(binaryReader);
+                case 1: return this._parseV1(binaryReader);
+                case 2: return this._parseV2(binaryReader);
             }
 
             throw new Error("Unsupported version: " + version);
         }
 
-        private static _parseV1(binaryReader: BinaryReader): IGLTFLoaderData {
+        private _parseV1(binaryReader: BinaryReader): IGLTFLoaderData {
             const ContentFormat = {
                 JSON: 0
             };
@@ -667,7 +617,7 @@ module BABYLON {
             };
         }
 
-        private static _parseV2(binaryReader: BinaryReader): IGLTFLoaderData {
+        private _parseV2(binaryReader: BinaryReader): IGLTFLoaderData {
             const ChunkFormat = {
                 JSON: 0x4E4F534A,
                 BIN: 0x004E4942
@@ -750,6 +700,54 @@ module BABYLON {
 
             return result;
         }
+
+        private static readonly _logSpaces = "                                ";
+        private _logIndentLevel = 0;
+        private _loggingEnabled = false;
+
+        /** @hidden */
+        public _log = this._logDisabled;
+
+        /** @hidden */
+        public _logOpen(message: string): void {
+            this._log(message);
+            this._logIndentLevel++;
+        }
+
+        /** @hidden */
+        public _logClose(): void {
+            --this._logIndentLevel;
+        }
+
+        private _logEnabled(message: string): void {
+            const spaces = GLTFFileLoader._logSpaces.substr(0, this._logIndentLevel * 2);
+            Tools.Log(`${spaces}${message}`);
+        }
+
+        private _logDisabled(message: string): void {
+        }
+
+        private _capturePerformanceCounters = false;
+
+        /** @hidden */
+        public _startPerformanceCounter = this._startPerformanceCounterDisabled;
+
+        /** @hidden */
+        public _endPerformanceCounter = this._endPerformanceCounterDisabled;
+
+        private _startPerformanceCounterEnabled(counterName: string): void {
+            Tools.StartPerformanceCounter(counterName);
+        }
+
+        private _startPerformanceCounterDisabled(counterName: string): void {
+        }
+
+        private _endPerformanceCounterEnabled(counterName: string): void {
+            Tools.EndPerformanceCounter(counterName);
+        }
+
+        private _endPerformanceCounterDisabled(counterName: string): void {
+        }
     }
 
     class BinaryReader {

+ 21 - 1
proceduralTexturesLibrary/src/fire/babylon.fireProceduralTexture.ts

@@ -79,7 +79,15 @@ module BABYLON {
             ];
         }
 
-        @serializeAsColor3()
+        @serialize()
+        public get autoGenerateTime(): boolean {
+            return this._autoGenerateTime;
+        }
+
+        public set autoGenerateTime(value: boolean) {
+            this._autoGenerateTime = value;
+        }
+        
         public get fireColors(): Color3[] {
             return this._fireColors;
         }
@@ -127,6 +135,11 @@ module BABYLON {
             var serializationObject = SerializationHelper.Serialize(this, super.serialize());
             serializationObject.customType = "BABYLON.FireProceduralTexture";
 
+            serializationObject.fireColors = [];
+            for (var i = 0; i < this._fireColors.length; i++) {
+                serializationObject.fireColors.push(this._fireColors[i].asArray());
+            }
+
             return serializationObject;
         }
 
@@ -140,6 +153,13 @@ module BABYLON {
         public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): FireProceduralTexture {
             var texture = SerializationHelper.Parse(() => new FireProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps), parsedTexture, scene, rootUrl);
 
+            var colors: Color3[] = [];
+            for (var i = 0; i < parsedTexture.fireColors.length; i++) {
+                colors.push(Color3.FromArray(parsedTexture.fireColors[i]));
+            }
+
+            texture.fireColors = colors;
+
             return texture;
         }
     }

+ 12 - 1
proceduralTexturesLibrary/src/grass/babylon.grassProceduralTexture.ts

@@ -24,7 +24,6 @@ module BABYLON {
             this.setColor3("groundColor", this._groundColor);
         }
 
-        @serializeAsColor3()
         public get grassColors(): Color3[] {
             return this._grassColors;
         }
@@ -52,6 +51,11 @@ module BABYLON {
             var serializationObject = SerializationHelper.Serialize(this, super.serialize());
             serializationObject.customType = "BABYLON.GrassProceduralTexture";
 
+            serializationObject.grassColors = [];
+            for (var i = 0; i < this._grassColors.length; i++) {
+                serializationObject.grassColors.push(this._grassColors[i].asArray());
+            }
+
             return serializationObject;
         }
 
@@ -65,6 +69,13 @@ module BABYLON {
         public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): GrassProceduralTexture {
             var texture = SerializationHelper.Parse(() => new GrassProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps), parsedTexture, scene, rootUrl);
 
+            var colors: Color3[] = [];
+            for (var i = 0; i < parsedTexture.grassColors.length; i++) {
+                colors.push(Color3.FromArray(parsedTexture.grassColors[i]));
+            }
+
+            texture.grassColors = colors;
+
             return texture;
         }
     }

+ 2 - 2
proceduralTexturesLibrary/src/perlinNoise/babylon.perlinNoiseProceduralTexture.ts

@@ -6,7 +6,7 @@ module BABYLON {
         public time: number = 0.0;
 
         @serialize()
-        public speed: number = 1.0;
+        public timeScale: number = 1.0;
 
         @serialize()
         public translationSpeed: number = 1.0;
@@ -29,7 +29,7 @@ module BABYLON {
             var deltaTime = scene.getEngine().getDeltaTime();
 
             this.time += deltaTime;
-            this.setFloat("time", this.time * this.speed / 1000);
+            this.setFloat("time", this.time * this.timeScale / 1000);
 
             this._currentTranslation += deltaTime * this.translationSpeed / 1000.0;
             this.setFloat("translationSpeed", this._currentTranslation);

+ 2 - 1
sandbox/index.js

@@ -264,8 +264,9 @@ if (BABYLON.Engine.isSupported()) {
 
     window.addEventListener("keydown", function (event) {
         // Press R to reload
-        if (event.keyCode === 82 && event.target.nodeName !== "INPUT") {
+        if (event.keyCode === 82 && event.target.nodeName !== "INPUT" && currentScene) {
             debugLayerLastActiveTab = currentScene.debugLayer.getActiveTab();
+
             if (assetUrl) {
                 loadFromAssetUrl();
             }

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFAnimation.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 module BABYLON.GLTF2 {
     /**

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFData.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 module BABYLON {
     /**

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 module BABYLON.GLTF2 {
     /** 

+ 32 - 84
serializers/src/glTF/2.0/babylon.glTFMaterial.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 module BABYLON.GLTF2 {
     /** 
@@ -238,67 +238,15 @@ module BABYLON.GLTF2 {
          * @param babylonMaterial Babylon Material
          * @returns The Babylon alpha mode value
          */
-        public static _GetAlphaMode(babylonMaterial: Material): Nullable<MaterialAlphaMode> {
-            if (babylonMaterial instanceof StandardMaterial) {
-                const babylonStandardMaterial = babylonMaterial as StandardMaterial;
-                if ((babylonStandardMaterial.alpha !== 1.0) ||
-                    (babylonStandardMaterial.diffuseTexture != null && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
-                    (babylonStandardMaterial.opacityTexture != null)) {
-                    return MaterialAlphaMode.BLEND;
-                }
-                else {
-                    return MaterialAlphaMode.OPAQUE;
-                }
+        public static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode {
+            if (babylonMaterial.needAlphaBlending()) {
+                return MaterialAlphaMode.BLEND;
             }
-            else if (babylonMaterial instanceof PBRMetallicRoughnessMaterial) {
-                const babylonPBRMetallicRoughness = babylonMaterial as PBRMetallicRoughnessMaterial;
-
-                switch (babylonPBRMetallicRoughness.transparencyMode) {
-                    case PBRMaterial.PBRMATERIAL_OPAQUE: {
-                        return MaterialAlphaMode.OPAQUE;
-                    }
-                    case PBRMaterial.PBRMATERIAL_ALPHABLEND: {
-                        return MaterialAlphaMode.BLEND;
-                    }
-                    case PBRMaterial.PBRMATERIAL_ALPHATEST: {
-                        return MaterialAlphaMode.MASK;
-                    }
-                    case PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
-                        Tools.Warn(babylonMaterial.name + ": GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
-                        return MaterialAlphaMode.BLEND;
-                    }
-                    default: {
-                        Tools.Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
-                        return null;
-                    }
-                }
-            }
-            else if (babylonMaterial instanceof PBRMaterial) {
-                const babylonPBRMaterial = babylonMaterial as PBRMaterial;
-
-                switch (babylonPBRMaterial.transparencyMode) {
-                    case PBRMaterial.PBRMATERIAL_OPAQUE: {
-                        return MaterialAlphaMode.OPAQUE;
-                    }
-                    case PBRMaterial.PBRMATERIAL_ALPHABLEND: {
-                        return MaterialAlphaMode.BLEND;
-                    }
-                    case PBRMaterial.PBRMATERIAL_ALPHATEST: {
-                        return MaterialAlphaMode.MASK;
-                    }
-                    case PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
-                        Tools.Warn(babylonMaterial.name + ": GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
-                        return MaterialAlphaMode.BLEND;
-                    }
-                    default: {
-                        Tools.Error("Unsupported alpha mode " + babylonPBRMaterial.transparencyMode);
-                        return null;
-                    }
-                }
+            else if (babylonMaterial.needAlphaTesting) {
+                return MaterialAlphaMode.MASK;
             }
             else {
-                Tools.Error("Unsupported Babylon material type");
-                return null;
+                return MaterialAlphaMode.OPAQUE;
             }
         }
 
@@ -382,7 +330,7 @@ module BABYLON.GLTF2 {
 
             glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
             if (alphaMode !== MaterialAlphaMode.OPAQUE) {
-                switch(alphaMode) {
+                switch (alphaMode) {
                     case MaterialAlphaMode.BLEND: {
                         glTFMaterial.alphaMode = GLTF2.MaterialAlphaMode.BLEND;
                         break;
@@ -410,31 +358,32 @@ module BABYLON.GLTF2 {
          * @param useAlpha Specifies if alpha should be preserved or not
          * @returns Promise with texture
          */
-        public static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<Texture> {
+        public static _SetAlphaToOneAsync(texture: BaseTexture, useAlpha: boolean): Promise<BaseTexture> {
             return new Promise((resolve, reject) => {
                 if (useAlpha) {
-                    resolve(texture as Texture);
+                    resolve(texture);
                 }
                 else {
-                    const scene = texture.getScene();
-                    if (scene) {
-                        const proceduralTexture = new ProceduralTexture('texture', texture.getSize(), 'setAlphaToOne', scene);
-                        
-                        if (proceduralTexture) {
-                            proceduralTexture.setTexture('textureSampler', texture as Texture);
-                            proceduralTexture.onLoadObservable.add(() => { resolve(proceduralTexture) });
+                    if (texture instanceof Texture) {
+                        const scene = texture.getScene();
+                        if (scene) {
+                            const proceduralTexture = new ProceduralTexture('texture', texture.getSize(), 'setAlphaToOne', scene);
+
+                            proceduralTexture.setTexture('textureSampler', texture);
+                            proceduralTexture.onGenerated = () => {
+                                resolve(proceduralTexture);
+                            };
                         }
                         else {
-                            reject(`Cannot create procedural texture for ${texture.name}!`);
+                            reject(`Scene not available for texture ${texture.name}`);
                         }
                     }
                     else {
-                        reject(`Scene not available for texture ${texture.name}`);
+                        Tools.Warn(`Removing alpha for ${texture.textureType} not supported`);
+                        resolve(texture);
                     }
                 }
-
-            })
-
+            });
         }
 
         /**
@@ -538,7 +487,7 @@ module BABYLON.GLTF2 {
             glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
 
             materials.push(glTFMaterial);
-            materialMap[babylonPBRMetalRoughMaterial.uniqueId] = materials.length -1 ;
+            materialMap[babylonPBRMetalRoughMaterial.uniqueId] = materials.length - 1;
 
             return Promise.all(promises).then(() => { /* do nothing */ });
         }
@@ -600,8 +549,8 @@ module BABYLON.GLTF2 {
             let resizedTexture2;
 
             if (texture1Size.width < texture2Size.width) {
-                if (texture1) {
-                    resizedTexture1 = TextureTools.CreateResizedCopy(texture1 as Texture, texture2Size.width, texture2Size.height, true);
+                if (texture1 && texture1 instanceof Texture) {
+                    resizedTexture1 = TextureTools.CreateResizedCopy(texture1, texture2Size.width, texture2Size.height, true);
                 }
                 else {
                     resizedTexture1 = this._CreateWhiteTexture(texture2Size.width, texture2Size.height, scene);
@@ -609,8 +558,8 @@ module BABYLON.GLTF2 {
                 resizedTexture2 = texture2;
             }
             else if (texture1Size.width > texture2Size.width) {
-                if (texture2) {
-                    resizedTexture2 = TextureTools.CreateResizedCopy(texture2 as Texture, texture1Size.width, texture1Size.height, true);
+                if (texture2 && texture2 instanceof Texture) {
+                    resizedTexture2 = TextureTools.CreateResizedCopy(texture2, texture1Size.width, texture1Size.height, true);
                 }
                 else {
                     resizedTexture2 = this._CreateWhiteTexture(texture1Size.width, texture1Size.height, scene);
@@ -871,7 +820,7 @@ module BABYLON.GLTF2 {
         private static _GetGLTFTextureSampler(texture: BaseTexture): ISampler {
             const sampler = _GLTFMaterial._GetGLTFTextureWrapModesSampler(texture);
 
-            let samplingMode = texture instanceof Texture ? (texture as Texture).samplingMode : null;
+            let samplingMode = texture instanceof Texture ? texture.samplingMode : null;
             if (samplingMode != null) {
                 switch (samplingMode) {
                     case Texture.LINEAR_LINEAR: {
@@ -958,8 +907,8 @@ module BABYLON.GLTF2 {
         }
 
         private static _GetGLTFTextureWrapModesSampler(texture: BaseTexture): ISampler {
-            let wrapS = _GLTFMaterial._GetGLTFTextureWrapMode(texture instanceof Texture ? (texture as Texture).wrapU : Texture.WRAP_ADDRESSMODE);
-            let wrapT = _GLTFMaterial._GetGLTFTextureWrapMode(texture instanceof Texture ? (texture as Texture).wrapV : Texture.WRAP_ADDRESSMODE);
+            let wrapS = _GLTFMaterial._GetGLTFTextureWrapMode(texture instanceof Texture ? texture.wrapU : Texture.WRAP_ADDRESSMODE);
+            let wrapT = _GLTFMaterial._GetGLTFTextureWrapMode(texture instanceof Texture ? texture.wrapV : Texture.WRAP_ADDRESSMODE);
 
             if (wrapS === TextureWrapMode.REPEAT && wrapT === TextureWrapMode.REPEAT) { // default wrapping mode in glTF, so omitting
                 return {};
@@ -1148,7 +1097,7 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(result => { /* do nothing */ });
         }
 
-        private static GetPixelsFromTexture(babylonTexture: Texture): Uint8Array | Float32Array {
+        private static GetPixelsFromTexture(babylonTexture: BaseTexture): Uint8Array | Float32Array {
             const pixels = babylonTexture.textureType === Engine.TEXTURETYPE_UNSIGNED_INT ? babylonTexture.readPixels() as Uint8Array : babylonTexture.readPixels() as Float32Array;
             return pixels;
         }
@@ -1184,7 +1133,6 @@ module BABYLON.GLTF2 {
             else {
                 samplerIndex = foundSamplerIndex;
             }
-            
             return this._SetAlphaToOneAsync(babylonTexture, useAlpha).then((texture) => {
                 const pixels = _GLTFMaterial.GetPixelsFromTexture(texture);
                 const size = babylonTexture.getSize();

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFUtilities.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 module BABYLON.GLTF2 {
     /**

+ 101 - 0
src/Behaviors/Mesh/babylon.multiPointerScaleBehavior.ts

@@ -0,0 +1,101 @@
+module BABYLON {
+    /**
+     * A behavior that when attached to a mesh will allow the mesh to be scaled
+     */
+    export class MultiPointerScaleBehavior implements Behavior<Mesh> {
+        private _dragBehaviorA:PointerDragBehavior;
+        private _dragBehaviorB:PointerDragBehavior;
+        private _startDistance = 0;
+        private _initialScale = new Vector3(0,0,0);
+        private _targetScale = new Vector3(0,0,0);
+        private _ownerNode:Mesh;
+        private _sceneRenderObserver:Nullable<Observer<Scene>> = null;
+
+        constructor(){
+            this._dragBehaviorA = new BABYLON.PointerDragBehavior({});
+            this._dragBehaviorA.moveAttached = false;
+            this._dragBehaviorB = new BABYLON.PointerDragBehavior({});
+            this._dragBehaviorB.moveAttached = false;
+        }
+        
+        /**
+         *  The name of the behavior
+         */
+        public get name(): string {
+            return "MultiPointerScale";
+        }
+
+        /**
+         *  Initializes the behavior
+         */
+        public init() {}
+
+        private _getCurrentDistance(){
+            return this._dragBehaviorA.lastDragPosition.subtract(this._dragBehaviorB.lastDragPosition).length();
+        }
+
+        /**
+         * Attaches the scale behavior the passed in mesh
+         * @param ownerNode The mesh that will be scaled around once attached
+         */
+        public attach(ownerNode: Mesh): void {
+            this._ownerNode = ownerNode;
+
+            // Create 2 drag behaviors such that each will only be triggered by a separate pointer
+            this._dragBehaviorA.onDragStartObservable.add((e)=>{
+                if(this._dragBehaviorA.dragging && this._dragBehaviorB.dragging){
+                    if(this._dragBehaviorA.currentDraggingPointerID == this._dragBehaviorB.currentDraggingPointerID){
+                        this._dragBehaviorA.releaseDrag();
+                    }else{
+                        this._initialScale.copyFrom(ownerNode.scaling)
+                        this._startDistance = this._getCurrentDistance();
+                    }
+                }
+            });
+            this._dragBehaviorB.onDragStartObservable.add((e)=>{
+                if(this._dragBehaviorA.dragging && this._dragBehaviorB.dragging){
+                    if(this._dragBehaviorA.currentDraggingPointerID == this._dragBehaviorB.currentDraggingPointerID){
+                        this._dragBehaviorB.releaseDrag();
+                    }else{
+                        this._initialScale.copyFrom(ownerNode.scaling)
+                        this._startDistance = this._getCurrentDistance();
+                    }
+                }
+            });
+
+            // Once both drag behaviors are active scale based on the distance between the two pointers
+            [this._dragBehaviorA, this._dragBehaviorB].forEach((behavior)=>{
+                behavior.onDragObservable.add(()=>{
+                    if(this._dragBehaviorA.dragging && this._dragBehaviorB.dragging){
+                        var ratio = this._getCurrentDistance()/this._startDistance;
+                        this._initialScale.scaleToRef(ratio, this._targetScale);
+                    }
+                });
+            })
+
+            ownerNode.addBehavior(this._dragBehaviorA);
+            ownerNode.addBehavior(this._dragBehaviorB);
+
+            // On every frame move towards target scaling to avoid jitter caused by vr controllers
+            this._sceneRenderObserver = ownerNode.getScene().onBeforeRenderObservable.add(()=>{
+                if(this._dragBehaviorA.dragging && this._dragBehaviorB.dragging){
+                    var change = this._targetScale.subtract(ownerNode.scaling).scaleInPlace(0.1);
+                    if(change.length()>0.01){
+                        ownerNode.scaling.addInPlace(change);
+                    }
+                }
+            });
+        }
+        /**
+         *  Detaches the behavior from the mesh
+         */
+        public detach(): void {
+            this._ownerNode.getScene().onBeforeRenderObservable.remove(this._sceneRenderObserver);
+            [this._dragBehaviorA, this._dragBehaviorB].forEach((behavior)=>{
+                behavior.onDragStartObservable.clear();
+                behavior.onDragObservable.clear();
+                this._ownerNode.removeBehavior(behavior);
+            });
+        }
+    }
+}

+ 74 - 37
src/Behaviors/Mesh/babylon.pointerDragBehavior.ts

@@ -8,7 +8,18 @@ module BABYLON {
         private _scene:Scene;
         private _pointerObserver:Nullable<Observer<PointerInfo>>;
         private static _planeScene:Scene;
-        private _draggingID = -1;
+        /**
+         * The id of the pointer that is currently interacting with the behavior (-1 when no pointer is active)
+         */
+        public currentDraggingPointerID = -1;
+        /**
+         * The last position where the pointer hit the drag plane in world space
+         */
+        public lastDragPosition:Vector3;
+        /**
+         * If the behavior is currently in a dragging state
+         */
+        public dragging = false;
         // Debug mode will display drag planes to help visualize behavior
         private _debugMode = false;
         private _maxDragAngle = Math.PI/5;
@@ -20,15 +31,15 @@ module BABYLON {
          *  * dragPlaneNormal normal of the current drag plane used during the drag
          *  * dragPlanePoint in world space where the drag intersects the drag plane
          */
-        public onDragObservable = new Observable<{delta:Vector3, dragPlanePoint:Vector3, dragPlaneNormal:Vector3, dragDistance:number}>()
+        public onDragObservable = new Observable<{delta:Vector3, dragPlanePoint:Vector3, dragPlaneNormal:Vector3, dragDistance:number, pointerId:number}>()
         /**
          *  Fires each time a drag begins (eg. mouse down on mesh)
          */
-        public onDragStartObservable = new Observable<{dragPlanePoint:Vector3}>()
+        public onDragStartObservable = new Observable<{dragPlanePoint:Vector3, pointerId:number}>()
         /**
          *  Fires each time a drag ends (eg. mouse release after drag)
          */
-        public onDragEndObservable = new Observable<{dragPlanePoint:Vector3}>()
+        public onDragEndObservable = new Observable<{dragPlanePoint:Vector3, pointerId:number}>()
         /**
          *  If the attached mesh should be moved when dragged
          */
@@ -39,11 +50,16 @@ module BABYLON {
         public _dragPlaneParent:Nullable<Mesh>=null;
 
         /**
-         *  If the drag behavior will react to drag events
+         *  If the drag behavior will react to drag events (Default: true)
          */
         public enabled = true;
         
         /**
+         * If set, the drag plane/axis will be rotated based on the attached mesh's world rotation (Default: true)
+         */
+        public useObjectOrienationForDragging = true;
+
+        /**
          * Creates a pointer drag behavior that can be attached to a mesh
          * @param options The drag axis or normal of the plane that will be dragged across. If no options are specified the drag plane will always face the ray's origin (eg. camera)
          */
@@ -75,6 +91,8 @@ module BABYLON {
          */
         public init() {}
 
+        private _tmpVector = new Vector3(0,0,0);
+        private _worldDragAxis = new Vector3(0,0,0);
         /**
          * Attaches the drag behavior the passed in mesh
          * @param ownerNode The mesh that will be dragged around once attached
@@ -95,8 +113,7 @@ module BABYLON {
             this._dragPlane = BABYLON.Mesh.CreatePlane("pointerDragPlane", this._debugMode ? 1 : 10000, PointerDragBehavior._planeScene, false, BABYLON.Mesh.DOUBLESIDE);
 
             // State of the drag
-            var dragging = false;
-            var lastPosition = new BABYLON.Vector3(0,0,0);
+            this.lastDragPosition = new BABYLON.Vector3(0,0,0);
             var delta = new BABYLON.Vector3(0,0,0);
             var dragLength = 0;
 
@@ -110,24 +127,23 @@ module BABYLON {
                 }
                 
                 if (pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN) {
-                    if(!dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
+                    
+                    if(!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
                         this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
                         var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
                         if(pickedPoint){
-                            dragging = true;
-                            this._draggingID = (<PointerEvent>pointerInfo.event).pointerId;
-                            lastPosition.copyFrom(pickedPoint);
-                            this.onDragStartObservable.notifyObservers({dragPlanePoint: pickedPoint});
+                            this.dragging = true;
+                            this.currentDraggingPointerID = (<PointerEvent>pointerInfo.event).pointerId;
+                            this.lastDragPosition.copyFrom(pickedPoint);
+                            this.onDragStartObservable.notifyObservers({dragPlanePoint: pickedPoint, pointerId: this.currentDraggingPointerID});
                         }
                     }
                 }else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERUP){
-                    if(this._draggingID == (<PointerEvent>pointerInfo.event).pointerId){
-                        dragging = false;
-                        this._draggingID = -1;
-                        this.onDragEndObservable.notifyObservers({dragPlanePoint: lastPosition});
+                    if(this.currentDraggingPointerID == (<PointerEvent>pointerInfo.event).pointerId){
+                        this.releaseDrag();
                     }
                 }else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERMOVE){
-                    if(this._draggingID == (<PointerEvent>pointerInfo.event).pointerId && dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.ray){
+                    if(this.currentDraggingPointerID == (<PointerEvent>pointerInfo.event).pointerId && this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.ray){
                         var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
                         
                          // Get angle between drag plane and ray. Only update the drag plane at non steep angles to avoid jumps in delta position
@@ -140,26 +156,34 @@ module BABYLON {
                             // depending on the drag mode option drag accordingly
                             if(this.options.dragAxis){
                                 // Convert local drag axis to world
-                                var worldDragAxis = Vector3.TransformCoordinates(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix());
+                                Vector3.TransformCoordinatesToRef(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix(), this._worldDragAxis);
 
                                 // Project delta drag from the drag plane onto the drag axis
-                                dragLength = BABYLON.Vector3.Dot(pickedPoint.subtract(lastPosition), worldDragAxis)
-                                worldDragAxis.scaleToRef(dragLength, delta);
+                                pickedPoint.subtractToRef(this.lastDragPosition, this._tmpVector);
+                                dragLength = BABYLON.Vector3.Dot(this._tmpVector, this._worldDragAxis)
+                                this._worldDragAxis.scaleToRef(dragLength, delta);
                             }else{
                                 dragLength = delta.length();
-                                pickedPoint.subtractToRef(lastPosition, delta);
+                                pickedPoint.subtractToRef(this.lastDragPosition, delta);
                             }
                             if(this.moveAttached){
-                                (<Mesh>this._attachedNode).position.addInPlace(delta);
+                                (<Mesh>this._attachedNode).absolutePosition.addToRef(delta, this._tmpVector);
+                                (<Mesh>this._attachedNode).setAbsolutePosition(this._tmpVector);
                             }
-                            this.onDragObservable.notifyObservers({dragDistance: dragLength, delta: delta, dragPlanePoint: pickedPoint, dragPlaneNormal: this._dragPlane.forward});
-                            lastPosition.copyFrom(pickedPoint);
+                            this.onDragObservable.notifyObservers({dragDistance: dragLength, delta: delta, dragPlanePoint: pickedPoint, dragPlaneNormal: this._dragPlane.forward, pointerId: this.currentDraggingPointerID});
+                            this.lastDragPosition.copyFrom(pickedPoint);
                         }
                     }
                 }
             });
         }
 
+        public releaseDrag(){
+            this.dragging = false;
+            this.onDragEndObservable.notifyObservers({dragPlanePoint: this.lastDragPosition, pointerId: this.currentDraggingPointerID});
+            this.currentDraggingPointerID = -1;
+        }
+
         private _pickWithRayOnDragPlane(ray:Nullable<Ray>){
             if(!ray){
                 return null;
@@ -172,29 +196,42 @@ module BABYLON {
             }
         }
 
+        // Variables to avoid instantiation in the below method
+        private _pointA = new Vector3(0,0,0);
+        private _pointB = new Vector3(0,0,0);
+        private _pointC = new Vector3(0,0,0);
+        private _lineA = new Vector3(0,0,0);
+        private _lineB = new Vector3(0,0,0);
+        private _localAxis = new Vector3(0,0,0);
+        private _lookAt = new Vector3(0,0,0); 
         // Position the drag plane based on the attached mesh position, for single axis rotate the plane along the axis to face the camera
         private _updateDragPlanePosition(ray:Ray){
-            var pointA = this._dragPlaneParent ? this._dragPlaneParent.absolutePosition : (<Mesh>this._attachedNode).absolutePosition;
+            this._pointA.copyFrom(this._dragPlaneParent ? this._dragPlaneParent.absolutePosition : (<Mesh>this._attachedNode).absolutePosition);
             if(this.options.dragAxis){
-                var localAxis = Vector3.TransformCoordinates(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix());
+                this.useObjectOrienationForDragging ? Vector3.TransformCoordinatesToRef(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix(), this._localAxis) : this._localAxis.copyFrom(this.options.dragAxis);
 
                 // Calculate plane normal in direction of camera but perpendicular to drag axis
-                var pointB = pointA.add(localAxis); // towards drag axis
-                var pointC = pointA.add(ray.origin.subtract(pointA).normalize()); // towards camera
+                this._pointA.addToRef(this._localAxis, this._pointB); // towards drag axis
+                ray.origin.subtractToRef(this._pointA, this._pointC)
+                this._pointA.addToRef(this._pointC.normalize(), this._pointC); // towards camera
                 // Get perpendicular line from direction to camera and drag axis
-                var lineA = pointB.subtract(pointA);
-                var lineB = pointC.subtract(pointA);
-                var perpLine = BABYLON.Vector3.Cross(lineA, lineB);
+                this._pointB.subtractToRef(this._pointA, this._lineA);
+                this._pointC.subtractToRef(this._pointA, this._lineB);
+                BABYLON.Vector3.CrossToRef(this._lineA, this._lineB, this._lookAt);
                 // Get perpendicular line from previous result and drag axis to adjust lineB to be perpendiculat to camera
-                var norm = BABYLON.Vector3.Cross(lineA, perpLine).normalize();
+                BABYLON.Vector3.CrossToRef(this._lineA, this._lookAt, this._lookAt);
+                this._lookAt.normalize();
 
-                this._dragPlane.position.copyFrom(pointA);
-                this._dragPlane.lookAt(pointA.subtract(norm));
+                this._dragPlane.position.copyFrom(this._pointA);
+                this._pointA.subtractToRef(this._lookAt, this._lookAt);
+                this._dragPlane.lookAt(this._lookAt);
             }else if(this.options.dragPlaneNormal){
-                this._dragPlane.position.copyFrom(pointA);
-                this._dragPlane.lookAt(pointA.subtract(this.options.dragPlaneNormal));
+                this.useObjectOrienationForDragging ? Vector3.TransformCoordinatesToRef(this.options.dragPlaneNormal, this._attachedNode.getWorldMatrix().getRotationMatrix(),this._localAxis) : this._localAxis.copyFrom(this.options.dragPlaneNormal);
+                this._dragPlane.position.copyFrom(this._pointA);
+                this._pointA.subtractToRef(this._localAxis, this._lookAt);
+                this._dragPlane.lookAt(this._lookAt);
             }else{
-                this._dragPlane.position.copyFrom(pointA);
+                this._dragPlane.position.copyFrom(this._pointA);
                 this._dragPlane.lookAt(ray.origin);
             }
             this._dragPlane.computeWorldMatrix(true);

+ 0 - 0
src/Behaviors/Mesh/babylon.sixDofDragBehavior.ts


Некоторые файлы не были показаны из-за большого количества измененных файлов