theatre/packages/playground/src/r3f/App.tsx

156 lines
3.9 KiB
TypeScript
Raw Normal View History

2021-06-29 15:39:47 +02:00
import {editable as e, bindToCanvas} from '@theatre/plugin-r3f'
2021-06-18 13:05:06 +02:00
import {PerspectiveCamera} from '@react-three/drei'
import {getProject} from '@theatre/core'
import * as THREE from 'three'
import React, {useState, useEffect, useRef} from 'react'
import type {Color} from '@react-three/fiber'
import {Canvas, useFrame} from '@react-three/fiber'
import {softShadows, Shadow} from '@react-three/drei'
import type {DirectionalLight} from 'three'
import type {$FixMe} from '../../../plugin-r3f/src/types'
const ECamera = e(PerspectiveCamera, 'perspectiveCamera')
// Soft shadows are expensive, comment and refresh when it's too slow
softShadows()
// credit: https://codesandbox.io/s/camera-pan-nsb7f
function Button() {
const vec = new THREE.Vector3()
const light = useRef<DirectionalLight>(undefined as any)
const [active, setActive] = useState(false)
const [zoom, set] = useState(true)
useEffect(
() => void (document.body.style.cursor = active ? 'pointer' : 'auto'),
[active],
)
useFrame((state) => {
const step = 0.1
const camera = state.camera as THREE.PerspectiveCamera
camera.fov = (THREE as $FixMe).MathUtils.lerp(
camera.fov,
zoom ? 10 : 42,
step,
)
camera.position.lerp(
vec.set(zoom ? 25 : 10, zoom ? 1 : 5, zoom ? 0 : 10),
step,
)
state.camera.lookAt(0, 0, 0)
state.camera.updateProjectionMatrix()
light.current.position.lerp(
vec.set(zoom ? 4 : 0, zoom ? 3 : 8, zoom ? 3 : 5),
step,
)
})
return (
<e.mesh
receiveShadow
castShadow
onClick={() => set(!zoom)}
onPointerOver={() => setActive(true)}
onPointerOut={() => setActive(false)}
uniqueName="The Button"
>
<sphereBufferGeometry args={[0.75, 64, 64]} />
<meshPhysicalMaterial
color={active ? 'purple' : '#e7b056'}
clearcoat={1}
clearcoatRoughness={0}
/>
<Shadow
position-y={-0.79}
rotation-x={-Math.PI / 2}
opacity={0.6}
scale={[0.8, 0.8, 1]}
/>
<directionalLight
ref={light}
castShadow
intensity={1.5}
shadow-camera-far={70}
/>
</e.mesh>
)
}
function Plane({
color,
uniqueName,
...props
}: {color: Color; uniqueName: string} & Parameters<typeof e.mesh>[0]) {
return (
<e.mesh receiveShadow castShadow {...props} uniqueName={uniqueName}>
<boxBufferGeometry />
<meshStandardMaterial color={color as any} />
</e.mesh>
)
}
function App() {
return (
<div>
<Canvas
// @ts-ignore
shadowMap
onCreated={bindToCanvas({
sheet: getProject('Example project').sheet('R3F-Canvas'),
})}
>
<ECamera makeDefault uniqueName="Camera" />
<ambientLight intensity={0.4} />
<e.pointLight
position={[-10, -10, 5]}
intensity={2}
color="#ff20f0"
uniqueName="Light 1"
/>
<e.pointLight
position={[0, 0.5, -1]}
distance={1}
intensity={2}
color="#e4be00"
uniqueName="Light 2"
/>
<group position={[0, -0.9, -3]}>
<Plane
color="hotpink"
rotation-x={-Math.PI / 2}
position-z={2}
scale={[4, 20, 0.2]}
uniqueName="plane1"
/>
<Plane
color="#e4be00"
rotation-x={-Math.PI / 2}
position-y={1}
scale={[4.2, 0.2, 4]}
uniqueName="plane2"
/>
<Plane
color="#736fbd"
rotation-x={-Math.PI / 2}
position={[-1.7, 1, 3.5]}
scale={[0.5, 4, 4]}
uniqueName="plane3"
/>
<Plane
color="white"
rotation-x={-Math.PI / 2}
position={[0, 4.5, 3]}
scale={[2, 0.03, 4]}
uniqueName="plane4"
/>
</group>
<Button />
</Canvas>
</div>
)
}
export default App