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