Enhance TriggerConnector and useProductStore: add removeTrigger return value and improve event handling in TriggerConnector

This commit is contained in:
Jerald-Golden-B 2025-05-02 11:35:03 +05:30
parent 571da0a78a
commit d3f5c5e506
2 changed files with 104 additions and 8 deletions

View File

@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useThree } from "@react-three/fiber"; import { useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three"; import * as THREE from "three";
import { useSubModuleStore } from "../../../../store/useModuleStore"; import { useSubModuleStore } from "../../../../store/useModuleStore";
import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore"; import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
@ -9,6 +9,7 @@ import { useSelectedProduct } from "../../../../store/simulation/useSimulationSt
import { handleAddEventToProduct } from "../../events/points/functions/handleAddEventToProduct"; import { handleAddEventToProduct } from "../../events/points/functions/handleAddEventToProduct";
import { QuadraticBezierLine } from "@react-three/drei"; import { QuadraticBezierLine } from "@react-three/drei";
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi"; import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
import { useDeleteTool } from "../../../../store/store";
interface ConnectionLine { interface ConnectionLine {
id: string; id: string;
@ -18,13 +19,16 @@ interface ConnectionLine {
} }
function TriggerConnector() { function TriggerConnector() {
const { gl, raycaster, scene } = useThree(); const { gl, raycaster, scene, pointer, camera } = useThree();
const { subModule } = useSubModuleStore(); const { subModule } = useSubModuleStore();
const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, addEvent, getEventByModelUuid, getProductById } = useProductStore(); const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, removeTrigger, addEvent, getEventByModelUuid, getProductById } = useProductStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const { selectedProduct } = useSelectedProduct(); const { selectedProduct } = useSelectedProduct();
const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null); const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
const groupRefs = useRef<Record<string, any>>({}); const groupRefs = useRef<Record<string, any>>({});
const [helperlineColor, setHelperLineColor] = useState<string>("red");
const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3; end: THREE.Vector3; mid: THREE.Vector3; } | null>(null);
const { deleteTool } = useDeleteTool();
const [firstSelectedPoint, setFirstSelectedPoint] = useState<{ const [firstSelectedPoint, setFirstSelectedPoint] = useState<{
productId: string; productId: string;
@ -303,6 +307,61 @@ function TriggerConnector() {
}, [gl, subModule, selectedProduct, firstSelectedPoint]); }, [gl, subModule, selectedProduct, firstSelectedPoint]);
useFrame(() => {
if (firstSelectedPoint) {
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(scene.children, true).filter(
(intersect) =>
!intersect.object.name.includes("Roof") &&
!intersect.object.name.includes("agv-collider") &&
!intersect.object.name.includes("MeasurementReference") &&
!intersect.object.userData.isPathObject &&
!(intersect.object.type === "GridHelper")
);
let point: THREE.Vector3 | null = null;
if (intersects.length > 0) {
point = intersects[0].point;
if (point.y < 0.05) {
point = new THREE.Vector3(point.x, 0.05, point.z);
}
}
const sphereIntersects = raycaster.intersectObjects(scene.children, true).filter((intersect) => intersect.object.name === ('Event-Sphere'));
const startPoint = getWorldPositionFromScene(firstSelectedPoint.pointUuid);
if (point && startPoint) {
const distance = startPoint.distanceTo(point);
const heightFactor = Math.max(0.5, distance * 0.2);
const midPoint = new THREE.Vector3(
(startPoint.x + point.x) / 2,
Math.max(startPoint.y, point.y) + heightFactor,
(startPoint.z + point.z) / 2
);
setCurrentLine({
start: startPoint,
mid: midPoint,
end: point,
});
if (sphereIntersects.length > 0) {
setHelperLineColor("#6cf542");
} else {
setHelperLineColor("red");
}
} else {
setCurrentLine(null);
}
} else {
setCurrentLine(null);
}
})
const getWorldPositionFromScene = (pointUuid: string): THREE.Vector3 | null => { const getWorldPositionFromScene = (pointUuid: string): THREE.Vector3 | null => {
const pointObj = scene.getObjectByProperty("uuid", pointUuid); const pointObj = scene.getObjectByProperty("uuid", pointUuid);
if (!pointObj) return null; if (!pointObj) return null;
@ -312,8 +371,23 @@ function TriggerConnector() {
return worldPosition; return worldPosition;
}; };
const removeConnection = (connection: ConnectionLine) => {
if (connection.trigger.triggerUuid) {
const event = removeTrigger(connection.trigger.triggerUuid);
if (event) {
console.log('event: ', event);
updateBackend(
selectedProduct.productName,
selectedProduct.productId,
organization,
event
);
}
}
};
return ( return (
<group> <group name="simulationConnectionGroup" >
{connections.map((connection) => { {connections.map((connection) => {
const startPoint = getWorldPositionFromScene(connection.startPointUuid); const startPoint = getWorldPositionFromScene(connection.startPointUuid);
const endPoint = getWorldPositionFromScene(connection.endPointUuid); const endPoint = getWorldPositionFromScene(connection.endPointUuid);
@ -335,20 +409,37 @@ function TriggerConnector() {
start={startPoint.toArray()} start={startPoint.toArray()}
end={endPoint.toArray()} end={endPoint.toArray()}
mid={midPoint.toArray()} mid={midPoint.toArray()}
color={hoveredLineKey === connection.id ? "red" : "#42a5f5"} color={deleteTool && hoveredLineKey === connection.id ? "red" : "#42a5f5"}
lineWidth={4} lineWidth={4}
dashed={hoveredLineKey !== connection.id} dashed={deleteTool && hoveredLineKey === connection.id ? false : true}
dashSize={0.75} dashSize={0.75}
dashScale={20} dashScale={20}
onPointerOver={() => setHoveredLineKey(connection.id)} onPointerOver={() => setHoveredLineKey(connection.id)}
onPointerOut={() => setHoveredLineKey(null)} onPointerOut={() => setHoveredLineKey(null)}
onClick={() => { onClick={() => {
console.log("Connection clicked:", connection); if (deleteTool) {
setHoveredLineKey(null);
setCurrentLine(null);
removeConnection(connection);
}
}} }}
userData={connection.trigger} userData={connection.trigger}
/> />
); );
})} })}
{currentLine && (
<QuadraticBezierLine
start={currentLine.start.toArray()}
end={currentLine.end.toArray()}
mid={currentLine.mid.toArray()}
color={helperlineColor}
lineWidth={4}
dashed
dashSize={1}
dashScale={20}
/>
)}
</group> </group>
); );
} }

View File

@ -44,7 +44,7 @@ type ProductsStore = {
actionUuid: string, actionUuid: string,
trigger: TriggerSchema trigger: TriggerSchema
) => EventsSchema | undefined; ) => EventsSchema | undefined;
removeTrigger: (triggerUuid: string) => void; removeTrigger: (triggerUuid: string) => EventsSchema | undefined;
updateTrigger: ( updateTrigger: (
triggerUuid: string, triggerUuid: string,
updates: Partial<TriggerSchema> updates: Partial<TriggerSchema>
@ -318,6 +318,7 @@ export const useProductStore = create<ProductsStore>()(
}, },
removeTrigger: (triggerUuid) => { removeTrigger: (triggerUuid) => {
let updatedEvent: EventsSchema | undefined;
set((state) => { set((state) => {
for (const product of state.products) { for (const product of state.products) {
for (const event of product.eventDatas) { for (const event of product.eventDatas) {
@ -325,16 +326,19 @@ export const useProductStore = create<ProductsStore>()(
for (const point of (event as ConveyorEventSchema).points) { for (const point of (event as ConveyorEventSchema).points) {
if (point.action && 'triggers' in point.action) { if (point.action && 'triggers' in point.action) {
point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid); point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
updatedEvent = JSON.parse(JSON.stringify(event));
} }
} }
} else if ('point' in event) { } else if ('point' in event) {
const point = (event as any).point; const point = (event as any).point;
if ('action' in point && 'triggers' in point.action) { if ('action' in point && 'triggers' in point.action) {
point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid); point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
updatedEvent = JSON.parse(JSON.stringify(event));
} else if ('actions' in point) { } else if ('actions' in point) {
for (const action of point.actions) { for (const action of point.actions) {
if ('triggers' in action) { if ('triggers' in action) {
action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid); action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
updatedEvent = JSON.parse(JSON.stringify(event));
} }
} }
} }
@ -342,6 +346,7 @@ export const useProductStore = create<ProductsStore>()(
} }
} }
}); });
return updatedEvent;
}, },
updateTrigger: (triggerUuid, updates) => { updateTrigger: (triggerUuid, updates) => {