"updated Animation"
This commit is contained in:
@@ -1,134 +1,45 @@
|
||||
import React, { useRef, useState, useEffect, useMemo } from "react";
|
||||
import {
|
||||
useAnimationPlaySpeed,
|
||||
usePauseButtonStore,
|
||||
usePlayButtonStore,
|
||||
useResetButtonStore,
|
||||
} from "../../../store/usePlayButtonStore";
|
||||
import { GLTFLoader } from "three-stdlib";
|
||||
import React, { useRef, useEffect, useMemo } from "react";
|
||||
import { useLoader, useFrame } from "@react-three/fiber";
|
||||
import { GLTFLoader } from "three-stdlib";
|
||||
import * as THREE from "three";
|
||||
import { GLTF } from "three-stdlib";
|
||||
import crate from "../../../assets/gltf-glb/crate_box.glb";
|
||||
import box from "../../../assets/gltf-glb/box.glb";
|
||||
|
||||
interface PointAction {
|
||||
uuid: string;
|
||||
name: string;
|
||||
type: "Inherit" | "Spawn" | "Despawn" | "Delay" | "Swap";
|
||||
objectType: string;
|
||||
material: string;
|
||||
delay: string | number;
|
||||
spawnInterval: string | number;
|
||||
isUsed: boolean;
|
||||
import { useProcessAnimation } from "./useProcessAnimations";
|
||||
import ProcessObject from "./processObject";
|
||||
import { ProcessData } from "./types";
|
||||
import { useSimulationStates } from "../../../store/store";
|
||||
|
||||
interface ProcessContainerProps {
|
||||
processes: ProcessData[];
|
||||
setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
|
||||
agvRef: any;
|
||||
}
|
||||
|
||||
interface ProcessPoint {
|
||||
uuid: string;
|
||||
position: number[];
|
||||
rotation: number[];
|
||||
actions: PointAction[];
|
||||
connections: {
|
||||
source: { modelUUID: string; pointUUID: string };
|
||||
targets: { modelUUID: string; pointUUID: string }[];
|
||||
};
|
||||
}
|
||||
|
||||
interface ProcessPath {
|
||||
modeluuid: string;
|
||||
modelName: string;
|
||||
points: ProcessPoint[];
|
||||
pathPosition: number[];
|
||||
pathRotation: number[];
|
||||
speed: number;
|
||||
}
|
||||
|
||||
interface ProcessData {
|
||||
id: string;
|
||||
paths: ProcessPath[];
|
||||
animationPath: { x: number; y: number; z: number }[];
|
||||
pointActions: PointAction[][];
|
||||
speed: number;
|
||||
customMaterials?: Record<string, THREE.Material>;
|
||||
renderAs?: "box" | "custom";
|
||||
}
|
||||
|
||||
interface AnimationState {
|
||||
currentIndex: number;
|
||||
progress: number;
|
||||
isAnimating: boolean;
|
||||
speed: number;
|
||||
isDelaying: boolean;
|
||||
delayStartTime: number;
|
||||
currentDelayDuration: number;
|
||||
delayComplete: boolean;
|
||||
currentPathIndex: number;
|
||||
}
|
||||
|
||||
interface SpawnedObject {
|
||||
ref: React.RefObject<THREE.Group | THREE.Mesh>;
|
||||
state: AnimationState;
|
||||
visible: boolean;
|
||||
material: THREE.Material;
|
||||
spawnTime: number;
|
||||
currentMaterialType: string;
|
||||
position: THREE.Vector3;
|
||||
}
|
||||
|
||||
interface ProcessAnimationState {
|
||||
spawnedObjects: { [objectId: string]: SpawnedObject };
|
||||
nextSpawnTime: number;
|
||||
objectIdCounter: number;
|
||||
isProcessDelaying: boolean;
|
||||
processDelayStartTime: number;
|
||||
processDelayDuration: number;
|
||||
}
|
||||
|
||||
const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||
processes,
|
||||
setProcesses,
|
||||
agvRef,
|
||||
}) => {
|
||||
const gltf = useLoader(GLTFLoader, crate) as GLTF;
|
||||
const { isPlaying, setIsPlaying } = usePlayButtonStore();
|
||||
const { isPaused, setIsPaused } = usePauseButtonStore();
|
||||
const { isReset, setReset } = useResetButtonStore();
|
||||
const groupRef = useRef<THREE.Group>(null);
|
||||
const debugRef = useRef<boolean>(false);
|
||||
const clockRef = useRef<THREE.Clock>(new THREE.Clock());
|
||||
const pauseTimeRef = useRef<number>(0);
|
||||
const elapsedBeforePauseRef = useRef<number>(0);
|
||||
const animationStatesRef = useRef<Record<string, ProcessAnimationState>>({});
|
||||
const { speed, setSpeed } = useAnimationPlaySpeed();
|
||||
const prevIsPlaying = useRef<boolean | null>(null);
|
||||
const [internalResetFlag, setInternalResetFlag] = useState(false);
|
||||
const [animationStates, setAnimationStates] = useState<
|
||||
Record<string, ProcessAnimationState>
|
||||
>({});
|
||||
|
||||
// Store the speed in a ref to access the latest value in animation frames
|
||||
const speedRef = useRef<number>(speed);
|
||||
const {
|
||||
animationStates,
|
||||
setAnimationStates,
|
||||
clockRef,
|
||||
elapsedBeforePauseRef,
|
||||
speedRef,
|
||||
debugRef,
|
||||
findSpawnPoint,
|
||||
createSpawnedObject,
|
||||
handlePointActions,
|
||||
hasNonInheritActions,
|
||||
getPointDataForAnimationIndex,
|
||||
processes: processedProcesses,
|
||||
checkAndCountTriggers,
|
||||
} = useProcessAnimation(processes, setProcesses, agvRef);
|
||||
|
||||
// Update the ref when speed changes
|
||||
useEffect(() => {
|
||||
speedRef.current = speed;
|
||||
}, [speed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (prevIsPlaying.current !== null) {
|
||||
setAnimationStates({});
|
||||
}
|
||||
|
||||
// Update ref to current isPlaying after effect
|
||||
prevIsPlaying.current = isPlaying;
|
||||
|
||||
// setAnimationStates({});
|
||||
}, [isPlaying]);
|
||||
|
||||
// Sync ref with state
|
||||
useEffect(() => {
|
||||
animationStatesRef.current = animationStates;
|
||||
}, [animationStates]);
|
||||
|
||||
// Base materials
|
||||
const baseMaterials = useMemo(
|
||||
() => ({
|
||||
Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
|
||||
@@ -138,365 +49,22 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
[]
|
||||
);
|
||||
|
||||
// Replace your reset effect with this:
|
||||
useEffect(() => {
|
||||
if (isReset) {
|
||||
// 1. Mark that we're doing an internal reset
|
||||
setInternalResetFlag(true);
|
||||
|
||||
// 2. Pause the animation first
|
||||
setIsPlaying(false);
|
||||
setIsPaused(false);
|
||||
|
||||
// 3. Reset all animation states
|
||||
setAnimationStates({});
|
||||
animationStatesRef.current = {};
|
||||
|
||||
// 4. Reset timing references
|
||||
clockRef.current = new THREE.Clock();
|
||||
elapsedBeforePauseRef.current = 0;
|
||||
pauseTimeRef.current = 0;
|
||||
|
||||
// 5. Clear the external reset flag
|
||||
setReset(false);
|
||||
|
||||
// 6. After state updates are complete, restart
|
||||
setTimeout(() => {
|
||||
setInternalResetFlag(false);
|
||||
setIsPlaying(true);
|
||||
}, 0);
|
||||
}
|
||||
}, [isReset, setReset, setIsPlaying, setIsPaused]);
|
||||
|
||||
// Handle pause state changes
|
||||
useEffect(() => {
|
||||
if (isPaused) {
|
||||
pauseTimeRef.current = clockRef.current.getElapsedTime();
|
||||
} else if (pauseTimeRef.current > 0) {
|
||||
const pausedDuration =
|
||||
clockRef.current.getElapsedTime() - pauseTimeRef.current;
|
||||
elapsedBeforePauseRef.current += pausedDuration;
|
||||
}
|
||||
}, [isPaused]);
|
||||
|
||||
// Initialize animation states when processes or play state changes
|
||||
useEffect(() => {
|
||||
if (isPlaying && !internalResetFlag) {
|
||||
const newStates: Record<string, ProcessAnimationState> = {};
|
||||
processes.forEach((process) => {
|
||||
newStates[process.id] = {
|
||||
spawnedObjects: {},
|
||||
nextSpawnTime: 0,
|
||||
objectIdCounter: 0,
|
||||
isProcessDelaying: false,
|
||||
processDelayStartTime: 0,
|
||||
processDelayDuration: 0,
|
||||
};
|
||||
});
|
||||
setAnimationStates(newStates);
|
||||
animationStatesRef.current = newStates;
|
||||
clockRef.current.start();
|
||||
}
|
||||
}, [isPlaying, processes, internalResetFlag]);
|
||||
|
||||
const findSpawnPoint = (process: ProcessData): ProcessPoint | null => {
|
||||
for (const path of process.paths || []) {
|
||||
for (const point of path.points || []) {
|
||||
const spawnAction = point.actions?.find(
|
||||
(a) => a.isUsed && a.type === "Spawn"
|
||||
);
|
||||
if (spawnAction) {
|
||||
return point;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const findAnimationPathPoint = (
|
||||
process: ProcessData,
|
||||
spawnPoint: ProcessPoint
|
||||
): THREE.Vector3 => {
|
||||
if (process.animationPath && process.animationPath.length > 0) {
|
||||
let pointIndex = 0;
|
||||
for (const path of process.paths || []) {
|
||||
for (let i = 0; i < (path.points?.length || 0); i++) {
|
||||
const point = path.points?.[i];
|
||||
if (point && point.uuid === spawnPoint.uuid) {
|
||||
if (process.animationPath[pointIndex]) {
|
||||
const p = process.animationPath[pointIndex];
|
||||
return new THREE.Vector3(p.x, p.y, p.z);
|
||||
}
|
||||
}
|
||||
pointIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new THREE.Vector3(
|
||||
spawnPoint.position[0],
|
||||
spawnPoint.position[1],
|
||||
spawnPoint.position[2]
|
||||
);
|
||||
};
|
||||
|
||||
const createSpawnedObject = (
|
||||
process: ProcessData,
|
||||
currentTime: number,
|
||||
materialType: string,
|
||||
spawnPoint: ProcessPoint
|
||||
): SpawnedObject => {
|
||||
const processMaterials = {
|
||||
...baseMaterials,
|
||||
...(process.customMaterials || {}),
|
||||
};
|
||||
|
||||
const spawnPosition = findAnimationPathPoint(process, spawnPoint);
|
||||
const material =
|
||||
processMaterials[materialType as keyof typeof processMaterials] ||
|
||||
baseMaterials.Default;
|
||||
|
||||
if (debugRef.current) {
|
||||
console.log(`Creating object with material: ${materialType}`, material);
|
||||
}
|
||||
|
||||
return {
|
||||
ref: React.createRef(),
|
||||
state: {
|
||||
currentIndex: 0,
|
||||
progress: 0,
|
||||
isAnimating: true,
|
||||
speed: process.speed || 1, // Process base speed (will be multiplied by global speed)
|
||||
isDelaying: false,
|
||||
delayStartTime: 0,
|
||||
currentDelayDuration: 0,
|
||||
delayComplete: false,
|
||||
currentPathIndex: 0,
|
||||
},
|
||||
visible: true,
|
||||
material: material,
|
||||
currentMaterialType: materialType,
|
||||
spawnTime: currentTime,
|
||||
position: spawnPosition,
|
||||
};
|
||||
};
|
||||
|
||||
const handleMaterialSwap = (
|
||||
processId: string,
|
||||
objectId: string,
|
||||
materialType: string
|
||||
) => {
|
||||
if (debugRef.current) {
|
||||
console.log(`Attempting material swap to: ${materialType}`);
|
||||
}
|
||||
|
||||
setAnimationStates((prev) => {
|
||||
const processState = prev[processId];
|
||||
if (!processState || !processState.spawnedObjects[objectId]) {
|
||||
if (debugRef.current) console.log("Object not found for swap");
|
||||
return prev;
|
||||
}
|
||||
|
||||
const process = processes.find((p) => p.id === processId);
|
||||
if (!process) {
|
||||
if (debugRef.current) console.log("Process not found");
|
||||
return prev;
|
||||
}
|
||||
|
||||
const processMaterials = {
|
||||
...baseMaterials,
|
||||
...(process.customMaterials || {}),
|
||||
};
|
||||
|
||||
const newMaterial =
|
||||
processMaterials[materialType as keyof typeof processMaterials];
|
||||
if (!newMaterial) {
|
||||
if (debugRef.current) console.log(`Material ${materialType} not found`);
|
||||
return prev;
|
||||
}
|
||||
|
||||
if (debugRef.current) {
|
||||
console.log(`Swapping material for ${objectId} to ${materialType}`);
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
[processId]: {
|
||||
...processState,
|
||||
spawnedObjects: {
|
||||
...processState.spawnedObjects,
|
||||
[objectId]: {
|
||||
...processState.spawnedObjects[objectId],
|
||||
material: newMaterial,
|
||||
currentMaterialType: materialType,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const handlePointActions = (
|
||||
processId: string,
|
||||
objectId: string,
|
||||
actions: PointAction[] = [],
|
||||
currentTime: number
|
||||
): boolean => {
|
||||
let shouldStopAnimation = false;
|
||||
|
||||
actions.forEach((action) => {
|
||||
if (!action.isUsed) return;
|
||||
|
||||
if (debugRef.current) {
|
||||
console.log(`Processing action: ${action.type} for ${objectId}`);
|
||||
}
|
||||
|
||||
switch (action.type) {
|
||||
case "Delay":
|
||||
setAnimationStates((prev) => {
|
||||
const processState = prev[processId];
|
||||
if (!processState || processState.isProcessDelaying) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
const delayDuration =
|
||||
typeof action.delay === "number"
|
||||
? action.delay
|
||||
: parseFloat(action.delay as string) || 0;
|
||||
|
||||
if (delayDuration > 0) {
|
||||
return {
|
||||
...prev,
|
||||
[processId]: {
|
||||
...processState,
|
||||
isProcessDelaying: true,
|
||||
processDelayStartTime: currentTime,
|
||||
processDelayDuration: delayDuration,
|
||||
spawnedObjects: {
|
||||
...processState.spawnedObjects,
|
||||
[objectId]: {
|
||||
...processState.spawnedObjects[objectId],
|
||||
state: {
|
||||
...processState.spawnedObjects[objectId].state,
|
||||
isAnimating: false,
|
||||
isDelaying: true,
|
||||
delayStartTime: currentTime,
|
||||
currentDelayDuration: delayDuration,
|
||||
delayComplete: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
return prev;
|
||||
});
|
||||
shouldStopAnimation = true;
|
||||
break;
|
||||
|
||||
case "Despawn":
|
||||
setAnimationStates((prev) => {
|
||||
const processState = prev[processId];
|
||||
if (!processState) return prev;
|
||||
|
||||
const newSpawnedObjects = { ...processState.spawnedObjects };
|
||||
delete newSpawnedObjects[objectId];
|
||||
|
||||
return {
|
||||
...prev,
|
||||
[processId]: {
|
||||
...processState,
|
||||
spawnedObjects: newSpawnedObjects,
|
||||
},
|
||||
};
|
||||
});
|
||||
shouldStopAnimation = true;
|
||||
break;
|
||||
|
||||
case "Swap":
|
||||
if (action.material) {
|
||||
handleMaterialSwap(processId, objectId, action.material);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return shouldStopAnimation;
|
||||
};
|
||||
|
||||
const hasNonInheritActions = (actions: PointAction[] = []): boolean => {
|
||||
return actions.some((action) => action.isUsed && action.type !== "Inherit");
|
||||
};
|
||||
|
||||
const getPointDataForAnimationIndex = (
|
||||
process: ProcessData,
|
||||
index: number
|
||||
): ProcessPoint | null => {
|
||||
if (!process.paths) return null;
|
||||
|
||||
let cumulativePoints = 0;
|
||||
for (const path of process.paths) {
|
||||
const pointCount = path.points?.length || 0;
|
||||
|
||||
if (index < cumulativePoints + pointCount) {
|
||||
const pointIndex = index - cumulativePoints;
|
||||
return path.points?.[pointIndex] || null;
|
||||
}
|
||||
|
||||
cumulativePoints += pointCount;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
// In processAnimator.tsx - only the relevant spawn logic part that needs fixes
|
||||
|
||||
useFrame(() => {
|
||||
if (!isPlaying || isPaused) return;
|
||||
|
||||
// Spawn logic frame
|
||||
const currentTime =
|
||||
clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
|
||||
|
||||
setAnimationStates((prev) => {
|
||||
const newStates = { ...prev };
|
||||
|
||||
processes.forEach((process) => {
|
||||
processedProcesses.forEach((process) => {
|
||||
const processState = newStates[process.id];
|
||||
if (!processState) return;
|
||||
|
||||
if (processState.isProcessDelaying) {
|
||||
// Apply global speed to delays (faster speed = shorter delays)
|
||||
const effectiveDelayTime =
|
||||
processState.processDelayDuration / speedRef.current;
|
||||
|
||||
if (
|
||||
currentTime - processState.processDelayStartTime >=
|
||||
effectiveDelayTime
|
||||
) {
|
||||
newStates[process.id] = {
|
||||
...processState,
|
||||
isProcessDelaying: false,
|
||||
spawnedObjects: Object.entries(
|
||||
processState.spawnedObjects
|
||||
).reduce(
|
||||
(acc, [id, obj]) => ({
|
||||
...acc,
|
||||
[id]: {
|
||||
...obj,
|
||||
state: {
|
||||
...obj.state,
|
||||
isDelaying: false,
|
||||
delayComplete: true,
|
||||
isAnimating: true,
|
||||
progress:
|
||||
obj.state.progress === 0 ? 0.001 : obj.state.progress,
|
||||
},
|
||||
},
|
||||
}),
|
||||
{}
|
||||
),
|
||||
};
|
||||
}
|
||||
// Existing delay handling logic...
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -513,7 +81,14 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
? spawnAction.spawnInterval
|
||||
: parseFloat(spawnAction.spawnInterval as string) || 0;
|
||||
|
||||
// Apply global speed to spawn intervals (faster speed = more frequent spawns)
|
||||
// Check if this is a zero interval spawn and we already spawned an object
|
||||
if (
|
||||
spawnInterval === 0 &&
|
||||
processState.hasSpawnedZeroIntervalObject === true
|
||||
) {
|
||||
return; // Don't spawn more objects for zero interval
|
||||
}
|
||||
|
||||
const effectiveSpawnInterval = spawnInterval / speedRef.current;
|
||||
|
||||
if (currentTime >= processState.nextSpawnTime) {
|
||||
@@ -522,9 +97,11 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
process,
|
||||
currentTime,
|
||||
spawnAction.material || "Default",
|
||||
spawnPoint
|
||||
spawnPoint,
|
||||
baseMaterials
|
||||
);
|
||||
|
||||
// Update state with the new object and flag for zero interval
|
||||
newStates[process.id] = {
|
||||
...processState,
|
||||
spawnedObjects: {
|
||||
@@ -533,6 +110,11 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
},
|
||||
objectIdCounter: processState.objectIdCounter + 1,
|
||||
nextSpawnTime: currentTime + effectiveSpawnInterval,
|
||||
// Mark that we've spawned an object for zero interval case
|
||||
hasSpawnedZeroIntervalObject:
|
||||
spawnInterval === 0
|
||||
? true
|
||||
: processState.hasSpawnedZeroIntervalObject,
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -542,20 +124,18 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
});
|
||||
|
||||
useFrame((_, delta) => {
|
||||
if (!isPlaying || isPaused) return;
|
||||
|
||||
// Animation logic frame
|
||||
const currentTime =
|
||||
clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
|
||||
|
||||
setAnimationStates((prev) => {
|
||||
const newStates = { ...prev };
|
||||
|
||||
processes.forEach((process) => {
|
||||
processedProcesses.forEach((process) => {
|
||||
const processState = newStates[process.id];
|
||||
if (!processState) return;
|
||||
|
||||
if (processState.isProcessDelaying) {
|
||||
// Apply global speed to delays (faster speed = shorter delays)
|
||||
const effectiveDelayTime =
|
||||
processState.processDelayDuration / speedRef.current;
|
||||
|
||||
@@ -617,7 +197,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
const stateRef = obj.state;
|
||||
|
||||
if (stateRef.isDelaying) {
|
||||
// Apply global speed to delays (faster speed = shorter delays)
|
||||
const effectiveDelayTime =
|
||||
stateRef.currentDelayDuration / speedRef.current;
|
||||
|
||||
@@ -654,18 +233,15 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
stateRef.currentIndex
|
||||
);
|
||||
|
||||
// Handle point actions when first arriving at point
|
||||
if (stateRef.progress === 0 && currentPointData?.actions) {
|
||||
if (debugRef.current) {
|
||||
console.log(
|
||||
`At point ${stateRef.currentIndex} with actions:`,
|
||||
currentPointData.actions
|
||||
);
|
||||
}
|
||||
const shouldStop = handlePointActions(
|
||||
process.id,
|
||||
objectId,
|
||||
currentPointData.actions,
|
||||
currentTime
|
||||
currentTime,
|
||||
processedProcesses,
|
||||
baseMaterials
|
||||
);
|
||||
if (shouldStop) {
|
||||
updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
||||
@@ -691,8 +267,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
const nextPoint = path[nextPointIdx];
|
||||
const distance =
|
||||
path[stateRef.currentIndex].distanceTo(nextPoint);
|
||||
|
||||
// Apply both process-specific speed and global speed multiplier
|
||||
const effectiveSpeed = stateRef.speed * speedRef.current;
|
||||
const movement = effectiveSpeed * delta;
|
||||
|
||||
@@ -708,17 +282,19 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
stateRef.progress = 0;
|
||||
currentRef.position.copy(nextPoint);
|
||||
|
||||
// TRIGGER CHECK - When object arrives at new point
|
||||
checkAndCountTriggers(
|
||||
process.id,
|
||||
objectId,
|
||||
stateRef.currentIndex, // The new point index
|
||||
processedProcesses,
|
||||
currentTime
|
||||
);
|
||||
|
||||
const newPointData = getPointDataForAnimationIndex(
|
||||
process,
|
||||
stateRef.currentIndex
|
||||
);
|
||||
|
||||
if (newPointData?.actions && debugRef.current) {
|
||||
console.log(
|
||||
`Reached new point with actions:`,
|
||||
newPointData.actions
|
||||
);
|
||||
}
|
||||
} else {
|
||||
currentRef.position.lerpVectors(
|
||||
path[stateRef.currentIndex],
|
||||
@@ -742,56 +318,31 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
|
||||
});
|
||||
});
|
||||
|
||||
if (!processes || processes.length === 0) {
|
||||
if (!processedProcesses || processedProcesses.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<group ref={groupRef}>
|
||||
{Object.entries(animationStates).flatMap(([processId, processState]) =>
|
||||
Object.entries(processState.spawnedObjects)
|
||||
.filter(([_, obj]) => obj.visible)
|
||||
.map(([objectId, obj]) => {
|
||||
const process = processes.find((p) => p.id === processId);
|
||||
const process = processedProcesses.find((p) => p.id === processId);
|
||||
const renderAs = process?.renderAs || "custom";
|
||||
|
||||
if (renderAs === "box") {
|
||||
return (
|
||||
<mesh
|
||||
key={objectId}
|
||||
ref={obj.ref as React.RefObject<THREE.Mesh>}
|
||||
material={obj.material}
|
||||
position={obj.position}
|
||||
>
|
||||
<boxGeometry args={[1, 1, 1]} />
|
||||
</mesh>
|
||||
);
|
||||
}
|
||||
|
||||
if (gltf?.scene) {
|
||||
// Clone the scene and apply the material to all meshes
|
||||
const clonedScene = gltf.scene.clone();
|
||||
clonedScene.traverse((child) => {
|
||||
if (child instanceof THREE.Mesh) {
|
||||
child.material = obj.material;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<group
|
||||
key={objectId}
|
||||
ref={obj.ref as React.RefObject<THREE.Group>}
|
||||
position={obj.position}
|
||||
>
|
||||
<primitive object={clonedScene} />
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
return (
|
||||
<ProcessObject
|
||||
key={objectId}
|
||||
objectId={objectId}
|
||||
obj={obj}
|
||||
renderAs={renderAs}
|
||||
gltf={gltf}
|
||||
/>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</>
|
||||
</group>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user