From 844c8c3366d52029f0aff845052975523fb2b7a6 Mon Sep 17 00:00:00 2001 From: SreeNath14 <153710861+SreeNath14@users.noreply.github.com> Date: Wed, 2 Apr 2025 11:10:44 +0530 Subject: [PATCH] updated new animation --- .../simulation/process/animationWorker.js | 4 + .../simulation/process/processAnimator.tsx | 149 ++--- .../simulation/process/processCreator.tsx | 542 +++++++++++++++--- 3 files changed, 514 insertions(+), 181 deletions(-) create mode 100644 app/src/modules/simulation/process/animationWorker.js diff --git a/app/src/modules/simulation/process/animationWorker.js b/app/src/modules/simulation/process/animationWorker.js new file mode 100644 index 0000000..e9dddd1 --- /dev/null +++ b/app/src/modules/simulation/process/animationWorker.js @@ -0,0 +1,4 @@ + +const animationWorker = () => { + return; +}; diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx index 123ec80..d8e35e6 100644 --- a/app/src/modules/simulation/process/processAnimator.tsx +++ b/app/src/modules/simulation/process/processAnimator.tsx @@ -5,11 +5,13 @@ import { useLoader, useFrame } from "@react-three/fiber"; import * as THREE from "three"; import { GLTF } from "three-stdlib"; import boxGltb from "../../../assets/gltf-glb/crate_box.glb"; +import camera from "../../../assets/gltf-glb/camera face 2.gltf"; interface PointAction { uuid: string; name: string; type: "Inherit" | "Spawn" | "Despawn" | "Delay" | "Swap"; + objectType: string; material: string; delay: string | number; spawnInterval: string | number; @@ -54,18 +56,8 @@ interface AnimationState { currentDelayDuration: number; delayComplete: boolean; currentPathIndex: number; - spawnPoints: Record< - string, - { - position: THREE.Vector3; - interval: number; - lastSpawnTime: number; - } - >; } -const MAX_SPAWNED_OBJECTS = 20; - const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ processes, }) => { @@ -76,7 +68,7 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ const groupRef = useRef<THREE.Group>(null); const meshRef = useRef<THREE.Mesh>(null); const [visible, setVisible] = useState(false); - const spawnedObjectsRef = useRef<THREE.Object3D[]>([]); + const [currentPathIndex, setCurrentPathIndex] = useState(0); const materials = useMemo( () => ({ @@ -125,18 +117,26 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ currentDelayDuration: 0, delayComplete: false, currentPathIndex: 0, - spawnPoints: {}, }); const getPointDataForAnimationIndex = (index: number) => { if (!processes[0]?.paths) return null; - if (index < 3) { - return processes[0].paths[0]?.points[index]; - } else { - const path2Index = index - 3; - return processes[0].paths[1]?.points[path2Index]; + let cumulativePoints = 0; + console.log("cumulativePoints: ", cumulativePoints); + + for (const path of processes[0].paths) { + const pointCount = path.points?.length || 0; + + if (index < cumulativePoints + pointCount) { + const pointIndex = index - cumulativePoints; + return path.points?.[pointIndex] || null; + } + + cumulativePoints += pointCount; } + + return null; }; useEffect(() => { @@ -152,22 +152,8 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ currentDelayDuration: 0, delayComplete: false, currentPathIndex: 0, - spawnPoints: {}, }; - // Clear spawned objects - if (groupRef.current) { - spawnedObjectsRef.current.forEach((obj) => { - if (groupRef.current?.children.includes(obj)) { - groupRef.current.remove(obj); - } - if (obj instanceof THREE.Mesh) { - obj.material.dispose(); - } - }); - spawnedObjectsRef.current = []; - } - const currentRef = gltf?.scene ? groupRef.current : meshRef.current; if (currentRef && animationPath.length > 0) { currentRef.position.copy(animationPath[0]); @@ -178,15 +164,9 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ }, [isPlaying, currentProcess, animationPath]); const handleMaterialSwap = (materialType: string) => { - const newMaterial = - materials[materialType as keyof typeof materials] || materials.Default; - setCurrentMaterial(newMaterial); - - spawnedObjectsRef.current.forEach((obj) => { - if (obj instanceof THREE.Mesh) { - obj.material = newMaterial.clone(); - } - }); + setCurrentMaterial( + materials[materialType as keyof typeof materials] || materials.Default + ); }; const hasNonInheritActions = (actions: PointAction[] = []) => { @@ -195,8 +175,7 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ const handlePointActions = ( actions: PointAction[] = [], - currentTime: number, - currentPosition: THREE.Vector3 + currentTime: number ) => { let shouldStopAnimation = false; @@ -231,18 +210,7 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ break; case "Spawn": - const spawnInterval = - typeof action.spawnInterval === "number" - ? action.spawnInterval - : parseFloat(action.spawnInterval as string) || 1; - - const positionKey = currentPosition.toArray().join(","); - - animationStateRef.current.spawnPoints[positionKey] = { - position: currentPosition.clone(), - interval: spawnInterval, - lastSpawnTime: currentTime - spawnInterval, // Force immediate spawn - }; + setVisible(true); break; case "Swap": @@ -252,6 +220,7 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ break; case "Inherit": + // Handle inherit logic if needed break; } }); @@ -273,24 +242,38 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ const path = animationPath; const stateRef = animationStateRef.current; + // Check if we need to switch paths (specific to your structure) if (stateRef.currentIndex === 3 && stateRef.currentPathIndex === 0) { + setCurrentPathIndex(1); stateRef.currentPathIndex = 1; } + // Get the current point data const currentPointData = getPointDataForAnimationIndex( stateRef.currentIndex ); + // Execute actions when we first arrive at a point + if (stateRef.progress === 0 && currentPointData?.actions) { + console.log( + `Processing actions at point ${stateRef.currentIndex}`, + currentPointData.actions + ); const shouldStop = handlePointActions( currentPointData.actions, - currentTime, - currentRef.position + currentTime ); if (shouldStop) return; } + // Handle delays if (stateRef.isDelaying) { + console.log( + `Delaying... ${currentTime - stateRef.delayStartTime}/${ + stateRef.currentDelayDuration + }` + ); if ( currentTime - stateRef.delayStartTime >= stateRef.currentDelayDuration @@ -298,46 +281,10 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ stateRef.isDelaying = false; stateRef.delayComplete = true; } else { - return; + return; // Keep waiting } } - // Handle spawning - this is the key updated part - Object.entries(stateRef.spawnPoints).forEach(([key, spawnPoint]) => { - if (currentTime - spawnPoint.lastSpawnTime >= spawnPoint.interval) { - spawnPoint.lastSpawnTime = currentTime; - - if (gltf?.scene && groupRef?.current) { - const newObject = gltf.scene.clone(); - newObject.position.copy(spawnPoint.position); - - newObject.traverse((child) => { - if (child instanceof THREE.Mesh) { - child.material = currentMaterial.clone(); - } - }); - - groupRef.current.add(newObject); - spawnedObjectsRef.current.push(newObject); - - // Clean up old objects if needed - console.log( - "spawnedObjectsRef.current.length: ", - spawnedObjectsRef.current.length - ); - if (spawnedObjectsRef.current.length > MAX_SPAWNED_OBJECTS) { - const oldest = spawnedObjectsRef.current.shift(); - if (oldest && groupRef.current.children.includes(oldest)) { - groupRef.current.remove(oldest); - if (oldest instanceof THREE.Mesh) { - oldest.material.dispose(); - } - } - } - } - } - }); - const nextPointIdx = stateRef.currentIndex + 1; const isLastPoint = nextPointIdx >= path.length; @@ -374,22 +321,6 @@ const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({ } }); - useEffect(() => { - return () => { - if (groupRef.current) { - spawnedObjectsRef.current.forEach((obj) => { - if (groupRef.current?.children.includes(obj)) { - groupRef.current.remove(obj); - } - if (obj instanceof THREE.Mesh) { - obj.material.dispose(); - } - }); - spawnedObjectsRef.current = []; - } - }; - }, []); - if (!processes || processes.length === 0) { return null; } diff --git a/app/src/modules/simulation/process/processCreator.tsx b/app/src/modules/simulation/process/processCreator.tsx index 8e1ed1d..e70408b 100644 --- a/app/src/modules/simulation/process/processCreator.tsx +++ b/app/src/modules/simulation/process/processCreator.tsx @@ -1,3 +1,402 @@ +// import React, { +// useEffect, +// useMemo, +// useState, +// useCallback, +// useRef, +// } from "react"; +// import { useSimulationPaths } from "../../../store/store"; +// import * as THREE from "three"; +// import { useThree } from "@react-three/fiber"; +// import { +// ConveyorEventsSchema, +// VehicleEventsSchema, +// } from "../../../types/world/worldTypes"; + +// // Type definitions +// export interface PointAction { +// uuid: string; +// name: string; +// type: string; +// material: string; +// delay: number | string; +// spawnInterval: string | number; +// isUsed: boolean; +// } + +// export interface PathPoint { +// uuid: string; +// position: [number, number, number]; +// actions: PointAction[]; +// connections: { +// targets: Array<{ pathUUID: string }>; +// }; +// } + +// export interface SimulationPath { +// modeluuid: string; +// points: PathPoint[]; +// pathPosition: [number, number, number]; +// speed?: number; +// } + +// export interface Process { +// id: string; +// paths: SimulationPath[]; +// animationPath: THREE.Vector3[]; +// pointActions: PointAction[][]; +// speed: number; +// } + +// interface ProcessCreatorProps { +// onProcessesCreated: (processes: Process[]) => void; +// } + +// // Convert event schemas to SimulationPath +// function convertToSimulationPath( +// path: ConveyorEventsSchema | VehicleEventsSchema +// ): SimulationPath { +// const { modeluuid } = path; + +// // Simplified normalizeAction function that preserves exact original properties +// const normalizeAction = (action: any): PointAction => { +// return { ...action }; // Return exact copy with no modifications +// }; + +// if (path.type === "Conveyor") { +// return { +// modeluuid, +// points: path.points.map((point) => ({ +// uuid: point.uuid, +// position: point.position, +// actions: point.actions.map(normalizeAction), // Preserve exact actions +// connections: { +// targets: point.connections.targets.map((target) => ({ +// pathUUID: target.pathUUID, +// })), +// }, +// })), +// pathPosition: path.position, +// speed: +// typeof path.speed === "string" +// ? parseFloat(path.speed) || 1 +// : path.speed || 1, +// }; +// } else { +// return { +// modeluuid, +// points: [ +// { +// uuid: path.point.uuid, +// position: path.point.position, +// actions: Array.isArray(path.point.actions) +// ? path.point.actions.map(normalizeAction) +// : [normalizeAction(path.point.actions)], +// connections: { +// targets: path.point.connections.targets.map((target) => ({ +// pathUUID: target.pathUUID, +// })), +// }, +// }, +// ], +// pathPosition: path.position, +// speed: path.point.speed || 1, +// }; +// } +// } + +// // Custom shallow comparison for arrays +// const areArraysEqual = (a: any[], b: any[]) => { +// if (a.length !== b.length) return false; +// for (let i = 0; i < a.length; i++) { +// if (a[i] !== b[i]) return false; +// } +// return true; +// }; + +// // Helper function to create an empty process +// const createEmptyProcess = (): Process => ({ +// id: `process-${Math.random().toString(36).substring(2, 11)}`, +// paths: [], +// animationPath: [], +// pointActions: [], +// speed: 1, +// }); + +// // Enhanced connection checking function +// function shouldReverseNextPath( +// currentPath: SimulationPath, +// nextPath: SimulationPath +// ): boolean { +// if (nextPath.points.length !== 3) return false; + +// const currentLastPoint = currentPath.points[currentPath.points.length - 1]; +// const nextFirstPoint = nextPath.points[0]; +// const nextLastPoint = nextPath.points[nextPath.points.length - 1]; + +// // Check if current last connects to next last (requires reversal) +// const connectsToLast = currentLastPoint.connections.targets.some( +// (target) => +// target.pathUUID === nextPath.modeluuid && +// nextLastPoint.connections.targets.some( +// (t) => t.pathUUID === currentPath.modeluuid +// ) +// ); + +// // Check if current last connects to next first (no reversal needed) +// const connectsToFirst = currentLastPoint.connections.targets.some( +// (target) => +// target.pathUUID === nextPath.modeluuid && +// nextFirstPoint.connections.targets.some( +// (t) => t.pathUUID === currentPath.modeluuid +// ) +// ); + +// // Only reverse if connected to last point and not to first point +// return connectsToLast && !connectsToFirst; +// } + +// // Updated path adjustment function +// function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] { +// if (paths.length < 2) return paths; + +// const adjustedPaths = [...paths]; + +// for (let i = 0; i < adjustedPaths.length - 1; i++) { +// const currentPath = adjustedPaths[i]; +// const nextPath = adjustedPaths[i + 1]; + +// if (shouldReverseNextPath(currentPath, nextPath)) { +// const reversedPoints = [ +// nextPath.points[2], +// nextPath.points[1], +// nextPath.points[0], +// ]; + +// adjustedPaths[i + 1] = { +// ...nextPath, +// points: reversedPoints, +// }; +// } +// } + +// return adjustedPaths; +// } + +// // Main hook for process creation +// export function useProcessCreation() { +// const { scene } = useThree(); +// const [processes, setProcesses] = useState<Process[]>([]); + +// const hasSpawnAction = useCallback((path: SimulationPath): boolean => { +// return path.points.some((point) => +// point.actions.some((action) => action.type.toLowerCase() === "spawn") +// ); +// }, []); + +// const createProcess = useCallback( +// (paths: SimulationPath[]): Process => { +// if (!paths || paths.length === 0) { +// return createEmptyProcess(); +// } + +// const animationPath: THREE.Vector3[] = []; +// const pointActions: PointAction[][] = []; +// const processSpeed = paths[0]?.speed || 1; + +// for (const path of paths) { +// for (const point of path.points) { +// const obj = scene.getObjectByProperty("uuid", point.uuid); +// if (!obj) { +// console.warn(`Object with UUID ${point.uuid} not found in scene`); +// continue; +// } + +// const position = obj.getWorldPosition(new THREE.Vector3()); +// animationPath.push(position.clone()); +// pointActions.push(point.actions); +// } +// } + +// return { +// id: `process-${Math.random().toString(36).substring(2, 11)}`, +// paths, +// animationPath, +// pointActions, +// speed: processSpeed, +// }; +// }, +// [scene] +// ); + +// const getAllConnectedPaths = useCallback( +// ( +// initialPath: SimulationPath, +// allPaths: SimulationPath[], +// visited: Set<string> = new Set() +// ): SimulationPath[] => { +// const connectedPaths: SimulationPath[] = []; +// const queue: SimulationPath[] = [initialPath]; +// visited.add(initialPath.modeluuid); + +// const pathMap = new Map<string, SimulationPath>(); +// allPaths.forEach((path) => pathMap.set(path.modeluuid, path)); + +// while (queue.length > 0) { +// const currentPath = queue.shift()!; +// connectedPaths.push(currentPath); + +// // Process outgoing connections +// for (const point of currentPath.points) { +// for (const target of point.connections.targets) { +// if (!visited.has(target.pathUUID)) { +// const targetPath = pathMap.get(target.pathUUID); +// if (targetPath) { +// visited.add(target.pathUUID); +// queue.push(targetPath); +// } +// } +// } +// } + +// // Process incoming connections +// for (const [uuid, path] of pathMap) { +// if (!visited.has(uuid)) { +// const hasConnectionToCurrent = path.points.some((point) => +// point.connections.targets.some( +// (t) => t.pathUUID === currentPath.modeluuid +// ) +// ); +// if (hasConnectionToCurrent) { +// visited.add(uuid); +// queue.push(path); +// } +// } +// } +// } + +// return connectedPaths; +// }, +// [] +// ); + +// const createProcessesFromPaths = useCallback( +// (paths: SimulationPath[]): Process[] => { +// if (!paths || paths.length === 0) return []; + +// const visited = new Set<string>(); +// const processes: Process[] = []; +// const pathMap = new Map<string, SimulationPath>(); +// paths.forEach((path) => pathMap.set(path.modeluuid, path)); + +// for (const path of paths) { +// if (!visited.has(path.modeluuid) && hasSpawnAction(path)) { +// const connectedPaths = getAllConnectedPaths(path, paths, visited); +// const adjustedPaths = adjustPathPointsOrder(connectedPaths); +// const process = createProcess(adjustedPaths); +// processes.push(process); +// } +// } + +// return processes; +// }, +// [createProcess, getAllConnectedPaths, hasSpawnAction] +// ); + +// return { +// processes, +// createProcessesFromPaths, +// setProcesses, +// }; +// } + +// const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo( +// ({ onProcessesCreated }) => { +// const { simulationPaths } = useSimulationPaths(); +// const { createProcessesFromPaths } = useProcessCreation(); +// const prevPathsRef = useRef<SimulationPath[]>([]); +// const prevProcessesRef = useRef<Process[]>([]); + +// const convertedPaths = useMemo((): SimulationPath[] => { +// if (!simulationPaths) return []; +// return simulationPaths.map((path) => +// convertToSimulationPath( +// path as ConveyorEventsSchema | VehicleEventsSchema +// ) +// ); +// }, [simulationPaths]); + +// const pathsDependency = useMemo(() => { +// if (!convertedPaths) return null; +// return convertedPaths.map((path) => ({ +// id: path.modeluuid, +// hasSpawn: path.points.some((p: PathPoint) => +// p.actions.some((a: PointAction) => a.type.toLowerCase() === "spawn") +// ), +// connections: path.points +// .flatMap((p: PathPoint) => +// p.connections.targets.map((t: { pathUUID: string }) => t.pathUUID) +// ) +// .join(","), +// })); +// }, [convertedPaths]); + +// useEffect(() => { +// if (!convertedPaths || convertedPaths.length === 0) { +// if (prevProcessesRef.current.length > 0) { +// onProcessesCreated([]); +// prevProcessesRef.current = []; +// } +// return; +// } + +// if (areArraysEqual(prevPathsRef.current, convertedPaths)) { +// return; +// } + +// prevPathsRef.current = convertedPaths; +// const newProcesses = createProcessesFromPaths(convertedPaths); + +// // console.log("--- Action Types in Paths ---"); +// // convertedPaths.forEach((path) => { +// // path.points.forEach((point) => { +// // point.actions.forEach((action) => { +// // console.log( +// // `Path ${path.modeluuid}, Point ${point.uuid}: ${action.type}` +// // ); +// // }); +// // }); +// // }); +// // console.log("New processes:", newProcesses); + +// if ( +// newProcesses.length !== prevProcessesRef.current.length || +// !newProcesses.every( +// (proc, i) => +// proc.paths.length === prevProcessesRef.current[i]?.paths.length && +// proc.paths.every( +// (path, j) => +// path.modeluuid === +// prevProcessesRef.current[i]?.paths[j]?.modeluuid +// ) +// ) +// ) { +// onProcessesCreated(newProcesses); +// // prevProcessesRef.current = newProcesses; +// } +// }, [ +// pathsDependency, +// onProcessesCreated, +// convertedPaths, +// createProcessesFromPaths, +// ]); + +// return null; +// } +// ); + +// export default ProcessCreator; + import React, { useEffect, useMemo, @@ -23,7 +422,6 @@ export interface PointAction { spawnInterval: string | number; isUsed: boolean; } - export interface PathPoint { uuid: string; position: [number, number, number]; @@ -32,14 +430,12 @@ export interface PathPoint { targets: Array<{ pathUUID: string }>; }; } - export interface SimulationPath { modeluuid: string; points: PathPoint[]; pathPosition: [number, number, number]; speed?: number; } - export interface Process { id: string; paths: SimulationPath[]; @@ -47,7 +443,6 @@ export interface Process { pointActions: PointAction[][]; speed: number; } - interface ProcessCreatorProps { onProcessesCreated: (processes: Process[]) => void; } @@ -58,51 +453,83 @@ function convertToSimulationPath( ): SimulationPath { const { modeluuid } = path; - // Simplified normalizeAction function that preserves exact original properties + // Helper function to normalize actions const normalizeAction = (action: any): PointAction => { return { ...action }; // Return exact copy with no modifications }; + // Extract points from the path + let points: PathPoint[]; if (path.type === "Conveyor") { - return { - modeluuid, - points: path.points.map((point) => ({ - uuid: point.uuid, - position: point.position, - actions: point.actions.map(normalizeAction), // Preserve exact actions + points = path.points.map((point) => ({ + uuid: point.uuid, + position: point.position, + actions: point.actions.map(normalizeAction), // Preserve exact actions + connections: { + targets: point.connections.targets.map((target) => ({ + pathUUID: target.pathUUID, + })), + }, + })); + } else { + points = [ + { + uuid: path.point.uuid, + position: path.point.position, + actions: Array.isArray(path.point.actions) + ? path.point.actions.map(normalizeAction) + : [normalizeAction(path.point.actions)], connections: { - targets: point.connections.targets.map((target) => ({ + targets: path.point.connections.targets.map((target) => ({ pathUUID: target.pathUUID, })), }, - })), - pathPosition: path.position, - speed: - typeof path.speed === "string" - ? parseFloat(path.speed) || 1 - : path.speed || 1, - }; - } else { - return { - modeluuid, - points: [ - { - uuid: path.point.uuid, - position: path.point.position, - actions: Array.isArray(path.point.actions) - ? path.point.actions.map(normalizeAction) - : [normalizeAction(path.point.actions)], - connections: { - targets: path.point.connections.targets.map((target) => ({ - pathUUID: target.pathUUID, - })), - }, - }, - ], - pathPosition: path.position, - speed: path.point.speed || 1, - }; + }, + ]; } + + // Check if point 1 or point 2 has a spawn action + const hasSpawnInFirstTwoPoints = + points.length >= 2 && + (points[0].actions.some( + (action) => action.type.toLowerCase() === "spawn" + ) || + points[1].actions.some( + (action) => action.type.toLowerCase() === "spawn" + )); + + // Swap points 1 and 3 only if: + // 1. There are at least three points, + // 2. The third point contains a spawn action, and + // 3. Neither point 1 nor point 2 has a spawn action + if ( + !hasSpawnInFirstTwoPoints && + points.length >= 3 && + points[2].actions.some((action) => action.type.toLowerCase() === "spawn") + ) { + const temp = points[0]; + points[0] = points[2]; + points[2] = temp; + } + + // Determine the speed based on the type of path + let speed: number; + if (path.type === "Conveyor") { + speed = + typeof path.speed === "string" + ? parseFloat(path.speed) || 1 + : path.speed || 1; + } else { + // For VehicleEventsSchema, use a default speed of 1 + speed = 1; + } + + return { + modeluuid, + points, + pathPosition: path.position, + speed, + }; } // Custom shallow comparison for arrays @@ -129,7 +556,6 @@ function shouldReverseNextPath( nextPath: SimulationPath ): boolean { if (nextPath.points.length !== 3) return false; - const currentLastPoint = currentPath.points[currentPath.points.length - 1]; const nextFirstPoint = nextPath.points[0]; const nextLastPoint = nextPath.points[nextPath.points.length - 1]; @@ -159,27 +585,22 @@ function shouldReverseNextPath( // Updated path adjustment function function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] { if (paths.length < 2) return paths; - const adjustedPaths = [...paths]; - for (let i = 0; i < adjustedPaths.length - 1; i++) { const currentPath = adjustedPaths[i]; const nextPath = adjustedPaths[i + 1]; - if (shouldReverseNextPath(currentPath, nextPath)) { const reversedPoints = [ nextPath.points[2], nextPath.points[1], nextPath.points[0], ]; - adjustedPaths[i + 1] = { ...nextPath, points: reversedPoints, }; } } - return adjustedPaths; } @@ -187,7 +608,6 @@ function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] { export function useProcessCreation() { const { scene } = useThree(); const [processes, setProcesses] = useState<Process[]>([]); - const hasSpawnAction = useCallback((path: SimulationPath): boolean => { return path.points.some((point) => point.actions.some((action) => action.type.toLowerCase() === "spawn") @@ -199,11 +619,9 @@ export function useProcessCreation() { if (!paths || paths.length === 0) { return createEmptyProcess(); } - const animationPath: THREE.Vector3[] = []; const pointActions: PointAction[][] = []; const processSpeed = paths[0]?.speed || 1; - for (const path of paths) { for (const point of path.points) { const obj = scene.getObjectByProperty("uuid", point.uuid); @@ -211,13 +629,11 @@ export function useProcessCreation() { console.warn(`Object with UUID ${point.uuid} not found in scene`); continue; } - const position = obj.getWorldPosition(new THREE.Vector3()); animationPath.push(position.clone()); pointActions.push(point.actions); } } - return { id: `process-${Math.random().toString(36).substring(2, 11)}`, paths, @@ -238,10 +654,8 @@ export function useProcessCreation() { const connectedPaths: SimulationPath[] = []; const queue: SimulationPath[] = [initialPath]; visited.add(initialPath.modeluuid); - const pathMap = new Map<string, SimulationPath>(); allPaths.forEach((path) => pathMap.set(path.modeluuid, path)); - while (queue.length > 0) { const currentPath = queue.shift()!; connectedPaths.push(currentPath); @@ -274,7 +688,6 @@ export function useProcessCreation() { } } } - return connectedPaths; }, [] @@ -283,12 +696,10 @@ export function useProcessCreation() { const createProcessesFromPaths = useCallback( (paths: SimulationPath[]): Process[] => { if (!paths || paths.length === 0) return []; - const visited = new Set<string>(); const processes: Process[] = []; const pathMap = new Map<string, SimulationPath>(); paths.forEach((path) => pathMap.set(path.modeluuid, path)); - for (const path of paths) { if (!visited.has(path.modeluuid) && hasSpawnAction(path)) { const connectedPaths = getAllConnectedPaths(path, paths, visited); @@ -297,7 +708,6 @@ export function useProcessCreation() { processes.push(process); } } - return processes; }, [createProcess, getAllConnectedPaths, hasSpawnAction] @@ -338,6 +748,9 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo( p.connections.targets.map((t: { pathUUID: string }) => t.pathUUID) ) .join(","), + actions: JSON.stringify( + path.points.flatMap((p: PathPoint) => p.actions) + ), // Serialize all actions })); }, [convertedPaths]); @@ -349,26 +762,11 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo( } return; } - if (areArraysEqual(prevPathsRef.current, convertedPaths)) { return; } - prevPathsRef.current = convertedPaths; const newProcesses = createProcessesFromPaths(convertedPaths); - - // console.log("--- Action Types in Paths ---"); - // convertedPaths.forEach((path) => { - // path.points.forEach((point) => { - // point.actions.forEach((action) => { - // console.log( - // `Path ${path.modeluuid}, Point ${point.uuid}: ${action.type}` - // ); - // }); - // }); - // }); - // console.log("New processes:", newProcesses); - if ( newProcesses.length !== prevProcessesRef.current.length || !newProcesses.every( @@ -382,7 +780,7 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo( ) ) { onProcessesCreated(newProcesses); - // prevProcessesRef.current = newProcesses; + prevProcessesRef.current = newProcesses; } }, [ pathsDependency,