Anna Sun
Initial OSS demo commit
2bd3674
raw
history blame
3.2 kB
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';
/**
* Using `?url` at the end of this import tells vite this is a static asset, and
* provides us a URL to the hashed version of the file when the project is built.
* See: https://vitejs.dev/guide/assets.html#explicit-url-imports
*/
import robotoFontFamilyJson from '../assets/RobotoMono-Regular-msdf.json?url';
import robotoFontTexture from '../assets/RobotoMono-Regular.png';
extend(ThreeMeshUI);
/**
* Button component that renders as a three-mesh-ui block
*/
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>
);
}