From 620a0a40e6526a59404dbb73ee2bb9ec957b545d Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Fri, 1 Dec 2017 15:43:25 -0800 Subject: [PATCH 01/27] if you disconnect & reconnect the controllers while in VR, the teleportation no longer works --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 47 ++++++++++++++------ src/Cameras/VR/babylon.webVRCamera.ts | 8 ++++ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index d1e252b1dc2..0198c497257 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -272,6 +272,7 @@ module BABYLON { this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions); this._webVRCamera.onControllerMeshLoadedObservable.add((webVRController) => this._onDefaultMeshLoaded(webVRController)); this._scene.gamepadManager.onGamepadConnectedObservable.add((pad) => this._onNewGamepadConnected(pad)); + this._scene.gamepadManager.onGamepadDisconnectedObservable.add((pad) => this._onNewGamepadDisconnected(pad)); this.updateButtonVisibility(); @@ -282,6 +283,7 @@ module BABYLON { // Raised when one of the controller has loaded successfully its associated default mesh private _onDefaultMeshLoaded(webVRController: WebVRController) { + console.log("mesh loaded") if (webVRController.hand === "left") { this._leftControllerReady = true; if (this._interactionsRequested && !this._interactionsEnabledOnLeftController) { @@ -546,6 +548,7 @@ module BABYLON { } private _onNewGamepadConnected(gamepad: Gamepad) { + console.log("gamepad connected!") if (gamepad.type !== BABYLON.Gamepad.POSE_ENABLED) { if (gamepad.leftStick) { gamepad.onleftstickchanged((stickValues) => { @@ -605,6 +608,7 @@ module BABYLON { } if (gamepad.type === BABYLON.Gamepad.XBOX) { (gamepad).onbuttondown((buttonPressed: Xbox360Button) => { + console.log("bdown") if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) { this._pointerDownOnMeshAsked = true; if (this._currentMeshSelected && this._currentHit) { @@ -613,6 +617,7 @@ module BABYLON { } }); (gamepad).onbuttonup((buttonPressed: Xbox360Button) => { + console.log("bup") if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) { if (this._currentMeshSelected && this._currentHit) { this._scene.simulatePointerUp(this._currentHit); @@ -624,6 +629,27 @@ module BABYLON { } } + private _onNewGamepadDisconnected(gamepad: Gamepad) { + if(gamepad instanceof WebVRController){ + if (gamepad.hand === "left") { + this._interactionsEnabledOnLeftController = false; + this._teleportationEnabledOnLeftController = false; + this._leftControllerReady = false; + if(this._leftLaserPointer){ + this._leftLaserPointer.dispose(); + } + } + if (gamepad.hand === "right") { + this._interactionsEnabledOnRightController = false; + this._teleportationEnabledOnRightController = false; + this._rightControllerReady = false; + if(this._rightLaserPointer){ + this._rightLaserPointer.dispose(); + } + } + } + } + private _enableInteractionOnController(webVRController: WebVRController) { var controllerMesh = webVRController.mesh; if (controllerMesh) { @@ -1035,20 +1061,15 @@ module BABYLON { } private _castRayAndSelectObject () { + //console.log("cast") var ray; - if ((!(this.currentVRCamera).rightController && !(this.currentVRCamera).leftController) || - (this._leftLaserPointer && !this._leftLaserPointer.isVisible && !this._rightLaserPointer) || - (this._rightLaserPointer && !this._rightLaserPointer.isVisible && !this._leftLaserPointer) || - (this._rightLaserPointer && this._leftLaserPointer && !this._rightLaserPointer.isVisible && !this._leftLaserPointer.isVisible)) { - ray = this.currentVRCamera.getForwardRay(this._rayLength); - - } else { - if (this._leftLaserPointer && this._leftLaserPointer.isVisible) { - ray = (this.currentVRCamera).leftController.getForwardRay(this._rayLength); - } - else { - ray = (this.currentVRCamera).rightController.getForwardRay(this._rayLength); - } + if (this._leftLaserPointer && this._leftLaserPointer.isVisible && (this.currentVRCamera).leftController) { + ray = (this.currentVRCamera).leftController.getForwardRay(this._rayLength); + } + else if(this._rightLaserPointer && this._rightLaserPointer.isVisible && (this.currentVRCamera).rightController){ + ray = (this.currentVRCamera).rightController.getForwardRay(this._rayLength); + }else{ + ray = this.currentVRCamera.getForwardRay(this._rayLength); } var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate); diff --git a/src/Cameras/VR/babylon.webVRCamera.ts b/src/Cameras/VR/babylon.webVRCamera.ts index 2659a297c9c..6d211569772 100644 --- a/src/Cameras/VR/babylon.webVRCamera.ts +++ b/src/Cameras/VR/babylon.webVRCamera.ts @@ -351,6 +351,14 @@ module BABYLON { if (webVrController.defaultModel) { webVrController.defaultModel.setEnabled(false); } + + if(webVrController.hand === "right"){ + this._rightController = null; + } + if(webVrController.hand === "left"){ + this._rightController = null; + } + this.controllers.splice(this.controllers.indexOf(webVrController), 1) } }); From 470ea23abe51c8e113cff5dab7dd179a75e8a059 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Fri, 1 Dec 2017 16:05:31 -0800 Subject: [PATCH 02/27] remove logging --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 0198c497257..dcf454868fd 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -283,7 +283,6 @@ module BABYLON { // Raised when one of the controller has loaded successfully its associated default mesh private _onDefaultMeshLoaded(webVRController: WebVRController) { - console.log("mesh loaded") if (webVRController.hand === "left") { this._leftControllerReady = true; if (this._interactionsRequested && !this._interactionsEnabledOnLeftController) { @@ -548,7 +547,6 @@ module BABYLON { } private _onNewGamepadConnected(gamepad: Gamepad) { - console.log("gamepad connected!") if (gamepad.type !== BABYLON.Gamepad.POSE_ENABLED) { if (gamepad.leftStick) { gamepad.onleftstickchanged((stickValues) => { @@ -608,7 +606,6 @@ module BABYLON { } if (gamepad.type === BABYLON.Gamepad.XBOX) { (gamepad).onbuttondown((buttonPressed: Xbox360Button) => { - console.log("bdown") if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) { this._pointerDownOnMeshAsked = true; if (this._currentMeshSelected && this._currentHit) { @@ -617,7 +614,6 @@ module BABYLON { } }); (gamepad).onbuttonup((buttonPressed: Xbox360Button) => { - console.log("bup") if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) { if (this._currentMeshSelected && this._currentHit) { this._scene.simulatePointerUp(this._currentHit); @@ -1061,7 +1057,6 @@ module BABYLON { } private _castRayAndSelectObject () { - //console.log("cast") var ray; if (this._leftLaserPointer && this._leftLaserPointer.isVisible && (this.currentVRCamera).leftController) { ray = (this.currentVRCamera).leftController.getForwardRay(this._rayLength); From f3577579684701d3c8fcbe9546a33de8c0b29732 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Fri, 1 Dec 2017 17:50:21 -0800 Subject: [PATCH 03/27] add option to disable vr fallback camera --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 25 ++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index dcf454868fd..3aae318940e 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -4,10 +4,15 @@ module BABYLON { floorMeshes?: Mesh[]; } + export interface VRExperienceHelperOptions extends WebVROptions { + createFallbackVRDeviceOrientationFreeCamera?: boolean; // Create a VRDeviceOrientationFreeCamera to be used for VR when no external HMD is found + } + export class VRExperienceHelper { private _scene: BABYLON.Scene; private _position: Vector3; private _btnVR: HTMLButtonElement; + private _btnVRDisplayed: Boolean; // Can the system support WebVR, even if a headset isn't plugged in? private _webVRsupported = false; @@ -139,11 +144,15 @@ module BABYLON { return this._vrDeviceOrientationCamera; } - constructor(scene: Scene, public webVROptions: WebVROptions = {}) { + constructor(scene: Scene, public webVROptions: VRExperienceHelperOptions = {}) { this._scene = scene; this._defaultHeight = webVROptions.defaultHeight || 1.7; + if(webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined){ + webVROptions.createFallbackVRDeviceOrientationFreeCamera = true; + } + if (!this._scene.activeCamera || isNaN(this._scene.activeCamera.position.x)) { this._position = new BABYLON.Vector3(0, this._defaultHeight, 0); this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); @@ -228,7 +237,13 @@ module BABYLON { document.addEventListener("webkitfullscreenchange", () => { this._onFullscreenChange() }, false); document.addEventListener("msfullscreenchange", () => { this._onFullscreenChange() }, false); - if (!this._useCustomVRButton) { + this._scene.getEngine().onVRDisplayChangedObservable.add((e)=>{ + if(!this._useCustomVRButton && !this._btnVRDisplayed && e.vrDisplay){ + document.body.appendChild(this._btnVR); + } + }) + + if (!this._useCustomVRButton && webVROptions.createFallbackVRDeviceOrientationFreeCamera) { document.body.appendChild(this._btnVR); } @@ -268,7 +283,9 @@ module BABYLON { window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange); // Create the cameras - this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene); + if(webVROptions.createFallbackVRDeviceOrientationFreeCamera){ + this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene); + } this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions); this._webVRCamera.onControllerMeshLoadedObservable.add((webVRController) => this._onDefaultMeshLoaded(webVRController)); this._scene.gamepadManager.onGamepadConnectedObservable.add((pad) => this._onNewGamepadConnected(pad)); @@ -398,7 +415,7 @@ module BABYLON { this._scene.activeCamera = this._webVRCamera; } } - else { + else if(this._vrDeviceOrientationCamera){ this._vrDeviceOrientationCamera.position = this._position; this._scene.activeCamera = this._vrDeviceOrientationCamera; this._scene.getEngine().switchFullscreen(true); From 5b14e72a2bb944e6bd4c4287299401c859d11685 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Fri, 1 Dec 2017 18:02:56 -0800 Subject: [PATCH 04/27] do not create a device orientation camera when a camera already exists in the scene --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 42 ++++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 3aae318940e..42fb0b03475 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -30,6 +30,7 @@ module BABYLON { private _webVRCamera: WebVRFreeCamera; private _vrDeviceOrientationCamera: VRDeviceOrientationFreeCamera; private _deviceOrientationCamera: DeviceOrientationCamera; + private _existingCamera: Camera; private _onKeyDown: (event: KeyboardEvent) => void; private _onVrDisplayPresentChange: any; @@ -158,25 +159,16 @@ module BABYLON { this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); } else { + this._existingCamera = this._scene.activeCamera this._position = this._scene.activeCamera.position.clone(); - this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); - this._deviceOrientationCamera.minZ = this._scene.activeCamera.minZ; - this._deviceOrientationCamera.maxZ = this._scene.activeCamera.maxZ; - // Set rotation from previous camera - if(this._scene.activeCamera instanceof TargetCamera && this._scene.activeCamera.rotation){ - var targetCamera = this._scene.activeCamera; - if(targetCamera.rotationQuaternion){ - this._deviceOrientationCamera.rotationQuaternion.copyFrom(targetCamera.rotationQuaternion); - }else{ - this._deviceOrientationCamera.rotationQuaternion.copyFrom(Quaternion.RotationYawPitchRoll(targetCamera.rotation.y, targetCamera.rotation.x, targetCamera.rotation.z)); - } - this._deviceOrientationCamera.rotation = targetCamera.rotation.clone(); - } } - this._scene.activeCamera = this._deviceOrientationCamera; + this._canvas = scene.getEngine().getRenderingCanvas(); if (this._canvas) { - this._scene.activeCamera.attachControl(this._canvas); + if(this._deviceOrientationCamera){ + this._scene.activeCamera = this._deviceOrientationCamera; + this._scene.activeCamera.attachControl(this._canvas); + } } if (webVROptions) { @@ -446,12 +438,17 @@ module BABYLON { this._position = this._scene.activeCamera.position.clone(); } - this._deviceOrientationCamera.position = this._position; - this._scene.activeCamera = this._deviceOrientationCamera; - if (this._canvas) { - this._scene.activeCamera.attachControl(this._canvas); - } + if(this._deviceOrientationCamera){ + this._deviceOrientationCamera.position = this._position; + this._scene.activeCamera = this._deviceOrientationCamera; + if (this._canvas) { + this._scene.activeCamera.attachControl(this._canvas); + } + }else if(this._existingCamera){ + this._existingCamera.position = this._position; + this._scene.activeCamera = this._existingCamera; + } this.updateButtonVisibility(); } @@ -1215,7 +1212,10 @@ module BABYLON { if (this.isInVRMode()) { this.exitVR(); } - this._deviceOrientationCamera.dispose(); + + if(this._deviceOrientationCamera){ + this._deviceOrientationCamera.dispose(); + } if (this._passProcessMove) { this._passProcessMove.dispose(); From 00d93d65173a245e55d6b126e42e1f562f5407e7 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 13:03:10 -0800 Subject: [PATCH 05/27] seb's additions --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 335 +++++++++++-------- src/Cameras/VR/babylon.webVRCamera.ts | 5 +- 2 files changed, 201 insertions(+), 139 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 42fb0b03475..c67350edcf4 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -5,6 +5,7 @@ module BABYLON { } export interface VRExperienceHelperOptions extends WebVROptions { + createDeviceOrientationCamera?: boolean; // Create a DeviceOrientationCamera to be used as your out of vr camera. createFallbackVRDeviceOrientationFreeCamera?: boolean; // Create a VRDeviceOrientationFreeCamera to be used for VR when no external HMD is found } @@ -28,19 +29,19 @@ module BABYLON { private _canvas: Nullable; private _webVRCamera: WebVRFreeCamera; - private _vrDeviceOrientationCamera: VRDeviceOrientationFreeCamera; - private _deviceOrientationCamera: DeviceOrientationCamera; + private _vrDeviceOrientationCamera: Nullable; + private _deviceOrientationCamera: Nullable; private _existingCamera: Camera; - + private _onKeyDown: (event: KeyboardEvent) => void; private _onVrDisplayPresentChange: any; - private _onVRDisplayChanged: (eventArgs:IDisplayChangedEventArgs) => void; + private _onVRDisplayChanged: (eventArgs: IDisplayChangedEventArgs) => void; private _onVRRequestPresentStart: () => void; private _onVRRequestPresentComplete: (success: boolean) => void; - - public onEnteringVR = new Observable(); + + public onEnteringVR = new Observable(); public onExitingVR = new Observable(); - public onControllerMeshLoaded = new Observable(); + public onControllerMeshLoaded = new Observable(); private _rayLength: number; private _useCustomVRButton: boolean = false; @@ -72,7 +73,7 @@ module BABYLON { private _rightLaserPointer: Nullable; private _currentMeshSelected: Nullable; public onNewMeshSelected = new Observable(); - private _circleEase:CircleEase; + private _circleEase: CircleEase; private _raySelectionPredicate: (mesh: AbstractMesh) => boolean; @@ -85,11 +86,11 @@ module BABYLON { * To be optionaly changed by user to define custom selection logic (after ray selection) */ public meshSelectionPredicate: (mesh: AbstractMesh) => boolean; - + private _currentHit: Nullable; private _pointerDownOnMeshAsked = false; private _isActionableMesh = false; - private _defaultHeight:number; + private _defaultHeight: number; private _teleportationEnabled = false; private _interactionsEnabled = false; private _interactionsRequested = false; @@ -116,24 +117,24 @@ module BABYLON { if (!value) { if (this._rightLaserPointer) { this._rightLaserPointer.isVisible = false; - } + } if (this._leftLaserPointer) { this._leftLaserPointer.isVisible = false; - } + } } } - public get deviceOrientationCamera(): DeviceOrientationCamera { + public get deviceOrientationCamera(): Nullable { return this._deviceOrientationCamera; } // Based on the current WebVR support, returns the current VR camera used - public get currentVRCamera(): FreeCamera { + public get currentVRCamera(): Nullable { if (this._webVRready) { return this._webVRCamera; } else { - return this._vrDeviceOrientationCamera; + return this._scene.activeCamera; } } @@ -141,35 +142,54 @@ module BABYLON { return this._webVRCamera; } - public get vrDeviceOrientationCamera(): VRDeviceOrientationFreeCamera { + public get vrDeviceOrientationCamera(): Nullable { return this._vrDeviceOrientationCamera; } - + constructor(scene: Scene, public webVROptions: VRExperienceHelperOptions = {}) { this._scene = scene; this._defaultHeight = webVROptions.defaultHeight || 1.7; - - if(webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined){ + + if (webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined) { webVROptions.createFallbackVRDeviceOrientationFreeCamera = true; } - if (!this._scene.activeCamera || isNaN(this._scene.activeCamera.position.x)) { - this._position = new BABYLON.Vector3(0, this._defaultHeight, 0); - this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); + if (webVROptions.createDeviceOrientationCamera === undefined) { + webVROptions.createDeviceOrientationCamera = true; } - else { - this._existingCamera = this._scene.activeCamera - this._position = this._scene.activeCamera.position.clone(); - } - - this._canvas = scene.getEngine().getRenderingCanvas(); - if (this._canvas) { - if(this._deviceOrientationCamera){ - this._scene.activeCamera = this._deviceOrientationCamera; + + if (!this._scene.activeCamera || webVROptions.createDeviceOrientationCamera) { + if (!this._scene.activeCamera || isNaN(this._scene.activeCamera.position.x)) { + this._position = new BABYLON.Vector3(0, this._defaultHeight, 0); + this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); + } + else { + this._position = this._scene.activeCamera.position.clone(); + this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); + this._deviceOrientationCamera.minZ = this._scene.activeCamera.minZ; + this._deviceOrientationCamera.maxZ = this._scene.activeCamera.maxZ; + // Set rotation from previous camera + if (this._scene.activeCamera instanceof TargetCamera && this._scene.activeCamera.rotation) { + var targetCamera = this._scene.activeCamera; + if (targetCamera.rotationQuaternion) { + this._deviceOrientationCamera.rotationQuaternion.copyFrom(targetCamera.rotationQuaternion); + } else { + this._deviceOrientationCamera.rotationQuaternion.copyFrom(Quaternion.RotationYawPitchRoll(targetCamera.rotation.y, targetCamera.rotation.x, targetCamera.rotation.z)); + } + this._deviceOrientationCamera.rotation = targetCamera.rotation.clone(); + } + } + this._scene.activeCamera = this._deviceOrientationCamera; + this._canvas = scene.getEngine().getRenderingCanvas(); + if (this._canvas) { this._scene.activeCamera.attachControl(this._canvas); } } + else { + this._existingCamera = this._scene.activeCamera; + this._position = this._scene.activeCamera.position.clone(); + } if (webVROptions) { if (webVROptions.useCustomVRButton) { @@ -199,7 +219,7 @@ module BABYLON { var style = document.createElement('style'); style.appendChild(document.createTextNode(css)); document.getElementsByTagName('head')[0].appendChild(style); - } + } if (this._canvas) { if (!this._useCustomVRButton) { @@ -229,14 +249,16 @@ module BABYLON { document.addEventListener("webkitfullscreenchange", () => { this._onFullscreenChange() }, false); document.addEventListener("msfullscreenchange", () => { this._onFullscreenChange() }, false); - this._scene.getEngine().onVRDisplayChangedObservable.add((e)=>{ - if(!this._useCustomVRButton && !this._btnVRDisplayed && e.vrDisplay){ + this._scene.getEngine().onVRDisplayChangedObservable.add((e) => { + if (!this._useCustomVRButton && !this._btnVRDisplayed && e.vrDisplay) { document.body.appendChild(this._btnVR); + this._btnVRDisplayed = true; } }) - - if (!this._useCustomVRButton && webVROptions.createFallbackVRDeviceOrientationFreeCamera) { + + if (!this._useCustomVRButton && !this._btnVRDisplayed && webVROptions.createFallbackVRDeviceOrientationFreeCamera) { document.body.appendChild(this._btnVR); + this._btnVRDisplayed = true; } // Exiting VR mode using 'ESC' key on desktop @@ -248,7 +270,7 @@ module BABYLON { document.addEventListener("keydown", this._onKeyDown); // Exiting VR mode double tapping the touch screen - this._scene.onPrePointerObservable.add( (pointerInfo, eventState) => { + this._scene.onPrePointerObservable.add((pointerInfo, eventState) => { if (this.isInVRMode()) { this.exitVR(); if (this._fullscreenVRpresenting) { @@ -256,9 +278,9 @@ module BABYLON { } } }, BABYLON.PointerEventTypes.POINTERDOUBLETAP, false); - + // Listen for WebVR display changes - this._onVRDisplayChanged = (eventArgs:IDisplayChangedEventArgs) => this.onVRDisplayChanged(eventArgs); + this._onVRDisplayChanged = (eventArgs: IDisplayChangedEventArgs) => this.onVRDisplayChanged(eventArgs); this._onVrDisplayPresentChange = () => this.onVrDisplayPresentChange(); this._onVRRequestPresentStart = () => { this._webVRrequesting = true; @@ -275,14 +297,14 @@ module BABYLON { window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange); // Create the cameras - if(webVROptions.createFallbackVRDeviceOrientationFreeCamera){ - this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene); - } + if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) { + this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene); + } this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions); this._webVRCamera.onControllerMeshLoadedObservable.add((webVRController) => this._onDefaultMeshLoaded(webVRController)); this._scene.gamepadManager.onGamepadConnectedObservable.add((pad) => this._onNewGamepadConnected(pad)); this._scene.gamepadManager.onGamepadDisconnectedObservable.add((pad) => this._onNewGamepadDisconnected(pad)); - + this.updateButtonVisibility(); //create easing functions @@ -312,7 +334,7 @@ module BABYLON { } try { this.onControllerMeshLoaded.notifyObservers(webVRController); - } + } catch (err) { Tools.Warn("Error in your custom logic onControllerMeshLoaded: " + err); } @@ -345,10 +367,10 @@ module BABYLON { var vrDisplay = this._scene.getEngine().getVRDevice(); if (vrDisplay) { var wasPresenting = this._webVRpresenting; - + // A VR display is connected this._webVRpresenting = vrDisplay.isPresenting; - + if (wasPresenting && !this._webVRpresenting) this.exitVR(); } else { @@ -358,7 +380,7 @@ module BABYLON { this.updateButtonVisibility(); } - private onVRDisplayChanged(eventArgs:IDisplayChangedEventArgs) { + private onVRDisplayChanged(eventArgs: IDisplayChangedEventArgs) { this._webVRsupported = eventArgs.vrSupported; this._webVRready = !!eventArgs.vrDisplay; this._webVRpresenting = eventArgs.vrDisplay && eventArgs.vrDisplay.isPresenting; @@ -366,13 +388,13 @@ module BABYLON { this.updateButtonVisibility(); } - private updateButtonVisibility() { + private updateButtonVisibility() { if (!this._btnVR) { return; } this._btnVR.className = "babylonVRicon"; if (this.isInVRMode()) { - this._btnVR.className += " vrdisplaypresenting"; + this._btnVR.className += " vrdisplaypresenting"; } else { if (this._webVRready) this._btnVR.className += " vrdisplayready"; if (this._webVRsupported) this._btnVR.className += " vrdisplaysupported"; @@ -407,13 +429,13 @@ module BABYLON { this._scene.activeCamera = this._webVRCamera; } } - else if(this._vrDeviceOrientationCamera){ + else if (this._vrDeviceOrientationCamera) { this._vrDeviceOrientationCamera.position = this._position; this._scene.activeCamera = this._vrDeviceOrientationCamera; this._scene.getEngine().switchFullscreen(true); this.updateButtonVisibility(); } - + if (this._scene.activeCamera && this._canvas) { this._scene.activeCamera.attachControl(this._canvas); } @@ -436,21 +458,21 @@ module BABYLON { } if (this._scene.activeCamera) { this._position = this._scene.activeCamera.position.clone(); - + } - if(this._deviceOrientationCamera){ + if (this._deviceOrientationCamera) { this._deviceOrientationCamera.position = this._position; this._scene.activeCamera = this._deviceOrientationCamera; if (this._canvas) { this._scene.activeCamera.attachControl(this._canvas); } - }else if(this._existingCamera){ + } else if (this._existingCamera) { this._existingCamera.position = this._position; this._scene.activeCamera = this._existingCamera; - } + } - this.updateButtonVisibility(); + this.updateButtonVisibility(); } public get position(): Vector3 { @@ -487,10 +509,10 @@ module BABYLON { } this._raySelectionPredicate = (mesh) => { - if (this._isTeleportationFloor(mesh) || (mesh.isVisible && mesh.name.indexOf("gazeTracker") === -1 - && mesh.name.indexOf("teleportationCircle") === -1 - && mesh.name.indexOf("torusTeleportation") === -1 - && mesh.name.indexOf("laserPointer") === -1)) { + if (this._isTeleportationFloor(mesh) || (mesh.isVisible && mesh.name.indexOf("gazeTracker") === -1 + && mesh.name.indexOf("teleportationCircle") === -1 + && mesh.name.indexOf("torusTeleportation") === -1 + && mesh.name.indexOf("laserPointer") === -1)) { return this.raySelectionPredicate(mesh); } return false; @@ -505,23 +527,46 @@ module BABYLON { } private _isTeleportationFloor(mesh: AbstractMesh): boolean { - for (var i=0; i -1) { + return; + } + + this._floorMeshesCollection.push(floorMesh); + } + + public removeFloorMesh(floorMesh: Mesh): void { + if (!this._floorMeshesCollection) { + return + } + + const meshIndex = this._floorMeshesCollection.indexOf(floorMesh); + if (meshIndex !== -1) { + this._floorMeshesCollection.splice(meshIndex, 1); + } + } + public enableTeleportation(vrTeleportationOptions: VRTeleportationOptions = {}) { if (!this._teleportationEnabled) { this._teleportationRequested = true; this.enableInteractions(); - + if (vrTeleportationOptions) { if (vrTeleportationOptions.floorMeshName) { this._floorMeshName = vrTeleportationOptions.floorMeshName; @@ -544,15 +589,15 @@ module BABYLON { const imageProcessingConfiguration = new ImageProcessingConfiguration(); imageProcessingConfiguration.vignetteColor = new BABYLON.Color4(0, 0, 0, 0); imageProcessingConfiguration.vignetteEnabled = true; - this._postProcessMove = new BABYLON.ImageProcessingPostProcess("postProcessMove", - 1.0, + this._postProcessMove = new BABYLON.ImageProcessingPostProcess("postProcessMove", + 1.0, this._webVRCamera, undefined, undefined, undefined, undefined, imageProcessingConfiguration); - + this._webVRCamera.detachPostProcess(this._postProcessMove) this._passProcessMove = new BABYLON.PassPostProcess("pass", 1.0, this._webVRCamera); this._teleportationEnabled = true; @@ -566,9 +611,9 @@ module BABYLON { gamepad.onleftstickchanged((stickValues) => { if (this._teleportationEnabled) { // Listening to classic/xbox gamepad only if no VR controller is active - if ((!this._leftLaserPointer && !this._rightLaserPointer) || - ((this._leftLaserPointer && !this._leftLaserPointer.isVisible) && - (this._rightLaserPointer && !this._rightLaserPointer.isVisible))) { + if ((!this._leftLaserPointer && !this._rightLaserPointer) || + ((this._leftLaserPointer && !this._leftLaserPointer.isVisible) && + (this._rightLaserPointer && !this._rightLaserPointer.isVisible))) { if (!this._teleportationRequestInitiated) { if (stickValues.y < -this._padSensibilityUp) { this._teleportationRequestInitiated = true; @@ -640,12 +685,12 @@ module BABYLON { } private _onNewGamepadDisconnected(gamepad: Gamepad) { - if(gamepad instanceof WebVRController){ + if (gamepad instanceof WebVRController) { if (gamepad.hand === "left") { this._interactionsEnabledOnLeftController = false; this._teleportationEnabledOnLeftController = false; this._leftControllerReady = false; - if(this._leftLaserPointer){ + if (this._leftLaserPointer) { this._leftLaserPointer.dispose(); } } @@ -653,7 +698,7 @@ module BABYLON { this._interactionsEnabledOnRightController = false; this._teleportationEnabledOnRightController = false; this._rightControllerReady = false; - if(this._rightLaserPointer){ + if (this._rightLaserPointer) { this._rightLaserPointer.dispose(); } } @@ -740,7 +785,7 @@ module BABYLON { if (!this._teleportationRequestInitiated) { if (stateObject.y < -this._padSensibilityUp) { // If laser pointer wasn't enabled yet - if (this._displayLaserPointer && webVRController.hand === "left" && this._leftLaserPointer) { + if (this._displayLaserPointer && webVRController.hand === "left" && this._leftLaserPointer) { this._leftLaserPointer.isVisible = true; if (this._rightLaserPointer) { this._rightLaserPointer.isVisible = false; @@ -757,7 +802,7 @@ module BABYLON { } else { // Listening to the proper controller values changes to confirm teleportation - if ((webVRController.hand === "left" && this._leftLaserPointer && this._leftLaserPointer.isVisible) + if ((webVRController.hand === "left" && this._leftLaserPointer && this._leftLaserPointer.isVisible) || (webVRController.hand === "right" && this._rightLaserPointer && this._rightLaserPointer.isVisible)) { if (stateObject.y > -this._padSensibilityDown) { if (this._teleportationAllowed) { @@ -781,7 +826,7 @@ module BABYLON { this._rotationLeftAsked = false; } } - + if (!this._rotationRightAsked) { if (stateObject.x > this._padSensibilityUp) { this._rotationRightAsked = true; @@ -810,22 +855,22 @@ module BABYLON { targetMat.specularColor = BABYLON.Color3.Black(); targetMat.emissiveColor = new BABYLON.Color3(0.7, 0.7, 0.7) targetMat.backFaceCulling = false; - this._gazeTracker.material = targetMat; + this._gazeTracker.material = targetMat; } private _createTeleportationCircles() { this._teleportationCircle = BABYLON.Mesh.CreateGround("teleportationCircle", 2, 2, 2, this._scene); this._teleportationCircle.isPickable = false; - + var length = 512; var dynamicTexture = new BABYLON.DynamicTexture("DynamicTexture", length, this._scene, true); dynamicTexture.hasAlpha = true; var context = dynamicTexture.getContext(); - + var centerX = length / 2; var centerY = length / 2; var radius = 200; - + context.beginPath(); context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); context.fillStyle = this._teleportationFillColor; @@ -835,17 +880,17 @@ module BABYLON { context.stroke(); context.closePath(); dynamicTexture.update(); - + var teleportationCircleMaterial = new BABYLON.StandardMaterial("TextPlaneMaterial", this._scene); teleportationCircleMaterial.diffuseTexture = dynamicTexture; this._teleportationCircle.material = teleportationCircleMaterial; - + var torus = BABYLON.Mesh.CreateTorus("torusTeleportation", 0.75, 0.1, 25, this._scene, false); torus.isPickable = false; torus.parent = this._teleportationCircle; - + var animationInnerCircle = new BABYLON.Animation("animationInnerCircle", "position.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE); - + var keys = []; keys.push({ frame: 0, @@ -859,18 +904,18 @@ module BABYLON { frame: 60, value: 0 }); - + animationInnerCircle.setKeys(keys); - + var easingFunction = new BABYLON.SineEase(); easingFunction.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT); animationInnerCircle.setEasingFunction(easingFunction); - + torus.animations = []; torus.animations.push(animationInnerCircle); - + this._scene.beginAnimation(torus, 0, 60, true); - + this._hideTeleportationCircle(); } @@ -880,7 +925,7 @@ module BABYLON { (this._teleportationCircle.getChildren()[0]).isVisible = true; } } - + private _hideTeleportationCircle() { if (this._teleportationEnabled) { this._teleportationCircle.isVisible = false; @@ -889,20 +934,24 @@ module BABYLON { } private _rotateCamera(right: boolean) { + if (!(this.currentVRCamera instanceof FreeCamera)) { + return; + } + if (right) { this._rotationAngle++; } else { this._rotationAngle--; } - + this.currentVRCamera.animations = []; - + var target = BABYLON.Quaternion.FromRotationMatrix(BABYLON.Matrix.RotationY(Math.PI / 4 * this._rotationAngle)); - + var animationRotation = new BABYLON.Animation("animationRotation", "rotationQuaternion", 90, BABYLON.Animation.ANIMATIONTYPE_QUATERNION, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var animationRotationKeys = []; animationRotationKeys.push({ frame: 0, @@ -912,18 +961,18 @@ module BABYLON { frame: 6, value: target }); - + animationRotation.setKeys(animationRotationKeys); animationRotation.setEasingFunction(this._circleEase); - + this.currentVRCamera.animations.push(animationRotation); - + this._postProcessMove.animations = []; - + var animationPP = new BABYLON.Animation("animationPP", "vignetteWeight", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var vignetteWeightKeys = []; vignetteWeightKeys.push({ frame: 0, @@ -937,14 +986,14 @@ module BABYLON { frame: 6, value: 0 }); - + animationPP.setKeys(vignetteWeightKeys); animationPP.setEasingFunction(this._circleEase); this._postProcessMove.animations.push(animationPP); - + var animationPP2 = new BABYLON.Animation("animationPP2", "vignetteStretch", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var vignetteStretchKeys = []; vignetteStretchKeys.push({ frame: 0, @@ -958,11 +1007,11 @@ module BABYLON { frame: 6, value: 0 }); - + animationPP2.setKeys(vignetteStretchKeys); animationPP2.setEasingFunction(this._circleEase); this._postProcessMove.animations.push(animationPP2); - + this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0; this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0; @@ -995,34 +1044,38 @@ module BABYLON { } private _workingVector = Vector3.Zero(); private _teleportCamera() { + if (!(this.currentVRCamera instanceof FreeCamera)) { + return; + } + // Teleport the hmd to where the user is looking by moving the anchor to where they are looking minus the // offset of the headset from the anchor. Then add the helper's position to account for user's height offset this.webVRCamera.leftCamera!.globalPosition.subtractToRef(this.webVRCamera.position, this._workingVector); this._haloCenter.subtractToRef(this._workingVector, this._workingVector); this._workingVector.y += this._defaultHeight; - + // Create animation from the camera's position to the new location this.currentVRCamera.animations = []; var animationCameraTeleportation = new BABYLON.Animation("animationCameraTeleportation", "position", 90, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); var animationCameraTeleportationKeys = [{ - frame: 0, - value: this.currentVRCamera.position - }, - { - frame: 11, - value: this._workingVector - } + frame: 0, + value: this.currentVRCamera.position + }, + { + frame: 11, + value: this._workingVector + } ]; - + animationCameraTeleportation.setKeys(animationCameraTeleportationKeys); animationCameraTeleportation.setEasingFunction(this._circleEase); this.currentVRCamera.animations.push(animationCameraTeleportation); - + this._postProcessMove.animations = []; - + var animationPP = new BABYLON.Animation("animationPP", "vignetteWeight", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var vignetteWeightKeys = []; vignetteWeightKeys.push({ frame: 0, @@ -1036,13 +1089,13 @@ module BABYLON { frame: 11, value: 0 }); - + animationPP.setKeys(vignetteWeightKeys); this._postProcessMove.animations.push(animationPP); - + var animationPP2 = new BABYLON.Animation("animationPP2", "vignetteStretch", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var vignetteStretchKeys = []; vignetteStretchKeys.push({ frame: 0, @@ -1056,13 +1109,13 @@ module BABYLON { frame: 11, value: 0 }); - + animationPP2.setKeys(vignetteStretchKeys); this._postProcessMove.animations.push(animationPP2); - + this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 8; this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 10; - + this._webVRCamera.attachPostProcess(this._postProcessMove) this._scene.beginAnimation(this._postProcessMove, 0, 11, false, 1, () => { this._webVRCamera.detachPostProcess(this._postProcessMove) @@ -1070,17 +1123,21 @@ module BABYLON { this._scene.beginAnimation(this.currentVRCamera, 0, 11, false, 1); } - private _castRayAndSelectObject () { + private _castRayAndSelectObject() { + if (!(this.currentVRCamera instanceof FreeCamera)) { + return; + } + var ray; if (this._leftLaserPointer && this._leftLaserPointer.isVisible && (this.currentVRCamera).leftController) { ray = (this.currentVRCamera).leftController.getForwardRay(this._rayLength); } - else if(this._rightLaserPointer && this._rightLaserPointer.isVisible && (this.currentVRCamera).rightController){ + else if (this._rightLaserPointer && this._rightLaserPointer.isVisible && (this.currentVRCamera).rightController) { ray = (this.currentVRCamera).rightController.getForwardRay(this._rayLength); - }else{ + } else { ray = this.currentVRCamera.getForwardRay(this._rayLength); } - + var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate); // Moving the gazeTracker on the mesh face targetted @@ -1100,14 +1157,14 @@ module BABYLON { var pickNormal = hit.getNormal(); // To avoid z-fighting let deltaFighting = 0.002; - + if (pickNormal) { var axis1 = BABYLON.Vector3.Cross(BABYLON.Axis.Y, pickNormal); var axis2 = BABYLON.Vector3.Cross(pickNormal, axis1); BABYLON.Vector3.RotationFromAxisToRef(axis2, pickNormal, axis1, this._gazeTracker.rotation); } this._gazeTracker.position.copyFrom(hit.pickedPoint); - + if (this._gazeTracker.position.x < 0) { this._gazeTracker.position.x += deltaFighting; } @@ -1141,7 +1198,7 @@ module BABYLON { else { this._gazeTracker.isVisible = false; } - + if (hit && hit.pickedMesh) { this._currentHit = hit; if (this._pointerDownOnMeshAsked) { @@ -1160,13 +1217,13 @@ module BABYLON { if (this.meshSelectionPredicate(hit.pickedMesh)) { this._currentMeshSelected = hit.pickedMesh; if (hit.pickedMesh.isPickable && hit.pickedMesh.actionManager) { - this.changeGazeColor(new BABYLON.Color3(0,0,1)); - this.changeLaserColor(new BABYLON.Color3(0.2,0.2,1)); + this.changeGazeColor(new BABYLON.Color3(0, 0, 1)); + this.changeLaserColor(new BABYLON.Color3(0.2, 0.2, 1)); this._isActionableMesh = true; } else { - this.changeGazeColor(new BABYLON.Color3(0.7,0.7,0.7)); - this.changeLaserColor(new BABYLON.Color3(0.7,0.7,0.7)); + this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7)); + this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7)); this._isActionableMesh = false; } try { @@ -1178,8 +1235,8 @@ module BABYLON { } else { this._currentMeshSelected = null; - this.changeGazeColor(new BABYLON.Color3(0.7,0.7,0.7)); - this.changeLaserColor(new BABYLON.Color3(0.7,0.7,0.7)); + this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7)); + this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7)); } } } @@ -1188,8 +1245,8 @@ module BABYLON { this._currentMeshSelected = null; this._teleportationAllowed = false; this._hideTeleportationCircle(); - this.changeGazeColor(new BABYLON.Color3(0.7,0.7,0.7)); - this.changeLaserColor(new BABYLON.Color3(0.7,0.7,0.7)); + this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7)); + this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7)); } } @@ -1213,7 +1270,7 @@ module BABYLON { this.exitVR(); } - if(this._deviceOrientationCamera){ + if (this._deviceOrientationCamera) { this._deviceOrientationCamera.dispose(); } @@ -1235,6 +1292,8 @@ module BABYLON { document.body.removeChild(this._btnVR); } + this._floorMeshesCollection = []; + document.removeEventListener("keydown", this._onKeyDown); window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange); } @@ -1243,4 +1302,4 @@ module BABYLON { return "VRExperienceHelper"; } } -} +} \ No newline at end of file diff --git a/src/Cameras/VR/babylon.webVRCamera.ts b/src/Cameras/VR/babylon.webVRCamera.ts index 6d211569772..352b0629bf2 100644 --- a/src/Cameras/VR/babylon.webVRCamera.ts +++ b/src/Cameras/VR/babylon.webVRCamera.ts @@ -358,7 +358,10 @@ module BABYLON { if(webVrController.hand === "left"){ this._rightController = null; } - this.controllers.splice(this.controllers.indexOf(webVrController), 1) + const controllerIndex = this.controllers.indexOf(webVrController); + if (controllerIndex !== -1) { + this.controllers.splice(controllerIndex, 1); + } } }); From 40500e7ecab6fc058bbadef885cd49a1f6343445 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 13:12:03 -0800 Subject: [PATCH 06/27] update webVROption to be vrExperienceOptions when creating from scene, fix enter vr button not appearing when using createDeviceOrientationCamera: false --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 4 ++-- src/babylon.scene.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index c67350edcf4..31a9e349adf 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -148,6 +148,7 @@ module BABYLON { constructor(scene: Scene, public webVROptions: VRExperienceHelperOptions = {}) { this._scene = scene; + this._canvas = scene.getEngine().getRenderingCanvas(); this._defaultHeight = webVROptions.defaultHeight || 1.7; @@ -180,8 +181,7 @@ module BABYLON { this._deviceOrientationCamera.rotation = targetCamera.rotation.clone(); } } - this._scene.activeCamera = this._deviceOrientationCamera; - this._canvas = scene.getEngine().getRenderingCanvas(); + this._scene.activeCamera = this._deviceOrientationCamera; if (this._canvas) { this._scene.activeCamera.attachControl(this._canvas); } diff --git a/src/babylon.scene.ts b/src/babylon.scene.ts index de1335d988c..08cbd4dbac2 100644 --- a/src/babylon.scene.ts +++ b/src/babylon.scene.ts @@ -4475,7 +4475,7 @@ return null; } - public createDefaultVRExperience(webVROptions: WebVROptions = {}): VRExperienceHelper { + public createDefaultVRExperience(webVROptions: VRExperienceHelperOptions = {}): VRExperienceHelper { return new BABYLON.VRExperienceHelper(this, webVROptions); } From 6e54b4d43e25503c220dde4e61720b312f945df5 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 13:26:14 -0800 Subject: [PATCH 07/27] fix tp flicker --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 31a9e349adf..ccfb554daf7 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -1113,8 +1113,8 @@ module BABYLON { animationPP2.setKeys(vignetteStretchKeys); this._postProcessMove.animations.push(animationPP2); - this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 8; - this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 10; + this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0; + this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0; this._webVRCamera.attachPostProcess(this._postProcessMove) this._scene.beginAnimation(this._postProcessMove, 0, 11, false, 1, () => { From 8ecf20e325ddcca56a93520b54cb71d9af47e875 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 14:04:30 -0800 Subject: [PATCH 08/27] fix tp when not in vr mode --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index ccfb554daf7..30c9357c0e0 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -1050,8 +1050,13 @@ module BABYLON { // Teleport the hmd to where the user is looking by moving the anchor to where they are looking minus the // offset of the headset from the anchor. Then add the helper's position to account for user's height offset - this.webVRCamera.leftCamera!.globalPosition.subtractToRef(this.webVRCamera.position, this._workingVector); - this._haloCenter.subtractToRef(this._workingVector, this._workingVector); + if(this.webVRCamera.leftCamera){ + this._workingVector.copyFrom(this.webVRCamera.leftCamera.globalPosition); + this._workingVector.subtractInPlace(this.webVRCamera.position); + this._haloCenter.subtractToRef(this._workingVector, this._workingVector); + }else{ + this._workingVector.copyFrom(this._haloCenter); + } this._workingVector.y += this._defaultHeight; // Create animation from the camera's position to the new location From 65dcd1367f726964e161e8e1d4673a57323c8b00 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 14:25:36 -0800 Subject: [PATCH 09/27] issue to align teleportation circle on stairs --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 30c9357c0e0..dab7a098378 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -1033,7 +1033,7 @@ module BABYLON { } this._haloCenter.copyFrom(hit.pickedPoint); this._teleportationCircle.position.copyFrom(hit.pickedPoint); - var pickNormal = hit.getNormal(); + var pickNormal = hit.getNormal(true, false); if (pickNormal) { var axis1 = BABYLON.Vector3.Cross(BABYLON.Axis.Y, pickNormal); var axis2 = BABYLON.Vector3.Cross(pickNormal, axis1); From 8b1b50e284a0549533315b2c480bb327e6a4a14d Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Fri, 1 Dec 2017 15:43:25 -0800 Subject: [PATCH 10/27] if you disconnect & reconnect the controllers while in VR, the teleportation no longer works --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 47 ++++++++++++++------ src/Cameras/VR/babylon.webVRCamera.ts | 8 ++++ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index d1e252b1dc2..0198c497257 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -272,6 +272,7 @@ module BABYLON { this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions); this._webVRCamera.onControllerMeshLoadedObservable.add((webVRController) => this._onDefaultMeshLoaded(webVRController)); this._scene.gamepadManager.onGamepadConnectedObservable.add((pad) => this._onNewGamepadConnected(pad)); + this._scene.gamepadManager.onGamepadDisconnectedObservable.add((pad) => this._onNewGamepadDisconnected(pad)); this.updateButtonVisibility(); @@ -282,6 +283,7 @@ module BABYLON { // Raised when one of the controller has loaded successfully its associated default mesh private _onDefaultMeshLoaded(webVRController: WebVRController) { + console.log("mesh loaded") if (webVRController.hand === "left") { this._leftControllerReady = true; if (this._interactionsRequested && !this._interactionsEnabledOnLeftController) { @@ -546,6 +548,7 @@ module BABYLON { } private _onNewGamepadConnected(gamepad: Gamepad) { + console.log("gamepad connected!") if (gamepad.type !== BABYLON.Gamepad.POSE_ENABLED) { if (gamepad.leftStick) { gamepad.onleftstickchanged((stickValues) => { @@ -605,6 +608,7 @@ module BABYLON { } if (gamepad.type === BABYLON.Gamepad.XBOX) { (gamepad).onbuttondown((buttonPressed: Xbox360Button) => { + console.log("bdown") if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) { this._pointerDownOnMeshAsked = true; if (this._currentMeshSelected && this._currentHit) { @@ -613,6 +617,7 @@ module BABYLON { } }); (gamepad).onbuttonup((buttonPressed: Xbox360Button) => { + console.log("bup") if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) { if (this._currentMeshSelected && this._currentHit) { this._scene.simulatePointerUp(this._currentHit); @@ -624,6 +629,27 @@ module BABYLON { } } + private _onNewGamepadDisconnected(gamepad: Gamepad) { + if(gamepad instanceof WebVRController){ + if (gamepad.hand === "left") { + this._interactionsEnabledOnLeftController = false; + this._teleportationEnabledOnLeftController = false; + this._leftControllerReady = false; + if(this._leftLaserPointer){ + this._leftLaserPointer.dispose(); + } + } + if (gamepad.hand === "right") { + this._interactionsEnabledOnRightController = false; + this._teleportationEnabledOnRightController = false; + this._rightControllerReady = false; + if(this._rightLaserPointer){ + this._rightLaserPointer.dispose(); + } + } + } + } + private _enableInteractionOnController(webVRController: WebVRController) { var controllerMesh = webVRController.mesh; if (controllerMesh) { @@ -1035,20 +1061,15 @@ module BABYLON { } private _castRayAndSelectObject () { + //console.log("cast") var ray; - if ((!(this.currentVRCamera).rightController && !(this.currentVRCamera).leftController) || - (this._leftLaserPointer && !this._leftLaserPointer.isVisible && !this._rightLaserPointer) || - (this._rightLaserPointer && !this._rightLaserPointer.isVisible && !this._leftLaserPointer) || - (this._rightLaserPointer && this._leftLaserPointer && !this._rightLaserPointer.isVisible && !this._leftLaserPointer.isVisible)) { - ray = this.currentVRCamera.getForwardRay(this._rayLength); - - } else { - if (this._leftLaserPointer && this._leftLaserPointer.isVisible) { - ray = (this.currentVRCamera).leftController.getForwardRay(this._rayLength); - } - else { - ray = (this.currentVRCamera).rightController.getForwardRay(this._rayLength); - } + if (this._leftLaserPointer && this._leftLaserPointer.isVisible && (this.currentVRCamera).leftController) { + ray = (this.currentVRCamera).leftController.getForwardRay(this._rayLength); + } + else if(this._rightLaserPointer && this._rightLaserPointer.isVisible && (this.currentVRCamera).rightController){ + ray = (this.currentVRCamera).rightController.getForwardRay(this._rayLength); + }else{ + ray = this.currentVRCamera.getForwardRay(this._rayLength); } var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate); diff --git a/src/Cameras/VR/babylon.webVRCamera.ts b/src/Cameras/VR/babylon.webVRCamera.ts index 2659a297c9c..6d211569772 100644 --- a/src/Cameras/VR/babylon.webVRCamera.ts +++ b/src/Cameras/VR/babylon.webVRCamera.ts @@ -351,6 +351,14 @@ module BABYLON { if (webVrController.defaultModel) { webVrController.defaultModel.setEnabled(false); } + + if(webVrController.hand === "right"){ + this._rightController = null; + } + if(webVrController.hand === "left"){ + this._rightController = null; + } + this.controllers.splice(this.controllers.indexOf(webVrController), 1) } }); From 29d603a27544de8c023a67e8c23e065b332eaebe Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Fri, 1 Dec 2017 16:05:31 -0800 Subject: [PATCH 11/27] remove logging --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 0198c497257..dcf454868fd 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -283,7 +283,6 @@ module BABYLON { // Raised when one of the controller has loaded successfully its associated default mesh private _onDefaultMeshLoaded(webVRController: WebVRController) { - console.log("mesh loaded") if (webVRController.hand === "left") { this._leftControllerReady = true; if (this._interactionsRequested && !this._interactionsEnabledOnLeftController) { @@ -548,7 +547,6 @@ module BABYLON { } private _onNewGamepadConnected(gamepad: Gamepad) { - console.log("gamepad connected!") if (gamepad.type !== BABYLON.Gamepad.POSE_ENABLED) { if (gamepad.leftStick) { gamepad.onleftstickchanged((stickValues) => { @@ -608,7 +606,6 @@ module BABYLON { } if (gamepad.type === BABYLON.Gamepad.XBOX) { (gamepad).onbuttondown((buttonPressed: Xbox360Button) => { - console.log("bdown") if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) { this._pointerDownOnMeshAsked = true; if (this._currentMeshSelected && this._currentHit) { @@ -617,7 +614,6 @@ module BABYLON { } }); (gamepad).onbuttonup((buttonPressed: Xbox360Button) => { - console.log("bup") if (this._interactionsEnabled && buttonPressed === Xbox360Button.A) { if (this._currentMeshSelected && this._currentHit) { this._scene.simulatePointerUp(this._currentHit); @@ -1061,7 +1057,6 @@ module BABYLON { } private _castRayAndSelectObject () { - //console.log("cast") var ray; if (this._leftLaserPointer && this._leftLaserPointer.isVisible && (this.currentVRCamera).leftController) { ray = (this.currentVRCamera).leftController.getForwardRay(this._rayLength); From 53fa127d0f70ec6e3a071b390b8925754aff4406 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Fri, 1 Dec 2017 17:50:21 -0800 Subject: [PATCH 12/27] add option to disable vr fallback camera --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 25 ++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index dcf454868fd..3aae318940e 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -4,10 +4,15 @@ module BABYLON { floorMeshes?: Mesh[]; } + export interface VRExperienceHelperOptions extends WebVROptions { + createFallbackVRDeviceOrientationFreeCamera?: boolean; // Create a VRDeviceOrientationFreeCamera to be used for VR when no external HMD is found + } + export class VRExperienceHelper { private _scene: BABYLON.Scene; private _position: Vector3; private _btnVR: HTMLButtonElement; + private _btnVRDisplayed: Boolean; // Can the system support WebVR, even if a headset isn't plugged in? private _webVRsupported = false; @@ -139,11 +144,15 @@ module BABYLON { return this._vrDeviceOrientationCamera; } - constructor(scene: Scene, public webVROptions: WebVROptions = {}) { + constructor(scene: Scene, public webVROptions: VRExperienceHelperOptions = {}) { this._scene = scene; this._defaultHeight = webVROptions.defaultHeight || 1.7; + if(webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined){ + webVROptions.createFallbackVRDeviceOrientationFreeCamera = true; + } + if (!this._scene.activeCamera || isNaN(this._scene.activeCamera.position.x)) { this._position = new BABYLON.Vector3(0, this._defaultHeight, 0); this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); @@ -228,7 +237,13 @@ module BABYLON { document.addEventListener("webkitfullscreenchange", () => { this._onFullscreenChange() }, false); document.addEventListener("msfullscreenchange", () => { this._onFullscreenChange() }, false); - if (!this._useCustomVRButton) { + this._scene.getEngine().onVRDisplayChangedObservable.add((e)=>{ + if(!this._useCustomVRButton && !this._btnVRDisplayed && e.vrDisplay){ + document.body.appendChild(this._btnVR); + } + }) + + if (!this._useCustomVRButton && webVROptions.createFallbackVRDeviceOrientationFreeCamera) { document.body.appendChild(this._btnVR); } @@ -268,7 +283,9 @@ module BABYLON { window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange); // Create the cameras - this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene); + if(webVROptions.createFallbackVRDeviceOrientationFreeCamera){ + this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene); + } this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions); this._webVRCamera.onControllerMeshLoadedObservable.add((webVRController) => this._onDefaultMeshLoaded(webVRController)); this._scene.gamepadManager.onGamepadConnectedObservable.add((pad) => this._onNewGamepadConnected(pad)); @@ -398,7 +415,7 @@ module BABYLON { this._scene.activeCamera = this._webVRCamera; } } - else { + else if(this._vrDeviceOrientationCamera){ this._vrDeviceOrientationCamera.position = this._position; this._scene.activeCamera = this._vrDeviceOrientationCamera; this._scene.getEngine().switchFullscreen(true); From 7988b9071a5b1d3cd397a14b4fea9ea0438e7260 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Fri, 1 Dec 2017 18:02:56 -0800 Subject: [PATCH 13/27] do not create a device orientation camera when a camera already exists in the scene --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 42 ++++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 3aae318940e..42fb0b03475 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -30,6 +30,7 @@ module BABYLON { private _webVRCamera: WebVRFreeCamera; private _vrDeviceOrientationCamera: VRDeviceOrientationFreeCamera; private _deviceOrientationCamera: DeviceOrientationCamera; + private _existingCamera: Camera; private _onKeyDown: (event: KeyboardEvent) => void; private _onVrDisplayPresentChange: any; @@ -158,25 +159,16 @@ module BABYLON { this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); } else { + this._existingCamera = this._scene.activeCamera this._position = this._scene.activeCamera.position.clone(); - this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); - this._deviceOrientationCamera.minZ = this._scene.activeCamera.minZ; - this._deviceOrientationCamera.maxZ = this._scene.activeCamera.maxZ; - // Set rotation from previous camera - if(this._scene.activeCamera instanceof TargetCamera && this._scene.activeCamera.rotation){ - var targetCamera = this._scene.activeCamera; - if(targetCamera.rotationQuaternion){ - this._deviceOrientationCamera.rotationQuaternion.copyFrom(targetCamera.rotationQuaternion); - }else{ - this._deviceOrientationCamera.rotationQuaternion.copyFrom(Quaternion.RotationYawPitchRoll(targetCamera.rotation.y, targetCamera.rotation.x, targetCamera.rotation.z)); - } - this._deviceOrientationCamera.rotation = targetCamera.rotation.clone(); - } } - this._scene.activeCamera = this._deviceOrientationCamera; + this._canvas = scene.getEngine().getRenderingCanvas(); if (this._canvas) { - this._scene.activeCamera.attachControl(this._canvas); + if(this._deviceOrientationCamera){ + this._scene.activeCamera = this._deviceOrientationCamera; + this._scene.activeCamera.attachControl(this._canvas); + } } if (webVROptions) { @@ -446,12 +438,17 @@ module BABYLON { this._position = this._scene.activeCamera.position.clone(); } - this._deviceOrientationCamera.position = this._position; - this._scene.activeCamera = this._deviceOrientationCamera; - if (this._canvas) { - this._scene.activeCamera.attachControl(this._canvas); - } + if(this._deviceOrientationCamera){ + this._deviceOrientationCamera.position = this._position; + this._scene.activeCamera = this._deviceOrientationCamera; + if (this._canvas) { + this._scene.activeCamera.attachControl(this._canvas); + } + }else if(this._existingCamera){ + this._existingCamera.position = this._position; + this._scene.activeCamera = this._existingCamera; + } this.updateButtonVisibility(); } @@ -1215,7 +1212,10 @@ module BABYLON { if (this.isInVRMode()) { this.exitVR(); } - this._deviceOrientationCamera.dispose(); + + if(this._deviceOrientationCamera){ + this._deviceOrientationCamera.dispose(); + } if (this._passProcessMove) { this._passProcessMove.dispose(); From 06d6cc20af1a96bbfb291e6f5d0c42f6c17b225d Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 13:03:10 -0800 Subject: [PATCH 14/27] seb's additions --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 335 +++++++++++-------- src/Cameras/VR/babylon.webVRCamera.ts | 5 +- 2 files changed, 201 insertions(+), 139 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 42fb0b03475..c67350edcf4 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -5,6 +5,7 @@ module BABYLON { } export interface VRExperienceHelperOptions extends WebVROptions { + createDeviceOrientationCamera?: boolean; // Create a DeviceOrientationCamera to be used as your out of vr camera. createFallbackVRDeviceOrientationFreeCamera?: boolean; // Create a VRDeviceOrientationFreeCamera to be used for VR when no external HMD is found } @@ -28,19 +29,19 @@ module BABYLON { private _canvas: Nullable; private _webVRCamera: WebVRFreeCamera; - private _vrDeviceOrientationCamera: VRDeviceOrientationFreeCamera; - private _deviceOrientationCamera: DeviceOrientationCamera; + private _vrDeviceOrientationCamera: Nullable; + private _deviceOrientationCamera: Nullable; private _existingCamera: Camera; - + private _onKeyDown: (event: KeyboardEvent) => void; private _onVrDisplayPresentChange: any; - private _onVRDisplayChanged: (eventArgs:IDisplayChangedEventArgs) => void; + private _onVRDisplayChanged: (eventArgs: IDisplayChangedEventArgs) => void; private _onVRRequestPresentStart: () => void; private _onVRRequestPresentComplete: (success: boolean) => void; - - public onEnteringVR = new Observable(); + + public onEnteringVR = new Observable(); public onExitingVR = new Observable(); - public onControllerMeshLoaded = new Observable(); + public onControllerMeshLoaded = new Observable(); private _rayLength: number; private _useCustomVRButton: boolean = false; @@ -72,7 +73,7 @@ module BABYLON { private _rightLaserPointer: Nullable; private _currentMeshSelected: Nullable; public onNewMeshSelected = new Observable(); - private _circleEase:CircleEase; + private _circleEase: CircleEase; private _raySelectionPredicate: (mesh: AbstractMesh) => boolean; @@ -85,11 +86,11 @@ module BABYLON { * To be optionaly changed by user to define custom selection logic (after ray selection) */ public meshSelectionPredicate: (mesh: AbstractMesh) => boolean; - + private _currentHit: Nullable; private _pointerDownOnMeshAsked = false; private _isActionableMesh = false; - private _defaultHeight:number; + private _defaultHeight: number; private _teleportationEnabled = false; private _interactionsEnabled = false; private _interactionsRequested = false; @@ -116,24 +117,24 @@ module BABYLON { if (!value) { if (this._rightLaserPointer) { this._rightLaserPointer.isVisible = false; - } + } if (this._leftLaserPointer) { this._leftLaserPointer.isVisible = false; - } + } } } - public get deviceOrientationCamera(): DeviceOrientationCamera { + public get deviceOrientationCamera(): Nullable { return this._deviceOrientationCamera; } // Based on the current WebVR support, returns the current VR camera used - public get currentVRCamera(): FreeCamera { + public get currentVRCamera(): Nullable { if (this._webVRready) { return this._webVRCamera; } else { - return this._vrDeviceOrientationCamera; + return this._scene.activeCamera; } } @@ -141,35 +142,54 @@ module BABYLON { return this._webVRCamera; } - public get vrDeviceOrientationCamera(): VRDeviceOrientationFreeCamera { + public get vrDeviceOrientationCamera(): Nullable { return this._vrDeviceOrientationCamera; } - + constructor(scene: Scene, public webVROptions: VRExperienceHelperOptions = {}) { this._scene = scene; this._defaultHeight = webVROptions.defaultHeight || 1.7; - - if(webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined){ + + if (webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined) { webVROptions.createFallbackVRDeviceOrientationFreeCamera = true; } - if (!this._scene.activeCamera || isNaN(this._scene.activeCamera.position.x)) { - this._position = new BABYLON.Vector3(0, this._defaultHeight, 0); - this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); + if (webVROptions.createDeviceOrientationCamera === undefined) { + webVROptions.createDeviceOrientationCamera = true; } - else { - this._existingCamera = this._scene.activeCamera - this._position = this._scene.activeCamera.position.clone(); - } - - this._canvas = scene.getEngine().getRenderingCanvas(); - if (this._canvas) { - if(this._deviceOrientationCamera){ - this._scene.activeCamera = this._deviceOrientationCamera; + + if (!this._scene.activeCamera || webVROptions.createDeviceOrientationCamera) { + if (!this._scene.activeCamera || isNaN(this._scene.activeCamera.position.x)) { + this._position = new BABYLON.Vector3(0, this._defaultHeight, 0); + this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); + } + else { + this._position = this._scene.activeCamera.position.clone(); + this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene); + this._deviceOrientationCamera.minZ = this._scene.activeCamera.minZ; + this._deviceOrientationCamera.maxZ = this._scene.activeCamera.maxZ; + // Set rotation from previous camera + if (this._scene.activeCamera instanceof TargetCamera && this._scene.activeCamera.rotation) { + var targetCamera = this._scene.activeCamera; + if (targetCamera.rotationQuaternion) { + this._deviceOrientationCamera.rotationQuaternion.copyFrom(targetCamera.rotationQuaternion); + } else { + this._deviceOrientationCamera.rotationQuaternion.copyFrom(Quaternion.RotationYawPitchRoll(targetCamera.rotation.y, targetCamera.rotation.x, targetCamera.rotation.z)); + } + this._deviceOrientationCamera.rotation = targetCamera.rotation.clone(); + } + } + this._scene.activeCamera = this._deviceOrientationCamera; + this._canvas = scene.getEngine().getRenderingCanvas(); + if (this._canvas) { this._scene.activeCamera.attachControl(this._canvas); } } + else { + this._existingCamera = this._scene.activeCamera; + this._position = this._scene.activeCamera.position.clone(); + } if (webVROptions) { if (webVROptions.useCustomVRButton) { @@ -199,7 +219,7 @@ module BABYLON { var style = document.createElement('style'); style.appendChild(document.createTextNode(css)); document.getElementsByTagName('head')[0].appendChild(style); - } + } if (this._canvas) { if (!this._useCustomVRButton) { @@ -229,14 +249,16 @@ module BABYLON { document.addEventListener("webkitfullscreenchange", () => { this._onFullscreenChange() }, false); document.addEventListener("msfullscreenchange", () => { this._onFullscreenChange() }, false); - this._scene.getEngine().onVRDisplayChangedObservable.add((e)=>{ - if(!this._useCustomVRButton && !this._btnVRDisplayed && e.vrDisplay){ + this._scene.getEngine().onVRDisplayChangedObservable.add((e) => { + if (!this._useCustomVRButton && !this._btnVRDisplayed && e.vrDisplay) { document.body.appendChild(this._btnVR); + this._btnVRDisplayed = true; } }) - - if (!this._useCustomVRButton && webVROptions.createFallbackVRDeviceOrientationFreeCamera) { + + if (!this._useCustomVRButton && !this._btnVRDisplayed && webVROptions.createFallbackVRDeviceOrientationFreeCamera) { document.body.appendChild(this._btnVR); + this._btnVRDisplayed = true; } // Exiting VR mode using 'ESC' key on desktop @@ -248,7 +270,7 @@ module BABYLON { document.addEventListener("keydown", this._onKeyDown); // Exiting VR mode double tapping the touch screen - this._scene.onPrePointerObservable.add( (pointerInfo, eventState) => { + this._scene.onPrePointerObservable.add((pointerInfo, eventState) => { if (this.isInVRMode()) { this.exitVR(); if (this._fullscreenVRpresenting) { @@ -256,9 +278,9 @@ module BABYLON { } } }, BABYLON.PointerEventTypes.POINTERDOUBLETAP, false); - + // Listen for WebVR display changes - this._onVRDisplayChanged = (eventArgs:IDisplayChangedEventArgs) => this.onVRDisplayChanged(eventArgs); + this._onVRDisplayChanged = (eventArgs: IDisplayChangedEventArgs) => this.onVRDisplayChanged(eventArgs); this._onVrDisplayPresentChange = () => this.onVrDisplayPresentChange(); this._onVRRequestPresentStart = () => { this._webVRrequesting = true; @@ -275,14 +297,14 @@ module BABYLON { window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange); // Create the cameras - if(webVROptions.createFallbackVRDeviceOrientationFreeCamera){ - this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene); - } + if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) { + this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene); + } this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions); this._webVRCamera.onControllerMeshLoadedObservable.add((webVRController) => this._onDefaultMeshLoaded(webVRController)); this._scene.gamepadManager.onGamepadConnectedObservable.add((pad) => this._onNewGamepadConnected(pad)); this._scene.gamepadManager.onGamepadDisconnectedObservable.add((pad) => this._onNewGamepadDisconnected(pad)); - + this.updateButtonVisibility(); //create easing functions @@ -312,7 +334,7 @@ module BABYLON { } try { this.onControllerMeshLoaded.notifyObservers(webVRController); - } + } catch (err) { Tools.Warn("Error in your custom logic onControllerMeshLoaded: " + err); } @@ -345,10 +367,10 @@ module BABYLON { var vrDisplay = this._scene.getEngine().getVRDevice(); if (vrDisplay) { var wasPresenting = this._webVRpresenting; - + // A VR display is connected this._webVRpresenting = vrDisplay.isPresenting; - + if (wasPresenting && !this._webVRpresenting) this.exitVR(); } else { @@ -358,7 +380,7 @@ module BABYLON { this.updateButtonVisibility(); } - private onVRDisplayChanged(eventArgs:IDisplayChangedEventArgs) { + private onVRDisplayChanged(eventArgs: IDisplayChangedEventArgs) { this._webVRsupported = eventArgs.vrSupported; this._webVRready = !!eventArgs.vrDisplay; this._webVRpresenting = eventArgs.vrDisplay && eventArgs.vrDisplay.isPresenting; @@ -366,13 +388,13 @@ module BABYLON { this.updateButtonVisibility(); } - private updateButtonVisibility() { + private updateButtonVisibility() { if (!this._btnVR) { return; } this._btnVR.className = "babylonVRicon"; if (this.isInVRMode()) { - this._btnVR.className += " vrdisplaypresenting"; + this._btnVR.className += " vrdisplaypresenting"; } else { if (this._webVRready) this._btnVR.className += " vrdisplayready"; if (this._webVRsupported) this._btnVR.className += " vrdisplaysupported"; @@ -407,13 +429,13 @@ module BABYLON { this._scene.activeCamera = this._webVRCamera; } } - else if(this._vrDeviceOrientationCamera){ + else if (this._vrDeviceOrientationCamera) { this._vrDeviceOrientationCamera.position = this._position; this._scene.activeCamera = this._vrDeviceOrientationCamera; this._scene.getEngine().switchFullscreen(true); this.updateButtonVisibility(); } - + if (this._scene.activeCamera && this._canvas) { this._scene.activeCamera.attachControl(this._canvas); } @@ -436,21 +458,21 @@ module BABYLON { } if (this._scene.activeCamera) { this._position = this._scene.activeCamera.position.clone(); - + } - if(this._deviceOrientationCamera){ + if (this._deviceOrientationCamera) { this._deviceOrientationCamera.position = this._position; this._scene.activeCamera = this._deviceOrientationCamera; if (this._canvas) { this._scene.activeCamera.attachControl(this._canvas); } - }else if(this._existingCamera){ + } else if (this._existingCamera) { this._existingCamera.position = this._position; this._scene.activeCamera = this._existingCamera; - } + } - this.updateButtonVisibility(); + this.updateButtonVisibility(); } public get position(): Vector3 { @@ -487,10 +509,10 @@ module BABYLON { } this._raySelectionPredicate = (mesh) => { - if (this._isTeleportationFloor(mesh) || (mesh.isVisible && mesh.name.indexOf("gazeTracker") === -1 - && mesh.name.indexOf("teleportationCircle") === -1 - && mesh.name.indexOf("torusTeleportation") === -1 - && mesh.name.indexOf("laserPointer") === -1)) { + if (this._isTeleportationFloor(mesh) || (mesh.isVisible && mesh.name.indexOf("gazeTracker") === -1 + && mesh.name.indexOf("teleportationCircle") === -1 + && mesh.name.indexOf("torusTeleportation") === -1 + && mesh.name.indexOf("laserPointer") === -1)) { return this.raySelectionPredicate(mesh); } return false; @@ -505,23 +527,46 @@ module BABYLON { } private _isTeleportationFloor(mesh: AbstractMesh): boolean { - for (var i=0; i -1) { + return; + } + + this._floorMeshesCollection.push(floorMesh); + } + + public removeFloorMesh(floorMesh: Mesh): void { + if (!this._floorMeshesCollection) { + return + } + + const meshIndex = this._floorMeshesCollection.indexOf(floorMesh); + if (meshIndex !== -1) { + this._floorMeshesCollection.splice(meshIndex, 1); + } + } + public enableTeleportation(vrTeleportationOptions: VRTeleportationOptions = {}) { if (!this._teleportationEnabled) { this._teleportationRequested = true; this.enableInteractions(); - + if (vrTeleportationOptions) { if (vrTeleportationOptions.floorMeshName) { this._floorMeshName = vrTeleportationOptions.floorMeshName; @@ -544,15 +589,15 @@ module BABYLON { const imageProcessingConfiguration = new ImageProcessingConfiguration(); imageProcessingConfiguration.vignetteColor = new BABYLON.Color4(0, 0, 0, 0); imageProcessingConfiguration.vignetteEnabled = true; - this._postProcessMove = new BABYLON.ImageProcessingPostProcess("postProcessMove", - 1.0, + this._postProcessMove = new BABYLON.ImageProcessingPostProcess("postProcessMove", + 1.0, this._webVRCamera, undefined, undefined, undefined, undefined, imageProcessingConfiguration); - + this._webVRCamera.detachPostProcess(this._postProcessMove) this._passProcessMove = new BABYLON.PassPostProcess("pass", 1.0, this._webVRCamera); this._teleportationEnabled = true; @@ -566,9 +611,9 @@ module BABYLON { gamepad.onleftstickchanged((stickValues) => { if (this._teleportationEnabled) { // Listening to classic/xbox gamepad only if no VR controller is active - if ((!this._leftLaserPointer && !this._rightLaserPointer) || - ((this._leftLaserPointer && !this._leftLaserPointer.isVisible) && - (this._rightLaserPointer && !this._rightLaserPointer.isVisible))) { + if ((!this._leftLaserPointer && !this._rightLaserPointer) || + ((this._leftLaserPointer && !this._leftLaserPointer.isVisible) && + (this._rightLaserPointer && !this._rightLaserPointer.isVisible))) { if (!this._teleportationRequestInitiated) { if (stickValues.y < -this._padSensibilityUp) { this._teleportationRequestInitiated = true; @@ -640,12 +685,12 @@ module BABYLON { } private _onNewGamepadDisconnected(gamepad: Gamepad) { - if(gamepad instanceof WebVRController){ + if (gamepad instanceof WebVRController) { if (gamepad.hand === "left") { this._interactionsEnabledOnLeftController = false; this._teleportationEnabledOnLeftController = false; this._leftControllerReady = false; - if(this._leftLaserPointer){ + if (this._leftLaserPointer) { this._leftLaserPointer.dispose(); } } @@ -653,7 +698,7 @@ module BABYLON { this._interactionsEnabledOnRightController = false; this._teleportationEnabledOnRightController = false; this._rightControllerReady = false; - if(this._rightLaserPointer){ + if (this._rightLaserPointer) { this._rightLaserPointer.dispose(); } } @@ -740,7 +785,7 @@ module BABYLON { if (!this._teleportationRequestInitiated) { if (stateObject.y < -this._padSensibilityUp) { // If laser pointer wasn't enabled yet - if (this._displayLaserPointer && webVRController.hand === "left" && this._leftLaserPointer) { + if (this._displayLaserPointer && webVRController.hand === "left" && this._leftLaserPointer) { this._leftLaserPointer.isVisible = true; if (this._rightLaserPointer) { this._rightLaserPointer.isVisible = false; @@ -757,7 +802,7 @@ module BABYLON { } else { // Listening to the proper controller values changes to confirm teleportation - if ((webVRController.hand === "left" && this._leftLaserPointer && this._leftLaserPointer.isVisible) + if ((webVRController.hand === "left" && this._leftLaserPointer && this._leftLaserPointer.isVisible) || (webVRController.hand === "right" && this._rightLaserPointer && this._rightLaserPointer.isVisible)) { if (stateObject.y > -this._padSensibilityDown) { if (this._teleportationAllowed) { @@ -781,7 +826,7 @@ module BABYLON { this._rotationLeftAsked = false; } } - + if (!this._rotationRightAsked) { if (stateObject.x > this._padSensibilityUp) { this._rotationRightAsked = true; @@ -810,22 +855,22 @@ module BABYLON { targetMat.specularColor = BABYLON.Color3.Black(); targetMat.emissiveColor = new BABYLON.Color3(0.7, 0.7, 0.7) targetMat.backFaceCulling = false; - this._gazeTracker.material = targetMat; + this._gazeTracker.material = targetMat; } private _createTeleportationCircles() { this._teleportationCircle = BABYLON.Mesh.CreateGround("teleportationCircle", 2, 2, 2, this._scene); this._teleportationCircle.isPickable = false; - + var length = 512; var dynamicTexture = new BABYLON.DynamicTexture("DynamicTexture", length, this._scene, true); dynamicTexture.hasAlpha = true; var context = dynamicTexture.getContext(); - + var centerX = length / 2; var centerY = length / 2; var radius = 200; - + context.beginPath(); context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); context.fillStyle = this._teleportationFillColor; @@ -835,17 +880,17 @@ module BABYLON { context.stroke(); context.closePath(); dynamicTexture.update(); - + var teleportationCircleMaterial = new BABYLON.StandardMaterial("TextPlaneMaterial", this._scene); teleportationCircleMaterial.diffuseTexture = dynamicTexture; this._teleportationCircle.material = teleportationCircleMaterial; - + var torus = BABYLON.Mesh.CreateTorus("torusTeleportation", 0.75, 0.1, 25, this._scene, false); torus.isPickable = false; torus.parent = this._teleportationCircle; - + var animationInnerCircle = new BABYLON.Animation("animationInnerCircle", "position.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE); - + var keys = []; keys.push({ frame: 0, @@ -859,18 +904,18 @@ module BABYLON { frame: 60, value: 0 }); - + animationInnerCircle.setKeys(keys); - + var easingFunction = new BABYLON.SineEase(); easingFunction.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT); animationInnerCircle.setEasingFunction(easingFunction); - + torus.animations = []; torus.animations.push(animationInnerCircle); - + this._scene.beginAnimation(torus, 0, 60, true); - + this._hideTeleportationCircle(); } @@ -880,7 +925,7 @@ module BABYLON { (this._teleportationCircle.getChildren()[0]).isVisible = true; } } - + private _hideTeleportationCircle() { if (this._teleportationEnabled) { this._teleportationCircle.isVisible = false; @@ -889,20 +934,24 @@ module BABYLON { } private _rotateCamera(right: boolean) { + if (!(this.currentVRCamera instanceof FreeCamera)) { + return; + } + if (right) { this._rotationAngle++; } else { this._rotationAngle--; } - + this.currentVRCamera.animations = []; - + var target = BABYLON.Quaternion.FromRotationMatrix(BABYLON.Matrix.RotationY(Math.PI / 4 * this._rotationAngle)); - + var animationRotation = new BABYLON.Animation("animationRotation", "rotationQuaternion", 90, BABYLON.Animation.ANIMATIONTYPE_QUATERNION, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var animationRotationKeys = []; animationRotationKeys.push({ frame: 0, @@ -912,18 +961,18 @@ module BABYLON { frame: 6, value: target }); - + animationRotation.setKeys(animationRotationKeys); animationRotation.setEasingFunction(this._circleEase); - + this.currentVRCamera.animations.push(animationRotation); - + this._postProcessMove.animations = []; - + var animationPP = new BABYLON.Animation("animationPP", "vignetteWeight", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var vignetteWeightKeys = []; vignetteWeightKeys.push({ frame: 0, @@ -937,14 +986,14 @@ module BABYLON { frame: 6, value: 0 }); - + animationPP.setKeys(vignetteWeightKeys); animationPP.setEasingFunction(this._circleEase); this._postProcessMove.animations.push(animationPP); - + var animationPP2 = new BABYLON.Animation("animationPP2", "vignetteStretch", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var vignetteStretchKeys = []; vignetteStretchKeys.push({ frame: 0, @@ -958,11 +1007,11 @@ module BABYLON { frame: 6, value: 0 }); - + animationPP2.setKeys(vignetteStretchKeys); animationPP2.setEasingFunction(this._circleEase); this._postProcessMove.animations.push(animationPP2); - + this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0; this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0; @@ -995,34 +1044,38 @@ module BABYLON { } private _workingVector = Vector3.Zero(); private _teleportCamera() { + if (!(this.currentVRCamera instanceof FreeCamera)) { + return; + } + // Teleport the hmd to where the user is looking by moving the anchor to where they are looking minus the // offset of the headset from the anchor. Then add the helper's position to account for user's height offset this.webVRCamera.leftCamera!.globalPosition.subtractToRef(this.webVRCamera.position, this._workingVector); this._haloCenter.subtractToRef(this._workingVector, this._workingVector); this._workingVector.y += this._defaultHeight; - + // Create animation from the camera's position to the new location this.currentVRCamera.animations = []; var animationCameraTeleportation = new BABYLON.Animation("animationCameraTeleportation", "position", 90, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); var animationCameraTeleportationKeys = [{ - frame: 0, - value: this.currentVRCamera.position - }, - { - frame: 11, - value: this._workingVector - } + frame: 0, + value: this.currentVRCamera.position + }, + { + frame: 11, + value: this._workingVector + } ]; - + animationCameraTeleportation.setKeys(animationCameraTeleportationKeys); animationCameraTeleportation.setEasingFunction(this._circleEase); this.currentVRCamera.animations.push(animationCameraTeleportation); - + this._postProcessMove.animations = []; - + var animationPP = new BABYLON.Animation("animationPP", "vignetteWeight", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var vignetteWeightKeys = []; vignetteWeightKeys.push({ frame: 0, @@ -1036,13 +1089,13 @@ module BABYLON { frame: 11, value: 0 }); - + animationPP.setKeys(vignetteWeightKeys); this._postProcessMove.animations.push(animationPP); - + var animationPP2 = new BABYLON.Animation("animationPP2", "vignetteStretch", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT); - + var vignetteStretchKeys = []; vignetteStretchKeys.push({ frame: 0, @@ -1056,13 +1109,13 @@ module BABYLON { frame: 11, value: 0 }); - + animationPP2.setKeys(vignetteStretchKeys); this._postProcessMove.animations.push(animationPP2); - + this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 8; this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 10; - + this._webVRCamera.attachPostProcess(this._postProcessMove) this._scene.beginAnimation(this._postProcessMove, 0, 11, false, 1, () => { this._webVRCamera.detachPostProcess(this._postProcessMove) @@ -1070,17 +1123,21 @@ module BABYLON { this._scene.beginAnimation(this.currentVRCamera, 0, 11, false, 1); } - private _castRayAndSelectObject () { + private _castRayAndSelectObject() { + if (!(this.currentVRCamera instanceof FreeCamera)) { + return; + } + var ray; if (this._leftLaserPointer && this._leftLaserPointer.isVisible && (this.currentVRCamera).leftController) { ray = (this.currentVRCamera).leftController.getForwardRay(this._rayLength); } - else if(this._rightLaserPointer && this._rightLaserPointer.isVisible && (this.currentVRCamera).rightController){ + else if (this._rightLaserPointer && this._rightLaserPointer.isVisible && (this.currentVRCamera).rightController) { ray = (this.currentVRCamera).rightController.getForwardRay(this._rayLength); - }else{ + } else { ray = this.currentVRCamera.getForwardRay(this._rayLength); } - + var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate); // Moving the gazeTracker on the mesh face targetted @@ -1100,14 +1157,14 @@ module BABYLON { var pickNormal = hit.getNormal(); // To avoid z-fighting let deltaFighting = 0.002; - + if (pickNormal) { var axis1 = BABYLON.Vector3.Cross(BABYLON.Axis.Y, pickNormal); var axis2 = BABYLON.Vector3.Cross(pickNormal, axis1); BABYLON.Vector3.RotationFromAxisToRef(axis2, pickNormal, axis1, this._gazeTracker.rotation); } this._gazeTracker.position.copyFrom(hit.pickedPoint); - + if (this._gazeTracker.position.x < 0) { this._gazeTracker.position.x += deltaFighting; } @@ -1141,7 +1198,7 @@ module BABYLON { else { this._gazeTracker.isVisible = false; } - + if (hit && hit.pickedMesh) { this._currentHit = hit; if (this._pointerDownOnMeshAsked) { @@ -1160,13 +1217,13 @@ module BABYLON { if (this.meshSelectionPredicate(hit.pickedMesh)) { this._currentMeshSelected = hit.pickedMesh; if (hit.pickedMesh.isPickable && hit.pickedMesh.actionManager) { - this.changeGazeColor(new BABYLON.Color3(0,0,1)); - this.changeLaserColor(new BABYLON.Color3(0.2,0.2,1)); + this.changeGazeColor(new BABYLON.Color3(0, 0, 1)); + this.changeLaserColor(new BABYLON.Color3(0.2, 0.2, 1)); this._isActionableMesh = true; } else { - this.changeGazeColor(new BABYLON.Color3(0.7,0.7,0.7)); - this.changeLaserColor(new BABYLON.Color3(0.7,0.7,0.7)); + this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7)); + this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7)); this._isActionableMesh = false; } try { @@ -1178,8 +1235,8 @@ module BABYLON { } else { this._currentMeshSelected = null; - this.changeGazeColor(new BABYLON.Color3(0.7,0.7,0.7)); - this.changeLaserColor(new BABYLON.Color3(0.7,0.7,0.7)); + this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7)); + this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7)); } } } @@ -1188,8 +1245,8 @@ module BABYLON { this._currentMeshSelected = null; this._teleportationAllowed = false; this._hideTeleportationCircle(); - this.changeGazeColor(new BABYLON.Color3(0.7,0.7,0.7)); - this.changeLaserColor(new BABYLON.Color3(0.7,0.7,0.7)); + this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7)); + this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7)); } } @@ -1213,7 +1270,7 @@ module BABYLON { this.exitVR(); } - if(this._deviceOrientationCamera){ + if (this._deviceOrientationCamera) { this._deviceOrientationCamera.dispose(); } @@ -1235,6 +1292,8 @@ module BABYLON { document.body.removeChild(this._btnVR); } + this._floorMeshesCollection = []; + document.removeEventListener("keydown", this._onKeyDown); window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange); } @@ -1243,4 +1302,4 @@ module BABYLON { return "VRExperienceHelper"; } } -} +} \ No newline at end of file diff --git a/src/Cameras/VR/babylon.webVRCamera.ts b/src/Cameras/VR/babylon.webVRCamera.ts index 6d211569772..352b0629bf2 100644 --- a/src/Cameras/VR/babylon.webVRCamera.ts +++ b/src/Cameras/VR/babylon.webVRCamera.ts @@ -358,7 +358,10 @@ module BABYLON { if(webVrController.hand === "left"){ this._rightController = null; } - this.controllers.splice(this.controllers.indexOf(webVrController), 1) + const controllerIndex = this.controllers.indexOf(webVrController); + if (controllerIndex !== -1) { + this.controllers.splice(controllerIndex, 1); + } } }); From b2271bd2363fc59078259de0778f2af2d096e405 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 13:12:03 -0800 Subject: [PATCH 15/27] update webVROption to be vrExperienceOptions when creating from scene, fix enter vr button not appearing when using createDeviceOrientationCamera: false --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 4 ++-- src/babylon.scene.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index c67350edcf4..31a9e349adf 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -148,6 +148,7 @@ module BABYLON { constructor(scene: Scene, public webVROptions: VRExperienceHelperOptions = {}) { this._scene = scene; + this._canvas = scene.getEngine().getRenderingCanvas(); this._defaultHeight = webVROptions.defaultHeight || 1.7; @@ -180,8 +181,7 @@ module BABYLON { this._deviceOrientationCamera.rotation = targetCamera.rotation.clone(); } } - this._scene.activeCamera = this._deviceOrientationCamera; - this._canvas = scene.getEngine().getRenderingCanvas(); + this._scene.activeCamera = this._deviceOrientationCamera; if (this._canvas) { this._scene.activeCamera.attachControl(this._canvas); } diff --git a/src/babylon.scene.ts b/src/babylon.scene.ts index de1335d988c..08cbd4dbac2 100644 --- a/src/babylon.scene.ts +++ b/src/babylon.scene.ts @@ -4475,7 +4475,7 @@ return null; } - public createDefaultVRExperience(webVROptions: WebVROptions = {}): VRExperienceHelper { + public createDefaultVRExperience(webVROptions: VRExperienceHelperOptions = {}): VRExperienceHelper { return new BABYLON.VRExperienceHelper(this, webVROptions); } From 64b6270bea5974bf74f723550d6bfb22789a6163 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 13:26:14 -0800 Subject: [PATCH 16/27] fix tp flicker --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 31a9e349adf..ccfb554daf7 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -1113,8 +1113,8 @@ module BABYLON { animationPP2.setKeys(vignetteStretchKeys); this._postProcessMove.animations.push(animationPP2); - this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 8; - this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 10; + this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0; + this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0; this._webVRCamera.attachPostProcess(this._postProcessMove) this._scene.beginAnimation(this._postProcessMove, 0, 11, false, 1, () => { From aca4bb4379f16b47a52fee5d2ef025dcd1dedb37 Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 14:04:30 -0800 Subject: [PATCH 17/27] fix tp when not in vr mode --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index ccfb554daf7..30c9357c0e0 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -1050,8 +1050,13 @@ module BABYLON { // Teleport the hmd to where the user is looking by moving the anchor to where they are looking minus the // offset of the headset from the anchor. Then add the helper's position to account for user's height offset - this.webVRCamera.leftCamera!.globalPosition.subtractToRef(this.webVRCamera.position, this._workingVector); - this._haloCenter.subtractToRef(this._workingVector, this._workingVector); + if(this.webVRCamera.leftCamera){ + this._workingVector.copyFrom(this.webVRCamera.leftCamera.globalPosition); + this._workingVector.subtractInPlace(this.webVRCamera.position); + this._haloCenter.subtractToRef(this._workingVector, this._workingVector); + }else{ + this._workingVector.copyFrom(this._haloCenter); + } this._workingVector.y += this._defaultHeight; // Create animation from the camera's position to the new location From 3688a0441d5a5e2d32ef907085f81966b15c994b Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 14:25:36 -0800 Subject: [PATCH 18/27] issue to align teleportation circle on stairs --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index 30c9357c0e0..dab7a098378 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -1033,7 +1033,7 @@ module BABYLON { } this._haloCenter.copyFrom(hit.pickedPoint); this._teleportationCircle.position.copyFrom(hit.pickedPoint); - var pickNormal = hit.getNormal(); + var pickNormal = hit.getNormal(true, false); if (pickNormal) { var axis1 = BABYLON.Vector3.Cross(BABYLON.Axis.Y, pickNormal); var axis2 = BABYLON.Vector3.Cross(pickNormal, axis1); From 8e10989f50911de8bb374687bd16e79781aabbbf Mon Sep 17 00:00:00 2001 From: Trevor Baron Date: Mon, 4 Dec 2017 16:52:21 -0800 Subject: [PATCH 19/27] address comments --- src/Cameras/VR/babylon.vrExperienceHelper.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cameras/VR/babylon.vrExperienceHelper.ts b/src/Cameras/VR/babylon.vrExperienceHelper.ts index dab7a098378..066ef9edb31 100644 --- a/src/Cameras/VR/babylon.vrExperienceHelper.ts +++ b/src/Cameras/VR/babylon.vrExperienceHelper.ts @@ -13,7 +13,7 @@ module BABYLON { private _scene: BABYLON.Scene; private _position: Vector3; private _btnVR: HTMLButtonElement; - private _btnVRDisplayed: Boolean; + private _btnVRDisplayed: boolean; // Can the system support WebVR, even if a headset isn't plugged in? private _webVRsupported = false; @@ -39,8 +39,8 @@ module BABYLON { private _onVRRequestPresentStart: () => void; private _onVRRequestPresentComplete: (success: boolean) => void; - public onEnteringVR = new Observable(); - public onExitingVR = new Observable(); + public onEnteringVR = new Observable(); + public onExitingVR = new Observable(); public onControllerMeshLoaded = new Observable(); private _rayLength: number; @@ -413,7 +413,7 @@ module BABYLON { if (this.onEnteringVR) { try { - this.onEnteringVR.notifyObservers({}); + this.onEnteringVR.notifyObservers(this); } catch (err) { Tools.Warn("Error in your custom logic onEnteringVR: " + err); @@ -447,7 +447,7 @@ module BABYLON { public exitVR() { if (this.onExitingVR) { try { - this.onExitingVR.notifyObservers({}); + this.onExitingVR.notifyObservers(this); } catch (err) { Tools.Warn("Error in your custom logic onExitingVR: " + err); From 34d4ca1766021163c37263661f521b13e935840a Mon Sep 17 00:00:00 2001 From: Sebastien Vandenberghe Date: Mon, 4 Dec 2017 17:46:51 -0800 Subject: [PATCH 20/27] CORS Anonymous --- gui/src/controls/image.ts | 2 +- src/Audio/babylon.sound.ts | 2 +- .../Textures/babylon.videoTexture.ts | 5 ++- src/Tools/babylon.tools.ts | 39 +++++++++++-------- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/gui/src/controls/image.ts b/gui/src/controls/image.ts index 2f64b8e9a1e..119e3823df4 100644 --- a/gui/src/controls/image.ts +++ b/gui/src/controls/image.ts @@ -150,7 +150,7 @@ module BABYLON.GUI { this._onImageLoaded(); } if (value) { - this._domImage.crossOrigin = "anonymous"; + Tools.SetCorsBehavior(value, this._domImage); this._domImage.src = value; } } diff --git a/src/Audio/babylon.sound.ts b/src/Audio/babylon.sound.ts index a1ba3183024..0ebcca1047e 100644 --- a/src/Audio/babylon.sound.ts +++ b/src/Audio/babylon.sound.ts @@ -136,7 +136,7 @@ module BABYLON { this._htmlAudioElement = new Audio(url); this._htmlAudioElement.controls = false; this._htmlAudioElement.loop = this.loop; - this._htmlAudioElement.crossOrigin = "anonymous"; + Tools.SetCorsBehavior(url, this._htmlAudioElement); this._htmlAudioElement.preload = "auto"; this._htmlAudioElement.addEventListener("canplaythrough", () => { this._isReadyToPlay = true; diff --git a/src/Materials/Textures/babylon.videoTexture.ts b/src/Materials/Textures/babylon.videoTexture.ts index 9b89985bdb6..46db4e10bf0 100644 --- a/src/Materials/Textures/babylon.videoTexture.ts +++ b/src/Materials/Textures/babylon.videoTexture.ts @@ -26,11 +26,12 @@ if (urlsOrVideo instanceof HTMLVideoElement) { this.video = urlsOrVideo; } else { - urls = urlsOrVideo; - + urls = urlsOrVideo; + this.video = document.createElement("video"); this.video.autoplay = false; this.video.loop = true; + Tools.SetCorsBehavior(urls, this.video); } this._engine = (this.getScene()).getEngine(); diff --git a/src/Tools/babylon.tools.ts b/src/Tools/babylon.tools.ts index 684be65835d..928f5ca59f5 100644 --- a/src/Tools/babylon.tools.ts +++ b/src/Tools/babylon.tools.ts @@ -24,7 +24,14 @@ export class Tools { public static BaseUrl = ""; - public static CorsBehavior: any = "anonymous"; + + /** + * Default behaviour for cors in the application. + * It can be a string if the expected behavior is identical in the entire app. + * Or a callback to be able to set it per url or on a group of them (in case of Video source for instance) + */ + public static CorsBehavior: string | ((url: string | string[]) => string) = "anonymous"; + public static UseFallbackTexture = true; /** @@ -384,19 +391,20 @@ } } - public static SetCorsBehavior(url: string, img: HTMLImageElement): void { + public static SetCorsBehavior(url: string | string[], element: { crossOrigin: string | null }): void { + if (url && url.indexOf("data:") === 0) { + return; + } + if (Tools.CorsBehavior) { - switch (typeof (Tools.CorsBehavior)) { - case "function": - var result = Tools.CorsBehavior(url); - if (result) { - img.crossOrigin = result; - } - break; - case "string": - default: - img.crossOrigin = Tools.CorsBehavior; - break; + if (typeof(Tools.CorsBehavior) === 'string' || Tools.CorsBehavior instanceof String) { + element.crossOrigin = Tools.CorsBehavior; + } + else { + var result = Tools.CorsBehavior(url); + if (result) { + element.crossOrigin = result; + } } } } @@ -421,10 +429,7 @@ url = Tools.PreprocessUrl(url); var img = new Image(); - - if (url.substr(0, 5) !== "data:") { - Tools.SetCorsBehavior(url, img); - } + Tools.SetCorsBehavior(url, img); img.onload = () => { onLoad(img); From 107b08e78077f023fecdadd355600345b4f76302 Mon Sep 17 00:00:00 2001 From: Raanan Weber Date: Mon, 4 Dec 2017 18:20:22 -0800 Subject: [PATCH 21/27] Checking if Tags exist --- src/Materials/babylon.multiMaterial.ts | 20 +++++++++++--------- src/Mesh/babylon.mesh.ts | 2 +- src/babylon.scene.ts | 10 +++++----- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Materials/babylon.multiMaterial.ts b/src/Materials/babylon.multiMaterial.ts index 318af9b2aa1..2dca5d4cfc8 100644 --- a/src/Materials/babylon.multiMaterial.ts +++ b/src/Materials/babylon.multiMaterial.ts @@ -9,10 +9,10 @@ this._subMaterials = value; this._hookArray(value); } - + constructor(name: string, scene: Scene) { super(name, scene, true); - + scene.multiMaterials.push(this); this.subMaterials = new Array(); @@ -38,7 +38,7 @@ return deleted; } - } + } // Properties public getSubMaterial(index: number): Nullable { @@ -52,10 +52,11 @@ public getActiveTextures(): BaseTexture[] { return super.getActiveTextures().concat(...this.subMaterials.map(subMaterial => { if (subMaterial) { - return subMaterial.getActiveTextures(); - } else { - return []; - }})); + return subMaterial.getActiveTextures(); + } else { + return []; + } + })); } // Methods @@ -105,8 +106,9 @@ serializationObject.name = this.name; serializationObject.id = this.id; - serializationObject.tags = Tags.GetTags(this); - + if (Tags) { + serializationObject.tags = Tags.GetTags(this); + } serializationObject.materials = []; for (var matIndex = 0; matIndex < this.subMaterials.length; matIndex++) { diff --git a/src/Mesh/babylon.mesh.ts b/src/Mesh/babylon.mesh.ts index e6a1f3deb07..d884396bc60 100644 --- a/src/Mesh/babylon.mesh.ts +++ b/src/Mesh/babylon.mesh.ts @@ -178,7 +178,7 @@ Tools.DeepCopy(source, this, ["name", "material", "skeleton", "instances", "parent", "uniqueId", "source"], ["_poseMatrix", "_source"]); // Tags - if (Tags.HasTags(source)) { + if (Tags && Tags.HasTags(source)) { Tags.AddTagsTo(this, Tags.GetTags(source, true)); } diff --git a/src/babylon.scene.ts b/src/babylon.scene.ts index de1335d988c..d9f94975b5c 100644 --- a/src/babylon.scene.ts +++ b/src/babylon.scene.ts @@ -3377,7 +3377,7 @@ let defaultFrameTime = 1000 / 60; // frame time in MS if (this._physicsEngine) { - defaultFrameTime = this._physicsEngine.getTimeStep() / 1000; //timestep in physics engine is in seconds + defaultFrameTime = this._physicsEngine.getTimeStep() * 1000; } let stepsTaken = 0; @@ -3397,7 +3397,7 @@ // Physics if (this._physicsEngine) { this.onBeforePhysicsObservable.notifyObservers(this); - this._physicsEngine._step(defaultFPS); + this._physicsEngine._step((defaultFrameTime / 1000)); this.onAfterPhysicsObservable.notifyObservers(this); } @@ -3411,9 +3411,9 @@ stepsTaken++; deltaTime -= defaultFrameTime; - } while (deltaTime > 0 && stepsTaken < maxSubSteps); + } while (deltaTime > 0 && stepsTaken < internalSteps); - this._timeAccumulator = deltaTime; + this._timeAccumulator = 0; //deltaTime < 0 ? 0 : deltaTime; } else { @@ -4492,7 +4492,7 @@ for (var i in list) { var item = list[i]; - if (Tags.MatchesQuery(item, tagsQuery)) { + if (Tags && Tags.MatchesQuery(item, tagsQuery)) { listByTags.push(item); forEach(item); } From 8f4cc191af3b60b71dc26465fc1f9df653c20d8f Mon Sep 17 00:00:00 2001 From: Raanan Weber Date: Mon, 4 Dec 2017 18:23:59 -0800 Subject: [PATCH 22/27] picking is a physics dependency The physicsHelper is using it --- Tools/Gulp/config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tools/Gulp/config.json b/Tools/Gulp/config.json index 2f2aa631e56..78b5f4f269a 100644 --- a/Tools/Gulp/config.json +++ b/Tools/Gulp/config.json @@ -931,7 +931,8 @@ "../../src/Physics/Plugins/babylon.oimoJSPlugin.js" ], "dependUpon": [ - "core" + "core", + "picking" ] }, "textureFormats": { From 28b45639bfcc56db54af73f09d3ad03a8791c45d Mon Sep 17 00:00:00 2001 From: Raanan Weber Date: Mon, 4 Dec 2017 18:29:05 -0800 Subject: [PATCH 23/27] revert small changes --- src/babylon.scene.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/babylon.scene.ts b/src/babylon.scene.ts index d9f94975b5c..2f36dc625e5 100644 --- a/src/babylon.scene.ts +++ b/src/babylon.scene.ts @@ -3377,7 +3377,7 @@ let defaultFrameTime = 1000 / 60; // frame time in MS if (this._physicsEngine) { - defaultFrameTime = this._physicsEngine.getTimeStep() * 1000; + defaultFrameTime = this._physicsEngine.getTimeStep() / 1000; } let stepsTaken = 0; @@ -3397,7 +3397,7 @@ // Physics if (this._physicsEngine) { this.onBeforePhysicsObservable.notifyObservers(this); - this._physicsEngine._step((defaultFrameTime / 1000)); + this._physicsEngine._step(defaultFPS); this.onAfterPhysicsObservable.notifyObservers(this); } @@ -3411,9 +3411,9 @@ stepsTaken++; deltaTime -= defaultFrameTime; - } while (deltaTime > 0 && stepsTaken < internalSteps); + } while (deltaTime > 0 && stepsTaken < maxSubSteps); - this._timeAccumulator = 0; //deltaTime < 0 ? 0 : deltaTime; + this._timeAccumulator = deltaTime; } else { From 5d49e824d9662b16c8aab65426ee57f3af2fc752 Mon Sep 17 00:00:00 2001 From: Adam Bowman Date: Mon, 4 Dec 2017 22:39:14 -0500 Subject: [PATCH 24/27] fixed #3295 --- src/Cameras/babylon.camera.ts | 7 +++++++ src/Mesh/babylon.transformNode.ts | 8 ++++---- src/babylon.node.ts | 5 +++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Cameras/babylon.camera.ts b/src/Cameras/babylon.camera.ts index 3be4837b6d7..21550d39ea3 100644 --- a/src/Cameras/babylon.camera.ts +++ b/src/Cameras/babylon.camera.ts @@ -907,6 +907,13 @@ } } + public computeWorldMatrix(force?: boolean): Matrix { + if(force){ + this.getViewMatrix(force); + } + return this.getWorldMatrix(); + } + public static Parse(parsedCamera: any, scene: Scene): Camera { var type = parsedCamera.type; var construct = Camera.GetConstructorFromName(type, parsedCamera.name, scene, parsedCamera.interaxial_distance, parsedCamera.isStereoscopicSideBySide); diff --git a/src/Mesh/babylon.transformNode.ts b/src/Mesh/babylon.transformNode.ts index f16b59602b6..44f41425c27 100644 --- a/src/Mesh/babylon.transformNode.ts +++ b/src/Mesh/babylon.transformNode.ts @@ -450,15 +450,15 @@ module BABYLON { * The node will remain exactly where it is and its position / rotation will be updated accordingly * Returns the TransformNode. */ - public setParent(node: Nullable): TransformNode { + public setParent(node: Nullable): TransformNode { if (node == null) { var rotation = Tmp.Quaternion[0]; var position = Tmp.Vector3[0]; var scale = Tmp.Vector3[1]; - - if (this.parent && (this.parent).computeWorldMatrix) { - (this.parent).computeWorldMatrix(true); + + if (this.parent && this.parent.computeWorldMatrix) { + this.parent.computeWorldMatrix(true); } this.computeWorldMatrix(true); this.getWorldMatrix().decompose(scale, rotation, position); diff --git a/src/babylon.node.ts b/src/babylon.node.ts index ad20449a911..7ae995d213b 100644 --- a/src/babylon.node.ts +++ b/src/babylon.node.ts @@ -426,6 +426,11 @@ return serializationRanges; } + // override it in derived class + public computeWorldMatrix(force?: boolean): Matrix { + return Matrix.Identity(); + } + public dispose(): void { this.parent = null; From 6728aa8ced1a9cb33fba871ab6e3b74ed3855884 Mon Sep 17 00:00:00 2001 From: Adam Bowman Date: Mon, 4 Dec 2017 22:46:41 -0500 Subject: [PATCH 25/27] always call getViewMatrix in camera.computeWorldMatrix --- src/Cameras/babylon.camera.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Cameras/babylon.camera.ts b/src/Cameras/babylon.camera.ts index 21550d39ea3..7110346d56b 100644 --- a/src/Cameras/babylon.camera.ts +++ b/src/Cameras/babylon.camera.ts @@ -908,9 +908,7 @@ } public computeWorldMatrix(force?: boolean): Matrix { - if(force){ - this.getViewMatrix(force); - } + this.getViewMatrix(force); return this.getWorldMatrix(); } From 6f5cb194cddf43b2c54cc1473848a7d5cdb57f16 Mon Sep 17 00:00:00 2001 From: Adam Bowman Date: Mon, 4 Dec 2017 22:59:02 -0500 Subject: [PATCH 26/27] just call getWorldMatrix in camera.computeWorldMatrix --- src/Cameras/babylon.camera.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Cameras/babylon.camera.ts b/src/Cameras/babylon.camera.ts index 7110346d56b..db9e7b7d7bb 100644 --- a/src/Cameras/babylon.camera.ts +++ b/src/Cameras/babylon.camera.ts @@ -907,8 +907,7 @@ } } - public computeWorldMatrix(force?: boolean): Matrix { - this.getViewMatrix(force); + public computeWorldMatrix(): Matrix { return this.getWorldMatrix(); } From 7829ae410de4caa63b51d495620ac5eaf3c8554a Mon Sep 17 00:00:00 2001 From: jchenard Date: Tue, 5 Dec 2017 10:26:06 +0100 Subject: [PATCH 27/27] Fix inspector for IE (colorpicker elements are not supported) --- dist/inspector/babylon.inspector.css | 17 ++++----- .../inspector/babylon.inspector.bundle.js | 6 ++-- .../inspector/babylon.inspector.d.ts | 4 +++ .../inspector/babylon.inspector.js | 13 +++++-- .../inspector/babylon.inspector.min.js | 8 ++--- inspector/src/details/PropertyLine.ts | 5 +-- inspector/src/helpers/Helpers.ts | 8 +++++ inspector/test/index.js | 35 ++++++++++--------- 8 files changed, 58 insertions(+), 38 deletions(-) diff --git a/dist/inspector/babylon.inspector.css b/dist/inspector/babylon.inspector.css index 5d9df028c65..44414824ed0 100644 --- a/dist/inspector/babylon.inspector.css +++ b/dist/inspector/babylon.inspector.css @@ -1,6 +1,3 @@ -@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css); -@import url(https://fonts.googleapis.com/css?family=Inconsolata); - @import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css); @import url(https://fonts.googleapis.com/css?family=Inconsolata); .insp-wrapper { @@ -9,14 +6,14 @@ font-size: 0.9em; font-family: "Inconsolata", sans-serif; background-color: #242424; - /** - * A tool contained in the tree panel (available for each item of the tree) + /** + * A tool contained in the tree panel (available for each item of the tree) */ - /** - * The toolbar contains : - * - a refresh tool - refresh the whole panel - * - a popup tool - Open the inspector in a new panel - * ... + /** + * The toolbar contains : + * - a refresh tool - refresh the whole panel + * - a popup tool - Open the inspector in a new panel + * ... */ } .insp-wrapper .gutter { background-color: #2c2c2c; } diff --git a/dist/preview release/inspector/babylon.inspector.bundle.js b/dist/preview release/inspector/babylon.inspector.bundle.js index f859188dec4..af35f4a67ef 100644 --- a/dist/preview release/inspector/babylon.inspector.bundle.js +++ b/dist/preview release/inspector/babylon.inspector.bundle.js @@ -1,4 +1,4 @@ var globalObject="undefined"!=typeof global?global:"undefined"!=typeof window?window:this,babylonDependency=globalObject&&globalObject.BABYLON||BABYLON||"undefined"!=typeof require&&require("babylonjs"),BABYLON=babylonDependency,INSPECTOR=(function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)})([(function(e,t,n){n(1),e.exports=n(5)}),(function(e,t,n){var r=n(2);"string"==typeof r&&(r=[[e.i,r,""]]);n(4)(r,{});r.locals&&(e.exports=r.locals)}),(function(e,t,n){t=e.exports=n(3)(),t.push([e.i,"@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);",""]),t.push([e.i,"@import url(https://fonts.googleapis.com/css?family=Inconsolata);",""]),t.push([e.i,'.insp-wrapper {\n user-select: none;\n display: flex;\n font-size: 0.9em;\n font-family: "Inconsolata", sans-serif;\n background-color: #242424;\n /**\r\n * A tool contained in the tree panel (available for each item of the tree)\r\n */\n /**\r\n * The toolbar contains : \r\n * - a refresh tool - refresh the whole panel\r\n * - a popup tool - Open the inspector in a new panel\r\n * ...\r\n */\n /*\r\n* 1. Set to 0 height and width, and remove border for a slider without a thumb\r\n*/ }\n .insp-wrapper .gutter {\n background-color: #2c2c2c; }\n .insp-wrapper .gutter.gutter-vertical:not(.blocked) {\n cursor: ns-resize; }\n .insp-wrapper .gutter.gutter-horizontal:not(.blocked) {\n cursor: ew-resize; }\n .insp-wrapper .insp-right-panel {\n width: 750px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n flex-shrink: 0; }\n .insp-wrapper .insp-right-panel.popupmode {\n width: 100% !important; }\n .insp-wrapper .insp-right-panel .top-panel {\n width: 100%;\n height: 100%;\n position: relative;\n background-color: #242424;\n color: #ccc;\n font-size: 1em; }\n .insp-wrapper .insp-right-panel .top-panel .tab-panel-content {\n width: 100%;\n height: calc(100% - 32px); }\n .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel {\n position: absolute;\n z-index: 10;\n top: 32px;\n right: 0;\n width: 100px;\n display: none;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border: 1px solid #454545;\n background-color: #242424; }\n .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel .invisible-tab {\n height: 25px;\n width: 100%;\n line-height: 25px;\n text-align: center;\n background-color: #2c2c2c;\n cursor: pointer; }\n .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel .invisible-tab:hover {\n background-color: #383838; }\n .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel .invisible-tab:active {\n background-color: #454545; }\n .insp-wrapper .tooltip {\n position: absolute;\n top: 32px;\n right: 0;\n color: #f29766;\n display: none;\n z-index: 4;\n font-family: "Inconsolata", sans-serif;\n padding: 2px;\n background-color: #242424;\n border: 1px solid #454545; }\n .insp-wrapper .treeTool {\n margin: 3px 8px 3px 3px;\n cursor: pointer;\n position: relative; }\n .insp-wrapper .treeTool:hover {\n color: #5db0d7; }\n .insp-wrapper .treeTool.active {\n color: #5db0d7; }\n .insp-wrapper .tab-panel {\n height: 100%; }\n .insp-wrapper .tab-panel.searchable {\n height: calc(100% - 30px - 10px); }\n .insp-wrapper .tab-panel .texture-image {\n max-height: 400px; }\n .insp-wrapper .tab-panel .scene-actions {\n overflow-y: auto;\n padding-left: 5px; }\n .insp-wrapper .tab-panel .scene-actions .actions-title {\n font-size: 1.1em;\n padding-bottom: 10px;\n border-bottom: 1px solid #5db0d7;\n margin: 10px 0 10px 0; }\n .insp-wrapper .tab-panel .scene-actions .defaut-action, .insp-wrapper .tab-panel .scene-actions .action-radio, .insp-wrapper .tab-panel .scene-actions .action {\n height: 20px;\n line-height: 20px;\n width: 100%;\n cursor: pointer; }\n .insp-wrapper .tab-panel .scene-actions .defaut-action:hover, .insp-wrapper .tab-panel .scene-actions .action-radio:hover, .insp-wrapper .tab-panel .scene-actions .action:hover {\n background-color: #2c2c2c; }\n .insp-wrapper .tab-panel .scene-actions .defaut-action:active, .insp-wrapper .tab-panel .scene-actions .action-radio:active, .insp-wrapper .tab-panel .scene-actions .action:active {\n background-color: #383838; }\n .insp-wrapper .tab-panel .scene-actions .action-radio:before {\n width: 1em;\n height: 1em;\n line-height: 1em;\n display: inline-block;\n font-family: \'FontAwesome\', sans-serif;\n content: "\\F10C";\n margin-right: 10px; }\n .insp-wrapper .tab-panel .scene-actions .action-radio.active:before {\n width: 1em;\n height: 1em;\n line-height: 1em;\n display: inline-block;\n font-family: \'FontAwesome\', sans-serif;\n content: "\\F192";\n color: #5db0d7;\n margin-right: 10px; }\n .insp-wrapper .tab-panel .scene-actions .action:before {\n width: 1em;\n height: 1em;\n line-height: 1em;\n display: inline-block;\n font-family: \'FontAwesome\', sans-serif;\n content: "\\F096";\n margin-right: 10px; }\n .insp-wrapper .tab-panel .scene-actions .action.active:before {\n width: 1em;\n height: 1em;\n line-height: 1em;\n display: inline-block;\n font-family: \'FontAwesome\', sans-serif;\n content: "\\F14A";\n color: #5db0d7;\n margin-right: 10px; }\n .insp-wrapper .tab-panel .shader-tree-panel {\n height: 30px; }\n .insp-wrapper .tab-panel .shader-tree-panel select {\n height: 30px;\n background-color: transparent;\n color: #ccc;\n height: 30px;\n width: 100%;\n max-width: 300px;\n padding-left: 15px;\n border: 1px solid #2c2c2c;\n outline: 1px solid #454545; }\n .insp-wrapper .tab-panel .shader-tree-panel select option {\n padding: 5px;\n color: gray; }\n .insp-wrapper .tab-panel .shader-panel {\n min-height: 100px;\n user-select: text;\n box-sizing: border-box;\n padding: 0 15px; }\n .insp-wrapper .tab-panel .shader-panel pre {\n margin: 0;\n white-space: pre-wrap; }\n .insp-wrapper .tab-panel .shader-panel pre code {\n background-color: #242424 !important;\n padding: 0;\n margin: 0; }\n .insp-wrapper .tab-panel .shader-panel .shader-panel-title {\n height: 25px;\n border-bottom: 1px solid #383838;\n text-transform: uppercase;\n line-height: 25px;\n margin-bottom: 10px; }\n .insp-wrapper .tab-panel .console-panel {\n min-height: 100px;\n user-select: text;\n box-sizing: border-box;\n padding: 0 15px; }\n .insp-wrapper .tab-panel .console-panel .console-panel-title {\n height: 25px;\n border-bottom: 1px solid #383838;\n text-transform: uppercase;\n line-height: 25px;\n margin-bottom: 10px; }\n .insp-wrapper .tab-panel .console-panel .console-panel-content {\n overflow-y: auto;\n overflow-x: hidden;\n height: calc(100% - 30px); }\n .insp-wrapper .tab-panel .console-panel .defaut-line, .insp-wrapper .tab-panel .console-panel .log, .insp-wrapper .tab-panel .console-panel .warn, .insp-wrapper .tab-panel .console-panel .error, .insp-wrapper .tab-panel .console-panel .object {\n word-wrap: break-word;\n padding: 3px 0 3px 5px; }\n .insp-wrapper .tab-panel .console-panel .caller {\n padding: 3px 0 3px 0;\n color: #349ccd; }\n .insp-wrapper .tab-panel .console-panel .log {\n color: white; }\n .insp-wrapper .tab-panel .console-panel .warn {\n color: orange; }\n .insp-wrapper .tab-panel .console-panel .error {\n color: orangered; }\n .insp-wrapper .tab-panel .console-panel .object {\n color: #5db0d7; }\n .insp-wrapper .tab-panel.stats-panel {\n overflow-y: auto; }\n .insp-wrapper .tab-panel .stats-fps {\n font-weight: 600;\n color: #f29766; }\n .insp-wrapper .tab-panel .stat-title1 {\n font-size: 1.1em;\n padding: 10px; }\n .insp-wrapper .tab-panel .stat-title2 {\n margin: 10px 0 10px 0;\n font-size: 1.05em;\n border-bottom: 1px solid #5db0d7;\n box-sizing: border-box; }\n .insp-wrapper .tab-panel .stat-label {\n display: inline-block;\n width: 80%;\n padding: 2px;\n background-color: #2c2c2c;\n border-bottom: 1px solid #242424;\n border-top: 1px solid #242424;\n height: 30px;\n line-height: 30px;\n box-sizing: border-box; }\n .insp-wrapper .tab-panel .stat-value {\n display: inline-block;\n width: 20%;\n padding: 2px;\n background-color: #2c2c2c;\n border-top: 1px solid #242424;\n border-bottom: 1px solid #242424;\n height: 30px;\n line-height: 30px;\n box-sizing: border-box; }\n .insp-wrapper .tab-panel .stat-infos {\n width: 100%;\n padding: 4px; }\n .insp-wrapper .property-type {\n color: #5db0d7; }\n .insp-wrapper .property-name, .insp-wrapper .insp-details .base-row .prop-name, .insp-wrapper .insp-details .row .prop-name, .insp-wrapper .insp-details .header-row .prop-name {\n color: #f29766; }\n .insp-wrapper .insp-tree {\n overflow-y: auto;\n overflow-x: hidden;\n height: calc(50% - 32px - 30px); }\n .insp-wrapper .insp-tree .line {\n padding: 3px;\n cursor: pointer; }\n .insp-wrapper .insp-tree .line:hover {\n background-color: #2c2c2c; }\n .insp-wrapper .insp-tree .line.active {\n background-color: #454545; }\n .insp-wrapper .insp-tree .line.active .line-content {\n background-color: #242424; }\n .insp-wrapper .insp-tree .line.unfolded:before {\n width: 1em;\n height: 1em;\n line-height: 1em;\n display: inline-block;\n font-family: \'FontAwesome\', sans-serif;\n content: "\\F078"; }\n .insp-wrapper .insp-tree .line.folded:before {\n width: 1em;\n height: 1em;\n line-height: 1em;\n display: inline-block;\n font-family: \'FontAwesome\', sans-serif;\n content: "\\F054"; }\n .insp-wrapper .insp-tree .line.unfolded.transformNode > span:first-of-type {\n color: #f29766; }\n .insp-wrapper .insp-tree .line.folded.transformNode > span:first-of-type {\n color: #f29766; }\n .insp-wrapper .insp-tree .line .line-content {\n padding-left: 15px; }\n .insp-wrapper .insp-tree .line .line-content:hover {\n background-color: #242424; }\n .insp-wrapper .insp-tree .line .line-content .line:hover:first-child {\n background-color: #383838; }\n .insp-wrapper .insp-details {\n background-color: #242424;\n overflow-y: auto;\n overflow-x: auto;\n color: #ccc;\n font-family: "Inconsolata", sans-serif; }\n .insp-wrapper .insp-details .details {\n padding-left: 5px; }\n .insp-wrapper .insp-details .base-row, .insp-wrapper .insp-details .row, .insp-wrapper .insp-details .header-row {\n display: flex;\n width: 100%; }\n .insp-wrapper .insp-details .base-row .base-property, .insp-wrapper .insp-details .row .base-property, .insp-wrapper .insp-details .header-row .base-property, .insp-wrapper .insp-details .base-row .prop-name, .insp-wrapper .insp-details .row .prop-name, .insp-wrapper .insp-details .header-row .prop-name, .insp-wrapper .insp-details .base-row .prop-value, .insp-wrapper .insp-details .row .prop-value, .insp-wrapper .insp-details .header-row .prop-value {\n padding: 2px 0 2px 0;\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden; }\n .insp-wrapper .insp-details .base-row .prop-name, .insp-wrapper .insp-details .row .prop-name, .insp-wrapper .insp-details .header-row .prop-name {\n width: 35%; }\n .insp-wrapper .insp-details .base-row .prop-value, .insp-wrapper .insp-details .row .prop-value, .insp-wrapper .insp-details .header-row .prop-value {\n width: 59%;\n padding-left: 10px; }\n .insp-wrapper .insp-details .base-row .prop-value.clickable, .insp-wrapper .insp-details .row .prop-value.clickable, .insp-wrapper .insp-details .header-row .prop-value.clickable {\n cursor: pointer; }\n .insp-wrapper .insp-details .base-row .prop-value.clickable:hover, .insp-wrapper .insp-details .row .prop-value.clickable:hover, .insp-wrapper .insp-details .header-row .prop-value.clickable:hover {\n background-color: #383838; }\n .insp-wrapper .insp-details .base-row .prop-value.clickable:after, .insp-wrapper .insp-details .row .prop-value.clickable:after, .insp-wrapper .insp-details .header-row .prop-value.clickable:after {\n font-family: \'FontAwesome\', sans-serif;\n content: "\\A0 \\A0 \\A0 \\F054"; }\n .insp-wrapper .insp-details .row:nth-child(even) {\n background-color: #2c2c2c; }\n .insp-wrapper .insp-details .row.unfolded .prop-value.clickable:after {\n font-family: \'FontAwesome\', sans-serif;\n content: "\\A0 \\A0 \\A0 \\F078"; }\n .insp-wrapper .insp-details .header-row {\n background-color: #2c2c2c;\n color: #ccc;\n width: 100%;\n max-width: 100%; }\n .insp-wrapper .insp-details .header-row > * {\n color: #ccc !important;\n padding: 5px 0 5px 5px !important;\n cursor: pointer; }\n .insp-wrapper .insp-details .header-row > *:hover {\n background-color: #383838; }\n .insp-wrapper .insp-details .header-row .header-col {\n display: flex;\n justify-content: space-between;\n align-items: center; }\n .insp-wrapper .insp-details .header-row .header-col .sort-direction {\n margin-right: 5px; }\n .insp-wrapper .insp-details .element-viewer, .insp-wrapper .insp-details .color-element, .insp-wrapper .insp-details .texture-element {\n position: relative;\n width: 10px;\n height: 10px;\n display: inline-block;\n margin-left: 5px; }\n .insp-wrapper .insp-details .color-element {\n top: 2px; }\n .insp-wrapper .insp-details .texture-element {\n color: #f29766;\n margin-left: 10px; }\n .insp-wrapper .insp-details .texture-element .texture-viewer {\n color: #ccc;\n position: absolute;\n z-index: 10;\n bottom: 0;\n right: 0;\n display: block;\n width: 150px;\n height: 150px;\n border: 1px solid #454545;\n background-color: #242424;\n transform: translateX(100%) translateY(100%);\n display: none;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center; }\n .insp-wrapper .insp-details .texture-element .texture-viewer .texture-viewer-img {\n margin: 10px 0 10px 0;\n max-width: 110px;\n max-height: 110px; }\n .insp-wrapper .tabbar {\n height: 32px;\n display: flex;\n align-items: center;\n border-bottom: 1px solid #383838;\n width: 100%;\n overflow-x: auto;\n overflow-y: hidden;\n box-sizing: border-box; }\n .insp-wrapper .tabbar .tab {\n height: calc(32px - 2px);\n width: auto;\n padding: 0 10px 0 10px;\n color: #ccc;\n line-height: 32px;\n text-align: center;\n cursor: pointer;\n margin: 0 5px 0 5px;\n box-sizing: border-box; }\n .insp-wrapper .tabbar .tab:hover {\n border-bottom: 1px solid #f29766;\n background-color: #2c2c2c; }\n .insp-wrapper .tabbar .tab:active {\n background-color: #383838; }\n .insp-wrapper .tabbar .tab.active {\n border-bottom: 1px solid #f29766; }\n .insp-wrapper .tabbar .more-tabs {\n width: 32px;\n height: 32px;\n display: flex;\n justify-content: center;\n align-items: center;\n cursor: pointer;\n position: relative;\n border-right: 1px solid #383838; }\n .insp-wrapper .tabbar .more-tabs:hover {\n background-color: #383838; }\n .insp-wrapper .tabbar .more-tabs:active {\n color: #f29766;\n background-color: #454545; }\n .insp-wrapper .tabbar .more-tabs.active {\n color: #f29766; }\n .insp-wrapper .toolbar {\n display: flex; }\n .insp-wrapper .toolbar .tool {\n width: 32px;\n height: 32px;\n display: flex;\n justify-content: center;\n align-items: center;\n cursor: pointer;\n position: relative;\n border-right: 1px solid #383838; }\n .insp-wrapper .toolbar .tool:hover {\n background-color: #383838; }\n .insp-wrapper .toolbar .tool:active {\n color: #f29766;\n background-color: #454545; }\n .insp-wrapper .toolbar .tool.active {\n color: #f29766; }\n .insp-wrapper .searchbar {\n border: 1px solid #2c2c2c;\n margin-bottom: 5px;\n display: flex;\n align-items: center;\n color: #b3b3b3; }\n .insp-wrapper .searchbar input {\n background-color: #242424;\n border: none;\n width: 100%;\n outline: none;\n font-family: "Inconsolata", sans-serif;\n color: #b3b3b3;\n padding: 3px 0 3px 10px;\n margin: 6px 0 6px 0; }\n .insp-wrapper input[type="range"] {\n margin: auto;\n -webkit-appearance: none;\n position: relative;\n overflow: hidden;\n height: 15px;\n width: 50%;\n cursor: pointer;\n border-radius: 0;\n /* iOS */ }\n .insp-wrapper ::-webkit-slider-runnable-track {\n background: #ddd; }\n .insp-wrapper ::-webkit-slider-thumb {\n -webkit-appearance: none;\n width: 20px;\n /* 1 */\n height: 15px;\n /* 1 */\n background: #fff;\n box-shadow: -100vw 0 0 100vw dodgerblue;\n border: 0px solid #999;\n /* 1 */ }\n .insp-wrapper ::-moz-range-track {\n height: 15px;\n background: #ddd; }\n .insp-wrapper ::-moz-range-thumb {\n background: #fff;\n height: 15px;\n width: 20px;\n border: 0px solid #999;\n border-radius: 0 !important;\n box-shadow: -100vw 0 0 100vw dodgerblue;\n box-sizing: border-box; }\n .insp-wrapper ::-ms-fill-lower {\n background: dodgerblue; }\n .insp-wrapper ::-ms-thumb {\n background: #fff;\n border: 0px solid #999;\n height: 15px;\n width: 20px;\n box-sizing: border-box; }\n .insp-wrapper ::-ms-ticks-after {\n display: none; }\n .insp-wrapper ::-ms-ticks-before {\n display: none; }\n .insp-wrapper ::-ms-track {\n background: #ddd;\n color: transparent;\n height: 15px;\n border: none; }\n .insp-wrapper ::-ms-tooltip {\n display: none; }\n',""])}),(function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t=0&&m.splice(t,1)}function a(e){var t=document.createElement("style");return t.type="text/css",i(e,t),t}function s(e){var t=document.createElement("link");return t.rel="stylesheet",i(e,t),t}function p(e,t){var n,r,i;if(t.singleton){var p=b++;n=v||(v=a(t)),r=l.bind(null,n,p,!1),i=l.bind(null,n,p,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=s(t),r=u.bind(null,n),i=function(){o(n),n.href&&URL.revokeObjectURL(n.href)}):(n=a(t),r=c.bind(null,n),i=function(){o(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else i()}}function l(e,t,n,r){var i=n?"":r.css;if(e.styleSheet)e.styleSheet.cssText=g(t,i);else{var o=document.createTextNode(i),a=e.childNodes;a[t]&&e.removeChild(a[t]),a.length?e.insertBefore(o,a[t]):e.appendChild(o)}}function c(e,t){var n=t.css,r=t.media;if(r&&e.setAttribute("media",r),e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}function u(e,t){var n=t.css,r=t.sourceMap;r&&(n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var i=new Blob([n],{type:"text/css"}),o=e.href;e.href=URL.createObjectURL(i),o&&URL.revokeObjectURL(o)}var d={},h=function(e){var t;return function(){return void 0===t&&(t=e.apply(this,arguments)),t}},_=h((function(){return/msie [6-9]\b/.test(self.navigator.userAgent.toLowerCase())})),f=h((function(){return document.head||document.getElementsByTagName("head")[0]})),v=null,b=0,m=[];e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");t=t||{},void 0===t.singleton&&(t.singleton=_()),void 0===t.insertAt&&(t.insertAt="bottom");var i=r(e);return n(i,t),function(e){for(var o=[],a=0;a=t.WINDOW.innerWidth&&(this._c2diwrapper.style.maxWidth=_-v+"px")}var b=this._getRelativeParent(l),m=b.clientWidth,g=b.clientHeight,y=_/m*100,w=f/g*100;this._c2diwrapper.style.width=y+"%",this._c2diwrapper.style.height=w+"%",l.style.position="static",l.style.width="100%",l.style.height="100%",l.style.paddingBottom="0",l.style.paddingLeft="0",l.style.paddingTop="0",l.style.paddingRight="0",l.style.margin="0",l.style.marginBottom="0",l.style.marginLeft="0",l.style.marginTop="0",l.style.marginRight="0",c&&c.replaceChild(this._c2diwrapper,l),this._c2diwrapper.appendChild(l);var d=e.Helpers.CreateDiv("insp-right-panel",this._c2diwrapper);this._parentElement||i([l,d],{direction:"horizontal",sizes:[75,25],onDrag:function(){e.Helpers.SEND_EVENT("resize"),p._tabbar&&p._tabbar.updateWidth()}}),this._buildInspector(d)}e.Helpers.SEND_EVENT("resize"),this._tabbar.updateWidth()}if(e.Helpers.IsBrowserEdge()||this.refresh(),s)for(var x=s.backgroundColor||"#242424",C=s.backgroundColorLighter||"#2c2c2c",T=s.backgroundColorLighter2||"#383838",O=s.backgroundColorLighter3||"#454545",L=s.color||"#ccc",P=s.colorTop||"#f29766",A=s.colorBot||"#5db0d7",B=t.DOCUMENT.querySelectorAll("style"),E=0;E0&&t.push(new e.BoundingBox(this)),t.push(new e.Info(this)),t},n.prototype.setVisible=function(e){this._obj.setEnabled(e),this._obj.isVisible=e},n.prototype.isVisible=function(){return this._obj.isEnabled()&&(void 0===this._obj.isVisible||this._obj.isVisible)},n.prototype.isBoxVisible=function(){return this._obj.showBoundingBox},n.prototype.setBoxVisible=function(e){return this._obj.showBoundingBox=e},n.prototype.debug=function(e){if(this._axesViewer||this._drawAxis(),!e&&this._axesViewer){this._obj.getScene().onBeforeRenderObservable.remove(this.onBeforeRenderObserver),this._axesViewer.dispose(),this._axesViewer=null}},n.prototype.getInfo=function(){return this._obj instanceof BABYLON.AbstractMesh?this._obj.getTotalVertices()+" vertices":"0 vertices"},n.prototype._drawAxis=function(){var e=this;this._obj.computeWorldMatrix();var t=new BABYLON.Vector3(1,0,0),n=new BABYLON.Vector3(0,1,0),r=new BABYLON.Vector3(0,0,1);this._axesViewer=new BABYLON.Debug.AxesViewer(this._obj.getScene());var i=this._obj;this.onBeforeRenderObserver=i.getScene().onBeforeRenderObservable.add((function(){var o=i.getWorldMatrix(),a=new BABYLON.Vector3(1,1,1);i instanceof BABYLON.AbstractMesh&&(a=i.getBoundingInfo().boundingBox.extendSizeWorld),e._axesViewer.scaleLines=2*Math.max(a.x,a.y,a.z),e._axesViewer.update(e._obj.position,BABYLON.Vector3.TransformNormal(t,o),BABYLON.Vector3.TransformNormal(n,o),BABYLON.Vector3.TransformNormal(r,o))}))},n})(e.Adapter);e.MeshAdapter=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(t){function n(e){var n=t.call(this)||this;return n._detailRows=[],n._sortDirection={},n._build(),e&&(n._detailRows=e,n.update()),n}return o(n,t),Object.defineProperty(n.prototype,"details",{set:function(e){this.clean(),this._detailRows=e,this.update()},enumerable:!0,configurable:!0}),n.prototype._build=function(){this._div.className="insp-details",this._div.id="insp-details",this._createHeaderRow(),this._div.appendChild(this._headerRow)},n.prototype.update=function(){this._sortDetails("name",1),this._addDetails()},n.prototype._addDetails=function(){for(var t=e.Helpers.CreateDiv("details",this._div),n=0,r=this._detailRows;n0))return null;for(var i=0,o=r.children;i0){for(var o=new e.TreeItem(t,new e.GUIAdapter(n)),a=0,s=i;a0){for(var p=0,l=a;p=i._tabs.length)&&(r=0),i._tabs[r].active(!0);for(var o=0,a=i._tabs;o0&&t>e;){var n=this._visibleTabs.pop();if(!n)break;this._invisibleTabs.push(n),this._div.removeChild(n.toHtml()),t=this.getPixelWidth()+75}if(this._invisibleTabs.length>0&&t+750&&!this._div.contains(this._moreTabsIcon)&&this._div.appendChild(this._moreTabsIcon)}},n})(e.BasicElement);e.TabBar=t})(r||(r={}));var r;!(function(e){var t=(function(){function t(t,n,r,i){var o=this;this._inspector=r,this._elem=e.Inspector.DOCUMENT.createElement("i"),this._elem.className="tool fa "+t,n.appendChild(this._elem),this._elem.addEventListener("click",(function(e){o.action()})),new e.Tooltip(this._elem,i)}return t.prototype.toHtml=function(){return this._elem},t.prototype.getPixelWidth=function(){var t=e.Inspector.WINDOW.getComputedStyle(this._elem);if(!t.marginLeft||!t.marginRight)return 0;var n=parseFloat(t.marginLeft.substr(0,t.marginLeft.length-2))||0,r=parseFloat(t.marginRight.substr(0,t.marginRight.length-2))||0;return(this._elem.clientWidth||0)+n+r},t.prototype._updateIcon=function(e){this._elem.className="tool fa "+e},t})();e.AbstractTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(t){function n(e,n){var r=t.call(this,"fa-pause",e,n,"Pause the automatic update of properties")||this;return r._isPause=!1,r}return o(n,t),n.prototype.action=function(){this._isPause?(e.Scheduler.getInstance().pause=!1,this._updateIcon("fa-pause")):(e.Scheduler.getInstance().pause=!0,this._updateIcon("fa-play")),this._isPause=!this._isPause},n})(e.AbstractTool);e.PauseScheduleTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(e){function t(t,n){var r=e.call(this,"fa-mouse-pointer",t,n,"Select a mesh in the scene")||this;return r._isActive=!1,r._pickHandler=r._pickMesh.bind(r),r}return o(t,e),t.prototype.action=function(){if(this._isActive)this._deactivate();else{this.toHtml().classList.add("active");this._inspector.scene.getEngine().getRenderingCanvas().addEventListener("click",this._pickHandler),this._isActive=!0}},t.prototype._deactivate=function(){this.toHtml().classList.remove("active"),this._inspector.scene.getEngine().getRenderingCanvas().removeEventListener("click",this._pickHandler),this._isActive=!1},t.prototype._pickMesh=function(e){var t=this._updatePointerPosition(e),n=this._inspector.scene.pick(t.x,t.y,(function(e){return!0}));n&&n.pickedMesh&&this._inspector.displayObjectDetails(n.pickedMesh),this._deactivate()},t.prototype._updatePointerPosition=function(e){var t=this._inspector.scene.getEngine().getRenderingCanvasClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},t})(e.AbstractTool);e.PickTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(e){function t(t,n){return e.call(this,"fa-external-link",t,n,"Open the inspector in a popup")||this}return o(t,e),t.prototype.action=function(){this._inspector.openPopup()},t})(e.AbstractTool);e.PopupTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(e){function t(t,n){return e.call(this,"fa-refresh",t,n,"Refresh the current tab")||this}return o(t,e),t.prototype.action=function(){this._inspector.refresh()},t})(e.AbstractTool);e.RefreshTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(t){function n(e,n){var r=t.call(this,"fa-tags",e,n,"Display mesh names on the canvas")||this;return r._isDisplayed=!1,r._advancedTexture=null,r._labelInitialized=!1,r._scene=null,r._guiLoaded=!1,r._scene=n.scene,r}return o(n,t),n.prototype.dispose=function(){this._advancedTexture&&this._advancedTexture.dispose()},n.prototype._checkGUILoaded=function(){return!0===this._guiLoaded||(BABYLON.GUI&&(this._guiLoaded=!0),this._guiLoaded)},n.prototype._initializeLabels=function(){var e=this;if(!this._labelInitialized&&this._scene&&this._checkGUILoaded()){this._advancedTexture=BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");for(var t=0,n=this._scene.meshes;t0){for(var e=0,t=this.children;e0){for(var e=0,t=this.children;e0&&(this._div.classList.contains("folded")||this._div.classList.contains("unfolded")||this._div.classList.add("folded")),this.fold()},n.prototype._addEvent=function(){var e=this;this._div.addEventListener("click",(function(t){e._tab.select(e),e._isFolded()?e.unfold():e.fold(),t.stopPropagation()}))},n.prototype._isFolded=function(){return!this._div.classList.contains("unfolded")},n.prototype.active=function(e){this._div.classList.remove("active");for(var t=0,n=this.children;tthis.aMin+t.snapOffset+this.aGutterSize?n0&&(B={a:l(e[u-1]),b:E,aMin:t.minSize[u-1],bMin:t.minSize[u],dragging:!1,parent:L,isFirst:S,isLast:I,direction:t.direction},B.aGutterSize=t.gutterSize,B.bGutterSize=t.gutterSize,S&&(B.aGutterSize=t.gutterSize/2),I&&(B.bGutterSize=t.gutterSize/2)),!r){if(u>0){var N=i.createElement("div");N.className=f,N.style[c]=t.gutterSize+"px",N[o]("mousedown",g.bind(B)),N[o]("touchstart",g.bind(B)),L.insertBefore(N,E),B.gutter=N}(0===u||u==e.length-1)&&(H=t.gutterSize/2)}T(E,D,H),u>0&&m.push(B)}return{setSizes:function(e){for(var t=0;t0){var n=m[t-1];T(n.a,e[t-1],n.aGutterSize),T(n.b,e[t],n.bGutterSize)}},collapse:function(e){var t;e===m.length?(t=m[e-1],x.call(t),C.call(t,t.size-t.bGutterSize)):(t=m[e],x.call(t),C.call(t,t.aGutterSize))},destroy:function(){for(var e=0;e0&&t.push(new e.BoundingBox(this)),t.push(new e.Info(this)),t},n.prototype.setVisible=function(e){this._obj.setEnabled(e),this._obj.isVisible=e},n.prototype.isVisible=function(){return this._obj.isEnabled()&&(void 0===this._obj.isVisible||this._obj.isVisible)},n.prototype.isBoxVisible=function(){return this._obj.showBoundingBox},n.prototype.setBoxVisible=function(e){return this._obj.showBoundingBox=e},n.prototype.debug=function(e){if(this._axesViewer||this._drawAxis(),!e&&this._axesViewer){this._obj.getScene().onBeforeRenderObservable.remove(this.onBeforeRenderObserver),this._axesViewer.dispose(),this._axesViewer=null}},n.prototype.getInfo=function(){return this._obj instanceof BABYLON.AbstractMesh?this._obj.getTotalVertices()+" vertices":"0 vertices"},n.prototype._drawAxis=function(){var e=this;this._obj.computeWorldMatrix();var t=new BABYLON.Vector3(1,0,0),n=new BABYLON.Vector3(0,1,0),r=new BABYLON.Vector3(0,0,1);this._axesViewer=new BABYLON.Debug.AxesViewer(this._obj.getScene());var i=this._obj;this.onBeforeRenderObserver=i.getScene().onBeforeRenderObservable.add((function(){var o=i.getWorldMatrix(),a=new BABYLON.Vector3(1,1,1);i instanceof BABYLON.AbstractMesh&&(a=i.getBoundingInfo().boundingBox.extendSizeWorld),e._axesViewer.scaleLines=2*Math.max(a.x,a.y,a.z),e._axesViewer.update(e._obj.position,BABYLON.Vector3.TransformNormal(t,o),BABYLON.Vector3.TransformNormal(n,o),BABYLON.Vector3.TransformNormal(r,o))}))},n})(e.Adapter);e.MeshAdapter=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(t){function n(e){var n=t.call(this)||this;return n._detailRows=[],n._sortDirection={},n._build(),e&&(n._detailRows=e,n.update()),n}return o(n,t),Object.defineProperty(n.prototype,"details",{set:function(e){this.clean(),this._detailRows=e,this.update()},enumerable:!0,configurable:!0}),n.prototype._build=function(){this._div.className="insp-details",this._div.id="insp-details",this._createHeaderRow(),this._div.appendChild(this._headerRow)},n.prototype.update=function(){this._sortDetails("name",1),this._addDetails()},n.prototype._addDetails=function(){for(var t=e.Helpers.CreateDiv("details",this._div),n=0,r=this._detailRows;n0))return null;for(var i=0,o=r.children;i0){for(var o=new e.TreeItem(t,new e.GUIAdapter(n)),a=0,s=i;a0){for(var p=0,l=a;p=i._tabs.length)&&(r=0),i._tabs[r].active(!0);for(var o=0,a=i._tabs;o0&&t>e;){var n=this._visibleTabs.pop();if(!n)break;this._invisibleTabs.push(n),this._div.removeChild(n.toHtml()),t=this.getPixelWidth()+75}if(this._invisibleTabs.length>0&&t+750&&!this._div.contains(this._moreTabsIcon)&&this._div.appendChild(this._moreTabsIcon)}},n})(e.BasicElement);e.TabBar=t})(r||(r={}));var r;!(function(e){var t=(function(){function t(t,n,r,i){var o=this;this._inspector=r,this._elem=e.Inspector.DOCUMENT.createElement("i"),this._elem.className="tool fa "+t,n.appendChild(this._elem),this._elem.addEventListener("click",(function(e){o.action()})),new e.Tooltip(this._elem,i)}return t.prototype.toHtml=function(){return this._elem},t.prototype.getPixelWidth=function(){var t=e.Inspector.WINDOW.getComputedStyle(this._elem);if(!t.marginLeft||!t.marginRight)return 0;var n=parseFloat(t.marginLeft.substr(0,t.marginLeft.length-2))||0,r=parseFloat(t.marginRight.substr(0,t.marginRight.length-2))||0;return(this._elem.clientWidth||0)+n+r},t.prototype._updateIcon=function(e){this._elem.className="tool fa "+e},t})();e.AbstractTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(t){function n(e,n){var r=t.call(this,"fa-pause",e,n,"Pause the automatic update of properties")||this;return r._isPause=!1,r}return o(n,t),n.prototype.action=function(){this._isPause?(e.Scheduler.getInstance().pause=!1,this._updateIcon("fa-pause")):(e.Scheduler.getInstance().pause=!0,this._updateIcon("fa-play")),this._isPause=!this._isPause},n})(e.AbstractTool);e.PauseScheduleTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(e){function t(t,n){var r=e.call(this,"fa-mouse-pointer",t,n,"Select a mesh in the scene")||this;return r._isActive=!1,r._pickHandler=r._pickMesh.bind(r),r}return o(t,e),t.prototype.action=function(){if(this._isActive)this._deactivate();else{this.toHtml().classList.add("active");this._inspector.scene.getEngine().getRenderingCanvas().addEventListener("click",this._pickHandler),this._isActive=!0}},t.prototype._deactivate=function(){this.toHtml().classList.remove("active"),this._inspector.scene.getEngine().getRenderingCanvas().removeEventListener("click",this._pickHandler),this._isActive=!1},t.prototype._pickMesh=function(e){var t=this._updatePointerPosition(e),n=this._inspector.scene.pick(t.x,t.y,(function(e){return!0}));n&&n.pickedMesh&&this._inspector.displayObjectDetails(n.pickedMesh),this._deactivate()},t.prototype._updatePointerPosition=function(e){var t=this._inspector.scene.getEngine().getRenderingCanvasClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},t})(e.AbstractTool);e.PickTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(e){function t(t,n){return e.call(this,"fa-external-link",t,n,"Open the inspector in a popup")||this}return o(t,e),t.prototype.action=function(){this._inspector.openPopup()},t})(e.AbstractTool);e.PopupTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(e){function t(t,n){return e.call(this,"fa-refresh",t,n,"Refresh the current tab")||this}return o(t,e),t.prototype.action=function(){this._inspector.refresh()},t})(e.AbstractTool);e.RefreshTool=t})(r||(r={}));var r,o=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})();!(function(e){var t=(function(t){function n(e,n){var r=t.call(this,"fa-tags",e,n,"Display mesh names on the canvas")||this;return r._isDisplayed=!1,r._advancedTexture=null,r._labelInitialized=!1,r._scene=null,r._guiLoaded=!1,r._scene=n.scene,r}return o(n,t),n.prototype.dispose=function(){this._advancedTexture&&this._advancedTexture.dispose()},n.prototype._checkGUILoaded=function(){return!0===this._guiLoaded||(BABYLON.GUI&&(this._guiLoaded=!0),this._guiLoaded)},n.prototype._initializeLabels=function(){var e=this;if(!this._labelInitialized&&this._scene&&this._checkGUILoaded()){this._advancedTexture=BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");for(var t=0,n=this._scene.meshes;t0){for(var e=0,t=this.children;e0){for(var e=0,t=this.children;e0&&(this._div.classList.contains("folded")||this._div.classList.contains("unfolded")||this._div.classList.add("folded")),this.fold()},n.prototype._addEvent=function(){var e=this;this._div.addEventListener("click",(function(t){e._tab.select(e),e._isFolded()?e.unfold():e.fold(),t.stopPropagation()}))},n.prototype._isFolded=function(){return!this._div.classList.contains("unfolded")},n.prototype.active=function(e){this._div.classList.remove("active");for(var t=0,n=this.children;tthis.aMin+t.snapOffset+this.aGutterSize?n0&&(B={a:l(e[u-1]),b:E,aMin:t.minSize[u-1],bMin:t.minSize[u],dragging:!1,parent:L,isFirst:S,isLast:I,direction:t.direction},B.aGutterSize=t.gutterSize,B.bGutterSize=t.gutterSize,S&&(B.aGutterSize=t.gutterSize/2),I&&(B.bGutterSize=t.gutterSize/2)),!r){if(u>0){var N=i.createElement("div");N.className=f,N.style[c]=t.gutterSize+"px",N[o]("mousedown",g.bind(B)),N[o]("touchstart",g.bind(B)),L.insertBefore(N,E),B.gutter=N}(0===u||u==e.length-1)&&(H=t.gutterSize/2)}T(E,D,H),u>0&&m.push(B)}return{setSizes:function(e){for(var t=0;t0){var n=m[t-1];T(n.a,e[t-1],n.aGutterSize),T(n.b,e[t],n.bGutterSize)}},collapse:function(e){var t;e===m.length?(t=m[e-1],x.call(t),C.call(t,t.size-t.bGutterSize)):(t=m[e],x.call(t),C.call(t,t.aGutterSize))},destroy:function(){for(var e=0;e=t.WINDOW.innerWidth&&(this._c2diwrapper.style.maxWidth=h-f+"px")}var v=this._getRelativeParent(p),y=v.clientWidth,b=v.clientHeight,m=h/y*100,g=d/b*100;this._c2diwrapper.style.width=m+"%",this._c2diwrapper.style.height=g+"%",p.style.position="static",p.style.width="100%",p.style.height="100%",p.style.paddingBottom="0",p.style.paddingLeft="0",p.style.paddingTop="0",p.style.paddingRight="0",p.style.margin="0",p.style.marginBottom="0",p.style.marginLeft="0",p.style.marginTop="0",p.style.marginRight="0",c&&c.replaceChild(this._c2diwrapper,p),this._c2diwrapper.appendChild(p);var u=e.Helpers.CreateDiv("insp-right-panel",this._c2diwrapper);this._parentElement||Split([p,u],{direction:"horizontal",sizes:[75,25],onDrag:function(){e.Helpers.SEND_EVENT("resize"),a._tabbar&&a._tabbar.updateWidth()}}),this._buildInspector(u)}e.Helpers.SEND_EVENT("resize"),this._tabbar.updateWidth()}if(e.Helpers.IsBrowserEdge()||this.refresh(),s)for(var C=s.backgroundColor||"#242424",T=s.backgroundColorLighter||"#2c2c2c",O=s.backgroundColorLighter2||"#383838",P=s.backgroundColorLighter3||"#454545",E=s.color||"#ccc",I=s.colorTop||"#f29766",x=s.colorBot||"#5db0d7",S=t.DOCUMENT.querySelectorAll("style"),L=0;L0&&t.push(new e.BoundingBox(this)),t.push(new e.Info(this)),t},n.prototype.setVisible=function(e){this._obj.setEnabled(e),this._obj.isVisible=e},n.prototype.isVisible=function(){return this._obj.isEnabled()&&(void 0===this._obj.isVisible||this._obj.isVisible)},n.prototype.isBoxVisible=function(){return this._obj.showBoundingBox},n.prototype.setBoxVisible=function(e){return this._obj.showBoundingBox=e},n.prototype.debug=function(e){if(this._axesViewer||this._drawAxis(),!e&&this._axesViewer){this._obj.getScene().onBeforeRenderObservable.remove(this.onBeforeRenderObserver),this._axesViewer.dispose(),this._axesViewer=null}},n.prototype.getInfo=function(){return this._obj instanceof BABYLON.AbstractMesh?this._obj.getTotalVertices()+" vertices":"0 vertices"},n.prototype._drawAxis=function(){var e=this;this._obj.computeWorldMatrix();var t=new BABYLON.Vector3(1,0,0),n=new BABYLON.Vector3(0,1,0),r=new BABYLON.Vector3(0,0,1);this._axesViewer=new BABYLON.Debug.AxesViewer(this._obj.getScene());var i=this._obj;this.onBeforeRenderObserver=i.getScene().onBeforeRenderObservable.add((function(){var o=i.getWorldMatrix(),s=new BABYLON.Vector3(1,1,1);i instanceof BABYLON.AbstractMesh&&(s=i.getBoundingInfo().boundingBox.extendSizeWorld),e._axesViewer.scaleLines=2*Math.max(s.x,s.y,s.z),e._axesViewer.update(e._obj.position,BABYLON.Vector3.TransformNormal(t,o),BABYLON.Vector3.TransformNormal(n,o),BABYLON.Vector3.TransformNormal(r,o))}))},n})(e.Adapter);e.MeshAdapter=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(t){function n(e){var n=t.call(this)||this;return n._detailRows=[],n._sortDirection={},n._build(),e&&(n._detailRows=e,n.update()),n}return __extends(n,t),Object.defineProperty(n.prototype,"details",{set:function(e){this.clean(),this._detailRows=e,this.update()},enumerable:!0,configurable:!0}),n.prototype._build=function(){this._div.className="insp-details",this._div.id="insp-details",this._createHeaderRow(),this._div.appendChild(this._headerRow)},n.prototype.update=function(){this._sortDetails("name",1),this._addDetails()},n.prototype._addDetails=function(){for(var t=e.Helpers.CreateDiv("details",this._div),n=0,r=this._detailRows;n0))return null;for(var i=0,o=r.children;i0){for(var o=new e.TreeItem(t,new e.GUIAdapter(n)),s=0,a=i;s0){for(var p=0,c=s;p=i._tabs.length)&&(r=0),i._tabs[r].active(!0);for(var o=0,s=i._tabs;o0&&t>e;){var n=this._visibleTabs.pop();if(!n)break;this._invisibleTabs.push(n),this._div.removeChild(n.toHtml()),t=this.getPixelWidth()+75}if(this._invisibleTabs.length>0&&t+750&&!this._div.contains(this._moreTabsIcon)&&this._div.appendChild(this._moreTabsIcon)}},n})(e.BasicElement);e.TabBar=t})(INSPECTOR||(INSPECTOR={}));var INSPECTOR;!(function(e){var t=(function(){function t(t,n,r,i){var o=this;this._inspector=r,this._elem=e.Inspector.DOCUMENT.createElement("i"),this._elem.className="tool fa "+t,n.appendChild(this._elem),this._elem.addEventListener("click",(function(e){o.action()})),new e.Tooltip(this._elem,i)}return t.prototype.toHtml=function(){return this._elem},t.prototype.getPixelWidth=function(){var t=e.Inspector.WINDOW.getComputedStyle(this._elem);if(!t.marginLeft||!t.marginRight)return 0;var n=parseFloat(t.marginLeft.substr(0,t.marginLeft.length-2))||0,r=parseFloat(t.marginRight.substr(0,t.marginRight.length-2))||0;return(this._elem.clientWidth||0)+n+r},t.prototype._updateIcon=function(e){this._elem.className="tool fa "+e},t})();e.AbstractTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(t){function n(e,n){var r=t.call(this,"fa-pause",e,n,"Pause the automatic update of properties")||this;return r._isPause=!1,r}return __extends(n,t),n.prototype.action=function(){this._isPause?(e.Scheduler.getInstance().pause=!1,this._updateIcon("fa-pause")):(e.Scheduler.getInstance().pause=!0,this._updateIcon("fa-play")),this._isPause=!this._isPause},n})(e.AbstractTool);e.PauseScheduleTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(e){function t(t,n){var r=e.call(this,"fa-mouse-pointer",t,n,"Select a mesh in the scene")||this;return r._isActive=!1,r._pickHandler=r._pickMesh.bind(r),r}return __extends(t,e),t.prototype.action=function(){if(this._isActive)this._deactivate();else{this.toHtml().classList.add("active");this._inspector.scene.getEngine().getRenderingCanvas().addEventListener("click",this._pickHandler),this._isActive=!0}},t.prototype._deactivate=function(){this.toHtml().classList.remove("active"),this._inspector.scene.getEngine().getRenderingCanvas().removeEventListener("click",this._pickHandler),this._isActive=!1},t.prototype._pickMesh=function(e){var t=this._updatePointerPosition(e),n=this._inspector.scene.pick(t.x,t.y,(function(e){return!0}));n&&n.pickedMesh&&this._inspector.displayObjectDetails(n.pickedMesh),this._deactivate()},t.prototype._updatePointerPosition=function(e){var t=this._inspector.scene.getEngine().getRenderingCanvasClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},t})(e.AbstractTool);e.PickTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(e){function t(t,n){return e.call(this,"fa-external-link",t,n,"Open the inspector in a popup")||this}return __extends(t,e),t.prototype.action=function(){this._inspector.openPopup()},t})(e.AbstractTool);e.PopupTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(e){function t(t,n){return e.call(this,"fa-refresh",t,n,"Refresh the current tab")||this}return __extends(t,e),t.prototype.action=function(){this._inspector.refresh()},t})(e.AbstractTool);e.RefreshTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(t){function n(e,n){var r=t.call(this,"fa-tags",e,n,"Display mesh names on the canvas")||this;return r._isDisplayed=!1,r._advancedTexture=null,r._labelInitialized=!1,r._scene=null,r._guiLoaded=!1,r._scene=n.scene,r}return __extends(n,t),n.prototype.dispose=function(){this._advancedTexture&&this._advancedTexture.dispose()},n.prototype._checkGUILoaded=function(){return!0===this._guiLoaded||(BABYLON.GUI&&(this._guiLoaded=!0),this._guiLoaded)},n.prototype._initializeLabels=function(){var e=this;if(!this._labelInitialized&&this._scene&&this._checkGUILoaded()){this._advancedTexture=BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");for(var t=0,n=this._scene.meshes;t0){for(var e=0,t=this.children;e0){for(var e=0,t=this.children;e0&&(this._div.classList.contains("folded")||this._div.classList.contains("unfolded")||this._div.classList.add("folded")),this.fold()},n.prototype._addEvent=function(){var e=this;this._div.addEventListener("click",(function(t){e._tab.select(e),e._isFolded()?e.unfold():e.fold(),t.stopPropagation()}))},n.prototype._isFolded=function(){return!this._div.classList.contains("unfolded")},n.prototype.active=function(e){this._div.classList.remove("active");for(var t=0,n=this.children;t=t.WINDOW.innerWidth&&(this._c2diwrapper.style.maxWidth=h-f+"px")}var v=this._getRelativeParent(p),y=v.clientWidth,b=v.clientHeight,m=h/y*100,g=d/b*100;this._c2diwrapper.style.width=m+"%",this._c2diwrapper.style.height=g+"%",p.style.position="static",p.style.width="100%",p.style.height="100%",p.style.paddingBottom="0",p.style.paddingLeft="0",p.style.paddingTop="0",p.style.paddingRight="0",p.style.margin="0",p.style.marginBottom="0",p.style.marginLeft="0",p.style.marginTop="0",p.style.marginRight="0",c&&c.replaceChild(this._c2diwrapper,p),this._c2diwrapper.appendChild(p);var u=e.Helpers.CreateDiv("insp-right-panel",this._c2diwrapper);this._parentElement||Split([p,u],{direction:"horizontal",sizes:[75,25],onDrag:function(){e.Helpers.SEND_EVENT("resize"),a._tabbar&&a._tabbar.updateWidth()}}),this._buildInspector(u)}e.Helpers.SEND_EVENT("resize"),this._tabbar.updateWidth()}if(e.Helpers.IsBrowserEdge()||this.refresh(),s)for(var T=s.backgroundColor||"#242424",C=s.backgroundColorLighter||"#2c2c2c",O=s.backgroundColorLighter2||"#383838",P=s.backgroundColorLighter3||"#454545",E=s.color||"#ccc",I=s.colorTop||"#f29766",x=s.colorBot||"#5db0d7",S=t.DOCUMENT.querySelectorAll("style"),L=0;L0&&t.push(new e.BoundingBox(this)),t.push(new e.Info(this)),t},n.prototype.setVisible=function(e){this._obj.setEnabled(e),this._obj.isVisible=e},n.prototype.isVisible=function(){return this._obj.isEnabled()&&(void 0===this._obj.isVisible||this._obj.isVisible)},n.prototype.isBoxVisible=function(){return this._obj.showBoundingBox},n.prototype.setBoxVisible=function(e){return this._obj.showBoundingBox=e},n.prototype.debug=function(e){if(this._axesViewer||this._drawAxis(),!e&&this._axesViewer){this._obj.getScene().onBeforeRenderObservable.remove(this.onBeforeRenderObserver),this._axesViewer.dispose(),this._axesViewer=null}},n.prototype.getInfo=function(){return this._obj instanceof BABYLON.AbstractMesh?this._obj.getTotalVertices()+" vertices":"0 vertices"},n.prototype._drawAxis=function(){var e=this;this._obj.computeWorldMatrix();var t=new BABYLON.Vector3(1,0,0),n=new BABYLON.Vector3(0,1,0),r=new BABYLON.Vector3(0,0,1);this._axesViewer=new BABYLON.Debug.AxesViewer(this._obj.getScene());var i=this._obj;this.onBeforeRenderObserver=i.getScene().onBeforeRenderObservable.add((function(){var o=i.getWorldMatrix(),s=new BABYLON.Vector3(1,1,1);i instanceof BABYLON.AbstractMesh&&(s=i.getBoundingInfo().boundingBox.extendSizeWorld),e._axesViewer.scaleLines=2*Math.max(s.x,s.y,s.z),e._axesViewer.update(e._obj.position,BABYLON.Vector3.TransformNormal(t,o),BABYLON.Vector3.TransformNormal(n,o),BABYLON.Vector3.TransformNormal(r,o))}))},n})(e.Adapter);e.MeshAdapter=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(t){function n(e){var n=t.call(this)||this;return n._detailRows=[],n._sortDirection={},n._build(),e&&(n._detailRows=e,n.update()),n}return __extends(n,t),Object.defineProperty(n.prototype,"details",{set:function(e){this.clean(),this._detailRows=e,this.update()},enumerable:!0,configurable:!0}),n.prototype._build=function(){this._div.className="insp-details",this._div.id="insp-details",this._createHeaderRow(),this._div.appendChild(this._headerRow)},n.prototype.update=function(){this._sortDetails("name",1),this._addDetails()},n.prototype._addDetails=function(){for(var t=e.Helpers.CreateDiv("details",this._div),n=0,r=this._detailRows;n0))return null;for(var i=0,o=r.children;i0){for(var o=new e.TreeItem(t,new e.GUIAdapter(n)),s=0,a=i;s0){for(var p=0,c=s;p=i._tabs.length)&&(r=0),i._tabs[r].active(!0);for(var o=0,s=i._tabs;o0&&t>e;){var n=this._visibleTabs.pop();if(!n)break;this._invisibleTabs.push(n),this._div.removeChild(n.toHtml()),t=this.getPixelWidth()+75}if(this._invisibleTabs.length>0&&t+750&&!this._div.contains(this._moreTabsIcon)&&this._div.appendChild(this._moreTabsIcon)}},n})(e.BasicElement);e.TabBar=t})(INSPECTOR||(INSPECTOR={}));var INSPECTOR;!(function(e){var t=(function(){function t(t,n,r,i){var o=this;this._inspector=r,this._elem=e.Inspector.DOCUMENT.createElement("i"),this._elem.className="tool fa "+t,n.appendChild(this._elem),this._elem.addEventListener("click",(function(e){o.action()})),new e.Tooltip(this._elem,i)}return t.prototype.toHtml=function(){return this._elem},t.prototype.getPixelWidth=function(){var t=e.Inspector.WINDOW.getComputedStyle(this._elem);if(!t.marginLeft||!t.marginRight)return 0;var n=parseFloat(t.marginLeft.substr(0,t.marginLeft.length-2))||0,r=parseFloat(t.marginRight.substr(0,t.marginRight.length-2))||0;return(this._elem.clientWidth||0)+n+r},t.prototype._updateIcon=function(e){this._elem.className="tool fa "+e},t})();e.AbstractTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(t){function n(e,n){var r=t.call(this,"fa-pause",e,n,"Pause the automatic update of properties")||this;return r._isPause=!1,r}return __extends(n,t),n.prototype.action=function(){this._isPause?(e.Scheduler.getInstance().pause=!1,this._updateIcon("fa-pause")):(e.Scheduler.getInstance().pause=!0,this._updateIcon("fa-play")),this._isPause=!this._isPause},n})(e.AbstractTool);e.PauseScheduleTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(e){function t(t,n){var r=e.call(this,"fa-mouse-pointer",t,n,"Select a mesh in the scene")||this;return r._isActive=!1,r._pickHandler=r._pickMesh.bind(r),r}return __extends(t,e),t.prototype.action=function(){if(this._isActive)this._deactivate();else{this.toHtml().classList.add("active");this._inspector.scene.getEngine().getRenderingCanvas().addEventListener("click",this._pickHandler),this._isActive=!0}},t.prototype._deactivate=function(){this.toHtml().classList.remove("active"),this._inspector.scene.getEngine().getRenderingCanvas().removeEventListener("click",this._pickHandler),this._isActive=!1},t.prototype._pickMesh=function(e){var t=this._updatePointerPosition(e),n=this._inspector.scene.pick(t.x,t.y,(function(e){return!0}));n&&n.pickedMesh&&this._inspector.displayObjectDetails(n.pickedMesh),this._deactivate()},t.prototype._updatePointerPosition=function(e){var t=this._inspector.scene.getEngine().getRenderingCanvasClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},t})(e.AbstractTool);e.PickTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(e){function t(t,n){return e.call(this,"fa-external-link",t,n,"Open the inspector in a popup")||this}return __extends(t,e),t.prototype.action=function(){this._inspector.openPopup()},t})(e.AbstractTool);e.PopupTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(e){function t(t,n){return e.call(this,"fa-refresh",t,n,"Refresh the current tab")||this}return __extends(t,e),t.prototype.action=function(){this._inspector.refresh()},t})(e.AbstractTool);e.RefreshTool=t})(INSPECTOR||(INSPECTOR={}));var __extends=this&&this.__extends||(function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}})(),INSPECTOR;!(function(e){var t=(function(t){function n(e,n){var r=t.call(this,"fa-tags",e,n,"Display mesh names on the canvas")||this;return r._isDisplayed=!1,r._advancedTexture=null,r._labelInitialized=!1,r._scene=null,r._guiLoaded=!1,r._scene=n.scene,r}return __extends(n,t),n.prototype.dispose=function(){this._advancedTexture&&this._advancedTexture.dispose()},n.prototype._checkGUILoaded=function(){return!0===this._guiLoaded||(BABYLON.GUI&&(this._guiLoaded=!0),this._guiLoaded)},n.prototype._initializeLabels=function(){var e=this;if(!this._labelInitialized&&this._scene&&this._checkGUILoaded()){this._advancedTexture=BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");for(var t=0,n=this._scene.meshes;t0){for(var e=0,t=this.children;e0){for(var e=0,t=this.children;e0&&(this._div.classList.contains("folded")||this._div.classList.contains("unfolded")||this._div.classList.add("folded")),this.fold()},n.prototype._addEvent=function(){var e=this;this._div.addEventListener("click",(function(t){e._tab.select(e),e._isFolded()?e.unfold():e.fold(),t.stopPropagation()}))},n.prototype._isFolded=function(){return!this._div.classList.contains("unfolded")},n.prototype.active=function(e){this._div.classList.remove("active");for(var t=0,n=this.children;t { - ground.rotation.y += 0.01; - ground.position.y = Math.cos(t += 0.01); - }); + // scene.registerBeforeRender(() => { + // ground.rotation.y += 0.01; + // ground.position.y = Math.cos(t += 0.01); + // }); scene.createDefaultCameraOrLight(true); scene.activeCamera.attachControl(canvas); + scene.debugLayer.show(); this.scene = scene; };