Files
Dwinzo_dev/app/src/modules/market/GltfLoader.tsx

76 lines
1.9 KiB
TypeScript

import { useRef, useEffect } from "react";
import { useFrame } from "@react-three/fiber";
import { Stage, useGLTF } from "@react-three/drei";
import { AnimationMixer, AnimationAction, Object3D } from "three";
import * as THREE from "three";
interface GltfLoaderProps {
glbdata?: boolean;
fromServer?: string;
setAnimations?: (animations?: string[]) => void;
selectedAnimation?: string;
setSelectedAnimation?: (animation: string) => void;
}
const GltfLoader: React.FC<GltfLoaderProps> = ({
glbdata,
fromServer,
setAnimations,
selectedAnimation,
}) => {
const { scene, animations } = useGLTF(fromServer ?? "") as {
scene: Object3D;
animations: THREE.AnimationClip[];
};
const mixer = useRef<AnimationMixer | null>(
scene ? new AnimationMixer(scene) : null
);
const actions = useRef<Record<string, AnimationAction>>({});
useEffect(() => {
if (animations.length > 0 && mixer.current && setAnimations) {
const animationNames = animations.map((animation) => animation.name);
setAnimations(animationNames);
animations.forEach((animation) => {
const action = mixer.current!.clipAction(animation);
actions.current[animation.name] = action;
});
} else {
setAnimations && setAnimations([]);
}
}, [animations, setAnimations]);
useEffect(() => {
if (actions.current && selectedAnimation) {
const action = actions.current[selectedAnimation];
if (action) {
action.reset().fadeIn(0.5).play();
return () => {
action.fadeOut(0.5);
};
}
}
}, [selectedAnimation]);
useFrame((_, delta) => {
if (mixer.current) {
mixer.current.update(delta);
}
});
return (
<Stage
adjustCamera={false}
intensity={0.5}
shadows="contact"
environment="city"
>
<primitive object={scene} scale={1} />
</Stage>
);
};
export default GltfLoader;