-
Notifications
You must be signed in to change notification settings - Fork 116
/
Copy pathutil.tsx
55 lines (47 loc) · 2.01 KB
/
util.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
53
54
55
import React, { RefObject } from 'react'
import { Vector2 } from 'three'
import * as THREE from 'three'
import { type ReactThreeFiber, type ThreeElement, extend, useThree } from '@react-three/fiber'
import type { Effect, Pass, BlendFunction } from 'postprocessing'
export const resolveRef = <T,>(ref: T | React.RefObject<T>) =>
typeof ref === 'object' && ref != null && 'current' in ref ? ref.current : ref
export type EffectConstructor = new (...args: any[]) => Effect | Pass
export type EffectProps<T extends EffectConstructor> = ThreeElement<T> &
ConstructorParameters<T>[0] & {
blendFunction?: BlendFunction
opacity?: number
}
let i = 0
const components = new WeakMap<EffectConstructor, React.ExoticComponent<any> | string>()
export const wrapEffect = <T extends EffectConstructor>(effect: T, defaults?: EffectProps<T>) =>
/* @__PURE__ */ function Effect({ blendFunction = defaults?.blendFunction, opacity = defaults?.opacity, ...props }) {
let Component = components.get(effect)
if (!Component) {
const key = `@react-three/postprocessing/${effect.name}-${i++}`
extend({ [key]: effect })
components.set(effect, (Component = key))
}
const camera = useThree((state) => state.camera)
const args = React.useMemo(
() => [...(defaults?.args ?? []), ...(props.args ?? [{ ...defaults, ...props }])],
// eslint-disable-next-line react-hooks/exhaustive-deps
[JSON.stringify(props)]
)
return (
<Component
camera={camera}
blendMode-blendFunction={blendFunction}
blendMode-opacity-value={opacity}
{...props}
args={args}
/>
)
}
export const useVector2 = (props: Record<string, unknown>, key: string): THREE.Vector2 => {
const value = props[key] as ReactThreeFiber.Vector2 | undefined
return React.useMemo(() => {
if (typeof value === 'number') return new THREE.Vector2(value, value)
else if (value) return new THREE.Vector2(...(value as THREE.Vector2Tuple))
else return new THREE.Vector2()
}, [value])
}