feat: refactor TriggerConnector to include Arrows component for visualizing connections and update import paths
refactor: remove unused triggerConnector file and update trigger.tsx import path
This commit is contained in:
parent
92ae705399
commit
292ea0dbc2
|
@ -0,0 +1,207 @@
|
|||
import * as THREE from "three";
|
||||
import { useMemo, useRef } from "react";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
|
||||
interface ConnectionLine {
|
||||
id: string;
|
||||
startPointUuid: string;
|
||||
endPointUuid: string;
|
||||
trigger: TriggerSchema;
|
||||
}
|
||||
|
||||
export function Arrows({ connections }: { connections: ConnectionLine[] }) {
|
||||
const groupRef = useRef<THREE.Group>(null);
|
||||
const { scene } = useThree();
|
||||
|
||||
const getWorldPositionFromScene = (uuid: string): THREE.Vector3 | null => {
|
||||
const obj = scene.getObjectByProperty("uuid", uuid);
|
||||
if (!obj) return null;
|
||||
const pos = new THREE.Vector3();
|
||||
obj.getWorldPosition(pos);
|
||||
return pos;
|
||||
};
|
||||
|
||||
const createArrow = (
|
||||
key: string,
|
||||
fullCurve: THREE.QuadraticBezierCurve3,
|
||||
centerT: number,
|
||||
segmentSize: number,
|
||||
scale: number,
|
||||
reverse = false
|
||||
) => {
|
||||
const t1 = Math.max(0, centerT - segmentSize / 2);
|
||||
const t2 = Math.min(1, centerT + segmentSize / 2);
|
||||
const subCurve = getSubCurve(fullCurve, t1, t2, reverse);
|
||||
|
||||
const shaftGeometry = new THREE.TubeGeometry(subCurve, 8, 0.01 * scale, 8, false);
|
||||
|
||||
const end = subCurve.getPoint(1);
|
||||
const tangent = subCurve.getTangent(1).normalize();
|
||||
|
||||
const arrowHeadLength = 0.15 * scale;
|
||||
const arrowRadius = 0.01 * scale;
|
||||
const arrowHeadRadius = arrowRadius * 2.5;
|
||||
|
||||
const headGeometry = new THREE.ConeGeometry(arrowHeadRadius, arrowHeadLength, 8);
|
||||
headGeometry.translate(0, arrowHeadLength / 2, 0);
|
||||
|
||||
const rotation = new THREE.Quaternion().setFromUnitVectors(
|
||||
new THREE.Vector3(0, 1, 0),
|
||||
tangent
|
||||
);
|
||||
|
||||
return (
|
||||
<group key={key}>
|
||||
<mesh geometry={shaftGeometry}>
|
||||
<meshStandardMaterial color="#42a5f5" />
|
||||
</mesh>
|
||||
<mesh position={end} quaternion={rotation} geometry={headGeometry}>
|
||||
<meshStandardMaterial color="#42a5f5" />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
};
|
||||
|
||||
const getSubCurve = (
|
||||
curve: THREE.Curve<THREE.Vector3>,
|
||||
t1: number,
|
||||
t2: number,
|
||||
reverse = false
|
||||
) => {
|
||||
const divisions = 10;
|
||||
const subPoints = Array.from({ length: divisions + 1 }, (_, i) => {
|
||||
const t = THREE.MathUtils.lerp(t1, t2, i / divisions);
|
||||
return curve.getPoint(t);
|
||||
});
|
||||
|
||||
if (reverse) subPoints.reverse();
|
||||
|
||||
return new THREE.CatmullRomCurve3(subPoints);
|
||||
};
|
||||
|
||||
const arrowGroups = connections.flatMap((connection) => {
|
||||
const start = getWorldPositionFromScene(connection.startPointUuid);
|
||||
const end = getWorldPositionFromScene(connection.endPointUuid);
|
||||
if (!start || !end) return [];
|
||||
|
||||
const isBidirectional = connections.some(
|
||||
(other) =>
|
||||
other.startPointUuid === connection.endPointUuid &&
|
||||
other.endPointUuid === connection.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);
|
||||
|
||||
return [
|
||||
createArrow(connection.id + "-fwd", curve, 0.33, 0.25, scale, true),
|
||||
createArrow(connection.id + "-bwd", curve, 0.66, 0.25, scale, false),
|
||||
];
|
||||
}
|
||||
|
||||
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>;
|
||||
}
|
||||
|
||||
export function ArrowOnQuadraticBezier({
|
||||
start,
|
||||
mid,
|
||||
end,
|
||||
color = "#42a5f5",
|
||||
}: {
|
||||
start: number[];
|
||||
mid: number[];
|
||||
end: number[];
|
||||
color?: string;
|
||||
}) {
|
||||
const minScale = 0.5;
|
||||
const maxScale = 5;
|
||||
const segmentSize = 0.3;
|
||||
|
||||
const startVec = useMemo(() => new THREE.Vector3(...start), [start]);
|
||||
const midVec = useMemo(() => new THREE.Vector3(...mid), [mid]);
|
||||
const endVec = useMemo(() => new THREE.Vector3(...end), [end]);
|
||||
|
||||
const fullCurve = useMemo(
|
||||
() => new THREE.QuadraticBezierCurve3(startVec, midVec, endVec),
|
||||
[startVec, midVec, endVec]
|
||||
);
|
||||
|
||||
const distance = useMemo(() => startVec.distanceTo(endVec), [startVec, endVec]);
|
||||
const scale = useMemo(() => THREE.MathUtils.clamp(distance * 0.75, minScale, maxScale), [distance]);
|
||||
|
||||
const arrowHeadLength = 0.15 * scale;
|
||||
const arrowRadius = 0.01 * scale;
|
||||
const arrowHeadRadius = arrowRadius * 2.5;
|
||||
|
||||
const curveLength = useMemo(() => fullCurve.getLength(), [fullCurve]);
|
||||
const arrowHeadTOffset = useMemo(() => Math.min(arrowHeadLength / curveLength, 0.5), [arrowHeadLength, curveLength]);
|
||||
|
||||
const endT = 1 - arrowHeadTOffset;
|
||||
|
||||
const subCurve = useMemo(() => {
|
||||
const t1 = Math.max(0, endT - segmentSize / 2);
|
||||
const t2 = Math.min(1, endT + segmentSize / 2);
|
||||
const divisions = 10;
|
||||
const subPoints = Array.from({ length: divisions + 1 }, (_, i) => {
|
||||
const t = THREE.MathUtils.lerp(t1, t2, i / divisions);
|
||||
return fullCurve.getPoint(t);
|
||||
});
|
||||
return new THREE.CatmullRomCurve3(subPoints);
|
||||
}, [fullCurve, endT, segmentSize]);
|
||||
|
||||
const tubeGeometry = useMemo(
|
||||
() => new THREE.TubeGeometry(subCurve, 20, arrowRadius, 8, false),
|
||||
[subCurve, arrowRadius]
|
||||
);
|
||||
|
||||
const arrowPosition = useMemo(() => fullCurve.getPoint(1), [fullCurve]);
|
||||
const arrowTangent = useMemo(() => fullCurve.getTangent(1).normalize(), [fullCurve]);
|
||||
|
||||
const arrowRotation = useMemo(() => {
|
||||
return new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), arrowTangent);
|
||||
}, [arrowTangent]);
|
||||
|
||||
const coneGeometry = useMemo(() => {
|
||||
const geom = new THREE.ConeGeometry(arrowHeadRadius, arrowHeadLength, 8);
|
||||
geom.translate(0, arrowHeadLength / 2, 0);
|
||||
return geom;
|
||||
}, [arrowHeadRadius, arrowHeadLength]);
|
||||
|
||||
return (
|
||||
<group name="ArrowWithTube">
|
||||
<mesh name="ArrowWithTube" geometry={tubeGeometry}>
|
||||
<meshStandardMaterial color={color} />
|
||||
</mesh>
|
||||
<mesh name="ArrowWithTube" position={arrowPosition} quaternion={arrowRotation} geometry={coneGeometry}>
|
||||
<meshStandardMaterial color={color} />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
}
|
|
@ -6,11 +6,12 @@ import { useSelectedAction, useSelectedAsset } from "../../../../store/simulatio
|
|||
import { useProductStore } from "../../../../store/simulation/useProductStore";
|
||||
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
|
||||
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
|
||||
import { handleAddEventToProduct } from "../../events/points/functions/handleAddEventToProduct";
|
||||
import { handleAddEventToProduct } from "../points/functions/handleAddEventToProduct";
|
||||
import { QuadraticBezierLine } from "@react-three/drei";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
|
||||
import { useDeleteTool } from "../../../../store/builder/store";
|
||||
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
|
||||
import { ArrowOnQuadraticBezier, Arrows } from "../arrows/arrows";
|
||||
|
||||
interface ConnectionLine {
|
||||
id: string;
|
||||
|
@ -368,6 +369,7 @@ function TriggerConnector() {
|
|||
!intersect.object.name.includes("Roof") &&
|
||||
!intersect.object.name.includes("agv-collider") &&
|
||||
!intersect.object.name.includes("MeasurementReference") &&
|
||||
!intersect.object.name.includes("ArrowWithTube") &&
|
||||
!intersect.object.parent?.name.includes("Zone") &&
|
||||
!(intersect.object.type === "GridHelper") &&
|
||||
!(intersect.object.type === "Line2")
|
||||
|
@ -487,18 +489,29 @@ function TriggerConnector() {
|
|||
);
|
||||
})}
|
||||
|
||||
<Arrows connections={connections} />
|
||||
|
||||
{currentLine && (
|
||||
<QuadraticBezierLine
|
||||
start={currentLine.start.toArray()}
|
||||
end={currentLine.end.toArray()}
|
||||
mid={currentLine.mid.toArray()}
|
||||
color={helperlineColor}
|
||||
lineWidth={4}
|
||||
dashed
|
||||
dashSize={1}
|
||||
dashScale={20}
|
||||
/>
|
||||
<>
|
||||
<QuadraticBezierLine
|
||||
start={currentLine.start.toArray()}
|
||||
end={currentLine.end.toArray()}
|
||||
mid={currentLine.mid.toArray()}
|
||||
color={helperlineColor}
|
||||
lineWidth={4}
|
||||
dashed
|
||||
dashSize={1}
|
||||
dashScale={20}
|
||||
/>
|
||||
<ArrowOnQuadraticBezier
|
||||
start={currentLine.start.toArray()}
|
||||
mid={currentLine.mid.toArray()}
|
||||
end={currentLine.end.toArray()}
|
||||
color={helperlineColor}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
</group>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import TriggerConnector from './connector/triggerConnector'
|
||||
import TriggerConnector from '../events/triggerConnections/triggerConnector'
|
||||
|
||||
function Trigger() {
|
||||
|
||||
|
|
Loading…
Reference in New Issue