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

Merge branch 'master' into oimo-rotation

Raanan Weber 7 лет назад
Родитель
Сommit
f67c1cdaac
42 измененных файлов с 95678 добавлено и 94590 удалено
  1. 7362 7329
      Playground/babylon.d.txt
  2. 297 245
      Playground/js/index.js
  3. 80 0
      Playground/js/libs/typescript.js
  4. 60 0
      Playground/js/ts.js
  5. 32 0
      Playground/scripts/basic scene.txt
  6. 467 0
      Playground/ts.html
  7. 17 4
      Tools/Gulp/config.json
  8. 3 3
      Viewer/src/configuration/types/extended.ts
  9. 3 2
      Viewer/src/managers/sceneManager.ts
  10. 1 1
      contributing.md
  11. 7341 7332
      dist/preview release/babylon.d.ts
  12. 57 57
      dist/preview release/babylon.js
  13. 16936 16948
      dist/preview release/babylon.max.js
  14. 16936 16948
      dist/preview release/babylon.no-module.max.js
  15. 57 57
      dist/preview release/babylon.worker.js
  16. 16938 16950
      dist/preview release/es6.js
  17. 26 2
      dist/preview release/gui/babylon.gui.d.ts
  18. 71 12
      dist/preview release/gui/babylon.gui.js
  19. 3 3
      dist/preview release/gui/babylon.gui.min.js
  20. 26 2
      dist/preview release/gui/babylon.gui.module.d.ts
  21. 37 2
      dist/preview release/typedocValidationBaseline.json
  22. 69 69
      dist/preview release/viewer/babylon.viewer.js
  23. 28432 28443
      dist/preview release/viewer/babylon.viewer.max.js
  24. 5 1
      dist/preview release/what's new.md
  25. 16 0
      gui/src/2D/controls/inputPassword.ts
  26. 9 5
      gui/src/2D/controls/inputText.ts
  27. 79 13
      gui/src/2D/controls/textBlock.ts
  28. 27 0
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  29. 6 1
      src/Behaviors/Mesh/babylon.pointerDragBehavior.ts
  30. 1 3
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  31. 58 0
      src/Engine/Extensions/babylon.engine.occlusionQuery.ts
  32. 74 0
      src/Engine/Extensions/babylon.engine.transformFeedback.ts
  33. 0 59
      src/Engine/babylon.engine.ts
  34. 7 2
      src/Materials/babylon.materialHelper.ts
  35. 10 55
      src/Mesh/babylon.abstractMesh.ts
  36. 1 1
      src/Particles/babylon.gpuParticleSystem.ts
  37. 4 0
      src/Tools/babylon.environmentTextureTools.ts
  38. 0 4
      src/Tools/babylon.sceneOptimizer.ts
  39. 1 1
      src/Tools/babylon.tools.ts
  40. 128 35
      tests/nullEngine/app.js
  41. BIN
      tests/validation/ReferenceImages/dds.png
  42. 1 1
      tests/validation/config.json

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


Разница между файлами не показана из-за своего большого размера
+ 297 - 245
Playground/js/index.js


Разница между файлами не показана из-за своего большого размера
+ 80 - 0
Playground/js/libs/typescript.js


+ 60 - 0
Playground/js/ts.js

@@ -0,0 +1,60 @@
+
+var compilerTriggerTimeoutID;
+function triggerCompile(d, func) {
+    if (compilerTriggerTimeoutID !== null) {
+        window.clearTimeout(compilerTriggerTimeoutID);
+    }
+    compilerTriggerTimeoutID = window.setTimeout(function () {
+        try {
+             
+            var output = transpileModule(d, {
+                module: ts.ModuleKind.AMD,
+                target: ts.ScriptTarget.ES5,
+                noLib: true,
+                noResolve: true,
+                suppressOutputPathCheck: true
+            });
+            if (typeof output === "string") {
+                func(output);
+            }
+        }
+        catch (e) {
+            showError(e.message, e);
+        }
+    }, 100);
+}
+function transpileModule(input, options) {
+    var inputFileName = options.jsx ? "module.tsx" : "module.ts";
+    var sourceFile = ts.createSourceFile(inputFileName, input, options.target || ts.ScriptTarget.ES5);
+    // Output
+    var outputText;
+    var program = ts.createProgram([inputFileName], options, {
+        getSourceFile: function (fileName) { return fileName.indexOf("module") === 0 ? sourceFile : undefined; },
+        writeFile: function (_name, text) { outputText = text; },
+        getDefaultLibFileName: function () { return "lib.d.ts"; },
+        useCaseSensitiveFileNames: function () { return false; },
+        getCanonicalFileName: function (fileName) { return fileName; },
+        getCurrentDirectory: function () { return ""; },
+        getNewLine: function () { return "\r\n"; },
+        fileExists: function (fileName) { return fileName === inputFileName; },
+        readFile: function () { return ""; },
+        directoryExists: function () { return true; },
+        getDirectories: function () { return []; }
+    });
+    // Emit
+    program.emit();
+    if (outputText === undefined) {
+        throw new Error("Output generation failed");
+    }
+    return outputText;
+}
+
+function getRunCode(jsEditor, callBack) {
+    triggerCompile(jsEditor.getValue(), function(result) {
+        callBack(result + "var createScene = function() { return Playground.CreateScene(engine, engine.getRenderingCanvas()); }")
+    });
+}
+
+var defaultScene = "scripts/basic scene.txt";
+var monacoMode = "typescript";
+

+ 32 - 0
Playground/scripts/basic scene.txt

@@ -0,0 +1,32 @@
+class Playground { 
+    public static CreateScene(engine: BABYLON.Engine, canvas: HTMLCanvasElement): BABYLON.Scene {
+        // This creates a basic Babylon Scene object (non-mesh)
+        var scene = new BABYLON.Scene(engine);
+
+        // This creates and positions a free camera (non-mesh)
+        var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
+
+        // This targets the camera to scene origin
+        camera.setTarget(BABYLON.Vector3.Zero());
+
+        // This attaches the camera to the canvas
+        camera.attachControl(canvas, true);
+
+        // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
+        var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
+
+        // Default intensity is 1. Let's dim the light a small amount
+        light.intensity = 0.7;
+
+        // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
+        var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
+
+        // Move the sphere upward 1/2 its height
+        sphere.position.y = 1;
+
+        // Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
+        var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);
+
+        return scene;
+    }
+}

+ 467 - 0
Playground/ts.html

@@ -0,0 +1,467 @@
+<!DOCTYPE html>
+<html>
+
+    <head>
+        <title>Babylon.js Playground</title>
+        <meta charset='utf-8' />
+        <meta name="viewport" content="width=device-width, user-scalable=no">
+        <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
+        <link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
+        <link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
+        <link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
+        <link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
+        <link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
+        <link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
+        <link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
+        <link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
+        <link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
+        <link rel="icon" type="image/png" sizes="192x192" href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
+        <link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
+        <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
+        <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
+        <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
+        <meta name="msapplication-TileColor" content="#ffffff">
+        <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
+        <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
+        <meta name="theme-color" content="#ffffff">
+
+        <script src="js/libs/pep.min.js"></script>
+        <!--For canvas/code separator-->
+        <script src="js/libs/split.js"></script>
+
+        <script src="js/libs/dat.gui.min.js"></script>
+        <!-- jszip -->
+        <script src="js/libs/jszip.min.js"></script>
+        <script src="js/libs/fileSaver.js"></script>
+        <!-- Dependencies -->
+        <script src="https://preview.babylonjs.com/cannon.js"></script>
+        <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/earcut.min.js"></script>
+        <!-- Monaco -->
+        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+        <!-- Babylon.js -->
+        <script src="https://preview.babylonjs.com/babylon.js"></script>
+        <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
+        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
+        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
+        <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
+        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+
+        <!-- Extensions -->
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js" async></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js" async></script>
+        <script src="https://www.babylontoolkit.com/playground/scripts/babylon.navmesh.js"></script>
+        <script src="https://www.babylontoolkit.com/playground/scripts/babylon.manager.js"></script>
+                               
+        <link href="css/index.css" rel="stylesheet" />
+    </head>
+
+    <body>
+        <div class="navbar navBar1600">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+            </div>
+
+            <div class="category">
+                <div class="button run" id="runButton1600">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
+
+
+            <div class="category">
+                <div class="button" id="newButton1600">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1600">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button" id="saveButton1600">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1600">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1600">Dark</div>
+                                <div class="option" id="lightTheme1600">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1600">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle1600">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1600">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1600">Format code</div>
+                        <div class="option" id="minimapToggle1600">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="button uncheck" id="debugButton1600">Inspector
+                    <i class="fa fa-square-o" aria-hidden="true"></i>
+                </div>
+                <div class="button" id="metadataButton1600">Metadata</div>
+            </div>
+
+
+
+            <div class="category right">
+                <div class="button select">
+                    <span id="currentVersion1600">Version: Latest</span>
+                    <div class="toDisplay">
+                        <div class="option" onclick="setVersion('latest');">Latest</div>
+                        <div class="option" onclick="setVersion('stable');">Stable</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="navbar navBar1475">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+            </div>
+
+            <div class="category">
+                <div class="button run" id="runButton1475">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
+
+
+            <div class="category">
+                <div class="button" id="newButton1475">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1475">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button" id="saveButton1475">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1475">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1475">Dark</div>
+                                <div class="option" id="lightTheme1475">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1475">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id='safemodeToggle1475'>Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1475">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1475">Format code</div>
+                        <div class="option" id="minimapToggle1475">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton1475">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1475">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1475">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="navbar navBar1030">
+            <div class="category">
+                <div class="button run" id="runButton1030">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
+
+
+            <div class="category">
+                <div class="button" id="newButton1030">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1030">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button" id="saveButton1030">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1030">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1030">Dark</div>
+                                <div class="option" id="lightTheme1030">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1030">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle1030">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1030">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1030">Format code</div>
+                        <div class="option" id="minimapToggle1030">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton1030">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1030">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1030">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="navbar navBar750">
+            <div class="category">
+                <div class="button select">File
+                    <div class="toDisplay">
+                        <div class="option" id="runButton750">Run
+                            <i class="fa fa-play" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="newButton750">New
+                            <i class="fa fa-file" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="clearButton750">Clear
+                            <i class="fa fa-trash" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="saveButton750">Save
+                            <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="zipButton750">Zip
+                            <i class="fa fa-download" aria-hidden="true"></i>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme750">Dark</div>
+                                <div class="option" id="lightTheme750">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize750">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle750">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div style="display:none;" class="option checked" id="editorButton750">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton750">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
+                        <div class="option" id="formatButton750">Format code</div>
+                        <div class="option" id="minimapToggle750">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton750">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton750">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion750">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="wrapper">
+            <div id="jsEditor"></div>
+            <div id="canvasZone">
+                <canvas touch-action="none" id="renderCanvas"></canvas>
+            </div>
+        </div>
+
+        <span class="label" id="fpsLabel">FPS</span>
+
+        <div id="errorZone">
+        </div>
+
+        <div class="navbarBottom">
+            <div id="statusBar"></div>
+            <div class="links">
+                <div class='link'>
+                    <a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com">Documentation</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com/playground">Search</a>
+                </div>
+            </div>
+        </div>
+
+        <div id="saveLayer" class="save-layer">
+            <div class="save-form">
+                <label for="saveFormTitle">TITLE</label>
+                <div class="separator"></div>
+                <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+
+                <label for="saveFormDescription">DESCRIPTION</label>
+                <div class="separator"></div>
+                <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+
+                <label for="saveFormTags">TAGS (separated by comma)</label>
+                <div class="separator"></div>
+                <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+
+                <div class="save-form-buttons" id="saveFormButtons">
+
+                    <div id="saveFormButtonOk" class="button">OK</div>
+                    <div id="saveFormButtonCancel" class="button">Cancel</div>
+                </div>
+            </div>
+        </div>
+
+        <div id="waitDiv">
+            <span id="waitTitle">Babylon.js Playground
+                <BR>
+                <BR>
+                <BR>
+            </span>
+            <img src="waitlogo.png" id="waitLogo" />
+        </div>
+
+        <script src="js/libs/jquery.min.js"></script>
+
+        <script src="js/actions.js"></script>
+        <script src="js/pbt.js"></script>
+        <script src="js/libs/typescript.js"></script>
+        <script src="js/index.js"></script>
+        <script src="js/ts.js"></script>
+        
+        <!-- Global site tag (gtag.js) - Google Analytics -->
+        <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
+        <script>
+        window.dataLayer = window.dataLayer || [];
+        function gtag(){dataLayer.push(arguments);}
+        gtag('js', new Date());
+
+        gtag('config', 'UA-41767310-2');
+        </script>        
+    </body>
+
+</html>

+ 17 - 4
Tools/Gulp/config.json

@@ -121,7 +121,8 @@
             "photoDome",
             "behaviors",
             "imageProcessing",
-            "occlusionQuery"     
+            "occlusionQuery",
+            "transformFeedback"     
         ],
         "minimal": [
             "meshBuilder",
@@ -235,12 +236,22 @@
                 "fogFragment"
             ]
         },
+        "transformFeedback": {
+            "files": [
+                "../../src/Engine/Extensions/babylon.engine.transformFeedback.js"
+            ],
+            "dependUpon": [
+                "core",
+                "debug"
+            ]
+        },          
         "occlusionQuery": {
             "files": [
                 "../../src/Engine/Extensions/babylon.engine.occlusionQuery.js"
             ],
             "dependUpon": [
-                "core"
+                "core",
+                "debug"
             ]
         },          
         "behaviors": {
@@ -284,7 +295,8 @@
             ],
             "dependUpon": [
                 "core",
-                "particles"
+                "particles",
+                "transformFeedback"
             ],
             "shaders": [
                 "gpuRenderParticles.vertex",
@@ -1794,6 +1806,7 @@
                     "../../gui/src/2D/controls/button.ts",
                     "../../gui/src/2D/controls/colorpicker.ts",
                     "../../gui/src/2D/controls/inputText.ts",
+                    "../../gui/src/2D/controls/inputPassword.ts",
                     "../../gui/src/2D/controls/virtualKeyboard.ts",
                     "../../gui/src/2D/controls/multiLine.ts",
                     "../../gui/src/2D/controls/grid.ts",                    
@@ -2008,4 +2021,4 @@
             ]
         }
     }
-}
+}

+ 3 - 3
Viewer/src/configuration/types/extended.ts

@@ -62,7 +62,7 @@ export let extendedConfiguration: ViewerConfiguration = {
             intensity: 7,
             intensityMode: 0,
             radius: 0.6,
-            range: 0.6,
+            range: 4.4,
             spotAngle: 60,
             diffuse: {
                 r: 1,
@@ -101,7 +101,7 @@ export let extendedConfiguration: ViewerConfiguration = {
             intensity: 7,
             intensityMode: 0,
             radius: 0.4,
-            range: 0.4,
+            range: 5.8,
             spotAngle: 57,
             diffuse: {
                 r: 1,
@@ -132,7 +132,7 @@ export let extendedConfiguration: ViewerConfiguration = {
             intensity: 1,
             intensityMode: 0,
             radius: 0.5,
-            range: 0.5,
+            range: 6,
             spotAngle: 42.85,
             diffuse: {
                 r: 0.8,

+ 3 - 2
Viewer/src/managers/sceneManager.ts

@@ -7,6 +7,7 @@ import { ViewerLabs } from '../labs/viewerLabs';
 import { getCustomOptimizerByName } from '../optimizer/custom/';
 import { ObservablesManager } from '../managers/observablesManager';
 import { ConfigurationContainer } from '../configuration/configurationContainer';
+import { deepmerge } from '../helper';
 
 /**
  * This interface describes the structure of the variable sent with the configuration observables of the scene manager.
@@ -796,11 +797,11 @@ export class SceneManager {
             }
             return;
         }
-        let vrOptions: VRExperienceHelperOptions = vrConfig.vrOptions || {
+        let vrOptions: VRExperienceHelperOptions = deepmerge({
             useCustomVRButton: true,
             createDeviceOrientationCamera: false,
             trackPosition: true
-        }
+        }, vrConfig.vrOptions || {});
 
         this._vrHelper = this.scene.createDefaultVRExperience(vrOptions);
         if (!vrConfig.disableInteractions) {

+ 1 - 1
contributing.md

@@ -23,7 +23,7 @@ We will try to enforce these rules as we consider the forum is a better place fo
 
 ## Pull requests
 
-We are not complicated people, but we still have some [coding guidelines](http://doc.babylonjs.com/generals/Approved_Naming_Conventions)
+We are not complicated people, but we still have some [coding guidelines](http://doc.babylonjs.com/how_to/approved_naming_conventions)
 Before submitting your PR, just check that everything goes well by [creating the minified version](http://doc.babylonjs.com/generals/Creating_the_Mini-fied_Version)
 
 Need help contributing, here are some links:

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


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


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


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


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


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


+ 26 - 2
dist/preview release/gui/babylon.gui.d.ts

@@ -1316,6 +1316,23 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     /**
+     * Enum that determines the text-wrapping mode to use.
+     */
+    enum TextWrapping {
+        /**
+         * Clip the text when it's larger than Control.width; this is the default mode.
+         */
+        Clip = 0,
+        /**
+         * Wrap the text word-wise, i.e. try to add line-breaks at word boundary to fit within Control.width.
+         */
+        WordWrap = 1,
+        /**
+         * Ellipsize the text, i.e. shrink with trailing … when text is larger than Control.width.
+         */
+        Ellipsis = 2,
+    }
+    /**
      * Class used to create text block control
      */
     class TextBlock extends Control {
@@ -1357,7 +1374,7 @@ declare module BABYLON.GUI {
         /**
          * Gets or sets a boolean indicating if text must be wrapped
          */
-        textWrapping: boolean;
+        textWrapping: TextWrapping | boolean;
         /**
          * Gets or sets text to display
          */
@@ -1416,9 +1433,16 @@ declare module BABYLON.GUI {
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _breakLines(refWidth: number, context: CanvasRenderingContext2D): object[];
         protected _parseLine(line: string | undefined, context: CanvasRenderingContext2D): object;
-        protected _parseLineWithTextWrapping(line: string | undefined, context: CanvasRenderingContext2D): object;
+        protected _parseLineEllipsis(line: string | undefined, width: number, context: CanvasRenderingContext2D): object;
+        protected _parseLineWordWrap(line: string | undefined, width: number, context: CanvasRenderingContext2D): object[];
         protected _renderLines(context: CanvasRenderingContext2D): void;
+        /**
+         * Given a width constraint applied on the text block, find the expected height
+         * @returns expected height
+         */
+        computeExpectedHeight(): number;
         dispose(): void;
     }
 }

+ 71 - 12
dist/preview release/gui/babylon.gui.js

@@ -4483,6 +4483,24 @@ var BABYLON;
     var GUI;
     (function (GUI) {
         /**
+         * Enum that determines the text-wrapping mode to use.
+         */
+        var TextWrapping;
+        (function (TextWrapping) {
+            /**
+             * Clip the text when it's larger than Control.width; this is the default mode.
+             */
+            TextWrapping[TextWrapping["Clip"] = 0] = "Clip";
+            /**
+             * Wrap the text word-wise, i.e. try to add line-breaks at word boundary to fit within Control.width.
+             */
+            TextWrapping[TextWrapping["WordWrap"] = 1] = "WordWrap";
+            /**
+             * Ellipsize the text, i.e. shrink with trailing … when text is larger than Control.width.
+             */
+            TextWrapping[TextWrapping["Ellipsis"] = 2] = "Ellipsis";
+        })(TextWrapping = GUI.TextWrapping || (GUI.TextWrapping = {}));
+        /**
          * Class used to create text block control
          */
         var TextBlock = /** @class */ (function (_super) {
@@ -4501,7 +4519,7 @@ var BABYLON;
                 var _this = _super.call(this, name) || this;
                 _this.name = name;
                 _this._text = "";
-                _this._textWrapping = false;
+                _this._textWrapping = TextWrapping.Clip;
                 _this._textHorizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
                 _this._textVerticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_CENTER;
                 _this._resizeToFit = false;
@@ -4563,7 +4581,7 @@ var BABYLON;
                     if (this._textWrapping === value) {
                         return;
                     }
-                    this._textWrapping = value;
+                    this._textWrapping = +value;
                     this._markAsDirty();
                 },
                 enumerable: true,
@@ -4734,37 +4752,59 @@ var BABYLON;
                 }
             };
             TextBlock.prototype._additionalProcessing = function (parentMeasure, context) {
-                this._lines = [];
+                this._lines = this._breakLines(this._currentMeasure.width, context);
+                this.onLinesReadyObservable.notifyObservers(this);
+            };
+            TextBlock.prototype._breakLines = function (refWidth, context) {
+                var lines = [];
                 var _lines = this.text.split("\n");
-                if (this._textWrapping && !this._resizeToFit) {
+                if (this._textWrapping === TextWrapping.Ellipsis && !this._resizeToFit) {
                     for (var _i = 0, _lines_1 = _lines; _i < _lines_1.length; _i++) {
                         var _line = _lines_1[_i];
-                        this._lines.push(this._parseLineWithTextWrapping(_line, context));
+                        lines.push(this._parseLineEllipsis(_line, refWidth, context));
                     }
                 }
-                else {
+                else if (this._textWrapping === TextWrapping.WordWrap && !this._resizeToFit) {
                     for (var _a = 0, _lines_2 = _lines; _a < _lines_2.length; _a++) {
                         var _line = _lines_2[_a];
-                        this._lines.push(this._parseLine(_line, context));
+                        lines.push.apply(lines, this._parseLineWordWrap(_line, refWidth, context));
                     }
                 }
-                this.onLinesReadyObservable.notifyObservers(this);
+                else {
+                    for (var _b = 0, _lines_3 = _lines; _b < _lines_3.length; _b++) {
+                        var _line = _lines_3[_b];
+                        lines.push(this._parseLine(_line, context));
+                    }
+                }
+                return lines;
             };
             TextBlock.prototype._parseLine = function (line, context) {
                 if (line === void 0) { line = ''; }
                 return { text: line, width: context.measureText(line).width };
             };
-            TextBlock.prototype._parseLineWithTextWrapping = function (line, context) {
+            TextBlock.prototype._parseLineEllipsis = function (line, width, context) {
                 if (line === void 0) { line = ''; }
+                var lineWidth = context.measureText(line).width;
+                if (lineWidth > width) {
+                    line += '…';
+                }
+                while (line.length > 2 && lineWidth > width) {
+                    line = line.slice(0, -2) + '…';
+                    lineWidth = context.measureText(line).width;
+                }
+                return { text: line, width: lineWidth };
+            };
+            TextBlock.prototype._parseLineWordWrap = function (line, width, context) {
+                if (line === void 0) { line = ''; }
+                var lines = [];
                 var words = line.split(' ');
-                var width = this._currentMeasure.width;
                 var lineWidth = 0;
                 for (var n = 0; n < words.length; n++) {
                     var testLine = n > 0 ? line + " " + words[n] : words[0];
                     var metrics = context.measureText(testLine);
                     var testWidth = metrics.width;
                     if (testWidth > width && n > 0) {
-                        this._lines.push({ text: line, width: lineWidth });
+                        lines.push({ text: line, width: lineWidth });
                         line = words[n];
                         lineWidth = context.measureText(line).width;
                     }
@@ -4773,7 +4813,8 @@ var BABYLON;
                         line = testLine;
                     }
                 }
-                return { text: line, width: lineWidth };
+                lines.push({ text: line, width: lineWidth });
+                return lines;
             };
             TextBlock.prototype._renderLines = function (context) {
                 var height = this._currentMeasure.height;
@@ -4814,6 +4855,24 @@ var BABYLON;
                     this.height = this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * this._lines.length + 'px';
                 }
             };
+            /**
+             * Given a width constraint applied on the text block, find the expected height
+             * @returns expected height
+             */
+            TextBlock.prototype.computeExpectedHeight = function () {
+                if (this.text && this.widthInPixels) {
+                    var context = document.createElement('canvas').getContext('2d');
+                    if (context) {
+                        this._applyStates(context);
+                        if (!this._fontOffset) {
+                            this._fontOffset = GUI.Control._GetFontOffset(context.font);
+                        }
+                        var lines = this._lines ? this._lines : this._breakLines(this.widthInPixels - this.paddingLeftInPixels - this.paddingRightInPixels, context);
+                        return this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * lines.length;
+                    }
+                }
+                return 0;
+            };
             TextBlock.prototype.dispose = function () {
                 _super.prototype.dispose.call(this);
                 this.onTextChangedObservable.clear();

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


+ 26 - 2
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1321,6 +1321,23 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     /**
+     * Enum that determines the text-wrapping mode to use.
+     */
+    enum TextWrapping {
+        /**
+         * Clip the text when it's larger than Control.width; this is the default mode.
+         */
+        Clip = 0,
+        /**
+         * Wrap the text word-wise, i.e. try to add line-breaks at word boundary to fit within Control.width.
+         */
+        WordWrap = 1,
+        /**
+         * Ellipsize the text, i.e. shrink with trailing … when text is larger than Control.width.
+         */
+        Ellipsis = 2,
+    }
+    /**
      * Class used to create text block control
      */
     class TextBlock extends Control {
@@ -1362,7 +1379,7 @@ declare module BABYLON.GUI {
         /**
          * Gets or sets a boolean indicating if text must be wrapped
          */
-        textWrapping: boolean;
+        textWrapping: TextWrapping | boolean;
         /**
          * Gets or sets text to display
          */
@@ -1421,9 +1438,16 @@ declare module BABYLON.GUI {
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _breakLines(refWidth: number, context: CanvasRenderingContext2D): object[];
         protected _parseLine(line: string | undefined, context: CanvasRenderingContext2D): object;
-        protected _parseLineWithTextWrapping(line: string | undefined, context: CanvasRenderingContext2D): object;
+        protected _parseLineEllipsis(line: string | undefined, width: number, context: CanvasRenderingContext2D): object;
+        protected _parseLineWordWrap(line: string | undefined, width: number, context: CanvasRenderingContext2D): object[];
         protected _renderLines(context: CanvasRenderingContext2D): void;
+        /**
+         * Given a width constraint applied on the text block, find the expected height
+         * @returns expected height
+         */
+        computeExpectedHeight(): number;
         dispose(): void;
     }
 }

+ 37 - 2
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 4233,
+  "errors": 4240,
   "babylon.typedoc.json": {
-    "errors": 4233,
+    "errors": 4240,
     "AbstractMesh": {
       "Property": {
         "showBoundingBox": {
@@ -5190,6 +5190,21 @@
             "NotPascalCase": true
           }
         },
+        "beginTransformFeedback": {
+          "Naming": {
+            "NotPascalCase": true
+          }
+        },
+        "bindTransformFeedback": {
+          "Naming": {
+            "NotPascalCase": true
+          }
+        },
+        "bindTransformFeedbackBuffer": {
+          "Naming": {
+            "NotPascalCase": true
+          }
+        },
         "createEffectForParticles": {
           "Naming": {
             "NotPascalCase": true
@@ -5200,11 +5215,21 @@
             "NotPascalCase": true
           }
         },
+        "createTransformFeedback": {
+          "Naming": {
+            "NotPascalCase": true
+          }
+        },
         "deleteQuery": {
           "Naming": {
             "NotPascalCase": true
           }
         },
+        "deleteTransformFeedback": {
+          "Naming": {
+            "NotPascalCase": true
+          }
+        },
         "endOcclusionQuery": {
           "Naming": {
             "NotPascalCase": true
@@ -5215,6 +5240,11 @@
             "NotPascalCase": true
           }
         },
+        "endTransformFeedback": {
+          "Naming": {
+            "NotPascalCase": true
+          }
+        },
         "getQueryResult": {
           "Naming": {
             "NotPascalCase": true
@@ -5225,6 +5255,11 @@
             "NotPascalCase": true
           }
         },
+        "setTranformFeedbackVaryings": {
+          "Naming": {
+            "NotPascalCase": true
+          }
+        },
         "startTimeQuery": {
           "Naming": {
             "NotPascalCase": true

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


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


+ 5 - 1
dist/preview release/what's new.md

@@ -25,11 +25,14 @@
   - Added support for life time gradients. [Doc](https://doc.babylonjs.com/babylon101/particles#lifetime)
   - Added support for angular speed gradients. [Doc](https://doc.babylonjs.com/babylon101/particles#rotation)
 - Added SceneComponent to help decoupling Scene from its components ([sebavan](http://www.github.com/sebavan))
+- Playground can now be used with TypeScript directly!. [Demo](https://www.babylonjs-playground.com/ts.html) ([Deltakosh](https://github.com/deltakosh), [NasimiAsl](https://github.com/NasimiAsl)) 
+- New GUI control: [InputPassword](https://doc.babylonjs.com/how_to/gui#inputpassword) ([theom](https://github.com/theom))
 
 ## Updates
 
 - All NPM packages have `latest`and `preview` streams [#3055](https://github.com/BabylonJS/Babylon.js/issues/3055) ([RaananW](https://github.com/RaananW))
 - Added New Tools Tab in the inspector (env texture and screenshot tools so far) ([sebavan](http://www.github.com/sebavan))
+- Added `TextBlock.computeExpectedHeight`, added `TextWrapping.Ellipsis` as `TextBlock.wordWrapping` possible value ([adrientetar](https://github.com/adrientetar))
 
 ### Core Engine
 
@@ -66,7 +69,7 @@
 - Added `RawCubeTexture` class with RGBD and mipmap support ([bghgary](http://www.github.com/bghgary))
 - Added effect layer per rendering group addressing [Issue 4463](https://github.com/BabylonJS/Babylon.js/issues/4463) ([sebavan](http://www.github.com/sebavan))
 - Added predicate function `targetMask` argument to `scene.beginWeightedAnimation`, `scene.beginAnimation`, `scene.stopAnimation`, and `animatable.stop` to allow for selective application of animations.  ([fmmoret](http://github.com/fmmoret))
-- Oculus GO and GearVR 3dof controllers will now rotate with the user if they turn around in their room ([TrevorDev](https://github.com/TrevorDev))
+- Oculus GO and GearVR 3dof controllers will now rotate with the user's head if they turn around in their room ([TrevorDev](https://github.com/TrevorDev))
 - Added onPoseUpdatedFromDeviceObservable to webVRCamera to detect when the camera's pose has been updated ([TrevorDev](https://github.com/TrevorDev))
 
 ### glTF Loader
@@ -123,6 +126,7 @@
 - Fixed support for R and RG texture formats ([sebavan](http://www.github.com/sebavan))
 - Fixed `updatable` parameter setting in the SPS ([jerome](https://github.com/jbousquie))
 - Angular and linear velocity were using the wrong method to copy values to the physics engine ([RaananW](https://github.com/RaananW))
+- Fixed env texture generation in Byte Mode ([sebavan](http://www.github.com/sebavan))
 - Oimo.js now receives quaternion and not euler when a body is being constructed ([RaananW](https://github.com/RaananW))
 
 ### Viewer

+ 16 - 0
gui/src/2D/controls/inputPassword.ts

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

+ 9 - 5
gui/src/2D/controls/inputText.ts

@@ -239,7 +239,7 @@ module BABYLON.GUI {
             // Specific cases
             switch (keyCode) {
                 case 32: //SPACE
-                    key = " "; //ie11 key for space is "Spacebar" 
+                    key = " "; //ie11 key for space is "Spacebar"
                     break;
                 case 8: // BACKSPACE
                     if (this._text && this._text.length > 0) {
@@ -310,7 +310,7 @@ module BABYLON.GUI {
             }
         }
 
-        /** @hidden */       
+        /** @hidden */
         public processKeyboard(evt: KeyboardEvent): void {
             this.processKey(evt.keyCode, evt.key);
         }
@@ -357,7 +357,7 @@ module BABYLON.GUI {
                     context.fillStyle = this.color;
                 }
 
-                let text = this._text;
+                let text = this._beforeRenderText(this._text);
 
                 if (!this._isFocused && !this._text && this._placeholderText) {
                     text = this._placeholderText;
@@ -460,7 +460,7 @@ module BABYLON.GUI {
             context.restore();
         }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
+        public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
             if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
                 return false;
             }
@@ -477,10 +477,14 @@ module BABYLON.GUI {
             return true;
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
             super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
         }
 
+        protected _beforeRenderText(text: string): string {
+            return text;
+        }
+
         public dispose() {
             super.dispose();
 

+ 79 - 13
gui/src/2D/controls/textBlock.ts

@@ -2,11 +2,31 @@
 
 module BABYLON.GUI {
     /**
+     * Enum that determines the text-wrapping mode to use.
+     */
+    export enum TextWrapping {
+        /**
+         * Clip the text when it's larger than Control.width; this is the default mode.
+         */
+        Clip = 0,
+
+        /**
+         * Wrap the text word-wise, i.e. try to add line-breaks at word boundary to fit within Control.width.
+         */
+        WordWrap = 1,
+
+        /**
+         * Ellipsize the text, i.e. shrink with trailing … when text is larger than Control.width.
+         */
+        Ellipsis,
+    }
+
+    /**
      * Class used to create text block control
      */
     export class TextBlock extends Control {
         private _text = "";
-        private _textWrapping = false;
+        private _textWrapping = TextWrapping.Clip;
         private _textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
         private _textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
 
@@ -54,18 +74,18 @@ module BABYLON.GUI {
         /**
          * Gets or sets a boolean indicating if text must be wrapped
          */
-        public get textWrapping(): boolean {
+        public get textWrapping(): TextWrapping | boolean {
             return this._textWrapping;
         }
 
         /**
          * Gets or sets a boolean indicating if text must be wrapped
          */        
-        public set textWrapping(value: boolean) {
+        public set textWrapping(value: TextWrapping | boolean) {
             if (this._textWrapping === value) {
                 return;
             }
-            this._textWrapping = value;
+            this._textWrapping = +value;
             this._markAsDirty();
         }
 
@@ -249,29 +269,54 @@ module BABYLON.GUI {
         }
 
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            this._lines = [];
+            this._lines = this._breakLines(this._currentMeasure.width, context);
+            this.onLinesReadyObservable.notifyObservers(this);
+        }
+
+        protected _breakLines(refWidth: number, context: CanvasRenderingContext2D): object[] {
+            var lines = [];
             var _lines = this.text.split("\n");
 
-            if (this._textWrapping && !this._resizeToFit) {
+            if (this._textWrapping === TextWrapping.Ellipsis && !this._resizeToFit) {
+                for (var _line of _lines) {
+                    lines.push(this._parseLineEllipsis(_line, refWidth, context));
+                }
+            } else if (this._textWrapping === TextWrapping.WordWrap && !this._resizeToFit) {
                 for (var _line of _lines) {
-                    this._lines.push(this._parseLineWithTextWrapping(_line, context));
+                    lines.push(...this._parseLineWordWrap(_line, refWidth, context));
                 }
             } else {
                 for (var _line of _lines) {
-                    this._lines.push(this._parseLine(_line, context));
+                    lines.push(this._parseLine(_line, context));
                 }
             }
 
-            this.onLinesReadyObservable.notifyObservers(this);
+            return lines;
         }
 
         protected _parseLine(line: string = '', context: CanvasRenderingContext2D): object {
             return { text: line, width: context.measureText(line).width };
         }
 
-        protected _parseLineWithTextWrapping(line: string = '', context: CanvasRenderingContext2D): object {
+        protected _parseLineEllipsis(line: string = '', width: number,
+                                     context: CanvasRenderingContext2D): object {
+            var lineWidth = context.measureText(line).width;
+
+            if (lineWidth > width) {
+                line += '…';
+            }
+            while (line.length > 2 && lineWidth > width) {
+                line = line.slice(0, -2) + '…';
+                lineWidth = context.measureText(line).width;
+            }
+
+            return { text: line, width: lineWidth };
+        }
+
+        protected _parseLineWordWrap(line: string = '', width: number,
+                                     context: CanvasRenderingContext2D): object[] {
+            var lines = [];
             var words = line.split(' ');
-            var width = this._currentMeasure.width;
             var lineWidth = 0;
 
             for (var n = 0; n < words.length; n++) {
@@ -279,7 +324,7 @@ module BABYLON.GUI {
                 var metrics = context.measureText(testLine);
                 var testWidth = metrics.width;
                 if (testWidth > width && n > 0) {
-                    this._lines.push({ text: line, width: lineWidth });
+                    lines.push({ text: line, width: lineWidth });
                     line = words[n];
                     lineWidth = context.measureText(line).width;
                 }
@@ -288,8 +333,9 @@ module BABYLON.GUI {
                     line = testLine;
                 }
             }
+            lines.push({ text: line, width: lineWidth });
 
-            return { text: line, width: lineWidth };
+            return lines;
         }
 
         protected _renderLines(context: CanvasRenderingContext2D): void {
@@ -339,6 +385,26 @@ module BABYLON.GUI {
             }
         }
 
+        /**
+         * Given a width constraint applied on the text block, find the expected height
+         * @returns expected height
+         */
+        public computeExpectedHeight(): number {
+            if (this.text && this.widthInPixels) {
+                const context = document.createElement('canvas').getContext('2d');
+                if (context) {
+                    this._applyStates(context);
+                    if (!this._fontOffset) {
+                        this._fontOffset = Control._GetFontOffset(context.font);
+                    }
+                    const lines = this._lines ? this._lines : this._breakLines(
+                        this.widthInPixels - this.paddingLeftInPixels - this.paddingRightInPixels, context);
+                    return this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * lines.length;
+                }
+            }
+            return 0;
+        }
+
         dispose(): void {
             super.dispose();
 

+ 27 - 0
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -1168,6 +1168,18 @@ module BABYLON.GLTF2 {
             });
         }
 
+        private getRootNodes(babylonScene: Scene, nodes: TransformNode[], shouldExportTransformNode: (babylonTransformNode: TransformNode) => boolean): TransformNode[] {
+            const rootNodes: TransformNode[] = [];
+            for (let babylonTransformNode of nodes) {
+                if (shouldExportTransformNode(babylonTransformNode)) {
+                    if (babylonTransformNode.parent == null) {
+                        rootNodes.push(babylonTransformNode);
+                    }
+                }
+            }
+            return rootNodes;
+        }
+
         /**
          * Creates a mapping of Node unique id to node index and handles animations
          * @param babylonScene Babylon Scene
@@ -1187,9 +1199,24 @@ module BABYLON.GLTF2 {
             let idleGLTFAnimations: IAnimation[] = [];
             let node: INode;
 
+            let negScaleRootNode: Nullable<TransformNode> = null;
+
+            const rootNodes = this.getRootNodes(babylonScene, nodes, shouldExportTransformNode);
+            if (rootNodes.length === 1) {
+                const node = rootNodes[0];
+                if (node.scaling.equalsToFloats(1,1, -1)) {
+                    this._convertToRightHandedSystem = !this._convertToRightHandedSystem;
+                    negScaleRootNode = node;
+                }  
+            }
+
             for (let babylonTransformNode of nodes) {
                 if (shouldExportTransformNode(babylonTransformNode)) {
                     node = this.createNode(babylonTransformNode, binaryWriter);
+                    if (negScaleRootNode && babylonTransformNode === negScaleRootNode) {
+                        node.scale = [1,1,1];
+                        node.rotation = [0,0,0,1];
+                    }
 
                     this._nodes.push(node);
                     nodeIndex = this._nodes.length - 1;

+ 6 - 1
src/Behaviors/Mesh/babylon.pointerDragBehavior.ts

@@ -7,6 +7,7 @@ module BABYLON {
         private _dragPlane: Mesh;
         private _scene:Scene;
         private _pointerObserver:Nullable<Observer<PointerInfo>>;
+        private _beforeRenderObserver:Nullable<Observer<Scene>>;
         private static _planeScene:Scene;
         /**
          * The maximum tolerated angle between the drag plane and dragging pointer rays to trigger pointer events. Set to 0 to allow any angle (default: 0)
@@ -119,6 +120,7 @@ module BABYLON {
                     PointerDragBehavior._planeScene = this._scene;
                 }else{
                     PointerDragBehavior._planeScene = new BABYLON.Scene(this._scene.getEngine());
+                    PointerDragBehavior._planeScene.detachControl();
                     this._scene.getEngine().scenes.pop();
                 }
             }
@@ -187,7 +189,7 @@ module BABYLON {
                 }
             });
 
-            this._scene.onBeforeRenderObservable.add(()=>{
+            this._beforeRenderObserver = this._scene.onBeforeRenderObservable.add(()=>{
                 if(this._moving && this.moveAttached){
                     // Slowly move mesh to avoid jitter
                     targetPosition.subtractToRef((<Mesh>this._attachedNode).absolutePosition, this._tmpVector);
@@ -294,6 +296,9 @@ module BABYLON {
             if(this._pointerObserver){
                 this._scene.onPointerObservable.remove(this._pointerObserver);
             }
+            if(this._beforeRenderObserver){
+                this._scene.onBeforeRenderObservable.remove(this._beforeRenderObserver);
+            }
         }
     }
 }

+ 1 - 3
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -167,7 +167,6 @@ module BABYLON {
 
         public _setLaserPointerParent(mesh:AbstractMesh){
             var makeNotPick = (root: AbstractMesh) => {
-                root.name += " laserPointer";
                 root.isPickable = false;
                 root.getChildMeshes().forEach((c) => {
                     makeNotPick(c);
@@ -931,8 +930,7 @@ module BABYLON {
                 this._raySelectionPredicate = (mesh) => {
                     if (this._isTeleportationFloor(mesh) || (mesh.name.indexOf("gazeTracker") === -1
                         && mesh.name.indexOf("teleportationTarget") === -1
-                        && mesh.name.indexOf("torusTeleportation") === -1
-                        && mesh.name.indexOf("laserPointer") === -1)) {
+                        && mesh.name.indexOf("torusTeleportation") === -1)) {
                         return this.raySelectionPredicate(mesh);
                     }
                     return false;

+ 58 - 0
src/Engine/Extensions/babylon.engine.occlusionQuery.ts

@@ -247,4 +247,62 @@ module BABYLON {
     Engine.prototype._getGlAlgorithmType = function(algorithmType: number): number {
         return algorithmType === AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE ? this._gl.ANY_SAMPLES_PASSED_CONSERVATIVE : this._gl.ANY_SAMPLES_PASSED;
     }
+
+    // We also need to update AbstractMesh as there is a portion of the code there
+    AbstractMesh.prototype._checkOcclusionQuery = function() {
+        var engine = this.getEngine();
+
+        if (!engine.isQueryResultAvailable) { // Occlusion query where not referenced
+            this._isOccluded = false;
+            return;
+        }
+
+        if (engine.webGLVersion < 2 || this.occlusionType === AbstractMesh.OCCLUSION_TYPE_NONE) {
+            this._isOccluded = false;
+            return;
+        }
+
+        if (this.isOcclusionQueryInProgress && this._occlusionQuery) {
+
+            var isOcclusionQueryAvailable = engine.isQueryResultAvailable(this._occlusionQuery);
+            if (isOcclusionQueryAvailable) {
+                var occlusionQueryResult = engine.getQueryResult(this._occlusionQuery);
+
+                this._isOcclusionQueryInProgress = false;
+                this._occlusionInternalRetryCounter = 0;
+                this._isOccluded = occlusionQueryResult === 1 ? false : true;
+            }
+            else {
+
+                this._occlusionInternalRetryCounter++;
+
+                if (this.occlusionRetryCount !== -1 && this._occlusionInternalRetryCounter > this.occlusionRetryCount) {
+                    this._isOcclusionQueryInProgress = false;
+                    this._occlusionInternalRetryCounter = 0;
+
+                    // if optimistic set isOccluded to false regardless of the status of isOccluded. (Render in the current render loop)
+                    // if strict continue the last state of the object.
+                    this._isOccluded = this.occlusionType === AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC ? false : this._isOccluded;
+                }
+                else {
+                    return;
+                }
+
+            }
+        }
+
+        var scene = this.getScene();
+        if (scene.getBoundingBoxRenderer) {
+        var occlusionBoundingBoxRenderer = scene.getBoundingBoxRenderer();
+
+            if (!this._occlusionQuery) {
+                this._occlusionQuery = engine.createQuery();
+            }
+
+            engine.beginOcclusionQuery(this.occlusionQueryAlgorithmType, this._occlusionQuery);
+            occlusionBoundingBoxRenderer.renderOcclusionBoundingBox(this);
+            engine.endOcclusionQuery(this.occlusionQueryAlgorithmType);
+            this._isOcclusionQueryInProgress = true;
+        }
+    } 
 }

+ 74 - 0
src/Engine/Extensions/babylon.engine.transformFeedback.ts

@@ -0,0 +1,74 @@
+module BABYLON {
+    export interface Engine {
+        /**
+         * Creates a webGL transform feedback object
+         * Please makes sure to check webGLVersion property to check if you are running webGL 2+
+         * @returns the webGL transform feedback object
+         */
+        createTransformFeedback(): WebGLTransformFeedback;      
+        
+        /**
+         * Delete a webGL transform feedback object 
+         * @param value defines the webGL transform feedback object to delete
+         */
+        deleteTransformFeedback(value: WebGLTransformFeedback): void; 
+
+        /**
+         * Bind a webGL transform feedback object to the webgl context
+         * @param value defines the webGL transform feedback object to bind
+         */        
+        bindTransformFeedback(value: Nullable<WebGLTransformFeedback>): void;
+
+        /**
+         * Begins a transform feedback operation
+         * @param usePoints defines if points or triangles must be used
+         */              
+        beginTransformFeedback(usePoints: boolean): void;
+
+        /**
+         * Ends a transform feedback operation
+         */           
+        endTransformFeedback(): void;
+
+        /**
+         * Specify the varyings to use with transform feedback
+         * @param program defines the associated webGL program
+         * @param value defines the list of strings representing the varying names
+         */
+        setTranformFeedbackVaryings(program: WebGLProgram, value: string[]): void;
+        
+        /**
+         * Bind a webGL buffer for a transform feedback operation
+         * @param value defines the webGL buffer to bind
+         */          
+        bindTransformFeedbackBuffer(value: Nullable<WebGLBuffer>): void;
+    }
+
+    Engine.prototype.createTransformFeedback = function(): WebGLTransformFeedback {
+        return this._gl.createTransformFeedback();
+    }
+
+    Engine.prototype.deleteTransformFeedback = function(value: WebGLTransformFeedback): void {
+        this._gl.deleteTransformFeedback(value);
+    }
+
+    Engine.prototype.bindTransformFeedback = function(value: Nullable<WebGLTransformFeedback>): void {
+        this._gl.bindTransformFeedback(this._gl.TRANSFORM_FEEDBACK, value);
+    }
+
+    Engine.prototype.beginTransformFeedback = function(usePoints: boolean = true): void {
+        this._gl.beginTransformFeedback(usePoints ? this._gl.POINTS : this._gl.TRIANGLES);
+    }
+
+    Engine.prototype.endTransformFeedback = function(): void {
+        this._gl.endTransformFeedback();
+    }
+
+    Engine.prototype.setTranformFeedbackVaryings = function(program: WebGLProgram, value: string[]): void {
+        this._gl.transformFeedbackVaryings(program, value, this._gl.INTERLEAVED_ATTRIBS);
+    }
+
+    Engine.prototype.bindTransformFeedbackBuffer = function(value: Nullable<WebGLBuffer>): void {
+        this._gl.bindBufferBase(this._gl.TRANSFORM_FEEDBACK_BUFFER, 0, value);
+    }
+}

+ 0 - 59
src/Engine/babylon.engine.ts

@@ -7219,65 +7219,6 @@
             return this._gl.RGBA8;
         };
 
-        // Transform feedback
-
-        /**
-         * Creates a webGL transform feedback object
-         * Please makes sure to check webGLVersion property to check if you are running webGL 2+
-         * @returns the webGL transform feedback object
-         */
-        public createTransformFeedback(): WebGLTransformFeedback {
-            return this._gl.createTransformFeedback();
-        }
-
-        /**
-         * Delete a webGL transform feedback object 
-         * @param value defines the webGL transform feedback object to delete
-         */
-        public deleteTransformFeedback(value: WebGLTransformFeedback): void {
-            this._gl.deleteTransformFeedback(value);
-        }
-
-        /**
-         * Bind a webGL transform feedback object to the webgl context
-         * @param value defines the webGL transform feedback object to bind
-         */        
-        public bindTransformFeedback(value: Nullable<WebGLTransformFeedback>): void {
-            this._gl.bindTransformFeedback(this._gl.TRANSFORM_FEEDBACK, value);
-        }
-
-        /**
-         * Begins a transform feedback operation
-         * @param usePoints defines if points or triangles must be used
-         */              
-        public beginTransformFeedback(usePoints: boolean = true): void {
-            this._gl.beginTransformFeedback(usePoints ? this._gl.POINTS : this._gl.TRIANGLES);
-        }
-
-        /**
-         * Ends a transform feedback operation
-         */           
-        public endTransformFeedback(): void {
-            this._gl.endTransformFeedback();
-        }
-
-        /**
-         * Specify the varyings to use with transform feedback
-         * @param program defines the associated webGL program
-         * @param value defines the list of strings representing the varying names
-         */
-        public setTranformFeedbackVaryings(program: WebGLProgram, value: string[]): void {
-            this._gl.transformFeedbackVaryings(program, value, this._gl.INTERLEAVED_ATTRIBS);
-        }
-
-        /**
-         * Bind a webGL buffer for a transform feedback operation
-         * @param value defines the webGL buffer to bind
-         */          
-        public bindTransformFeedbackBuffer(value: Nullable<WebGLBuffer>): void {
-            this._gl.bindBufferBase(this._gl.TRANSFORM_FEEDBACK_BUFFER, 0, value);
-        }
-
         /** @hidden */
         public _loadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, database?: Database, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
             let request = Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);

+ 7 - 2
src/Materials/babylon.materialHelper.ts

@@ -236,8 +236,13 @@ module BABYLON {
                     if (mesh && mesh.receiveShadows && scene.shadowsEnabled && light.shadowEnabled) {
                         var shadowGenerator = light.getShadowGenerator();
                         if (shadowGenerator) {
-                            shadowEnabled = true;
-                            shadowGenerator.prepareDefines(defines, lightIndex);
+                            const shadowMap = shadowGenerator.getShadowMapForRendering();
+                            if (shadowMap) {
+                                if (shadowMap.renderList && shadowMap.renderList.length > 0) {
+                                    shadowEnabled = true;
+                                    shadowGenerator.prepareDefines(defines, lightIndex);
+                                }
+                            }
                         }
                     }
 

+ 10 - 55
src/Mesh/babylon.abstractMesh.ts

@@ -205,9 +205,11 @@
         * @see http://doc.babylonjs.com/features/occlusionquery
         */
         public occlusionRetryCount = -1;
-        private _occlusionInternalRetryCounter = 0;
+        /** @hidden */
+        public _occlusionInternalRetryCounter = 0;
 
-        protected _isOccluded = false;
+        /** @hidden */
+        public _isOccluded = false;
 
         /**
         * Gets or sets whether the mesh is occluded or not, it is used also to set the intial state of the mesh to be occluded or not
@@ -221,7 +223,8 @@
             this._isOccluded = value;
         }
 
-        private _isOcclusionQueryInProgress = false;
+        /** @hidden */
+        public _isOcclusionQueryInProgress = false;
 
         /**
          * Flag to check the progress status of the query
@@ -231,7 +234,8 @@
             return this._isOcclusionQueryInProgress;
         }
 
-        private _occlusionQuery: Nullable<WebGLQuery>;
+        /** @hidden */
+        public _occlusionQuery: Nullable<WebGLQuery>;
 
         private _visibility = 1.0;
 
@@ -2104,57 +2108,8 @@
         }
 
         /** @hidden */
-        protected _checkOcclusionQuery() {
-            var engine = this.getEngine();
-
-            if (engine.webGLVersion < 2 || this.occlusionType === AbstractMesh.OCCLUSION_TYPE_NONE) {
-                this._isOccluded = false;
-                return;
-            }
-
-            if (this.isOcclusionQueryInProgress && this._occlusionQuery) {
-
-                var isOcclusionQueryAvailable = engine.isQueryResultAvailable(this._occlusionQuery);
-                if (isOcclusionQueryAvailable) {
-                    var occlusionQueryResult = engine.getQueryResult(this._occlusionQuery);
-
-                    this._isOcclusionQueryInProgress = false;
-                    this._occlusionInternalRetryCounter = 0;
-                    this._isOccluded = occlusionQueryResult === 1 ? false : true;
-                }
-                else {
-
-                    this._occlusionInternalRetryCounter++;
-
-                    if (this.occlusionRetryCount !== -1 && this._occlusionInternalRetryCounter > this.occlusionRetryCount) {
-                        this._isOcclusionQueryInProgress = false;
-                        this._occlusionInternalRetryCounter = 0;
-
-                        // if optimistic set isOccluded to false regardless of the status of isOccluded. (Render in the current render loop)
-                        // if strict continue the last state of the object.
-                        this._isOccluded = this.occlusionType === AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC ? false : this._isOccluded;
-                    }
-                    else {
-                        return;
-                    }
-
-                }
-            }
-
-            // Todo. Move into an occlusion query component.
-            var scene = this.getScene();
-            if (scene.getBoundingBoxRenderer) {
-               var occlusionBoundingBoxRenderer = scene.getBoundingBoxRenderer();
-
-                if (!this._occlusionQuery) {
-                    this._occlusionQuery = engine.createQuery();
-                }
-
-                engine.beginOcclusionQuery(this.occlusionQueryAlgorithmType, this._occlusionQuery);
-                occlusionBoundingBoxRenderer.renderOcclusionBoundingBox(this);
-                engine.endOcclusionQuery(this.occlusionQueryAlgorithmType);
-                this._isOcclusionQueryInProgress = true;
-            }
+        public _checkOcclusionQuery() { // Will be replaced by correct code if Occlusion queries are referenced
+            this._isOccluded = false;
         }
     }
 }

+ 1 - 1
src/Particles/babylon.gpuParticleSystem.ts

@@ -1211,7 +1211,7 @@
             // Update
             this._engine.bindTransformFeedbackBuffer(this._targetBuffer.getBuffer());
             this._engine.setRasterizerState(false);
-            this._engine.beginTransformFeedback();
+            this._engine.beginTransformFeedback(true);
             this._engine.drawArraysType(Material.PointListDrawMode, 0, this._currentActiveCount);
             this._engine.endTransformFeedback();
             this._engine.setRasterizerState(true);

+ 4 - 0
src/Tools/babylon.environmentTextureTools.ts

@@ -141,6 +141,10 @@ module BABYLON {
                 return Promise.reject("Env texture can only be created when the engine is created with the premultipliedAlpha option set to false.");
             }
 
+            if (texture.textureType === Engine.TEXTURETYPE_UNSIGNED_INT) {
+                return Promise.reject("The cube texture should allow HDR (Full Float or Half Float).");
+            }
+
             let canvas = engine.getRenderingCanvas();
             if (!canvas) {
                 return Promise.reject("Env texture can only be created when the engine is associated to a canvas.");

+ 0 - 4
src/Tools/babylon.sceneOptimizer.ts

@@ -378,10 +378,6 @@
                 return false;
             }
 
-            if (mesh.parent) {
-                return false;
-            }
-
             return true;
         }
 

+ 1 - 1
src/Tools/babylon.tools.ts

@@ -197,7 +197,7 @@
         }
 
         public static SetImmediate(action: () => void) {
-            if (window.setImmediate) {
+            if (Tools.IsWindowObjectExist() && window.setImmediate) {
                 window.setImmediate(action);
             } else {
                 setTimeout(action, 1);

+ 128 - 35
tests/nullEngine/app.js

@@ -174,50 +174,143 @@ var engine = new BABYLON.NullEngine();
 // scene.render();
 // engine.dispose();
 
-var scene = new BABYLON.Scene(engine);
-var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(20, 20, 100), scene);
+// var scene = new BABYLON.Scene(engine);
+// var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(20, 20, 100), scene);
 
-var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 100, BABYLON.Vector3.Zero(), scene);
+// var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 100, BABYLON.Vector3.Zero(), scene);
 
-var assetsManager = new BABYLON.AssetsManager(scene);
-var meshTask = assetsManager.addMeshTask("skull task", "", "https://raw.githubusercontent.com/RaggarDK/Baby/baby/", "he4.babylon");
+// var assetsManager = new BABYLON.AssetsManager(scene);
+// var meshTask = assetsManager.addMeshTask("skull task", "", "https://raw.githubusercontent.com/RaggarDK/Baby/baby/", "he4.babylon");
+
+// meshTask.onSuccess = function (task) {
+//     
+//     //0 = ground plane, 1,2,3 = boxes
+//     for(var i=1;i<task.loadedMeshes.length;i++){
+//         var mesh = task.loadedMeshes[i];
+//         //mesh.computeWorldMatrix(true);
+
+//         var position = mesh.position.clone();
+//         var rotation = mesh.rotationQuaternion.clone();
+//         var scaling = mesh.getBoundingInfo().boundingBox.extendSize;
+//         var centerWorld = mesh.getBoundingInfo().boundingBox.centerWorld;
+//         console.log(position);
+//         console.log(mesh.getBoundingInfo());
+
+//         var box = BABYLON.MeshBuilder.CreateBox("box"+i,{height:2,width:2,depth:2});
+//         box.scaling.copyFromFloats(scaling.x,scaling.y,scaling.z);    
+//         box.rotationQuaternion = rotation;
+//         //box.position = position;
+//         box.position.set(centerWorld.x,centerWorld.y,centerWorld.z);
+
+//         var material = new BABYLON.StandardMaterial("mat", scene);
+//         material.diffuseColor = new BABYLON.Color3(0.5,1,0.5); 
+//         box.material = material;       
 
-meshTask.onSuccess = function (task) {
-    
-    //0 = ground plane, 1,2,3 = boxes
-    for(var i=1;i<task.loadedMeshes.length;i++){
-        var mesh = task.loadedMeshes[i];
-        //mesh.computeWorldMatrix(true);
+//     }
 
-        var position = mesh.position.clone();
-        var rotation = mesh.rotationQuaternion.clone();
-        var scaling = mesh.getBoundingInfo().boundingBox.extendSize;
-        var centerWorld = mesh.getBoundingInfo().boundingBox.centerWorld;
-        console.log(position);
-        console.log(mesh.getBoundingInfo());
+// }	
 
-        var box = BABYLON.MeshBuilder.CreateBox("box"+i,{height:2,width:2,depth:2});
-        box.scaling.copyFromFloats(scaling.x,scaling.y,scaling.z);    
-        box.rotationQuaternion = rotation;
-        //box.position = position;
-        box.position.set(centerWorld.x,centerWorld.y,centerWorld.z);
+// scene.registerBeforeRender(function () {
+//     light.position = camera.position;
+// });
 
-        var material = new BABYLON.StandardMaterial("mat", scene);
-        material.diffuseColor = new BABYLON.Color3(0.5,1,0.5); 
-        box.material = material;       
+// assetsManager.onFinish = function (tasks) {
+//     engine.runRenderLoop(function () {
+//         scene.render();
+//     });
+// };
 
-    }
+// assetsManager.load();
+
+var scene = new BABYLON.Scene(engine);
+var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 1,  Math.PI / 1, 5, BABYLON.Vector3.Zero(), scene);
+camera.setPosition(new BABYLON.Vector3(-800,1200,-2000));
+camera.setTarget(BABYLON.Vector3.Zero());
+var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
+light.intensity = 1;
+
+
+function createPart(name,opt,parent){
 
-}	
+    var part = BABYLON.MeshBuilder.CreateBox(name, opt.size, scene);
+    part.position = new BABYLON.Vector3(opt.pos.x, opt.pos.y, opt.pos.z);
 
-scene.registerBeforeRender(function () {
-    light.position = camera.position;
-});
+    let mate = new BABYLON.StandardMaterial('mat-'+name, scene);
 
-assetsManager.onFinish = function (tasks) {
-    engine.runRenderLoop(function () {
-        scene.render();
+    if(parent) {
+        mate.specularPower = 200;
+        mate.specularColor = new BABYLON.Color3(0.5, 0.5, 0.5);
+        mate.diffuseTexture = new BABYLON.Texture(opt.mat.url,scene);
+        mate.diffuseTexture.wAng = opt.mat.grain*Math.PI/180;
+        part.parent = parent;
+    }else{
+        mate.alpha = 0;
+    }
+
+    part.material = mate;
+
+    return part;
+}
+
+
+
+var parent;
+
+function createUnit(x,y,z,b){
+
+    var item = {
+        size:{width:x,depth:y,height:z},
+        pos:{x:0,y:0,z:0},
+        mat:{url:false,grain:0},
+        child:{
+            left:{
+                size:{width:b,depth:y,height:z},
+                pos:{x:-(x-b)/2,y:0,z:0},
+                mat:{url:"/playground/textures/crate.png",grain:90}
+            },
+            right:{
+                size:{width:b,depth:y,height:z},
+                pos:{x:(x-b)/2,y:0,z:0},
+                mat:{url:"/playground/textures/crate.png",grain:90}
+            },
+            top:{
+                size:{width:x-(b*2),depth:y,height:b},
+                pos:{x:0,y:(z-b-1)/2,z:0},
+                mat:{url:"/playground/textures/albedo.png",grain:0}
+            },
+            bottom:{
+                size:{width:x-(b*2),depth:y,height:b},
+                pos:{x:0,y:-(z-b-1)/2,z:0},
+                mat:{url:"/playground/textures/albedo.png",grain:0}
+            },
+            back:{
+                size:{width:x-(b*2),depth:b,height:z-(b*2)-1},
+                pos:{x:0,y:0,z:(y-b)/2-20},
+                mat:{url:"/playground/textures/albedo.png",grain:0}
+            },
+            shelf:{
+                size:{width:x-(b*2)-1,depth:y-b-30,height:b},
+                pos:{x:0,y:0,z:-((b+20)/2)+5},
+                mat:{url:"textures/crate.png",grain:45}
+            }
+        }
+    };
+
+    if(parent){
+        parent.dispose();
+    }
+    
+    parent = createPart("Unit",item,false);
+
+    Object.keys(item.child).forEach(function(key) {
+        createPart(key,item.child[key],parent);
     });
-};
 
-assetsManager.load();
+    return item;
+}
+
+createUnit(600,300,900,18);
+
+
+var serialized = BABYLON.SceneSerializer.SerializeMesh(parent, true, true);
+console.log(serialized);

BIN
tests/validation/ReferenceImages/dds.png


+ 1 - 1
tests/validation/config.json

@@ -483,7 +483,7 @@
     },
     {
       "title": "DDS",
-      "playgroundId": "#ZI77S7#2",
+      "playgroundId": "#ZI77S7#3",
       "referenceImage": "dds.png"
     }
   ]