From bffb1e6037f6fd490696e89fd1e7dcfc975d68f2 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Tue, 8 Jul 2025 14:19:09 +0530 Subject: [PATCH] feat: Refactor point management in PointsCreator and update product store for better event handling --- .../builder/asset/models/model/model.tsx | 94 ++++++++++++- .../events/points/creator/pointsCreator.tsx | 124 ++++++++++-------- app/src/store/simulation/useProductStore.ts | 54 +++++++- 3 files changed, 213 insertions(+), 59 deletions(-) diff --git a/app/src/modules/builder/asset/models/model/model.tsx b/app/src/modules/builder/asset/models/model/model.tsx index cb19890..fa9b2fd 100644 --- a/app/src/modules/builder/asset/models/model/model.tsx +++ b/app/src/modules/builder/asset/models/model/model.tsx @@ -27,10 +27,10 @@ function Model({ asset }: { readonly asset: Asset }) { const { activeModule } = useModuleStore(); const { speed } = useAnimationPlaySpeed(); const { assetStore, eventStore, productStore } = useSceneContext(); - const { removeAsset, setAnimations, resetAnimation, setAnimationComplete, setCurrentAnimation: setAnmationAnimation } = assetStore(); + const { removeAsset, setAnimations, resetAnimation, setAnimationComplete } = assetStore(); const { setTop } = useTopData(); const { setLeft } = useLeftData(); - const { getIsEventInProduct } = productStore(); + const { getIsEventInProduct, addPoint } = productStore(); const { getEventByModelUuid } = eventStore(); const { selectedProductStore } = useProductContext(); const { selectedProduct } = selectedProductStore(); @@ -46,6 +46,10 @@ function Model({ asset }: { readonly asset: Asset }) { const [boundingBox, setBoundingBox] = useState(null); const groupRef = useRef(null); const { toolMode } = useToolMode(); + const leftDrag = useRef(false); + const isLeftMouseDown = useRef(false); + const rightDrag = useRef(false); + const isRightMouseDown = useRef(false); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); const { projectId } = useParams(); @@ -217,7 +221,8 @@ function Model({ asset }: { readonly asset: Asset }) { } }; - const handleClick = (asset: Asset) => { + const handleClick = (evt: ThreeEvent, asset: Asset) => { + if (leftDrag.current || toggleView) return; if (activeTool === 'delete' && deletableFloorItem && deletableFloorItem.uuid === asset.modelUuid) { //REST @@ -257,6 +262,40 @@ function Model({ asset }: { readonly asset: Asset }) { echo.success("Model Removed!"); } + } else if (activeModule === 'simulation' && subModule === "simulations" && activeTool === 'pen') { + if (asset.eventData && asset.eventData.type === 'Conveyor') { + const intersectedPoint = evt.point; + const localPosition = groupRef.current?.worldToLocal(intersectedPoint.clone()); + if (localPosition) { + const conveyorPoint: ConveyorPointSchema = { + uuid: THREE.MathUtils.generateUUID(), + position: [localPosition?.x, localPosition?.y, localPosition?.z], + rotation: [0, 0, 0], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: `Action 1`, + actionType: 'default', + material: 'Default Material', + delay: 0, + spawnInterval: 5, + spawnCount: 1, + triggers: [] + } + } + + const event = addPoint(selectedProduct.productUuid, asset.modelUuid, conveyorPoint); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productUuid, + projectId || '', + event + ); + } + } + } + } } @@ -277,6 +316,7 @@ function Model({ asset }: { readonly asset: Asset }) { }, [activeTool, deletableFloorItem]); const handleContextMenu = (asset: Asset, evt: ThreeEvent) => { + if (rightDrag.current || toggleView) return; if (activeTool === "cursor" && subModule === 'simulations') { if (asset.modelUuid) { const canvasElement = gl.domElement; @@ -358,6 +398,50 @@ function Model({ asset }: { readonly asset: Asset }) { }; }, [asset.animationState?.current, asset.animationState?.isPlaying]); + useEffect(() => { + const canvasElement = gl.domElement; + + const onPointerDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown.current = true; + leftDrag.current = false; + } + if (evt.button === 2) { + isRightMouseDown.current = true; + rightDrag.current = false; + } + }; + + const onPointerMove = () => { + if (isLeftMouseDown.current) { + leftDrag.current = true; + } + if (isRightMouseDown.current) { + rightDrag.current = true; + } + }; + + const onPointerUp = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown.current = false; + } + if (evt.button === 2) { + isRightMouseDown.current = false; + } + }; + + canvasElement.addEventListener('pointerdown', onPointerDown); + canvasElement.addEventListener('pointermove', onPointerMove); + canvasElement.addEventListener('pointerup', onPointerUp); + + return () => { + canvasElement.removeEventListener('pointerdown', onPointerDown); + canvasElement.removeEventListener('pointermove', onPointerMove); + canvasElement.removeEventListener('pointerup', onPointerUp); + } + + }, [gl]) + return ( { e.stopPropagation(); if (!toggleView) { - handleClick(asset); + handleClick(e, asset); } }} onPointerOver={(e) => { @@ -404,7 +488,7 @@ function Model({ asset }: { readonly asset: Asset }) { ) )} - + ); } diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx index 25e0b3d..bfdf49d 100644 --- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx +++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx @@ -18,8 +18,8 @@ function PointsCreator() { const { subModule } = useSubModuleStore(); const { selectedProductStore } = useProductContext(); const { eventStore, productStore } = useSceneContext(); - const { events, updatePoint, getPointByUuid, getEventByModelUuid } = eventStore(); - const { getEventByModelUuid: getEventByModelUuidFromProduct, updatePoint: updatePointFromProduct, getEventByModelUuid: getEventByModelUuidFromProduct2, getPointByUuid: getPointByUuidFromProduct } = productStore(); + const { events, getEventByModelUuid } = eventStore(); + const { getEventByModelUuid: getEventByModelUuidFromProduct, updatePoint: updatePointFromProduct, getEventByModelUuid: getEventByModelUuidFromProduct2, getPointByUuid: getPointByUuidFromProduct, getTriggersByTriggeredPointUuid, removeTrigger, removePoint } = productStore(); const { selectedProduct } = selectedProductStore(); const { activeModule } = useModuleStore(); const transformRef = useRef(null); @@ -75,65 +75,87 @@ function PointsCreator() { if (keyCombination === "R") { setTransformMode((prev) => (prev === "rotate" ? null : "rotate")); } + if (keyCombination === 'DELETE') { + deletePointfromConveyor(selectedEventSphere); + } }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, [selectedEventSphere]); - const updatePointToState = (selectedEventSphere: THREE.Mesh) => { - let point: PointsScheme = JSON.parse( - JSON.stringify( - getPointByUuid( - selectedEventSphere.userData.modelUuid, - selectedEventSphere.userData.pointUuid - ) - ) - ); - if (point) { - point.position = [ - selectedEventSphere.position.x, - selectedEventSphere.position.y, - selectedEventSphere.position.z, - ]; - point.rotation = [ - selectedEventSphere.rotation.x, - selectedEventSphere.rotation.y, - selectedEventSphere.rotation.z, - ]; + const deletePointfromConveyor = (selectedEventSphere: THREE.Mesh) => { + const eventModel = getEventByModelUuidFromProduct(selectedProduct.productUuid, selectedEventSphere.userData.modelUuid); + if (!eventModel || eventModel.type !== 'transfer' || eventModel.points.length < 2) return; - const event = getEventByModelUuidFromProduct(selectedProduct.productUuid, selectedEventSphere.userData.modelUuid); + const triggers = getTriggersByTriggeredPointUuid(selectedProduct.productUuid, selectedEventSphere.userData.pointUuid); - if (event && selectedProduct.productUuid !== '') { + const updatedEvents: EventsSchema[] = []; + if (triggers.length > 0) { + triggers.map((trigger) => { + const event = removeTrigger(selectedProduct.productUuid, trigger.triggerUuid); + if (event) { + updatedEvents.push(event); + } + }) + } - const updatedPoint = JSON.parse( - JSON.stringify( - getPointByUuidFromProduct(selectedProduct.productUuid, selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid) - ) + const event = removePoint(selectedProduct.productUuid, selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid) + + if (event) { + updatedEvents.push(event); + } + + if (updatedEvents.length > 0) { + updatedEvents.map((updatedEvent) => { + updateBackend( + selectedProduct.productName, + selectedProduct.productUuid, + projectId || '', + updatedEvent ); - if (updatedPoint) { - updatedPoint.position = point.position; - updatedPoint.rotation = point.rotation; + }) + } + } - const updatedEvent = updatePointFromProduct( + const updatePointToState = (selectedEventSphere: THREE.Mesh) => { + const position = [ + selectedEventSphere.position.x, + selectedEventSphere.position.y, + selectedEventSphere.position.z, + ]; + const rotation = [ + selectedEventSphere.rotation.x, + selectedEventSphere.rotation.y, + selectedEventSphere.rotation.z, + ]; + + const event = getEventByModelUuidFromProduct(selectedProduct.productUuid, selectedEventSphere.userData.modelUuid); + + if (event && selectedProduct.productUuid !== '') { + + const updatedPoint = JSON.parse( + JSON.stringify( + getPointByUuidFromProduct(selectedProduct.productUuid, selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid) + ) + ); + if (updatedPoint) { + updatedPoint.position = position; + updatedPoint.rotation = rotation; + + const updatedEvent = updatePointFromProduct( + selectedProduct.productUuid, + selectedEventSphere.userData.modelUuid, + selectedEventSphere.userData.pointUuid, + updatedPoint + ) + if (updatedEvent) { + updateBackend( + selectedProduct.productName, selectedProduct.productUuid, - selectedEventSphere.userData.modelUuid, - selectedEventSphere.userData.pointUuid, - updatedPoint - ) - if (updatedEvent) { - updatePoint( - selectedEventSphere.userData.modelUuid, - selectedEventSphere.userData.pointUuid, - point - ) - updateBackend( - selectedProduct.productName, - selectedProduct.productUuid, - projectId || '', - updatedEvent - ); - } + projectId || '', + updatedEvent + ); } } } @@ -153,9 +175,7 @@ function PointsCreator() { const onMouseUp = () => { if (selectedEventSphere && !drag) { raycaster.setFromCamera(pointer, camera); - const intersects = raycaster - .intersectObjects(scene.children, true) - .filter((intersect) => intersect.object.name === "Event-Sphere"); + const intersects = raycaster.intersectObjects(scene.children, true).filter((intersect) => intersect.object.name === "Event-Sphere"); if (intersects.length === 0) { clearSelectedEventSphere(); setTransformMode(null); diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index 1a37964..aa75d68 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -18,8 +18,8 @@ type ProductsStore = { updateEvent: (productUuid: string, modelUuid: string, updates: Partial) => EventsSchema | undefined; // Point-level actions - addPoint: (productUuid: string, modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema) => void; - removePoint: (productUuid: string, modelUuid: string, pointUuid: string) => void; + addPoint: (productUuid: string, modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema) => EventsSchema | undefined; + removePoint: (productUuid: string, modelUuid: string, pointUuid: string) => EventsSchema | undefined; updatePoint: ( productUuid: string, modelUuid: string, @@ -72,6 +72,7 @@ type ProductsStore = { getModelUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined; getPointUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined; getTriggerByUuid: (productUuid: string, triggerUuid: string) => TriggerSchema | undefined; + getTriggersByTriggeredPointUuid: (productUuid: string, triggeredPointUuid: string) => TriggerSchema[]; getIsEventInProduct: (productUuid: string, modelUuid: string) => boolean; }; @@ -251,6 +252,7 @@ export const createProductStore = () => { // Point-level actions addPoint: (productUuid, modelUuid, point) => { + let updatedEvent: EventsSchema | undefined = undefined; set((state) => { const product = state.products.find(p => p.productUuid === productUuid); if (product) { @@ -259,29 +261,35 @@ export const createProductStore = () => { const existingPoint = (event as ConveyorEventSchema).points.find(p => p.uuid === point.uuid); if (!existingPoint) { (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema); + updatedEvent = JSON.parse(JSON.stringify(event)); } } else if (event && 'point' in event) { const existingPoint = (event as any).point?.uuid === point.uuid; if (!existingPoint) { (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any; + updatedEvent = JSON.parse(JSON.stringify(event)); } } } }); + return updatedEvent; }, removePoint: (productUuid, modelUuid, pointUuid) => { + let updatedEvent: EventsSchema | undefined = undefined; set((state) => { const product = state.products.find(p => p.productUuid === productUuid); if (product) { const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); if (event && 'points' in event) { (event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid); + updatedEvent = JSON.parse(JSON.stringify(event)); } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) { // For events with single point, we can't remove it, only reset to empty } } }); + return updatedEvent; }, updatePoint: (productUuid, modelUuid, pointUuid, updates) => { @@ -881,6 +889,48 @@ export const createProductStore = () => { return undefined; }, + getTriggersByTriggeredPointUuid: (productUuid, triggeredPointUuid) => { + const product = get().products.find(p => p.productUuid === productUuid); + if (!product) return []; + + const triggers: TriggerSchema[] = []; + + for (const event of product.eventDatas) { + if ('points' in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action?.triggers) { + for (const trigger of point.action.triggers) { + if (trigger.triggeredAsset?.triggeredPoint?.pointUuid === triggeredPointUuid) { + triggers.push(trigger); + } + } + } + } + } else if ('point' in event) { + const point = (event as any).point; + if ('action' in point && point.action?.triggers) { + for (const trigger of point.action.triggers) { + if (trigger.triggeredAsset?.triggeredPoint?.pointUuid === triggeredPointUuid) { + triggers.push(trigger); + } + } + } else if ('actions' in point) { + for (const action of point.actions) { + if (action.triggers) { + for (const trigger of action.triggers) { + if (trigger.triggeredAsset?.triggeredPoint?.pointUuid === triggeredPointUuid) { + triggers.push(trigger); + } + } + } + } + } + } + } + + return triggers; + }, + getIsEventInProduct: (productUuid, modelUuid) => { const product = get().getProductById(productUuid); if (!product) return false;