Pārlūkot izejas kodu

Merge branch 'master' into boundingBoxRotateThroughBox

Trevor Baron 6 gadi atpakaļ
vecāks
revīzija
ad1e128082
60 mainītis faili ar 13436 papildinājumiem un 11462 dzēšanām
  1. 5695 5537
      Playground/babylon.d.txt
  2. 3 1
      Tools/Gulp/config.json
  3. 5684 5563
      dist/preview release/babylon.d.ts
  4. 1 1
      dist/preview release/babylon.js
  5. 283 20
      dist/preview release/babylon.max.js
  6. 283 20
      dist/preview release/babylon.no-module.max.js
  7. 1 1
      dist/preview release/babylon.worker.js
  8. 285 22
      dist/preview release/es6.js
  9. 47 10
      dist/preview release/gui/babylon.gui.d.ts
  10. 1 1
      dist/preview release/gui/babylon.gui.js
  11. 1 1
      dist/preview release/gui/babylon.gui.min.js
  12. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  13. 96 22
      dist/preview release/gui/babylon.gui.module.d.ts
  14. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  15. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  16. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.js
  17. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  18. 2 2
      dist/preview release/loaders/babylonjs.loaders.js
  19. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  20. 2 0
      dist/preview release/materialsLibrary/babylon.gridMaterial.d.ts
  21. 43 5
      dist/preview release/materialsLibrary/babylon.gridMaterial.js
  22. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.min.js
  23. 1 0
      dist/preview release/materialsLibrary/babylon.normalMaterial.d.ts
  24. 9 8
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  25. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  26. 3 0
      dist/preview release/materialsLibrary/babylonjs.materials.d.ts
  27. 52 13
      dist/preview release/materialsLibrary/babylonjs.materials.js
  28. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  29. 3 0
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  30. 19 5
      dist/preview release/viewer/babylon.viewer.d.ts
  31. 1 1
      dist/preview release/viewer/babylon.viewer.js
  32. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  33. 22 5
      dist/preview release/viewer/babylon.viewer.module.d.ts
  34. 129 119
      dist/preview release/what's new.md
  35. 59 2
      gui/src/2D/advancedDynamicTexture.ts
  36. 6 0
      gui/src/2D/controls/container.ts
  37. 12 2
      gui/src/2D/controls/control.ts
  38. 245 2
      gui/src/2D/controls/inputText.ts
  39. 2 2
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  40. 46 4
      materialsLibrary/src/grid/babylon.gridmaterial.ts
  41. 17 4
      materialsLibrary/src/grid/grid.fragment.fx
  42. 29 0
      materialsLibrary/src/grid/grid.vertex.fx
  43. 9 7
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  44. 7 14
      materialsLibrary/src/normal/normal.fragment.fx
  45. 0 10
      materialsLibrary/src/normal/normal.vertex.fx
  46. 23 28
      materialsLibrary/test/addgrid.js
  47. 16 4
      src/Animations/babylon.animationGroup.ts
  48. 49 0
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  49. 6 4
      src/Culling/babylon.ray.ts
  50. 7 0
      src/Engine/babylon.engine.ts
  51. 57 0
      src/Events/babylon.clipboardEvents.ts
  52. 11 4
      src/Materials/Textures/babylon.texture.ts
  53. 7 2
      src/Materials/babylon.material.ts
  54. 8 0
      src/Mesh/babylon.abstractMesh.ts
  55. 8 0
      src/Mesh/babylon.instancedMesh.ts
  56. 20 0
      src/Morph/babylon.morphTarget.ts
  57. 63 0
      src/PostProcess/babylon.passPostProcess.ts
  58. 27 0
      src/Shaders/passCube.fragment.fx
  59. 3 3
      src/Shaders/pbr.fragment.fx
  60. 20 0
      src/babylon.scene.ts

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 5695 - 5537
Playground/babylon.d.txt


+ 3 - 1
Tools/Gulp/config.json

@@ -158,6 +158,7 @@
                 "../../src/babylon.types.js",
                 "../../src/Events/babylon.keyboardEvents.js",
                 "../../src/Events/babylon.pointerEvents.js",
+                "../../src/Events/babylon.clipboardEvents.js",
                 "../../src/Tools/babylon.tools.js",
                 "../../src/Math/babylon.math.js",
                 "../../src/Math/babylon.math.scalar.js",
@@ -794,7 +795,8 @@
             ],
             "shaders": [
                 "postprocess.vertex",
-                "pass.fragment"
+                "pass.fragment",
+                "passCube.fragment"
             ]
         },
         "additionalPostProcess_blur": {

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 5684 - 5563
dist/preview release/babylon.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/babylon.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 283 - 20
dist/preview release/babylon.max.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 283 - 20
dist/preview release/babylon.no-module.max.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/babylon.worker.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 285 - 22
dist/preview release/es6.js


+ 47 - 10
dist/preview release/gui/babylon.gui.d.ts

@@ -61,6 +61,10 @@ declare module BABYLON.GUI {
             /** @hidden */
             _linkedControls: Control[];
             /**
+                * BABYLON.Observable event triggered each time an clipboard event is received from the rendering canvas
+                */
+            onClipboardObservable: BABYLON.Observable<BABYLON.ClipboardInfo>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -110,14 +114,18 @@ declare module BABYLON.GUI {
                 */
             isForeground: boolean;
             /**
-                * Creates a new AdvancedDynamicTexture
-                * @param name defines the name of the texture
-                * @param width defines the width of the texture
-                * @param height defines the height of the texture
-                * @param scene defines the hosting scene
-                * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
-                * @param samplingMode defines the texture sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
+                * Gets or set information about clipboardData
                 */
+            clipboardData: string;
+            /**
+             * Creates a new AdvancedDynamicTexture
+             * @param name defines the name of the texture
+             * @param width defines the width of the texture
+             * @param height defines the height of the texture
+             * @param scene defines the hosting scene
+             * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
+             * @param samplingMode defines the texture sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
+             */
             constructor(name: string, width: number | undefined, height: number | undefined, scene: BABYLON.Nullable<BABYLON.Scene>, generateMipMaps?: boolean, samplingMode?: number);
             /**
                 * Function used to execute a function on all controls
@@ -171,6 +179,14 @@ declare module BABYLON.GUI {
             /** Attach to all scene events required to support pointer events */
             attach(): void;
             /**
+                * Register the clipboard Events onto the canvas
+                */
+            registerClipboardEvents(): void;
+            /**
+                * Unregister the clipboard Events from the canvas
+                */
+            unRegisterClipboardEvents(): void;
+            /**
                 * Connect the texture to a hosting mesh to enable interactions
                 * @param mesh defines the mesh to attach to
                 * @param supportPointerMove defines a boolean indicating if pointer move events must be catched as well
@@ -916,8 +932,12 @@ declare module BABYLON.GUI {
              */
             onDirtyObservable: BABYLON.Observable<Control>;
             /**
-            * An event triggered after the control is drawn
-            */
+                * An event triggered before drawing the control
+                */
+            onBeforeDrawObservable: BABYLON.Observable<Control>;
+            /**
+                * An event triggered after the control was drawn
+                */
             onAfterDrawObservable: BABYLON.Observable<Control>;
             /** Gets or set information about font offsets (used to render and align text) */
             fontOffset: {
@@ -1441,10 +1461,22 @@ declare module BABYLON.GUI {
             onFocusObservable: BABYLON.Observable<InputText>;
             /** BABYLON.Observable raised when the control loses the focus */
             onBlurObservable: BABYLON.Observable<InputText>;
+            /**Observable raised when the text is highlighted */
+            onTextHighlightObservable: BABYLON.Observable<InputText>;
+            /**Observable raised when copy event is triggered */
+            onTextCopyObservable: BABYLON.Observable<InputText>;
+            /** BABYLON.Observable raised when cut event is triggered */
+            onTextCutObservable: BABYLON.Observable<InputText>;
+            /** BABYLON.Observable raised when paste event is triggered */
+            onTextPasteObservable: BABYLON.Observable<InputText>;
             /** Gets or sets the maximum width allowed by the control */
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
+            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            highligherOpacity: number;
+            /** Gets and sets the text hightlight color */
+            textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;
             /** Gets control margin in pixels */
@@ -1463,6 +1495,8 @@ declare module BABYLON.GUI {
             placeholderText: string;
             /** Gets or sets the dead key flag */
             deadKey: boolean;
+            /** Gets or sets the highlight text */
+            highlightedText: string;
             /** Gets or sets if the current key should be added */
             addKey: boolean;
             /** Gets or sets the value of the current key being entered */
@@ -1489,7 +1523,10 @@ declare module BABYLON.GUI {
             keepsFocusWith(): BABYLON.Nullable<Control[]>;
             /** @hidden */
             processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
-            /** @hidden */
+            /**
+                * Handles the keyboard event
+                * @param evt Defines the KeyboardEvent
+                */
             processKeyboard(evt: KeyboardEvent): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
             _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/gui/babylon.gui.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


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

@@ -51,7 +51,7 @@ declare module 'babylonjs-gui/2D/controls' {
 }
 
 declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
-    import { DynamicTexture, Nullable, Layer, Viewport, Scene, Vector3, Matrix, Vector2, AbstractMesh } from "babylonjs";
+    import { DynamicTexture, Nullable, Layer, Viewport, Scene, Vector3, Matrix, Vector2, AbstractMesh, Observable, ClipboardInfo } from 'babylonjs';
     import { Container } from "babylonjs-gui/2D/controls/container";
     import { Control } from "babylonjs-gui/2D/controls/control";
     import { Style } from "babylonjs-gui/2D/style";
@@ -106,6 +106,10 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
             /** @hidden */
             _linkedControls: Control[];
             /**
+                * Observable event triggered each time an clipboard event is received from the rendering canvas
+                */
+            onClipboardObservable: Observable<ClipboardInfo>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -155,14 +159,18 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
                 */
             isForeground: boolean;
             /**
-                * Creates a new AdvancedDynamicTexture
-                * @param name defines the name of the texture
-                * @param width defines the width of the texture
-                * @param height defines the height of the texture
-                * @param scene defines the hosting scene
-                * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
-                * @param samplingMode defines the texture sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
+                * Gets or set information about clipboardData
                 */
+            clipboardData: string;
+            /**
+             * Creates a new AdvancedDynamicTexture
+             * @param name defines the name of the texture
+             * @param width defines the width of the texture
+             * @param height defines the height of the texture
+             * @param scene defines the hosting scene
+             * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
+             * @param samplingMode defines the texture sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
+             */
             constructor(name: string, width: number | undefined, height: number | undefined, scene: Nullable<Scene>, generateMipMaps?: boolean, samplingMode?: number);
             /**
                 * Function used to execute a function on all controls
@@ -216,6 +224,14 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
             /** Attach to all scene events required to support pointer events */
             attach(): void;
             /**
+                * Register the clipboard Events onto the canvas
+                */
+            registerClipboardEvents(): void;
+            /**
+                * Unregister the clipboard Events from the canvas
+                */
+            unRegisterClipboardEvents(): void;
+            /**
                 * Connect the texture to a hosting mesh to enable interactions
                 * @param mesh defines the mesh to attach to
                 * @param supportPointerMove defines a boolean indicating if pointer move events must be catched as well
@@ -1023,8 +1039,12 @@ declare module 'babylonjs-gui/2D/controls/control' {
              */
             onDirtyObservable: Observable<Control>;
             /**
-            * An event triggered after the control is drawn
-            */
+                * An event triggered before drawing the control
+                */
+            onBeforeDrawObservable: Observable<Control>;
+            /**
+                * An event triggered after the control was drawn
+                */
             onAfterDrawObservable: Observable<Control>;
             /** Gets or set information about font offsets (used to render and align text) */
             fontOffset: {
@@ -1546,7 +1566,7 @@ declare module 'babylonjs-gui/2D/controls/image' {
 declare module 'babylonjs-gui/2D/controls/inputText' {
     import { Control } from "babylonjs-gui/2D/controls/control";
     import { IFocusableControl } from "babylonjs-gui/2D/advancedDynamicTexture";
-    import { Nullable, Observable, Vector2 } from "babylonjs";
+    import { Nullable, Observable, Vector2 } from 'babylonjs';
     import { Measure } from "babylonjs-gui/2D/measure";
     import { VirtualKeyboard } from "babylonjs-gui/2D/controls/virtualKeyboard";
     /**
@@ -1566,10 +1586,22 @@ declare module 'babylonjs-gui/2D/controls/inputText' {
             onFocusObservable: Observable<InputText>;
             /** Observable raised when the control loses the focus */
             onBlurObservable: Observable<InputText>;
+            /**Observable raised when the text is highlighted */
+            onTextHighlightObservable: Observable<InputText>;
+            /**Observable raised when copy event is triggered */
+            onTextCopyObservable: Observable<InputText>;
+            /** Observable raised when cut event is triggered */
+            onTextCutObservable: Observable<InputText>;
+            /** Observable raised when paste event is triggered */
+            onTextPasteObservable: Observable<InputText>;
             /** Gets or sets the maximum width allowed by the control */
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
+            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            highligherOpacity: number;
+            /** Gets and sets the text hightlight color */
+            textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;
             /** Gets control margin in pixels */
@@ -1588,6 +1620,8 @@ declare module 'babylonjs-gui/2D/controls/inputText' {
             placeholderText: string;
             /** Gets or sets the dead key flag */
             deadKey: boolean;
+            /** Gets or sets the highlight text */
+            highlightedText: string;
             /** Gets or sets if the current key should be added */
             addKey: boolean;
             /** Gets or sets the value of the current key being entered */
@@ -1614,7 +1648,10 @@ declare module 'babylonjs-gui/2D/controls/inputText' {
             keepsFocusWith(): Nullable<Control[]>;
             /** @hidden */
             processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
-            /** @hidden */
+            /**
+                * Handles the keyboard event
+                * @param evt Defines the KeyboardEvent
+                */
             processKeyboard(evt: KeyboardEvent): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
             _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
@@ -3009,6 +3046,10 @@ declare module BABYLON.GUI {
             /** @hidden */
             _linkedControls: Control[];
             /**
+                * BABYLON.Observable event triggered each time an clipboard event is received from the rendering canvas
+                */
+            onClipboardObservable: BABYLON.Observable<BABYLON.ClipboardInfo>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -3058,14 +3099,18 @@ declare module BABYLON.GUI {
                 */
             isForeground: boolean;
             /**
-                * Creates a new AdvancedDynamicTexture
-                * @param name defines the name of the texture
-                * @param width defines the width of the texture
-                * @param height defines the height of the texture
-                * @param scene defines the hosting scene
-                * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
-                * @param samplingMode defines the texture sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
+                * Gets or set information about clipboardData
                 */
+            clipboardData: string;
+            /**
+             * Creates a new AdvancedDynamicTexture
+             * @param name defines the name of the texture
+             * @param width defines the width of the texture
+             * @param height defines the height of the texture
+             * @param scene defines the hosting scene
+             * @param generateMipMaps defines a boolean indicating if mipmaps must be generated (false by default)
+             * @param samplingMode defines the texture sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
+             */
             constructor(name: string, width: number | undefined, height: number | undefined, scene: BABYLON.Nullable<BABYLON.Scene>, generateMipMaps?: boolean, samplingMode?: number);
             /**
                 * Function used to execute a function on all controls
@@ -3119,6 +3164,14 @@ declare module BABYLON.GUI {
             /** Attach to all scene events required to support pointer events */
             attach(): void;
             /**
+                * Register the clipboard Events onto the canvas
+                */
+            registerClipboardEvents(): void;
+            /**
+                * Unregister the clipboard Events from the canvas
+                */
+            unRegisterClipboardEvents(): void;
+            /**
                 * Connect the texture to a hosting mesh to enable interactions
                 * @param mesh defines the mesh to attach to
                 * @param supportPointerMove defines a boolean indicating if pointer move events must be catched as well
@@ -3864,8 +3917,12 @@ declare module BABYLON.GUI {
              */
             onDirtyObservable: BABYLON.Observable<Control>;
             /**
-            * An event triggered after the control is drawn
-            */
+                * An event triggered before drawing the control
+                */
+            onBeforeDrawObservable: BABYLON.Observable<Control>;
+            /**
+                * An event triggered after the control was drawn
+                */
             onAfterDrawObservable: BABYLON.Observable<Control>;
             /** Gets or set information about font offsets (used to render and align text) */
             fontOffset: {
@@ -4389,10 +4446,22 @@ declare module BABYLON.GUI {
             onFocusObservable: BABYLON.Observable<InputText>;
             /** BABYLON.Observable raised when the control loses the focus */
             onBlurObservable: BABYLON.Observable<InputText>;
+            /**Observable raised when the text is highlighted */
+            onTextHighlightObservable: BABYLON.Observable<InputText>;
+            /**Observable raised when copy event is triggered */
+            onTextCopyObservable: BABYLON.Observable<InputText>;
+            /** BABYLON.Observable raised when cut event is triggered */
+            onTextCutObservable: BABYLON.Observable<InputText>;
+            /** BABYLON.Observable raised when paste event is triggered */
+            onTextPasteObservable: BABYLON.Observable<InputText>;
             /** Gets or sets the maximum width allowed by the control */
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
+            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            highligherOpacity: number;
+            /** Gets and sets the text hightlight color */
+            textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;
             /** Gets control margin in pixels */
@@ -4411,6 +4480,8 @@ declare module BABYLON.GUI {
             placeholderText: string;
             /** Gets or sets the dead key flag */
             deadKey: boolean;
+            /** Gets or sets the highlight text */
+            highlightedText: string;
             /** Gets or sets if the current key should be added */
             addKey: boolean;
             /** Gets or sets the value of the current key being entered */
@@ -4437,7 +4508,10 @@ declare module BABYLON.GUI {
             keepsFocusWith(): BABYLON.Nullable<Control[]>;
             /** @hidden */
             processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
-            /** @hidden */
+            /**
+                * Handles the keyboard event
+                * @param evt Defines the KeyboardEvent
+                */
             processKeyboard(evt: KeyboardEvent): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
             _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;

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

@@ -1273,7 +1273,7 @@ var BABYLON;
                 var name = node.name || "node" + node.index;
                 if (primitives.length === 1) {
                     var primitive = mesh.primitives[0];
-                    promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index + "}", name, node, mesh, primitive, function (babylonMesh) {
+                    promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index, name, node, mesh, primitive, function (babylonMesh) {
                         node._babylonTransformNode = babylonMesh;
                     }));
                 }
@@ -1282,7 +1282,7 @@ var BABYLON;
                     node._babylonTransformNode = babylonTransformNode_1;
                     for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
                         var primitive = primitives_1[_i];
-                        promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index + "}", name + "_primitive" + primitive.index, node, mesh, primitive, function (babylonMesh) {
+                        promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index, name + "_primitive" + primitive.index, node, mesh, primitive, function (babylonMesh) {
                             babylonMesh.parent = babylonTransformNode_1;
                             node._primitiveBabylonMeshes = node._primitiveBabylonMeshes || [];
                             node._primitiveBabylonMeshes.push(babylonMesh);

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


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

@@ -3481,7 +3481,7 @@ var BABYLON;
                 var name = node.name || "node" + node.index;
                 if (primitives.length === 1) {
                     var primitive = mesh.primitives[0];
-                    promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index + "}", name, node, mesh, primitive, function (babylonMesh) {
+                    promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index, name, node, mesh, primitive, function (babylonMesh) {
                         node._babylonTransformNode = babylonMesh;
                     }));
                 }
@@ -3490,7 +3490,7 @@ var BABYLON;
                     node._babylonTransformNode = babylonTransformNode_1;
                     for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
                         var primitive = primitives_1[_i];
-                        promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index + "}", name + "_primitive" + primitive.index, node, mesh, primitive, function (babylonMesh) {
+                        promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index, name + "_primitive" + primitive.index, node, mesh, primitive, function (babylonMesh) {
                             babylonMesh.parent = babylonTransformNode_1;
                             node._primitiveBabylonMeshes = node._primitiveBabylonMeshes || [];
                             node._primitiveBabylonMeshes.push(babylonMesh);

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


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

@@ -4543,7 +4543,7 @@ var BABYLON;
                 var name = node.name || "node" + node.index;
                 if (primitives.length === 1) {
                     var primitive = mesh.primitives[0];
-                    promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index + "}", name, node, mesh, primitive, function (babylonMesh) {
+                    promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index, name, node, mesh, primitive, function (babylonMesh) {
                         node._babylonTransformNode = babylonMesh;
                     }));
                 }
@@ -4552,7 +4552,7 @@ var BABYLON;
                     node._babylonTransformNode = babylonTransformNode_1;
                     for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
                         var primitive = primitives_1[_i];
-                        promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index + "}", name + "_primitive" + primitive.index, node, mesh, primitive, function (babylonMesh) {
+                        promises.push(this._loadMeshPrimitiveAsync(context + "/primitives/" + primitive.index, name + "_primitive" + primitive.index, node, mesh, primitive, function (babylonMesh) {
                             babylonMesh.parent = babylonTransformNode_1;
                             node._primitiveBabylonMeshes = node._primitiveBabylonMeshes || [];
                             node._primitiveBabylonMeshes.push(babylonMesh);

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


+ 2 - 0
dist/preview release/materialsLibrary/babylon.gridMaterial.d.ts

@@ -37,6 +37,8 @@ declare module BABYLON {
          * Determine RBG output is premultiplied by alpha value.
          */
         preMultiplyAlpha: boolean;
+        private _opacityTexture;
+        opacityTexture: BaseTexture;
         private _gridControl;
         private _renderId;
         /**

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 43 - 5
dist/preview release/materialsLibrary/babylon.gridMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gridMaterial.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylon.normalMaterial.d.ts

@@ -11,6 +11,7 @@ declare module BABYLON {
         private _renderId;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
+        needAlphaBlendingForMesh(mesh: AbstractMesh): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): Nullable<BaseTexture>;
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 9 - 8
dist/preview release/materialsLibrary/babylon.normalMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.normalMaterial.min.js


+ 3 - 0
dist/preview release/materialsLibrary/babylonjs.materials.d.ts

@@ -61,6 +61,7 @@ declare module BABYLON {
         private _renderId;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
+        needAlphaBlendingForMesh(mesh: AbstractMesh): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): Nullable<BaseTexture>;
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
@@ -541,6 +542,8 @@ declare module BABYLON {
          * Determine RBG output is premultiplied by alpha value.
          */
         preMultiplyAlpha: boolean;
+        private _opacityTexture;
+        opacityTexture: BaseTexture;
         private _gridControl;
         private _renderId;
         /**

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 52 - 13
dist/preview release/materialsLibrary/babylonjs.materials.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 3 - 0
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -66,6 +66,7 @@ declare module BABYLON {
         private _renderId;
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
+        needAlphaBlendingForMesh(mesh: AbstractMesh): boolean;
         needAlphaTesting(): boolean;
         getAlphaTestTexture(): Nullable<BaseTexture>;
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
@@ -546,6 +547,8 @@ declare module BABYLON {
          * Determine RBG output is premultiplied by alpha value.
          */
         preMultiplyAlpha: boolean;
+        private _opacityTexture;
+        opacityTexture: BaseTexture;
         private _gridControl;
         private _renderId;
         /**

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

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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


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

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

+ 129 - 119
dist/preview release/what's new.md

@@ -1,119 +1,129 @@
-# 4.0.0
-
-## Major updates
-
-- Added support for [parallel shader compilation](https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/) ([Deltakosh](https://github.com/deltakosh))
-- Added FlyCamera for free navigation in 3D space, with a limited set of settings ([Phuein](https://github.com/phuein)) [@NEED DEMO]
-- Added [Object Based Motion Blur](http://doc.babylonjs.com/how_to/using_motionblurpostprocess) post-process ([julien-moreau](https://github.com/julien-moreau))
-- WebXR ([TrevorDev](https://github.com/TrevorDev)) [@NEED DEMO]
-  - Add customAnimationFrameRequester to allow sessions to hook into engine's render loop ([TrevorDev](https://github.com/TrevorDev))
-  - camera customDefaultRenderTarget to allow cameras to render to a custom render target (eg. xr framebuffer) instead of the canvas ([TrevorDev](https://github.com/TrevorDev))
-  - webXR camera which can be updated by a webXRSession ([TrevorDev](https://github.com/TrevorDev))
-  - webXRSessionManager to bridge xrSession to babylon's camera/engine ([TrevorDev](https://github.com/TrevorDev))
-  - webXRExperienceHelper to setup a default XR experience ([TrevorDev](https://github.com/TrevorDev))
-  - WebXREnterExitUI and WebXRManagedOutputCanvas classes to configure the XR experience ([TrevorDev](https://github.com/TrevorDev))
-  - WebXRInput manage controllers for the XR experience ([TrevorDev](https://github.com/TrevorDev))
-  - WebXR camera rotation using parent container ([TrevorDev](https://github.com/TrevorDev))
-- GUI:
-  - Added new [ImageBasedSlider](http://doc.babylonjs.com/how_to/gui#imagebasedslider) to let users customize sliders using images ([Deltakosh](https://github.com/deltakosh))
-
-## Updates
-
-### GUI
-
-- Added `button.image` and `button.textBlock` to simplify access to button internal parts ([Deltakosh](https://github.com/deltakosh))
-- Added `sldier.displayThumb` to show/hide slider's thumb ([Deltakosh](https://github.com/deltakosh))
-- Added `grid.rowCount`, `grid.columnCount` and `grid.getChildrenAt()` ([Deltakosh](https://github.com/deltakosh))
-- Added `Control.AllowAlphaInheritance` to let users control the way alpha is used (inherited or not) ([Deltakosh](https://github.com/deltakosh))
-
-### Core Engine
-
-- Added support for utility layer for SkeletonViewer ([Deltakosh](https://github.com/deltakosh))
-- Improved shader precision detection ([Deltakosh](https://github.com/deltakosh))
-- Added support for bone matrix texture. Now skeletons will use a texture instead of uniforms when possible ([Deltakosh](https://github.com/deltakosh))
-- Refactored of the SolidParticleSystem code for performance and code quality improvement ([barroij](https://github.com/barroij))
-- Added utility function `Tools.BuildArray` for array initialisation ([barroij](https://github.com/barroij))
-- Introduced a new `IOfflineSupport` interface to hide IndexedDB ([Deltakosh](https://github.com/deltakosh))
-- `PBRMaterial` and `StandardMaterial` now use hot swapping feature for shaders. This means they can keep using a previous shader while a new one is being compiled ([Deltakosh](https://github.com/deltakosh))
-- Performance oriented changes ([barroij](https://github.com/barroij))
-  - Prevented avoidable matrix inversion or square root computation
-  - Enabled a removal in O(1) from the `transformNodes` array and `materials` array of the `Scene`. As a consequence, the order of the element within these arrays might change during a removal
-  - Enabled a removal in O(1) from the `instances` array of a `Mesh`. As a consequence, the order of the element within this array might change during a removal
-  - Stopped calling `Array.splice` on the `scene.meshes` array and on the `engine._uniformBuffer` when removing an element. As a consequence, the order of the element within these arrays might change during a removal
-  - Added an option `useMaterialMeshMap` in the `Scene` constructor options. When set to true, each `Material` isntance will have and will keep up-to-date a map of its bound meshes. This is to avoid browsing all the meshes of the scene to retrieve the ones bound to the current material when disposing the Material. Disabled by default
-  - Added an option `useClonedMeshhMap` in the `Scene` constructor options. When set to true, each `Mesh` will have and will keep up-to-date a map of cloned meshes. This is to avoid browsing all the meshes of the scene to retrieve the ones that have the current mesh as source mesh. Disabled by default
-  - Added `blockfreeActiveMeshesAndRenderingGroups` property in the `Scene`, following the same model as `blockMaterialDirtyMechanism`. This is to avoid calling `Scene.freeActiveMeshes` and `Scene.freeRenderingGroups` for each disposed mesh when we dispose several meshes in a row. One have to set `blockfreeActiveMeshesAndRenderingGroups` to `true` just before disposing the meshes, and set it back to `false` just after
-  - Prevented code from doing useless and possible time consuming computation when disposing the `ShaderMaterial` of a `LinesMesh`
-  - Make a better use of the `isIdentity` cached value wihtin a `Matrix`
-  - Make sure we browse all the submeshes only once in `Material.markAsDirty` function
-  - Added an `Vector3.UnprojectRayToRef` static function to avoid computing and inverting the projection matrix twice when updating a Ray.
-- Align `BoundingBox` and `BoundingSphere` API and behavior for clarity and simplicity. As a consequence, the `BoundingBox`'s method `setWorldMatrix` has been removed and the underlying world matrix cannot be modified but by calling `reConstruct` or `update`. ([barroij](https://github.com/barroij))
-- Make sure that `Material.markAsDirty` and all the `markXXXDirty` methods early out when `scene.blockMaterialDirtyMechanism` is true. ([barroij](https://github.com/barroij))
-- Add updateUpVectorFromRotation to target camera to allow the up vector to be computed from rotation ([TrevorDev](https://github.com/TrevorDev))
-
-### glTF Loader
-
-- Added support for mesh instancing for improved performance when multiple nodes point to the same mesh ([bghgary](https://github.com/bghgary))
-- Create `TransformNode` objects instead of `Mesh` objects for glTF nodes without geometry ([bghgary](https://github.com/bghgary))
-
-### glTF Serializer
-
-### Viewer
-
-### Materials Library
-
-## Bug fixes
-- Removed bones from rootNodes where they should never have been ([Deltakosh](https://github.com/deltakosh))
-- Refocusing on input gui with pointer events ([TrevorDev](https://github.com/TrevorDev))
-- Gizmo scaling not consistent when camera is parented ([TrevorDev](https://github.com/TrevorDev))
-- Context loss causing unexpected results with dynamic textures ([TrevorDev](https://github.com/TrevorDev))
-- CreateScreenshotUsingRenderTarget stretches mirror textures when setting both width and height ([TrevorDev](https://github.com/TrevorDev))
-- VR helper only updating vr cameras position when entering vr, rotation was missing ([TrevorDev](https://github.com/TrevorDev))
-- Fix VR controllers after gltfLoader transformNode change ([TrevorDev](https://github.com/TrevorDev))
-- Bounding Box fixedDragMeshScreenSize stopped working and allow rotating through bounding box ([TrevorDev](https://github.com/TrevorDev))
-
-### Core Engine
-- Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))
-- Fixed a bug with pointer up being fire twice ([Deltakosh](https://github.com/deltakosh))
-- Fixed a bug with particle systems being update once per camera instead of once per frame ([Deltakosh](https://github.com/deltakosh))
-- Handle properly the `LinesMesh` `intersectionThreshold` by using its value directly when the intersection against a `Ray` is checked, instead of extending the `BoundingInfo` accordingly + Addded an `InstancesLinesMesh` class used to create instance of `LinesMesh` so that each instance can have its own `intersectionThreshold` value ([barroij](https://github.com/barroij))
-- Fixed the `LineEdgesRenderer` used for edge rendering of `LinesMesh` handle properly LinesMesh made of disconnected lines + Make it work for instance of `LinesMesh` ([barroij](https://github.com/barroij))
-- Fixed `Matrix.toNormalMatrix`function ([barroij](https://github.com/barroij))
-- Add missing effect layer to asset container ([TrevorDev](https://github.com/TrevorDev))
-- Fixed effect layer compatibility with multi materials ([Sebavan](https://github.com/Sebavan))
-- Added a `DeepImmutable<T>` type to specifiy that a referenced object should be considered recursively immutable, meaning that all its properties are `readonly` and that if a property is a reference to an object, this object is also recursively immutable. ([barroij](https://github.com/barroij))
-
-### Viewer
-
-### Loaders
-
-## Breaking changes
-
-- `Database.IDBStorageEnabled` is now false by default ([Deltakosh](https://github.com/deltakosh))
-- `Database.openAsync` was renamed by `Database.open` ([Deltakosh](https://github.com/deltakosh))
-- `scene.database` was renamed to `scene.offlineProvider` ([Deltakosh](https://github.com/deltakosh))
-- `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `DeepImmutable<Matrix>` ([barroij](https://github.com/barroij))
-- `Matrix`'s accessor `m` and method `toArray` and `asArray` now returns a `DeepImmutable<Float32Array>` as the matrix underlying array is not supposed to be modified manually from the outside of the class ([barroij](https://github.com/barroij))
-- Removed some deprecated (flagged since 3.0) properties and functions ([Deltakosh](https://github.com/deltakosh))
-  - `scene.getInterFramePerfCounter()`: use SceneInstrumentation class instead
-  - `scene.interFramePerfCounter`: use SceneInstrumentation class instead
-  - `scene.getLastFrameDuration()`: use SceneInstrumentation class instead
-  - `scene.lastFramePerfCounter`: use SceneInstrumentation class instead
-  - `scene.getEvaluateActiveMeshesDuration()`: use SceneInstrumentation class instead
-  - `scene.evaluateActiveMeshesDurationPerfCounter`: use SceneInstrumentation class instead
-  - `scene.getRenderTargetsDuration()`: use SceneInstrumentation class instead
-  - `scene.getRenderDuration()`: use SceneInstrumentation class instead
-  - `scene.renderDurationPerfCounter`: use SceneInstrumentation class instead
-  - `scene.getParticlesDuration()`: use SceneInstrumentation class instead
-  - `scene.particlesDurationPerfCounter`: use SceneInstrumentation class instead
-  - `scene.getSpritesDuration()`: use SceneInstrumentation class instead
-  - `scene.spriteDuractionPerfCounter`: use SceneInstrumentation class instead
-  - `engine.drawCalls`: use SceneInstrumentation class instead
-  - `engine.drawCallsPerfCounter`: use SceneInstrumentation class instead
-  - `shadowGenerator.useVarianceShadowMap`: use useExponentialShadowMap instead
-  - `shadowGenerator.useBlurVarianceShadowMap`: use useBlurExponentialShadowMap instead
-- The glTF loader now creates `InstancedMesh` objects when two nodes point to the same mesh ([bghgary](https://github.com/bghgary))
-- The glTF loader now creates `TransformNode` objects instead of `Mesh` objects for glTF nodes without geometry ([bghgary](https://github.com/bghgary))
-  - _Note: The root node is still a `Mesh` object and is still the first in the returned list of meshes_
-  - `TransformNode` objects are excluded from the returned list of meshes when importing mesh
-  - `TransformNode` objects do not raise `onMeshLoaded` events
+# 4.0.0
+
+## Major updates
+
+- Added support for [parallel shader compilation](https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/) ([Deltakosh](https://github.com/deltakosh))
+- Added FlyCamera for free navigation in 3D space, with a limited set of settings ([Phuein](https://github.com/phuein)) [@NEED DEMO]
+- Added [Object Based Motion Blur](http://doc.babylonjs.com/how_to/using_motionblurpostprocess) post-process ([julien-moreau](https://github.com/julien-moreau))
+- WebXR ([TrevorDev](https://github.com/TrevorDev)) [@NEED DEMO]
+  - Add customAnimationFrameRequester to allow sessions to hook into engine's render loop ([TrevorDev](https://github.com/TrevorDev))
+  - camera customDefaultRenderTarget to allow cameras to render to a custom render target (eg. xr framebuffer) instead of the canvas ([TrevorDev](https://github.com/TrevorDev))
+  - webXR camera which can be updated by a webXRSession ([TrevorDev](https://github.com/TrevorDev))
+  - webXRSessionManager to bridge xrSession to babylon's camera/engine ([TrevorDev](https://github.com/TrevorDev))
+  - webXRExperienceHelper to setup a default XR experience ([TrevorDev](https://github.com/TrevorDev))
+  - WebXREnterExitUI and WebXRManagedOutputCanvas classes to configure the XR experience ([TrevorDev](https://github.com/TrevorDev))
+  - WebXRInput manage controllers for the XR experience ([TrevorDev](https://github.com/TrevorDev))
+  - WebXR camera rotation using parent container ([TrevorDev](https://github.com/TrevorDev))
+- GUI:
+  - Added new [ImageBasedSlider](http://doc.babylonjs.com/how_to/gui#imagebasedslider) to let users customize sliders using images ([Deltakosh](https://github.com/deltakosh))
+  - Added support for clipboard events to let users perform `cut`, `copy` and `paste` events ([Saket Saurabh](https://github.com/ssaket))
+
+## Updates
+
+### GUI
+
+- Added `button.image` and `button.textBlock` to simplify access to button internal parts ([Deltakosh](https://github.com/deltakosh))
+- Added `sldier.displayThumb` to show/hide slider's thumb ([Deltakosh](https://github.com/deltakosh))
+- Added `grid.rowCount`, `grid.columnCount` and `grid.getChildrenAt()` ([Deltakosh](https://github.com/deltakosh))
+- Added `Control.AllowAlphaInheritance` to let users control the way alpha is used (inherited or not) ([Deltakosh](https://github.com/deltakosh))
+- Added support for performing operations like select all, text highlight, delete selected in `inputText` ([Saket Saurabh](https://github.com/ssaket))
+- Added `inputText.onTextCopyObservable`, `inputText.onTextCutObservable` and `inputText.onTextPasteObservable` to inputText ([Saket Saurabh](https://github.com/ssaket))
+- Added `AdvancedDynamicTexture.onClipboardObservable` to observe for clipboard events in AdvancedDynamicTexture([Saket Saurabh](https://github.com/ssaket))
+
+
+### Core Engine
+
+- Added `Engine.onNewSceneAddedObservable` ([Deltakosh](https://github.com/deltakosh))
+- Added new `PassCubePostProcess` to render cube map content ([Deltakosh](https://github.com/deltakosh))
+- Added support for utility layer for SkeletonViewer ([Deltakosh](https://github.com/deltakosh))
+- Improved shader precision detection ([Deltakosh](https://github.com/deltakosh))
+- Added support for bone matrix texture. Now skeletons will use a texture instead of uniforms when possible ([Deltakosh](https://github.com/deltakosh))
+- Refactored of the SolidParticleSystem code for performance and code quality improvement ([barroij](https://github.com/barroij))
+- Added utility function `Tools.BuildArray` for array initialisation ([barroij](https://github.com/barroij))
+- Introduced a new `IOfflineSupport` interface to hide IndexedDB ([Deltakosh](https://github.com/deltakosh))
+- `PBRMaterial` and `StandardMaterial` now use hot swapping feature for shaders. This means they can keep using a previous shader while a new one is being compiled ([Deltakosh](https://github.com/deltakosh))
+- Performance oriented changes ([barroij](https://github.com/barroij))
+  - Prevented avoidable matrix inversion or square root computation
+  - Enabled a removal in O(1) from the `transformNodes` array and `materials` array of the `Scene`. As a consequence, the order of the element within these arrays might change during a removal
+  - Enabled a removal in O(1) from the `instances` array of a `Mesh`. As a consequence, the order of the element within this array might change during a removal
+  - Stopped calling `Array.splice` on the `scene.meshes` array and on the `engine._uniformBuffer` when removing an element. As a consequence, the order of the element within these arrays might change during a removal
+  - Added an option `useMaterialMeshMap` in the `Scene` constructor options. When set to true, each `Material` isntance will have and will keep up-to-date a map of its bound meshes. This is to avoid browsing all the meshes of the scene to retrieve the ones bound to the current material when disposing the Material. Disabled by default
+  - Added an option `useClonedMeshhMap` in the `Scene` constructor options. When set to true, each `Mesh` will have and will keep up-to-date a map of cloned meshes. This is to avoid browsing all the meshes of the scene to retrieve the ones that have the current mesh as source mesh. Disabled by default
+  - Added `blockfreeActiveMeshesAndRenderingGroups` property in the `Scene`, following the same model as `blockMaterialDirtyMechanism`. This is to avoid calling `Scene.freeActiveMeshes` and `Scene.freeRenderingGroups` for each disposed mesh when we dispose several meshes in a row. One have to set `blockfreeActiveMeshesAndRenderingGroups` to `true` just before disposing the meshes, and set it back to `false` just after
+  - Prevented code from doing useless and possible time consuming computation when disposing the `ShaderMaterial` of a `LinesMesh`
+  - Make a better use of the `isIdentity` cached value wihtin a `Matrix`
+  - Make sure we browse all the submeshes only once in `Material.markAsDirty` function
+  - Added an `Vector3.UnprojectRayToRef` static function to avoid computing and inverting the projection matrix twice when updating a Ray.
+- Align `BoundingBox` and `BoundingSphere` API and behavior for clarity and simplicity. As a consequence, the `BoundingBox`'s method `setWorldMatrix` has been removed and the underlying world matrix cannot be modified but by calling `reConstruct` or `update`. ([barroij](https://github.com/barroij))
+- Make sure that `Material.markAsDirty` and all the `markXXXDirty` methods early out when `scene.blockMaterialDirtyMechanism` is true. ([barroij](https://github.com/barroij))
+- Add updateUpVectorFromRotation to target camera to allow the up vector to be computed from rotation ([TrevorDev](https://github.com/TrevorDev))
+- Added opacity texture support to `GridMaterial` ([Deltakosh](https://github.com/deltakosh))
+- Added support for deserializing morph target animations in animation groups
+
+### glTF Loader
+
+- Added support for mesh instancing for improved performance when multiple nodes point to the same mesh ([bghgary](https://github.com/bghgary))
+- Create `TransformNode` objects instead of `Mesh` objects for glTF nodes without geometry ([bghgary](https://github.com/bghgary))
+
+### glTF Serializer
+
+### Viewer
+
+### Materials Library
+
+## Bug fixes
+- Removed bones from rootNodes where they should never have been ([Deltakosh](https://github.com/deltakosh))
+- Refocusing on input gui with pointer events ([TrevorDev](https://github.com/TrevorDev))
+- Gizmo scaling not consistent when camera is parented ([TrevorDev](https://github.com/TrevorDev))
+- Context loss causing unexpected results with dynamic textures ([TrevorDev](https://github.com/TrevorDev))
+- CreateScreenshotUsingRenderTarget stretches mirror textures when setting both width and height ([TrevorDev](https://github.com/TrevorDev))
+- VR helper only updating vr cameras position when entering vr, rotation was missing ([TrevorDev](https://github.com/TrevorDev))
+- Fix VR controllers after gltfLoader transformNode change ([TrevorDev](https://github.com/TrevorDev))
+- Bounding Box fixedDragMeshScreenSize stopped working and allow rotating through bounding box ([TrevorDev](https://github.com/TrevorDev))
+- VR helper would rotate non vr camera while in VR ([TrevorDev](https://github.com/TrevorDev))
+
+### Core Engine
+- Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))
+- Fixed a bug with pointer up being fire twice ([Deltakosh](https://github.com/deltakosh))
+- Fixed a bug with particle systems being update once per camera instead of once per frame ([Deltakosh](https://github.com/deltakosh))
+- Handle properly the `LinesMesh` `intersectionThreshold` by using its value directly when the intersection against a `Ray` is checked, instead of extending the `BoundingInfo` accordingly + Addded an `InstancesLinesMesh` class used to create instance of `LinesMesh` so that each instance can have its own `intersectionThreshold` value ([barroij](https://github.com/barroij))
+- Fixed the `LineEdgesRenderer` used for edge rendering of `LinesMesh` handle properly LinesMesh made of disconnected lines + Make it work for instance of `LinesMesh` ([barroij](https://github.com/barroij))
+- Fixed `Matrix.toNormalMatrix`function ([barroij](https://github.com/barroij))
+- Add missing effect layer to asset container ([TrevorDev](https://github.com/TrevorDev))
+- Fixed effect layer compatibility with multi materials ([Sebavan](https://github.com/Sebavan))
+- Added a `DeepImmutable<T>` type to specifiy that a referenced object should be considered recursively immutable, meaning that all its properties are `readonly` and that if a property is a reference to an object, this object is also recursively immutable. ([barroij](https://github.com/barroij))
+
+### Viewer
+
+### Loaders
+
+## Breaking changes
+
+- `Database.IDBStorageEnabled` is now false by default ([Deltakosh](https://github.com/deltakosh))
+- `Database.openAsync` was renamed by `Database.open` ([Deltakosh](https://github.com/deltakosh))
+- `scene.database` was renamed to `scene.offlineProvider` ([Deltakosh](https://github.com/deltakosh))
+- `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `DeepImmutable<Matrix>` ([barroij](https://github.com/barroij))
+- `Matrix`'s accessor `m` and method `toArray` and `asArray` now returns a `DeepImmutable<Float32Array>` as the matrix underlying array is not supposed to be modified manually from the outside of the class ([barroij](https://github.com/barroij))
+- Removed some deprecated (flagged since 3.0) properties and functions ([Deltakosh](https://github.com/deltakosh))
+  - `scene.getInterFramePerfCounter()`: use SceneInstrumentation class instead
+  - `scene.interFramePerfCounter`: use SceneInstrumentation class instead
+  - `scene.getLastFrameDuration()`: use SceneInstrumentation class instead
+  - `scene.lastFramePerfCounter`: use SceneInstrumentation class instead
+  - `scene.getEvaluateActiveMeshesDuration()`: use SceneInstrumentation class instead
+  - `scene.evaluateActiveMeshesDurationPerfCounter`: use SceneInstrumentation class instead
+  - `scene.getRenderTargetsDuration()`: use SceneInstrumentation class instead
+  - `scene.getRenderDuration()`: use SceneInstrumentation class instead
+  - `scene.renderDurationPerfCounter`: use SceneInstrumentation class instead
+  - `scene.getParticlesDuration()`: use SceneInstrumentation class instead
+  - `scene.particlesDurationPerfCounter`: use SceneInstrumentation class instead
+  - `scene.getSpritesDuration()`: use SceneInstrumentation class instead
+  - `scene.spriteDuractionPerfCounter`: use SceneInstrumentation class instead
+  - `engine.drawCalls`: use SceneInstrumentation class instead
+  - `engine.drawCallsPerfCounter`: use SceneInstrumentation class instead
+  - `shadowGenerator.useVarianceShadowMap`: use useExponentialShadowMap instead
+  - `shadowGenerator.useBlurVarianceShadowMap`: use useBlurExponentialShadowMap instead
+- The glTF loader now creates `InstancedMesh` objects when two nodes point to the same mesh ([bghgary](https://github.com/bghgary))
+- The glTF loader now creates `TransformNode` objects instead of `Mesh` objects for glTF nodes without geometry ([bghgary](https://github.com/bghgary))
+  - _Note: The root node is still a `Mesh` object and is still the first in the returned list of meshes_
+  - `TransformNode` objects are excluded from the returned list of meshes when importing mesh
+  - `TransformNode` objects do not raise `onMeshLoaded` events

+ 59 - 2
gui/src/2D/advancedDynamicTexture.ts

@@ -1,4 +1,4 @@
-import { DynamicTexture, Nullable, Observer, Camera, Engine, KeyboardInfoPre, PointerInfoPre, PointerInfo, Layer, Viewport, Scene, Texture, KeyboardEventTypes, Vector3, Matrix, Vector2, Tools, PointerEventTypes, AbstractMesh, StandardMaterial, Color3 } from "babylonjs";
+import { DynamicTexture, Nullable, Observer, Camera, Engine, KeyboardInfoPre, PointerInfoPre, PointerInfo, ClipboardEventTypes, Layer, Viewport, Scene, Texture, KeyboardEventTypes, Vector3, Matrix, Vector2, Tools, PointerEventTypes, AbstractMesh, StandardMaterial, Color3, Observable, ClipboardInfo } from 'babylonjs';
 import { Container } from "./controls/container";
 import { Control } from "./controls/control";
 import { Style } from "./style";
@@ -68,6 +68,16 @@ export class AdvancedDynamicTexture extends DynamicTexture {
     private _blockNextFocusCheck = false;
     private _renderScale = 1;
     private _rootCanvas: Nullable<HTMLCanvasElement>;
+    /**
+     * Define type to string to ensure compatibility across browsers
+     * Safari doesn't support DataTransfer constructor
+     */
+    private _clipboardData: string = "";
+
+    /**
+     * Observable event triggered each time an clipboard event is received from the rendering canvas
+     */
+    public onClipboardObservable = new Observable<ClipboardInfo>();
 
     /**
      * Gets or sets a boolean defining if alpha is stored as premultiplied
@@ -237,6 +247,16 @@ export class AdvancedDynamicTexture extends DynamicTexture {
     }
 
     /**
+     * Gets or set information about clipboardData
+     */
+    public get clipboardData(): string {
+        return this._clipboardData;
+    }
+    public set clipboardData(value: string) {
+        this._clipboardData = value;
+    }
+
+     /**
      * Creates a new AdvancedDynamicTexture
      * @param name defines the name of the texture
      * @param width defines the width of the texture
@@ -380,6 +400,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         }
 
         this._rootContainer.dispose();
+        this.onClipboardObservable.clear();
 
         super.dispose();
     }
@@ -596,7 +617,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
             if (pi.type !== PointerEventTypes.POINTERMOVE
                 && pi.type !== PointerEventTypes.POINTERUP
                 && pi.type !== PointerEventTypes.POINTERDOWN) {
-                return;
+                    return;
             }
 
             if (!scene) {
@@ -626,6 +647,42 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         this._attachToOnPointerOut(scene);
     }
 
+    /** @hidden */
+    private onClipboardCopy = (evt: ClipboardEvent) => {
+        let ev = new ClipboardInfo(ClipboardEventTypes.COPY, evt);
+        this.onClipboardObservable.notifyObservers(ev);
+        evt.preventDefault();
+    }
+     /** @hidden */
+    private onClipboardCut = (evt: ClipboardEvent) => {
+        let ev = new ClipboardInfo(ClipboardEventTypes.CUT, evt);
+        this.onClipboardObservable.notifyObservers(ev);
+        evt.preventDefault();
+    }
+    /** @hidden */
+    private onClipboardPaste = (evt: ClipboardEvent) => {
+        let ev = new ClipboardInfo(ClipboardEventTypes.PASTE, evt);
+        this.onClipboardObservable.notifyObservers(ev);
+        evt.preventDefault();
+    }
+
+   /**
+    * Register the clipboard Events onto the canvas
+    */
+    public registerClipboardEvents(): void {
+        self.addEventListener("copy", this.onClipboardCopy, false);
+        self.addEventListener("cut", this.onClipboardCut, false);
+        self.addEventListener("paste", this.onClipboardPaste, false);
+    }
+    /**
+     * Unregister the clipboard Events from the canvas
+     */
+    public unRegisterClipboardEvents(): void {
+        self.removeEventListener("copy", this.onClipboardCopy);
+        self.removeEventListener("cut",  this.onClipboardCut);
+        self.removeEventListener("paste", this.onClipboardPaste);
+    }
+
     /**
      * Connect the texture to a hosting mesh to enable interactions
      * @param mesh defines the mesh to attach to

+ 6 - 0
gui/src/2D/controls/container.ts

@@ -264,6 +264,11 @@ export class Container extends Control {
         this._applyStates(context);
 
         if (this._processMeasures(parentMeasure, context)) {
+
+            if (this.onBeforeDrawObservable.hasObservers()) {
+                this.onBeforeDrawObservable.notifyObservers(this);
+            }
+
             this._localDraw(context);
 
             if (this.clipChildren) {
@@ -276,6 +281,7 @@ export class Container extends Control {
             for (var child of this._children) {
                 if (child.isVisible && !child.notRenderable) {
                     child._tempParentMeasure.copyFrom(this._measureForChildren);
+
                     child._draw(this._measureForChildren, context);
 
                     if (child.onAfterDrawObservable.hasObservers()) {

+ 12 - 2
gui/src/2D/controls/control.ts

@@ -156,8 +156,13 @@ export class Control {
     public onDirtyObservable = new Observable<Control>();
 
     /**
-   * An event triggered after the control is drawn
-   */
+     * An event triggered before drawing the control
+     */
+    public onBeforeDrawObservable = new Observable<Control>();
+
+    /**
+     * An event triggered after the control was drawn
+     */
     public onAfterDrawObservable = new Observable<Control>();
 
     /** Gets or set information about font offsets (used to render and align text) */
@@ -1055,6 +1060,10 @@ export class Control {
             context.clip();
         }
 
+        if (this.onBeforeDrawObservable.hasObservers()) {
+            this.onBeforeDrawObservable.notifyObservers(this);
+        }
+
         return true;
     }
 
@@ -1397,6 +1406,7 @@ export class Control {
     /** Releases associated resources */
     public dispose() {
         this.onDirtyObservable.clear();
+        this.onBeforeDrawObservable.clear();
         this.onAfterDrawObservable.clear();
         this.onPointerDownObservable.clear();
         this.onPointerEnterObservable.clear();

+ 245 - 2
gui/src/2D/controls/inputText.ts

@@ -1,7 +1,7 @@
 import { Control } from "./control";
 import { IFocusableControl } from "../advancedDynamicTexture";
 import { ValueAndUnit } from "../valueAndUnit";
-import { Nullable, Observable, Vector2 } from "babylonjs";
+import { Nullable, Observable, Observer, Vector2, ClipboardEventTypes, ClipboardInfo, PointerInfo } from 'babylonjs';
 import { Measure } from "../measure";
 import { VirtualKeyboard } from "./virtualKeyboard";
 
@@ -28,6 +28,14 @@ export class InputText extends Control implements IFocusableControl {
     private _deadKey = false;
     private _addKey = true;
     private _currentKey = "";
+    private _isTextHighlightOn = false;
+    private _textHighlightColor = "#d5e0ff";
+    private _highligherOpacity = 0.4;
+    private _highlightedText = "";
+    private _startHighlightIndex = 0;
+    private _endHighlightIndex = 0;
+    private _onClipboardObserver: Nullable<Observer<ClipboardInfo>>;
+    private _onPointerDblTapObserver: Nullable<Observer<PointerInfo>>;
 
     /** @hidden */
     public _connectedVirtualKeyboard: Nullable<VirtualKeyboard>;
@@ -43,6 +51,14 @@ export class InputText extends Control implements IFocusableControl {
     public onFocusObservable = new Observable<InputText>();
     /** Observable raised when the control loses the focus */
     public onBlurObservable = new Observable<InputText>();
+    /**Observable raised when the text is highlighted */
+    public onTextHighlightObservable = new Observable<InputText>();
+    /**Observable raised when copy event is triggered */
+    public onTextCopyObservable = new Observable<InputText>();
+    /** Observable raised when cut event is triggered */
+    public onTextCutObservable = new Observable<InputText>();
+    /** Observable raised when paste event is triggered */
+    public onTextPasteObservable = new Observable<InputText>();
 
     /** Gets or sets the maximum width allowed by the control */
     public get maxWidth(): string | number {
@@ -64,6 +80,32 @@ export class InputText extends Control implements IFocusableControl {
         }
     }
 
+    /** Gets and sets the text highlighter transparency; default: 0.4 */
+    public get highligherOpacity(): number {
+        return this._highligherOpacity;
+    }
+
+    public set highligherOpacity(value: number) {
+        if (this._highligherOpacity === value) {
+            return;
+        }
+        this._highligherOpacity = value;
+        this._markAsDirty();
+    }
+
+    /** Gets and sets the text hightlight color */
+    public get textHighlightColor(): string {
+        return this._textHighlightColor;
+    }
+
+    public set textHighlightColor(value: string) {
+        if (this._textHighlightColor === value) {
+            return;
+        }
+        this._textHighlightColor = value;
+        this._markAsDirty();
+    }
+
     /** Gets or sets control margin */
     public get margin(): string {
         return this._margin.toString(this._host);
@@ -176,6 +218,18 @@ export class InputText extends Control implements IFocusableControl {
         this._deadKey = flag;
     }
 
+    /** Gets or sets the highlight text */
+    public get highlightedText(): string {
+        return this._highlightedText;
+    }
+    public set highlightedText(text: string) {
+        if (this._highlightedText === text) {
+            return;
+        }
+        this._highlightedText = text;
+        this._markAsDirty();
+    }
+
     /** Gets or sets if the current key should be added */
     public get addKey(): boolean {
         return this._addKey;
@@ -246,6 +300,15 @@ export class InputText extends Control implements IFocusableControl {
         this._markAsDirty();
 
         this.onBlurObservable.notifyObservers(this);
+
+        this._host.unRegisterClipboardEvents();
+        if (this._onClipboardObserver) {
+            this._host.onClipboardObservable.remove(this._onClipboardObserver);
+        }
+        let scene = this._host.getScene();
+        if (this._onPointerDblTapObserver && scene) {
+            scene.onPointerObservable.remove(this._onPointerDblTapObserver);
+        }
     }
 
     /** @hidden */
@@ -270,6 +333,41 @@ export class InputText extends Control implements IFocusableControl {
             this._host.focusedControl = null;
             return;
         }
+
+        this._host.registerClipboardEvents();
+
+        this._onClipboardObserver = this._host.onClipboardObservable.add((clipboardInfo) => {
+            // process clipboard event, can be configured.
+             switch (clipboardInfo.type){
+                 case ClipboardEventTypes.COPY:
+                         this._onCopyText(clipboardInfo.event);
+                         this.onTextCopyObservable.notifyObservers(this);
+                         break;
+                 case ClipboardEventTypes.CUT:
+                         this._onCutText(clipboardInfo.event);
+                         this.onTextCutObservable.notifyObservers(this);
+                         break;
+                 case ClipboardEventTypes.PASTE:
+                         this._onPasteText(clipboardInfo.event);
+                         this.onTextPasteObservable.notifyObservers(this);
+                         break;
+                 default: return;
+              }
+        });
+
+        let scene = this._host.getScene();
+        if (scene) {
+            //register the pointer double tap event
+            this._onPointerDblTapObserver = scene.onPointerObservable.add((pointerInfo) => {
+                if (!this._isFocused) {
+                    return;
+                }
+                if (pointerInfo.type === BABYLON.PointerEventTypes.POINTERDOUBLETAP) {
+                    this._processDblClick(pointerInfo);
+                }
+            });
+        }
+
     }
 
     protected _getTypeName(): string {
@@ -289,6 +387,29 @@ export class InputText extends Control implements IFocusableControl {
 
     /** @hidden */
     public processKey(keyCode: number, key?: string, evt?: KeyboardEvent) {
+
+        //return if clipboard event keys (i.e -ctr/cmd + c,v,x)
+        if (evt && (evt.ctrlKey || evt.metaKey) && (keyCode === 67 || keyCode === 86 || keyCode === 88)) {
+            return;
+        }
+
+        //select all
+        if (evt && (evt.ctrlKey || evt.metaKey) && keyCode === 65) {
+
+            this._blinkIsEven = false;
+            this._isTextHighlightOn = true;
+            evt.preventDefault();
+
+            //if already highlighted pass
+            if (this._highlightedText) {
+                return;
+            }
+
+            this._startHighlightIndex = 0;
+            this._endHighlightIndex = this._text.length;
+            this._cursorOffset = 0;
+            return;
+        }
         // Specific cases
         switch (keyCode) {
             case 32: //SPACE
@@ -301,6 +422,18 @@ export class InputText extends Control implements IFocusableControl {
                 break;
             case 8: // BACKSPACE
                 if (this._text && this._text.length > 0) {
+                    //delete the highlighted text
+                    if (this._isTextHighlightOn) {
+                        this.text = this._text.slice(0, this._startHighlightIndex) + this._text.slice(this._endHighlightIndex);
+                        this._isTextHighlightOn = false;
+                        this._cursorOffset =  this.text.length - this._startHighlightIndex;
+                        this._blinkIsEven = false;
+                        if (evt) {
+                            evt.preventDefault();
+                        }
+                        return;
+                    }
+                    //delete single character
                     if (this._cursorOffset === 0) {
                         this.text = this._text.substr(0, this._text.length - 1);
                     } else {
@@ -315,11 +448,27 @@ export class InputText extends Control implements IFocusableControl {
                 }
                 return;
             case 46: // DELETE
+                if (this._isTextHighlightOn) {
+                    this.text = this._text.slice(0, this._startHighlightIndex) + this._text.slice(this._endHighlightIndex);
+                    let decrementor = (this._endHighlightIndex - this._startHighlightIndex);
+                    while (decrementor > 0 && this._cursorOffset > 0) {
+                        this._cursorOffset--;
+                    }
+                    this._isTextHighlightOn = false;
+                    this._cursorOffset = this.text.length - this._startHighlightIndex;
+                    if (evt) {
+                        evt.preventDefault();
+                    }
+                    return;
+                }
                 if (this._text && this._text.length > 0  && this._cursorOffset > 0) {
                     let deletePosition = this._text.length - this._cursorOffset;
                     this.text = this._text.slice(0, deletePosition) + this._text.slice(deletePosition + 1);
                     this._cursorOffset--;
                 }
+                if (evt) {
+                    evt.preventDefault();
+                }
                 return;
             case 13: // RETURN
                 this._host.focusedControl = null;
@@ -335,6 +484,14 @@ export class InputText extends Control implements IFocusableControl {
                 this._markAsDirty();
                 return;
             case 37: // LEFT
+                if (evt && evt.shiftKey) {
+                    if (!this._isTextHighlightOn) {
+                        this._isTextHighlightOn = true;
+                        this._endHighlightIndex = this._text.length - this._cursorOffset;
+                        this._startHighlightIndex = this._endHighlightIndex;
+                    }
+                    (this._startHighlightIndex < 0) ? 0 : --this._startHighlightIndex;
+                }
                 this._cursorOffset++;
                 if (this._cursorOffset > this._text.length) {
                     this._cursorOffset = this._text.length;
@@ -343,6 +500,14 @@ export class InputText extends Control implements IFocusableControl {
                 this._markAsDirty();
                 return;
             case 39: // RIGHT
+                if (evt && evt.shiftKey) {
+                    if (!this._isTextHighlightOn) {
+                        this._isTextHighlightOn = true;
+                        this._startHighlightIndex = this._text.length - this._cursorOffset;
+                        this._endHighlightIndex = this._startHighlightIndex;
+                    }
+                    (this._endHighlightIndex > this._text.length) ? this._text.length - 1 : ++this._endHighlightIndex;
+                }
                 this._cursorOffset--;
                 if (this._cursorOffset < 0) {
                     this._cursorOffset = 0;
@@ -357,6 +522,7 @@ export class InputText extends Control implements IFocusableControl {
                 this.deadKey = true;
                 break;
         }
+        this._isTextHighlightOn = false;
 
         // Printable characters
         if (key &&
@@ -381,12 +547,70 @@ export class InputText extends Control implements IFocusableControl {
             }
         }
     }
-
     /** @hidden */
+    private _processDblClick(evt: PointerInfo) {
+        //pre-find the start and end index of the word under cursor, speeds up the rendering
+        this._startHighlightIndex = this._text.length - this._cursorOffset;
+        this._endHighlightIndex = this._startHighlightIndex;
+        for (let rWord = /\w+/g, left = 1, right = 1; this._startHighlightIndex > 0 && this._endHighlightIndex < this._text.length && (left || right);) {
+            right = (this._text[this._endHighlightIndex].search(rWord) !== -1) ? ++this._endHighlightIndex : 0;
+            left =  (this._text[this._startHighlightIndex - 1 ].search(rWord) !== -1) ? --this._startHighlightIndex : 0;
+        }
+        this.onTextHighlightObservable.notifyObservers(this);
+        this._isTextHighlightOn = true;
+        this._blinkIsEven = false;
+    }
+
+    /**
+     * Handles the keyboard event
+     * @param evt Defines the KeyboardEvent
+     */
     public processKeyboard(evt: KeyboardEvent): void {
+        // process pressed key
         this.processKey(evt.keyCode, evt.key, evt);
     }
 
+    /** @hidden */
+    private _onCopyText(ev: ClipboardEvent): void {
+        this._isTextHighlightOn = false;
+        //when write permission to clipbaord data is denied
+        try {
+            ev.clipboardData.setData("text/plain", this._highlightedText);
+        }
+        catch {} //pass
+        this._host.clipboardData = this._highlightedText;
+    }
+    /** @hidden */
+    private _onCutText(ev: ClipboardEvent): void {
+        if (!this._highlightedText) {
+            return;
+        }
+        this.text = this._text.slice(0, this._startHighlightIndex) + this._text.slice(this._endHighlightIndex);
+        this._isTextHighlightOn = false;
+        this._cursorOffset = this.text.length - this._startHighlightIndex;
+        //when write permission to clipbaord data is denied
+        try {
+            ev.clipboardData.setData("text/plain", this._highlightedText);
+        }
+        catch { } //pass
+
+        this._host.clipboardData = this._highlightedText;
+        this._highlightedText = "";
+    }
+    /** @hidden */
+    private _onPasteText(ev: ClipboardEvent): void {
+        let data: string = "";
+        if (ev.clipboardData && ev.clipboardData.types.indexOf("text/plain") !== -1) {
+            data = ev.clipboardData.getData("text/plain");
+        }
+        else {
+            //get the cached data; returns blank string by default
+            data = this._host.clipboardData;
+        }
+        let insertPosition = this._text.length - this._cursorOffset;
+        this.text = this._text.slice(0, insertPosition) + data + this._text.slice(insertPosition);
+    }
+
     public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
         context.save();
 
@@ -514,6 +738,19 @@ export class InputText extends Control implements IFocusableControl {
                     this._blinkIsEven = !this._blinkIsEven;
                     this._markAsDirty();
                 }, 500);
+
+                 //show the highlighted text
+                if (this._isTextHighlightOn) {
+                    clearTimeout(this._blinkTimeout);
+                    let highlightCursorOffsetWidth = context.measureText(this.text.substring(this._startHighlightIndex)).width;
+                    let highlightCursorLeft = this._scrollLeft + this._textWidth - highlightCursorOffsetWidth;
+                    this._highlightedText = this.text.substring(this._startHighlightIndex, this._endHighlightIndex);
+                    //for transparancy
+                    context.globalAlpha = this._highligherOpacity;
+                    context.fillStyle = this._textHighlightColor;
+                    context.fillRect(highlightCursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, context.measureText(this.text.substring(this._startHighlightIndex, this._endHighlightIndex)).width, this._fontOffset.height);
+                    context.globalAlpha = 1.0;
+                }
             }
 
             context.restore();
@@ -538,6 +775,8 @@ export class InputText extends Control implements IFocusableControl {
         }
 
         this._clickedCoordinate = coordinates.x;
+        this._isTextHighlightOn = false;
+        this._highlightedText = "";
         if (this._host.focusedControl === this) {
             // Move cursor
             clearTimeout(this._blinkTimeout);
@@ -566,5 +805,9 @@ export class InputText extends Control implements IFocusableControl {
         this.onBlurObservable.clear();
         this.onFocusObservable.clear();
         this.onTextChangedObservable.clear();
+        this.onTextCopyObservable.clear();
+        this.onTextCutObservable.clear();
+        this.onTextPasteObservable.clear();
+        this.onTextHighlightObservable.clear();
     }
 }

+ 2 - 2
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -613,7 +613,7 @@ module BABYLON.GLTF2 {
 
             if (primitives.length === 1) {
                 const primitive = mesh.primitives[0];
-                promises.push(this._loadMeshPrimitiveAsync(`${context}/primitives/${primitive.index}}`, name, node, mesh, primitive, (babylonMesh) => {
+                promises.push(this._loadMeshPrimitiveAsync(`${context}/primitives/${primitive.index}`, name, node, mesh, primitive, (babylonMesh) => {
                     node._babylonTransformNode = babylonMesh;
                 }));
             }
@@ -621,7 +621,7 @@ module BABYLON.GLTF2 {
                 const babylonTransformNode = new TransformNode(name, this.babylonScene);
                 node._babylonTransformNode = babylonTransformNode;
                 for (const primitive of primitives) {
-                    promises.push(this._loadMeshPrimitiveAsync(`${context}/primitives/${primitive.index}}`, `${name}_primitive${primitive.index}`, node, mesh, primitive, (babylonMesh) => {
+                    promises.push(this._loadMeshPrimitiveAsync(`${context}/primitives/${primitive.index}`, `${name}_primitive${primitive.index}`, node, mesh, primitive, (babylonMesh) => {
                         babylonMesh.parent = babylonTransformNode;
                         node._primitiveBabylonMeshes = node._primitiveBabylonMeshes || [];
                         node._primitiveBabylonMeshes.push(babylonMesh);

+ 46 - 4
materialsLibrary/src/grid/babylon.gridmaterial.ts

@@ -2,9 +2,12 @@
 
 module BABYLON {
     class GridMaterialDefines extends MaterialDefines {
+        public OPACITY = false;
         public TRANSPARENT = false;
         public FOG = false;
         public PREMULTIPLYALPHA = false;
+        public UV1 = false;
+        public UV2 = false;
 
         constructor() {
             super();
@@ -66,6 +69,11 @@ module BABYLON {
         @serialize()
         public preMultiplyAlpha = false;
 
+        @serializeAsTexture("opacityTexture")
+        private _opacityTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public opacityTexture: BaseTexture;
+
         private _gridControl: Vector4 = new Vector4(this.gridRatio, this.majorUnitFrequency, this.minorUnitVisibility, this.opacity);
 
         private _renderId: number;
@@ -83,7 +91,7 @@ module BABYLON {
          * Returns wehter or not the grid requires alpha blending.
          */
         public needAlphaBlending(): boolean {
-            return this.opacity < 1.0;
+            return this.opacity < 1.0 || this._opacityTexture && this._opacityTexture.isReady();
         }
 
         public needAlphaBlendingForMesh(mesh: AbstractMesh): boolean {
@@ -120,6 +128,21 @@ module BABYLON {
                 defines.markAsUnprocessed();
             }
 
+            // Textures
+            if (defines._areTexturesDirty) {
+                defines._needUVs = false;
+                if (scene.texturesEnabled) {
+                    if (this._opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                        if (!this._opacityTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.OPACITY = true;
+                        }
+                    }
+                }
+            }
+
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, false, this.fogEnabled, false, defines);
 
             // Get correct effect
@@ -127,15 +150,27 @@ module BABYLON {
                 defines.markAsProcessed();
                 scene.resetCachedMaterial();
 
-                // Attributes
+                // Attribs
+                MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, false);
+
+                //Attributes
                 var attribs = [VertexBuffer.PositionKind, VertexBuffer.NormalKind];
 
+                if (defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (defines.UV2) {
+                    attribs.push(VertexBuffer.UV2Kind);
+                }
+
                 // Defines
                 var join = defines.toString();
                 subMesh.setEffect(scene.getEngine().createEffect("grid",
                     attribs,
-                    ["projection", "worldView", "mainColor", "lineColor", "gridControl", "gridOffset", "vFogInfos", "vFogColor", "world", "view"],
-                    [],
+                    ["projection", "worldView", "mainColor", "lineColor", "gridControl", "gridOffset", "vFogInfos", "vFogColor", "world", "view",
+                        "opacityMatrix", "vOpacityInfos"],
+                    ["opacitySampler"],
                     join,
                     undefined,
                     this.onCompiled,
@@ -184,6 +219,13 @@ module BABYLON {
                 this._gridControl.z = this.minorUnitVisibility;
                 this._gridControl.w = this.opacity;
                 this._activeEffect.setVector4("gridControl", this._gridControl);
+
+                if (this._opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                    this._activeEffect.setTexture("opacitySampler", this._opacityTexture);
+
+                    this._activeEffect.setFloat2("vOpacityInfos", this._opacityTexture.coordinatesIndex, this._opacityTexture.level);
+                    this._activeEffect.setMatrix("opacityMatrix", this._opacityTexture.getTextureMatrix());
+                }
             }
             // Fog
             MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);

+ 17 - 4
materialsLibrary/src/grid/grid.fragment.fx

@@ -19,6 +19,13 @@ varying vec3 vNormal;
 
 #include<fogFragmentDeclaration>
 
+// Samplers
+#ifdef OPACITY
+varying vec2 vOpacityUV;
+uniform sampler2D opacitySampler;
+uniform vec2 vOpacityInfos;
+#endif
+
 float getVisibility(float position) {
     // Major grid line every Frequency defined in material.
     float majorGridFrequency = gridControl.y;
@@ -94,19 +101,25 @@ void main(void) {
     #include<fogFragment>
 #endif
 
+    float opacity = 1.0;
 #ifdef TRANSPARENT
     float distanceToFragment = length(vCameraSpacePosition.xyz);
     float cameraPassThrough = clamp(distanceToFragment - 0.25, 0.0, 1.0);
 
-    float opacity = clamp(grid, 0.08, cameraPassThrough * gridControl.w * grid);
+    opacity = clamp(grid, 0.08, cameraPassThrough * gridControl.w * grid);
+#endif    
+
+#ifdef OPACITY
+	opacity *= texture2D(opacitySampler, vOpacityUV).a;
+#endif    
 
+    // Apply the color.
     gl_FragColor = vec4(color.rgb, opacity);
 
+#ifdef TRANSPARENT
     #ifdef PREMULTIPLYALPHA
         gl_FragColor.rgb *= opacity;
     #endif
-#else
-    // Apply the color.
-    gl_FragColor = vec4(color.rgb, 1.0);
+#else    
 #endif
 }

+ 29 - 0
materialsLibrary/src/grid/grid.vertex.fx

@@ -3,6 +3,12 @@
 // Attributes
 attribute vec3 position;
 attribute vec3 normal;
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
 
 // Uniforms
 uniform mat4 projection;
@@ -19,6 +25,12 @@ varying vec3 vNormal;
 
 #include<fogVertexDeclaration>
 
+#ifdef OPACITY
+varying vec2 vOpacityUV;
+uniform mat4 opacityMatrix;
+uniform vec2 vOpacityInfos;
+#endif
+
 void main(void) {
 
     #ifdef FOG
@@ -34,6 +46,23 @@ void main(void) {
         vCameraSpacePosition = cameraSpacePosition;
     #endif
 
+#ifdef OPACITY
+#ifndef UV1
+	vec2 uv = vec2(0., 0.);
+#endif
+#ifndef UV2
+	vec2 uv2 = vec2(0., 0.);
+#endif
+	if (vOpacityInfos.x == 0.)
+	{
+		vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif    
+
     vPosition = position;
     vNormal = normal;
 }

+ 9 - 7
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -55,11 +55,10 @@ module BABYLON {
         public NORMAL = false;
         public UV1 = false;
         public UV2 = false;
-        public VERTEXCOLOR = false;
-        public VERTEXALPHA = false;
         public NUM_BONE_INFLUENCERS = 0;
         public BonesPerMesh = 0;
         public INSTANCES = false;
+        public LIGHTING = false;
 
         constructor() {
             super();
@@ -96,6 +95,10 @@ module BABYLON {
             return (this.alpha < 1.0);
         }
 
+        public needAlphaBlendingForMesh(mesh: AbstractMesh): boolean {
+            return this.needAlphaBlending() || (mesh.visibility < 1.0);
+        }
+
         public needAlphaTesting(): boolean {
             return false;
         }
@@ -146,11 +149,14 @@ module BABYLON {
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, this._shouldTurnAlphaTestOn(mesh), defines);
 
             // Lights
-            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+            defines._needNormals = true;
+            MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
 
             // Values that need to be evaluated on every frame
             MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
 
+            defines.LIGHTING = !this._disableLighting;
+
             // Attribs
             MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
 
@@ -187,10 +193,6 @@ module BABYLON {
                     attribs.push(VertexBuffer.UV2Kind);
                 }
 
-                if (defines.VERTEXCOLOR) {
-                    attribs.push(VertexBuffer.ColorKind);
-                }
-
                 MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
                 MaterialHelper.PrepareAttributesForInstances(attribs, defines);
 

+ 7 - 14
materialsLibrary/src/normal/normal.fragment.fx

@@ -11,10 +11,7 @@ varying vec3 vPositionW;
 varying vec3 vNormalW;
 #endif
 
-#ifdef VERTEXCOLOR
-varying vec4 vColor;
-#endif
-
+#ifdef LIGHTING
 // Helper functions
 #include<helperFunctions>
 
@@ -27,6 +24,7 @@ varying vec4 vColor;
 
 #include<lightsFragmentFunctions>
 #include<shadowsFragmentFunctions>
+#endif
 
 // Samplers
 #ifdef DIFFUSE
@@ -69,10 +67,6 @@ void main(void) {
     baseColor = mix(baseColor, vec4(vNormalW, 1.0), 0.5);
 #endif
 
-#ifdef VERTEXCOLOR
-	baseColor.rgb *= vColor.rgb;
-#endif
-
 	// Normal
 #ifdef NORMAL
 	vec3 normalW = normalize(vNormalW);
@@ -81,6 +75,8 @@ void main(void) {
 #endif
 
 	// Lighting
+
+#ifdef LIGHTING
 	vec3 diffuseBase = vec3(0., 0., 0.);
     lightingInfo info;
 	float shadow = 1.;
@@ -90,13 +86,10 @@ void main(void) {
 #include<lightFragment>[1]
 #include<lightFragment>[2]
 #include<lightFragment>[3]
-
-
-#ifdef VERTEXALPHA
-	alpha *= vColor.a;
-#endif
-
 	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;
+#else
+	vec3 finalDiffuse =  baseColor.rgb;
+#endif
 
 	// Composition
 	vec4 color = vec4(finalDiffuse, alpha);

+ 0 - 10
materialsLibrary/src/normal/normal.vertex.fx

@@ -39,11 +39,6 @@ varying vec3 vPositionW;
 varying vec3 vNormalW;
 #endif
 
-#ifdef VERTEXCOLOR
-varying vec4 vColor;
-#endif
-
-
 #include<clipPlaneVertexDeclaration>
 
 #include<fogVertexDeclaration>
@@ -89,11 +84,6 @@ void main(void) {
 #include<fogVertex>
 #include<shadowsVertex>[0..maxSimultaneousLights]
 
-	// Vertex color
-#ifdef VERTEXCOLOR
-	vColor = color;
-#endif
-
 	// Point size
 #ifdef POINTSIZE
 	gl_PointSize = pointSize;

+ 23 - 28
materialsLibrary/test/addgrid.js

@@ -1,43 +1,44 @@
 window.prepareGrid = function() {
 	var grid = new BABYLON.GridMaterial("grid", scene);
+	grid.opacityTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/backgroundGround.png", scene);
 
 	registerRangeUI("grid", "LineColorR", 0, 1, function(value) {
 		grid.lineColor.r = value;
 	}, function() {
 		return grid.lineColor.r;
 	});
-    
+
 	registerRangeUI("grid", "LineColorG", 0, 1, function(value) {
 		grid.lineColor.g = value;
 	}, function() {
 		return grid.lineColor.g;
 	});
-    
-  registerRangeUI("grid", "LineColorB", 0, 1, function(value) {
+
+	registerRangeUI("grid", "LineColorB", 0, 1, function(value) {
 		grid.lineColor.b = value;
 	}, function() {
 		return grid.lineColor.b;
 	});
-    
-  registerRangeUI("grid", "MainColorR", 0, 1, function(value) {
+
+	registerRangeUI("grid", "MainColorR", 0, 1, function(value) {
 		grid.mainColor.r = value;
 	}, function() {
 		return grid.mainColor.r;
 	});
-    
-  registerRangeUI("grid", "MainColorG", 0, 1, function(value) {
+
+	registerRangeUI("grid", "MainColorG", 0, 1, function(value) {
 		grid.mainColor.g = value;
 	}, function() {
 		return grid.mainColor.g;
 	});
-    
-  registerRangeUI("grid", "MainColorB", 0, 1, function(value) {
+
+	registerRangeUI("grid", "MainColorB", 0, 1, function(value) {
 		grid.mainColor.b = value;
 	}, function() {
 		return grid.mainColor.b;
 	});
-    
-  registerRangeUI("grid", "GridRatio", 0, 10, function(value) {
+
+	registerRangeUI("grid", "GridRatio", 0, 10, function(value) {
 		grid.gridRatio = value;
 	}, function() {
 		return grid.gridRatio;
@@ -48,43 +49,37 @@ window.prepareGrid = function() {
 	}, function() {
 		return grid.gridOffset.x;
 	});
-    
-  registerRangeUI("grid", "OffsetY", 0, 2, function(value) {
+
+	registerRangeUI("grid", "OffsetY", 0, 2, function(value) {
 		grid.gridOffset.y = value;
 	}, function() {
 		return grid.gridOffset.y;
 	});
-    
-  registerRangeUI("grid", "OffsetZ", 0, 2, function(value) {
+
+	registerRangeUI("grid", "OffsetZ", 0, 2, function(value) {
 		grid.gridOffset.z = value;
 	}, function() {
 		return grid.gridOffset.z;
 	});
-    
-    
-  registerRangeUI("grid", "MajorUnitFrequency", 1, 10, function(value) {
+
+
+	registerRangeUI("grid", "MajorUnitFrequency", 1, 10, function(value) {
 		grid.majorUnitFrequency = value;
 	}, function() {
 		return grid.majorUnitFrequency;
 	});
-    
-  registerRangeUI("grid", "MinorUnitVisibility", 0, 1, function(value) {
+
+	registerRangeUI("grid", "MinorUnitVisibility", 0, 1, function(value) {
 		grid.minorUnitVisibility = value;
 	}, function() {
 		return grid.minorUnitVisibility;
 	});
-    
-  registerRangeUI("grid", "Opacity", 0, 1, function(value) {
+
+	registerRangeUI("grid", "Opacity", 0, 1, function(value) {
 		grid.opacity = value;
 	}, function() {
 		return grid.opacity;
 	});
 
-	registerRangeUI("grid", "PlainGrid", 0, 1, function(value) {
-		grid.usePlainGrid = value;
-	}, function() {
-		return grid.usePlainGrid;
-	});
-
 	return grid;
 }

+ 16 - 4
src/Animations/babylon.animationGroup.ts

@@ -211,6 +211,10 @@ module BABYLON {
 
             this._speedRatio = speedRatio;
 
+            if (from !== undefined && to !== undefined && from > to && this._speedRatio > 0) {
+                this._speedRatio = -speedRatio;
+            }
+
             this._isStarted = true;
 
             return this;
@@ -401,15 +405,23 @@ module BABYLON {
                 var targetedAnimation = parsedAnimationGroup.targetedAnimations[i];
                 var animation = Animation.Parse(targetedAnimation.animation);
                 var id = targetedAnimation.targetId;
-                var targetNode = scene.getNodeByID(id);
+                if (targetedAnimation.animation.property === "influence") { // morph target animation
+                    let morphTarget = scene.getMorphTargetById(id);
+                    if (morphTarget) {
+                        animationGroup.addTargetedAnimation(animation, morphTarget);
+                    }
+                }
+                else {
+                    var targetNode = scene.getNodeByID(id);
 
-                if (targetNode != null) {
-                    animationGroup.addTargetedAnimation(animation, targetNode);
+                    if (targetNode != null) {
+                        animationGroup.addTargetedAnimation(animation, targetNode);
+                    }
                 }
             }
 
             if (parsedAnimationGroup.from !== null && parsedAnimationGroup.from !== null) {
-                animationGroup.normalize(parsedAnimationGroup.from, parsedAnimationGroup.to);
+                animationGroup.normalize(parsedAnimationGroup.from, parsedAnimationGroup.to);
             }
 
             return animationGroup;

+ 49 - 0
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -643,6 +643,7 @@ module BABYLON {
             // Create VR cameras
             if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
                 this._vrDeviceOrientationCamera = new VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene);
+                this._vrDeviceOrientationCamera.angularSensibility = Number.MAX_VALUE;
             }
             this._webVRCamera = new WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions);
             this._webVRCamera.useStandingMatrix();
@@ -860,6 +861,7 @@ module BABYLON {
             }
         }
 
+        private _cachedAngularSensibility = {angularSensibilityX: null, angularSensibilityY: null, angularSensibility: null};
         /**
          * Attempt to enter VR. If a headset is connected and ready, will request present on that.
          * Otherwise, will use the fullscreen API.
@@ -879,6 +881,7 @@ module BABYLON {
 
                 if (this.vrDeviceOrientationCamera) {
                     this.vrDeviceOrientationCamera.rotation = BABYLON.Quaternion.FromRotationMatrix(this._scene.activeCamera.getWorldMatrix().getRotationMatrix()).toEulerAngles();
+                    this.vrDeviceOrientationCamera.angularSensibility = 2000;
                 }
                 if (this.webVRCamera) {
                     var currentYRotation = this.webVRCamera.deviceRotationQuaternion.toEulerAngles().y;
@@ -890,6 +893,20 @@ module BABYLON {
 
                 // make sure that we return to the last active camera
                 this._existingCamera = this._scene.activeCamera;
+
+                // Remove and cache angular sensability to avoid camera rotation when in VR
+                if ((<any>this._existingCamera).angularSensibilityX) {
+                    this._cachedAngularSensibility.angularSensibilityX = (<any>this._existingCamera).angularSensibilityX;
+                    (<any>this._existingCamera).angularSensibilityX = Number.MAX_VALUE;
+                }
+                if ((<any>this._existingCamera).angularSensibilityY) {
+                    this._cachedAngularSensibility.angularSensibilityY = (<any>this._existingCamera).angularSensibilityY;
+                    (<any>this._existingCamera).angularSensibilityY = Number.MAX_VALUE;
+                }
+                if ((<any>this._existingCamera).angularSensibility) {
+                    this._cachedAngularSensibility.angularSensibility = (<any>this._existingCamera).angularSensibility;
+                    (<any>this._existingCamera).angularSensibility = Number.MAX_VALUE;
+                }
             }
 
             if (this._webVRrequesting) {
@@ -945,15 +962,47 @@ module BABYLON {
 
                 }
 
+                if (this.vrDeviceOrientationCamera) {
+                    this.vrDeviceOrientationCamera.angularSensibility = Number.MAX_VALUE;
+                }
+
                 if (this._deviceOrientationCamera) {
                     this._deviceOrientationCamera.position = this._position;
                     this._scene.activeCamera = this._deviceOrientationCamera;
                     if (this._canvas) {
                         this._scene.activeCamera.attachControl(this._canvas);
                     }
+
+                    // Restore angular sensibility
+                    if (this._cachedAngularSensibility.angularSensibilityX) {
+                        (<any>this._deviceOrientationCamera).angularSensibilityX = this._cachedAngularSensibility.angularSensibilityX;
+                        this._cachedAngularSensibility.angularSensibilityX = null;
+                    }
+                    if (this._cachedAngularSensibility.angularSensibilityY) {
+                        (<any>this._deviceOrientationCamera).angularSensibilityY = this._cachedAngularSensibility.angularSensibilityY;
+                        this._cachedAngularSensibility.angularSensibilityY = null;
+                    }
+                    if (this._cachedAngularSensibility.angularSensibility) {
+                        (<any>this._deviceOrientationCamera).angularSensibility = this._cachedAngularSensibility.angularSensibility;
+                        this._cachedAngularSensibility.angularSensibility = null;
+                    }
                 } else if (this._existingCamera) {
                     this._existingCamera.position = this._position;
                     this._scene.activeCamera = this._existingCamera;
+
+                    // Restore angular sensibility
+                    if (this._cachedAngularSensibility.angularSensibilityX) {
+                        (<any>this._existingCamera).angularSensibilityX = this._cachedAngularSensibility.angularSensibilityX;
+                        this._cachedAngularSensibility.angularSensibilityX = null;
+                    }
+                    if (this._cachedAngularSensibility.angularSensibilityY) {
+                        (<any>this._existingCamera).angularSensibilityY = this._cachedAngularSensibility.angularSensibilityY;
+                        this._cachedAngularSensibility.angularSensibilityY = null;
+                    }
+                    if (this._cachedAngularSensibility.angularSensibility) {
+                        (<any>this._existingCamera).angularSensibility = this._cachedAngularSensibility.angularSensibility;
+                        this._cachedAngularSensibility.angularSensibility = null;
+                    }
                 }
 
                 this.updateButtonVisibility();

+ 6 - 4
src/Culling/babylon.ray.ts

@@ -385,14 +385,16 @@ module BABYLON {
             // get the difference of the two closest points
             const qtc = Tmp.Vector3[4];
             v.scaleToRef(tc, qtc);
-            const dP = Tmp.Vector3[5];
-            u.scaleToRef(sc, dP);
-            dP.addInPlace(w).subtractInPlace(qtc);  // = S1(sc) - S2(tc)
+            const qsc = Tmp.Vector3[5];
+            u.scaleToRef(sc, qsc);
+            qsc.addInPlace(w);
+            const dP = Tmp.Vector3[6];
+            qsc.subtractToRef(qtc, dP); // = S1(sc) - S2(tc)
 
             var isIntersected = (tc > 0) && (tc <= this.length) && (dP.lengthSquared() < (threshold * threshold));   // return intersection result
 
             if (isIntersected) {
-                return qtc.length();
+                return qsc.length();
             }
             return -1;
         }

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

@@ -561,6 +561,11 @@ module BABYLON {
         public scenes = new Array<Scene>();
 
         /**
+         * Event raised when a new scene is created
+         */
+        public onNewSceneAddedObservable = new Observable<Scene>();
+
+        /**
          * Gets the list of created postprocesses
          */
         public postProcesses = new Array<PostProcess>();
@@ -6846,6 +6851,8 @@ module BABYLON {
 
             this.stopRenderLoop();
 
+            this.onNewSceneAddedObservable.clear();
+
             // Release postProcesses
             while (this.postProcesses.length) {
                 this.postProcesses[0].dispose();

+ 57 - 0
src/Events/babylon.clipboardEvents.ts

@@ -0,0 +1,57 @@
+
+module BABYLON {
+    /**
+     * Gather the list of clipboard event types as constants.
+     */
+    export class ClipboardEventTypes {
+        /**
+         * The clipboard event is fired when a copy command is active (pressed).
+         */
+        public static readonly COPY = 0x01; //
+        /**
+         *  The clipboard event is fired when a cut command is active (pressed).
+         */
+        public static readonly CUT = 0x02;
+
+        /**
+         * The clipboard event is fired when a paste command is active (pressed).
+         */
+        public static readonly PASTE = 0x03;
+    }
+    /**
+     * This class is used to store clipboard related info for the onClipboardObservable event.
+     */
+    export class ClipboardInfo {
+        /**
+         *Creates an instance of ClipboardInfo.
+         * @param {number} type
+         * @param {ClipboardEvent} event
+         */
+        constructor(
+            /**
+             * Defines the type of event (BABYLON.ClipboardEventTypes)
+             */
+            public type: number,
+            /**
+             * Defines the related dom event
+             */
+            public event: ClipboardEvent) {
+        }
+
+       /**
+        *  Get the clipboard event's type from the keycode.
+        * @param keyCode Defines the keyCode for the current keyboard event.
+        * @return {number}
+        */
+        public static GetTypeFromCharacter(keyCode: number): number {
+            let charCode = keyCode;
+            //TODO: add codes for extended ASCII
+            switch (charCode){
+                case 67: return ClipboardEventTypes.COPY;
+                case 86: return ClipboardEventTypes.PASTE;
+                case 88: return ClipboardEventTypes.CUT;
+                default: return -1;
+            }
+        }
+    }
+}

+ 11 - 4
src/Materials/Textures/babylon.texture.ts

@@ -205,6 +205,13 @@ module BABYLON {
         }
 
         /**
+         * Gets a boolean indicating if the texture needs to be inverted on the y axis during loading
+         */
+        public get invertY(): boolean {
+            return this._invertY;
+        }
+
+        /**
          * Instantiates a new texture.
          * This represents a texture in babylon. It can be easily loaded from a network, base64 or html input.
          * @see http://doc.babylonjs.com/babylon101/materials#texture
@@ -434,7 +441,7 @@ module BABYLON {
                 this._t1.x, this._t1.y, this._t1.z, 0.0,
                 this._t2.x, this._t2.y, this._t2.z, 0.0,
                 this._t0.x, this._t0.y, this._t0.z, 0.0,
-                       0.0,        0.0,        0.0, 1.0,
+                0.0, 0.0, 0.0, 1.0,
                 this._cachedTextureMatrix
             );
 
@@ -501,10 +508,10 @@ module BABYLON {
                     break;
                 case Texture.PROJECTION_MODE:
                     Matrix.FromValuesToRef(
-                        0.5,  0.0, 0.0, 0.0,
+                        0.5, 0.0, 0.0, 0.0,
                         0.0, -0.5, 0.0, 0.0,
-                        0.0,  0.0, 0.0, 0.0,
-                        0.5,  0.5, 1.0, 1.0,
+                        0.0, 0.0, 0.0, 0.0,
+                        0.5, 0.5, 1.0, 1.0,
                         this._projectionModeMatrix
                     );
 

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

@@ -377,6 +377,11 @@ module BABYLON {
         public name: string;
 
         /**
+         * Gets or sets user defined metadata
+         */
+        public metadata: any = null;
+
+        /**
          * Specifies if the ready state should be checked on each call
          */
         @serialize()
@@ -769,7 +774,7 @@ module BABYLON {
         public _indexInSceneMaterialArray = -1;
 
         /** @hidden */
-        public meshMap: Nullable<{[id: string]: AbstractMesh | undefined}>;
+        public meshMap: Nullable<{ [id: string]: AbstractMesh | undefined }>;
 
         /**
          * Creates a material instance
@@ -1362,7 +1367,7 @@ module BABYLON {
         }
 
         /** @hidden */
-        private  releaseVertexArrayObject(mesh: AbstractMesh, forceDisposeEffect?: boolean) {
+        private releaseVertexArrayObject(mesh: AbstractMesh, forceDisposeEffect?: boolean) {
             if ((<Mesh>mesh).geometry) {
                 var geometry = <Geometry>((<Mesh>mesh).geometry);
                 const scene = this.getScene();

+ 8 - 0
src/Mesh/babylon.abstractMesh.ts

@@ -743,6 +743,14 @@ module BABYLON {
         }
 
         /**
+         * Returns a positive integer : the total number of indices in this mesh geometry.
+         * @returns the numner of indices or zero if the mesh has no geometry.
+         */
+        public getTotalIndices(): number {
+            return 0;
+        }
+
+        /**
          * Returns null by default. Implemented by child classes
          * @returns null
          */

+ 8 - 0
src/Mesh/babylon.instancedMesh.ts

@@ -93,6 +93,14 @@ module BABYLON {
         }
 
         /**
+         * Returns a positive integer : the total number of indices in this mesh geometry.
+         * @returns the numner of indices or zero if the mesh has no geometry.
+         */
+        public getTotalIndices(): number {
+            return this._sourceMesh.getTotalIndices();
+        }
+
+        /**
          * The source mesh of the instance
          */
         public get sourceMesh(): Mesh {

+ 20 - 0
src/Morph/babylon.morphTarget.ts

@@ -43,6 +43,12 @@ module BABYLON {
             }
         }
 
+        /**
+         * Gets or sets the id of the morph Target
+         */
+        @serialize()
+        public id: string;
+
         private _animationPropertiesOverride: Nullable<AnimationPropertiesOverride> = null;
 
         /**
@@ -169,6 +175,9 @@ module BABYLON {
             serializationObject.influence = this.influence;
 
             serializationObject.positions = Array.prototype.slice.call(this.getPositions());
+            if (this.id != null) {
+                serializationObject.id = this.id;
+            }
             if (this.hasNormals) {
                 serializationObject.normals = Array.prototype.slice.call(this.getNormals());
             }
@@ -182,6 +191,14 @@ module BABYLON {
             return serializationObject;
         }
 
+        /**
+         * Returns the string "MorphTarget"
+         * @returns "MorphTarget"
+         */
+        public getClassName(): string {
+            return "MorphTarget";
+        }
+
         // Statics
 
         /**
@@ -194,6 +211,9 @@ module BABYLON {
 
             result.setPositions(serializationObject.positions);
 
+            if (serializationObject.id != null) {
+                result.id = serializationObject.id;
+            }
             if (serializationObject.normals) {
                 result.setNormals(serializationObject.normals);
             }

+ 63 - 0
src/PostProcess/babylon.passPostProcess.ts

@@ -18,4 +18,67 @@ module BABYLON {
             super(name, "pass", null, null, options, camera, samplingMode, engine, reusable, undefined, textureType, undefined, null, blockCompilation);
         }
     }
+
+    /**
+     * PassCubePostProcess which produces an output the same as it's input (which must be a cube texture)
+     */
+    export class PassCubePostProcess extends PostProcess {
+        private _face = 0;
+
+        /**
+         * Gets or sets the cube face to display.
+         *  * 0 is +X
+         *  * 1 is -X
+         *  * 2 is +Y
+         *  * 3 is -Y
+         *  * 4 is +Z
+         *  * 5 is -Z
+         */
+        public get face(): number {
+            return this._face;
+        }
+
+        public set face(value: number) {
+            if (value < 0 || value > 5) {
+                return;
+            }
+
+            this._face = value;
+            switch (this._face) {
+                case 0:
+                    this.updateEffect("#define POSITIVEX");
+                    break;
+                case 1:
+                    this.updateEffect("#define NEGATIVEX");
+                    break;
+                case 2:
+                    this.updateEffect("#define POSITIVEY");
+                    break;
+                case 3:
+                    this.updateEffect("#define NEGATIVEY");
+                    break;
+                case 4:
+                    this.updateEffect("#define POSITIVEZ");
+                    break;
+                case 5:
+                    this.updateEffect("#define NEGATIVEZ");
+                    break;
+            }
+        }
+
+        /**
+         * Creates the PassCubePostProcess
+         * @param name The name of the effect.
+         * @param options The required width/height ratio to downsize to before computing the render pass.
+         * @param camera The camera to apply the render pass to.
+         * @param samplingMode The sampling mode to be used when computing the pass. (default: 0)
+         * @param engine The engine which the post process will be applied. (default: current engine)
+         * @param reusable If the post process can be reused on the same frame. (default: false)
+         * @param textureType The type of texture to be used when performing the post processing.
+         * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
+         */
+        constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera> = null, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
+            super(name, "passCube", null, null, options, camera, samplingMode, engine, reusable, "#define POSITIVEX", textureType, undefined, null, blockCompilation);
+        }
+    }
 }

+ 27 - 0
src/Shaders/passCube.fragment.fx

@@ -0,0 +1,27 @@
+// Samplers
+varying vec2 vUV;
+uniform samplerCube textureSampler;
+
+void main(void) 
+{
+	vec2 uv = vUV * 2.0 - 1.0;
+
+#ifdef POSITIVEX
+	gl_FragColor = textureCube(textureSampler, vec3(1.001, uv.y, uv.x));
+#endif
+#ifdef NEGATIVEX
+	gl_FragColor = textureCube(textureSampler, vec3(-1.001, uv.y, uv.x));
+#endif
+#ifdef POSITIVEY
+	gl_FragColor = textureCube(textureSampler, vec3(uv.y, 1.001, uv.x));
+#endif
+#ifdef NEGATIVEY
+	gl_FragColor = textureCube(textureSampler, vec3(uv.y, -1.001, uv.x));
+#endif
+#ifdef POSITIVEZ
+	gl_FragColor = textureCube(textureSampler, vec3(uv, 1.001));
+#endif
+#ifdef NEGATIVEZ
+	gl_FragColor = textureCube(textureSampler, vec3(uv, -1.001));
+#endif
+}

+ 3 - 3
src/Shaders/pbr.fragment.fx

@@ -508,11 +508,11 @@ void main(void) {
             }
         #endif
 
-        #ifdef GAMMAREFRACTION
+        #ifdef RGBDREFRACTION
             environmentRefraction.rgb = fromRGBD(environmentRefraction);
         #endif
 
-        #ifdef RGBDREFRACTION
+        #ifdef GAMMAREFRACTION
             environmentRefraction.rgb = toLinearSpace(environmentRefraction.rgb);
         #endif
 
@@ -905,4 +905,4 @@ void main(void) {
     //gl_FragColor = vec4(eho, eho, eho, 1.0);
 
     //gl_FragColor = vec4(seo * eho, seo * eho, seo * eho, 1.0);
-}
+}

+ 20 - 0
src/babylon.scene.ts

@@ -1261,6 +1261,8 @@ module BABYLON {
 
             this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
             this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
+
+            this._engine.onNewSceneAddedObservable.notifyObservers(this);
         }
 
         private _defaultMeshCandidates: ISmartArrayLike<AbstractMesh> = {
@@ -3957,6 +3959,24 @@ module BABYLON {
         }
 
         /**
+         * Gets a morph target using a given id (if many are found, this function will pick the first one)
+         * @param id defines the id to search for
+         * @return the found morph target or null if not found at all.
+         */
+        public getMorphTargetById(id: string): Nullable<MorphTarget> {
+            for (let managerIndex = 0; managerIndex < this.morphTargetManagers.length; ++managerIndex) {
+                const morphTargetManager = this.morphTargetManagers[managerIndex];
+                for (let index = 0; index < morphTargetManager.numTargets; ++index) {
+                    const target = morphTargetManager.getTarget(index);
+                    if (target.id === id) {
+                        return target;
+                    }
+                }
+            }
+            return null;
+        }
+
+        /**
          * Gets a boolean indicating if the given mesh is active
          * @param mesh defines the mesh to look for
          * @returns true if the mesh is in the active list