-
Notifications
You must be signed in to change notification settings - Fork 730
/
Copy pathFlyControls.tsx
52 lines (45 loc) · 1.92 KB
/
FlyControls.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { EventManager, ReactThreeFiber, useFrame, useThree } from '@react-three/fiber'
import * as React from 'react'
import * as THREE from 'three'
import { FlyControls as FlyControlsImpl } from 'three-stdlib'
import { ForwardRefComponent } from '../helpers/ts-utils'
export type FlyControlsProps = ReactThreeFiber.Object3DNode<FlyControlsImpl, typeof FlyControlsImpl> & {
onChange?: (e?: THREE.Event) => void
domElement?: HTMLElement
makeDefault?: boolean
}
export const FlyControls: ForwardRefComponent<FlyControlsProps, FlyControlsImpl> = /* @__PURE__ */ React.forwardRef<
FlyControlsImpl,
FlyControlsProps
>(({ domElement, ...props }, fref) => {
const { onChange, makeDefault, ...rest } = props
const invalidate = useThree((state) => state.invalidate)
const camera = useThree((state) => state.camera)
const gl = useThree((state) => state.gl)
const events = useThree((state) => state.events) as EventManager<HTMLElement>
const get = useThree((state) => state.get)
const set = useThree((state) => state.set)
const explDomElement = (domElement || events.connected || gl.domElement) as HTMLElement
const controls = React.useMemo(() => new FlyControlsImpl(camera), [camera])
React.useEffect(() => {
controls.connect(explDomElement)
return () => void controls.dispose()
}, [explDomElement, controls, invalidate])
React.useEffect(() => {
const callback = (e: THREE.Event) => {
invalidate()
if (onChange) onChange(e)
}
controls.addEventListener?.('change', callback)
return () => controls.removeEventListener?.('change', callback)
}, [onChange, invalidate])
React.useEffect(() => {
if (makeDefault) {
const old = get().controls
set({ controls })
return () => set({ controls: old })
}
}, [makeDefault, controls])
useFrame((_, delta) => controls.update(delta))
return <primitive ref={fref} object={controls} args={[camera, explDomElement]} {...rest} />
})