Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
three.js/examples/jsm/webxr/VRButton.js /
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
200 lines (116 sloc)
4.12 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class VRButton { | |
| static createButton( renderer ) { | |
| const button = document.createElement( 'button' ); | |
| function showEnterVR( /*device*/ ) { | |
| let currentSession = null; | |
| async function onSessionStarted( session ) { | |
| session.addEventListener( 'end', onSessionEnded ); | |
| await renderer.xr.setSession( session ); | |
| button.textContent = 'EXIT VR'; | |
| currentSession = session; | |
| } | |
| function onSessionEnded( /*event*/ ) { | |
| currentSession.removeEventListener( 'end', onSessionEnded ); | |
| button.textContent = 'ENTER VR'; | |
| currentSession = null; | |
| } | |
| // | |
| button.style.display = ''; | |
| button.style.cursor = 'pointer'; | |
| button.style.left = 'calc(50% - 50px)'; | |
| button.style.width = '100px'; | |
| button.textContent = 'ENTER VR'; | |
| button.onmouseenter = function () { | |
| button.style.opacity = '1.0'; | |
| }; | |
| button.onmouseleave = function () { | |
| button.style.opacity = '0.5'; | |
| }; | |
| button.onclick = function () { | |
| if ( currentSession === null ) { | |
| // WebXR's requestReferenceSpace only works if the corresponding feature | |
| // was requested at session creation time. For simplicity, just ask for | |
| // the interesting ones as optional features, but be aware that the | |
| // requestReferenceSpace call will fail if it turns out to be unavailable. | |
| // ('local' is always available for immersive sessions and doesn't need to | |
| // be requested separately.) | |
| const sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor', 'hand-tracking', 'layers' ] }; | |
| navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted ); | |
| } else { | |
| currentSession.end(); | |
| } | |
| }; | |
| } | |
| function disableButton() { | |
| button.style.display = ''; | |
| button.style.cursor = 'auto'; | |
| button.style.left = 'calc(50% - 75px)'; | |
| button.style.width = '150px'; | |
| button.onmouseenter = null; | |
| button.onmouseleave = null; | |
| button.onclick = null; | |
| } | |
| function showWebXRNotFound() { | |
| disableButton(); | |
| button.textContent = 'VR NOT SUPPORTED'; | |
| } | |
| function showVRNotAllowed( exception ) { | |
| disableButton(); | |
| console.warn( 'Exception when trying to call xr.isSessionSupported', exception ); | |
| button.textContent = 'VR NOT ALLOWED'; | |
| } | |
| function stylizeElement( element ) { | |
| element.style.position = 'absolute'; | |
| element.style.bottom = '20px'; | |
| element.style.padding = '12px 6px'; | |
| element.style.border = '1px solid #fff'; | |
| element.style.borderRadius = '4px'; | |
| element.style.background = 'rgba(0,0,0,0.1)'; | |
| element.style.color = '#fff'; | |
| element.style.font = 'normal 13px sans-serif'; | |
| element.style.textAlign = 'center'; | |
| element.style.opacity = '0.5'; | |
| element.style.outline = 'none'; | |
| element.style.zIndex = '999'; | |
| } | |
| if ( 'xr' in navigator ) { | |
| button.id = 'VRButton'; | |
| button.style.display = 'none'; | |
| stylizeElement( button ); | |
| navigator.xr.isSessionSupported( 'immersive-vr' ).then( function ( supported ) { | |
| supported ? showEnterVR() : showWebXRNotFound(); | |
| if ( supported && VRButton.xrSessionIsGranted ) { | |
| button.click(); | |
| } | |
| } ).catch( showVRNotAllowed ); | |
| return button; | |
| } else { | |
| const message = document.createElement( 'a' ); | |
| if ( window.isSecureContext === false ) { | |
| message.href = document.location.href.replace( /^http:/, 'https:' ); | |
| message.innerHTML = 'WEBXR NEEDS HTTPS'; // TODO Improve message | |
| } else { | |
| message.href = 'https://immersiveweb.dev/'; | |
| message.innerHTML = 'WEBXR NOT AVAILABLE'; | |
| } | |
| message.style.left = 'calc(50% - 90px)'; | |
| message.style.width = '180px'; | |
| message.style.textDecoration = 'none'; | |
| stylizeElement( message ); | |
| return message; | |
| } | |
| } | |
| static registerSessionGrantedListener() { | |
| if ( 'xr' in navigator ) { | |
| // WebXRViewer (based on Firefox) has a bug where addEventListener | |
| // throws a silent exception and aborts execution entirely. | |
| if ( /WebXRViewer\//i.test( navigator.userAgent ) ) return; | |
| navigator.xr.addEventListener( 'sessiongranted', () => { | |
| VRButton.xrSessionIsGranted = true; | |
| } ); | |
| } | |
| } | |
| } | |
| VRButton.xrSessionIsGranted = false; | |
| VRButton.registerSessionGrantedListener(); | |
| export { VRButton }; |