|
import {useRef, useEffect} from 'react'; |
|
import * as THREE from 'three'; |
|
import {extend} from '@react-three/fiber'; |
|
import ThreeMeshUI from 'three-mesh-ui'; |
|
import ThreeMeshUIText, {ThreeMeshUITextType} from './ThreeMeshUIText'; |
|
import {Interactive} from '@react-three/xr'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
import robotoFontFamilyJson from '../assets/RobotoMono-Regular-msdf.json?url'; |
|
import robotoFontTexture from '../assets/RobotoMono-Regular.png'; |
|
|
|
extend(ThreeMeshUI); |
|
|
|
|
|
|
|
|
|
export default function Button({ |
|
onClick, |
|
content, |
|
width, |
|
height, |
|
fontSize, |
|
borderRadius, |
|
padding, |
|
}) { |
|
const button = useRef<JSX.IntrinsicElements['block']>(); |
|
const textRef = useRef<ThreeMeshUITextType>(); |
|
|
|
useEffect(() => { |
|
if (textRef.current != null) { |
|
textRef.current.set({content}); |
|
} |
|
}, [textRef, content]); |
|
|
|
useEffect(() => { |
|
if (!button.current) { |
|
return; |
|
} |
|
button.current.setupState({ |
|
state: 'hovered', |
|
attributes: { |
|
offset: 0.002, |
|
backgroundColor: new THREE.Color(0x607b8f), |
|
fontColor: new THREE.Color(0xffffff), |
|
}, |
|
}); |
|
button.current.setupState({ |
|
state: 'idle', |
|
attributes: { |
|
offset: 0.001, |
|
backgroundColor: new THREE.Color(0x465a69), |
|
fontColor: new THREE.Color(0xffffff), |
|
}, |
|
}); |
|
button.current.setupState({ |
|
state: 'selected', |
|
attributes: { |
|
offset: 0.005, |
|
backgroundColor: new THREE.Color(0x000000), |
|
fontColor: new THREE.Color(0xffffff), |
|
}, |
|
}); |
|
button.current.setState('idle'); |
|
}, []); |
|
|
|
const args = [ |
|
{ |
|
width, |
|
height, |
|
fontSize, |
|
padding, |
|
justifyContent: 'end', |
|
textAlign: 'center', |
|
alignItems: 'center', |
|
borderRadius, |
|
fontFamily: robotoFontFamilyJson, |
|
fontTexture: robotoFontTexture, |
|
backgroundOpacity: 1, |
|
backgroundColor: new THREE.Color(0x779092), |
|
fontColor: new THREE.Color(0x000000), |
|
}, |
|
]; |
|
|
|
return ( |
|
<Interactive |
|
// These are for XR mode |
|
onSelect={() => { |
|
onClick(); |
|
}} |
|
onHover={() => button.current.setState('hovered')} |
|
onBlur={() => button.current.setState('idle')} |
|
onSelectStart={() => button.current.setState('selected')} |
|
onSelectEnd={() => button.current.setState('idle')}> |
|
<block |
|
// These are for non-XR modes |
|
onPointerEnter={() => button.current.setState('hovered')} |
|
onPointerLeave={() => button.current.setState('idle')} |
|
onPointerDown={() => button.current.setState('selected')} |
|
onPointerUp={() => { |
|
button.current.setState('hovered'); |
|
onClick(); |
|
}}> |
|
<block args={args} ref={button}> |
|
<ThreeMeshUIText |
|
ref={textRef} |
|
fontColor={new THREE.Color(0xffffff)} |
|
content={content} |
|
/> |
|
</block> |
|
</block> |
|
</Interactive> |
|
); |
|
} |
|
|