feat: Enhance asset and human event handling with animation and loop capabilities
This commit is contained in:
@@ -6,7 +6,7 @@ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
|
||||
import { ThreeEvent, useFrame, useThree } from '@react-three/fiber';
|
||||
import { useActiveTool, useDeletableFloorItem, useLimitDistance, useRenderDistance, useSelectedFloorItem, useSocketStore, useToggleView, useToolMode } from '../../../../../store/builder/store';
|
||||
import { AssetBoundingBox } from '../../functions/assetBoundingBox';
|
||||
import { CameraControls, Html } from '@react-three/drei';
|
||||
import { CameraControls } from '@react-three/drei';
|
||||
import useModuleStore, { useSubModuleStore } from '../../../../../store/useModuleStore';
|
||||
import { useLeftData, useTopData } from '../../../../../store/visualization/useZone3DWidgetStore';
|
||||
import { useSelectedAsset } from '../../../../../store/simulation/useSimulationStore';
|
||||
@@ -15,6 +15,7 @@ import { useParams } from 'react-router-dom';
|
||||
import { getUserData } from '../../../../../functions/getUserData';
|
||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||
import { useVersionContext } from '../../../version/versionContext';
|
||||
import { SkeletonUtils } from 'three-stdlib';
|
||||
|
||||
function Model({ asset }: { readonly asset: Asset }) {
|
||||
const { camera, controls, gl } = useThree();
|
||||
@@ -23,7 +24,7 @@ function Model({ asset }: { readonly asset: Asset }) {
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { assetStore, eventStore, productStore } = useSceneContext();
|
||||
const { assets, removeAsset, setAnimations } = assetStore();
|
||||
const { removeAsset, setAnimations, resetAnimation } = assetStore();
|
||||
const { setTop } = useTopData();
|
||||
const { setLeft } = useLeftData();
|
||||
const { getIsEventInProduct } = productStore();
|
||||
@@ -33,7 +34,7 @@ function Model({ asset }: { readonly asset: Asset }) {
|
||||
const { setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
|
||||
const { socket } = useSocketStore();
|
||||
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
|
||||
const { setSelectedFloorItem } = useSelectedFloorItem();
|
||||
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
|
||||
const { limitDistance } = useLimitDistance();
|
||||
const { renderDistance } = useRenderDistance();
|
||||
const [isRendered, setIsRendered] = useState(false);
|
||||
@@ -46,13 +47,15 @@ function Model({ asset }: { readonly asset: Asset }) {
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
const { projectId } = useParams();
|
||||
const { userId, organization } = getUserData();
|
||||
const [animationNames, setAnimationNames] = useState<string[]>([]);
|
||||
const mixerRef = useRef<THREE.AnimationMixer>();
|
||||
const actions = useRef<{ [name: string]: THREE.AnimationAction }>({});
|
||||
|
||||
useEffect(() => {
|
||||
setDeletableFloorItem(null);
|
||||
}, [activeModule, toolMode])
|
||||
if (selectedFloorItem === null) {
|
||||
resetAnimation(asset.modelUuid);
|
||||
}
|
||||
}, [activeModule, toolMode, selectedFloorItem])
|
||||
|
||||
useEffect(() => {
|
||||
const loader = new GLTFLoader();
|
||||
@@ -62,40 +65,21 @@ function Model({ asset }: { readonly asset: Asset }) {
|
||||
loader.setDRACOLoader(dracoLoader);
|
||||
const loadModel = async () => {
|
||||
try {
|
||||
// Check Cache
|
||||
// const assetId = asset.assetId;
|
||||
// const cachedModel = THREE.Cache.get(assetId);
|
||||
// if (cachedModel) {
|
||||
// setGltfScene(cachedModel.scene.clone());
|
||||
// calculateBoundingBox(cachedModel.scene);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Check Cache
|
||||
// const assetId = asset.assetId;
|
||||
// console.log('assetId: ', assetId);
|
||||
// const cachedModel = THREE.Cache.get(assetId);
|
||||
// console.log('cachedModel: ', cachedModel);
|
||||
// if (cachedModel) {
|
||||
// setGltfScene(cachedModel.scene.clone());
|
||||
// calculateBoundingBox(cachedModel.scene);
|
||||
// return;
|
||||
// }
|
||||
|
||||
const assetId = asset.assetId;
|
||||
const cachedModel = THREE.Cache.get(assetId);
|
||||
if (cachedModel) {
|
||||
const clonedScene = cachedModel.scene.clone();
|
||||
clonedScene.animations = cachedModel.animations || [];
|
||||
setGltfScene(clonedScene);
|
||||
calculateBoundingBox(clonedScene);
|
||||
if (cachedModel.animations && clonedScene.animations.length > 0) {
|
||||
const animationName = clonedScene.animations.map((clip: any) => clip.name);
|
||||
setAnimationNames(animationName)
|
||||
const clone: any = SkeletonUtils.clone(cachedModel.scene);
|
||||
clone.animations = cachedModel.animations || [];
|
||||
setGltfScene(clone);
|
||||
calculateBoundingBox(clone);
|
||||
if (cachedModel.animations && clone.animations.length > 0) {
|
||||
const animationName = clone.animations.map((clip: any) => clip.name);
|
||||
setAnimations(asset.modelUuid, animationName)
|
||||
mixerRef.current = new THREE.AnimationMixer(clonedScene);
|
||||
mixerRef.current = new THREE.AnimationMixer(clone);
|
||||
|
||||
clonedScene.animations.forEach((animation: any) => {
|
||||
clone.animations.forEach((animation: any) => {
|
||||
const action = mixerRef.current!.clipAction(animation);
|
||||
actions.current[animation.name] = action;
|
||||
});
|
||||
@@ -293,28 +277,27 @@ function Model({ asset }: { readonly asset: Asset }) {
|
||||
clearSelectedAsset()
|
||||
}
|
||||
}
|
||||
|
||||
useFrame((_, delta) => {
|
||||
if (mixerRef.current) {
|
||||
mixerRef.current.update(delta);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (asset.animationState && asset.animationState.playing) {
|
||||
if (asset.animationState && asset.animationState.isPlaying) {
|
||||
if (!mixerRef.current) return;
|
||||
|
||||
Object.values(actions.current).forEach((action) => action.stop());
|
||||
|
||||
const action = actions.current[asset.animationState.current];
|
||||
if (action && asset.animationState?.playing) {
|
||||
action.reset().setLoop(THREE.LoopOnce, 1).play();
|
||||
if (action && asset.animationState?.isPlaying) {
|
||||
const loopMode = asset.animationState.loopAnimation ? THREE.LoopRepeat : THREE.LoopOnce;
|
||||
action.reset().setLoop(loopMode, loopMode === THREE.LoopRepeat ? Infinity : 1).play();
|
||||
}
|
||||
} else {
|
||||
Object.values(actions.current).forEach((action) => action.stop());
|
||||
}
|
||||
|
||||
}, [asset.animationState])
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user