From 280fe59a14cd84eff6d1fb7b9cca4eaa89cf32ee Mon Sep 17 00:00:00 2001 From: SreeNath14 <153710861+SreeNath14@users.noreply.github.com> Date: Fri, 4 Apr 2025 09:54:08 +0530 Subject: [PATCH] :updated swap" --- .../simulation/process/processAnimator.tsx | 201 ++++++++---------- app/src/types/world/worldTypes.d.ts | 29 ++- 2 files changed, 116 insertions(+), 114 deletions(-) diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx index 512b165..fe62343 100644 --- a/app/src/modules/simulation/process/processAnimator.tsx +++ b/app/src/modules/simulation/process/processAnimator.tsx @@ -78,7 +78,7 @@ // const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ // processes, // }) => { -// +// // const gltf = useLoader(GLTFLoader, boxGltb) as GLTF; // const { isPlaying } = usePlayButtonStore(); // const groupRef = useRef(null); @@ -646,14 +646,13 @@ interface SpawnedObject { material: THREE.Material; spawnTime: number; currentMaterialType: string; - position: THREE.Vector3; // The position of the object + position: THREE.Vector3; } interface ProcessAnimationState { spawnedObjects: { [objectId: string]: SpawnedObject }; nextSpawnTime: number; objectIdCounter: number; - // New fields for process-wide delay isProcessDelaying: boolean; processDelayStartTime: number; processDelayDuration: number; @@ -662,10 +661,10 @@ interface ProcessAnimationState { const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ processes, }) => { - const gltf = useLoader(GLTFLoader, boxGltb) as GLTF; const { isPlaying } = usePlayButtonStore(); const groupRef = useRef(null); + const debugRef = useRef(false); const [animationStates, setAnimationStates] = useState< Record @@ -674,15 +673,8 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ // Base materials const baseMaterials = useMemo( () => ({ - Wood: new THREE.MeshStandardMaterial({ color: 0x8b4513 }), - Box: new THREE.MeshPhongMaterial({ - color: 0xcccccc, - }), - Crate: new THREE.MeshStandardMaterial({ - color: 0x00aaff, - metalness: 0.1, - roughness: 0.5, - }), + Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }), + Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }), Default: new THREE.MeshStandardMaterial({ color: 0x00ff00 }), }), [] @@ -701,7 +693,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ spawnedObjects: {}, nextSpawnTime: 0, objectIdCounter: 0, - // Initialize process-wide delay state isProcessDelaying: false, processDelayStartTime: 0, processDelayDuration: 0, @@ -710,7 +701,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ setAnimationStates(newStates); }, [isPlaying, processes]); - // Find spawn point in a process const findSpawnPoint = (process: ProcessData): ProcessPoint | null => { for (const path of process.paths || []) { for (const point of path.points || []) { @@ -725,22 +715,16 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ return null; }; - // Find the corresponding animation path point for a spawn point const findAnimationPathPoint = ( process: ProcessData, spawnPoint: ProcessPoint ): THREE.Vector3 => { - // If we have an animation path, use the first point if (process.animationPath && process.animationPath.length > 0) { - // Find the index of this point in the path let pointIndex = 0; - - // Try to find the corresponding point in the animation path 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) { - // Found the matching point if (process.animationPath[pointIndex]) { const p = process.animationPath[pointIndex]; return new THREE.Vector3(p.x, p.y, p.z); @@ -749,16 +733,7 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ pointIndex++; } } - - // Fallback to the spawn point's position - return new THREE.Vector3( - spawnPoint.position[0], - spawnPoint.position[1], - spawnPoint.position[2] - ); } - - // If no animation path, use the spawn point's position return new THREE.Vector3( spawnPoint.position[0], spawnPoint.position[1], @@ -766,7 +741,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ ); }; - // Create a new spawned object const createSpawnedObject = ( process: ProcessData, currentTime: number, @@ -778,8 +752,14 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ ...(process.customMaterials || {}), }; - // Get the position where we should spawn 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(), @@ -795,34 +775,50 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ currentPathIndex: 0, }, visible: true, - material: - processMaterials[materialType as keyof typeof processMaterials] || - baseMaterials.Default, + material: material, currentMaterialType: materialType, spawnTime: currentTime, - position: spawnPosition, // Store the position directly + position: spawnPosition, }; }; - // Handle material swap for an object 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]) return prev; + 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 || {}), + ...(process.customMaterials || {}), }; const newMaterial = - processMaterials[materialType as keyof typeof processMaterials] || - baseMaterials.Default; + 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, @@ -841,7 +837,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ }); }; - // Handle point actions for an object const handlePointActions = ( processId: string, objectId: string, @@ -853,6 +848,10 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ 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) => { @@ -871,18 +870,16 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ ...prev, [processId]: { ...processState, - // Set process-wide delay instead of object-specific delay isProcessDelaying: true, processDelayStartTime: currentTime, processDelayDuration: delayDuration, - // Update the specific object's state as well spawnedObjects: { ...processState.spawnedObjects, [objectId]: { ...processState.spawnedObjects[objectId], state: { ...processState.spawnedObjects[objectId].state, - isAnimating: false, // Explicitly pause animation during delay + isAnimating: false, isDelaying: true, delayStartTime: currentTime, currentDelayDuration: delayDuration, @@ -931,12 +928,10 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ return shouldStopAnimation; }; - // Check if point has non-inherit actions const hasNonInheritActions = (actions: PointAction[] = []): boolean => { return actions.some((action) => action.isUsed && action.type !== "Inherit"); }; - // Get point data for current animation index const getPointDataForAnimationIndex = ( process: ProcessData, index: number @@ -958,7 +953,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ return null; }; - // Spawn objects for all processes useFrame((state) => { if (!isPlaying) return; @@ -970,18 +964,14 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ const processState = newStates[process.id]; if (!processState) return; - // Skip spawning if the process is currently in a delay if (processState.isProcessDelaying) { - // Check if delay is over if ( currentTime - processState.processDelayStartTime >= processState.processDelayDuration ) { - // Reset process delay state newStates[process.id] = { ...processState, isProcessDelaying: false, - // Reset delay state on all objects in this process spawnedObjects: Object.entries( processState.spawnedObjects ).reduce( @@ -993,8 +983,7 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ ...obj.state, isDelaying: false, delayComplete: true, - isAnimating: true, // Ensure animation resumes - // Force a small progress to ensure movement starts + isAnimating: true, progress: obj.state.progress === 0 ? 0.001 : obj.state.progress, }, @@ -1004,7 +993,7 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ ), }; } - return; // Skip spawning while delaying + return; } const spawnPoint = findSpawnPoint(process); @@ -1022,8 +1011,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ if (currentTime >= processState.nextSpawnTime) { const objectId = `obj-${process.id}-${processState.objectIdCounter}`; - - // Create the new object with the spawn point const newObject = createSpawnedObject( process, currentTime, @@ -1047,7 +1034,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ }); }); - // Animate objects for all processes useFrame((state, delta) => { if (!isPlaying) return; @@ -1059,18 +1045,14 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ const processState = newStates[process.id]; if (!processState) return; - // Check if the process-wide delay is active if (processState.isProcessDelaying) { - // Check if the delay has completed if ( currentTime - processState.processDelayStartTime >= processState.processDelayDuration ) { - // Reset process delay state AND resume animation newStates[process.id] = { ...processState, isProcessDelaying: false, - // Reset delay state on all objects in this process AND ensure isAnimating is true spawnedObjects: Object.entries( processState.spawnedObjects ).reduce( @@ -1082,8 +1064,7 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ ...obj.state, isDelaying: false, delayComplete: true, - isAnimating: true, // Ensure animation resumes - // Important: Force progress to a small positive value to ensure movement + isAnimating: true, progress: obj.state.progress === 0 ? 0.005 : obj.state.progress, }, @@ -1092,10 +1073,8 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ {} ), }; - // Skip the rest of the processing for this frame to allow the state update to take effect return newStates; } else { - // If we're still in a process-wide delay, don't animate anything return newStates; } } @@ -1109,13 +1088,11 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ Object.entries(processState.spawnedObjects).forEach( ([objectId, obj]) => { - // Skip objects that are explicitly not visible if (!obj.visible) return; const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current; if (!currentRef) return; - // Set the position when the reference is first available if ( obj.position && obj.state.currentIndex === 0 && @@ -1126,27 +1103,21 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ const stateRef = obj.state; - // Check if we're delaying at the object level and update accordingly if (stateRef.isDelaying) { if ( currentTime - stateRef.delayStartTime >= stateRef.currentDelayDuration ) { - // Delay is complete, resume animation stateRef.isDelaying = false; stateRef.delayComplete = true; - stateRef.isAnimating = true; // Explicitly resume animation + stateRef.isAnimating = true; - // Force movement from the current point by setting progress to a small value - // if we're at the start of a segment if (stateRef.progress === 0) { stateRef.progress = 0.005; } - // Force an immediate position update to ensure visually accurate position const nextPointIdx = stateRef.currentIndex + 1; if (nextPointIdx < path.length) { - // Calculate the position slightly ahead of the current point const slightProgress = Math.max(stateRef.progress, 0.005); currentRef.position.lerpVectors( path[stateRef.currentIndex], @@ -1157,23 +1128,25 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ ); } } else { - // Still delaying, don't animate this object updatedObjects[objectId] = { ...obj, state: { ...stateRef } }; return; } } - // Skip animation if the object shouldn't be animating if (!stateRef.isAnimating) return; - // Get current point data const currentPointData = getPointDataForAnimationIndex( process, stateRef.currentIndex ); - // Execute actions when arriving at a new 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, @@ -1195,10 +1168,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ currentPointData.actions ); if (shouldStop) { - // uncomment this or write own logic to handle the object when reaching the last point of the process - - // currentRef.position.copy(path[stateRef.currentIndex]); - // delete updatedObjects[objectId]; return; } } @@ -1210,35 +1179,30 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ path[stateRef.currentIndex].distanceTo(nextPoint); const movement = stateRef.speed * delta; - // If we just resumed from a delay, ensure we make actual progress if (stateRef.delayComplete && stateRef.progress < 0.01) { - // Boost initial movement after delay to ensure visible progress - stateRef.progress = 0.05; // Small but visible initial progress - stateRef.delayComplete = false; // Reset flag so we don't do this again + stateRef.progress = 0.05; + stateRef.delayComplete = false; } else { - // Normal progress calculation stateRef.progress += movement / distance; } if (stateRef.progress >= 1) { - // We've reached the next point stateRef.currentIndex = nextPointIdx; stateRef.progress = 0; currentRef.position.copy(nextPoint); - // Check if we need to execute actions at this new point const newPointData = getPointDataForAnimationIndex( process, stateRef.currentIndex ); - if (newPointData?.actions) { - // We've arrived at a new point with actions, handle them in the next frame - // We don't call handlePointActions directly here to avoid state update issues - // The actions will be handled in the next frame when progress is 0 + if (newPointData?.actions && debugRef.current) { + console.log( + `Reached new point with actions:`, + newPointData.actions + ); } } else { - // Normal path interpolation currentRef.position.lerpVectors( path[stateRef.currentIndex], nextPoint, @@ -1274,29 +1238,40 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ const process = processes.find((p) => p.id === processId); const renderAs = process?.renderAs || "custom"; - return renderAs === "box" ? ( - } - material={obj.material} - position={obj.position} // Set position directly in the JSX - > - - - ) : ( - gltf?.scene && ( + if (renderAs === "box") { + return ( + } + material={obj.material} + position={obj.position} + > + + + ); + } + + 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 ( } - position={obj.position} // Set position directly in the JSX + position={obj.position} > - + - ) - ); + ); + } + + return null; }) )} diff --git a/app/src/types/world/worldTypes.d.ts b/app/src/types/world/worldTypes.d.ts index d1ce13f..cbb1c39 100644 --- a/app/src/types/world/worldTypes.d.ts +++ b/app/src/types/world/worldTypes.d.ts @@ -336,4 +336,31 @@ interface VehicleEventsSchema { speed: number; }; position: [number, number, number]; -} \ No newline at end of file +} + +// interface ArmSchema { +// modeluuid: string; +// modelName: string; +// type: 'Arm'; +// point: { +// uuid: string; +// position: [number, number, number]; +// actions: { MaterialId: string, }[] |.; +// connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; +// speed: number; +// }; +// position: [number, number, number]; +// } + + + + +// export type FloorItemType = { +// modeluuid: string; +// modelname: string; +// position: [number, number, number]; +// rotation: { x: number; y: number; z: number }; +// modelfileID: string; +// isLocked: boolean; +// isVisible: boolean; +// }; \ No newline at end of file