UNPKG

react-native-filament

Version:

A real-time physically based 3D rendering engine for React Native

78 lines (67 loc) 2.65 kB
import { useEffect, useMemo } from 'react' import { LightConfig, LightManager } from '../types' import { ISharedValue } from 'react-native-worklets-core' import { useFilamentContext } from './useFilamentContext' export type UseLightEntityProps = | LightConfig | (Omit<LightConfig, 'intensity'> & { intensity?: ISharedValue<number> }) /** * Creates a new memoized light entity based on the given configuration. */ export function useLightEntity(lightManager: LightManager, config: UseLightEntityProps) { const falloffRadius = 'falloffRadius' in config ? config.falloffRadius : undefined const spotLightCone = 'spotLightCone' in config ? config.spotLightCone : undefined // Unwrap all array-ish values so the user doesn't have to memo them! const directionX = config.direction?.[0] ?? undefined const directionY = config.direction?.[1] ?? undefined const directionZ = config.direction?.[2] ?? undefined const positionX = config.position?.[0] ?? undefined const positionY = config.position?.[1] ?? undefined const positionZ = config.position?.[2] ?? undefined const innerSpotLightCone = spotLightCone?.[0] ?? undefined const outerSpotLightCone = spotLightCone?.[1] ?? undefined const entity = useMemo(() => { return lightManager.createLightEntity( config.type, config.colorKelvin, typeof config.intensity === 'number' ? config.intensity : config.intensity?.value, directionX != null && directionY != null && directionZ != null ? [directionX, directionY, directionZ] : undefined, positionX != null && positionY != null && positionZ != null ? [positionX, positionY, positionZ] : undefined, config.castShadows, falloffRadius, innerSpotLightCone != null && outerSpotLightCone != null ? [innerSpotLightCone, outerSpotLightCone] : undefined ) }, [ config.castShadows, config.colorKelvin, config.intensity, config.type, directionX, directionY, directionZ, falloffRadius, innerSpotLightCone, lightManager, outerSpotLightCone, positionX, positionY, positionZ, ]) // Eventually subscribe to the intensity shared value const { workletContext } = useFilamentContext() useEffect(() => { const intensity = config.intensity if (intensity == null) return if (typeof intensity === 'number') return const setIntensity = lightManager.setIntensity return intensity.addListener( workletContext.createRunAsync(() => { 'worklet' setIntensity(entity, intensity.value) }) ) }, [config.intensity, entity, lightManager, workletContext]) return entity }