瀏覽代碼

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js into inspector-viewlightfrustum

Popov72 4 年之前
父節點
當前提交
1b172e3a6a
共有 100 個文件被更改,包括 26167 次插入7369 次删除
  1. 14 0
      .vscode/launch.json
  2. 21 9
      Playground/libs/babylon.manager.d.ts
  3. 5 5
      Playground/libs/babylon.manager.js
  4. 624 338
      dist/preview release/babylon.d.ts
  5. 2 2
      dist/preview release/babylon.js
  6. 487 176
      dist/preview release/babylon.max.js
  7. 1 1
      dist/preview release/babylon.max.js.map
  8. 1264 683
      dist/preview release/babylon.module.d.ts
  9. 834 392
      dist/preview release/documentation.d.ts
  10. 210 54
      dist/preview release/gui/babylon.gui.d.ts
  11. 859 15
      dist/preview release/gui/babylon.gui.js
  12. 1 1
      dist/preview release/gui/babylon.gui.js.map
  13. 2 2
      dist/preview release/gui/babylon.gui.min.js
  14. 453 116
      dist/preview release/gui/babylon.gui.module.d.ts
  15. 300 143
      dist/preview release/guiEditor/babylon.guiEditor.d.ts
  16. 10 5
      dist/preview release/guiEditor/babylon.guiEditor.js
  17. 12672 4
      dist/preview release/guiEditor/babylon.guiEditor.max.js
  18. 1 1
      dist/preview release/guiEditor/babylon.guiEditor.max.js.map
  19. 1481 1097
      dist/preview release/guiEditor/babylon.guiEditor.module.d.ts
  20. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js
  21. 3128 3128
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  22. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  23. 0 14
      dist/preview release/inspector/babylon.inspector.d.ts
  24. 28 70
      dist/preview release/inspector/babylon.inspector.module.d.ts
  25. 2 0
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  26. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  27. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  28. 2 0
      dist/preview release/loaders/babylon.glTFFileLoader.js
  29. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  30. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  31. 2 0
      dist/preview release/loaders/babylonjs.loaders.js
  32. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  33. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  34. 157 0
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  35. 384 0
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  36. 1 1
      dist/preview release/packagesSizeBaseLine.json
  37. 1264 683
      dist/preview release/viewer/babylon.module.d.ts
  38. 26 22
      dist/preview release/viewer/babylon.viewer.js
  39. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  40. 4 1
      dist/preview release/what's new.md
  41. 8 7
      gui/src/2D/advancedDynamicTexture.ts
  42. 3 2
      gui/src/2D/controls/focusableButton.ts
  43. 2 1
      gui/src/2D/controls/focusableControl.ts
  44. 4 3
      gui/src/2D/controls/inputText.ts
  45. 20 12
      gui/src/3D/controls/control3D.ts
  46. 3 0
      gui/src/3D/controls/index.ts
  47. 367 0
      gui/src/3D/controls/touchButton3D.ts
  48. 364 0
      gui/src/3D/controls/touchHolographicButton.ts
  49. 81 0
      gui/src/3D/controls/touchMeshButton3D.ts
  50. 52 0
      gui/src/3D/gui3DManager.ts
  51. 119 3
      guiEditor/src/components/propertyTab/propertyTabComponent.tsx
  52. 14 28
      inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx
  53. 3 1
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/textureCanvasManager.ts
  54. 2 0
      loaders/src/glTF/2.0/glTFLoader.ts
  55. 1 0
      sandbox/src/sandbox.tsx
  56. 6 8
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/checkboxPropertyGridComponent.tsx
  57. 5 7
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/colorPickerPropertyGridComponent.tsx
  58. 3 5
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/controlPropertyGridComponent.tsx
  59. 6 8
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/ellipsePropertyGridComponent.tsx
  60. 5 7
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/gridPropertyGridComponent.tsx
  61. 7 9
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent.tsx
  62. 7 9
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/imagePropertyGridComponent.tsx
  63. 8 10
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/inputTextPropertyGridComponent.tsx
  64. 6 8
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/linePropertyGridComponent.tsx
  65. 7 9
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/radioButtonPropertyGridComponent.tsx
  66. 6 8
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/rectanglePropertyGridComponent.tsx
  67. 6 8
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent.tsx
  68. 5 7
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/stackPanelPropertyGridComponent.tsx
  69. 8 10
      inspector/src/components/actionTabs/tabs/propertyGrids/gui/textBlockPropertyGridComponent.tsx
  70. 4 3
      src/Actions/actionEvent.ts
  71. 3 2
      src/Cameras/Inputs/BaseCameraMouseWheelInput.ts
  72. 8 7
      src/Cameras/Inputs/BaseCameraPointersInput.ts
  73. 2 1
      src/Cameras/Inputs/arcRotateCameraMouseWheelInput.ts
  74. 3 2
      src/Cameras/Inputs/arcRotateCameraPointersInput.ts
  75. 2 1
      src/Cameras/Inputs/flyCameraMouseInput.ts
  76. 2 1
      src/Cameras/Inputs/followCameraMouseWheelInput.ts
  77. 4 3
      src/Cameras/Inputs/freeCameraMouseInput.ts
  78. 2 1
      src/Cameras/Inputs/freeCameraTouchInput.ts
  79. 11 1
      src/DeviceInput/InputDevices/deviceEnums.ts
  80. 170 35
      src/DeviceInput/deviceInputSystem.ts
  81. 2 0
      src/Engines/WebGPU/webgpuShaderProcessors.ts
  82. 4 2
      src/Engines/WebGPU/webgpuTextureHelper.ts
  83. 30 0
      src/Engines/constants.ts
  84. 2 1
      src/Engines/engine.ts
  85. 16 0
      src/Engines/nativeEngine.ts
  86. 44 7
      src/Engines/webgpuEngine.ts
  87. 281 0
      src/Events/deviceInputEvents.ts
  88. 2 1
      src/Events/index.ts
  89. 4 2
      src/Events/keyboardEvents.ts
  90. 4 3
      src/Events/pointerEvents.ts
  91. 129 135
      src/Inputs/scene.inputManager.ts
  92. 4 4
      src/Materials/Node/Blocks/Vertex/morphTargetsBlock.ts
  93. 20 0
      src/Meshes/mesh.ts
  94. 4 4
      src/Meshes/thinInstanceMesh.ts
  95. 1 1
      src/Shaders/ShadersInclude/morphTargetsVertexGlobalDeclaration.fx
  96. 3 2
      src/Sprites/spriteSceneComponent.ts
  97. 22 2
      src/XR/features/WebXRHandTracking.ts
  98. 5 4
      src/scene.ts
  99. 2 1
      src/sceneComponent.ts
  100. 0 0
      tests/validation/config.json

+ 14 - 0
.vscode/launch.json

@@ -361,6 +361,20 @@
             ]
             ]
         },
         },
         {
         {
+            "name": "Launch WebGPU Build Validation (Edge) - Direct",
+            "type": "edge",
+            "version": "canary",
+            "request": "launch",
+            "url": "http://localhost:1338/tests/validation/?engine=webgpu",
+            "webRoot": "${workspaceRoot}/",
+            "sourceMaps": true,
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis",
+                "--enable-unsafe-webgpu"
+            ]
+        },
+        {
             "name": "Launch memory checks (Chrome)",
             "name": "Launch memory checks (Chrome)",
             "type": "chrome",
             "type": "chrome",
             "request": "launch",
             "request": "launch",

+ 21 - 9
Playground/libs/babylon.manager.d.ts

@@ -1489,7 +1489,7 @@ declare module BABYLON {
         /** Creates a targeted float animation for tweening.  */
         /** Creates a targeted float animation for tweening.  */
         static CreateTweenAnimation(name: string, targetProperty: string, startValue: number, endValue: number, frameRate?: number, loopMode?: number): BABYLON.Animation;
         static CreateTweenAnimation(name: string, targetProperty: string, startValue: number, endValue: number, frameRate?: number, loopMode?: number): BABYLON.Animation;
         /** Gets the last key frame index value. */
         /** Gets the last key frame index value. */
-        static GetLastKeyFrameValue(animation: BABYLON.Animation): number;
+        static GetLastKeyFrameIndex(animation: BABYLON.Animation): number;
         /** Private internal frame interpolation helper */
         /** Private internal frame interpolation helper */
         private static InterpolateAnimation;
         private static InterpolateAnimation;
         /** Initialize default shader material properties */
         /** Initialize default shader material properties */
@@ -2177,6 +2177,7 @@ declare module BABYLON {
         private _isPhysicsReady;
         private _isPhysicsReady;
         private _maxCollisions;
         private _maxCollisions;
         private _useGhostSweepTest;
         private _useGhostSweepTest;
+        private _tmpPositionBuffer;
         private _tmpCollisionContacts;
         private _tmpCollisionContacts;
         updatePosition: boolean;
         updatePosition: boolean;
         getInternalCharacter(): any;
         getInternalCharacter(): any;
@@ -2214,7 +2215,7 @@ declare module BABYLON {
         protected m_moveDeltaX: number;
         protected m_moveDeltaX: number;
         protected m_moveDeltaZ: number;
         protected m_moveDeltaZ: number;
         protected m_physicsEngine: BABYLON.IPhysicsEngine;
         protected m_physicsEngine: BABYLON.IPhysicsEngine;
-        protected m_collisionPosition: BABYLON.Vector3;
+        protected m_characterPosition: BABYLON.Vector3;
         protected internalWarp(position: any): void;
         protected internalWarp(position: any): void;
         protected internalJump(): void;
         protected internalJump(): void;
         protected internalSetJumpSpeed(speed: number): void;
         protected internalSetJumpSpeed(speed: number): void;
@@ -2254,13 +2255,19 @@ declare module BABYLON {
         getContactProcessingThreshold(): number;
         getContactProcessingThreshold(): number;
         /** Sets character contact processing threshold using physics ghost object. (Advanved Use Only) */
         /** Sets character contact processing threshold using physics ghost object. (Advanved Use Only) */
         setContactProcessingThreshold(threshold: number): void;
         setContactProcessingThreshold(threshold: number): void;
+        /** Get the current position of the physics ghost object world transform. (Advanved Use Only) */
+        getGhostWorldPosition(): BABYLON.Vector3;
+        /** Get the current position of the physics ghost object world transform. (Advanved Use Only) */
+        getGhostWorldPositionToRef(result: BABYLON.Vector3): void;
         /** Manually set the position of the physics ghost object world transform. (Advanved Use Only) */
         /** Manually set the position of the physics ghost object world transform. (Advanved Use Only) */
         setGhostWorldPosition(position: BABYLON.Nullable<BABYLON.Vector3>): void;
         setGhostWorldPosition(position: BABYLON.Nullable<BABYLON.Vector3>): void;
-        /** Translates the kinematic character with the specfied movement velocity. */
+        /** Sets the kinematic character position to the specified location. */
+        set(x: number, y: number, z: number): void;
+        /** Translates the kinematic character with the specfied velocity. */
         move(velocity: BABYLON.Vector3): void;
         move(velocity: BABYLON.Vector3): void;
-        /** Jumps the kinematic chacracter with the specified jump speed. */
+        /** Jumps the kinematic chacracter with the specified speed. */
         jump(speed: number): void;
         jump(speed: number): void;
-        /** Warps the kinematic chacracter to the specified warp position. */
+        /** Warps the kinematic chacracter to the specified position. */
         warp(position: BABYLON.Vector3): void;
         warp(position: BABYLON.Vector3): void;
     }
     }
 }
 }
@@ -2286,10 +2293,13 @@ declare module BABYLON {
         private avoidancePriority;
         private avoidancePriority;
         private obstacleAvoidanceType;
         private obstacleAvoidanceType;
         private distanceToTarget;
         private distanceToTarget;
+        private teleporting;
         private moveDirection;
         private moveDirection;
         private resetPosition;
         private resetPosition;
         private lastPosition;
         private lastPosition;
+        private distancePosition;
         private currentPosition;
         private currentPosition;
+        private currentRotation;
         private currentVelocity;
         private currentVelocity;
         private currentWaypoint;
         private currentWaypoint;
         heightOffset: number;
         heightOffset: number;
@@ -2302,12 +2312,17 @@ declare module BABYLON {
         stoppingDistance: number;
         stoppingDistance: number;
         isReady(): boolean;
         isReady(): boolean;
         isNavigating(): boolean;
         isNavigating(): boolean;
+        isTeleporting(): boolean;
         isOnOffMeshLink(): boolean;
         isOnOffMeshLink(): boolean;
         getAgentType(): number;
         getAgentType(): number;
         getAgentState(): number;
         getAgentState(): number;
         getAgentIndex(): number;
         getAgentIndex(): number;
         getAgentOffset(): number;
         getAgentOffset(): number;
         getTargetDistance(): number;
         getTargetDistance(): number;
+        getCurrentWaypoint(): BABYLON.Vector3;
+        getCurrentPosition(): BABYLON.Vector3;
+        getCurrentRotation(): BABYLON.Quaternion;
+        getCurrentVelocity(): BABYLON.Vector3;
         getAgentParameters(): BABYLON.IAgentParameters;
         getAgentParameters(): BABYLON.IAgentParameters;
         setAgentParameters(parameters: BABYLON.IAgentParameters): void;
         setAgentParameters(parameters: BABYLON.IAgentParameters): void;
         protected m_agentState: number;
         protected m_agentState: number;
@@ -2315,13 +2330,12 @@ declare module BABYLON {
         protected m_agentReady: boolean;
         protected m_agentReady: boolean;
         protected m_agentGhost: BABYLON.TransformNode;
         protected m_agentGhost: BABYLON.TransformNode;
         protected m_agentParams: BABYLON.IAgentParameters;
         protected m_agentParams: BABYLON.IAgentParameters;
-        protected m_agentRotation: BABYLON.Quaternion;
         protected m_agentMovement: BABYLON.Vector3;
         protected m_agentMovement: BABYLON.Vector3;
         protected m_agentDirection: BABYLON.Vector3;
         protected m_agentDirection: BABYLON.Vector3;
         protected m_agentQuaternion: BABYLON.Quaternion;
         protected m_agentQuaternion: BABYLON.Quaternion;
         protected m_agentDestination: BABYLON.Vector3;
         protected m_agentDestination: BABYLON.Vector3;
         protected awake(): void;
         protected awake(): void;
-        protected late(): void;
+        protected update(): void;
         protected destroy(): void;
         protected destroy(): void;
         /** Register handler that is triggered when the agent is ready for navigation */
         /** Register handler that is triggered when the agent is ready for navigation */
         onReadyObservable: Observable<TransformNode>;
         onReadyObservable: Observable<TransformNode>;
@@ -2353,8 +2367,6 @@ declare module BABYLON {
         getAgentWaypoint(): BABYLON.Vector3;
         getAgentWaypoint(): BABYLON.Vector3;
         /** Gets agent current waypoint position. */
         /** Gets agent current waypoint position. */
         getAgentWaypointToRef(result: BABYLON.Vector3): void;
         getAgentWaypointToRef(result: BABYLON.Vector3): void;
-        /** Reset the agent to transform world space position. */
-        resetAgentPosition(): void;
         /** Cancel current waypoint path navigation. */
         /** Cancel current waypoint path navigation. */
         cancelNavigation(): void;
         cancelNavigation(): void;
     }
     }

File diff suppressed because it is too large
+ 5 - 5
Playground/libs/babylon.manager.js


File diff suppressed because it is too large
+ 624 - 338
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 487 - 176
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.max.js.map


File diff suppressed because it is too large
+ 1264 - 683
dist/preview release/babylon.module.d.ts


File diff suppressed because it is too large
+ 834 - 392
dist/preview release/documentation.d.ts


+ 210 - 54
dist/preview release/gui/babylon.gui.d.ts

@@ -15,7 +15,7 @@ declare module BABYLON.GUI {
          * Function called to let the control handle keyboard events
          * Function called to let the control handle keyboard events
          * @param evt defines the current keyboard event
          * @param evt defines the current keyboard event
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: BABYLON.IKeyboardEvent): void;
         /**
         /**
         * Function called to get the list of controls that should not steal the focus from this control
         * Function called to get the list of controls that should not steal the focus from this control
         * @returns an array of controls
         * @returns an array of controls
@@ -2190,7 +2190,7 @@ declare module BABYLON.GUI {
         /** BABYLON.Observable raised when paste event is triggered */
         /** BABYLON.Observable raised when paste event is triggered */
         onTextPasteObservable: BABYLON.Observable<InputText>;
         onTextPasteObservable: BABYLON.Observable<InputText>;
         /** BABYLON.Observable raised when a key event was processed */
         /** BABYLON.Observable raised when a key event was processed */
-        onKeyboardEventProcessedObservable: BABYLON.Observable<KeyboardEvent>;
+        onKeyboardEventProcessedObservable: BABYLON.Observable<BABYLON.IKeyboardEvent>;
         /** Gets or sets the maximum width allowed by the control */
         /** Gets or sets the maximum width allowed by the control */
         get maxWidth(): string | number;
         get maxWidth(): string | number;
         /** Gets the maximum width allowed by the control in pixels */
         /** Gets the maximum width allowed by the control in pixels */
@@ -2275,7 +2275,7 @@ declare module BABYLON.GUI {
          */
          */
         keepsFocusWith(): BABYLON.Nullable<Control[]>;
         keepsFocusWith(): BABYLON.Nullable<Control[]>;
         /** @hidden */
         /** @hidden */
-        processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
+        processKey(keyCode: number, key?: string, evt?: BABYLON.IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         private _updateValueFromCursorIndex;
         private _updateValueFromCursorIndex;
         /** @hidden */
         /** @hidden */
@@ -2286,7 +2286,7 @@ declare module BABYLON.GUI {
          * Handles the keyboard event
          * Handles the keyboard event
          * @param evt Defines the KeyboardEvent
          * @param evt Defines the KeyboardEvent
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: BABYLON.IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         private _onCopyText;
         private _onCopyText;
         /** @hidden */
         /** @hidden */
@@ -2540,7 +2540,7 @@ declare module BABYLON.GUI {
         /** BABYLON.Observable raised when the control loses the focus */
         /** BABYLON.Observable raised when the control loses the focus */
         onBlurObservable: BABYLON.Observable<Button>;
         onBlurObservable: BABYLON.Observable<Button>;
         /** BABYLON.Observable raised when a key event was processed */
         /** BABYLON.Observable raised when a key event was processed */
-        onKeyboardEventProcessedObservable: BABYLON.Observable<KeyboardEvent>;
+        onKeyboardEventProcessedObservable: BABYLON.Observable<BABYLON.IKeyboardEvent>;
         constructor(name?: string | undefined);
         constructor(name?: string | undefined);
         /** @hidden */
         /** @hidden */
         onBlur(): void;
         onBlur(): void;
@@ -2563,7 +2563,7 @@ declare module BABYLON.GUI {
          * Handles the keyboard event
          * Handles the keyboard event
          * @param evt Defines the KeyboardEvent
          * @param evt Defines the KeyboardEvent
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: BABYLON.IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, pi: BABYLON.PointerInfoBase): boolean;
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, pi: BABYLON.PointerInfoBase): boolean;
         /** @hidden */
         /** @hidden */
@@ -3777,6 +3777,105 @@ declare module BABYLON.GUI {
 }
 }
 declare module BABYLON.GUI {
 declare module BABYLON.GUI {
     /**
     /**
+     * Class used to create a button in 3D
+     */
+    export class Button3D extends AbstractButton3D {
+        /** @hidden */
+        protected _currentMaterial: BABYLON.Material;
+        private _facadeTexture;
+        private _content;
+        private _contentResolution;
+        private _contentScaleRatio;
+        /**
+         * Gets or sets the texture resolution used to render content (512 by default)
+         */
+        get contentResolution(): BABYLON.int;
+        set contentResolution(value: BABYLON.int);
+        /**
+         * Gets or sets the texture scale ratio used to render content (2 by default)
+         */
+        get contentScaleRatio(): number;
+        set contentScaleRatio(value: number);
+        protected _disposeFacadeTexture(): void;
+        protected _resetContent(): void;
+        /**
+         * Creates a new button
+         * @param name defines the control name
+         */
+        constructor(name?: string);
+        /**
+         * Gets or sets the GUI 2D content used to display the button's facade
+         */
+        get content(): Control;
+        set content(value: Control);
+        /**
+         * Apply the facade texture (created from the content property).
+         * This function can be overloaded by child classes
+         * @param facadeTexture defines the AdvancedDynamicTexture to use
+         */
+        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
+        protected _getTypeName(): string;
+        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
+        protected _affectMaterial(mesh: BABYLON.AbstractMesh): void;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a touchable button in 3D
+     */
+    export class TouchButton3D extends Button3D {
+        private _collisionMesh;
+        private _collidableFrontDirection;
+        private _lastTouchPoint;
+        private _tempButtonForwardRay;
+        private _lastKnownCollidableScale;
+        private _collidableInitialized;
+        private _frontOffset;
+        private _backOffset;
+        private _hoverOffset;
+        private _pushThroughBackOffset;
+        private _activeInteractions;
+        private _previousHeight;
+        /**
+         * Creates a new touchable button
+         * @param name defines the control name
+         * @param collisionMesh mesh to track collisions with
+         */
+        constructor(name?: string, collisionMesh?: BABYLON.Mesh);
+        /**
+         * Sets the front-facing direction of the button
+         * @param frontDir the forward direction of the button
+         */
+        set collidableFrontDirection(frontWorldDir: BABYLON.Vector3);
+        private _getWorldMatrixData;
+        /**
+         * Sets the mesh used for testing input collision
+         * @param collisionMesh the new collision mesh for the button
+         */
+        set collisionMesh(collisionMesh: BABYLON.Mesh);
+        private _getShortestDistancePointToLine;
+        private _isPrimedForInteraction;
+        private _getPointOnButton;
+        private _updateDistanceOffsets;
+        private _getHeightFromButtonCenter;
+        private _getDistanceOffPlane;
+        private _updateButtonState;
+        /** @hidden */
+        _collisionCheckForStateChange(mesh: BABYLON.AbstractMesh): void;
+        protected _getTypeName(): string;
+        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
      * Class used to manage 3D user interface
      * Class used to manage 3D user interface
      * @see https://doc.babylonjs.com/how_to/gui3d
      * @see https://doc.babylonjs.com/how_to/gui3d
      */
      */
@@ -3787,6 +3886,7 @@ declare module BABYLON.GUI {
         private _rootContainer;
         private _rootContainer;
         private _pointerObserver;
         private _pointerObserver;
         private _pointerOutObserver;
         private _pointerOutObserver;
+        private _touchableButtons;
         /** @hidden */
         /** @hidden */
         _lastPickedControl: Control3D;
         _lastPickedControl: Control3D;
         /** @hidden */
         /** @hidden */
@@ -3805,6 +3905,10 @@ declare module BABYLON.GUI {
         _sharedMaterials: {
         _sharedMaterials: {
             [key: string]: BABYLON.Material;
             [key: string]: BABYLON.Material;
         };
         };
+        /** @hidden */
+        _touchSharedMaterials: {
+            [key: string]: BABYLON.Material;
+        };
         /** Gets the hosting scene */
         /** Gets the hosting scene */
         get scene(): BABYLON.Scene;
         get scene(): BABYLON.Scene;
         /** Gets associated utility layer */
         /** Gets associated utility layer */
@@ -3816,6 +3920,7 @@ declare module BABYLON.GUI {
         constructor(scene?: BABYLON.Scene);
         constructor(scene?: BABYLON.Scene);
         private _handlePointerOut;
         private _handlePointerOut;
         private _doPicking;
         private _doPicking;
+        private _processTouchControls;
         /**
         /**
          * Gets the root container
          * Gets the root container
          */
          */
@@ -4031,54 +4136,6 @@ declare module BABYLON.GUI {
 }
 }
 declare module BABYLON.GUI {
 declare module BABYLON.GUI {
     /**
     /**
-     * Class used to create a button in 3D
-     */
-    export class Button3D extends AbstractButton3D {
-        /** @hidden */
-        protected _currentMaterial: BABYLON.Material;
-        private _facadeTexture;
-        private _content;
-        private _contentResolution;
-        private _contentScaleRatio;
-        /**
-         * Gets or sets the texture resolution used to render content (512 by default)
-         */
-        get contentResolution(): BABYLON.int;
-        set contentResolution(value: BABYLON.int);
-        /**
-         * Gets or sets the texture scale ratio used to render content (2 by default)
-         */
-        get contentScaleRatio(): number;
-        set contentScaleRatio(value: number);
-        protected _disposeFacadeTexture(): void;
-        protected _resetContent(): void;
-        /**
-         * Creates a new button
-         * @param name defines the control name
-         */
-        constructor(name?: string);
-        /**
-         * Gets or sets the GUI 2D content used to display the button's facade
-         */
-        get content(): Control;
-        set content(value: Control);
-        /**
-         * Apply the facade texture (created from the content property).
-         * This function can be overloaded by child classes
-         * @param facadeTexture defines the AdvancedDynamicTexture to use
-         */
-        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
-        protected _getTypeName(): string;
-        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
-        protected _affectMaterial(mesh: BABYLON.AbstractMesh): void;
-        /**
-         * Releases all associated resources
-         */
-        dispose(): void;
-    }
-}
-declare module BABYLON.GUI {
-    /**
      * Abstract class used to create a container panel deployed on the surface of a volume
      * Abstract class used to create a container panel deployed on the surface of a volume
      */
      */
     export abstract class VolumeBasedPanel extends Container3D {
     export abstract class VolumeBasedPanel extends Container3D {
@@ -4392,4 +4449,103 @@ declare module BABYLON.GUI {
         constructor(isVertical?: boolean);
         constructor(isVertical?: boolean);
         protected _arrangeChildren(): void;
         protected _arrangeChildren(): void;
     }
     }
+}
+declare module BABYLON.GUI {
+    /**
+     * Class used to create an interactable object. It's a touchable 3D button using a mesh coming from the current scene
+     */
+    export class TouchMeshButton3D extends TouchButton3D {
+        /** @hidden */
+        protected _currentMesh: BABYLON.Mesh;
+        /**
+         * Creates a new 3D button based on a mesh
+         * @param mesh mesh to become a 3D button
+         * @param collisionMesh mesh to track collisions with
+         * @param name defines the control name
+         */
+        constructor(mesh: BABYLON.Mesh, options: {
+            collisionMesh: BABYLON.Mesh;
+            useDynamicMesh?: boolean;
+        }, name?: string);
+        protected _getTypeName(): string;
+        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
+        protected _affectMaterial(mesh: BABYLON.AbstractMesh): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a holographic button in 3D
+     */
+    export class TouchHolographicButton extends TouchButton3D {
+        private _backPlate;
+        private _textPlate;
+        private _frontPlate;
+        private _text;
+        private _imageUrl;
+        private _shareMaterials;
+        private _frontMaterial;
+        private _backMaterial;
+        private _plateMaterial;
+        private _pickedPointObserver;
+        private _tooltipFade;
+        private _tooltipTextBlock;
+        private _tooltipTexture;
+        private _tooltipMesh;
+        private _tooltipHoverObserver;
+        private _tooltipOutObserver;
+        private _disposeTooltip;
+        /**
+         * Rendering ground id of all the mesh in the button
+         */
+        set renderingGroupId(id: number);
+        get renderingGroupId(): number;
+        /**
+         * Text to be displayed on the tooltip shown when hovering on the button. When set to null tooltip is disabled. (Default: null)
+         */
+        set tooltipText(text: BABYLON.Nullable<string>);
+        get tooltipText(): BABYLON.Nullable<string>;
+        /**
+         * Gets or sets text for the button
+         */
+        get text(): string;
+        set text(value: string);
+        /**
+         * Gets or sets the image url for the button
+         */
+        get imageUrl(): string;
+        set imageUrl(value: string);
+        /**
+         * Gets the back material used by this button
+         */
+        get backMaterial(): FluentMaterial;
+        /**
+         * Gets the front material used by this button
+         */
+        get frontMaterial(): FluentMaterial;
+        /**
+         * Gets the plate material used by this button
+         */
+        get plateMaterial(): BABYLON.StandardMaterial;
+        /**
+         * Gets a boolean indicating if this button shares its material with other HolographicButtons
+         */
+        get shareMaterials(): boolean;
+        /**
+         * Creates a new button
+         * @param name defines the control name
+         */
+        constructor(name?: string, shareMaterials?: boolean);
+        protected _getTypeName(): string;
+        private _rebuildContent;
+        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
+        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
+        private _createBackMaterial;
+        private _createFrontMaterial;
+        private _createPlateMaterial;
+        protected _affectMaterial(mesh: BABYLON.Mesh): void;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
 }
 }

File diff suppressed because it is too large
+ 859 - 15
dist/preview release/gui/babylon.gui.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/gui/babylon.gui.min.js


+ 453 - 116
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1,4 +1,5 @@
 declare module "babylonjs-gui/2D/controls/focusableControl" {
 declare module "babylonjs-gui/2D/controls/focusableControl" {
+    import { IKeyboardEvent } from "babylonjs/Events/deviceInputEvents";
     import { Nullable } from "babylonjs/types";
     import { Nullable } from "babylonjs/types";
     import { Control } from "babylonjs-gui/2D/controls/control";
     import { Control } from "babylonjs-gui/2D/controls/control";
     /**
     /**
@@ -17,7 +18,7 @@ declare module "babylonjs-gui/2D/controls/focusableControl" {
          * Function called to let the control handle keyboard events
          * Function called to let the control handle keyboard events
          * @param evt defines the current keyboard event
          * @param evt defines the current keyboard event
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: IKeyboardEvent): void;
         /**
         /**
         * Function called to get the list of controls that should not steal the focus from this control
         * Function called to get the list of controls that should not steal the focus from this control
         * @returns an array of controls
         * @returns an array of controls
@@ -2211,6 +2212,7 @@ declare module "babylonjs-gui/2D/controls/inputText" {
     import { VirtualKeyboard } from "babylonjs-gui/2D/controls/virtualKeyboard";
     import { VirtualKeyboard } from "babylonjs-gui/2D/controls/virtualKeyboard";
     import { Measure } from "babylonjs-gui/2D/measure";
     import { Measure } from "babylonjs-gui/2D/measure";
     import { TextWrapper } from "babylonjs-gui/2D/controls/textWrapper";
     import { TextWrapper } from "babylonjs-gui/2D/controls/textWrapper";
+    import { IKeyboardEvent } from 'babylonjs/Events/deviceInputEvents';
     /**
     /**
      * Class used to create input text control
      * Class used to create input text control
      */
      */
@@ -2270,7 +2272,7 @@ declare module "babylonjs-gui/2D/controls/inputText" {
         /** Observable raised when paste event is triggered */
         /** Observable raised when paste event is triggered */
         onTextPasteObservable: Observable<InputText>;
         onTextPasteObservable: Observable<InputText>;
         /** Observable raised when a key event was processed */
         /** Observable raised when a key event was processed */
-        onKeyboardEventProcessedObservable: Observable<KeyboardEvent>;
+        onKeyboardEventProcessedObservable: Observable<IKeyboardEvent>;
         /** Gets or sets the maximum width allowed by the control */
         /** Gets or sets the maximum width allowed by the control */
         get maxWidth(): string | number;
         get maxWidth(): string | number;
         /** Gets the maximum width allowed by the control in pixels */
         /** Gets the maximum width allowed by the control in pixels */
@@ -2355,7 +2357,7 @@ declare module "babylonjs-gui/2D/controls/inputText" {
          */
          */
         keepsFocusWith(): Nullable<Control[]>;
         keepsFocusWith(): Nullable<Control[]>;
         /** @hidden */
         /** @hidden */
-        processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
+        processKey(keyCode: number, key?: string, evt?: IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         private _updateValueFromCursorIndex;
         private _updateValueFromCursorIndex;
         /** @hidden */
         /** @hidden */
@@ -2366,7 +2368,7 @@ declare module "babylonjs-gui/2D/controls/inputText" {
          * Handles the keyboard event
          * Handles the keyboard event
          * @param evt Defines the KeyboardEvent
          * @param evt Defines the KeyboardEvent
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         private _onCopyText;
         private _onCopyText;
         /** @hidden */
         /** @hidden */
@@ -2627,6 +2629,7 @@ declare module "babylonjs-gui/2D/controls/focusableButton" {
     import { PointerInfoBase } from 'babylonjs/Events/pointerEvents';
     import { PointerInfoBase } from 'babylonjs/Events/pointerEvents';
     import { IFocusableControl } from "babylonjs-gui/2D/controls/focusableControl";
     import { IFocusableControl } from "babylonjs-gui/2D/controls/focusableControl";
     import { Observable } from 'babylonjs/Misc/observable';
     import { Observable } from 'babylonjs/Misc/observable';
+    import { IKeyboardEvent } from "babylonjs/Events/deviceInputEvents";
     /**
     /**
      * Class used to create a focusable button that can easily handle keyboard events
      * Class used to create a focusable button that can easily handle keyboard events
      */
      */
@@ -2641,7 +2644,7 @@ declare module "babylonjs-gui/2D/controls/focusableButton" {
         /** Observable raised when the control loses the focus */
         /** Observable raised when the control loses the focus */
         onBlurObservable: Observable<Button>;
         onBlurObservable: Observable<Button>;
         /** Observable raised when a key event was processed */
         /** Observable raised when a key event was processed */
-        onKeyboardEventProcessedObservable: Observable<KeyboardEvent>;
+        onKeyboardEventProcessedObservable: Observable<IKeyboardEvent>;
         constructor(name?: string | undefined);
         constructor(name?: string | undefined);
         /** @hidden */
         /** @hidden */
         onBlur(): void;
         onBlur(): void;
@@ -2664,7 +2667,7 @@ declare module "babylonjs-gui/2D/controls/focusableButton" {
          * Handles the keyboard event
          * Handles the keyboard event
          * @param evt Defines the KeyboardEvent
          * @param evt Defines the KeyboardEvent
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, pi: PointerInfoBase): boolean;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, pi: PointerInfoBase): boolean;
         /** @hidden */
         /** @hidden */
@@ -3992,6 +3995,119 @@ declare module "babylonjs-gui/3D/controls/container3D" {
         static readonly FACEFORWARDREVERSED_ORIENTATION: number;
         static readonly FACEFORWARDREVERSED_ORIENTATION: number;
     }
     }
 }
 }
+declare module "babylonjs-gui/3D/controls/button3D" {
+    import { int } from "babylonjs/types";
+    import { TransformNode } from "babylonjs/Meshes/transformNode";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { Material } from "babylonjs/Materials/material";
+    import { Scene } from "babylonjs/scene";
+    import { AbstractButton3D } from "babylonjs-gui/3D/controls/abstractButton3D";
+    import { AdvancedDynamicTexture } from "babylonjs-gui/2D/advancedDynamicTexture";
+    import { Control } from "babylonjs-gui/2D/controls/control";
+    /**
+     * Class used to create a button in 3D
+     */
+    export class Button3D extends AbstractButton3D {
+        /** @hidden */
+        protected _currentMaterial: Material;
+        private _facadeTexture;
+        private _content;
+        private _contentResolution;
+        private _contentScaleRatio;
+        /**
+         * Gets or sets the texture resolution used to render content (512 by default)
+         */
+        get contentResolution(): int;
+        set contentResolution(value: int);
+        /**
+         * Gets or sets the texture scale ratio used to render content (2 by default)
+         */
+        get contentScaleRatio(): number;
+        set contentScaleRatio(value: number);
+        protected _disposeFacadeTexture(): void;
+        protected _resetContent(): void;
+        /**
+         * Creates a new button
+         * @param name defines the control name
+         */
+        constructor(name?: string);
+        /**
+         * Gets or sets the GUI 2D content used to display the button's facade
+         */
+        get content(): Control;
+        set content(value: Control);
+        /**
+         * Apply the facade texture (created from the content property).
+         * This function can be overloaded by child classes
+         * @param facadeTexture defines the AdvancedDynamicTexture to use
+         */
+        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
+        protected _getTypeName(): string;
+        protected _createNode(scene: Scene): TransformNode;
+        protected _affectMaterial(mesh: AbstractMesh): void;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
+}
+declare module "babylonjs-gui/3D/controls/touchButton3D" {
+    import { Vector3 } from "babylonjs/Maths/math.vector";
+    import { Mesh } from "babylonjs/Meshes/mesh";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { TransformNode } from "babylonjs/Meshes/transformNode";
+    import { Scene } from "babylonjs/scene";
+    import { Button3D } from "babylonjs-gui/3D/controls/button3D";
+    /**
+     * Class used to create a touchable button in 3D
+     */
+    export class TouchButton3D extends Button3D {
+        private _collisionMesh;
+        private _collidableFrontDirection;
+        private _lastTouchPoint;
+        private _tempButtonForwardRay;
+        private _lastKnownCollidableScale;
+        private _collidableInitialized;
+        private _frontOffset;
+        private _backOffset;
+        private _hoverOffset;
+        private _pushThroughBackOffset;
+        private _activeInteractions;
+        private _previousHeight;
+        /**
+         * Creates a new touchable button
+         * @param name defines the control name
+         * @param collisionMesh mesh to track collisions with
+         */
+        constructor(name?: string, collisionMesh?: Mesh);
+        /**
+         * Sets the front-facing direction of the button
+         * @param frontDir the forward direction of the button
+         */
+        set collidableFrontDirection(frontWorldDir: Vector3);
+        private _getWorldMatrixData;
+        /**
+         * Sets the mesh used for testing input collision
+         * @param collisionMesh the new collision mesh for the button
+         */
+        set collisionMesh(collisionMesh: Mesh);
+        private _getShortestDistancePointToLine;
+        private _isPrimedForInteraction;
+        private _getPointOnButton;
+        private _updateDistanceOffsets;
+        private _getHeightFromButtonCenter;
+        private _getDistanceOffPlane;
+        private _updateButtonState;
+        /** @hidden */
+        _collisionCheckForStateChange(mesh: AbstractMesh): void;
+        protected _getTypeName(): string;
+        protected _createNode(scene: Scene): TransformNode;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
+}
 declare module "babylonjs-gui/3D/gui3DManager" {
 declare module "babylonjs-gui/3D/gui3DManager" {
     import { Nullable } from "babylonjs/types";
     import { Nullable } from "babylonjs/types";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
@@ -4012,6 +4128,7 @@ declare module "babylonjs-gui/3D/gui3DManager" {
         private _rootContainer;
         private _rootContainer;
         private _pointerObserver;
         private _pointerObserver;
         private _pointerOutObserver;
         private _pointerOutObserver;
+        private _touchableButtons;
         /** @hidden */
         /** @hidden */
         _lastPickedControl: Control3D;
         _lastPickedControl: Control3D;
         /** @hidden */
         /** @hidden */
@@ -4030,6 +4147,10 @@ declare module "babylonjs-gui/3D/gui3DManager" {
         _sharedMaterials: {
         _sharedMaterials: {
             [key: string]: Material;
             [key: string]: Material;
         };
         };
+        /** @hidden */
+        _touchSharedMaterials: {
+            [key: string]: Material;
+        };
         /** Gets the hosting scene */
         /** Gets the hosting scene */
         get scene(): Scene;
         get scene(): Scene;
         /** Gets associated utility layer */
         /** Gets associated utility layer */
@@ -4041,6 +4162,7 @@ declare module "babylonjs-gui/3D/gui3DManager" {
         constructor(scene?: Scene);
         constructor(scene?: Scene);
         private _handlePointerOut;
         private _handlePointerOut;
         private _doPicking;
         private _doPicking;
+        private _processTouchControls;
         /**
         /**
          * Gets the root container
          * Gets the root container
          */
          */
@@ -4268,62 +4390,6 @@ declare module "babylonjs-gui/3D/controls/abstractButton3D" {
         protected _createNode(scene: Scene): TransformNode;
         protected _createNode(scene: Scene): TransformNode;
     }
     }
 }
 }
-declare module "babylonjs-gui/3D/controls/button3D" {
-    import { int } from "babylonjs/types";
-    import { TransformNode } from "babylonjs/Meshes/transformNode";
-    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { Material } from "babylonjs/Materials/material";
-    import { Scene } from "babylonjs/scene";
-    import { AbstractButton3D } from "babylonjs-gui/3D/controls/abstractButton3D";
-    import { AdvancedDynamicTexture } from "babylonjs-gui/2D/advancedDynamicTexture";
-    import { Control } from "babylonjs-gui/2D/controls/control";
-    /**
-     * Class used to create a button in 3D
-     */
-    export class Button3D extends AbstractButton3D {
-        /** @hidden */
-        protected _currentMaterial: Material;
-        private _facadeTexture;
-        private _content;
-        private _contentResolution;
-        private _contentScaleRatio;
-        /**
-         * Gets or sets the texture resolution used to render content (512 by default)
-         */
-        get contentResolution(): int;
-        set contentResolution(value: int);
-        /**
-         * Gets or sets the texture scale ratio used to render content (2 by default)
-         */
-        get contentScaleRatio(): number;
-        set contentScaleRatio(value: number);
-        protected _disposeFacadeTexture(): void;
-        protected _resetContent(): void;
-        /**
-         * Creates a new button
-         * @param name defines the control name
-         */
-        constructor(name?: string);
-        /**
-         * Gets or sets the GUI 2D content used to display the button's facade
-         */
-        get content(): Control;
-        set content(value: Control);
-        /**
-         * Apply the facade texture (created from the content property).
-         * This function can be overloaded by child classes
-         * @param facadeTexture defines the AdvancedDynamicTexture to use
-         */
-        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
-        protected _getTypeName(): string;
-        protected _createNode(scene: Scene): TransformNode;
-        protected _affectMaterial(mesh: AbstractMesh): void;
-        /**
-         * Releases all associated resources
-         */
-        dispose(): void;
-    }
-}
 declare module "babylonjs-gui/3D/controls/volumeBasedPanel" {
 declare module "babylonjs-gui/3D/controls/volumeBasedPanel" {
     import { Vector3 } from "babylonjs/Maths/math.vector";
     import { Vector3 } from "babylonjs/Maths/math.vector";
     import { int } from "babylonjs/types";
     import { int } from "babylonjs/types";
@@ -4685,6 +4751,118 @@ declare module "babylonjs-gui/3D/controls/stackPanel3D" {
         protected _arrangeChildren(): void;
         protected _arrangeChildren(): void;
     }
     }
 }
 }
+declare module "babylonjs-gui/3D/controls/touchMeshButton3D" {
+    import { TransformNode } from "babylonjs/Meshes/transformNode";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { Mesh } from "babylonjs/Meshes/mesh";
+    import { Scene } from "babylonjs/scene";
+    import { TouchButton3D } from "babylonjs-gui/3D/controls/touchButton3D";
+    /**
+     * Class used to create an interactable object. It's a touchable 3D button using a mesh coming from the current scene
+     */
+    export class TouchMeshButton3D extends TouchButton3D {
+        /** @hidden */
+        protected _currentMesh: Mesh;
+        /**
+         * Creates a new 3D button based on a mesh
+         * @param mesh mesh to become a 3D button
+         * @param collisionMesh mesh to track collisions with
+         * @param name defines the control name
+         */
+        constructor(mesh: Mesh, options: {
+            collisionMesh: Mesh;
+            useDynamicMesh?: boolean;
+        }, name?: string);
+        protected _getTypeName(): string;
+        protected _createNode(scene: Scene): TransformNode;
+        protected _affectMaterial(mesh: AbstractMesh): void;
+    }
+}
+declare module "babylonjs-gui/3D/controls/touchHolographicButton" {
+    import { Nullable } from "babylonjs/types";
+    import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
+    import { TransformNode } from "babylonjs/Meshes/transformNode";
+    import { Mesh } from "babylonjs/Meshes/mesh";
+    import { Scene } from "babylonjs/scene";
+    import { FluentMaterial } from "babylonjs-gui/3D/materials/fluentMaterial";
+    import { AdvancedDynamicTexture } from "babylonjs-gui/2D/advancedDynamicTexture";
+    import { TouchButton3D } from "babylonjs-gui/3D/controls/touchButton3D";
+    /**
+     * Class used to create a holographic button in 3D
+     */
+    export class TouchHolographicButton extends TouchButton3D {
+        private _backPlate;
+        private _textPlate;
+        private _frontPlate;
+        private _text;
+        private _imageUrl;
+        private _shareMaterials;
+        private _frontMaterial;
+        private _backMaterial;
+        private _plateMaterial;
+        private _pickedPointObserver;
+        private _tooltipFade;
+        private _tooltipTextBlock;
+        private _tooltipTexture;
+        private _tooltipMesh;
+        private _tooltipHoverObserver;
+        private _tooltipOutObserver;
+        private _disposeTooltip;
+        /**
+         * Rendering ground id of all the mesh in the button
+         */
+        set renderingGroupId(id: number);
+        get renderingGroupId(): number;
+        /**
+         * Text to be displayed on the tooltip shown when hovering on the button. When set to null tooltip is disabled. (Default: null)
+         */
+        set tooltipText(text: Nullable<string>);
+        get tooltipText(): Nullable<string>;
+        /**
+         * Gets or sets text for the button
+         */
+        get text(): string;
+        set text(value: string);
+        /**
+         * Gets or sets the image url for the button
+         */
+        get imageUrl(): string;
+        set imageUrl(value: string);
+        /**
+         * Gets the back material used by this button
+         */
+        get backMaterial(): FluentMaterial;
+        /**
+         * Gets the front material used by this button
+         */
+        get frontMaterial(): FluentMaterial;
+        /**
+         * Gets the plate material used by this button
+         */
+        get plateMaterial(): StandardMaterial;
+        /**
+         * Gets a boolean indicating if this button shares its material with other HolographicButtons
+         */
+        get shareMaterials(): boolean;
+        /**
+         * Creates a new button
+         * @param name defines the control name
+         */
+        constructor(name?: string, shareMaterials?: boolean);
+        protected _getTypeName(): string;
+        private _rebuildContent;
+        protected _createNode(scene: Scene): TransformNode;
+        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
+        private _createBackMaterial;
+        private _createFrontMaterial;
+        private _createPlateMaterial;
+        protected _affectMaterial(mesh: Mesh): void;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
+}
 declare module "babylonjs-gui/3D/controls/index" {
 declare module "babylonjs-gui/3D/controls/index" {
     export * from "babylonjs-gui/3D/controls/abstractButton3D";
     export * from "babylonjs-gui/3D/controls/abstractButton3D";
     export * from "babylonjs-gui/3D/controls/button3D";
     export * from "babylonjs-gui/3D/controls/button3D";
@@ -4697,6 +4875,9 @@ declare module "babylonjs-gui/3D/controls/index" {
     export * from "babylonjs-gui/3D/controls/scatterPanel";
     export * from "babylonjs-gui/3D/controls/scatterPanel";
     export * from "babylonjs-gui/3D/controls/spherePanel";
     export * from "babylonjs-gui/3D/controls/spherePanel";
     export * from "babylonjs-gui/3D/controls/stackPanel3D";
     export * from "babylonjs-gui/3D/controls/stackPanel3D";
+    export * from "babylonjs-gui/3D/controls/touchButton3D";
+    export * from "babylonjs-gui/3D/controls/touchMeshButton3D";
+    export * from "babylonjs-gui/3D/controls/touchHolographicButton";
     export * from "babylonjs-gui/3D/controls/volumeBasedPanel";
     export * from "babylonjs-gui/3D/controls/volumeBasedPanel";
 }
 }
 declare module "babylonjs-gui/3D/materials/index" {
 declare module "babylonjs-gui/3D/materials/index" {
@@ -4735,7 +4916,7 @@ declare module BABYLON.GUI {
          * Function called to let the control handle keyboard events
          * Function called to let the control handle keyboard events
          * @param evt defines the current keyboard event
          * @param evt defines the current keyboard event
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: BABYLON.IKeyboardEvent): void;
         /**
         /**
         * Function called to get the list of controls that should not steal the focus from this control
         * Function called to get the list of controls that should not steal the focus from this control
         * @returns an array of controls
         * @returns an array of controls
@@ -6910,7 +7091,7 @@ declare module BABYLON.GUI {
         /** BABYLON.Observable raised when paste event is triggered */
         /** BABYLON.Observable raised when paste event is triggered */
         onTextPasteObservable: BABYLON.Observable<InputText>;
         onTextPasteObservable: BABYLON.Observable<InputText>;
         /** BABYLON.Observable raised when a key event was processed */
         /** BABYLON.Observable raised when a key event was processed */
-        onKeyboardEventProcessedObservable: BABYLON.Observable<KeyboardEvent>;
+        onKeyboardEventProcessedObservable: BABYLON.Observable<BABYLON.IKeyboardEvent>;
         /** Gets or sets the maximum width allowed by the control */
         /** Gets or sets the maximum width allowed by the control */
         get maxWidth(): string | number;
         get maxWidth(): string | number;
         /** Gets the maximum width allowed by the control in pixels */
         /** Gets the maximum width allowed by the control in pixels */
@@ -6995,7 +7176,7 @@ declare module BABYLON.GUI {
          */
          */
         keepsFocusWith(): BABYLON.Nullable<Control[]>;
         keepsFocusWith(): BABYLON.Nullable<Control[]>;
         /** @hidden */
         /** @hidden */
-        processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
+        processKey(keyCode: number, key?: string, evt?: BABYLON.IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         private _updateValueFromCursorIndex;
         private _updateValueFromCursorIndex;
         /** @hidden */
         /** @hidden */
@@ -7006,7 +7187,7 @@ declare module BABYLON.GUI {
          * Handles the keyboard event
          * Handles the keyboard event
          * @param evt Defines the KeyboardEvent
          * @param evt Defines the KeyboardEvent
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: BABYLON.IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         private _onCopyText;
         private _onCopyText;
         /** @hidden */
         /** @hidden */
@@ -7260,7 +7441,7 @@ declare module BABYLON.GUI {
         /** BABYLON.Observable raised when the control loses the focus */
         /** BABYLON.Observable raised when the control loses the focus */
         onBlurObservable: BABYLON.Observable<Button>;
         onBlurObservable: BABYLON.Observable<Button>;
         /** BABYLON.Observable raised when a key event was processed */
         /** BABYLON.Observable raised when a key event was processed */
-        onKeyboardEventProcessedObservable: BABYLON.Observable<KeyboardEvent>;
+        onKeyboardEventProcessedObservable: BABYLON.Observable<BABYLON.IKeyboardEvent>;
         constructor(name?: string | undefined);
         constructor(name?: string | undefined);
         /** @hidden */
         /** @hidden */
         onBlur(): void;
         onBlur(): void;
@@ -7283,7 +7464,7 @@ declare module BABYLON.GUI {
          * Handles the keyboard event
          * Handles the keyboard event
          * @param evt Defines the KeyboardEvent
          * @param evt Defines the KeyboardEvent
          */
          */
-        processKeyboard(evt: KeyboardEvent): void;
+        processKeyboard(evt: BABYLON.IKeyboardEvent): void;
         /** @hidden */
         /** @hidden */
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, pi: BABYLON.PointerInfoBase): boolean;
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, pi: BABYLON.PointerInfoBase): boolean;
         /** @hidden */
         /** @hidden */
@@ -8497,6 +8678,105 @@ declare module BABYLON.GUI {
 }
 }
 declare module BABYLON.GUI {
 declare module BABYLON.GUI {
     /**
     /**
+     * Class used to create a button in 3D
+     */
+    export class Button3D extends AbstractButton3D {
+        /** @hidden */
+        protected _currentMaterial: BABYLON.Material;
+        private _facadeTexture;
+        private _content;
+        private _contentResolution;
+        private _contentScaleRatio;
+        /**
+         * Gets or sets the texture resolution used to render content (512 by default)
+         */
+        get contentResolution(): BABYLON.int;
+        set contentResolution(value: BABYLON.int);
+        /**
+         * Gets or sets the texture scale ratio used to render content (2 by default)
+         */
+        get contentScaleRatio(): number;
+        set contentScaleRatio(value: number);
+        protected _disposeFacadeTexture(): void;
+        protected _resetContent(): void;
+        /**
+         * Creates a new button
+         * @param name defines the control name
+         */
+        constructor(name?: string);
+        /**
+         * Gets or sets the GUI 2D content used to display the button's facade
+         */
+        get content(): Control;
+        set content(value: Control);
+        /**
+         * Apply the facade texture (created from the content property).
+         * This function can be overloaded by child classes
+         * @param facadeTexture defines the AdvancedDynamicTexture to use
+         */
+        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
+        protected _getTypeName(): string;
+        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
+        protected _affectMaterial(mesh: BABYLON.AbstractMesh): void;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a touchable button in 3D
+     */
+    export class TouchButton3D extends Button3D {
+        private _collisionMesh;
+        private _collidableFrontDirection;
+        private _lastTouchPoint;
+        private _tempButtonForwardRay;
+        private _lastKnownCollidableScale;
+        private _collidableInitialized;
+        private _frontOffset;
+        private _backOffset;
+        private _hoverOffset;
+        private _pushThroughBackOffset;
+        private _activeInteractions;
+        private _previousHeight;
+        /**
+         * Creates a new touchable button
+         * @param name defines the control name
+         * @param collisionMesh mesh to track collisions with
+         */
+        constructor(name?: string, collisionMesh?: BABYLON.Mesh);
+        /**
+         * Sets the front-facing direction of the button
+         * @param frontDir the forward direction of the button
+         */
+        set collidableFrontDirection(frontWorldDir: BABYLON.Vector3);
+        private _getWorldMatrixData;
+        /**
+         * Sets the mesh used for testing input collision
+         * @param collisionMesh the new collision mesh for the button
+         */
+        set collisionMesh(collisionMesh: BABYLON.Mesh);
+        private _getShortestDistancePointToLine;
+        private _isPrimedForInteraction;
+        private _getPointOnButton;
+        private _updateDistanceOffsets;
+        private _getHeightFromButtonCenter;
+        private _getDistanceOffPlane;
+        private _updateButtonState;
+        /** @hidden */
+        _collisionCheckForStateChange(mesh: BABYLON.AbstractMesh): void;
+        protected _getTypeName(): string;
+        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
      * Class used to manage 3D user interface
      * Class used to manage 3D user interface
      * @see https://doc.babylonjs.com/how_to/gui3d
      * @see https://doc.babylonjs.com/how_to/gui3d
      */
      */
@@ -8507,6 +8787,7 @@ declare module BABYLON.GUI {
         private _rootContainer;
         private _rootContainer;
         private _pointerObserver;
         private _pointerObserver;
         private _pointerOutObserver;
         private _pointerOutObserver;
+        private _touchableButtons;
         /** @hidden */
         /** @hidden */
         _lastPickedControl: Control3D;
         _lastPickedControl: Control3D;
         /** @hidden */
         /** @hidden */
@@ -8525,6 +8806,10 @@ declare module BABYLON.GUI {
         _sharedMaterials: {
         _sharedMaterials: {
             [key: string]: BABYLON.Material;
             [key: string]: BABYLON.Material;
         };
         };
+        /** @hidden */
+        _touchSharedMaterials: {
+            [key: string]: BABYLON.Material;
+        };
         /** Gets the hosting scene */
         /** Gets the hosting scene */
         get scene(): BABYLON.Scene;
         get scene(): BABYLON.Scene;
         /** Gets associated utility layer */
         /** Gets associated utility layer */
@@ -8536,6 +8821,7 @@ declare module BABYLON.GUI {
         constructor(scene?: BABYLON.Scene);
         constructor(scene?: BABYLON.Scene);
         private _handlePointerOut;
         private _handlePointerOut;
         private _doPicking;
         private _doPicking;
+        private _processTouchControls;
         /**
         /**
          * Gets the root container
          * Gets the root container
          */
          */
@@ -8751,54 +9037,6 @@ declare module BABYLON.GUI {
 }
 }
 declare module BABYLON.GUI {
 declare module BABYLON.GUI {
     /**
     /**
-     * Class used to create a button in 3D
-     */
-    export class Button3D extends AbstractButton3D {
-        /** @hidden */
-        protected _currentMaterial: BABYLON.Material;
-        private _facadeTexture;
-        private _content;
-        private _contentResolution;
-        private _contentScaleRatio;
-        /**
-         * Gets or sets the texture resolution used to render content (512 by default)
-         */
-        get contentResolution(): BABYLON.int;
-        set contentResolution(value: BABYLON.int);
-        /**
-         * Gets or sets the texture scale ratio used to render content (2 by default)
-         */
-        get contentScaleRatio(): number;
-        set contentScaleRatio(value: number);
-        protected _disposeFacadeTexture(): void;
-        protected _resetContent(): void;
-        /**
-         * Creates a new button
-         * @param name defines the control name
-         */
-        constructor(name?: string);
-        /**
-         * Gets or sets the GUI 2D content used to display the button's facade
-         */
-        get content(): Control;
-        set content(value: Control);
-        /**
-         * Apply the facade texture (created from the content property).
-         * This function can be overloaded by child classes
-         * @param facadeTexture defines the AdvancedDynamicTexture to use
-         */
-        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
-        protected _getTypeName(): string;
-        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
-        protected _affectMaterial(mesh: BABYLON.AbstractMesh): void;
-        /**
-         * Releases all associated resources
-         */
-        dispose(): void;
-    }
-}
-declare module BABYLON.GUI {
-    /**
      * Abstract class used to create a container panel deployed on the surface of a volume
      * Abstract class used to create a container panel deployed on the surface of a volume
      */
      */
     export abstract class VolumeBasedPanel extends Container3D {
     export abstract class VolumeBasedPanel extends Container3D {
@@ -9112,4 +9350,103 @@ declare module BABYLON.GUI {
         constructor(isVertical?: boolean);
         constructor(isVertical?: boolean);
         protected _arrangeChildren(): void;
         protected _arrangeChildren(): void;
     }
     }
+}
+declare module BABYLON.GUI {
+    /**
+     * Class used to create an interactable object. It's a touchable 3D button using a mesh coming from the current scene
+     */
+    export class TouchMeshButton3D extends TouchButton3D {
+        /** @hidden */
+        protected _currentMesh: BABYLON.Mesh;
+        /**
+         * Creates a new 3D button based on a mesh
+         * @param mesh mesh to become a 3D button
+         * @param collisionMesh mesh to track collisions with
+         * @param name defines the control name
+         */
+        constructor(mesh: BABYLON.Mesh, options: {
+            collisionMesh: BABYLON.Mesh;
+            useDynamicMesh?: boolean;
+        }, name?: string);
+        protected _getTypeName(): string;
+        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
+        protected _affectMaterial(mesh: BABYLON.AbstractMesh): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a holographic button in 3D
+     */
+    export class TouchHolographicButton extends TouchButton3D {
+        private _backPlate;
+        private _textPlate;
+        private _frontPlate;
+        private _text;
+        private _imageUrl;
+        private _shareMaterials;
+        private _frontMaterial;
+        private _backMaterial;
+        private _plateMaterial;
+        private _pickedPointObserver;
+        private _tooltipFade;
+        private _tooltipTextBlock;
+        private _tooltipTexture;
+        private _tooltipMesh;
+        private _tooltipHoverObserver;
+        private _tooltipOutObserver;
+        private _disposeTooltip;
+        /**
+         * Rendering ground id of all the mesh in the button
+         */
+        set renderingGroupId(id: number);
+        get renderingGroupId(): number;
+        /**
+         * Text to be displayed on the tooltip shown when hovering on the button. When set to null tooltip is disabled. (Default: null)
+         */
+        set tooltipText(text: BABYLON.Nullable<string>);
+        get tooltipText(): BABYLON.Nullable<string>;
+        /**
+         * Gets or sets text for the button
+         */
+        get text(): string;
+        set text(value: string);
+        /**
+         * Gets or sets the image url for the button
+         */
+        get imageUrl(): string;
+        set imageUrl(value: string);
+        /**
+         * Gets the back material used by this button
+         */
+        get backMaterial(): FluentMaterial;
+        /**
+         * Gets the front material used by this button
+         */
+        get frontMaterial(): FluentMaterial;
+        /**
+         * Gets the plate material used by this button
+         */
+        get plateMaterial(): BABYLON.StandardMaterial;
+        /**
+         * Gets a boolean indicating if this button shares its material with other HolographicButtons
+         */
+        get shareMaterials(): boolean;
+        /**
+         * Creates a new button
+         * @param name defines the control name
+         */
+        constructor(name?: string, shareMaterials?: boolean);
+        protected _getTypeName(): string;
+        private _rebuildContent;
+        protected _createNode(scene: BABYLON.Scene): BABYLON.TransformNode;
+        protected _applyFacade(facadeTexture: AdvancedDynamicTexture): void;
+        private _createBackMaterial;
+        private _createFrontMaterial;
+        private _createPlateMaterial;
+        protected _affectMaterial(mesh: BABYLON.Mesh): void;
+        /**
+         * Releases all associated resources
+         */
+        dispose(): void;
+    }
 }
 }

+ 300 - 143
dist/preview release/guiEditor/babylon.guiEditor.d.ts

@@ -436,6 +436,305 @@ declare module GUIEDITOR {
     }
     }
 }
 }
 declare module GUIEDITOR {
 declare module GUIEDITOR {
+    interface ILinePropertyGridComponentProps {
+        line: Line;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class LinePropertyGridComponent extends React.Component<ILinePropertyGridComponentProps> {
+        constructor(props: ILinePropertyGridComponentProps);
+        onDashChange(value: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IRadioButtonPropertyGridComponentProps {
+        radioButton: RadioButton;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class RadioButtonPropertyGridComponent extends React.Component<IRadioButtonPropertyGridComponentProps> {
+        constructor(props: IRadioButtonPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface ITextBlockPropertyGridComponentProps {
+        textBlock: TextBlock;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class TextBlockPropertyGridComponent extends React.Component<ITextBlockPropertyGridComponentProps> {
+        constructor(props: ITextBlockPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IInputTextPropertyGridComponentProps {
+        inputText: InputText;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class InputTextPropertyGridComponent extends React.Component<IInputTextPropertyGridComponentProps> {
+        constructor(props: IInputTextPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface INumericInputComponentProps {
+        label: string;
+        value: number;
+        step?: number;
+        onChange: (value: number) => void;
+        precision?: number;
+    }
+    export class NumericInputComponent extends React.Component<INumericInputComponentProps, {
+        value: string;
+    }> {
+        static defaultProps: {
+            step: number;
+        };
+        private _localChange;
+        constructor(props: INumericInputComponentProps);
+        shouldComponentUpdate(nextProps: INumericInputComponentProps, nextState: {
+            value: string;
+        }): boolean;
+        updateValue(evt: any): void;
+        onBlur(): void;
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    export interface IColorComponentEntryProps {
+        value: number;
+        label: string;
+        max?: number;
+        min?: number;
+        onChange: (value: number) => void;
+    }
+    export class ColorComponentEntry extends React.Component<IColorComponentEntryProps> {
+        constructor(props: IColorComponentEntryProps);
+        updateValue(valueString: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    export interface IHexColorProps {
+        value: string;
+        expectedLength: number;
+        onChange: (value: string) => void;
+    }
+    export class HexColor extends React.Component<IHexColorProps, {
+        hex: string;
+    }> {
+        constructor(props: IHexColorProps);
+        shouldComponentUpdate(nextProps: IHexColorProps, nextState: {
+            hex: string;
+        }): boolean;
+        updateHexValue(valueString: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerProps {
+        color: BABYLON.Color3 | BABYLON.Color4;
+        debugMode?: boolean;
+        onColorChanged?: (color: BABYLON.Color3 | BABYLON.Color4) => void;
+    }
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerState {
+        color: BABYLON.Color3;
+        alpha: number;
+    }
+    /**
+     * Class used to create a color picker
+     */
+    export class ColorPicker extends React.Component<IColorPickerProps, IColorPickerState> {
+        private _saturationRef;
+        private _hueRef;
+        private _isSaturationPointerDown;
+        private _isHuePointerDown;
+        constructor(props: IColorPickerProps);
+        onSaturationPointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onSaturationPointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        onSaturationPointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
+        private _evaluateSaturation;
+        private _evaluateHue;
+        componentDidUpdate(): void;
+        raiseOnColorChanged(): void;
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    export interface IColorPickerComponentProps {
+        value: BABYLON.Color4 | BABYLON.Color3;
+        onColorChanged: (newOne: string) => void;
+    }
+    interface IColorPickerComponentState {
+        pickerEnabled: boolean;
+        color: BABYLON.Color3 | BABYLON.Color4;
+        hex: string;
+    }
+    export class ColorPickerLineComponent extends React.Component<IColorPickerComponentProps, IColorPickerComponentState> {
+        private _floatRef;
+        private _floatHostRef;
+        constructor(props: IColorPickerComponentProps);
+        syncPositions(): void;
+        shouldComponentUpdate(nextProps: IColorPickerComponentProps, nextState: IColorPickerComponentState): boolean;
+        componentDidUpdate(): void;
+        componentDidMount(): void;
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    export interface IColor3LineComponentProps {
+        label: string;
+        target: any;
+        propertyName: string;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+        isLinear?: boolean;
+    }
+    export class Color3LineComponent extends React.Component<IColor3LineComponentProps, {
+        isExpanded: boolean;
+        color: BABYLON.Color3;
+    }> {
+        private _localChange;
+        constructor(props: IColor3LineComponentProps);
+        shouldComponentUpdate(nextProps: IColor3LineComponentProps, nextState: {
+            color: BABYLON.Color3;
+        }): boolean;
+        setPropertyValue(newColor: BABYLON.Color3): void;
+        onChange(newValue: string): void;
+        switchExpandState(): void;
+        raiseOnPropertyChanged(previousValue: BABYLON.Color3): void;
+        updateStateR(value: number): void;
+        updateStateG(value: number): void;
+        updateStateB(value: number): void;
+        copyToClipboard(): void;
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IColorPickerPropertyGridComponentProps {
+        colorPicker: ColorPicker;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ColorPickerPropertyGridComponent extends React.Component<IColorPickerPropertyGridComponentProps> {
+        constructor(props: IColorPickerPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IImagePropertyGridComponentProps {
+        image: Image;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ImagePropertyGridComponent extends React.Component<IImagePropertyGridComponentProps> {
+        constructor(props: IImagePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IImageBasedSliderPropertyGridComponentProps {
+        imageBasedSlider: ImageBasedSlider;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ImageBasedSliderPropertyGridComponent extends React.Component<IImageBasedSliderPropertyGridComponentProps> {
+        constructor(props: IImageBasedSliderPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IRectanglePropertyGridComponentProps {
+        rectangle: Rectangle;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class RectanglePropertyGridComponent extends React.Component<IRectanglePropertyGridComponentProps> {
+        constructor(props: IRectanglePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IStackPanelPropertyGridComponentProps {
+        stackPanel: StackPanel;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class StackPanelPropertyGridComponent extends React.Component<IStackPanelPropertyGridComponentProps> {
+        constructor(props: IStackPanelPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IGridPropertyGridComponentProps {
+        grid: Grid;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class GridPropertyGridComponent extends React.Component<IGridPropertyGridComponentProps> {
+        constructor(props: IGridPropertyGridComponentProps);
+        renderRows(): JSX.Element[];
+        renderColumns(): JSX.Element[];
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IScrollViewerPropertyGridComponentProps {
+        scrollViewer: ScrollViewer;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ScrollViewerPropertyGridComponent extends React.Component<IScrollViewerPropertyGridComponentProps> {
+        constructor(props: IScrollViewerPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IEllipsePropertyGridComponentProps {
+        ellipse: Ellipse;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class EllipsePropertyGridComponent extends React.Component<IEllipsePropertyGridComponentProps> {
+        constructor(props: IEllipsePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface ICheckboxPropertyGridComponentProps {
+        checkbox: Checkbox;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class CheckboxPropertyGridComponent extends React.Component<ICheckboxPropertyGridComponentProps> {
+        constructor(props: ICheckboxPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
+    interface IControlPropertyGridComponentProps {
+        control: Control;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ControlPropertyGridComponent extends React.Component<IControlPropertyGridComponentProps> {
+        constructor(props: IControlPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module GUIEDITOR {
     interface IPropertyTabComponentProps {
     interface IPropertyTabComponentProps {
         globalState: GlobalState;
         globalState: GlobalState;
     }
     }
@@ -470,7 +769,7 @@ declare module GUIEDITOR {
 }
 }
 declare module GUIEDITOR {
 declare module GUIEDITOR {
     export class GUINodeTools {
     export class GUINodeTools {
-        static CreateControlFromString(data: string): Slider | Checkbox | ColorPicker | Ellipse | Rectangle | Line | TextBlock;
+        static CreateControlFromString(data: string): Slider | Line | TextBlock | ColorPicker | Rectangle | Ellipse | Checkbox;
     }
     }
 }
 }
 declare module GUIEDITOR {
 declare module GUIEDITOR {
@@ -749,75 +1048,6 @@ declare module GUIEDITOR {
     }
     }
 }
 }
 declare module GUIEDITOR {
 declare module GUIEDITOR {
-    export interface IColorComponentEntryProps {
-        value: number;
-        label: string;
-        max?: number;
-        min?: number;
-        onChange: (value: number) => void;
-    }
-    export class ColorComponentEntry extends React.Component<IColorComponentEntryProps> {
-        constructor(props: IColorComponentEntryProps);
-        updateValue(valueString: string): void;
-        render(): JSX.Element;
-    }
-}
-declare module GUIEDITOR {
-    export interface IHexColorProps {
-        value: string;
-        expectedLength: number;
-        onChange: (value: string) => void;
-    }
-    export class HexColor extends React.Component<IHexColorProps, {
-        hex: string;
-    }> {
-        constructor(props: IHexColorProps);
-        shouldComponentUpdate(nextProps: IHexColorProps, nextState: {
-            hex: string;
-        }): boolean;
-        updateHexValue(valueString: string): void;
-        render(): JSX.Element;
-    }
-}
-declare module GUIEDITOR {
-    /**
-     * Interface used to specify creation options for color picker
-     */
-    export interface IColorPickerProps {
-        color: BABYLON.Color3 | BABYLON.Color4;
-        debugMode?: boolean;
-        onColorChanged?: (color: BABYLON.Color3 | BABYLON.Color4) => void;
-    }
-    /**
-     * Interface used to specify creation options for color picker
-     */
-    export interface IColorPickerState {
-        color: BABYLON.Color3;
-        alpha: number;
-    }
-    /**
-     * Class used to create a color picker
-     */
-    export class ColorPicker extends React.Component<IColorPickerProps, IColorPickerState> {
-        private _saturationRef;
-        private _hueRef;
-        private _isSaturationPointerDown;
-        private _isHuePointerDown;
-        constructor(props: IColorPickerProps);
-        onSaturationPointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
-        onSaturationPointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
-        onSaturationPointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
-        onHuePointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
-        onHuePointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
-        onHuePointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
-        private _evaluateSaturation;
-        private _evaluateHue;
-        componentDidUpdate(): void;
-        raiseOnColorChanged(): void;
-        render(): JSX.Element;
-    }
-}
-declare module GUIEDITOR {
     export interface IBooleanLineComponentProps {
     export interface IBooleanLineComponentProps {
         label: string;
         label: string;
         value: boolean;
         value: boolean;
@@ -828,79 +1058,6 @@ declare module GUIEDITOR {
     }
     }
 }
 }
 declare module GUIEDITOR {
 declare module GUIEDITOR {
-    interface INumericInputComponentProps {
-        label: string;
-        value: number;
-        step?: number;
-        onChange: (value: number) => void;
-        precision?: number;
-    }
-    export class NumericInputComponent extends React.Component<INumericInputComponentProps, {
-        value: string;
-    }> {
-        static defaultProps: {
-            step: number;
-        };
-        private _localChange;
-        constructor(props: INumericInputComponentProps);
-        shouldComponentUpdate(nextProps: INumericInputComponentProps, nextState: {
-            value: string;
-        }): boolean;
-        updateValue(evt: any): void;
-        onBlur(): void;
-        render(): JSX.Element;
-    }
-}
-declare module GUIEDITOR {
-    export interface IColorPickerComponentProps {
-        value: BABYLON.Color4 | BABYLON.Color3;
-        onColorChanged: (newOne: string) => void;
-    }
-    interface IColorPickerComponentState {
-        pickerEnabled: boolean;
-        color: BABYLON.Color3 | BABYLON.Color4;
-        hex: string;
-    }
-    export class ColorPickerLineComponent extends React.Component<IColorPickerComponentProps, IColorPickerComponentState> {
-        private _floatRef;
-        private _floatHostRef;
-        constructor(props: IColorPickerComponentProps);
-        syncPositions(): void;
-        shouldComponentUpdate(nextProps: IColorPickerComponentProps, nextState: IColorPickerComponentState): boolean;
-        componentDidUpdate(): void;
-        componentDidMount(): void;
-        render(): JSX.Element;
-    }
-}
-declare module GUIEDITOR {
-    export interface IColor3LineComponentProps {
-        label: string;
-        target: any;
-        propertyName: string;
-        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
-        isLinear?: boolean;
-    }
-    export class Color3LineComponent extends React.Component<IColor3LineComponentProps, {
-        isExpanded: boolean;
-        color: BABYLON.Color3;
-    }> {
-        private _localChange;
-        constructor(props: IColor3LineComponentProps);
-        shouldComponentUpdate(nextProps: IColor3LineComponentProps, nextState: {
-            color: BABYLON.Color3;
-        }): boolean;
-        setPropertyValue(newColor: BABYLON.Color3): void;
-        onChange(newValue: string): void;
-        switchExpandState(): void;
-        raiseOnPropertyChanged(previousValue: BABYLON.Color3): void;
-        updateStateR(value: number): void;
-        updateStateG(value: number): void;
-        updateStateB(value: number): void;
-        copyToClipboard(): void;
-        render(): JSX.Element;
-    }
-}
-declare module GUIEDITOR {
     export interface IColor4LineComponentProps {
     export interface IColor4LineComponentProps {
         label: string;
         label: string;
         target: any;
         target: any;

File diff suppressed because it is too large
+ 10 - 5
dist/preview release/guiEditor/babylon.guiEditor.js


File diff suppressed because it is too large
+ 12672 - 4
dist/preview release/guiEditor/babylon.guiEditor.max.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/guiEditor/babylon.guiEditor.max.js.map


File diff suppressed because it is too large
+ 1481 - 1097
dist/preview release/guiEditor/babylon.guiEditor.module.d.ts


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js


File diff suppressed because it is too large
+ 3128 - 3128
dist/preview release/inspector/babylon.inspector.bundle.max.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


+ 0 - 14
dist/preview release/inspector/babylon.inspector.d.ts

@@ -1483,7 +1483,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IControlPropertyGridComponentProps {
     interface IControlPropertyGridComponentProps {
-        globalState: GlobalState;
         control: BABYLON.GUI.Control;
         control: BABYLON.GUI.Control;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1495,7 +1494,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface ITextBlockPropertyGridComponentProps {
     interface ITextBlockPropertyGridComponentProps {
-        globalState: GlobalState;
         textBlock: BABYLON.GUI.TextBlock;
         textBlock: BABYLON.GUI.TextBlock;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1507,7 +1505,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IInputTextPropertyGridComponentProps {
     interface IInputTextPropertyGridComponentProps {
-        globalState: GlobalState;
         inputText: BABYLON.GUI.InputText;
         inputText: BABYLON.GUI.InputText;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1519,7 +1516,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IColorPickerPropertyGridComponentProps {
     interface IColorPickerPropertyGridComponentProps {
-        globalState: GlobalState;
         colorPicker: BABYLON.GUI.ColorPicker;
         colorPicker: BABYLON.GUI.ColorPicker;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1558,7 +1554,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IImagePropertyGridComponentProps {
     interface IImagePropertyGridComponentProps {
-        globalState: GlobalState;
         image: BABYLON.GUI.Image;
         image: BABYLON.GUI.Image;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1581,7 +1576,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IImageBasedSliderPropertyGridComponentProps {
     interface IImageBasedSliderPropertyGridComponentProps {
-        globalState: GlobalState;
         imageBasedSlider: BABYLON.GUI.ImageBasedSlider;
         imageBasedSlider: BABYLON.GUI.ImageBasedSlider;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1593,7 +1587,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IRectanglePropertyGridComponentProps {
     interface IRectanglePropertyGridComponentProps {
-        globalState: GlobalState;
         rectangle: BABYLON.GUI.Rectangle;
         rectangle: BABYLON.GUI.Rectangle;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1605,7 +1598,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IEllipsePropertyGridComponentProps {
     interface IEllipsePropertyGridComponentProps {
-        globalState: GlobalState;
         ellipse: BABYLON.GUI.Ellipse;
         ellipse: BABYLON.GUI.Ellipse;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1617,7 +1609,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface ICheckboxPropertyGridComponentProps {
     interface ICheckboxPropertyGridComponentProps {
-        globalState: GlobalState;
         checkbox: BABYLON.GUI.Checkbox;
         checkbox: BABYLON.GUI.Checkbox;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1629,7 +1620,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IRadioButtonPropertyGridComponentProps {
     interface IRadioButtonPropertyGridComponentProps {
-        globalState: GlobalState;
         radioButton: BABYLON.GUI.RadioButton;
         radioButton: BABYLON.GUI.RadioButton;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1641,7 +1631,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface ILinePropertyGridComponentProps {
     interface ILinePropertyGridComponentProps {
-        globalState: GlobalState;
         line: BABYLON.GUI.Line;
         line: BABYLON.GUI.Line;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1654,7 +1643,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IScrollViewerPropertyGridComponentProps {
     interface IScrollViewerPropertyGridComponentProps {
-        globalState: GlobalState;
         scrollViewer: BABYLON.GUI.ScrollViewer;
         scrollViewer: BABYLON.GUI.ScrollViewer;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1666,7 +1654,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IGridPropertyGridComponentProps {
     interface IGridPropertyGridComponentProps {
-        globalState: GlobalState;
         grid: BABYLON.GUI.Grid;
         grid: BABYLON.GUI.Grid;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -1710,7 +1697,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IStackPanelPropertyGridComponentProps {
     interface IStackPanelPropertyGridComponentProps {
-        globalState: GlobalState;
         stackPanel: BABYLON.GUI.StackPanel;
         stackPanel: BABYLON.GUI.StackPanel;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;

+ 28 - 70
dist/preview release/inspector/babylon.inspector.module.d.ts

@@ -1742,15 +1742,13 @@ declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/co
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/controlPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/controlPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { Control } from "babylonjs-gui/2D/controls/control";
     import { Control } from "babylonjs-gui/2D/controls/control";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     interface IControlPropertyGridComponentProps {
     interface IControlPropertyGridComponentProps {
-        globalState: GlobalState;
         control: Control;
         control: Control;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1760,15 +1758,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/textBlockPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/textBlockPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { TextBlock } from "babylonjs-gui/2D/controls/textBlock";
     import { TextBlock } from "babylonjs-gui/2D/controls/textBlock";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface ITextBlockPropertyGridComponentProps {
     interface ITextBlockPropertyGridComponentProps {
-        globalState: GlobalState;
         textBlock: TextBlock;
         textBlock: TextBlock;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1778,15 +1774,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/inputTextPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/inputTextPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { InputText } from "babylonjs-gui/2D/controls/inputText";
     import { InputText } from "babylonjs-gui/2D/controls/inputText";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IInputTextPropertyGridComponentProps {
     interface IInputTextPropertyGridComponentProps {
-        globalState: GlobalState;
         inputText: InputText;
         inputText: InputText;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1796,15 +1790,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/colorPickerPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/colorPickerPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { ColorPicker } from "babylonjs-gui/2D/controls/colorpicker";
     import { ColorPicker } from "babylonjs-gui/2D/controls/colorpicker";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IColorPickerPropertyGridComponentProps {
     interface IColorPickerPropertyGridComponentProps {
-        globalState: GlobalState;
         colorPicker: ColorPicker;
         colorPicker: ColorPicker;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1848,15 +1840,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/ani
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/imagePropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/imagePropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { Image } from "babylonjs-gui/2D/controls/image";
     import { Image } from "babylonjs-gui/2D/controls/image";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IImagePropertyGridComponentProps {
     interface IImagePropertyGridComponentProps {
-        globalState: GlobalState;
         image: Image;
         image: Image;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1882,15 +1872,13 @@ declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/sl
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { ImageBasedSlider } from "babylonjs-gui/2D/controls/sliders/imageBasedSlider";
     import { ImageBasedSlider } from "babylonjs-gui/2D/controls/sliders/imageBasedSlider";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IImageBasedSliderPropertyGridComponentProps {
     interface IImageBasedSliderPropertyGridComponentProps {
-        globalState: GlobalState;
         imageBasedSlider: ImageBasedSlider;
         imageBasedSlider: ImageBasedSlider;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1900,15 +1888,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/rectanglePropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/rectanglePropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { Rectangle } from "babylonjs-gui/2D/controls/rectangle";
     import { Rectangle } from "babylonjs-gui/2D/controls/rectangle";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IRectanglePropertyGridComponentProps {
     interface IRectanglePropertyGridComponentProps {
-        globalState: GlobalState;
         rectangle: Rectangle;
         rectangle: Rectangle;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1918,15 +1904,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/ellipsePropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/ellipsePropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { Ellipse } from "babylonjs-gui/2D/controls/ellipse";
     import { Ellipse } from "babylonjs-gui/2D/controls/ellipse";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IEllipsePropertyGridComponentProps {
     interface IEllipsePropertyGridComponentProps {
-        globalState: GlobalState;
         ellipse: Ellipse;
         ellipse: Ellipse;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1936,15 +1920,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/checkboxPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/checkboxPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { Checkbox } from "babylonjs-gui/2D/controls/checkbox";
     import { Checkbox } from "babylonjs-gui/2D/controls/checkbox";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface ICheckboxPropertyGridComponentProps {
     interface ICheckboxPropertyGridComponentProps {
-        globalState: GlobalState;
         checkbox: Checkbox;
         checkbox: Checkbox;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1954,15 +1936,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/radioButtonPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/radioButtonPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { RadioButton } from "babylonjs-gui/2D/controls/radioButton";
     import { RadioButton } from "babylonjs-gui/2D/controls/radioButton";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IRadioButtonPropertyGridComponentProps {
     interface IRadioButtonPropertyGridComponentProps {
-        globalState: GlobalState;
         radioButton: RadioButton;
         radioButton: RadioButton;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1972,15 +1952,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/linePropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/linePropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { Line } from "babylonjs-gui/2D/controls/line";
     import { Line } from "babylonjs-gui/2D/controls/line";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface ILinePropertyGridComponentProps {
     interface ILinePropertyGridComponentProps {
-        globalState: GlobalState;
         line: Line;
         line: Line;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -1991,15 +1969,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { ScrollViewer } from "babylonjs-gui/2D/controls/scrollViewers/scrollViewer";
     import { ScrollViewer } from "babylonjs-gui/2D/controls/scrollViewers/scrollViewer";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IScrollViewerPropertyGridComponentProps {
     interface IScrollViewerPropertyGridComponentProps {
-        globalState: GlobalState;
         scrollViewer: ScrollViewer;
         scrollViewer: ScrollViewer;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -2009,15 +1985,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/gridPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/gridPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { Grid } from "babylonjs-gui/2D/controls/grid";
     import { Grid } from "babylonjs-gui/2D/controls/grid";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IGridPropertyGridComponentProps {
     interface IGridPropertyGridComponentProps {
-        globalState: GlobalState;
         grid: Grid;
         grid: Grid;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -2071,15 +2045,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/mat
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/gui/stackPanelPropertyGridComponent" {
+declare module "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/gui/stackPanelPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
-    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    import { PropertyChangedEvent } from "babylonjs-inspector/sharedUiComponents/propertyChangedEvent";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { LockObject } from "babylonjs-inspector/sharedUiComponents/tabs/propertyGrids/lockObject";
     import { StackPanel } from "babylonjs-gui/2D/controls/stackPanel";
     import { StackPanel } from "babylonjs-gui/2D/controls/stackPanel";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface IStackPanelPropertyGridComponentProps {
     interface IStackPanelPropertyGridComponentProps {
-        globalState: GlobalState;
         stackPanel: StackPanel;
         stackPanel: StackPanel;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
@@ -6664,7 +6636,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IControlPropertyGridComponentProps {
     interface IControlPropertyGridComponentProps {
-        globalState: GlobalState;
         control: BABYLON.GUI.Control;
         control: BABYLON.GUI.Control;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6676,7 +6647,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface ITextBlockPropertyGridComponentProps {
     interface ITextBlockPropertyGridComponentProps {
-        globalState: GlobalState;
         textBlock: BABYLON.GUI.TextBlock;
         textBlock: BABYLON.GUI.TextBlock;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6688,7 +6658,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IInputTextPropertyGridComponentProps {
     interface IInputTextPropertyGridComponentProps {
-        globalState: GlobalState;
         inputText: BABYLON.GUI.InputText;
         inputText: BABYLON.GUI.InputText;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6700,7 +6669,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IColorPickerPropertyGridComponentProps {
     interface IColorPickerPropertyGridComponentProps {
-        globalState: GlobalState;
         colorPicker: BABYLON.GUI.ColorPicker;
         colorPicker: BABYLON.GUI.ColorPicker;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6739,7 +6707,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IImagePropertyGridComponentProps {
     interface IImagePropertyGridComponentProps {
-        globalState: GlobalState;
         image: BABYLON.GUI.Image;
         image: BABYLON.GUI.Image;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6762,7 +6729,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IImageBasedSliderPropertyGridComponentProps {
     interface IImageBasedSliderPropertyGridComponentProps {
-        globalState: GlobalState;
         imageBasedSlider: BABYLON.GUI.ImageBasedSlider;
         imageBasedSlider: BABYLON.GUI.ImageBasedSlider;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6774,7 +6740,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IRectanglePropertyGridComponentProps {
     interface IRectanglePropertyGridComponentProps {
-        globalState: GlobalState;
         rectangle: BABYLON.GUI.Rectangle;
         rectangle: BABYLON.GUI.Rectangle;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6786,7 +6751,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IEllipsePropertyGridComponentProps {
     interface IEllipsePropertyGridComponentProps {
-        globalState: GlobalState;
         ellipse: BABYLON.GUI.Ellipse;
         ellipse: BABYLON.GUI.Ellipse;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6798,7 +6762,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface ICheckboxPropertyGridComponentProps {
     interface ICheckboxPropertyGridComponentProps {
-        globalState: GlobalState;
         checkbox: BABYLON.GUI.Checkbox;
         checkbox: BABYLON.GUI.Checkbox;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6810,7 +6773,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IRadioButtonPropertyGridComponentProps {
     interface IRadioButtonPropertyGridComponentProps {
-        globalState: GlobalState;
         radioButton: BABYLON.GUI.RadioButton;
         radioButton: BABYLON.GUI.RadioButton;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6822,7 +6784,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface ILinePropertyGridComponentProps {
     interface ILinePropertyGridComponentProps {
-        globalState: GlobalState;
         line: BABYLON.GUI.Line;
         line: BABYLON.GUI.Line;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6835,7 +6796,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IScrollViewerPropertyGridComponentProps {
     interface IScrollViewerPropertyGridComponentProps {
-        globalState: GlobalState;
         scrollViewer: BABYLON.GUI.ScrollViewer;
         scrollViewer: BABYLON.GUI.ScrollViewer;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6847,7 +6807,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IGridPropertyGridComponentProps {
     interface IGridPropertyGridComponentProps {
-        globalState: GlobalState;
         grid: BABYLON.GUI.Grid;
         grid: BABYLON.GUI.Grid;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
@@ -6891,7 +6850,6 @@ declare module INSPECTOR {
 }
 }
 declare module INSPECTOR {
 declare module INSPECTOR {
     interface IStackPanelPropertyGridComponentProps {
     interface IStackPanelPropertyGridComponentProps {
-        globalState: GlobalState;
         stackPanel: BABYLON.GUI.StackPanel;
         stackPanel: BABYLON.GUI.StackPanel;
         lockObject: LockObject;
         lockObject: LockObject;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;

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

@@ -3798,7 +3798,9 @@ var GLTFLoader = /** @class */ (function () {
         var babylonAbstractMesh;
         var babylonAbstractMesh;
         var promise;
         var promise;
         if (shouldInstance && primitive._instanceData) {
         if (shouldInstance && primitive._instanceData) {
+            this._babylonScene._blockEntityCollection = this._forAssetContainer;
             babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name);
             babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name);
+            this._babylonScene._blockEntityCollection = false;
             promise = primitive._instanceData.promise;
             promise = primitive._instanceData.promise;
         }
         }
         else {
         else {

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js.map


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


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

@@ -6150,7 +6150,9 @@ var GLTFLoader = /** @class */ (function () {
         var babylonAbstractMesh;
         var babylonAbstractMesh;
         var promise;
         var promise;
         if (shouldInstance && primitive._instanceData) {
         if (shouldInstance && primitive._instanceData) {
+            this._babylonScene._blockEntityCollection = this._forAssetContainer;
             babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name);
             babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name);
+            this._babylonScene._blockEntityCollection = false;
             promise = primitive._instanceData.promise;
             promise = primitive._instanceData.promise;
         }
         }
         else {
         else {

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js.map


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


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

@@ -7586,7 +7586,9 @@ var GLTFLoader = /** @class */ (function () {
         var babylonAbstractMesh;
         var babylonAbstractMesh;
         var promise;
         var promise;
         if (shouldInstance && primitive._instanceData) {
         if (shouldInstance && primitive._instanceData) {
+            this._babylonScene._blockEntityCollection = this._forAssetContainer;
             babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name);
             babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name);
+            this._babylonScene._blockEntityCollection = false;
             promise = primitive._instanceData.promise;
             promise = primitive._instanceData.promise;
         }
         }
         else {
         else {

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js.map


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


+ 157 - 0
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts

@@ -2279,6 +2279,141 @@ declare module NODEEDITOR {
     }
     }
 }
 }
 declare module NODEEDITOR {
 declare module NODEEDITOR {
+    interface ICheckboxPropertyGridComponentProps {
+        checkbox: Checkbox;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class CheckboxPropertyGridComponent extends React.Component<ICheckboxPropertyGridComponentProps> {
+        constructor(props: ICheckboxPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IColorPickerPropertyGridComponentProps {
+        colorPicker: ColorPicker;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ColorPickerPropertyGridComponent extends React.Component<IColorPickerPropertyGridComponentProps> {
+        constructor(props: IColorPickerPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IControlPropertyGridComponentProps {
+        control: Control;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ControlPropertyGridComponent extends React.Component<IControlPropertyGridComponentProps> {
+        constructor(props: IControlPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IEllipsePropertyGridComponentProps {
+        ellipse: Ellipse;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class EllipsePropertyGridComponent extends React.Component<IEllipsePropertyGridComponentProps> {
+        constructor(props: IEllipsePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IGridPropertyGridComponentProps {
+        grid: Grid;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class GridPropertyGridComponent extends React.Component<IGridPropertyGridComponentProps> {
+        constructor(props: IGridPropertyGridComponentProps);
+        renderRows(): JSX.Element[];
+        renderColumns(): JSX.Element[];
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IImageBasedSliderPropertyGridComponentProps {
+        imageBasedSlider: ImageBasedSlider;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ImageBasedSliderPropertyGridComponent extends React.Component<IImageBasedSliderPropertyGridComponentProps> {
+        constructor(props: IImageBasedSliderPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IImagePropertyGridComponentProps {
+        image: Image;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ImagePropertyGridComponent extends React.Component<IImagePropertyGridComponentProps> {
+        constructor(props: IImagePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IInputTextPropertyGridComponentProps {
+        inputText: InputText;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class InputTextPropertyGridComponent extends React.Component<IInputTextPropertyGridComponentProps> {
+        constructor(props: IInputTextPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface ILinePropertyGridComponentProps {
+        line: Line;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class LinePropertyGridComponent extends React.Component<ILinePropertyGridComponentProps> {
+        constructor(props: ILinePropertyGridComponentProps);
+        onDashChange(value: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IRadioButtonPropertyGridComponentProps {
+        radioButton: RadioButton;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class RadioButtonPropertyGridComponent extends React.Component<IRadioButtonPropertyGridComponentProps> {
+        constructor(props: IRadioButtonPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IRectanglePropertyGridComponentProps {
+        rectangle: Rectangle;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class RectanglePropertyGridComponent extends React.Component<IRectanglePropertyGridComponentProps> {
+        constructor(props: IRectanglePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IScrollViewerPropertyGridComponentProps {
+        scrollViewer: ScrollViewer;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ScrollViewerPropertyGridComponent extends React.Component<IScrollViewerPropertyGridComponentProps> {
+        constructor(props: IScrollViewerPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
     interface ISliderPropertyGridComponentProps {
     interface ISliderPropertyGridComponentProps {
         slider: Slider;
         slider: Slider;
         lockObject: LockObject;
         lockObject: LockObject;
@@ -2288,4 +2423,26 @@ declare module NODEEDITOR {
         constructor(props: ISliderPropertyGridComponentProps);
         constructor(props: ISliderPropertyGridComponentProps);
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
+}
+declare module NODEEDITOR {
+    interface IStackPanelPropertyGridComponentProps {
+        stackPanel: StackPanel;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class StackPanelPropertyGridComponent extends React.Component<IStackPanelPropertyGridComponentProps> {
+        constructor(props: IStackPanelPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface ITextBlockPropertyGridComponentProps {
+        textBlock: TextBlock;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class TextBlockPropertyGridComponent extends React.Component<ITextBlockPropertyGridComponentProps> {
+        constructor(props: ITextBlockPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
 }
 }

+ 384 - 0
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts

@@ -2674,6 +2674,201 @@ declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/checkboxPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { Checkbox } from "babylonjs-gui/2D/controls/checkbox";
+    interface ICheckboxPropertyGridComponentProps {
+        checkbox: Checkbox;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class CheckboxPropertyGridComponent extends React.Component<ICheckboxPropertyGridComponentProps> {
+        constructor(props: ICheckboxPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/colorPickerPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { ColorPicker } from "babylonjs-gui/2D/controls/colorpicker";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    interface IColorPickerPropertyGridComponentProps {
+        colorPicker: ColorPicker;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class ColorPickerPropertyGridComponent extends React.Component<IColorPickerPropertyGridComponentProps> {
+        constructor(props: IColorPickerPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/controlPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { Control } from "babylonjs-gui/2D/controls/control";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    interface IControlPropertyGridComponentProps {
+        control: Control;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class ControlPropertyGridComponent extends React.Component<IControlPropertyGridComponentProps> {
+        constructor(props: IControlPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/ellipsePropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { Ellipse } from "babylonjs-gui/2D/controls/ellipse";
+    interface IEllipsePropertyGridComponentProps {
+        ellipse: Ellipse;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class EllipsePropertyGridComponent extends React.Component<IEllipsePropertyGridComponentProps> {
+        constructor(props: IEllipsePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/gridPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { Grid } from "babylonjs-gui/2D/controls/grid";
+    interface IGridPropertyGridComponentProps {
+        grid: Grid;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class GridPropertyGridComponent extends React.Component<IGridPropertyGridComponentProps> {
+        constructor(props: IGridPropertyGridComponentProps);
+        renderRows(): JSX.Element[];
+        renderColumns(): JSX.Element[];
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { ImageBasedSlider } from "babylonjs-gui/2D/controls/sliders/imageBasedSlider";
+    interface IImageBasedSliderPropertyGridComponentProps {
+        imageBasedSlider: ImageBasedSlider;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class ImageBasedSliderPropertyGridComponent extends React.Component<IImageBasedSliderPropertyGridComponentProps> {
+        constructor(props: IImageBasedSliderPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/imagePropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { Image } from "babylonjs-gui/2D/controls/image";
+    interface IImagePropertyGridComponentProps {
+        image: Image;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class ImagePropertyGridComponent extends React.Component<IImagePropertyGridComponentProps> {
+        constructor(props: IImagePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/inputTextPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { InputText } from "babylonjs-gui/2D/controls/inputText";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    interface IInputTextPropertyGridComponentProps {
+        inputText: InputText;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class InputTextPropertyGridComponent extends React.Component<IInputTextPropertyGridComponentProps> {
+        constructor(props: IInputTextPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/linePropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { Line } from "babylonjs-gui/2D/controls/line";
+    interface ILinePropertyGridComponentProps {
+        line: Line;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class LinePropertyGridComponent extends React.Component<ILinePropertyGridComponentProps> {
+        constructor(props: ILinePropertyGridComponentProps);
+        onDashChange(value: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/radioButtonPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { RadioButton } from "babylonjs-gui/2D/controls/radioButton";
+    interface IRadioButtonPropertyGridComponentProps {
+        radioButton: RadioButton;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class RadioButtonPropertyGridComponent extends React.Component<IRadioButtonPropertyGridComponentProps> {
+        constructor(props: IRadioButtonPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/rectanglePropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { Rectangle } from "babylonjs-gui/2D/controls/rectangle";
+    interface IRectanglePropertyGridComponentProps {
+        rectangle: Rectangle;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class RectanglePropertyGridComponent extends React.Component<IRectanglePropertyGridComponentProps> {
+        constructor(props: IRectanglePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { ScrollViewer } from "babylonjs-gui/2D/controls/scrollViewers/scrollViewer";
+    interface IScrollViewerPropertyGridComponentProps {
+        scrollViewer: ScrollViewer;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class ScrollViewerPropertyGridComponent extends React.Component<IScrollViewerPropertyGridComponentProps> {
+        constructor(props: IScrollViewerPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
 declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/sliderPropertyGridComponent" {
 declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/sliderPropertyGridComponent" {
     import * as React from "react";
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
@@ -2690,6 +2885,38 @@ declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/stackPanelPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    import { StackPanel } from "babylonjs-gui/2D/controls/stackPanel";
+    interface IStackPanelPropertyGridComponentProps {
+        stackPanel: StackPanel;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class StackPanelPropertyGridComponent extends React.Component<IStackPanelPropertyGridComponentProps> {
+        constructor(props: IStackPanelPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/gui/textBlockPropertyGridComponent" {
+    import * as React from "react";
+    import { Observable } from "babylonjs/Misc/observable";
+    import { PropertyChangedEvent } from "babylonjs-node-editor/sharedUiComponents/propertyChangedEvent";
+    import { TextBlock } from "babylonjs-gui/2D/controls/textBlock";
+    import { LockObject } from "babylonjs-node-editor/sharedUiComponents/tabs/propertyGrids/lockObject";
+    interface ITextBlockPropertyGridComponentProps {
+        textBlock: TextBlock;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    }
+    export class TextBlockPropertyGridComponent extends React.Component<ITextBlockPropertyGridComponentProps> {
+        constructor(props: ITextBlockPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
 declare module "babylonjs-node-editor" {
 declare module "babylonjs-node-editor" {
     export * from "babylonjs-node-editor/legacy/legacy";
     export * from "babylonjs-node-editor/legacy/legacy";
 }
 }
@@ -4974,6 +5201,141 @@ declare module NODEEDITOR {
     }
     }
 }
 }
 declare module NODEEDITOR {
 declare module NODEEDITOR {
+    interface ICheckboxPropertyGridComponentProps {
+        checkbox: Checkbox;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class CheckboxPropertyGridComponent extends React.Component<ICheckboxPropertyGridComponentProps> {
+        constructor(props: ICheckboxPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IColorPickerPropertyGridComponentProps {
+        colorPicker: ColorPicker;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ColorPickerPropertyGridComponent extends React.Component<IColorPickerPropertyGridComponentProps> {
+        constructor(props: IColorPickerPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IControlPropertyGridComponentProps {
+        control: Control;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ControlPropertyGridComponent extends React.Component<IControlPropertyGridComponentProps> {
+        constructor(props: IControlPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IEllipsePropertyGridComponentProps {
+        ellipse: Ellipse;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class EllipsePropertyGridComponent extends React.Component<IEllipsePropertyGridComponentProps> {
+        constructor(props: IEllipsePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IGridPropertyGridComponentProps {
+        grid: Grid;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class GridPropertyGridComponent extends React.Component<IGridPropertyGridComponentProps> {
+        constructor(props: IGridPropertyGridComponentProps);
+        renderRows(): JSX.Element[];
+        renderColumns(): JSX.Element[];
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IImageBasedSliderPropertyGridComponentProps {
+        imageBasedSlider: ImageBasedSlider;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ImageBasedSliderPropertyGridComponent extends React.Component<IImageBasedSliderPropertyGridComponentProps> {
+        constructor(props: IImageBasedSliderPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IImagePropertyGridComponentProps {
+        image: Image;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ImagePropertyGridComponent extends React.Component<IImagePropertyGridComponentProps> {
+        constructor(props: IImagePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IInputTextPropertyGridComponentProps {
+        inputText: InputText;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class InputTextPropertyGridComponent extends React.Component<IInputTextPropertyGridComponentProps> {
+        constructor(props: IInputTextPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface ILinePropertyGridComponentProps {
+        line: Line;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class LinePropertyGridComponent extends React.Component<ILinePropertyGridComponentProps> {
+        constructor(props: ILinePropertyGridComponentProps);
+        onDashChange(value: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IRadioButtonPropertyGridComponentProps {
+        radioButton: RadioButton;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class RadioButtonPropertyGridComponent extends React.Component<IRadioButtonPropertyGridComponentProps> {
+        constructor(props: IRadioButtonPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IRectanglePropertyGridComponentProps {
+        rectangle: Rectangle;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class RectanglePropertyGridComponent extends React.Component<IRectanglePropertyGridComponentProps> {
+        constructor(props: IRectanglePropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface IScrollViewerPropertyGridComponentProps {
+        scrollViewer: ScrollViewer;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class ScrollViewerPropertyGridComponent extends React.Component<IScrollViewerPropertyGridComponentProps> {
+        constructor(props: IScrollViewerPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
     interface ISliderPropertyGridComponentProps {
     interface ISliderPropertyGridComponentProps {
         slider: Slider;
         slider: Slider;
         lockObject: LockObject;
         lockObject: LockObject;
@@ -4983,4 +5345,26 @@ declare module NODEEDITOR {
         constructor(props: ISliderPropertyGridComponentProps);
         constructor(props: ISliderPropertyGridComponentProps);
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
+}
+declare module NODEEDITOR {
+    interface IStackPanelPropertyGridComponentProps {
+        stackPanel: StackPanel;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class StackPanelPropertyGridComponent extends React.Component<IStackPanelPropertyGridComponentProps> {
+        constructor(props: IStackPanelPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    interface ITextBlockPropertyGridComponentProps {
+        textBlock: TextBlock;
+        lockObject: LockObject;
+        onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
+    }
+    export class TextBlockPropertyGridComponent extends React.Component<ITextBlockPropertyGridComponentProps> {
+        constructor(props: ITextBlockPropertyGridComponentProps);
+        render(): JSX.Element;
+    }
 }
 }

+ 1 - 1
dist/preview release/packagesSizeBaseLine.json

@@ -1 +1 @@
-{"thinEngineOnly":130230,"engineOnly":167557,"sceneOnly":523120,"minGridMaterial":699118,"minStandardMaterial":862977}
+{"thinEngineOnly":130254,"engineOnly":167581,"sceneOnly":533539,"minGridMaterial":710011,"minStandardMaterial":873876}

File diff suppressed because it is too large
+ 1264 - 683
dist/preview release/viewer/babylon.module.d.ts


File diff suppressed because it is too large
+ 26 - 22
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -17,6 +17,7 @@
 - Moved sharedUI component to shared UI folder. ([msDestiny14](https://github.com/msDestiny14))
 - Moved sharedUI component to shared UI folder. ([msDestiny14](https://github.com/msDestiny14))
 - Added encapsulate and encapsulateBoundingInfo methods to BoundingInfo. ([Tolo789](https://github.com/Tolo789))
 - Added encapsulate and encapsulateBoundingInfo methods to BoundingInfo. ([Tolo789](https://github.com/Tolo789))
 - Added onLoadObservable to the textureDome class(es) ([RaananW](https://github.com/RaananW))
 - Added onLoadObservable to the textureDome class(es) ([RaananW](https://github.com/RaananW))
+- Modified InputManager to use DeviceInputSystem ([PolygonalSun](https://github.com/PolygonalSun))
 
 
 ### Engine
 ### Engine
 
 
@@ -55,7 +56,7 @@
 ### GUIEditor
 ### GUIEditor
 
 
 - Added GUI Editor project to master. ([msDestiny14](https://github.com/msDestiny14))
 - Added GUI Editor project to master. ([msDestiny14](https://github.com/msDestiny14))
-- Moving GUI property tab components into GUIEditor: Slider. ([msDestiny14](https://github.com/msDestiny14))
+- Moving GUI property tab components into GUIEditor. ([msDestiny14](https://github.com/msDestiny14))
 
 
 ### GUI
 ### GUI
 
 
@@ -63,6 +64,7 @@
 - Added `focus()` and `blur()` functions for controls that implement `IFocusableControl` ([Flux159](https://github.com/Flux159))
 - Added `focus()` and `blur()` functions for controls that implement `IFocusableControl` ([Flux159](https://github.com/Flux159))
 - Added `ToggleButton` GUI control ([kintz09](https://github.com/kintz09))
 - Added `ToggleButton` GUI control ([kintz09](https://github.com/kintz09))
 - Added shorthand methods which set all padding values at once, named `setPadding` and `setPaddingInPixels`, to the control class  ([kintz09](https://github.com/kintz09))
 - Added shorthand methods which set all padding values at once, named `setPadding` and `setPaddingInPixels`, to the control class  ([kintz09](https://github.com/kintz09))
+- Added two touch-enabled GUI controls, `TouchMeshButton3D` and `TouchHolographicButton`, added option on the WebXR hand tracking feature for enabling touch collisions ([rickfromwork](https://github.com/rickfromwork), [satyapoojasama](https://github.com/satyapoojasama))
 
 
 ### WebXR
 ### WebXR
 
 
@@ -72,6 +74,7 @@
 - Pointer Events of WebXR controllers have pointerType `xr` ([RaananW](https://github.com/RaananW))
 - Pointer Events of WebXR controllers have pointerType `xr` ([RaananW](https://github.com/RaananW))
 - better support for custom hand meshes ([RaananW](https://github.com/RaananW))
 - better support for custom hand meshes ([RaananW](https://github.com/RaananW))
 - Allow disabling of the WebXRControllerPointerSelection feature as part of the WebXR Default Experience ([rgerd](https://github.com/rgerd))
 - Allow disabling of the WebXRControllerPointerSelection feature as part of the WebXR Default Experience ([rgerd](https://github.com/rgerd))
+- Added two touch-enabled GUI controls, `TouchMeshButton3D` and `TouchHolographicButton`, added option on the WebXR hand tracking feature for enabling touch collisions ([rickfromwork](https://github.com/rickfromwork), [satyapoojasama](https://github.com/satyapoojasama))
 
 
 ### Viewer
 ### Viewer
 
 

+ 8 - 7
gui/src/2D/advancedDynamicTexture.ts

@@ -23,6 +23,7 @@ import { Constants } from 'babylonjs/Engines/constants';
 import { Viewport } from 'babylonjs/Maths/math.viewport';
 import { Viewport } from 'babylonjs/Maths/math.viewport';
 import { Color3 } from 'babylonjs/Maths/math.color';
 import { Color3 } from 'babylonjs/Maths/math.color';
 import { WebRequest } from "babylonjs/Misc/webRequest";
 import { WebRequest } from "babylonjs/Misc/webRequest";
+import { IPointerEvent, IWheelEvent } from 'babylonjs/Events/deviceInputEvents';
 
 
 /**
 /**
 * Class used to create texture to support 2D GUI elements
 * Class used to create texture to support 2D GUI elements
@@ -41,7 +42,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
     private _preKeyboardObserver: Nullable<Observer<KeyboardInfoPre>>;
     private _preKeyboardObserver: Nullable<Observer<KeyboardInfoPre>>;
     private _pointerMoveObserver: Nullable<Observer<PointerInfoPre>>;
     private _pointerMoveObserver: Nullable<Observer<PointerInfoPre>>;
     private _pointerObserver: Nullable<Observer<PointerInfo>>;
     private _pointerObserver: Nullable<Observer<PointerInfo>>;
-    private _canvasPointerOutObserver: Nullable<Observer<PointerEvent>>;
+    private _canvasPointerOutObserver: Nullable<Observer<IPointerEvent>>;
     private _canvasBlurObserver: Nullable<Observer<Engine>>;
     private _canvasBlurObserver: Nullable<Observer<Engine>>;
     private _background: string;
     private _background: string;
     /** @hidden */
     /** @hidden */
@@ -711,7 +712,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         let tempViewport = new Viewport(0, 0, 0, 0);
         let tempViewport = new Viewport(0, 0, 0, 0);
 
 
         this._pointerMoveObserver = scene.onPrePointerObservable.add((pi, state) => {
         this._pointerMoveObserver = scene.onPrePointerObservable.add((pi, state) => {
-            if (scene!.isPointerCaptured((<PointerEvent>(pi.event)).pointerId)) {
+            if (scene!.isPointerCaptured((<IPointerEvent>(pi.event)).pointerId)) {
                 return;
                 return;
             }
             }
             if (pi.type !== PointerEventTypes.POINTERMOVE
             if (pi.type !== PointerEventTypes.POINTERMOVE
@@ -724,8 +725,8 @@ export class AdvancedDynamicTexture extends DynamicTexture {
                 return;
                 return;
             }
             }
 
 
-            if (pi.type === PointerEventTypes.POINTERMOVE && (pi.event as PointerEvent).pointerId) {
-                this._defaultMousePointerId = (pi.event as PointerEvent).pointerId; // This is required to make sure we have the correct pointer ID for wheel
+            if (pi.type === PointerEventTypes.POINTERMOVE && (pi.event as IPointerEvent).pointerId) {
+                this._defaultMousePointerId = (pi.event as IPointerEvent).pointerId; // This is required to make sure we have the correct pointer ID for wheel
             }
             }
 
 
             let camera = scene.cameraToUseForPointers || scene.activeCamera;
             let camera = scene.cameraToUseForPointers || scene.activeCamera;
@@ -744,8 +745,8 @@ export class AdvancedDynamicTexture extends DynamicTexture {
             let y = scene.pointerY / engine.getHardwareScalingLevel() - (engine.getRenderHeight() - tempViewport.y - tempViewport.height);
             let y = scene.pointerY / engine.getHardwareScalingLevel() - (engine.getRenderHeight() - tempViewport.y - tempViewport.height);
             this._shouldBlockPointer = false;
             this._shouldBlockPointer = false;
             // Do picking modifies _shouldBlockPointer
             // Do picking modifies _shouldBlockPointer
-            let pointerId = (pi.event as PointerEvent).pointerId || this._defaultMousePointerId;
-            this._doPicking(x, y, pi, pi.type, pointerId, pi.event.button, (<MouseWheelEvent>pi.event).deltaX, (<MouseWheelEvent>pi.event).deltaY);
+            let pointerId = (pi.event as IPointerEvent).pointerId || this._defaultMousePointerId;
+            this._doPicking(x, y, pi, pi.type, pointerId, pi.event.button, (<IWheelEvent>pi.event).deltaX, (<IWheelEvent>pi.event).deltaY);
             // Avoid overwriting a true skipOnPointerObservable to false
             // Avoid overwriting a true skipOnPointerObservable to false
             if (this._shouldBlockPointer) {
             if (this._shouldBlockPointer) {
                 pi.skipOnPointerObservable = this._shouldBlockPointer;
                 pi.skipOnPointerObservable = this._shouldBlockPointer;
@@ -808,7 +809,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
                 return;
                 return;
             }
             }
 
 
-            var pointerId = (pi.event as PointerEvent).pointerId || this._defaultMousePointerId;
+            var pointerId = (pi.event as IPointerEvent).pointerId || this._defaultMousePointerId;
             if (pi.pickInfo && pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
             if (pi.pickInfo && pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
                 var uv = pi.pickInfo.getTextureCoordinates();
                 var uv = pi.pickInfo.getTextureCoordinates();
                 if (uv) {
                 if (uv) {

+ 3 - 2
gui/src/2D/controls/focusableButton.ts

@@ -7,6 +7,7 @@ import { _TypeStore } from 'babylonjs/Misc/typeStore';
 import { PointerInfoBase } from 'babylonjs/Events/pointerEvents';
 import { PointerInfoBase } from 'babylonjs/Events/pointerEvents';
 import { IFocusableControl } from "./focusableControl";
 import { IFocusableControl } from "./focusableControl";
 import { Observable } from 'babylonjs/Misc/observable';
 import { Observable } from 'babylonjs/Misc/observable';
+import { IKeyboardEvent } from "babylonjs/Events/deviceInputEvents";
 
 
 /**
 /**
  * Class used to create a focusable button that can easily handle keyboard events
  * Class used to create a focusable button that can easily handle keyboard events
@@ -22,7 +23,7 @@ export class FocusableButton extends Button implements IFocusableControl {
     /** Observable raised when the control loses the focus */
     /** Observable raised when the control loses the focus */
     public onBlurObservable = new Observable<Button>();
     public onBlurObservable = new Observable<Button>();
     /** Observable raised when a key event was processed */
     /** Observable raised when a key event was processed */
-    public onKeyboardEventProcessedObservable = new Observable<KeyboardEvent>();
+    public onKeyboardEventProcessedObservable = new Observable<IKeyboardEvent>();
 
 
     constructor(public name?: string) {
     constructor(public name?: string) {
         super(name);
         super(name);
@@ -80,7 +81,7 @@ export class FocusableButton extends Button implements IFocusableControl {
      * Handles the keyboard event
      * Handles the keyboard event
      * @param evt Defines the KeyboardEvent
      * @param evt Defines the KeyboardEvent
      */
      */
-    public processKeyboard(evt: KeyboardEvent): void {
+    public processKeyboard(evt: IKeyboardEvent): void {
         this.onKeyboardEventProcessedObservable.notifyObservers(evt, -1, this);
         this.onKeyboardEventProcessedObservable.notifyObservers(evt, -1, this);
     }
     }
 
 

+ 2 - 1
gui/src/2D/controls/focusableControl.ts

@@ -1,3 +1,4 @@
+import { IKeyboardEvent } from "babylonjs/Events/deviceInputEvents";
 import { Nullable } from "babylonjs/types";
 import { Nullable } from "babylonjs/types";
 import { Control } from "./control";
 import { Control } from "./control";
 
 
@@ -17,7 +18,7 @@ export interface IFocusableControl {
      * Function called to let the control handle keyboard events
      * Function called to let the control handle keyboard events
      * @param evt defines the current keyboard event
      * @param evt defines the current keyboard event
      */
      */
-    processKeyboard(evt: KeyboardEvent): void;
+    processKeyboard(evt: IKeyboardEvent): void;
     /**
     /**
     * Function called to get the list of controls that should not steal the focus from this control
     * Function called to get the list of controls that should not steal the focus from this control
     * @returns an array of controls
     * @returns an array of controls

+ 4 - 3
gui/src/2D/controls/inputText.ts

@@ -12,6 +12,7 @@ import { _TypeStore } from 'babylonjs/Misc/typeStore';
 import { Measure } from '../measure';
 import { Measure } from '../measure';
 import { TextWrapper } from './textWrapper';
 import { TextWrapper } from './textWrapper';
 import { serialize } from 'babylonjs/Misc/decorators';
 import { serialize } from 'babylonjs/Misc/decorators';
+import { IKeyboardEvent } from 'babylonjs/Events/deviceInputEvents';
 
 
 /**
 /**
  * Class used to create input text control
  * Class used to create input text control
@@ -76,7 +77,7 @@ export class InputText extends Control implements IFocusableControl {
     /** Observable raised when paste event is triggered */
     /** Observable raised when paste event is triggered */
     public onTextPasteObservable = new Observable<InputText>();
     public onTextPasteObservable = new Observable<InputText>();
     /** Observable raised when a key event was processed */
     /** Observable raised when a key event was processed */
-    public onKeyboardEventProcessedObservable = new Observable<KeyboardEvent>();
+    public onKeyboardEventProcessedObservable = new Observable<IKeyboardEvent>();
 
 
     /** Gets or sets the maximum width allowed by the control */
     /** Gets or sets the maximum width allowed by the control */
     @serialize()
     @serialize()
@@ -474,7 +475,7 @@ export class InputText extends Control implements IFocusableControl {
     }
     }
 
 
     /** @hidden */
     /** @hidden */
-    public processKey(keyCode: number, key?: string, evt?: KeyboardEvent) {
+    public processKey(keyCode: number, key?: string, evt?: IKeyboardEvent) {
 
 
         //return if clipboard event keys (i.e -ctr/cmd + c,v,x)
         //return if clipboard event keys (i.e -ctr/cmd + c,v,x)
         if (evt && (evt.ctrlKey || evt.metaKey) && (keyCode === 67 || keyCode === 86 || keyCode === 88)) {
         if (evt && (evt.ctrlKey || evt.metaKey) && (keyCode === 67 || keyCode === 86 || keyCode === 88)) {
@@ -792,7 +793,7 @@ export class InputText extends Control implements IFocusableControl {
      * Handles the keyboard event
      * Handles the keyboard event
      * @param evt Defines the KeyboardEvent
      * @param evt Defines the KeyboardEvent
      */
      */
-    public processKeyboard(evt: KeyboardEvent): void {
+    public processKeyboard(evt: IKeyboardEvent): void {
         // process pressed key
         // process pressed key
         this.processKey(evt.keyCode, evt.key, evt);
         this.processKey(evt.keyCode, evt.key, evt);
 
 

+ 20 - 12
gui/src/3D/controls/control3D.ts

@@ -20,7 +20,7 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
     private _node: Nullable<TransformNode>;
     private _node: Nullable<TransformNode>;
     private _downCount = 0;
     private _downCount = 0;
     private _enterCount = -1;
     private _enterCount = -1;
-    private _downPointerIds: { [id: number]: boolean } = {};
+    private _downPointerIds: { [id: number]: number } = {}; // Store number of pointer downs per ID, from near and far interactions
     private _isVisible = true;
     private _isVisible = true;
 
 
     /** Gets or sets the control position  in world space */
     /** Gets or sets the control position  in world space */
@@ -306,16 +306,16 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
 
 
     /** @hidden */
     /** @hidden */
     public _onPointerEnter(target: Control3D): boolean {
     public _onPointerEnter(target: Control3D): boolean {
-        if (this._enterCount > 0) {
-            return false;
-        }
-
         if (this._enterCount === -1) { // -1 is for touch input, we are now sure we are with a mouse or pencil
         if (this._enterCount === -1) { // -1 is for touch input, we are now sure we are with a mouse or pencil
             this._enterCount = 0;
             this._enterCount = 0;
         }
         }
 
 
         this._enterCount++;
         this._enterCount++;
 
 
+        if (this._enterCount > 1) {
+            return false;
+        }
+
         this.onPointerEnterObservable.notifyObservers(this, -1, target, this);
         this.onPointerEnterObservable.notifyObservers(this, -1, target, this);
 
 
         if (this.pointerEnterAnimation) {
         if (this.pointerEnterAnimation) {
@@ -327,6 +327,12 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
 
 
     /** @hidden */
     /** @hidden */
     public _onPointerOut(target: Control3D): void {
     public _onPointerOut(target: Control3D): void {
+        this._enterCount--;
+
+        if (this._enterCount > 0) {
+            return;
+        }
+
         this._enterCount = 0;
         this._enterCount = 0;
 
 
         this.onPointerOutObservable.notifyObservers(this, -1, target, this);
         this.onPointerOutObservable.notifyObservers(this, -1, target, this);
@@ -338,14 +344,12 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
 
 
     /** @hidden */
     /** @hidden */
     public _onPointerDown(target: Control3D, coordinates: Vector3, pointerId: number, buttonIndex: number): boolean {
     public _onPointerDown(target: Control3D, coordinates: Vector3, pointerId: number, buttonIndex: number): boolean {
-        if (this._downCount !== 0) {
-            this._downCount++;
-            return false;
-        }
-
         this._downCount++;
         this._downCount++;
+        this._downPointerIds[pointerId] = this._downPointerIds[pointerId] + 1 || 1;
 
 
-        this._downPointerIds[pointerId] = true;
+        if (this._downCount !== 1) {
+            return false;
+        }
 
 
         this.onPointerDownObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
         this.onPointerDownObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
 
 
@@ -359,7 +363,11 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
     /** @hidden */
     /** @hidden */
     public _onPointerUp(target: Control3D, coordinates: Vector3, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
     public _onPointerUp(target: Control3D, coordinates: Vector3, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
         this._downCount--;
         this._downCount--;
-        delete this._downPointerIds[pointerId];
+        this._downPointerIds[pointerId]--;
+
+        if (this._downPointerIds[pointerId] <= 0) {
+            delete this._downPointerIds[pointerId];
+        }
 
 
         if (this._downCount < 0) {
         if (this._downCount < 0) {
             // Handle if forcePointerUp was called prior to this
             // Handle if forcePointerUp was called prior to this

+ 3 - 0
gui/src/3D/controls/index.ts

@@ -9,4 +9,7 @@ export * from "./planePanel";
 export * from "./scatterPanel";
 export * from "./scatterPanel";
 export * from "./spherePanel";
 export * from "./spherePanel";
 export * from "./stackPanel3D";
 export * from "./stackPanel3D";
+export * from "./touchButton3D";
+export * from "./touchMeshButton3D";
+export * from "./touchHolographicButton";
 export * from "./volumeBasedPanel";
 export * from "./volumeBasedPanel";

+ 367 - 0
gui/src/3D/controls/touchButton3D.ts

@@ -0,0 +1,367 @@
+// Assumptions: absolute position of button mesh is inside the mesh
+
+import { DeepImmutableObject } from "babylonjs/types";
+import { Vector3, Quaternion } from "babylonjs/Maths/math.vector";
+import { Mesh } from "babylonjs/Meshes/mesh";
+import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+import { TransformNode } from "babylonjs/Meshes/transformNode";
+import { Scene } from "babylonjs/scene";
+import { Ray } from "babylonjs/Culling/ray";
+
+import { Button3D } from "./button3D";
+
+/**
+ * Enum for Button States
+ */
+enum ButtonState {
+    /** None */
+    None = 0,
+    /** Pointer Entered */
+    Hover = 1,
+    /** Pointer Down */
+    Press = 2
+}
+
+/**
+ * Class used to create a touchable button in 3D
+ */
+export class TouchButton3D extends Button3D {
+    private _collisionMesh: Mesh;
+    private _collidableFrontDirection: Vector3;
+    private _lastTouchPoint: Vector3;
+    private _tempButtonForwardRay: Ray;
+    private _lastKnownCollidableScale: Vector3;
+
+    private _collidableInitialized = false;
+
+    private _frontOffset = 0;
+    private _backOffset = 0;
+    private _hoverOffset = 0;
+    private _pushThroughBackOffset = 0;
+
+    private _activeInteractions = new Map<number, ButtonState>();
+    private _previousHeight = new Map<number, number>();
+
+    /**
+     * Creates a new touchable button
+     * @param name defines the control name
+     * @param collisionMesh mesh to track collisions with
+     */
+    constructor(name?: string, collisionMesh?: Mesh) {
+        super(name);
+
+        this._tempButtonForwardRay = new Ray(Vector3.Zero(), Vector3.Zero());
+
+        if (collisionMesh) {
+            this.collisionMesh = collisionMesh;
+        }
+    }
+
+    /**
+     * Sets the front-facing direction of the button
+     * @param frontDir the forward direction of the button
+     */
+    public set collidableFrontDirection(frontWorldDir: Vector3) {
+        this._collidableFrontDirection = frontWorldDir.normalize();
+
+        // Zero out the scale to force it to be proplerly updated in _updateDistanceOffsets
+        this._lastKnownCollidableScale = Vector3.Zero();
+
+        this._updateDistanceOffsets();
+    }
+
+    private _getWorldMatrixData(mesh: Mesh) {
+        let translation = Vector3.Zero();
+        let rotation = Quaternion.Identity();
+        let scale = Vector3.Zero();
+
+        mesh.getWorldMatrix().decompose(scale, rotation, translation);
+
+        return {translation: translation, rotation: rotation, scale: scale};
+    }
+
+    /**
+     * Sets the mesh used for testing input collision
+     * @param collisionMesh the new collision mesh for the button
+     */
+    public set collisionMesh(collisionMesh: Mesh) {
+        if (this._collisionMesh) {
+            this._collisionMesh.dispose();
+        }
+
+        // parent the mesh to sync transforms
+        if (!collisionMesh.parent && this.mesh) {
+            collisionMesh.setParent(this.mesh);
+        }
+
+        this._collisionMesh = collisionMesh;
+        this._collisionMesh.metadata = this;
+
+        this.collidableFrontDirection = collisionMesh.forward;
+
+        this._collidableInitialized = true;
+    }
+
+    /*
+     * Given a point, and two points on a line, this returns the distance between
+     * the point and the closest point on the line. The closest point on the line
+     * does not have to be between the two given points.
+     *
+     * Based off the 3D point-line distance equation
+     *
+     * Assumes lineDirection is normalized
+     */
+    private _getShortestDistancePointToLine(point: Vector3, linePoint: Vector3, lineDirection: Vector3) {
+        const pointToLine = linePoint.subtract(point);
+        const cross = lineDirection.cross(pointToLine);
+
+        return cross.length();
+    }
+
+    /*
+     * Checks to see if collidable is in a position to interact with the button
+     *   - check if collidable has a plane height off the button that is within range
+     *   - check that collidable + normal ray intersect the bounding sphere
+     */
+    private _isPrimedForInteraction(collidable: Vector3): boolean {
+        // Check if the collidable has an appropriate planar height
+        const heightFromCenter = this._getHeightFromButtonCenter(collidable);
+
+        if (heightFromCenter > this._hoverOffset || heightFromCenter < this._pushThroughBackOffset) {
+            return false;
+        }
+
+        // Check if the collidable or its hover ray lands within the bounding sphere of the button
+        const distanceFromCenter = this._getShortestDistancePointToLine(this._collisionMesh.getAbsolutePosition(),
+                                                                        collidable,
+                                                                        this._collidableFrontDirection);
+        return distanceFromCenter <= this._collisionMesh.getBoundingInfo().boundingSphere.radiusWorld;
+    }
+
+    /*
+     * Returns a Vector3 of the collidable's projected position on the button
+     * Returns the collidable's position if it is inside the button
+     */
+    private _getPointOnButton(collidable: Vector3): Vector3 {
+        const heightFromCenter = this._getHeightFromButtonCenter(collidable);
+
+        if (heightFromCenter <= this._frontOffset && heightFromCenter >= this._backOffset) {
+            // The collidable is in the button, return its position
+            return collidable;
+        }
+        else if (heightFromCenter > this._frontOffset) {
+            // The collidable is in front of the button, project it to the surface
+            const collidableDistanceToFront = (this._frontOffset - heightFromCenter);
+            return collidable.add(this._collidableFrontDirection.scale(collidableDistanceToFront));
+        }
+        else {
+            // The collidable is behind the button, project it to its back
+            const collidableDistanceToBack = (this._backOffset - heightFromCenter);
+            return collidable.add(this._collidableFrontDirection.scale(collidableDistanceToBack));
+        }
+    }
+
+    /*
+     * Updates the distance values.
+     * Should be called when the front direction changes, or the mesh size changes
+     *
+     * Sets the following values:
+     *    _frontOffset
+     *    _backOffset
+     *    _hoverOffset
+     *    _pushThroughBackOffset
+     *
+     * Requires population of:
+     *    _collisionMesh
+     *    _collidableFrontDirection
+     */
+    private _updateDistanceOffsets() {
+        let worldMatrixData = this._getWorldMatrixData(this._collisionMesh);
+
+        if (!worldMatrixData.scale.equalsWithEpsilon(this._lastKnownCollidableScale)) {
+            const collisionMeshPos = this._collisionMesh.getAbsolutePosition();
+
+            this._tempButtonForwardRay.origin = collisionMeshPos;
+            this._tempButtonForwardRay.direction = this._collidableFrontDirection;
+
+            const frontPickingInfo = this._tempButtonForwardRay.intersectsMesh(this._collisionMesh as DeepImmutableObject<AbstractMesh>);
+            this._tempButtonForwardRay.direction = this._tempButtonForwardRay.direction.negate();
+            const backPickingInfo = this._tempButtonForwardRay.intersectsMesh(this._collisionMesh as DeepImmutableObject<AbstractMesh>);
+
+            this._frontOffset = 0;
+            this._backOffset = 0;
+
+            if (frontPickingInfo.hit && backPickingInfo.hit) {
+                this._frontOffset = this._getDistanceOffPlane(frontPickingInfo.pickedPoint!,
+                                                                  this._collidableFrontDirection,
+                                                                  collisionMeshPos);
+                this._backOffset = this._getDistanceOffPlane(backPickingInfo.pickedPoint!,
+                                                                 this._collidableFrontDirection,
+                                                                 collisionMeshPos);
+            }
+
+            // For now, set the hover height equal to the thickness of the button
+            const buttonThickness = this._frontOffset - this._backOffset;
+
+            this._hoverOffset = this._frontOffset + (buttonThickness * 1.25);
+            this._pushThroughBackOffset = this._backOffset - (buttonThickness * 1.5);
+
+            this._lastKnownCollidableScale = this._getWorldMatrixData(this._collisionMesh).scale;
+        }
+    }
+
+    // Returns the distance in front of the center of the button
+    // Returned value is negative when collidable is past the center
+    private _getHeightFromButtonCenter(collidablePos: Vector3) {
+        return this._getDistanceOffPlane(collidablePos, this._collidableFrontDirection, this._collisionMesh.getAbsolutePosition());
+    }
+
+    // Returns the distance from pointOnPlane to point along planeNormal
+    private _getDistanceOffPlane(point: Vector3, planeNormal: Vector3, pointOnPlane: Vector3) {
+        const d = Vector3.Dot(pointOnPlane, planeNormal);
+        const abc = Vector3.Dot(point, planeNormal);
+
+        return abc - d;
+    }
+
+    // Updates the stored state of the button, and fire pointer events
+    private _updateButtonState(id: number, newState: ButtonState, pointOnButton: Vector3) {
+        const dummyPointerId = 0;
+        const buttonIndex = 0; // Left click
+        const buttonStateForId = this._activeInteractions.get(id) || ButtonState.None;
+
+        // Take into account all inputs interacting with the button to avoid state flickering
+        let previousPushDepth = 0;
+        this._activeInteractions.forEach(function(value, key) {
+            previousPushDepth = Math.max(previousPushDepth, value);
+        });
+
+        if (buttonStateForId != newState) {
+            if (newState == ButtonState.None) {
+                this._activeInteractions.delete(id);
+            }
+            else {
+                this._activeInteractions.set(id, newState);
+            }
+        }
+
+        let newPushDepth = 0;
+        this._activeInteractions.forEach(function(value, key) {
+            newPushDepth = Math.max(newPushDepth, value);
+        });
+
+        if (newPushDepth == ButtonState.Press) {
+            if (previousPushDepth == ButtonState.Hover) {
+                this._onPointerDown(this, pointOnButton, dummyPointerId, buttonIndex);
+            }
+            else if (previousPushDepth == ButtonState.Press) {
+                this._onPointerMove(this, pointOnButton);
+            }
+        }
+        else if (newPushDepth == ButtonState.Hover) {
+            if (previousPushDepth == ButtonState.None) {
+                this._onPointerEnter(this);
+            }
+            else if (previousPushDepth == ButtonState.Press) {
+                this._onPointerUp(this, pointOnButton, dummyPointerId, buttonIndex, false);
+            }
+            else {
+                this._onPointerMove(this, pointOnButton);
+            }
+        }
+        else if (newPushDepth == ButtonState.None) {
+            if (previousPushDepth == ButtonState.Hover) {
+                this._onPointerOut(this);
+            }
+            else if (previousPushDepth == ButtonState.Press) {
+                this._onPointerUp(this, pointOnButton, dummyPointerId, buttonIndex, false);
+                this._onPointerOut(this);
+            }
+        }
+    }
+
+    // Decides whether to change button state based on the planar depth of the input source
+    /** @hidden */
+    public _collisionCheckForStateChange(mesh: AbstractMesh) {
+        if (this._collidableInitialized) {
+            this._updateDistanceOffsets();
+
+            const collidablePosition = mesh.getAbsolutePosition();
+            const inRange = this._isPrimedForInteraction(collidablePosition);
+
+            const uniqueId = mesh.uniqueId;
+
+            let activeInteraction = this._activeInteractions.get(uniqueId);
+            if (inRange) {
+                const pointOnButton = this._getPointOnButton(collidablePosition);
+                const heightFromCenter = this._getHeightFromButtonCenter(collidablePosition);
+                const flickerDelta = 0.003;
+
+                this._lastTouchPoint = pointOnButton;
+
+                const isGreater = function (compareHeight: number) {
+                    return heightFromCenter >= (compareHeight + flickerDelta);
+                };
+
+                const isLower = function (compareHeight: number) {
+                    return heightFromCenter <= (compareHeight - flickerDelta);
+                };
+
+                // Update button state and fire events
+                switch (activeInteraction || ButtonState.None) {
+                    case ButtonState.None:
+                        if (isGreater(this._frontOffset) &&
+                            isLower(this._hoverOffset)) {
+                            this._updateButtonState(uniqueId, ButtonState.Hover, pointOnButton);
+                        }
+
+                        break;
+                    case ButtonState.Hover:
+                        if (isGreater(this._hoverOffset)) {
+                            this._updateButtonState(uniqueId, ButtonState.None, pointOnButton);
+                        }
+                        else if (isLower(this._frontOffset)) {
+                            this._updateButtonState(uniqueId, ButtonState.Press, pointOnButton);
+                        }
+
+                        break;
+                    case ButtonState.Press:
+                        if (isGreater(this._frontOffset)) {
+                            this._updateButtonState(uniqueId, ButtonState.Hover, pointOnButton);
+                        }
+                        else if (isLower(this._pushThroughBackOffset)) {
+                            this._updateButtonState(uniqueId, ButtonState.None, pointOnButton);
+                        }
+
+                        break;
+                }
+
+                this._previousHeight.set(uniqueId, heightFromCenter);
+            }
+            else if ((activeInteraction != undefined) && (activeInteraction != ButtonState.None)) {
+                this._updateButtonState(uniqueId, ButtonState.None, this._lastTouchPoint);
+                this._previousHeight.delete(uniqueId);
+            }
+        }
+    }
+
+    protected _getTypeName(): string {
+        return "TouchButton3D";
+    }
+
+    // Mesh association
+    protected _createNode(scene: Scene): TransformNode {
+        return super._createNode(scene);
+    }
+
+    /**
+     * Releases all associated resources
+     */
+    public dispose() {
+        super.dispose();
+
+        if (this._collisionMesh) {
+            this._collisionMesh.dispose();
+        }
+    }
+}

+ 364 - 0
gui/src/3D/controls/touchHolographicButton.ts

@@ -0,0 +1,364 @@
+import { Nullable } from "babylonjs/types";
+import { Observer } from "babylonjs/Misc/observable";
+import { Vector3 } from "babylonjs/Maths/math.vector";
+import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
+import { TransformNode } from "babylonjs/Meshes/transformNode";
+import { Mesh } from "babylonjs/Meshes/mesh";
+import { PlaneBuilder } from "babylonjs/Meshes/Builders/planeBuilder";
+import { BoxBuilder } from "babylonjs/Meshes/Builders/boxBuilder";
+import { FadeInOutBehavior } from "babylonjs/Behaviors/Meshes/fadeInOutBehavior";
+import { Scene } from "babylonjs/scene";
+
+import { FluentMaterial } from "../materials/fluentMaterial";
+import { StackPanel } from "../../2D/controls/stackPanel";
+import { Image } from "../../2D/controls/image";
+import { TextBlock } from "../../2D/controls/textBlock";
+import { AdvancedDynamicTexture } from "../../2D/advancedDynamicTexture";
+import { Control3D } from "./control3D";
+import { Color3 } from 'babylonjs/Maths/math.color';
+
+import { TouchButton3D } from "./touchButton3D";
+
+/**
+ * Class used to create a holographic button in 3D
+ */
+export class TouchHolographicButton extends TouchButton3D {
+    private _backPlate: Mesh;
+    private _textPlate: Mesh;
+    private _frontPlate: Mesh;
+    private _text: string;
+    private _imageUrl: string;
+    private _shareMaterials = true;
+    private _frontMaterial: FluentMaterial;
+    private _backMaterial: FluentMaterial;
+    private _plateMaterial: StandardMaterial;
+    private _pickedPointObserver: Nullable<Observer<Nullable<Vector3>>>;
+
+    // Tooltip
+    private _tooltipFade: Nullable<FadeInOutBehavior>;
+    private _tooltipTextBlock: Nullable<TextBlock>;
+    private _tooltipTexture: Nullable<AdvancedDynamicTexture>;
+    private _tooltipMesh: Nullable<Mesh>;
+    private _tooltipHoverObserver: Nullable<Observer<Control3D>>;
+    private _tooltipOutObserver: Nullable<Observer<Control3D>>;
+
+    private _disposeTooltip() {
+        this._tooltipFade = null;
+        if (this._tooltipTextBlock) {
+            this._tooltipTextBlock.dispose();
+        }
+        if (this._tooltipTexture) {
+            this._tooltipTexture.dispose();
+        }
+        if (this._tooltipMesh) {
+            this._tooltipMesh.dispose();
+        }
+        this.onPointerEnterObservable.remove(this._tooltipHoverObserver);
+        this.onPointerOutObservable.remove(this._tooltipOutObserver);
+    }
+
+    /**
+     * Rendering ground id of all the mesh in the button
+     */
+    public set renderingGroupId(id: number) {
+        this._backPlate.renderingGroupId = id;
+        this._textPlate.renderingGroupId = id;
+        this._frontPlate.renderingGroupId = id;
+
+        if (this._tooltipMesh) {
+            this._tooltipMesh.renderingGroupId = id;
+        }
+    }
+    public get renderingGroupId(): number {
+        return this._backPlate.renderingGroupId;
+    }
+
+    /**
+     * Text to be displayed on the tooltip shown when hovering on the button. When set to null tooltip is disabled. (Default: null)
+     */
+    public set tooltipText(text: Nullable<string>) {
+        if (!text) {
+            this._disposeTooltip();
+            return;
+        }
+        if (!this._tooltipFade) {
+            // Create tooltip with mesh and text
+            this._tooltipMesh = PlaneBuilder.CreatePlane("", { size: 1 }, this._backPlate._scene);
+            var tooltipBackground = PlaneBuilder.CreatePlane("", { size: 1, sideOrientation: Mesh.DOUBLESIDE }, this._backPlate._scene);
+            var mat = new StandardMaterial("", this._backPlate._scene);
+            mat.diffuseColor = Color3.FromHexString("#212121");
+            tooltipBackground.material = mat;
+            tooltipBackground.isPickable = false;
+            this._tooltipMesh.addChild(tooltipBackground);
+            tooltipBackground.position.z = 0.05;
+            this._tooltipMesh.scaling.y = 1 / 3;
+            this._tooltipMesh.position.y = 0.7;
+            this._tooltipMesh.position.z = -0.15;
+            this._tooltipMesh.isPickable = false;
+            this._tooltipMesh.parent = this._backPlate;
+
+            // Create text texture for the tooltip
+            this._tooltipTexture = AdvancedDynamicTexture.CreateForMesh(this._tooltipMesh);
+            this._tooltipTextBlock = new TextBlock();
+            this._tooltipTextBlock.scaleY = 3;
+            this._tooltipTextBlock.color = "white";
+            this._tooltipTextBlock.fontSize = 130;
+            this._tooltipTexture.addControl(this._tooltipTextBlock);
+
+            // Add hover action to tooltip
+            this._tooltipFade = new FadeInOutBehavior();
+            this._tooltipFade.delay = 500;
+            this._tooltipMesh.addBehavior(this._tooltipFade);
+            this._tooltipHoverObserver = this.onPointerEnterObservable.add(() => {
+                if (this._tooltipFade) {
+                    this._tooltipFade.fadeIn(true);
+                }
+            });
+            this._tooltipOutObserver = this.onPointerOutObservable.add(() => {
+                if (this._tooltipFade) {
+                    this._tooltipFade.fadeIn(false);
+                }
+            });
+        }
+        if (this._tooltipTextBlock) {
+            this._tooltipTextBlock.text = text;
+        }
+    }
+
+    public get tooltipText() {
+        if (this._tooltipTextBlock) {
+            return this._tooltipTextBlock.text;
+        }
+        return null;
+    }
+
+    /**
+     * Gets or sets text for the button
+     */
+    public get text(): string {
+        return this._text;
+    }
+
+    public set text(value: string) {
+        if (this._text === value) {
+            return;
+        }
+
+        this._text = value;
+        this._rebuildContent();
+    }
+
+    /**
+     * Gets or sets the image url for the button
+     */
+    public get imageUrl(): string {
+        return this._imageUrl;
+    }
+
+    public set imageUrl(value: string) {
+        if (this._imageUrl === value) {
+            return;
+        }
+
+        this._imageUrl = value;
+        this._rebuildContent();
+    }
+
+    /**
+     * Gets the back material used by this button
+     */
+    public get backMaterial(): FluentMaterial {
+        return this._backMaterial;
+    }
+
+    /**
+     * Gets the front material used by this button
+     */
+    public get frontMaterial(): FluentMaterial {
+        return this._frontMaterial;
+    }
+
+    /**
+     * Gets the plate material used by this button
+     */
+    public get plateMaterial(): StandardMaterial {
+        return this._plateMaterial;
+    }
+
+    /**
+     * Gets a boolean indicating if this button shares its material with other HolographicButtons
+     */
+    public get shareMaterials(): boolean {
+        return this._shareMaterials;
+    }
+
+    /**
+     * Creates a new button
+     * @param name defines the control name
+     */
+    constructor(name?: string, shareMaterials = true) {
+        super(name);
+
+        this._shareMaterials = shareMaterials;
+
+        // Default animations
+        this.pointerEnterAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
+            this._frontPlate.setEnabled(true);
+        };
+
+        this.pointerOutAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
+            this._frontPlate.setEnabled(false);
+        };
+    }
+
+    protected _getTypeName(): string {
+        return "TouchHolographicButton";
+    }
+
+    private _rebuildContent(): void {
+        this._disposeFacadeTexture();
+
+        let panel = new StackPanel();
+        panel.isVertical = true;
+
+        if (this._imageUrl) {
+            let image = new Image();
+            image.source = this._imageUrl;
+            image.paddingTop = "40px";
+            image.height = "180px";
+            image.width = "100px";
+            image.paddingBottom = "40px";
+            panel.addControl(image);
+        }
+
+        if (this._text) {
+            let text = new TextBlock();
+            text.text = this._text;
+            text.color = "white";
+            text.height = "30px";
+            text.fontSize = 24;
+            panel.addControl(text);
+        }
+
+        if (this._frontPlate) {
+            this.content = panel;
+        }
+    }
+
+    // Mesh association
+    protected _createNode(scene: Scene): TransformNode {
+        this._backPlate = BoxBuilder.CreateBox(this.name + "BackMesh", {
+            width: 1.0,
+            height: 1.0,
+            depth: 0.08
+        }, scene);
+
+        this._frontPlate = BoxBuilder.CreateBox(this.name + "FrontMesh", {
+            width: 1.0,
+            height: 1.0,
+            depth: 0.4
+        }, scene);
+
+        this._frontPlate.parent = this._backPlate;
+        this._frontPlate.position.z = -0.08;
+        this._frontPlate.isPickable = false;
+        this._frontPlate.setEnabled(false);
+
+        this._textPlate = <Mesh>super._createNode(scene);
+        this._textPlate.parent = this._backPlate;
+        this._textPlate.position.z = -0.08;
+        this._textPlate.isPickable = false;
+
+        this.collisionMesh = this._frontPlate;
+        this.collidableFrontDirection = this._frontPlate.forward.negate(); // Mesh is facing the wrong way
+
+        return this._backPlate;
+    }
+
+    protected _applyFacade(facadeTexture: AdvancedDynamicTexture) {
+        this._plateMaterial.emissiveTexture = facadeTexture;
+        this._plateMaterial.opacityTexture = facadeTexture;
+    }
+
+    private _createBackMaterial(mesh: Mesh) {
+        this._backMaterial = new FluentMaterial(this.name + "Back Material", mesh.getScene());
+        this._backMaterial.renderHoverLight = true;
+        this._backMaterial.albedoColor = new Color3(0.1, 0.1, 0.4);
+        this._pickedPointObserver = this._host.onPickedPointChangedObservable.add((pickedPoint) => {
+            if (pickedPoint) {
+                this._backMaterial.hoverPosition = pickedPoint;
+                this._backMaterial.hoverColor.a = 1.0;
+            } else {
+                this._backMaterial.hoverColor.a = 0;
+            }
+        });
+    }
+
+    private _createFrontMaterial(mesh: Mesh) {
+        this._frontMaterial = new FluentMaterial(this.name + "Front Material", mesh.getScene());
+        this._frontMaterial.innerGlowColorIntensity = 0; // No inner glow
+        this._frontMaterial.alpha = 0.3; // Additive
+        this._frontMaterial.renderBorders = false;
+    }
+
+    private _createPlateMaterial(mesh: Mesh) {
+        this._plateMaterial = new StandardMaterial(this.name + "Plate Material", mesh.getScene());
+        this._plateMaterial.specularColor = Color3.Black();
+    }
+
+    protected _affectMaterial(mesh: Mesh) {
+        // Back
+        if (this._shareMaterials) {
+            if (!this._host._touchSharedMaterials["backFluentMaterial"]) {
+                this._createBackMaterial(mesh);
+                this._host._touchSharedMaterials["backFluentMaterial"] = this._backMaterial;
+            } else {
+                this._backMaterial = this._host._touchSharedMaterials["backFluentMaterial"] as FluentMaterial;
+            }
+
+            // Front
+            if (!this._host._touchSharedMaterials["frontFluentMaterial"]) {
+                this._createFrontMaterial(mesh);
+                this._host._touchSharedMaterials["frontFluentMaterial"] = this._frontMaterial;
+            } else {
+                this._frontMaterial = this._host._touchSharedMaterials["frontFluentMaterial"] as FluentMaterial;
+            }
+        } else {
+            this._createBackMaterial(mesh);
+            this._createFrontMaterial(mesh);
+        }
+
+        this._createPlateMaterial(mesh);
+        this._backPlate.material = this._backMaterial;
+        this._frontPlate.material = this._frontMaterial;
+        this._textPlate.material = this._plateMaterial;
+
+        this._rebuildContent();
+    }
+
+    /**
+     * Releases all associated resources
+     */
+    public dispose() {
+        super.dispose(); // will dispose main mesh ie. back plate
+
+        this._disposeTooltip();
+
+        if (!this.shareMaterials) {
+            this._backMaterial.dispose();
+            this._frontMaterial.dispose();
+            this._plateMaterial.dispose();
+
+            if (this._pickedPointObserver) {
+                this._host.onPickedPointChangedObservable.remove(this._pickedPointObserver);
+                this._pickedPointObserver = null;
+            }
+        }
+    }
+}

+ 81 - 0
gui/src/3D/controls/touchMeshButton3D.ts

@@ -0,0 +1,81 @@
+import { TransformNode } from "babylonjs/Meshes/transformNode";
+import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+import { Mesh } from "babylonjs/Meshes/mesh";
+import { Scene } from "babylonjs/scene";
+
+import { TouchButton3D } from "./touchButton3D";
+
+/**
+ * Class used to create an interactable object. It's a touchable 3D button using a mesh coming from the current scene
+ */
+export class TouchMeshButton3D extends TouchButton3D {
+    /** @hidden */
+    protected _currentMesh: Mesh;
+
+    /**
+     * Creates a new 3D button based on a mesh
+     * @param mesh mesh to become a 3D button
+     * @param collisionMesh mesh to track collisions with
+     * @param name defines the control name
+     */
+    constructor(mesh: Mesh, options: {collisionMesh: Mesh, useDynamicMesh?: boolean}, name?: string) {
+        if (options.useDynamicMesh) {
+            super(name, options.collisionMesh);
+        }
+        else {
+            let newCollisionMesh = options.collisionMesh.clone("", options.collisionMesh.parent);
+            newCollisionMesh.isVisible = false;
+            super(name, newCollisionMesh);
+        }
+
+        this._currentMesh = mesh;
+
+        /**
+         * Provides a default behavior on hover/out & up/down
+         * Override those function to create your own desired behavior specific to your mesh
+         */
+        this.pointerEnterAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
+            this.mesh.scaling.scaleInPlace(1.1);
+        };
+
+        this.pointerOutAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
+            this.mesh.scaling.scaleInPlace(1.0 / 1.1);
+        };
+
+        this.pointerDownAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
+            this.mesh.scaling.scaleInPlace(0.95);
+        };
+
+        this.pointerUpAnimation = () => {
+            if (!this.mesh) {
+                return;
+            }
+            this.mesh.scaling.scaleInPlace(1.0 / 0.95);
+        };
+    }
+
+    protected _getTypeName(): string {
+        return "TouchMeshButton3D";
+    }
+
+    // Mesh association
+    protected _createNode(scene: Scene): TransformNode {
+        this._currentMesh.getChildMeshes().forEach((mesh) => {
+            mesh.metadata = this;
+        });
+
+        return this._currentMesh;
+    }
+
+    protected _affectMaterial(mesh: AbstractMesh) {
+    }
+}

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

@@ -11,6 +11,7 @@ import { IDisposable, Scene } from "babylonjs/scene";
 
 
 import { Container3D } from "./controls/container3D";
 import { Container3D } from "./controls/container3D";
 import { Control3D } from "./controls/control3D";
 import { Control3D } from "./controls/control3D";
+import { TouchButton3D } from "./controls/touchButton3D";
 
 
 /**
 /**
  * Class used to manage 3D user interface
  * Class used to manage 3D user interface
@@ -23,6 +24,7 @@ export class GUI3DManager implements IDisposable {
     private _rootContainer: Container3D;
     private _rootContainer: Container3D;
     private _pointerObserver: Nullable<Observer<PointerInfo>>;
     private _pointerObserver: Nullable<Observer<PointerInfo>>;
     private _pointerOutObserver: Nullable<Observer<number>>;
     private _pointerOutObserver: Nullable<Observer<number>>;
+    private _touchableButtons = new Set<TouchButton3D>();
     /** @hidden */
     /** @hidden */
     public _lastPickedControl: Control3D;
     public _lastPickedControl: Control3D;
     /** @hidden */
     /** @hidden */
@@ -39,6 +41,9 @@ export class GUI3DManager implements IDisposable {
     /** @hidden */
     /** @hidden */
     public _sharedMaterials: { [key: string]: Material } = {};
     public _sharedMaterials: { [key: string]: Material } = {};
 
 
+    /** @hidden */
+    public _touchSharedMaterials:  { [key: string]: Material } = {};
+
     /** Gets the hosting scene */
     /** Gets the hosting scene */
     public get scene(): Scene {
     public get scene(): Scene {
         return this._scene;
         return this._scene;
@@ -151,6 +156,19 @@ export class GUI3DManager implements IDisposable {
         return true;
         return true;
     }
     }
 
 
+    private _processTouchControls = () => {
+        let utilityLayerScene = this._utilityLayer ? this._utilityLayer.utilityLayerScene : null;
+        if (utilityLayerScene) {
+            const touchMeshes = utilityLayerScene.getMeshesByTags("touchEnabled");
+
+            this._touchableButtons.forEach(function (button: TouchButton3D) {
+                touchMeshes.forEach(function (mesh: AbstractMesh) {
+                    button._collisionCheckForStateChange(mesh);
+                });
+            });
+        }
+    }
+
     /**
     /**
      * Gets the root container
      * Gets the root container
      */
      */
@@ -174,6 +192,16 @@ export class GUI3DManager implements IDisposable {
      */
      */
     public addControl(control: Control3D): GUI3DManager {
     public addControl(control: Control3D): GUI3DManager {
         this._rootContainer.addControl(control);
         this._rootContainer.addControl(control);
+
+        let utilityLayerScene = this._utilityLayer ? this._utilityLayer.utilityLayerScene : null;
+        if (utilityLayerScene && (control instanceof TouchButton3D)) {
+            if (this._touchableButtons.size == 0) {
+                utilityLayerScene.registerBeforeRender(this._processTouchControls);
+            }
+
+            this._touchableButtons.add(control as TouchButton3D);
+        }
+
         return this;
         return this;
     }
     }
 
 
@@ -184,6 +212,16 @@ export class GUI3DManager implements IDisposable {
      */
      */
     public removeControl(control: Control3D): GUI3DManager {
     public removeControl(control: Control3D): GUI3DManager {
         this._rootContainer.removeControl(control);
         this._rootContainer.removeControl(control);
+
+        let utilityLayerScene = this._utilityLayer ? this._utilityLayer.utilityLayerScene : null;
+        if (utilityLayerScene && (control instanceof TouchButton3D)) {
+            this._touchableButtons.delete(control);
+
+            if (this._touchableButtons.size == 0) {
+                utilityLayerScene.unregisterBeforeRender(this._processTouchControls);
+            }
+        }
+
         return this;
         return this;
     }
     }
 
 
@@ -203,6 +241,16 @@ export class GUI3DManager implements IDisposable {
 
 
         this._sharedMaterials = {};
         this._sharedMaterials = {};
 
 
+        for (var materialName in this._touchSharedMaterials) {
+            if (!this._touchSharedMaterials.hasOwnProperty(materialName)) {
+                continue;
+            }
+
+            this._touchSharedMaterials[materialName].dispose();
+        }
+
+        this._touchSharedMaterials = {};
+
         if (this._pointerOutObserver && this._utilityLayer) {
         if (this._pointerOutObserver && this._utilityLayer) {
             this._utilityLayer.onPointerOutObservable.remove(this._pointerOutObserver);
             this._utilityLayer.onPointerOutObservable.remove(this._pointerOutObserver);
             this._pointerOutObserver = null;
             this._pointerOutObserver = null;
@@ -213,6 +261,10 @@ export class GUI3DManager implements IDisposable {
         let utilityLayerScene = this._utilityLayer ? this._utilityLayer.utilityLayerScene : null;
         let utilityLayerScene = this._utilityLayer ? this._utilityLayer.utilityLayerScene : null;
 
 
         if (utilityLayerScene) {
         if (utilityLayerScene) {
+            if (this._touchableButtons.size != 0) {
+                utilityLayerScene.unregisterBeforeRender(this._processTouchControls);
+            }
+
             if (this._pointerObserver) {
             if (this._pointerObserver) {
                 utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
                 utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
                 this._pointerObserver = null;
                 this._pointerObserver = null;

+ 119 - 3
guiEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -16,6 +16,35 @@ import { Engine } from "babylonjs/Engines/engine";
 import { LockObject } from "../../sharedUiComponents/tabs/propertyGrids/lockObject";
 import { LockObject } from "../../sharedUiComponents/tabs/propertyGrids/lockObject";
 import { SliderPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/sliderPropertyGridComponent";
 import { SliderPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/sliderPropertyGridComponent";
 import { Slider } from "babylonjs-gui/2D/controls/sliders/slider";
 import { Slider } from "babylonjs-gui/2D/controls/sliders/slider";
+import { LinePropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/linePropertyGridComponent";
+import { RadioButtonPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/radioButtonPropertyGridComponent";
+
+import { TextBlock } from "babylonjs-gui/2D/controls/textBlock";
+import { InputText } from "babylonjs-gui/2D/controls/inputText";
+import { ColorPicker } from "babylonjs-gui/2D/controls/colorpicker";
+import { Image } from "babylonjs-gui/2D/controls/image";
+import { ImageBasedSlider } from "babylonjs-gui/2D/controls/sliders/imageBasedSlider";
+import { Rectangle } from "babylonjs-gui/2D/controls/rectangle";
+import { Ellipse } from "babylonjs-gui/2D/controls/ellipse";
+import { Checkbox } from "babylonjs-gui/2D/controls/checkbox";
+import { RadioButton } from "babylonjs-gui/2D/controls/radioButton";
+import { Line } from "babylonjs-gui/2D/controls/line";
+import { ScrollViewer } from "babylonjs-gui/2D/controls/scrollViewers/scrollViewer";
+import { Grid } from "babylonjs-gui/2D/controls/grid";
+import { StackPanel } from "babylonjs-gui/2D/controls/stackPanel";
+import { TextBlockPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/textBlockPropertyGridComponent";
+import { InputTextPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/inputTextPropertyGridComponent";
+import { ColorPickerPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/colorPickerPropertyGridComponent";
+import { ImagePropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/imagePropertyGridComponent";
+import { ImageBasedSliderPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent";
+import { RectanglePropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/rectanglePropertyGridComponent";
+import { StackPanelPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/stackPanelPropertyGridComponent";
+import { GridPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/gridPropertyGridComponent";
+import { ScrollViewerPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent";
+import { EllipsePropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/ellipsePropertyGridComponent";
+import { CheckboxPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/checkboxPropertyGridComponent";
+import { Control } from "babylonjs-gui/2D/controls/control";
+import { ControlPropertyGridComponent } from "../../sharedUiComponents/tabs/propertyGrids/gui/controlPropertyGridComponent";
 
 
 require("./propertyTab.scss");
 require("./propertyTab.scss");
 
 
@@ -175,9 +204,96 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
     renderProperties()
     renderProperties()
     {
     {
         var className = this.state.currentNode?.guiControl.getClassName();
         var className = this.state.currentNode?.guiControl.getClassName();
-        if (className === "Slider") {
-            const slider = this.state.currentNode?.guiControl as Slider;
-            return (<SliderPropertyGridComponent slider={slider}
+        switch (className) {
+            case "TextBlock": {
+                const textBlock = this.state.currentNode?.guiControl as TextBlock;
+                return (<TextBlockPropertyGridComponent textBlock={textBlock}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "InputText": {
+                const inputText = this.state.currentNode?.guiControl as InputText;
+                return (<InputTextPropertyGridComponent inputText={inputText}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "ColorPicker": {
+                const colorPicker = this.state.currentNode?.guiControl as ColorPicker;
+                return (<ColorPickerPropertyGridComponent colorPicker={colorPicker}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "Image": {
+                const image = this.state.currentNode?.guiControl as Image;
+                return (<ImagePropertyGridComponent image={image}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "Slider": {
+                const slider = this.state.currentNode?.guiControl as Slider;
+                return (<SliderPropertyGridComponent slider={slider}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "ImageBasedSlider": {
+                const imageBasedSlider = this.state.currentNode?.guiControl as ImageBasedSlider;
+                return (<ImageBasedSliderPropertyGridComponent imageBasedSlider={imageBasedSlider}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "Rectangle": {
+                const rectangle = this.state.currentNode?.guiControl as Rectangle;
+                return (<RectanglePropertyGridComponent rectangle={rectangle}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "StackPanel": {
+                const stackPanel = this.state.currentNode?.guiControl as StackPanel;
+                return (<StackPanelPropertyGridComponent stackPanel={stackPanel}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "Grid": {
+                const grid = this.state.currentNode?.guiControl as Grid;
+                return (<GridPropertyGridComponent grid={grid}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "ScrollViewer": {
+                const scrollViewer = this.state.currentNode?.guiControl as ScrollViewer;
+                return (<ScrollViewerPropertyGridComponent scrollViewer={scrollViewer}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "Ellipse": {
+                const ellipse = this.state.currentNode?.guiControl as Ellipse;
+                return (<EllipsePropertyGridComponent ellipse={ellipse}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "Checkbox": {
+                const checkbox = this.state.currentNode?.guiControl as Checkbox;
+                return (<CheckboxPropertyGridComponent checkbox={checkbox}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "RadioButton": {
+                const radioButton = this.state.currentNode?.guiControl as RadioButton;
+                return (<RadioButtonPropertyGridComponent radioButton={radioButton}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+            case "Line": {
+                const line = this.state.currentNode?.guiControl as Line;
+                return (<LinePropertyGridComponent line={line}
+                    lockObject={this._lockObject}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
+            }
+        }
+
+        if (className !== "") {
+            const control = this.state.currentNode?.guiControl as Control;
+            return (<ControlPropertyGridComponent control={control}
                 lockObject={this._lockObject}
                 lockObject={this._lockObject}
                 onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
                 onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />);
         }
         }

+ 14 - 28
inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx

@@ -30,11 +30,11 @@ import { MeshPropertyGridComponent } from "./propertyGrids/meshes/meshPropertyGr
 import { TransformNodePropertyGridComponent } from "./propertyGrids/meshes/transformNodePropertyGridComponent";
 import { TransformNodePropertyGridComponent } from "./propertyGrids/meshes/transformNodePropertyGridComponent";
 import { BackgroundMaterialPropertyGridComponent } from "./propertyGrids/materials/backgroundMaterialPropertyGridComponent";
 import { BackgroundMaterialPropertyGridComponent } from "./propertyGrids/materials/backgroundMaterialPropertyGridComponent";
 import { Control } from "babylonjs-gui/2D/controls/control";
 import { Control } from "babylonjs-gui/2D/controls/control";
-import { ControlPropertyGridComponent } from "./propertyGrids/gui/controlPropertyGridComponent";
-import { TextBlockPropertyGridComponent } from "./propertyGrids/gui/textBlockPropertyGridComponent";
+import { ControlPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/controlPropertyGridComponent";
+import { TextBlockPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/textBlockPropertyGridComponent";
 import { TextBlock } from "babylonjs-gui/2D/controls/textBlock";
 import { TextBlock } from "babylonjs-gui/2D/controls/textBlock";
 import { InputText } from "babylonjs-gui/2D/controls/inputText";
 import { InputText } from "babylonjs-gui/2D/controls/inputText";
-import { InputTextPropertyGridComponent } from "./propertyGrids/gui/inputTextPropertyGridComponent";
+import { InputTextPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/inputTextPropertyGridComponent";
 
 
 import { ColorPicker } from "babylonjs-gui/2D/controls/colorpicker";
 import { ColorPicker } from "babylonjs-gui/2D/controls/colorpicker";
 import { Image } from "babylonjs-gui/2D/controls/image";
 import { Image } from "babylonjs-gui/2D/controls/image";
@@ -49,22 +49,22 @@ import { ScrollViewer } from "babylonjs-gui/2D/controls/scrollViewers/scrollView
 import { Grid } from "babylonjs-gui/2D/controls/grid";
 import { Grid } from "babylonjs-gui/2D/controls/grid";
 import { StackPanel } from "babylonjs-gui/2D/controls/stackPanel";
 import { StackPanel } from "babylonjs-gui/2D/controls/stackPanel";
 
 
-import { ColorPickerPropertyGridComponent } from "./propertyGrids/gui/colorPickerPropertyGridComponent";
+import { ColorPickerPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/colorPickerPropertyGridComponent";
 import { AnimationGroupGridComponent } from "./propertyGrids/animations/animationGroupPropertyGridComponent";
 import { AnimationGroupGridComponent } from "./propertyGrids/animations/animationGroupPropertyGridComponent";
 import { LockObject } from "../../../sharedUiComponents/tabs/propertyGrids/lockObject";
 import { LockObject } from "../../../sharedUiComponents/tabs/propertyGrids/lockObject";
-import { ImagePropertyGridComponent } from "./propertyGrids/gui/imagePropertyGridComponent";
+import { ImagePropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/imagePropertyGridComponent";
 import { SliderPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/sliderPropertyGridComponent";
 import { SliderPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/sliderPropertyGridComponent";
-import { ImageBasedSliderPropertyGridComponent } from "./propertyGrids/gui/imageBasedSliderPropertyGridComponent";
-import { RectanglePropertyGridComponent } from "./propertyGrids/gui/rectanglePropertyGridComponent";
-import { EllipsePropertyGridComponent } from "./propertyGrids/gui/ellipsePropertyGridComponent";
-import { CheckboxPropertyGridComponent } from "./propertyGrids/gui/checkboxPropertyGridComponent";
-import { RadioButtonPropertyGridComponent } from "./propertyGrids/gui/radioButtonPropertyGridComponent";
-import { LinePropertyGridComponent } from "./propertyGrids/gui/linePropertyGridComponent";
-import { ScrollViewerPropertyGridComponent } from "./propertyGrids/gui/scrollViewerPropertyGridComponent";
-import { GridPropertyGridComponent } from "./propertyGrids/gui/gridPropertyGridComponent";
+import { ImageBasedSliderPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent";
+import { RectanglePropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/rectanglePropertyGridComponent";
+import { EllipsePropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/ellipsePropertyGridComponent";
+import { CheckboxPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/checkboxPropertyGridComponent";
+import { RadioButtonPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/radioButtonPropertyGridComponent";
+import { LinePropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/linePropertyGridComponent";
+import { ScrollViewerPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent";
+import { GridPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/gridPropertyGridComponent";
 import { PBRMetallicRoughnessMaterialPropertyGridComponent } from "./propertyGrids/materials/pbrMetallicRoughnessMaterialPropertyGridComponent";
 import { PBRMetallicRoughnessMaterialPropertyGridComponent } from "./propertyGrids/materials/pbrMetallicRoughnessMaterialPropertyGridComponent";
 import { PBRSpecularGlossinessMaterialPropertyGridComponent } from "./propertyGrids/materials/pbrSpecularGlossinessMaterialPropertyGridComponent";
 import { PBRSpecularGlossinessMaterialPropertyGridComponent } from "./propertyGrids/materials/pbrSpecularGlossinessMaterialPropertyGridComponent";
-import { StackPanelPropertyGridComponent } from "./propertyGrids/gui/stackPanelPropertyGridComponent";
+import { StackPanelPropertyGridComponent } from "../../../sharedUiComponents/tabs/propertyGrids/gui/stackPanelPropertyGridComponent";
 import { PostProcess } from 'babylonjs/PostProcesses/postProcess';
 import { PostProcess } from 'babylonjs/PostProcesses/postProcess';
 import { PostProcessPropertyGridComponent } from './propertyGrids/postProcesses/postProcessPropertyGridComponent';
 import { PostProcessPropertyGridComponent } from './propertyGrids/postProcesses/postProcessPropertyGridComponent';
 import { RenderingPipelinePropertyGridComponent } from './propertyGrids/postProcesses/renderingPipelinePropertyGridComponent';
 import { RenderingPipelinePropertyGridComponent } from './propertyGrids/postProcesses/renderingPipelinePropertyGridComponent';
@@ -434,7 +434,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "TextBlock") {
             if (className === "TextBlock") {
                 const textBlock = entity as TextBlock;
                 const textBlock = entity as TextBlock;
                 return (<TextBlockPropertyGridComponent textBlock={textBlock}
                 return (<TextBlockPropertyGridComponent textBlock={textBlock}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -442,7 +441,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "InputText") {
             if (className === "InputText") {
                 const inputText = entity as InputText;
                 const inputText = entity as InputText;
                 return (<InputTextPropertyGridComponent inputText={inputText}
                 return (<InputTextPropertyGridComponent inputText={inputText}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -450,7 +448,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "ColorPicker") {
             if (className === "ColorPicker") {
                 const colorPicker = entity as ColorPicker;
                 const colorPicker = entity as ColorPicker;
                 return (<ColorPickerPropertyGridComponent colorPicker={colorPicker}
                 return (<ColorPickerPropertyGridComponent colorPicker={colorPicker}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -458,7 +455,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "Image") {
             if (className === "Image") {
                 const image = entity as Image;
                 const image = entity as Image;
                 return (<ImagePropertyGridComponent image={image}
                 return (<ImagePropertyGridComponent image={image}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -473,7 +469,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "ImageBasedSlider") {
             if (className === "ImageBasedSlider") {
                 const imageBasedSlider = entity as ImageBasedSlider;
                 const imageBasedSlider = entity as ImageBasedSlider;
                 return (<ImageBasedSliderPropertyGridComponent imageBasedSlider={imageBasedSlider}
                 return (<ImageBasedSliderPropertyGridComponent imageBasedSlider={imageBasedSlider}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -481,7 +476,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "Rectangle") {
             if (className === "Rectangle") {
                 const rectangle = entity as Rectangle;
                 const rectangle = entity as Rectangle;
                 return (<RectanglePropertyGridComponent rectangle={rectangle}
                 return (<RectanglePropertyGridComponent rectangle={rectangle}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -489,7 +483,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "StackPanel") {
             if (className === "StackPanel") {
                 const stackPanel = entity as StackPanel;
                 const stackPanel = entity as StackPanel;
                 return (<StackPanelPropertyGridComponent stackPanel={stackPanel}
                 return (<StackPanelPropertyGridComponent stackPanel={stackPanel}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -497,7 +490,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "Grid") {
             if (className === "Grid") {
                 const grid = entity as Grid;
                 const grid = entity as Grid;
                 return (<GridPropertyGridComponent grid={grid}
                 return (<GridPropertyGridComponent grid={grid}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -505,7 +497,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "ScrollViewer") {
             if (className === "ScrollViewer") {
                 const scrollViewer = entity as ScrollViewer;
                 const scrollViewer = entity as ScrollViewer;
                 return (<ScrollViewerPropertyGridComponent scrollViewer={scrollViewer}
                 return (<ScrollViewerPropertyGridComponent scrollViewer={scrollViewer}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -513,7 +504,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "Ellipse") {
             if (className === "Ellipse") {
                 const ellipse = entity as Ellipse;
                 const ellipse = entity as Ellipse;
                 return (<EllipsePropertyGridComponent ellipse={ellipse}
                 return (<EllipsePropertyGridComponent ellipse={ellipse}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -521,7 +511,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "Checkbox") {
             if (className === "Checkbox") {
                 const checkbox = entity as Checkbox;
                 const checkbox = entity as Checkbox;
                 return (<CheckboxPropertyGridComponent checkbox={checkbox}
                 return (<CheckboxPropertyGridComponent checkbox={checkbox}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -529,7 +518,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "RadioButton") {
             if (className === "RadioButton") {
                 const radioButton = entity as RadioButton;
                 const radioButton = entity as RadioButton;
                 return (<RadioButtonPropertyGridComponent radioButton={radioButton}
                 return (<RadioButtonPropertyGridComponent radioButton={radioButton}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -537,7 +525,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className === "Line") {
             if (className === "Line") {
                 const line = entity as Line;
                 const line = entity as Line;
                 return (<LinePropertyGridComponent line={line}
                 return (<LinePropertyGridComponent line={line}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }
@@ -545,7 +532,6 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (entity._host) {
             if (entity._host) {
                 const control = entity as Control;
                 const control = entity as Control;
                 return (<ControlPropertyGridComponent control={control}
                 return (<ControlPropertyGridComponent control={control}
-                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
             }

+ 3 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/textureCanvasManager.ts

@@ -31,6 +31,8 @@ import { IMetadata } from './textureEditorComponent';
 
 
 import { canvasShader } from './canvasShader';
 import { canvasShader } from './canvasShader';
 
 
+import { IWheelEvent } from 'babylonjs/Events/deviceInputEvents';
+
 export interface IPixelData {
 export interface IPixelData {
     x? : number;
     x? : number;
     y? : number;
     y? : number;
@@ -267,7 +269,7 @@ export class TextureCanvasManager {
         this._scene.onPointerObservable.add((pointerInfo) => {
         this._scene.onPointerObservable.add((pointerInfo) => {
             switch (pointerInfo.type) {
             switch (pointerInfo.type) {
                 case PointerEventTypes.POINTERWHEEL:
                 case PointerEventTypes.POINTERWHEEL:
-                    const event = pointerInfo.event as MouseWheelEvent;
+                    const event = pointerInfo.event as IWheelEvent;
                     this._scale -= (event.deltaY * this.ZOOM_MOUSE_SPEED * this._scale);
                     this._scale -= (event.deltaY * this.ZOOM_MOUSE_SPEED * this._scale);
                     break;
                     break;
                 case PointerEventTypes.POINTERDOWN:
                 case PointerEventTypes.POINTERDOWN:

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

@@ -803,7 +803,9 @@ export class GLTFLoader implements IGLTFLoader {
         let promise: Promise<any>;
         let promise: Promise<any>;
 
 
         if (shouldInstance && primitive._instanceData) {
         if (shouldInstance && primitive._instanceData) {
+            this._babylonScene._blockEntityCollection = this._forAssetContainer;
             babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name) as InstancedMesh;
             babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name) as InstancedMesh;
+            this._babylonScene._blockEntityCollection = false;
             promise = primitive._instanceData.promise;
             promise = primitive._instanceData.promise;
         }
         }
         else {
         else {

+ 1 - 0
sandbox/src/sandbox.tsx

@@ -37,6 +37,7 @@ export class Sandbox extends React.Component<ISandboxProps, { isFooterVisible: b
         // Events
         // Events
         this._globalState.onSceneLoaded.add((info) => {
         this._globalState.onSceneLoaded.add((info) => {
             document.title = "Babylon.js - " + info.filename;
             document.title = "Babylon.js - " + info.filename;
+            this.setState({ errorMessage: "" });
 
 
             this._globalState.currentScene = info.scene;
             this._globalState.currentScene = info.scene;
             if (this._globalState.currentScene.meshes.length === 0 && this._globalState.currentScene.clearColor.r === 1 && this._globalState.currentScene.clearColor.g === 0 && this._globalState.currentScene.clearColor.b === 0) {
             if (this._globalState.currentScene.meshes.length === 0 && this._globalState.currentScene.clearColor.r === 1 && this._globalState.currentScene.clearColor.g === 0 && this._globalState.currentScene.clearColor.b === 0) {

+ 6 - 8
inspector/src/components/actionTabs/tabs/propertyGrids/gui/checkboxPropertyGridComponent.tsx

@@ -1,16 +1,14 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { Checkbox } from "babylonjs-gui/2D/controls/checkbox";
 import { Checkbox } from "babylonjs-gui/2D/controls/checkbox";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 
 
 interface ICheckboxPropertyGridComponentProps {
 interface ICheckboxPropertyGridComponentProps {
-    globalState: GlobalState;
     checkbox: Checkbox;
     checkbox: Checkbox;
     lockObject: LockObject;
     lockObject: LockObject;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;

+ 5 - 7
inspector/src/components/actionTabs/tabs/propertyGrids/gui/colorPickerPropertyGridComponent.tsx

@@ -1,15 +1,13 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
 import { ColorPicker } from "babylonjs-gui/2D/controls/colorpicker";
 import { ColorPicker } from "babylonjs-gui/2D/controls/colorpicker";
-import { Color3LineComponent } from "../../../../../sharedUiComponents/lines/color3LineComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
-import { GlobalState } from '../../../../globalState';
+import { Color3LineComponent } from "../../../lines/color3LineComponent";
+import { LockObject } from "../lockObject";
 
 
 interface IColorPickerPropertyGridComponentProps {
 interface IColorPickerPropertyGridComponentProps {
-    globalState: GlobalState;
     colorPicker: ColorPicker;
     colorPicker: ColorPicker;
     lockObject: LockObject;
     lockObject: LockObject;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;

+ 3 - 5
inspector/src/components/actionTabs/tabs/propertyGrids/gui/controlPropertyGridComponent.tsx

@@ -1,13 +1,11 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
 import { Control } from "babylonjs-gui/2D/controls/control";
 import { Control } from "babylonjs-gui/2D/controls/control";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { GlobalState } from '../../../../globalState';
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 
 
 interface IControlPropertyGridComponentProps {
 interface IControlPropertyGridComponentProps {
-    globalState: GlobalState;
     control: Control,
     control: Control,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 6 - 8
inspector/src/components/actionTabs/tabs/propertyGrids/gui/ellipsePropertyGridComponent.tsx

@@ -1,16 +1,14 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { Ellipse } from "babylonjs-gui/2D/controls/ellipse";
 import { Ellipse } from "babylonjs-gui/2D/controls/ellipse";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 
 
 interface IEllipsePropertyGridComponentProps {
 interface IEllipsePropertyGridComponentProps {
-    globalState: GlobalState;
     ellipse: Ellipse,
     ellipse: Ellipse,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 5 - 7
inspector/src/components/actionTabs/tabs/propertyGrids/gui/gridPropertyGridComponent.tsx

@@ -1,15 +1,13 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { Grid } from "babylonjs-gui/2D/controls/grid";
 import { Grid } from "babylonjs-gui/2D/controls/grid";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { TextLineComponent } from "../../../../../sharedUiComponents/lines/textLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { TextLineComponent } from "../../../lines/textLineComponent";
 
 
 interface IGridPropertyGridComponentProps {
 interface IGridPropertyGridComponentProps {
-    globalState: GlobalState;
     grid: Grid,
     grid: Grid,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 7 - 9
inspector/src/components/actionTabs/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent.tsx

@@ -1,17 +1,15 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { ImageBasedSlider } from "babylonjs-gui/2D/controls/sliders/imageBasedSlider";
 import { ImageBasedSlider } from "babylonjs-gui/2D/controls/sliders/imageBasedSlider";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { TextInputLineComponent } from "../../../../../sharedUiComponents/lines/textInputLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
+import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
 
 
 interface IImageBasedSliderPropertyGridComponentProps {
 interface IImageBasedSliderPropertyGridComponentProps {
-    globalState: GlobalState;
     imageBasedSlider: ImageBasedSlider,
     imageBasedSlider: ImageBasedSlider,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 7 - 9
inspector/src/components/actionTabs/tabs/propertyGrids/gui/imagePropertyGridComponent.tsx

@@ -1,17 +1,15 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { Image } from "babylonjs-gui/2D/controls/image";
 import { Image } from "babylonjs-gui/2D/controls/image";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { OptionsLineComponent } from "../../../../../sharedUiComponents/lines/optionsLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
+import { OptionsLineComponent } from "../../../lines/optionsLineComponent";
 
 
 interface IImagePropertyGridComponentProps {
 interface IImagePropertyGridComponentProps {
-    globalState: GlobalState;
     image: Image,
     image: Image,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 8 - 10
inspector/src/components/actionTabs/tabs/propertyGrids/gui/inputTextPropertyGridComponent.tsx

@@ -1,18 +1,16 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
 import { InputText } from "babylonjs-gui/2D/controls/inputText";
 import { InputText } from "babylonjs-gui/2D/controls/inputText";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { TextInputLineComponent } from "../../../../../sharedUiComponents/lines/textInputLineComponent";
-import { SliderLineComponent } from "../../../../../sharedUiComponents/lines/sliderLineComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
+import { SliderLineComponent } from "../../../lines/sliderLineComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 
 
 interface IInputTextPropertyGridComponentProps {
 interface IInputTextPropertyGridComponentProps {
-    globalState: GlobalState;
     inputText: InputText;
     inputText: InputText;
     lockObject: LockObject;
     lockObject: LockObject;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;

+ 6 - 8
inspector/src/components/actionTabs/tabs/propertyGrids/gui/linePropertyGridComponent.tsx

@@ -1,16 +1,14 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { Line } from "babylonjs-gui/2D/controls/line";
 import { Line } from "babylonjs-gui/2D/controls/line";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { TextInputLineComponent } from "../../../../../sharedUiComponents/lines/textInputLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
 
 
 interface ILinePropertyGridComponentProps {
 interface ILinePropertyGridComponentProps {
-    globalState: GlobalState;
     line: Line,
     line: Line,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 7 - 9
inspector/src/components/actionTabs/tabs/propertyGrids/gui/radioButtonPropertyGridComponent.tsx

@@ -1,17 +1,15 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { RadioButton } from "babylonjs-gui/2D/controls/radioButton";
 import { RadioButton } from "babylonjs-gui/2D/controls/radioButton";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { TextInputLineComponent } from "../../../../../sharedUiComponents/lines/textInputLineComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 
 
 interface IRadioButtonPropertyGridComponentProps {
 interface IRadioButtonPropertyGridComponentProps {
-    globalState: GlobalState;
     radioButton: RadioButton,
     radioButton: RadioButton,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 6 - 8
inspector/src/components/actionTabs/tabs/propertyGrids/gui/rectanglePropertyGridComponent.tsx

@@ -1,16 +1,14 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { Rectangle } from "babylonjs-gui/2D/controls/rectangle";
 import { Rectangle } from "babylonjs-gui/2D/controls/rectangle";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 
 
 interface IRectanglePropertyGridComponentProps {
 interface IRectanglePropertyGridComponentProps {
-    globalState: GlobalState;
     rectangle: Rectangle,
     rectangle: Rectangle,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 6 - 8
inspector/src/components/actionTabs/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent.tsx

@@ -1,16 +1,14 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { ScrollViewer } from "babylonjs-gui/2D/controls/scrollViewers/scrollViewer";
 import { ScrollViewer } from "babylonjs-gui/2D/controls/scrollViewers/scrollViewer";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { TextInputLineComponent } from "../../../../../sharedUiComponents/lines/textInputLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
 
 
 interface IScrollViewerPropertyGridComponentProps {
 interface IScrollViewerPropertyGridComponentProps {
-    globalState: GlobalState;
     scrollViewer: ScrollViewer,
     scrollViewer: ScrollViewer,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 5 - 7
inspector/src/components/actionTabs/tabs/propertyGrids/gui/stackPanelPropertyGridComponent.tsx

@@ -1,15 +1,13 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
 import { StackPanel } from "babylonjs-gui/2D/controls/stackPanel";
 import { StackPanel } from "babylonjs-gui/2D/controls/stackPanel";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 
 
 interface IStackPanelPropertyGridComponentProps {
 interface IStackPanelPropertyGridComponentProps {
-    globalState: GlobalState;
     stackPanel: StackPanel,
     stackPanel: StackPanel,
     lockObject: LockObject,
     lockObject: LockObject,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>

+ 8 - 10
inspector/src/components/actionTabs/tabs/propertyGrids/gui/textBlockPropertyGridComponent.tsx

@@ -1,19 +1,17 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { CommonControlPropertyGridComponent } from "../../../../../sharedUiComponents/tabs/propertyGrids/gui/commonControlPropertyGridComponent";
+import { PropertyChangedEvent } from "../../../propertyChangedEvent";
+import { CommonControlPropertyGridComponent } from "../../../tabs/propertyGrids/gui/commonControlPropertyGridComponent";
 import { TextBlock, TextWrapping } from "babylonjs-gui/2D/controls/textBlock";
 import { TextBlock, TextWrapping } from "babylonjs-gui/2D/controls/textBlock";
 import { Control } from "babylonjs-gui/2D/controls/control";
 import { Control } from "babylonjs-gui/2D/controls/control";
-import { LineContainerComponent } from "../../../../../sharedUiComponents/lines/lineContainerComponent";
-import { TextInputLineComponent } from "../../../../../sharedUiComponents/lines/textInputLineComponent";
-import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
-import { OptionsLineComponent } from "../../../../../sharedUiComponents/lines/optionsLineComponent";
-import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
-import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
-import { GlobalState } from '../../../../globalState';
+import { LineContainerComponent } from "../../../lines/lineContainerComponent";
+import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
+import { LockObject } from "../../../tabs/propertyGrids/lockObject";
+import { OptionsLineComponent } from "../../../lines/optionsLineComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
 
 
 interface ITextBlockPropertyGridComponentProps {
 interface ITextBlockPropertyGridComponentProps {
-    globalState: GlobalState;
     textBlock: TextBlock;
     textBlock: TextBlock;
     lockObject: LockObject;
     lockObject: LockObject;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;

+ 4 - 3
src/Actions/actionEvent.ts

@@ -3,6 +3,7 @@ import { Nullable } from "../types";
 import { Sprite } from "../Sprites/sprite";
 import { Sprite } from "../Sprites/sprite";
 import { Scene } from "../scene";
 import { Scene } from "../scene";
 import { Vector2 } from "../Maths/math.vector";
 import { Vector2 } from "../Maths/math.vector";
+import { IEvent } from "../Events/deviceInputEvents";
 
 
 /**
 /**
  * Interface used to define ActionEvent
  * Interface used to define ActionEvent
@@ -57,7 +58,7 @@ export class ActionEvent implements IActionEvent {
      * @param additionalData additional data for the event
      * @param additionalData additional data for the event
      * @returns the new ActionEvent
      * @returns the new ActionEvent
      */
      */
-    public static CreateNew(source: AbstractMesh, evt?: Event, additionalData?: any): ActionEvent {
+    public static CreateNew(source: AbstractMesh, evt?: IEvent, additionalData?: any): ActionEvent {
         var scene = source.getScene();
         var scene = source.getScene();
         return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer || source, evt, additionalData);
         return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer || source, evt, additionalData);
     }
     }
@@ -70,7 +71,7 @@ export class ActionEvent implements IActionEvent {
      * @param additionalData additional data for the event
      * @param additionalData additional data for the event
      * @returns the new ActionEvent
      * @returns the new ActionEvent
      */
      */
-    public static CreateNewFromSprite(source: Sprite, scene: Scene, evt?: Event, additionalData?: any): ActionEvent {
+    public static CreateNewFromSprite(source: Sprite, scene: Scene, evt?: IEvent, additionalData?: any): ActionEvent {
         return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt, additionalData);
         return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt, additionalData);
     }
     }
 
 
@@ -80,7 +81,7 @@ export class ActionEvent implements IActionEvent {
      * @param evt The original (browser) event
      * @param evt The original (browser) event
      * @returns the new ActionEvent
      * @returns the new ActionEvent
      */
      */
-    public static CreateNewFromScene(scene: Scene, evt: Event): ActionEvent {
+    public static CreateNewFromScene(scene: Scene, evt: IEvent): ActionEvent {
         return new ActionEvent(null, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt);
         return new ActionEvent(null, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt);
     }
     }
 
 

+ 3 - 2
src/Cameras/Inputs/BaseCameraMouseWheelInput.ts

@@ -5,6 +5,7 @@ import { Camera } from "../../Cameras/camera";
 import { ICameraInput } from "../../Cameras/cameraInputsManager";
 import { ICameraInput } from "../../Cameras/cameraInputsManager";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { Tools } from "../../Misc/tools";
 import { Tools } from "../../Misc/tools";
+import { EventConstants, IWheelEvent } from "../../Events/deviceInputEvents";
 
 
 /**
 /**
  * Base class for mouse wheel input..
  * Base class for mouse wheel input..
@@ -61,9 +62,9 @@ export abstract class BaseCameraMouseWheelInput implements ICameraInput<Camera>
                 return;
                 return;
             }
             }
 
 
-            const event = <MouseWheelEvent>pointer.event;
+            const event = <IWheelEvent>pointer.event;
 
 
-            const platformScale = event.deltaMode === WheelEvent.DOM_DELTA_LINE ? this._ffMultiplier : 1;
+            const platformScale = event.deltaMode === EventConstants.DOM_DELTA_LINE ? this._ffMultiplier : 1;  // If this happens to be set to DOM_DELTA_LINE, adjust accordingly
 
 
             if (event.deltaY !== undefined) {
             if (event.deltaY !== undefined) {
                 // Most recent browsers versions have delta properties.
                 // Most recent browsers versions have delta properties.

+ 8 - 7
src/Cameras/Inputs/BaseCameraPointersInput.ts

@@ -5,6 +5,7 @@ import { Tools } from "../../Misc/tools";
 import { Camera } from "../../Cameras/camera";
 import { Camera } from "../../Cameras/camera";
 import { ICameraInput } from "../../Cameras/cameraInputsManager";
 import { ICameraInput } from "../../Cameras/cameraInputsManager";
 import { PointerInfo, PointerEventTypes, PointerTouch } from "../../Events/pointerEvents";
 import { PointerInfo, PointerEventTypes, PointerTouch } from "../../Events/pointerEvents";
+import { IPointerEvent } from "../../Events/deviceInputEvents";
 
 
 /**
 /**
  * Base class for Camera Pointer Inputs.
  * Base class for Camera Pointer Inputs.
@@ -59,7 +60,7 @@ export abstract class BaseCameraPointersInput implements ICameraInput<Camera> {
         this._buttonsPressed = 0;
         this._buttonsPressed = 0;
 
 
         this._pointerInput = (p, s) => {
         this._pointerInput = (p, s) => {
-            var evt = <PointerEvent>p.event;
+            var evt = <IPointerEvent>p.event;
             let isTouch = evt.pointerType === "touch";
             let isTouch = evt.pointerType === "touch";
 
 
             if (engine.isInVRExclusivePointerMode) {
             if (engine.isInVRExclusivePointerMode) {
@@ -80,12 +81,12 @@ export abstract class BaseCameraPointersInput implements ICameraInput<Camera> {
             this._buttonsPressed = evt.buttons;
             this._buttonsPressed = evt.buttons;
 
 
             if (engine.isPointerLock) {
             if (engine.isPointerLock) {
-                var offsetX = evt.movementX ||
+                const offsetX = evt.movementX ||
                               evt.mozMovementX ||
                               evt.mozMovementX ||
                               evt.webkitMovementX ||
                               evt.webkitMovementX ||
                               evt.msMovementX ||
                               evt.msMovementX ||
                               0;
                               0;
-                var offsetY = evt.movementY ||
+                const offsetY = evt.movementY ||
                               evt.mozMovementY ||
                               evt.mozMovementY ||
                               evt.webkitMovementY ||
                               evt.webkitMovementY ||
                               evt.msMovementY ||
                               evt.msMovementY ||
@@ -180,8 +181,8 @@ export abstract class BaseCameraPointersInput implements ICameraInput<Camera> {
 
 
                 // One button down
                 // One button down
                 if (this.pointA && this.pointB === null) {
                 if (this.pointA && this.pointB === null) {
-                    var offsetX = evt.clientX - this.pointA.x;
-                    var offsetY = evt.clientY - this.pointA.y;
+                    const offsetX = evt.clientX - this.pointA.x;
+                    const offsetY = evt.clientY - this.pointA.y;
                     this.onTouch(this.pointA, offsetX, offsetY);
                     this.onTouch(this.pointA, offsetX, offsetY);
 
 
                     this.pointA.x = evt.clientX;
                     this.pointA.x = evt.clientX;
@@ -334,7 +335,7 @@ export abstract class BaseCameraPointersInput implements ICameraInput<Camera> {
      * press.
      * press.
      * Override this method to provide functionality.
      * Override this method to provide functionality.
      */
      */
-    protected onButtonDown(evt: PointerEvent): void {
+    protected onButtonDown(evt: IPointerEvent): void {
     }
     }
 
 
     /**
     /**
@@ -342,7 +343,7 @@ export abstract class BaseCameraPointersInput implements ICameraInput<Camera> {
      * release.
      * release.
      * Override this method to provide functionality.
      * Override this method to provide functionality.
      */
      */
-    protected onButtonUp(evt: PointerEvent): void {
+    protected onButtonUp(evt: IPointerEvent): void {
     }
     }
 
 
     /**
     /**

+ 2 - 1
src/Cameras/Inputs/arcRotateCameraMouseWheelInput.ts

@@ -6,6 +6,7 @@ import { ICameraInput, CameraInputTypes } from "../../Cameras/cameraInputsManage
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { Scalar } from '../../Maths/math.scalar';
 import { Scalar } from '../../Maths/math.scalar';
 import { Tools } from '../../Misc/tools';
 import { Tools } from '../../Misc/tools';
+import { IWheelEvent } from "../../Events/deviceInputEvents";
 
 
 /**
 /**
  * Manage the mouse wheel inputs to control an arc rotate camera.
  * Manage the mouse wheel inputs to control an arc rotate camera.
@@ -53,7 +54,7 @@ export class ArcRotateCameraMouseWheelInput implements ICameraInput<ArcRotateCam
         this._wheel = (p, s) => {
         this._wheel = (p, s) => {
             //sanity check - this should be a PointerWheel event.
             //sanity check - this should be a PointerWheel event.
             if (p.type !== PointerEventTypes.POINTERWHEEL) { return; }
             if (p.type !== PointerEventTypes.POINTERWHEEL) { return; }
-            var event = <MouseWheelEvent>p.event;
+            var event = <IWheelEvent>p.event;
             var delta = 0;
             var delta = 0;
 
 
             let mouseWheelLegacyEvent = event as any;
             let mouseWheelLegacyEvent = event as any;

+ 3 - 2
src/Cameras/Inputs/arcRotateCameraPointersInput.ts

@@ -4,6 +4,7 @@ import { ArcRotateCamera } from "../../Cameras/arcRotateCamera";
 import { CameraInputTypes } from "../../Cameras/cameraInputsManager";
 import { CameraInputTypes } from "../../Cameras/cameraInputsManager";
 import { BaseCameraPointersInput } from "../../Cameras/Inputs/BaseCameraPointersInput";
 import { BaseCameraPointersInput } from "../../Cameras/Inputs/BaseCameraPointersInput";
 import { PointerTouch } from "../../Events/pointerEvents";
 import { PointerTouch } from "../../Events/pointerEvents";
+import { IPointerEvent } from "../../Events/deviceInputEvents";
 
 
 /**
 /**
  * Manage the pointers inputs to control an arc rotate camera.
  * Manage the pointers inputs to control an arc rotate camera.
@@ -223,7 +224,7 @@ export class ArcRotateCameraPointersInput extends BaseCameraPointersInput {
      * Called each time a new POINTERDOWN event occurs. Ie, for each button
      * Called each time a new POINTERDOWN event occurs. Ie, for each button
      * press.
      * press.
      */
      */
-    protected onButtonDown(evt: PointerEvent): void {
+    protected onButtonDown(evt: IPointerEvent): void {
         this._isPanClick = evt.button === this.camera._panningMouseButton;
         this._isPanClick = evt.button === this.camera._panningMouseButton;
     }
     }
 
 
@@ -231,7 +232,7 @@ export class ArcRotateCameraPointersInput extends BaseCameraPointersInput {
      * Called each time a new POINTERUP event occurs. Ie, for each button
      * Called each time a new POINTERUP event occurs. Ie, for each button
      * release.
      * release.
      */
      */
-    protected onButtonUp(evt: PointerEvent): void {
+    protected onButtonUp(evt: IPointerEvent): void {
         this._twoFingerActivityCount = 0;
         this._twoFingerActivityCount = 0;
         this._isPinching = false;
         this._isPinching = false;
     }
     }

+ 2 - 1
src/Cameras/Inputs/flyCameraMouseInput.ts

@@ -8,6 +8,7 @@ import { Scene } from "../../scene";
 import { Quaternion } from "../../Maths/math.vector";
 import { Quaternion } from "../../Maths/math.vector";
 import { Axis } from '../../Maths/math.axis';
 import { Axis } from '../../Maths/math.axis';
 import { Tools } from '../../Misc/tools';
 import { Tools } from '../../Misc/tools';
+import { IPointerEvent } from "../../Events/deviceInputEvents";
 /**
 /**
  * Listen to mouse events to control the camera.
  * Listen to mouse events to control the camera.
  * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
  * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
@@ -139,7 +140,7 @@ export class FlyCameraMouseInput implements ICameraInput<FlyCamera> {
 
 
     // Track mouse movement, when the pointer is not locked.
     // Track mouse movement, when the pointer is not locked.
     private _pointerInput(p: any, s: any): void {
     private _pointerInput(p: any, s: any): void {
-        var e = <PointerEvent>p.event;
+        var e = <IPointerEvent>p.event;
 
 
         let camera = this.camera;
         let camera = this.camera;
         let engine = camera.getEngine();
         let engine = camera.getEngine();

+ 2 - 1
src/Cameras/Inputs/followCameraMouseWheelInput.ts

@@ -5,6 +5,7 @@ import { FollowCamera } from "../../Cameras/followCamera";
 import { ICameraInput, CameraInputTypes } from "../../Cameras/cameraInputsManager";
 import { ICameraInput, CameraInputTypes } from "../../Cameras/cameraInputsManager";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { Tools } from '../../Misc/tools';
 import { Tools } from '../../Misc/tools';
+import { IWheelEvent } from "../../Events/deviceInputEvents";
 
 
 /**
 /**
  * Manage the mouse wheel inputs to control a follow camera.
  * Manage the mouse wheel inputs to control a follow camera.
@@ -60,7 +61,7 @@ export class FollowCameraMouseWheelInput implements ICameraInput<FollowCamera> {
         this._wheel = (p, s) => {
         this._wheel = (p, s) => {
             // sanity check - this should be a PointerWheel event.
             // sanity check - this should be a PointerWheel event.
             if (p.type !== PointerEventTypes.POINTERWHEEL) { return; }
             if (p.type !== PointerEventTypes.POINTERWHEEL) { return; }
-            var event = <MouseWheelEvent>p.event;
+            var event = <IWheelEvent>p.event;
             var delta = 0;
             var delta = 0;
 
 
             // Chrome, Safari: event.deltaY
             // Chrome, Safari: event.deltaY

+ 4 - 3
src/Cameras/Inputs/freeCameraMouseInput.ts

@@ -5,6 +5,7 @@ import { ICameraInput, CameraInputTypes } from "../../Cameras/cameraInputsManage
 import { FreeCamera } from "../../Cameras/freeCamera";
 import { FreeCamera } from "../../Cameras/freeCamera";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { Tools } from "../../Misc/tools";
 import { Tools } from "../../Misc/tools";
+import { IMouseEvent, IPointerEvent } from "../../Events/deviceInputEvents";
 /**
 /**
  * Manage the mouse inputs to control the movement of a free camera.
  * Manage the mouse inputs to control the movement of a free camera.
  * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
  * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
@@ -28,7 +29,7 @@ export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
     public angularSensibility = 2000.0;
     public angularSensibility = 2000.0;
 
 
     private _pointerInput: (p: PointerInfo, s: EventState) => void;
     private _pointerInput: (p: PointerInfo, s: EventState) => void;
-    private _onMouseMove: Nullable<(e: MouseEvent) => any>;
+    private _onMouseMove: Nullable<(e: IMouseEvent) => any>;
     private _observer: Nullable<Observer<PointerInfo>>;
     private _observer: Nullable<Observer<PointerInfo>>;
     private previousPosition: Nullable<{ x: number; y: number }> = null;
     private previousPosition: Nullable<{ x: number; y: number }> = null;
 
 
@@ -64,7 +65,7 @@ export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
 
 
         if (!this._pointerInput) {
         if (!this._pointerInput) {
             this._pointerInput = (p) => {
             this._pointerInput = (p) => {
-                var evt = <PointerEvent>p.event;
+                var evt = <IPointerEvent>p.event;
 
 
                 if (engine.isInVRExclusivePointerMode) {
                 if (engine.isInVRExclusivePointerMode) {
                     return;
                     return;
@@ -178,7 +179,7 @@ export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
 
 
         this._observer = this.camera.getScene().onPointerObservable.add(this._pointerInput, PointerEventTypes.POINTERDOWN | PointerEventTypes.POINTERUP | PointerEventTypes.POINTERMOVE);
         this._observer = this.camera.getScene().onPointerObservable.add(this._pointerInput, PointerEventTypes.POINTERDOWN | PointerEventTypes.POINTERUP | PointerEventTypes.POINTERMOVE);
 
 
-        element && element.addEventListener("contextmenu", <EventListener>this.onContextMenu.bind(this), false);
+        element && element.addEventListener("contextmenu", <EventListener>this.onContextMenu.bind(this), false); // TODO: We need to figure out how to handle this for Native
     }
     }
 
 
     /**
     /**

+ 2 - 1
src/Cameras/Inputs/freeCameraTouchInput.ts

@@ -6,6 +6,7 @@ import { FreeCamera } from "../../Cameras/freeCamera";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { PointerInfo, PointerEventTypes } from "../../Events/pointerEvents";
 import { Matrix, Vector3 } from "../../Maths/math.vector";
 import { Matrix, Vector3 } from "../../Maths/math.vector";
 import { Tools } from "../../Misc/tools";
 import { Tools } from "../../Misc/tools";
+import { IPointerEvent } from "../../Events/deviceInputEvents";
 /**
 /**
  * Manage the touch inputs to control the movement of a free camera.
  * Manage the touch inputs to control the movement of a free camera.
  * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
  * @see https://doc.babylonjs.com/how_to/customizing_camera_inputs
@@ -65,7 +66,7 @@ export class FreeCameraTouchInput implements ICameraInput<FreeCamera> {
             };
             };
 
 
             this._pointerInput = (p) => {
             this._pointerInput = (p) => {
-                var evt = <PointerEvent>p.event;
+                var evt = <IPointerEvent>p.event;
 
 
                 let isMouseEvent = !this.camera.getEngine().hostInformation.isMobile && evt instanceof MouseEvent;
                 let isMouseEvent = !this.camera.getEngine().hostInformation.isMobile && evt instanceof MouseEvent;
                 if (!this.allowMouse && (evt.pointerType === "mouse" || isMouseEvent)) {
                 if (!this.allowMouse && (evt.pointerType === "mouse" || isMouseEvent)) {

+ 11 - 1
src/DeviceInput/InputDevices/deviceEnums.ts

@@ -36,7 +36,17 @@ export enum PointerInput {
     /** Browser Back */
     /** Browser Back */
     BrowserBack = 5,
     BrowserBack = 5,
     /** Browser Forward */
     /** Browser Forward */
-    BrowserForward = 6
+    BrowserForward = 6,
+    /** Mouse Wheel X */
+    MouseWheelX = 7,
+    /** Mouse Wheel Y */
+    MouseWheelY = 8,
+    /** Mouse Wheel Z */
+    MouseWheelZ = 9,
+    /** Delta X */
+    DeltaHorizontal = 10,
+    /** Delta Y */
+    DeltaVertical = 11
 }
 }
 
 
 /**
 /**

+ 170 - 35
src/DeviceInput/deviceInputSystem.ts

@@ -1,7 +1,8 @@
 import { Engine } from '../Engines/engine';
 import { Engine } from '../Engines/engine';
+import { Tools } from '../Misc/tools';
 import { IDisposable } from '../scene';
 import { IDisposable } from '../scene';
 import { Nullable } from '../types';
 import { Nullable } from '../types';
-import { DeviceType } from './InputDevices/deviceEnums';
+import { DeviceType, PointerInput } from './InputDevices/deviceEnums';
 
 
 /** @hidden */
 /** @hidden */
 declare const _native: any;
 declare const _native: any;
@@ -62,6 +63,8 @@ export class DeviceInputSystem implements IDisposable {
     private _pointerMoveEvent = (evt: any) => { };
     private _pointerMoveEvent = (evt: any) => { };
     private _pointerDownEvent = (evt: any) => { };
     private _pointerDownEvent = (evt: any) => { };
     private _pointerUpEvent = (evt: any) => { };
     private _pointerUpEvent = (evt: any) => { };
+    private _pointerWheelEvent = (evt: any) => { };
+    private _wheelEventName: string;
 
 
     private _gamepadConnectedEvent = (evt: any) => { };
     private _gamepadConnectedEvent = (evt: any) => { };
     private _gamepadDisconnectedEvent = (evt: any) => { };
     private _gamepadDisconnectedEvent = (evt: any) => { };
@@ -69,10 +72,13 @@ export class DeviceInputSystem implements IDisposable {
     private _onDeviceConnected: (deviceType: DeviceType, deviceSlot: number) => void = () => { };
     private _onDeviceConnected: (deviceType: DeviceType, deviceSlot: number) => void = () => { };
 
 
     private static _MAX_KEYCODES: number = 255;
     private static _MAX_KEYCODES: number = 255;
-    private static _MAX_POINTER_INPUTS: number = 7;
+    private static _MAX_POINTER_INPUTS: number = Object.keys(PointerInput).length / 2;
+
+    private _eventPrefix: string;
 
 
     private constructor(engine: Engine) {
     private constructor(engine: Engine) {
         const inputElement = engine.getInputElement();
         const inputElement = engine.getInputElement();
+        this._eventPrefix = Tools.GetPointerPrefix(engine);
 
 
         if (inputElement) {
         if (inputElement) {
             this._elementToAttachTo = inputElement;
             this._elementToAttachTo = inputElement;
@@ -127,10 +133,28 @@ export class DeviceInputSystem implements IDisposable {
             throw `Unable to find input ${inputIndex} for device ${DeviceType[deviceType]} in slot ${deviceSlot}`;
             throw `Unable to find input ${inputIndex} for device ${DeviceType[deviceType]} in slot ${deviceSlot}`;
         }
         }
 
 
+        // When the mouse wheel is moved, only clear the value if that input is polled for
+        if (deviceType === DeviceType.Mouse && (inputIndex >= PointerInput.MouseWheelX && inputIndex <= PointerInput.MouseWheelZ)) {
+            const currentValue = device[inputIndex];
+
+            device[inputIndex] = 0;
+
+            return currentValue;
+        }
+
         return device[inputIndex];
         return device[inputIndex];
     }
     }
 
 
     /**
     /**
+     * Check for a specific device in the DeviceInputSystem
+     * @param deviceType Type of device to check for
+     * @returns bool with status of device's existence
+     */
+    public isDeviceAvailable(deviceType: DeviceType) {
+        return (this._inputs[deviceType] !== undefined);
+    }
+
+    /**
      * Dispose of all the eventlisteners
      * Dispose of all the eventlisteners
      */
      */
     public dispose() {
     public dispose() {
@@ -142,9 +166,10 @@ export class DeviceInputSystem implements IDisposable {
 
 
         // Pointer Events
         // Pointer Events
         if (this._pointerActive) {
         if (this._pointerActive) {
-            this._elementToAttachTo.removeEventListener("pointermove", this._pointerMoveEvent);
-            this._elementToAttachTo.removeEventListener("pointerdown", this._pointerDownEvent);
-            this._elementToAttachTo.removeEventListener("pointerup", this._pointerUpEvent);
+            this._elementToAttachTo.removeEventListener(this._eventPrefix + "move", this._pointerMoveEvent);
+            this._elementToAttachTo.removeEventListener(this._eventPrefix + "down", this._pointerDownEvent);
+            this._elementToAttachTo.removeEventListener(this._eventPrefix + "up", this._pointerUpEvent);
+            this._elementToAttachTo.removeEventListener(this._wheelEventName, this._pointerWheelEvent);
         }
         }
 
 
         // Gamepad Events
         // Gamepad Events
@@ -249,20 +274,25 @@ export class DeviceInputSystem implements IDisposable {
 
 
             const kbKey = this._inputs[DeviceType.Keyboard][0];
             const kbKey = this._inputs[DeviceType.Keyboard][0];
             if (kbKey) {
             if (kbKey) {
+                kbKey[evt.keyCode] = 1;
                 if (this.onInputChanged) {
                 if (this.onInputChanged) {
-                    this.onInputChanged(DeviceType.Keyboard, 0, evt.keyCode, kbKey[evt.keyCode], 1);
+                    this.onInputChanged(DeviceType.Keyboard, 0, evt.keyCode, 0, kbKey[evt.keyCode]);
                 }
                 }
-                kbKey[evt.keyCode] = 1;
             }
             }
         });
         });
 
 
         this._keyboardUpEvent = ((evt) => {
         this._keyboardUpEvent = ((evt) => {
+            if (!this._keyboardActive) {
+                this._keyboardActive = true;
+                this._registerDevice(DeviceType.Keyboard, 0, DeviceInputSystem._MAX_KEYCODES);
+            }
+
             const kbKey = this._inputs[DeviceType.Keyboard][0];
             const kbKey = this._inputs[DeviceType.Keyboard][0];
             if (kbKey) {
             if (kbKey) {
+                kbKey[evt.keyCode] = 0;
                 if (this.onInputChanged) {
                 if (this.onInputChanged) {
-                    this.onInputChanged(DeviceType.Keyboard, 0, evt.keyCode, kbKey[evt.keyCode], 0);
+                    this.onInputChanged(DeviceType.Keyboard, 0, evt.keyCode, 1, kbKey[evt.keyCode]);
                 }
                 }
-                kbKey[evt.keyCode] = 0;
             }
             }
         });
         });
 
 
@@ -275,8 +305,8 @@ export class DeviceInputSystem implements IDisposable {
      */
      */
     private _handlePointerActions() {
     private _handlePointerActions() {
         this._pointerMoveEvent = ((evt) => {
         this._pointerMoveEvent = ((evt) => {
-            const deviceType = (evt.pointerType == "mouse") ? DeviceType.Mouse : DeviceType.Touch;
-            const deviceSlot = (evt.pointerType == "mouse") ? 0 : evt.pointerId;
+            const deviceType = (evt.pointerType === "mouse") ? DeviceType.Mouse : DeviceType.Touch;
+            const deviceSlot = (evt.pointerType === "mouse") ? 0 : evt.pointerId;
 
 
             if (!this._inputs[deviceType]) {
             if (!this._inputs[deviceType]) {
                 this._inputs[deviceType] = [];
                 this._inputs[deviceType] = [];
@@ -288,18 +318,37 @@ export class DeviceInputSystem implements IDisposable {
 
 
             const pointer = this._inputs[deviceType][deviceSlot];
             const pointer = this._inputs[deviceType][deviceSlot];
             if (pointer) {
             if (pointer) {
+                // Store previous values for event
+                const previousHorizontal = pointer[PointerInput.Horizontal];
+                const previousVertical = pointer[PointerInput.Vertical];
+                const previousDeltaHorizontal = pointer[PointerInput.DeltaHorizontal];
+                const previousDeltaVertical = pointer[PointerInput.DeltaVertical];
+
+                pointer[PointerInput.Horizontal] = evt.clientX;
+                pointer[PointerInput.Vertical] = evt.clientY;
+                pointer[PointerInput.DeltaHorizontal] = evt.movementX;
+                pointer[PointerInput.DeltaVertical] = evt.movementY;
+
                 if (this.onInputChanged) {
                 if (this.onInputChanged) {
-                    this.onInputChanged(deviceType, deviceSlot, 0, pointer[0], evt.clientX);
-                    this.onInputChanged(deviceType, deviceSlot, 1, pointer[1], evt.clientY);
+                    if (previousHorizontal !== evt.clientX) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.Horizontal, previousHorizontal, pointer[PointerInput.Horizontal]);
+                    }
+                    if (previousVertical !== evt.clientY) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.Vertical, previousVertical, pointer[PointerInput.Vertical]);
+                    }
+                    if (pointer[PointerInput.DeltaHorizontal] !== 0) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.DeltaHorizontal, previousDeltaHorizontal, pointer[PointerInput.DeltaHorizontal]);
+                    }
+                    if (pointer[PointerInput.DeltaVertical] !== 0) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.DeltaVertical, previousDeltaVertical, pointer[PointerInput.DeltaVertical]);
+                    }
                 }
                 }
-                pointer[0] = evt.clientX;
-                pointer[1] = evt.clientY;
             }
             }
         });
         });
 
 
         this._pointerDownEvent = ((evt) => {
         this._pointerDownEvent = ((evt) => {
-            const deviceType = (evt.pointerType == "mouse") ? DeviceType.Mouse : DeviceType.Touch;
-            const deviceSlot = (evt.pointerType == "mouse") ? 0 : evt.pointerId;
+            const deviceType = (evt.pointerType === "mouse") ? DeviceType.Mouse : DeviceType.Touch;
+            const deviceSlot = (evt.pointerType === "mouse") ? 0 : evt.pointerId;
 
 
             if (!this._inputs[deviceType]) {
             if (!this._inputs[deviceType]) {
                 this._inputs[deviceType] = [];
                 this._inputs[deviceType] = [];
@@ -311,41 +360,127 @@ export class DeviceInputSystem implements IDisposable {
 
 
             const pointer = this._inputs[deviceType][deviceSlot];
             const pointer = this._inputs[deviceType][deviceSlot];
             if (pointer) {
             if (pointer) {
+                const previousHorizontal = pointer[PointerInput.Horizontal];
+                const previousVertical = pointer[PointerInput.Vertical];
+                const previousButton = pointer[evt.button + 2];
+
+                pointer[PointerInput.Horizontal] = evt.clientX;
+                pointer[PointerInput.Vertical] = evt.clientY;
+                pointer[evt.button + 2] = 1;
+
                 if (this.onInputChanged) {
                 if (this.onInputChanged) {
-                    this.onInputChanged(deviceType, deviceSlot, 0, pointer[0], evt.clientX);
-                    this.onInputChanged(deviceType, deviceSlot, 1, pointer[1], evt.clientY);
-                    this.onInputChanged(deviceType, deviceSlot, evt.button + 2, pointer[evt.button + 2], 1);
+                    if (previousHorizontal !== evt.clientX) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.Horizontal, previousHorizontal, pointer[PointerInput.Horizontal]);
+                    }
+                    if (previousVertical !== evt.clientY) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.Vertical, previousVertical, pointer[PointerInput.Vertical]);
+                    }
+                    this.onInputChanged(deviceType, deviceSlot, evt.button + 2, previousButton, pointer[evt.button + 2]);
                 }
                 }
-                pointer[0] = evt.clientX;
-                pointer[1] = evt.clientY;
-                pointer[evt.button + 2] = 1;
             }
             }
         });
         });
 
 
         this._pointerUpEvent = ((evt) => {
         this._pointerUpEvent = ((evt) => {
-            const deviceType = (evt.pointerType == "mouse") ? DeviceType.Mouse : DeviceType.Touch;
-            const deviceSlot = (evt.pointerType == "mouse") ? 0 : evt.pointerId;
+            const deviceType = (evt.pointerType === "mouse") ? DeviceType.Mouse : DeviceType.Touch;
+            const deviceSlot = (evt.pointerType === "mouse") ? 0 : evt.pointerId;
 
 
             const pointer = this._inputs[deviceType][deviceSlot];
             const pointer = this._inputs[deviceType][deviceSlot];
             if (pointer) {
             if (pointer) {
-                if (this.onInputChanged) {
-                    this.onInputChanged(deviceType, deviceSlot, evt.button + 2, pointer[evt.button + 2], 0);
-                }
+                const previousHorizontal = pointer[PointerInput.Horizontal];
+                const previousVertical = pointer[PointerInput.Vertical];
+                const previousButton = pointer[evt.button + 2];
 
 
-                pointer[0] = evt.clientX;
-                pointer[1] = evt.clientY;
+                pointer[PointerInput.Horizontal] = evt.clientX;
+                pointer[PointerInput.Vertical] = evt.clientY;
                 pointer[evt.button + 2] = 0;
                 pointer[evt.button + 2] = 0;
+
+                if (this.onInputChanged) {
+                    if (previousHorizontal !== evt.clientX) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.Horizontal, previousHorizontal, pointer[PointerInput.Horizontal]);
+                    }
+                    if (previousVertical !== evt.clientY) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.Vertical, previousVertical, pointer[PointerInput.Vertical]);
+                    }
+                    this.onInputChanged(deviceType, deviceSlot, evt.button + 2, previousButton, pointer[evt.button + 2]);
+                }
             }
             }
             // We don't want to unregister the mouse because we may miss input data when a mouse is moving after a click
             // We don't want to unregister the mouse because we may miss input data when a mouse is moving after a click
-            if (evt.pointerType != "mouse") {
+            if (evt.pointerType !== "mouse") {
                 this._unregisterDevice(deviceType, deviceSlot);
                 this._unregisterDevice(deviceType, deviceSlot);
             }
             }
 
 
         });
         });
 
 
-        this._elementToAttachTo.addEventListener("pointermove", this._pointerMoveEvent);
-        this._elementToAttachTo.addEventListener("pointerdown", this._pointerDownEvent);
-        this._elementToAttachTo.addEventListener("pointerup", this._pointerUpEvent);
+        // Set Wheel Event Name, code originally from scene.inputManager
+        this._wheelEventName = "onwheel" in document.createElement("div") ? "wheel" :       // Modern browsers support "wheel"
+            (<any>document).onmousewheel !== undefined ? "mousewheel" :                     // Webkit and IE support at least "mousewheel"
+                "DOMMouseScroll";                                                           // let's assume that remaining browsers are older Firefox
+
+        // Code originally in scene.inputManager.ts
+        // Chrome reports warning in console if wheel listener doesn't set an explicit passive option.
+        // IE11 only supports captureEvent:boolean, not options:object, and it defaults to false.
+        // Feature detection technique copied from: https://github.com/github/eventlistener-polyfill (MIT license)
+        let passiveSupported = false;
+        const noop = function () { };
+
+        try {
+            const options: object = {
+                passive: {
+                    get: function () {
+                        passiveSupported = true;
+                    }
+                }
+            };
+
+            this._elementToAttachTo.addEventListener("test", noop, options);
+            this._elementToAttachTo.removeEventListener("test", noop, options);
+        }
+        catch (e) {
+            /* */
+        }
+
+        this._pointerWheelEvent = ((evt) => {
+            const deviceType = DeviceType.Mouse;
+            const deviceSlot = 0;
+
+            if (!this._inputs[deviceType]) {
+                this._inputs[deviceType] = [];
+            }
+
+            if (!this._inputs[deviceType][deviceSlot]) {
+                this._pointerActive = true;
+                this._registerDevice(deviceType, deviceSlot, DeviceInputSystem._MAX_POINTER_INPUTS);
+            }
+
+            const pointer = this._inputs[deviceType][deviceSlot];
+            if (pointer) {
+                // Store previous values for event
+                let previousWheelScrollX = pointer[PointerInput.MouseWheelX];
+                let previousWheelScrollY = pointer[PointerInput.MouseWheelY];
+                let previousWheelScrollZ = pointer[PointerInput.MouseWheelZ];
+
+                pointer[PointerInput.MouseWheelX] = evt.deltaX;
+                pointer[PointerInput.MouseWheelY] = evt.deltaY;
+                pointer[PointerInput.MouseWheelZ] = evt.deltaZ;
+
+                if (this.onInputChanged) {
+                    if (evt.deltaX !== 0) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.MouseWheelX, previousWheelScrollX, pointer[PointerInput.MouseWheelX]);
+                    }
+                    if (evt.deltaY !== 0) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.MouseWheelY, previousWheelScrollY, pointer[PointerInput.MouseWheelY]);
+                    }
+                    if (evt.deltaZ !== 0) {
+                        this.onInputChanged(deviceType, deviceSlot, PointerInput.MouseWheelZ, previousWheelScrollZ, pointer[PointerInput.MouseWheelZ]);
+                    }
+                }
+            }
+        });
+
+        this._elementToAttachTo.addEventListener(this._eventPrefix + "move", this._pointerMoveEvent);
+        this._elementToAttachTo.addEventListener(this._eventPrefix + "down", this._pointerDownEvent);
+        this._elementToAttachTo.addEventListener(this._eventPrefix + "up", this._pointerUpEvent);
+        this._elementToAttachTo.addEventListener(this._wheelEventName, this._pointerWheelEvent, passiveSupported ? { passive: false } : false);
     }
     }
 
 
     /**
     /**
@@ -380,7 +515,7 @@ export class DeviceInputSystem implements IDisposable {
         // Gamepads
         // Gamepads
         const gp = navigator.getGamepads()[deviceSlot];
         const gp = navigator.getGamepads()[deviceSlot];
 
 
-        if (gp && deviceType == this._gamepads[deviceSlot]) {
+        if (gp && deviceType === this._gamepads[deviceSlot]) {
             const device = this._inputs[deviceType][deviceSlot];
             const device = this._inputs[deviceType][deviceSlot];
 
 
             if (inputIndex >= gp.buttons.length) {
             if (inputIndex >= gp.buttons.length) {

+ 2 - 0
src/Engines/WebGPU/webgpuShaderProcessors.ts

@@ -31,6 +31,7 @@ const _knownSamplers: { [key: string]: WebGPUTextureSamplerBindingDescription }
 // TODO WEBGPU. sampler3D
 // TODO WEBGPU. sampler3D
 const _samplerFunctionByWebGLSamplerType: { [key: string]: string } = {
 const _samplerFunctionByWebGLSamplerType: { [key: string]: string } = {
     "sampler2D": "sampler2D",
     "sampler2D": "sampler2D",
+    "sampler2DArray": "sampler2DArray",
     "sampler2DShadow": "sampler2DShadow",
     "sampler2DShadow": "sampler2DShadow",
     "sampler2DArrayShadow": "sampler2DArrayShadow",
     "sampler2DArrayShadow": "sampler2DArrayShadow",
     "samplerCube": "samplerCube"
     "samplerCube": "samplerCube"
@@ -38,6 +39,7 @@ const _samplerFunctionByWebGLSamplerType: { [key: string]: string } = {
 
 
 const _textureTypeByWebGLSamplerType: { [key: string]: string } = {
 const _textureTypeByWebGLSamplerType: { [key: string]: string } = {
     "sampler2D": "texture2D",
     "sampler2D": "texture2D",
+    "sampler2DArray": "texture2DArray",
     "sampler2DShadow": "texture2D",
     "sampler2DShadow": "texture2D",
     "sampler2DArrayShadow": "texture2DArray",
     "sampler2DArrayShadow": "texture2DArray",
     "samplerCube": "textureCube",
     "samplerCube": "textureCube",

+ 4 - 2
src/Engines/WebGPU/webgpuTextureHelper.ts

@@ -1031,7 +1031,8 @@ export class WebGPUTextureHelper {
                 commandEncoder!.copyBufferToTexture({
                 commandEncoder!.copyBufferToTexture({
                     buffer: buffer,
                     buffer: buffer,
                     offset: 0,
                     offset: 0,
-                    bytesPerRow
+                    bytesPerRow,
+                    rowsPerImage: height,
                 }, textureCopyView, textureExtent);
                 }, textureCopyView, textureExtent);
 
 
                 if (useOwnCommandEncoder) {
                 if (useOwnCommandEncoder) {
@@ -1043,7 +1044,8 @@ export class WebGPUTextureHelper {
             } else {
             } else {
                 this._device.defaultQueue.writeTexture(textureCopyView, imageBitmap, {
                 this._device.defaultQueue.writeTexture(textureCopyView, imageBitmap, {
                     offset: 0,
                     offset: 0,
-                    bytesPerRow
+                    bytesPerRow,
+                    rowsPerImage: height,
                 }, textureExtent);
                 }, textureExtent);
             }
             }
 
 

+ 30 - 0
src/Engines/constants.ts

@@ -556,4 +556,34 @@ export class Constants {
      * Prefixes used by the engine for custom effects
      * Prefixes used by the engine for custom effects
      */
      */
     public static readonly CUSTOMEFFECT_PREFIX_SHADOWGENERATOR = "bjs_shadowgenerator_";
     public static readonly CUSTOMEFFECT_PREFIX_SHADOWGENERATOR = "bjs_shadowgenerator_";
+
+    /**
+     * Constant used as key code for Alt key
+     */
+    public static readonly INPUT_ALT_KEY = 18;
+
+    /**
+     * Constant used as key code for Ctrl key
+     */
+    public static readonly INPUT_CTRL_KEY = 17;
+
+    /**
+     * Constant used as key code for Meta key (Left Win, Left Cmd)
+     */
+    public static readonly INPUT_META_KEY1 = 91;
+
+    /**
+     * Constant used as key code for Meta key (Right Win)
+     */
+    public static readonly INPUT_META_KEY2 = 92;
+
+    /**
+     * Constant used as key code for Meta key (Right Win, Right Cmd)
+     */
+    public static readonly INPUT_META_KEY3 = 93;
+
+    /**
+     * Constant used as key code for Shift key
+     */
+    public static readonly INPUT_SHIFT_KEY = 16;
 }
 }

+ 2 - 1
src/Engines/engine.ts

@@ -24,6 +24,7 @@ import "./Extensions/engine.alpha";
 import "./Extensions/engine.readTexture";
 import "./Extensions/engine.readTexture";
 import "./Extensions/engine.dynamicBuffer";
 import "./Extensions/engine.dynamicBuffer";
 import { IAudioEngine } from '../Audio/Interfaces/IAudioEngine';
 import { IAudioEngine } from '../Audio/Interfaces/IAudioEngine';
+import { IPointerEvent } from "../Events/deviceInputEvents";
 
 
 declare type Material = import("../Materials/material").Material;
 declare type Material = import("../Materials/material").Material;
 declare type PostProcess = import("../PostProcesses/postProcess").PostProcess;
 declare type PostProcess = import("../PostProcesses/postProcess").PostProcess;
@@ -371,7 +372,7 @@ export class Engine extends ThinEngine {
     /**
     /**
      * Observable event triggered each time the canvas receives pointerout event
      * Observable event triggered each time the canvas receives pointerout event
      */
      */
-    public onCanvasPointerOutObservable = new Observable<PointerEvent>();
+    public onCanvasPointerOutObservable = new Observable<IPointerEvent>();
 
 
     /**
     /**
      * Observable raised when the engine begins a new frame
      * Observable raised when the engine begins a new frame

+ 16 - 0
src/Engines/nativeEngine.ts

@@ -1163,6 +1163,22 @@ export class NativeEngine extends Engine {
     }
     }
 
 
     /**
     /**
+     * Gets the client rect of native canvas.  Needed for InputManager.
+     * @returns a client rectangle
+     */
+    public getInputElementClientRect(): Nullable<ClientRect> {
+        const rect = {
+            bottom: this.getRenderHeight(),
+            height: this.getRenderHeight(),
+            left: 0,
+            right: this.getRenderWidth(),
+            top: 0,
+            width: this.getRenderWidth()
+        };
+        return rect;
+    }
+
+    /**
      * Set the z offset to apply to current rendering
      * Set the z offset to apply to current rendering
      * @param value defines the offset to apply
      * @param value defines the offset to apply
      */
      */

+ 44 - 7
src/Engines/webgpuEngine.ts

@@ -232,8 +232,6 @@ export class WebGPUEngine extends Engine {
     public dbgVerboseLogsForFirstFrames = false;
     public dbgVerboseLogsForFirstFrames = false;
     /** @hidden */
     /** @hidden */
     public dbgVerboseLogsNumFrames = 10;
     public dbgVerboseLogsNumFrames = 10;
-    /** @hidden */
-    public dbgShowWarningsNotImplemented = false;
 
 
     /**
     /**
      * Sets this to true to disable the cache for the samplers. You should do it only for testing purpose!
      * Sets this to true to disable the cache for the samplers. You should do it only for testing purpose!
@@ -1677,10 +1675,28 @@ export class WebGPUEngine extends Engine {
         var source = InternalTextureSource.Raw2DArray;
         var source = InternalTextureSource.Raw2DArray;
         var texture = new InternalTexture(this, source);
         var texture = new InternalTexture(this, source);
 
 
-        if (this.dbgShowWarningsNotImplemented) {
-            console.warn("createRawTexture2DArray not implemented yet in WebGPU");
+        texture.baseWidth = width;
+        texture.baseHeight = height;
+        texture.baseDepth = depth;
+        texture.width = width;
+        texture.height = height;
+        texture.depth = depth;
+        texture.format = format;
+        texture.type = textureType;
+        texture.generateMipMaps = generateMipMaps;
+        texture.samplingMode = samplingMode;
+        texture.is2DArray = true;
+
+        if (!this._doNotHandleContextLost) {
+            texture._bufferView = data;
         }
         }
 
 
+        this._textureHelper.createGPUTextureForInternalTexture(texture, width, height, depth);
+
+        this.updateRawTexture2DArray(texture, data, format, invertY, compression, textureType);
+
+        this._internalTexturesCache.push(texture);
+
         return texture;
         return texture;
     }
     }
 
 
@@ -2224,9 +2240,30 @@ export class WebGPUEngine extends Engine {
      * @param textureType defines the texture Type (Engine.TEXTURETYPE_UNSIGNED_INT, Engine.TEXTURETYPE_FLOAT...)
      * @param textureType defines the texture Type (Engine.TEXTURETYPE_UNSIGNED_INT, Engine.TEXTURETYPE_FLOAT...)
      */
      */
     public updateRawTexture2DArray(texture: InternalTexture, bufferView: Nullable<ArrayBufferView>, format: number, invertY: boolean, compression: Nullable<string> = null, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT): void {
     public updateRawTexture2DArray(texture: InternalTexture, bufferView: Nullable<ArrayBufferView>, format: number, invertY: boolean, compression: Nullable<string> = null, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT): void {
-        if (this.dbgShowWarningsNotImplemented) {
-            console.warn("updateRawTexture2DArray not implemented yet in WebGPU");
+        if (!this._doNotHandleContextLost) {
+            texture._bufferView = bufferView;
+            texture.format = format;
+            texture.invertY = invertY;
+            texture._compression = compression;
         }
         }
+
+        if (bufferView) {
+            const gpuTextureWrapper = texture._hardwareTexture as WebGPUHardwareTexture;
+            const needConversion = format === Constants.TEXTUREFORMAT_RGB;
+
+            if (needConversion) {
+                bufferView = _convertRGBtoRGBATextureData(bufferView, texture.width, texture.height, textureType);
+            }
+
+            const data = new Uint8Array(bufferView.buffer, bufferView.byteOffset, bufferView.byteLength);
+
+            this._textureHelper.updateTexture(data, gpuTextureWrapper.underlyingResource!, texture.width, texture.height, texture.depth, gpuTextureWrapper.format, 0, 0, invertY, false, 0, 0, this._uploadEncoder);
+            if (texture.generateMipMaps) {
+                this._generateMipmaps(texture, this._uploadEncoder);
+            }
+        }
+
+        texture.isReady = true;
     }
     }
 
 
     /**
     /**
@@ -2239,7 +2276,7 @@ export class WebGPUEngine extends Engine {
      * @param textureType defines the texture Type (Engine.TEXTURETYPE_UNSIGNED_INT, Engine.TEXTURETYPE_FLOAT...)
      * @param textureType defines the texture Type (Engine.TEXTURETYPE_UNSIGNED_INT, Engine.TEXTURETYPE_FLOAT...)
      */
      */
     public updateRawTexture3D(texture: InternalTexture, bufferView: Nullable<ArrayBufferView>, format: number, invertY: boolean, compression: Nullable<string> = null, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT): void {
     public updateRawTexture3D(texture: InternalTexture, bufferView: Nullable<ArrayBufferView>, format: number, invertY: boolean, compression: Nullable<string> = null, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT): void {
-    if (!this._doNotHandleContextLost) {
+        if (!this._doNotHandleContextLost) {
             texture._bufferView = bufferView;
             texture._bufferView = bufferView;
             texture.format = format;
             texture.format = format;
             texture.invertY = invertY;
             texture.invertY = invertY;

+ 281 - 0
src/Events/deviceInputEvents.ts

@@ -0,0 +1,281 @@
+/**
+ * Event Types
+ */
+export enum DeviceInputEventType {
+    // Pointers
+    /** PointerMove */
+    PointerMove,
+    /** PointerDown */
+    PointerDown,
+    /** PointerUp */
+    PointerUp
+}
+
+/**
+ * Native friendly interface for Event Object
+ */
+export interface IEvent {
+    // Properties
+    /**
+     * Current target for an event
+     */
+    currentTarget?: any;
+
+    /**
+     * Alias for target
+     * @deprecated
+     */
+    srcElement?: any;
+
+    /**
+     * Type of event
+     */
+    type: string;
+
+    /**
+     * Reference to object where object was dispatched
+     */
+    target: any;
+
+    // Methods
+    /**
+     * Tells user agent what to do when not explicitly handled
+     */
+    preventDefault: () => void;
+}
+
+/**
+ * Native friendly interface for UIEvent Object
+ */
+export interface IUIEvent extends IEvent {
+    // Properties
+    /**
+     * Provides current click count
+     */
+    detail: number;
+
+    /**
+     * Horizontal coordinate of event
+     */
+    pageX: number;
+
+    /**
+     * Vertical coordinate of event
+     */
+    pageY: number;
+}
+
+/**
+ * Native friendly interface for KeyboardEvent Object
+ */
+export interface IKeyboardEvent extends IUIEvent {
+    // Properties
+    /**
+     * Status of Alt key being pressed
+     */
+    altKey: boolean;
+
+    /**
+     * Unicode value of character pressed
+     * @deprecated
+     */
+    charCode?: number;
+
+    /**
+     * Code for key based on layout
+     */
+    code: string;
+
+    /**
+     * Status of Ctrl key being pressed
+     */
+    ctrlKey: boolean;
+
+    /**
+     * String representation of key
+     */
+    key: string;
+    /**
+     * ASCII value of key
+     * @deprecated
+     */
+    keyCode: number;
+
+    /**
+     * Status of Meta key (eg. Windows key) being pressed
+     */
+    metaKey: boolean;
+
+    /**
+     * Status of Shift key being pressed
+     */
+    shiftKey: boolean;
+}
+
+/**
+ * Native friendly interface for MouseEvent Object
+ */
+export interface IMouseEvent extends IUIEvent{
+    // Properties
+    /**
+     * Status of Alt key being pressed
+     */
+    altKey: boolean;
+
+    /**
+     * Value of single mouse button pressed
+     */
+    button: number;
+
+    /**
+     * Value of all mouse buttons pressed
+     */
+    buttons: number;
+
+    /**
+     * Current X coordinate
+     */
+    clientX: number;
+
+    /**
+     * Current Y coordinate
+     */
+    clientY: number;
+
+    /**
+     * Status of Ctrl key being pressed
+     */
+    ctrlKey: boolean;
+
+    /**
+     * Status of Meta key (eg. Windows key) being pressed
+     */
+    metaKey: boolean;
+
+    /**
+     * Delta of movement on X axis
+     */
+    movementX: number;
+
+    /**
+     * Delta of movement on Y axis
+     */
+    movementY: number;
+
+    /**
+     * Delta of movement on X axis
+     */
+    mozMovementX?: number;
+
+    /**
+     * Delta of movement on Y axis
+     */
+    mozMovementY?: number;
+
+    /**
+     * Delta of movement on X axis
+     */
+    msMovementX?: any;
+
+    /**
+     * Delta of movement on Y axis
+     */
+    msMovementY?: any;
+
+    /**
+     * Current coordinate of X within container
+     */
+    offsetX: number;
+
+    /**
+     * Current coordinate of Y within container
+     */
+    offsetY: number;
+
+    /**
+     * Status of Shift key being pressed
+     */
+    shiftKey: boolean;
+
+    /**
+     * Delta of movement on X axis
+     */
+    webkitMovementX?: any;
+
+    /**
+     * Delta of movement on Y axis
+     */
+    webkitMovementY?: any;
+
+    /**
+     * Alias of clientX
+     */
+    x: number;
+
+    /**
+     * Alias of clientY
+     */
+    y: number;
+}
+
+/**
+ * Native friendly interface for PointerEvent Object
+ */
+export interface IPointerEvent extends IMouseEvent {
+    // Properties
+    /**
+     * Pointer Event ID
+     */
+    pointerId: number;
+
+    /**
+     * Type of pointer
+     */
+    pointerType: string;
+}
+
+/**
+ * Native friendly interface for WheelEvent Object
+ */
+export interface IWheelEvent extends IMouseEvent {
+    // Properties
+    /**
+     * Units for delta value
+     */
+    deltaMode: number;
+
+    /**
+     * Horizontal scroll delta
+     */
+    deltaX: number;
+
+    /**
+     * Vertical scroll delta
+     */
+    deltaY: number;
+
+    /**
+     * Z-Axis scroll delta
+     */
+    deltaZ: number;
+}
+
+/**
+ * Constants used for Events
+ */
+export class EventConstants {
+    /**
+     * Pixel delta for Wheel Events (Default)
+     */
+    public static DOM_DELTA_PIXEL = 0x00;
+
+    /**
+     * Line delta for Wheel Events
+     */
+    public static DOM_DELTA_LINE = 0x01;
+
+    /**
+     * Page delta for Wheel Events
+     */
+    public static DOM_DELTA_PAGE = 0x02;
+}

+ 2 - 1
src/Events/index.ts

@@ -1,3 +1,4 @@
 export * from "./keyboardEvents";
 export * from "./keyboardEvents";
 export * from "./pointerEvents";
 export * from "./pointerEvents";
-export * from "./clipboardEvents";
+export * from "./clipboardEvents";
+export * from "./deviceInputEvents";

+ 4 - 2
src/Events/keyboardEvents.ts

@@ -1,3 +1,5 @@
+import { IKeyboardEvent } from "./deviceInputEvents";
+
 /**
 /**
  * Gather the list of keyboard event types as constants.
  * Gather the list of keyboard event types as constants.
  */
  */
@@ -30,7 +32,7 @@ export class KeyboardInfo {
         /**
         /**
          * Defines the related dom event
          * Defines the related dom event
          */
          */
-        public event: KeyboardEvent) {
+        public event: IKeyboardEvent) {
     }
     }
 }
 }
 
 
@@ -58,7 +60,7 @@ export class KeyboardInfoPre extends KeyboardInfo {
         /**
         /**
          * Defines the related dom event
          * Defines the related dom event
          */
          */
-        public event: KeyboardEvent) {
+        public event: IKeyboardEvent) {
         super(type, event);
         super(type, event);
         this.skipOnPointerObservable = false;
         this.skipOnPointerObservable = false;
     }
     }

+ 4 - 3
src/Events/pointerEvents.ts

@@ -1,6 +1,7 @@
 import { Nullable } from "../types";
 import { Nullable } from "../types";
 import { Vector2 } from "../Maths/math.vector";
 import { Vector2 } from "../Maths/math.vector";
 import { PickingInfo } from "../Collisions/pickingInfo";
 import { PickingInfo } from "../Collisions/pickingInfo";
+import { IMouseEvent } from "./deviceInputEvents";
 
 
 declare type Ray = import("../Culling/ray").Ray;
 declare type Ray = import("../Culling/ray").Ray;
 
 
@@ -55,7 +56,7 @@ export class PointerInfoBase {
         /**
         /**
          * Defines the related dom event
          * Defines the related dom event
          */
          */
-        public event: PointerEvent | MouseWheelEvent) {
+        public event: IMouseEvent) {
     }
     }
 }
 }
 
 
@@ -86,7 +87,7 @@ export class PointerInfoPre extends PointerInfoBase {
      * @param localX Defines the local x coordinates of the pointer when the event occured
      * @param localX Defines the local x coordinates of the pointer when the event occured
      * @param localY Defines the local y coordinates of the pointer when the event occured
      * @param localY Defines the local y coordinates of the pointer when the event occured
      */
      */
-    constructor(type: number, event: PointerEvent | MouseWheelEvent, localX: number, localY: number) {
+    constructor(type: number, event: IMouseEvent, localX: number, localY: number) {
         super(type, event);
         super(type, event);
         this.skipOnPointerObservable = false;
         this.skipOnPointerObservable = false;
         this.localPosition = new Vector2(localX, localY);
         this.localPosition = new Vector2(localX, localY);
@@ -105,7 +106,7 @@ export class PointerInfo extends PointerInfoBase {
      * @param pickInfo Defines the picking info associated to the info (if any)\
      * @param pickInfo Defines the picking info associated to the info (if any)\
      */
      */
     constructor(type: number,
     constructor(type: number,
-        event: PointerEvent | MouseWheelEvent,
+        event: IMouseEvent,
         /**
         /**
          * Defines the picking info associated to the info (if any)\
          * Defines the picking info associated to the info (if any)\
          */
          */

+ 129 - 135
src/Inputs/scene.inputManager.ts

@@ -1,4 +1,4 @@
-import { Observable, Observer } from "../Misc/observable";
+import { Observable } from "../Misc/observable";
 import { PointerInfoPre, PointerInfo, PointerEventTypes } from "../Events/pointerEvents";
 import { PointerInfoPre, PointerInfo, PointerEventTypes } from "../Events/pointerEvents";
 import { Nullable } from "../types";
 import { Nullable } from "../types";
 import { AbstractActionManager } from "../Actions/abstractActionManager";
 import { AbstractActionManager } from "../Actions/abstractActionManager";
@@ -7,9 +7,10 @@ import { Vector2, Matrix } from "../Maths/math.vector";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 import { Constants } from "../Engines/constants";
 import { Constants } from "../Engines/constants";
 import { ActionEvent } from "../Actions/actionEvent";
 import { ActionEvent } from "../Actions/actionEvent";
-import { Tools } from "../Misc/tools";
-import { Engine } from "../Engines/engine";
 import { KeyboardEventTypes, KeyboardInfoPre, KeyboardInfo } from "../Events/keyboardEvents";
 import { KeyboardEventTypes, KeyboardInfoPre, KeyboardInfo } from "../Events/keyboardEvents";
+import { DeviceType, PointerInput } from '../DeviceInput/InputDevices/deviceEnums';
+import { EventConstants, IKeyboardEvent, IMouseEvent, IPointerEvent, IWheelEvent } from '../Events/deviceInputEvents';
+import { DeviceInputSystem } from '../DeviceInput/deviceInputSystem';
 
 
 declare type Scene = import("../scene").Scene;
 declare type Scene = import("../scene").Scene;
 
 
@@ -65,12 +66,11 @@ export class InputManager {
     private _alreadyAttachedTo: HTMLElement;
     private _alreadyAttachedTo: HTMLElement;
 
 
     // Pointers
     // Pointers
-    private _wheelEventName = "";
-    private _onPointerMove: (evt: PointerEvent) => void;
-    private _onPointerDown: (evt: PointerEvent) => void;
-    private _onPointerUp: (evt: PointerEvent) => void;
+    private _onPointerMove: (evt: IMouseEvent) => void;
+    private _onPointerDown: (evt: IPointerEvent) => void;
+    private _onPointerUp: (evt: IPointerEvent) => void;
 
 
-    private _initClickEvent: (obs1: Observable<PointerInfoPre>, obs2: Observable<PointerInfo>, evt: PointerEvent, cb: (clickInfo: _ClickInfo, pickResult: Nullable<PickingInfo>) => void) => void;
+    private _initClickEvent: (obs1: Observable<PointerInfoPre>, obs2: Observable<PointerInfo>, evt: IPointerEvent, cb: (clickInfo: _ClickInfo, pickResult: Nullable<PickingInfo>) => void) => void;
     private _initActionManager: (act: Nullable<AbstractActionManager>, clickInfo: _ClickInfo) => Nullable<AbstractActionManager>;
     private _initActionManager: (act: Nullable<AbstractActionManager>, clickInfo: _ClickInfo) => Nullable<AbstractActionManager>;
     private _delayedSimpleClick: (btn: number, clickInfo: _ClickInfo, cb: (clickInfo: _ClickInfo, pickResult: Nullable<PickingInfo>) => void) => void;
     private _delayedSimpleClick: (btn: number, clickInfo: _ClickInfo, cb: (clickInfo: _ClickInfo, pickResult: Nullable<PickingInfo>) => void) => void;
     private _delayedSimpleClickTimeout: number;
     private _delayedSimpleClickTimeout: number;
@@ -97,17 +97,14 @@ export class InputManager {
     private _startingPointerTime = 0;
     private _startingPointerTime = 0;
     private _previousStartingPointerTime = 0;
     private _previousStartingPointerTime = 0;
     private _pointerCaptures: { [pointerId: number]: boolean } = {};
     private _pointerCaptures: { [pointerId: number]: boolean } = {};
-
     private _meshUnderPointerId: Nullable<AbstractMesh>[] = [];
     private _meshUnderPointerId: Nullable<AbstractMesh>[] = [];
 
 
     // Keyboard
     // Keyboard
-    private _onKeyDown: (evt: KeyboardEvent) => void;
-    private _onKeyUp: (evt: KeyboardEvent) => void;
-    private _keyboardIsAttached = false;
-    private _onCanvasFocusObserver: Nullable<Observer<Engine>>;
-    private _onCanvasBlurObserver: Nullable<Observer<Engine>>;
+    private _onKeyDown: (evt: IKeyboardEvent) => void;
+    private _onKeyUp: (evt: IKeyboardEvent) => void;
 
 
     private _scene: Scene;
     private _scene: Scene;
+    private _deviceInputSystem: DeviceInputSystem;
 
 
     /**
     /**
      * Creates a new InputManager
      * Creates a new InputManager
@@ -162,7 +159,7 @@ export class InputManager {
         this._pointerY = value;
         this._pointerY = value;
     }
     }
 
 
-    private _updatePointerPosition(evt: PointerEvent): void {
+    private _updatePointerPosition(evt: IPointerEvent): void {
         var canvasRect = this._scene.getEngine().getInputElementClientRect();
         var canvasRect = this._scene.getEngine().getInputElementClientRect();
 
 
         if (!canvasRect) {
         if (!canvasRect) {
@@ -176,7 +173,7 @@ export class InputManager {
         this._unTranslatedPointerY = this._pointerY;
         this._unTranslatedPointerY = this._pointerY;
     }
     }
 
 
-    private _processPointerMove(pickResult: Nullable<PickingInfo>, evt: PointerEvent) {
+    private _processPointerMove(pickResult: Nullable<PickingInfo>, evt: IPointerEvent) {
         let scene = this._scene;
         let scene = this._scene;
         let engine = scene.getEngine();
         let engine = scene.getEngine();
         var canvas = engine.getInputElement();
         var canvas = engine.getInputElement();
@@ -214,7 +211,7 @@ export class InputManager {
         }
         }
 
 
         if (pickResult) {
         if (pickResult) {
-            let type = evt.type === this._wheelEventName ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE;
+            let type = evt.type === "wheel" ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE;
 
 
             if (scene.onPointerMove) {
             if (scene.onPointerMove) {
                 scene.onPointerMove(evt, pickResult, type);
                 scene.onPointerMove(evt, pickResult, type);
@@ -238,7 +235,7 @@ export class InputManager {
         }
         }
     }
     }
 
 
-    private _checkPrePointerObservable(pickResult: Nullable<PickingInfo>, evt: PointerEvent, type: number) {
+    private _checkPrePointerObservable(pickResult: Nullable<PickingInfo>, evt: IPointerEvent, type: number) {
         let scene = this._scene;
         let scene = this._scene;
         let pi = new PointerInfoPre(type, evt, this._unTranslatedPointerX, this._unTranslatedPointerY);
         let pi = new PointerInfoPre(type, evt, this._unTranslatedPointerX, this._unTranslatedPointerY);
         if (pickResult) {
         if (pickResult) {
@@ -283,7 +280,7 @@ export class InputManager {
         this._processPointerDown(pickResult, evt);
         this._processPointerDown(pickResult, evt);
     }
     }
 
 
-    private _processPointerDown(pickResult: Nullable<PickingInfo>, evt: PointerEvent): void {
+    private _processPointerDown(pickResult: Nullable<PickingInfo>, evt: IPointerEvent): void {
         let scene = this._scene;
         let scene = this._scene;
         if (pickResult && pickResult.hit && pickResult.pickedMesh) {
         if (pickResult && pickResult.hit && pickResult.pickedMesh) {
             this._pickedDownMesh = pickResult.pickedMesh;
             this._pickedDownMesh = pickResult.pickedMesh;
@@ -309,7 +306,7 @@ export class InputManager {
                         var pickResult = scene.pick(
                         var pickResult = scene.pick(
                             this._unTranslatedPointerX,
                             this._unTranslatedPointerX,
                             this._unTranslatedPointerY,
                             this._unTranslatedPointerY,
-                            (mesh: AbstractMesh): boolean => <boolean>(mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasSpecificTrigger(Constants.ACTION_OnLongPressTrigger) && mesh == this._pickedDownMesh),
+                            (mesh: AbstractMesh): boolean => <boolean>(mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasSpecificTrigger(Constants.ACTION_OnLongPressTrigger) && mesh === this._pickedDownMesh),
                             false,
                             false,
                             scene.cameraToUseForPointers
                             scene.cameraToUseForPointers
                         );
                         );
@@ -373,7 +370,7 @@ export class InputManager {
         this._processPointerUp(pickResult, evt, clickInfo);
         this._processPointerUp(pickResult, evt, clickInfo);
     }
     }
 
 
-    private _processPointerUp(pickResult: Nullable<PickingInfo>, evt: PointerEvent, clickInfo: _ClickInfo): void {
+    private _processPointerUp(pickResult: Nullable<PickingInfo>, evt: IPointerEvent, clickInfo: _ClickInfo): void {
         let scene = this._scene;
         let scene = this._scene;
         if (pickResult && pickResult && pickResult.pickedMesh) {
         if (pickResult && pickResult && pickResult.pickedMesh) {
             this._pickedUpMesh = pickResult.pickedMesh;
             this._pickedUpMesh = pickResult.pickedMesh;
@@ -478,6 +475,8 @@ export class InputManager {
         this._alreadyAttachedTo = elementToAttachTo;
         this._alreadyAttachedTo = elementToAttachTo;
         let engine = scene.getEngine();
         let engine = scene.getEngine();
 
 
+        this._deviceInputSystem = DeviceInputSystem.Create(engine);
+
         this._initActionManager = (act: Nullable<AbstractActionManager>, clickInfo: _ClickInfo): Nullable<AbstractActionManager> => {
         this._initActionManager = (act: Nullable<AbstractActionManager>, clickInfo: _ClickInfo): Nullable<AbstractActionManager> => {
             if (!this._meshPickProceed) {
             if (!this._meshPickProceed) {
                 let pickResult = scene.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, scene.pointerDownPredicate, false, scene.cameraToUseForPointers);
                 let pickResult = scene.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, scene.pointerDownPredicate, false, scene.cameraToUseForPointers);
@@ -500,7 +499,7 @@ export class InputManager {
             }
             }
         };
         };
 
 
-        this._initClickEvent = (obs1: Observable<PointerInfoPre>, obs2: Observable<PointerInfo>, evt: PointerEvent, cb: (clickInfo: _ClickInfo, pickResult: Nullable<PickingInfo>) => void): void => {
+        this._initClickEvent = (obs1: Observable<PointerInfoPre>, obs2: Observable<PointerInfo>, evt: IPointerEvent, cb: (clickInfo: _ClickInfo, pickResult: Nullable<PickingInfo>) => void): void => {
             let clickInfo = new _ClickInfo();
             let clickInfo = new _ClickInfo();
             this._currentPickResult = null;
             this._currentPickResult = null;
             let act: Nullable<AbstractActionManager> = null;
             let act: Nullable<AbstractActionManager> = null;
@@ -602,7 +601,7 @@ export class InputManager {
                             this._previousStartingPointerTime = this._startingPointerTime;
                             this._previousStartingPointerTime = this._startingPointerTime;
                             this._previousStartingPointerPosition.x = this._startingPointerPosition.x;
                             this._previousStartingPointerPosition.x = this._startingPointerPosition.x;
                             this._previousStartingPointerPosition.y = this._startingPointerPosition.y;
                             this._previousStartingPointerPosition.y = this._startingPointerPosition.y;
-                            this._previousButtonPressed = btn;
+                            this._previousButtonPressed = btn!;
                         }
                         }
                     }
                     }
                 }
                 }
@@ -613,16 +612,16 @@ export class InputManager {
             }
             }
         };
         };
 
 
-        this._onPointerMove = (evt: PointerEvent) => {
+        this._onPointerMove = (evt: IMouseEvent) => {
             // preserve compatibility with Safari when pointerId is not present
             // preserve compatibility with Safari when pointerId is not present
-            if (evt.pointerId === undefined) {
-                (evt as any).pointerId = 0;
+            if ((evt as IPointerEvent).pointerId === undefined) {
+                ((evt as IPointerEvent) as any).pointerId = 0;
             }
             }
 
 
-            this._updatePointerPosition(evt);
+            this._updatePointerPosition((evt as IPointerEvent));
 
 
             // PreObservable support
             // PreObservable support
-            if (this._checkPrePointerObservable(null, evt, evt.type === this._wheelEventName ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE)) {
+            if (this._checkPrePointerObservable(null, (evt as IPointerEvent), evt.type === "wheel" ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE)) {
                 return;
                 return;
             }
             }
 
 
@@ -636,17 +635,17 @@ export class InputManager {
                     mesh.isVisible &&
                     mesh.isVisible &&
                     mesh.isReady() &&
                     mesh.isReady() &&
                     mesh.isEnabled() &&
                     mesh.isEnabled() &&
-                    (mesh.enablePointerMoveEvents || scene.constantlyUpdateMeshUnderPointer || mesh._getActionManagerForTrigger() != null) &&
+                    (mesh.enablePointerMoveEvents || scene.constantlyUpdateMeshUnderPointer || mesh._getActionManagerForTrigger() !== null) &&
                     (!scene.cameraToUseForPointers || (scene.cameraToUseForPointers.layerMask & mesh.layerMask) !== 0);
                     (!scene.cameraToUseForPointers || (scene.cameraToUseForPointers.layerMask & mesh.layerMask) !== 0);
             }
             }
 
 
             // Meshes
             // Meshes
             var pickResult = scene.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, scene.pointerMovePredicate, false, scene.cameraToUseForPointers);
             var pickResult = scene.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, scene.pointerMovePredicate, false, scene.cameraToUseForPointers);
 
 
-            this._processPointerMove(pickResult, evt);
+            this._processPointerMove(pickResult, (evt as IPointerEvent));
         };
         };
 
 
-        this._onPointerDown = (evt: PointerEvent) => {
+        this._onPointerDown = (evt: IPointerEvent) => {
             this._totalPointersPressed++;
             this._totalPointersPressed++;
             this._pickedDownMesh = null;
             this._pickedDownMesh = null;
             this._meshPickProceed = false;
             this._meshPickProceed = false;
@@ -658,8 +657,7 @@ export class InputManager {
 
 
             this._updatePointerPosition(evt);
             this._updatePointerPosition(evt);
 
 
-            if (scene.preventDefaultOnPointerDown && elementToAttachTo) {
-                evt.preventDefault();
+            if (scene.preventDefaultOnPointerDown && elementToAttachTo) { // TODO: DO WE NEED THIS?
                 elementToAttachTo.focus();
                 elementToAttachTo.focus();
             }
             }
 
 
@@ -691,7 +689,7 @@ export class InputManager {
             this._processPointerDown(pickResult, evt);
             this._processPointerDown(pickResult, evt);
         };
         };
 
 
-        this._onPointerUp = (evt: PointerEvent) => {
+        this._onPointerUp = (evt: IPointerEvent) => {
             if (this._totalPointersPressed === 0) {
             if (this._totalPointersPressed === 0) {
                 // We are attaching the pointer up to windows because of a bug in FF
                 // We are attaching the pointer up to windows because of a bug in FF
                 return; // So we need to test it the pointer down was pressed before.
                 return; // So we need to test it the pointer down was pressed before.
@@ -708,8 +706,7 @@ export class InputManager {
 
 
             this._updatePointerPosition(evt);
             this._updatePointerPosition(evt);
 
 
-            if (scene.preventDefaultOnPointerUp && elementToAttachTo) {
-                evt.preventDefault();
+            if (scene.preventDefaultOnPointerUp && elementToAttachTo) { // TODO: DO WE NEED THIS?
                 elementToAttachTo.focus();
                 elementToAttachTo.focus();
             }
             }
 
 
@@ -764,7 +761,7 @@ export class InputManager {
             });
             });
         };
         };
 
 
-        this._onKeyDown = (evt: KeyboardEvent) => {
+        this._onKeyDown = (evt: IKeyboardEvent) => {
             let type = KeyboardEventTypes.KEYDOWN;
             let type = KeyboardEventTypes.KEYDOWN;
             if (scene.onPreKeyboardObservable.hasObservers()) {
             if (scene.onPreKeyboardObservable.hasObservers()) {
                 let pi = new KeyboardInfoPre(type, evt);
                 let pi = new KeyboardInfoPre(type, evt);
@@ -784,7 +781,7 @@ export class InputManager {
             }
             }
         };
         };
 
 
-        this._onKeyUp = (evt: KeyboardEvent) => {
+        this._onKeyUp = (evt: IKeyboardEvent) => {
             let type = KeyboardEventTypes.KEYUP;
             let type = KeyboardEventTypes.KEYUP;
             if (scene.onPreKeyboardObservable.hasObservers()) {
             if (scene.onPreKeyboardObservable.hasObservers()) {
                 let pi = new KeyboardInfoPre(type, evt);
                 let pi = new KeyboardInfoPre(type, evt);
@@ -804,84 +801,106 @@ export class InputManager {
             }
             }
         };
         };
 
 
-        let attachedFunction = () => {
-            if (!elementToAttachTo || this._keyboardIsAttached) {
-                return;
+        this._deviceInputSystem.onInputChanged = (deviceType, deviceSlot, inputIndex, previousState, currentState) => {
+            let isKeyboardActive = this._deviceInputSystem.isDeviceAvailable(DeviceType.Keyboard);
+
+            const altKey = (isKeyboardActive && this._deviceInputSystem.pollInput(DeviceType.Keyboard, 0, Constants.INPUT_ALT_KEY) === 1);
+            const ctrlKey = (isKeyboardActive && this._deviceInputSystem.pollInput(DeviceType.Keyboard, 0, Constants.INPUT_CTRL_KEY) === 1);
+            const metaKey = (isKeyboardActive && (this._deviceInputSystem.pollInput(DeviceType.Keyboard, 0, Constants.INPUT_META_KEY1) === 1
+                || this._deviceInputSystem.pollInput(DeviceType.Keyboard, 0, Constants.INPUT_META_KEY2) === 1
+                || this._deviceInputSystem.pollInput(DeviceType.Keyboard, 0, Constants.INPUT_META_KEY3) === 1));
+            const shiftKey = (isKeyboardActive && this._deviceInputSystem.pollInput(DeviceType.Keyboard, 0, Constants.INPUT_SHIFT_KEY) === 1);
+
+            const evt: {[k: string]: any} = {};
+
+            evt.target = elementToAttachTo;
+            evt.preventDefault = () => { },
+            evt.altKey = altKey;
+            evt.ctrlKey = ctrlKey;
+            evt.metaKey = metaKey;
+            evt.shiftKey = shiftKey;
+
+            // Keyboard Events
+            if (deviceType === DeviceType.Keyboard) {
+                evt.type = ((currentState === 1) ? "keydown" : "keyup");
+                evt.key = String.fromCharCode(inputIndex);
+                evt.keyCode = inputIndex;
+
+                if (currentState === 1) {
+                    this._onKeyDown((evt as IKeyboardEvent));
+                }
+
+                if (currentState === 0) {
+                    this._onKeyUp((evt as IKeyboardEvent));
+                }
             }
             }
-            elementToAttachTo.addEventListener("keydown", this._onKeyDown, false);
-            elementToAttachTo.addEventListener("keyup", this._onKeyUp, false);
-            this._keyboardIsAttached = true;
-        };
 
 
-        // Keyboard events
-        this._onCanvasFocusObserver = engine.onCanvasFocusObservable.add(
-            (() => {
-                if (document.activeElement === elementToAttachTo) {
-                    attachedFunction();
+            // Pointer Events
+            if (deviceType === DeviceType.Mouse || deviceType === DeviceType.Touch) {
+                const pointerX = this._deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.Horizontal);
+                const pointerY = this._deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.Vertical);
+                // If dealing with a change to the delta, grab values for event init
+                const movementX = (inputIndex === PointerInput.DeltaHorizontal) ? currentState : 0;
+                const movementY = (inputIndex === PointerInput.DeltaVertical) ? currentState : 0;
+                // Get offsets from container
+                const offsetX = (inputIndex === PointerInput.DeltaHorizontal && elementToAttachTo) ? movementX! - elementToAttachTo.getBoundingClientRect().x : 0;
+                const offsetY = (inputIndex === PointerInput.DeltaVertical && elementToAttachTo) ? movementY! - elementToAttachTo.getBoundingClientRect().y : 0;
+
+                evt.pointerId = (deviceType === DeviceType.Mouse ? 1 : deviceSlot);
+                evt.clientX = pointerX;
+                evt.clientY = pointerY;
+                evt.movementX = movementX;
+                evt.movementY = movementY;
+                evt.offsetX = offsetX;
+                evt.offsetY = offsetY;
+                evt.x = pointerX;
+                evt.y = pointerY;
+
+                if (attachDown && inputIndex >= PointerInput.LeftClick && inputIndex <= PointerInput.RightClick && currentState === 1) {   // Pointer Down
+                    evt.type = "pointerdown";
+                    evt.button = (inputIndex - 2);
+
+                    this._onPointerDown((evt as IPointerEvent));
                 }
                 }
-                return attachedFunction;
-            })()
-        );
 
 
-        this._onCanvasBlurObserver = engine.onCanvasBlurObservable.add(() => {
-            if (!elementToAttachTo) {
-                return;
-            }
-            elementToAttachTo.removeEventListener("keydown", this._onKeyDown);
-            elementToAttachTo.removeEventListener("keyup", this._onKeyUp);
-            this._keyboardIsAttached = false;
-        });
-
-        attachedFunction();
-
-        // Pointer events
-        var eventPrefix = Tools.GetPointerPrefix(engine);
-
-        if (attachMove) {
-            elementToAttachTo.addEventListener(eventPrefix + "move", <any>this._onPointerMove, false);
-
-            // Wheel
-            this._wheelEventName =
-                "onwheel" in document.createElement("div")
-                    ? "wheel" // Modern browsers support "wheel"
-                    : (<any>document).onmousewheel !== undefined
-                    ? "mousewheel" // Webkit and IE support at least "mousewheel"
-                    : "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox
-
-            // Chrome reports warning in console if wheel listener doesn't set an explicit passive option.
-            // IE11 only supports captureEvent:boolean, not options:object, and it defaults to false.
-            // Feature detection technique copied from: https://github.com/github/eventlistener-polyfill (MIT license)
-            // ----------
-            var passiveSupported = false;
-            var noop = function () {};
-            try {
-                var options: object = {
-                        passive: {
-                            get: function () {
-                                passiveSupported = true;
-                            }
-                        }
-                    };
-                elementToAttachTo.addEventListener("test", noop, options);
-                elementToAttachTo.removeEventListener("test", noop, options);
-            } catch (e) {
-                /* */
-            }
-            // ----------
+                if (attachUp && inputIndex >= PointerInput.LeftClick && inputIndex <= PointerInput.RightClick && currentState === 0) {   // Pointer Up
+                    evt.type = "pointerup";
+                    evt.button = (inputIndex - 2);
 
 
-            elementToAttachTo.addEventListener(this._wheelEventName, <any>this._onPointerMove, passiveSupported ? { passive: false } : false);
-        }
+                    this._onPointerUp((evt as IPointerEvent));
+                }
 
 
-        if (attachDown) {
-            elementToAttachTo.addEventListener(eventPrefix + "down", <any>this._onPointerDown, false);
-        }
+                if (attachMove) {
+                    if (inputIndex === PointerInput.Horizontal || inputIndex === PointerInput.Vertical || inputIndex === PointerInput.DeltaHorizontal || inputIndex === PointerInput.DeltaVertical) {
+                        evt.type = "pointermove";
 
 
-        if (attachUp) {
-            let hostWindow = scene.getEngine().getHostWindow();
-            if (hostWindow) {
-                hostWindow.addEventListener(eventPrefix + "up", <any>this._onPointerUp, false);
+                        this._onPointerMove((evt as IPointerEvent));
+                    }
+                    else if (inputIndex === PointerInput.MouseWheelX || inputIndex === PointerInput.MouseWheelY || inputIndex === PointerInput.MouseWheelZ) {
+                        /*
+                         * Since wheel inputs stay until they are read, we'll read everything at once.  We'll then fire off
+                         * a move event if any of them are not zero.  This will allow us to only fire off events with a proper
+                         * delta.
+                         */
+                        const deltaX = this._deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.MouseWheelX);
+                        const deltaY = this._deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.MouseWheelY);
+                        const deltaZ = this._deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.MouseWheelZ);
+
+                        evt.type = "wheel";
+                        evt.deltaMode = EventConstants.DOM_DELTA_PIXEL;
+                        evt.deltaX = deltaX;
+                        evt.deltaY = deltaY;
+                        evt.deltaZ = deltaZ;
+
+                        // If we have a delta, use it.
+                        if (deltaX !== 0 || deltaY !== 0 || deltaZ !== 0) {
+                            this._onPointerMove((evt as IWheelEvent));
+                        }
+                    }
+                }
             }
             }
-        }
+        };
+
         this._alreadyAttached = true;
         this._alreadyAttached = true;
     }
     }
 
 
@@ -889,36 +908,11 @@ export class InputManager {
      * Detaches all event handlers
      * Detaches all event handlers
      */
      */
     public detachControl() {
     public detachControl() {
-        const engine = this._scene.getEngine();
-        const eventPrefix = Tools.GetPointerPrefix(engine);
-
-        if (!this._alreadyAttachedTo) {
+        if (!this._alreadyAttachedTo || !this._alreadyAttached) {
             return;
             return;
         }
         }
 
 
-        if (!this._alreadyAttached) {
-            return;
-        }
-
-        // Pointer
-        this._alreadyAttachedTo.removeEventListener(eventPrefix + "move", <any>this._onPointerMove);
-        this._alreadyAttachedTo.removeEventListener(this._wheelEventName, <any>this._onPointerMove);
-        this._alreadyAttachedTo.removeEventListener(eventPrefix + "down", <any>this._onPointerDown);
-        window.removeEventListener(eventPrefix + "up", <any>this._onPointerUp);
-
-        // Blur / Focus
-        if (this._onCanvasBlurObserver) {
-            engine.onCanvasBlurObservable.remove(this._onCanvasBlurObserver);
-        }
-
-        if (this._onCanvasFocusObserver) {
-            engine.onCanvasFocusObservable.remove(this._onCanvasFocusObserver);
-        }
-
-        // Keyboard
-        this._alreadyAttachedTo.removeEventListener("keydown", this._onKeyDown);
-        this._alreadyAttachedTo.removeEventListener("keyup", this._onKeyUp);
-        this._keyboardIsAttached = false;
+        this._deviceInputSystem.dispose();
 
 
         // Cursor
         // Cursor
         if (!this._scene.doNotHandleCursors) {
         if (!this._scene.doNotHandleCursors) {

+ 4 - 4
src/Materials/Node/Blocks/Vertex/morphTargetsBlock.ts

@@ -188,7 +188,7 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
         for (var index = 0; index < repeatCount; index++) {
         for (var index = 0; index < repeatCount; index++) {
             injectionCode += `#ifdef MORPHTARGETS\r\n`;
             injectionCode += `#ifdef MORPHTARGETS\r\n`;
             if (manager?.isUsingTextureForTargets) {
             if (manager?.isUsingTextureForTargets) {
-                injectionCode += `${positionOutput.associatedVariableName} += (readVector3FromRawSampler(morphTargets[${index}], vertexID) - ${position.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
+                injectionCode += `${positionOutput.associatedVariableName} += (readVector3FromRawSampler(${index}., vertexID) - ${position.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
                 injectionCode += `vertexID += 1.0;\r\n`;
                 injectionCode += `vertexID += 1.0;\r\n`;
             } else {
             } else {
                 injectionCode += `${positionOutput.associatedVariableName} += (position${index} - ${position.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
                 injectionCode += `${positionOutput.associatedVariableName} += (position${index} - ${position.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
@@ -197,7 +197,7 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
             if (hasNormals) {
             if (hasNormals) {
                 injectionCode += `#ifdef MORPHTARGETS_NORMAL\r\n`;
                 injectionCode += `#ifdef MORPHTARGETS_NORMAL\r\n`;
                 if (manager?.isUsingTextureForTargets) {
                 if (manager?.isUsingTextureForTargets) {
-                    injectionCode += `${normalOutput.associatedVariableName} += (readVector3FromRawSampler(morphTargets[${index}], vertexID) - ${normal.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
+                    injectionCode += `${normalOutput.associatedVariableName} += (readVector3FromRawSampler(${index}., vertexID) - ${normal.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
                     injectionCode += `vertexID += 1.0;\r\n`;
                     injectionCode += `vertexID += 1.0;\r\n`;
                 } else {
                 } else {
                     injectionCode += `${normalOutput.associatedVariableName} += (normal${index} - ${normal.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
                     injectionCode += `${normalOutput.associatedVariableName} += (normal${index} - ${normal.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
@@ -208,7 +208,7 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
             if (hasUVs) {
             if (hasUVs) {
                 injectionCode += `#ifdef MORPHTARGETS_UV\r\n`;
                 injectionCode += `#ifdef MORPHTARGETS_UV\r\n`;
                 if (manager?.isUsingTextureForTargets) {
                 if (manager?.isUsingTextureForTargets) {
-                    injectionCode += `${uvOutput.associatedVariableName} += (readVector3FromRawSampler(morphTargets[${index}], vertexID).xy - ${uv.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
+                    injectionCode += `${uvOutput.associatedVariableName} += (readVector3FromRawSampler(${index}., vertexID).xy - ${uv.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
                     injectionCode += `vertexID += 1.0;\r\n`;
                     injectionCode += `vertexID += 1.0;\r\n`;
                 } else {
                 } else {
                     injectionCode += `${uvOutput.associatedVariableName}.xy += (uv_${index} - ${uv.associatedVariableName}.xy) * morphTargetInfluences[${index}];\r\n`;
                     injectionCode += `${uvOutput.associatedVariableName}.xy += (uv_${index} - ${uv.associatedVariableName}.xy) * morphTargetInfluences[${index}];\r\n`;
@@ -219,7 +219,7 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
             if (hasTangents) {
             if (hasTangents) {
                 injectionCode += `#ifdef MORPHTARGETS_TANGENT\r\n`;
                 injectionCode += `#ifdef MORPHTARGETS_TANGENT\r\n`;
                 if (manager?.isUsingTextureForTargets) {
                 if (manager?.isUsingTextureForTargets) {
-                    injectionCode += `${tangentOutput.associatedVariableName} += (readVector3FromRawSampler(morphTargets[${index}], vertexID) - ${tangent.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
+                    injectionCode += `${tangentOutput.associatedVariableName} += (readVector3FromRawSampler(${index}., vertexID) - ${tangent.associatedVariableName}) * morphTargetInfluences[${index}];\r\n`;
                 } else {
                 } else {
                     injectionCode += `${tangentOutput.associatedVariableName}.xyz += (tangent${index} - ${tangent.associatedVariableName}.xyz) * morphTargetInfluences[${index}];\r\n`;
                     injectionCode += `${tangentOutput.associatedVariableName}.xyz += (tangent${index} - ${tangent.associatedVariableName}.xyz) * morphTargetInfluences[${index}];\r\n`;
                 }
                 }

+ 20 - 0
src/Meshes/mesh.ts

@@ -111,6 +111,7 @@ class _InternalMeshDataInfo {
     public _onBeforeBindObservable: Nullable<Observable<Mesh>>;
     public _onBeforeBindObservable: Nullable<Observable<Mesh>>;
     public _onAfterRenderObservable: Nullable<Observable<Mesh>>;
     public _onAfterRenderObservable: Nullable<Observable<Mesh>>;
     public _onBeforeDrawObservable: Nullable<Observable<Mesh>>;
     public _onBeforeDrawObservable: Nullable<Observable<Mesh>>;
+    public _onBetweenPassObservable: Nullable<Observable<Mesh>>;
 
 
     public _areNormalsFrozen: boolean = false; // Will be used by ribbons mainly
     public _areNormalsFrozen: boolean = false; // Will be used by ribbons mainly
     public _sourcePositions: Float32Array; // Will be used to save original positions when using software skinning
     public _sourcePositions: Float32Array; // Will be used to save original positions when using software skinning
@@ -283,6 +284,17 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
     }
     }
 
 
     /**
     /**
+    * An event triggeredbetween rendering pass wneh using separateCullingPass = true
+    */
+   public get onBetweenPassObservable(): Observable<Mesh> {
+    if (!this._internalMeshDataInfo._onBetweenPassObservable) {
+        this._internalMeshDataInfo._onBetweenPassObservable = new Observable<Mesh>();
+    }
+
+    return this._internalMeshDataInfo._onBetweenPassObservable;
+}
+
+    /**
     * An event triggered before drawing the mesh
     * An event triggered before drawing the mesh
     */
     */
     public get onBeforeDrawObservable(): Observable<Mesh> {
     public get onBeforeDrawObservable(): Observable<Mesh> {
@@ -1997,6 +2009,10 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
             engine.setState(true, this._effectiveMaterial.zOffset, false, !reverse);
             engine.setState(true, this._effectiveMaterial.zOffset, false, !reverse);
             this._processRendering(this, subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, this._effectiveMaterial);
             this._processRendering(this, subMesh, effect, fillMode, batch, hardwareInstancedRendering, this._onBeforeDraw, this._effectiveMaterial);
             engine.setState(true, this._effectiveMaterial.zOffset, false, reverse);
             engine.setState(true, this._effectiveMaterial.zOffset, false, reverse);
+
+            if (this._internalMeshDataInfo._onBetweenPassObservable) {
+                this._internalMeshDataInfo._onBetweenPassObservable.notifyObservers(this);
+            }
         }
         }
 
 
         // Draw
         // Draw
@@ -2422,6 +2438,10 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
             internalDataInfo._onAfterRenderObservable.clear();
             internalDataInfo._onAfterRenderObservable.clear();
         }
         }
 
 
+        if (internalDataInfo._onBetweenPassObservable) {
+            internalDataInfo._onBetweenPassObservable.clear();
+        }
+
         // Sources
         // Sources
         if (this._scene.useClonedMeshMap) {
         if (this._scene.useClonedMeshMap) {
             if (internalDataInfo.meshMap) {
             if (internalDataInfo.meshMap) {

+ 4 - 4
src/Meshes/thinInstanceMesh.ts

@@ -15,14 +15,14 @@ declare module "./mesh" {
          * @param refresh true to refresh the underlying gpu buffer (default: true). If you do multiple calls to this method in a row, set refresh to true only for the last call to save performance
          * @param refresh true to refresh the underlying gpu buffer (default: true). If you do multiple calls to this method in a row, set refresh to true only for the last call to save performance
          * @returns the thin instance index number. If you pass an array of matrices, other instance indexes are index+1, index+2, etc
          * @returns the thin instance index number. If you pass an array of matrices, other instance indexes are index+1, index+2, etc
          */
          */
-        thinInstanceAdd(matrix: DeepImmutableObject<Matrix> | Array<DeepImmutableObject<Matrix>>, refresh: boolean): number;
+        thinInstanceAdd(matrix: DeepImmutableObject<Matrix> | Array<DeepImmutableObject<Matrix>>, refresh?: boolean): number;
 
 
         /**
         /**
          * Adds the transformation (matrix) of the current mesh as a thin instance
          * Adds the transformation (matrix) of the current mesh as a thin instance
          * @param refresh true to refresh the underlying gpu buffer (default: true). If you do multiple calls to this method in a row, set refresh to true only for the last call to save performance
          * @param refresh true to refresh the underlying gpu buffer (default: true). If you do multiple calls to this method in a row, set refresh to true only for the last call to save performance
          * @returns the thin instance index number
          * @returns the thin instance index number
          */
          */
-        thinInstanceAddSelf(refresh: boolean): number;
+        thinInstanceAddSelf(refresh?: boolean): number;
 
 
         /**
         /**
          * Registers a custom attribute to be used with thin instances
          * Registers a custom attribute to be used with thin instances
@@ -37,7 +37,7 @@ declare module "./mesh" {
          * @param matrix matrix to set
          * @param matrix matrix to set
          * @param refresh true to refresh the underlying gpu buffer (default: true). If you do multiple calls to this method in a row, set refresh to true only for the last call to save performance
          * @param refresh true to refresh the underlying gpu buffer (default: true). If you do multiple calls to this method in a row, set refresh to true only for the last call to save performance
          */
          */
-        thinInstanceSetMatrixAt(index: number, matrix: DeepImmutableObject<Matrix>, refresh: boolean): void;
+        thinInstanceSetMatrixAt(index: number, matrix: DeepImmutableObject<Matrix>, refresh?: boolean): void;
 
 
         /**
         /**
          * Sets the value of a custom attribute for a thin instance
          * Sets the value of a custom attribute for a thin instance
@@ -46,7 +46,7 @@ declare module "./mesh" {
          * @param value value to set
          * @param value value to set
          * @param refresh true to refresh the underlying gpu buffer (default: true). If you do multiple calls to this method in a row, set refresh to true only for the last call to save performance
          * @param refresh true to refresh the underlying gpu buffer (default: true). If you do multiple calls to this method in a row, set refresh to true only for the last call to save performance
          */
          */
-        thinInstanceSetAttributeAt(kind: string, index: number, value: Array<number>, refresh: boolean): void;
+        thinInstanceSetAttributeAt(kind: string, index: number, value: Array<number>, refresh?: boolean): void;
 
 
         /**
         /**
          * Gets / sets the number of thin instances to display. Note that you can't set a number higher than what the underlying buffer can handle.
          * Gets / sets the number of thin instances to display. Note that you can't set a number higher than what the underlying buffer can handle.

+ 1 - 1
src/Shaders/ShadersInclude/morphTargetsVertexGlobalDeclaration.fx

@@ -10,7 +10,7 @@
 		{			
 		{			
 			float y = floor(vertexIndex / morphTargetTextureInfo.y);
 			float y = floor(vertexIndex / morphTargetTextureInfo.y);
 			float x = vertexIndex - y * morphTargetTextureInfo.y;
 			float x = vertexIndex - y * morphTargetTextureInfo.y;
-			vec3 textureUV = vec3((x + 0.5) / morphTargetTextureInfo.y, y / morphTargetTextureInfo.z, targetIndex);
+			vec3 textureUV = vec3((x + 0.5) / morphTargetTextureInfo.y, (y + 0.5) / morphTargetTextureInfo.z, targetIndex);
 			return texture(morphTargets, textureUV).xyz;
 			return texture(morphTargets, textureUV).xyz;
 		}
 		}
 	#endif
 	#endif

+ 3 - 2
src/Sprites/spriteSceneComponent.ts

@@ -9,6 +9,7 @@ import { PickingInfo } from "../Collisions/pickingInfo";
 import { ISceneComponent, SceneComponentConstants } from "../sceneComponent";
 import { ISceneComponent, SceneComponentConstants } from "../sceneComponent";
 import { ActionEvent } from "../Actions/actionEvent";
 import { ActionEvent } from "../Actions/actionEvent";
 import { Constants } from "../Engines/constants";
 import { Constants } from "../Engines/constants";
+import { IPointerEvent } from "../Events/deviceInputEvents";
 
 
 declare module "../scene" {
 declare module "../scene" {
     export interface Scene {
     export interface Scene {
@@ -337,7 +338,7 @@ export class SpriteSceneComponent implements ISceneComponent {
         return pickResult;
         return pickResult;
     }
     }
 
 
-    private _pointerDown(unTranslatedPointerX: number, unTranslatedPointerY: number, pickResult: Nullable<PickingInfo>, evt: PointerEvent): Nullable<PickingInfo> {
+    private _pointerDown(unTranslatedPointerX: number, unTranslatedPointerY: number, pickResult: Nullable<PickingInfo>, evt: IPointerEvent): Nullable<PickingInfo> {
         var scene = this.scene;
         var scene = this.scene;
         scene._pickedDownSprite = null;
         scene._pickedDownSprite = null;
         if (scene.spriteManagers.length > 0) {
         if (scene.spriteManagers.length > 0) {
@@ -367,7 +368,7 @@ export class SpriteSceneComponent implements ISceneComponent {
         return pickResult;
         return pickResult;
     }
     }
 
 
-    private _pointerUp(unTranslatedPointerX: number, unTranslatedPointerY: number, pickResult: Nullable<PickingInfo>, evt: PointerEvent): Nullable<PickingInfo> {
+    private _pointerUp(unTranslatedPointerX: number, unTranslatedPointerY: number, pickResult: Nullable<PickingInfo>, evt: IPointerEvent): Nullable<PickingInfo> {
         var scene = this.scene;
         var scene = this.scene;
         if (scene.spriteManagers.length > 0) {
         if (scene.spriteManagers.length > 0) {
             let spritePickResult = scene.pickSprite(unTranslatedPointerX, unTranslatedPointerY, this._spritePredicate, false, scene.cameraToUseForPointers || undefined);
             let spritePickResult = scene.pickSprite(unTranslatedPointerX, unTranslatedPointerY, this._spritePredicate, false, scene.cameraToUseForPointers || undefined);

+ 22 - 2
src/XR/features/WebXRHandTracking.ts

@@ -22,6 +22,7 @@ import { Engine } from "../../Engines/engine";
 import { Tools } from "../../Misc/tools";
 import { Tools } from "../../Misc/tools";
 import { Axis } from "../../Maths/math.axis";
 import { Axis } from "../../Maths/math.axis";
 import { TransformNode } from "../../Meshes/transformNode";
 import { TransformNode } from "../../Meshes/transformNode";
+import { Tags } from "../../Misc/tags";
 import { Bone } from "../../Bones/bone";
 import { Bone } from "../../Bones/bone";
 
 
 declare const XRHand: XRHand;
 declare const XRHand: XRHand;
@@ -94,6 +95,10 @@ export interface IWebXRHandTrackingOptions {
             right: string[];
             right: string[];
             left: string[];
             left: string[];
         };
         };
+        /**
+         * The utilityLayer scene that contains the 3D UI elements. Passing this in turns on near interactions with the index finger tip
+         */
+        sceneForNearInteraction?: Scene;
     };
     };
 }
 }
 
 
@@ -106,7 +111,7 @@ export const enum HandPart {
      */
      */
     WRIST = "wrist",
     WRIST = "wrist",
     /**
     /**
-     * HandPart - The Thumb
+     * HandPart - The thumb
      */
      */
     THUMB = "thumb",
     THUMB = "thumb",
     /**
     /**
@@ -168,6 +173,7 @@ export class WebXRHand implements IDisposable {
      * @param _handMesh an optional hand mesh. if not provided, ours will be used
      * @param _handMesh an optional hand mesh. if not provided, ours will be used
      * @param _rigMapping an optional rig mapping for the hand mesh. if not provided, ours will be used
      * @param _rigMapping an optional rig mapping for the hand mesh. if not provided, ours will be used
      * @param disableDefaultHandMesh should the default mesh creation be disabled
      * @param disableDefaultHandMesh should the default mesh creation be disabled
+     * @param _nearInteractionMesh as optional mesh used for near interaction collision checking
      * @param _leftHandedMeshes are the hand meshes left-handed-system meshes
      * @param _leftHandedMeshes are the hand meshes left-handed-system meshes
      */
      */
     constructor(
     constructor(
@@ -178,6 +184,7 @@ export class WebXRHand implements IDisposable {
         private _handMesh?: AbstractMesh,
         private _handMesh?: AbstractMesh,
         private _rigMapping?: string[],
         private _rigMapping?: string[],
         disableDefaultHandMesh?: boolean,
         disableDefaultHandMesh?: boolean,
+        private _nearInteractionMesh?: Nullable<AbstractMesh>,
         private _leftHandedMeshes?: boolean
         private _leftHandedMeshes?: boolean
     ) {
     ) {
         this.handPartsDefinition = this.generateHandPartsDefinition(xrController.inputSource.hand!);
         this.handPartsDefinition = this.generateHandPartsDefinition(xrController.inputSource.hand!);
@@ -302,6 +309,11 @@ export class WebXRHand implements IDisposable {
                 }
                 }
             }
             }
         });
         });
+        // Update the invisible fingertip collidable
+        if (this._nearInteractionMesh) {
+            const indexTipPose = this.trackedMeshes[hand.INDEX_PHALANX_TIP].position;
+            this._nearInteractionMesh.position.set(indexTipPose.x, indexTipPose.y, indexTipPose.z);
+        }
     }
     }
 
 
     /**
     /**
@@ -318,6 +330,7 @@ export class WebXRHand implements IDisposable {
      */
      */
     public dispose() {
     public dispose() {
         this.trackedMeshes.forEach((mesh) => mesh.dispose());
         this.trackedMeshes.forEach((mesh) => mesh.dispose());
+        this._nearInteractionMesh?.dispose();
         this.onHandMeshReadyObservable.clear();
         this.onHandMeshReadyObservable.clear();
         // dispose the hand mesh, if it is the default one
         // dispose the hand mesh, if it is the default one
         if (this._defaultHandMesh && this._handMesh) {
         if (this._defaultHandMesh && this._handMesh) {
@@ -574,10 +587,17 @@ export class WebXRHandTracking extends WebXRAbstractFeature {
             trackedMeshes.push(newInstance);
             trackedMeshes.push(newInstance);
         }
         }
 
 
+        let touchMesh: Nullable<AbstractMesh> = null;
+        if (this.options.jointMeshes?.sceneForNearInteraction) {
+            touchMesh = SphereBuilder.CreateSphere(`${xrController.uniqueId}-handJoint-indexCollidable`, {}, this.options.jointMeshes.sceneForNearInteraction);
+            touchMesh.isVisible = false;
+            Tags.AddTagsTo(touchMesh, "touchEnabled");
+        }
+
         const handedness = xrController.inputSource.handedness === "right" ? "right" : "left";
         const handedness = xrController.inputSource.handedness === "right" ? "right" : "left";
         const handMesh = this.options.jointMeshes?.handMeshes && this.options.jointMeshes?.handMeshes[handedness];
         const handMesh = this.options.jointMeshes?.handMeshes && this.options.jointMeshes?.handMeshes[handedness];
         const rigMapping = this.options.jointMeshes?.rigMapping && this.options.jointMeshes?.rigMapping[handedness];
         const rigMapping = this.options.jointMeshes?.rigMapping && this.options.jointMeshes?.rigMapping[handedness];
-        const webxrHand = new WebXRHand(xrController, trackedMeshes, handMesh, rigMapping, this.options.jointMeshes?.disableDefaultHandMesh, this.options.jointMeshes?.leftHandedSystemMeshes);
+        const webxrHand = new WebXRHand(xrController, trackedMeshes, handMesh, rigMapping, this.options.jointMeshes?.disableDefaultHandMesh, touchMesh, this.options.jointMeshes?.leftHandedSystemMeshes);
 
 
         // get two new meshes
         // get two new meshes
         this._hands[xrController.uniqueId] = {
         this._hands[xrController.uniqueId] = {

+ 5 - 4
src/scene.ts

@@ -55,6 +55,7 @@ import { Frustum } from './Maths/math.frustum';
 import { UniqueIdGenerator } from './Misc/uniqueIdGenerator';
 import { UniqueIdGenerator } from './Misc/uniqueIdGenerator';
 import { FileTools, LoadFileError, RequestFileError, ReadFileError } from './Misc/fileTools';
 import { FileTools, LoadFileError, RequestFileError, ReadFileError } from './Misc/fileTools';
 import { IClipPlanesHolder } from './Misc/interfaces/iClipPlanesHolder';
 import { IClipPlanesHolder } from './Misc/interfaces/iClipPlanesHolder';
+import { IPointerEvent } from "./Events/deviceInputEvents";
 
 
 declare type Ray = import("./Culling/ray").Ray;
 declare type Ray = import("./Culling/ray").Ray;
 declare type TrianglePickingPredicate = import("./Culling/ray").TrianglePickingPredicate;
 declare type TrianglePickingPredicate = import("./Culling/ray").TrianglePickingPredicate;
@@ -694,13 +695,13 @@ export class Scene extends AbstractScene implements IAnimatable, IClipPlanesHold
     public pointerMovePredicate: (Mesh: AbstractMesh) => boolean;
     public pointerMovePredicate: (Mesh: AbstractMesh) => boolean;
 
 
     /** Callback called when a pointer move is detected */
     /** Callback called when a pointer move is detected */
-    public onPointerMove: (evt: PointerEvent, pickInfo: PickingInfo, type: PointerEventTypes) => void;
+    public onPointerMove: (evt: IPointerEvent, pickInfo: PickingInfo, type: PointerEventTypes) => void;
     /** Callback called when a pointer down is detected  */
     /** Callback called when a pointer down is detected  */
-    public onPointerDown: (evt: PointerEvent, pickInfo: PickingInfo, type: PointerEventTypes) => void;
+    public onPointerDown: (evt: IPointerEvent, pickInfo: PickingInfo, type: PointerEventTypes) => void;
     /** Callback called when a pointer up is detected  */
     /** Callback called when a pointer up is detected  */
-    public onPointerUp: (evt: PointerEvent, pickInfo: Nullable<PickingInfo>, type: PointerEventTypes) => void;
+    public onPointerUp: (evt: IPointerEvent, pickInfo: Nullable<PickingInfo>, type: PointerEventTypes) => void;
     /** Callback called when a pointer pick is detected */
     /** Callback called when a pointer pick is detected */
-    public onPointerPick: (evt: PointerEvent, pickInfo: PickingInfo) => void;
+    public onPointerPick: (evt: IPointerEvent, pickInfo: PickingInfo) => void;
 
 
     /**
     /**
      * This observable event is triggered when any ponter event is triggered. It is registered during Scene.attachControl() and it is called BEFORE the 3D engine process anything (mesh/sprite picking for instance).
      * This observable event is triggered when any ponter event is triggered. It is registered during Scene.attachControl() and it is called BEFORE the 3D engine process anything (mesh/sprite picking for instance).

+ 2 - 1
src/sceneComponent.ts

@@ -8,6 +8,7 @@ import { Camera } from "./Cameras/camera";
 import { RenderTargetTexture } from "./Materials/Textures/renderTargetTexture";
 import { RenderTargetTexture } from "./Materials/Textures/renderTargetTexture";
 import { PickingInfo } from "./Collisions/pickingInfo";
 import { PickingInfo } from "./Collisions/pickingInfo";
 import { AbstractScene } from "./abstractScene";
 import { AbstractScene } from "./abstractScene";
+import { IPointerEvent } from "./Events/deviceInputEvents";
 
 
 declare type Mesh = import("./Meshes/mesh").Mesh;
 declare type Mesh = import("./Meshes/mesh").Mesh;
 declare type Effect = import("./Materials/effect").Effect;
 declare type Effect = import("./Materials/effect").Effect;
@@ -212,7 +213,7 @@ export type PointerMoveStageAction = (unTranslatedPointerX: number, unTranslated
 /**
 /**
  * Strong typing of a pointer up/down action.
  * Strong typing of a pointer up/down action.
  */
  */
-export type PointerUpDownStageAction = (unTranslatedPointerX: number, unTranslatedPointerY: number, pickResult: Nullable<PickingInfo>, evt: PointerEvent) => Nullable<PickingInfo>;
+export type PointerUpDownStageAction = (unTranslatedPointerX: number, unTranslatedPointerY: number, pickResult: Nullable<PickingInfo>, evt: IPointerEvent) => Nullable<PickingInfo>;
 
 
 /**
 /**
  * Representation of a stage in the scene (Basically a list of ordered steps)
  * Representation of a stage in the scene (Basically a list of ordered steps)

+ 0 - 0
tests/validation/config.json


Some files were not shown because too many files changed in this diff