UNPKG

@react-three/drei

Version:

useful add-ons for react-three-fiber

53 lines (50 loc) 1.6 kB
import * as React from 'react'; import { Object3D, AnimationMixer } from 'three'; import { useFrame } from '@react-three/fiber'; function useAnimations(clips, root) { const ref = React.useRef(null); const [actualRef] = React.useState(() => root ? root instanceof Object3D ? { current: root } : root : ref); const [mixer] = React.useState(() => new AnimationMixer(undefined)); React.useLayoutEffect(() => { if (root) actualRef.current = root instanceof Object3D ? root : root.current; mixer._root = actualRef.current; }); const lazyActions = React.useRef({}); const api = React.useMemo(() => { const actions = {}; clips.forEach(clip => Object.defineProperty(actions, clip.name, { enumerable: true, get() { if (actualRef.current) { return lazyActions.current[clip.name] || (lazyActions.current[clip.name] = mixer.clipAction(clip, actualRef.current)); } }, configurable: true })); return { ref: actualRef, clips, actions, names: clips.map(c => c.name), mixer }; }, [clips]); useFrame((state, delta) => mixer.update(delta)); React.useEffect(() => { const currentRoot = actualRef.current; return () => { // Clean up only when clips change, wipe out lazy actions and uncache clips lazyActions.current = {}; mixer.stopAllAction(); Object.values(api.actions).forEach(action => { if (currentRoot) { mixer.uncacheAction(action, currentRoot); } }); }; }, [clips]); return api; } export { useAnimations };