| 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> |
| ); |
| } |
|
|