|
import * as THREE from 'three'; |
|
import {Button} from '@mui/material'; |
|
import {useCallback, useEffect, useState} from 'react'; |
|
import {BufferedSpeechPlayer} from '../createBufferedSpeechPlayer'; |
|
|
|
type Props = { |
|
bufferedSpeechPlayer: BufferedSpeechPlayer; |
|
renderer: THREE.WebGLRenderer | null; |
|
onARVisible?: () => void; |
|
onARHidden?: () => void; |
|
}; |
|
|
|
export default function ARButton({ |
|
bufferedSpeechPlayer, |
|
renderer, |
|
onARVisible, |
|
onARHidden, |
|
}: Props) { |
|
const [session, setSession] = useState<XRSession | null>(null); |
|
const [supported, setSupported] = useState<boolean>(true); |
|
|
|
useEffect(() => { |
|
if (!navigator.xr) { |
|
setSupported(false); |
|
return; |
|
} |
|
navigator.xr.isSessionSupported('immersive-ar').then((supported) => { |
|
setSupported(supported); |
|
}); |
|
}, []); |
|
|
|
const resetBuffers = useCallback( |
|
(event: XRSessionEvent) => { |
|
const session = event.target; |
|
if (!(session instanceof XRSession)) { |
|
return; |
|
} |
|
switch (session.visibilityState) { |
|
case 'visible': |
|
console.log('Restarting speech player, device is visible'); |
|
bufferedSpeechPlayer.stop(); |
|
bufferedSpeechPlayer.start(); |
|
onARVisible?.(); |
|
break; |
|
case 'hidden': |
|
console.log('Stopping speech player, device is hidden'); |
|
bufferedSpeechPlayer.stop(); |
|
bufferedSpeechPlayer.start(); |
|
onARHidden?.(); |
|
break; |
|
} |
|
}, |
|
[bufferedSpeechPlayer], |
|
); |
|
|
|
async function onSessionStarted(session: XRSession) { |
|
setSession(session); |
|
|
|
session.onvisibilitychange = resetBuffers; |
|
session.onend = onSessionEnded; |
|
|
|
await renderer.xr.setSession(session); |
|
} |
|
|
|
function onSessionEnded() { |
|
setSession(null); |
|
} |
|
|
|
const onClick = () => { |
|
if (session === null) { |
|
navigator.xr!.requestSession('immersive-ar').then(onSessionStarted); |
|
} else { |
|
session.end(); |
|
} |
|
}; |
|
return ( |
|
<Button |
|
variant="contained" |
|
onClick={onClick} |
|
disabled={!supported || renderer == null} |
|
sx={{mt: 1}}> |
|
{supported |
|
? renderer != null |
|
? 'Enter AR' |
|
: 'Initializing AR...' |
|
: 'AR Not Supported'} |
|
</Button> |
|
); |
|
} |
|
|