feat: Enhance arrow and trigger connection handling with backend updates and improved event management

This commit is contained in:
2025-07-08 10:12:16 +05:30
parent 5af0ba303e
commit 7f51ce1d58
2 changed files with 81 additions and 54 deletions

View File

@@ -2,6 +2,11 @@ import * as THREE from "three";
import { useMemo, useRef, useState } from "react";
import { useThree } from "@react-three/fiber";
import { useToolMode } from "../../../../store/builder/store";
import { useSceneContext } from "../../../scene/sceneContext";
import { useVersionContext } from "../../../builder/version/versionContext";
import { useProductContext } from "../../products/productContext";
import { useParams } from "react-router-dom";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
interface ConnectionLine {
id: string;
@@ -15,6 +20,28 @@ export function Arrows({ connections }: { readonly connections: ConnectionLine[]
const groupRef = useRef<THREE.Group>(null);
const { scene } = useThree();
const { toolMode } = useToolMode();
const { eventStore, productStore } = useSceneContext();
const { removeTrigger } = productStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { projectId } = useParams();
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
upsertProductOrEventApi({
productName: productName,
productUuid: productUuid,
projectId: projectId,
eventDatas: eventData,
versionId: selectedVersion?.versionId || '',
})
}
const getWorldPositionFromScene = (uuid: string): THREE.Vector3 | null => {
const obj = scene.getObjectByProperty("uuid", uuid);
@@ -24,14 +51,20 @@ export function Arrows({ connections }: { readonly connections: ConnectionLine[]
return pos;
};
const processedArrows = new Set<string>();
const createArrow = (
key: string,
fullCurve: THREE.QuadraticBezierCurve3,
centerT: number,
segmentSize: number,
scale: number,
reverse = false
reverse: boolean,
trigger: TriggerSchema
) => {
if (processedArrows.has(trigger.triggerUuid)) return [];
processedArrows.add(trigger.triggerUuid);
const t1 = Math.max(0, centerT - segmentSize / 2);
const t2 = Math.min(1, centerT + segmentSize / 2);
const subCurve = getSubCurve(fullCurve, t1, t2, reverse);
@@ -53,26 +86,41 @@ export function Arrows({ connections }: { readonly connections: ConnectionLine[]
tangent
);
const removeConnection = (trigger: TriggerSchema) => {
if (trigger.triggerUuid) {
const event = removeTrigger(selectedProduct.productUuid, trigger.triggerUuid);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
}
}
};
return (
<group key={key}>
<group
key={key}
onPointerOver={() => setHoveredLineKey(trigger.triggerUuid)}
onPointerOut={() => setHoveredLineKey(null)}
onClick={() => { removeConnection(trigger) }}
>
<mesh
geometry={shaftGeometry}
onPointerOver={() => setHoveredLineKey(key)}
onPointerOut={() => setHoveredLineKey(null)}
>
<meshStandardMaterial
color={toolMode === '2D-Delete' && hoveredLineKey === key ? "red" : "#42a5f5"}
color={toolMode === '3D-Delete' && hoveredLineKey === trigger.triggerUuid ? "red" : "#42a5f5"}
/>
</mesh>
<mesh
position={end}
quaternion={rotation}
geometry={headGeometry}
onPointerOver={() => setHoveredLineKey(key)}
onPointerOut={() => setHoveredLineKey(null)}
>
<meshStandardMaterial
color={toolMode === '2D-Delete' && hoveredLineKey === key ? "red" : "#42a5f5"}
color={toolMode === '3D-Delete' && hoveredLineKey === trigger.triggerUuid ? "red" : "#42a5f5"}
/>
</mesh>
</group>
@@ -97,50 +145,29 @@ export function Arrows({ connections }: { readonly connections: ConnectionLine[]
};
const arrowGroups = connections.flatMap((connection) => {
const start = getWorldPositionFromScene(connection.startPointUuid);
const end = getWorldPositionFromScene(connection.endPointUuid);
const { startPointUuid, endPointUuid } = connection;
const start = getWorldPositionFromScene(startPointUuid);
const end = getWorldPositionFromScene(endPointUuid);
if (!start || !end) return [];
const isBidirectional = connections.some(
(other) =>
other.startPointUuid === connection.endPointUuid &&
other.endPointUuid === connection.startPointUuid
);
const isBidirectional = connections.some((other) => other.startPointUuid === endPointUuid && other.endPointUuid === startPointUuid);
if (isBidirectional && connection.startPointUuid < connection.endPointUuid) {
const distance = start.distanceTo(end);
const heightFactor = Math.max(0.5, distance * 0.2);
const control = new THREE.Vector3(
(start.x + end.x) / 2,
Math.max(start.y, end.y) + heightFactor,
(start.z + end.z) / 2
);
const curve = new THREE.QuadraticBezierCurve3(start, control, end);
const scale = THREE.MathUtils.clamp(distance * 0.75, 0.5, 3);
const distance = start.distanceTo(end);
const heightFactor = Math.max(0.5, distance * 0.2);
const control = new THREE.Vector3((start.x + end.x) / 2, Math.max(start.y, end.y) + heightFactor, (start.z + end.z) / 2);
const curve = new THREE.QuadraticBezierCurve3(start, control, end);
const scale = THREE.MathUtils.clamp(distance * 0.75, 0.5, 5);
if (isBidirectional) {
return [
createArrow(connection.id + "-fwd", curve, 0.33, 0.25, scale, true),
createArrow(connection.id + "-bwd", curve, 0.66, 0.25, scale, false),
createArrow(connection.id + "-fwd", curve, 0.33, 0.25, scale, true, connection.trigger),
createArrow(connection.id + "-bwd", curve, 0.66, 0.25, scale, false, connection.trigger),
];
} else {
return [
createArrow(connection.id, curve, 0.5, 0.3, scale, false, connection.trigger)
];
}
if (!isBidirectional) {
const distance = start.distanceTo(end);
const heightFactor = Math.max(0.5, distance * 0.2);
const control = new THREE.Vector3(
(start.x + end.x) / 2,
Math.max(start.y, end.y) + heightFactor,
(start.z + end.z) / 2
);
const curve = new THREE.QuadraticBezierCurve3(start, control, end);
const scale = THREE.MathUtils.clamp(distance * 0.75, 0.5, 5);
return [
createArrow(connection.id, curve, 0.5, 0.3, scale)
];
}
return [];
});
return <group ref={groupRef} name="connectionArrows">{arrowGroups}</group>;

View File

@@ -503,15 +503,15 @@ function TriggerConnector() {
dashed={toolMode === '3D-Delete' && hoveredLineKey === connection.id ? false : true}
dashSize={0.75}
dashScale={20}
onPointerOver={() => setHoveredLineKey(connection.id)}
onPointerOut={() => setHoveredLineKey(null)}
onClick={() => {
if (toolMode === '3D-Delete') {
setHoveredLineKey(null);
setCurrentLine(null);
removeConnection(connection);
}
}}
// onPointerOver={() => setHoveredLineKey(connection.id)}
// onPointerOut={() => setHoveredLineKey(null)}
// onClick={() => {
// if (toolMode === '3D-Delete') {
// setHoveredLineKey(null);
// setCurrentLine(null);
// removeConnection(connection);
// }
// }}
userData={connection.trigger}
/>
);