Refactor AssetProperties layout, enhance PositionInput component with optional properties, and implement new asset event fetching logic

This commit is contained in:
Jerald-Golden-B 2025-03-31 14:28:24 +05:30
parent dd03216393
commit 6e4c8282c5
11 changed files with 288 additions and 124 deletions

View File

@ -1,23 +1,32 @@
import React from "react"; import React from "react";
import { EyeDroperIcon } from "../../../icons/ExportCommonIcons";
interface PositionInputProps { interface PositionInputProps {
label?: string; // Optional label for the input
onChange: (value: string) => void; // Callback for value change onChange: (value: string) => void; // Callback for value change
placeholder?: string; // Optional placeholder placeholder?: string; // Optional placeholder
type?: string; // Input type (e.g., text, number, email) type?: string; // Input type (e.g., text, number, email)
value1?: number; value1?: number;
value2?: number; value2?: number;
disabled?: boolean; // Optional disabled property
isEyedrop?: boolean; // Optional eyedrop property
handleEyeDropClick?: () => void; // Optional function for eye drop click
} }
const PositionInput: React.FC<PositionInputProps> = ({ const PositionInput: React.FC<PositionInputProps> = ({
onChange, onChange,
label = "Position", // Default label
placeholder = "Enter value", // Default placeholder placeholder = "Enter value", // Default placeholder
type = "number", // Default type type = "number", // Default type
value1 = "number", value1 = "number",
value2 = "number", value2 = "number",
disabled = false, // Default disabled value
isEyedrop = false, // Default isEyedrop value
handleEyeDropClick = () => { }, // Default function for eye drop click
}) => { }) => {
return ( return (
<div className="custom-input-container"> <div className="custom-input-container">
<div className="header">Position</div> <div className="header">{label}</div>
<div className="inputs-container"> <div className="inputs-container">
<div className="input-container"> <div className="input-container">
<div className="custom-input-label">X : </div> <div className="custom-input-label">X : </div>
@ -26,7 +35,8 @@ const PositionInput: React.FC<PositionInputProps> = ({
type={type} type={type}
onChange={(e) => onChange(e.target.value)} onChange={(e) => onChange(e.target.value)}
placeholder={placeholder} placeholder={placeholder}
value={value2} value={value1}
disabled={disabled} // Apply disabled prop
/> />
</div> </div>
<div className="input-container"> <div className="input-container">
@ -36,10 +46,16 @@ const PositionInput: React.FC<PositionInputProps> = ({
type={type} type={type}
onChange={(e) => onChange(e.target.value)} onChange={(e) => onChange(e.target.value)}
placeholder={placeholder} placeholder={placeholder}
value={value1} value={value2}
disabled={disabled} // Apply disabled prop
/> />
</div> </div>
</div> </div>
{isEyedrop && (
<div className="eye-picker-button" onClick={handleEyeDropClick}>
<EyeDroperIcon isActive={false} />
</div>
)}
</div> </div>
); );
}; };

View File

@ -1,13 +1,16 @@
import React, { useRef, useMemo } from "react"; import React, { useRef, useMemo } from "react";
import { InfoIcon } from "../../../icons/ExportCommonIcons"; import { InfoIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { useSelectedActionSphere, useSimulationPaths } from "../../../../store/store"; import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationPaths } from "../../../../store/store";
import * as Types from '../../../../types/world/worldTypes'; import * as Types from '../../../../types/world/worldTypes';
import LabledDropdown from "../../../ui/inputs/LabledDropdown"; import PositionInput from "../customInput/PositionInputs";
const VehicleMechanics: React.FC = () => { const VehicleMechanics: React.FC = () => {
const { selectedActionSphere } = useSelectedActionSphere(); const { selectedActionSphere } = useSelectedActionSphere();
const { simulationPaths, setSimulationPaths } = useSimulationPaths(); const { simulationPaths, setSimulationPaths } = useSimulationPaths();
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
const { editingPoint, setEditingPoint } = useEditingPoint();
const { previewPosition, setPreviewPosition } = usePreviewPosition();
const propertiesContainerRef = useRef<HTMLDivElement>(null); const propertiesContainerRef = useRef<HTMLDivElement>(null);
@ -59,12 +62,10 @@ const VehicleMechanics: React.FC = () => {
setSimulationPaths(updatedPaths); setSimulationPaths(updatedPaths);
}, [selectedActionSphere?.point?.uuid, simulationPaths, setSimulationPaths]); }, [selectedActionSphere?.point?.uuid, simulationPaths, setSimulationPaths]);
const handleStartPointChange = React.useCallback((uuid: string) => { const handleStartPointChange = React.useCallback((position: { x: number, y: number }) => {
handleActionUpdate({ start: uuid });
}, [handleActionUpdate]); }, [handleActionUpdate]);
const handleEndPointChange = React.useCallback((uuid: string) => { const handleEndPointChange = React.useCallback((position: { x: number, y: number }) => {
handleActionUpdate({ end: uuid });
}, [handleActionUpdate]); }, [handleActionUpdate]);
const handleHitCountChange = React.useCallback((hitCount: number) => { const handleHitCountChange = React.useCallback((hitCount: number) => {
@ -94,6 +95,16 @@ const VehicleMechanics: React.FC = () => {
setSimulationPaths(updatedPaths); setSimulationPaths(updatedPaths);
}, [selectedActionSphere?.point?.uuid, simulationPaths, setSimulationPaths]); }, [selectedActionSphere?.point?.uuid, simulationPaths, setSimulationPaths]);
const handleStartEyeDropClick = () => {
setEditingPoint('start');
setEyeDropMode(true);
};
const handleEndEyeDropClick = () => {
setEditingPoint('end');
setEyeDropMode(true);
};
return ( return (
<div className="machine-mechanics-container" key={selectedPoint?.uuid}> <div className="machine-mechanics-container" key={selectedPoint?.uuid}>
<div className="machine-mechanics-header"> <div className="machine-mechanics-header">
@ -106,20 +117,49 @@ const VehicleMechanics: React.FC = () => {
{selectedPoint && ( {selectedPoint && (
<> <>
<LabledDropdown <PositionInput
key={`start-${selectedPoint.uuid}`}
label="Start Point" label="Start Point"
defaultOption={selectedPoint.actions.start || "Select start point"} onChange={() => { }}
options={connectedPointUuids} disabled={true}
onSelect={handleStartPointChange} value1={
editingPoint === 'start' && previewPosition
? parseFloat(previewPosition.x.toFixed(4))
: selectedPoint.actions.start && 'x' in selectedPoint.actions.start
? parseFloat(selectedPoint.actions.start.x.toFixed(4))
: 0
}
value2={
editingPoint === 'start' && previewPosition
? parseFloat(previewPosition.y.toFixed(4))
: selectedPoint.actions.start && 'y' in selectedPoint.actions.start
? parseFloat(selectedPoint.actions.start.y.toFixed(4))
: 0
}
isEyedrop={true}
handleEyeDropClick={handleStartEyeDropClick}
/> />
<LabledDropdown <PositionInput
key={`end-${selectedPoint.uuid}`}
label="End Point" label="End Point"
defaultOption={selectedPoint.actions.end || "Select end point"} onChange={() => { }}
options={connectedPointUuids} disabled={true}
onSelect={handleEndPointChange} value1={
editingPoint === 'end' && previewPosition
? parseFloat(previewPosition.x.toFixed(4))
: selectedPoint.actions.end && 'x' in selectedPoint.actions.end
? parseFloat(selectedPoint.actions.end.x.toFixed(4))
: 0
}
value2={
editingPoint === 'end' && previewPosition
? parseFloat(previewPosition.y.toFixed(4))
: selectedPoint.actions.end && 'y' in selectedPoint.actions.end
? parseFloat(selectedPoint.actions.end.y.toFixed(4))
: 0
}
isEyedrop={true}
handleEyeDropClick={handleEndEyeDropClick}
/> />
<InputWithDropDown <InputWithDropDown

View File

@ -55,8 +55,6 @@ const AssetProperties: React.FC = () => {
{/* Name */} {/* Name */}
<div className="header">{selectedFloorItem.userData.name}</div> <div className="header">{selectedFloorItem.userData.name}</div>
<div className="split"></div>
<PositionInput <PositionInput
onChange={() => {}} onChange={() => {}}
value1={xValue.toFixed(5)} value1={xValue.toFixed(5)}

View File

@ -42,6 +42,8 @@ const SelectionControls: React.FC = () => {
itemsGroupRef.current = itemsGroup; itemsGroupRef.current = itemsGroup;
let isSelecting = false; let isSelecting = false;
let isRightClick = false;
let rightClickMoved = false;
let isCtrlSelecting = false; let isCtrlSelecting = false;
const helper = new SelectionHelper(gl); const helper = new SelectionHelper(gl);
@ -52,16 +54,23 @@ const SelectionControls: React.FC = () => {
} }
const onPointerDown = (event: PointerEvent) => { const onPointerDown = (event: PointerEvent) => {
if (event.button !== 0) return if (event.button === 2) {
isSelecting = false; isRightClick = true;
isCtrlSelecting = event.ctrlKey; rightClickMoved = false;
if (event.ctrlKey && duplicatedObjects.length === 0) { } else if (event.button === 0) {
if (controls) (controls as any).enabled = false; isSelecting = false;
selectionBox.startPoint.set(pointer.x, pointer.y, 0); isCtrlSelecting = event.ctrlKey;
if (event.ctrlKey && duplicatedObjects.length === 0) {
if (controls) (controls as any).enabled = false;
selectionBox.startPoint.set(pointer.x, pointer.y, 0);
}
} }
}; };
const onPointerMove = (event: PointerEvent) => { const onPointerMove = (event: PointerEvent) => {
if (isRightClick) {
rightClickMoved = true;
}
isSelecting = true; isSelecting = true;
if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) { if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) {
selectionBox.endPoint.set(pointer.x, pointer.y, 0); selectionBox.endPoint.set(pointer.x, pointer.y, 0);
@ -69,6 +78,14 @@ const SelectionControls: React.FC = () => {
}; };
const onPointerUp = (event: PointerEvent) => { const onPointerUp = (event: PointerEvent) => {
if (event.button === 2) {
isRightClick = false;
if (!rightClickMoved) {
clearSelection();
}
return;
}
if (isSelecting && isCtrlSelecting) { if (isSelecting && isCtrlSelecting) {
isCtrlSelecting = false; isCtrlSelecting = false;
isSelecting = false; isSelecting = false;
@ -94,10 +111,13 @@ const SelectionControls: React.FC = () => {
} }
}; };
const onContextMenu = (event: MouseEvent) => { const onContextMenu = (event: MouseEvent) => {
event.preventDefault(); event.preventDefault();
clearSelection(); if (!rightClickMoved) {
} clearSelection();
}
};
if (!toggleView && activeModule === "builder") { if (!toggleView && activeModule === "builder") {
helper.enabled = true; helper.enabled = true;

View File

@ -2,16 +2,22 @@ import { useFloorItems, useSimulationPaths } from '../../../store/store';
import * as THREE from 'three'; import * as THREE from 'three';
import * as Types from '../../../types/world/worldTypes'; import * as Types from '../../../types/world/worldTypes';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { getAssetEventType } from '../../../services/simulation/getAssetEventType';
function Behaviour() { function Behaviour() {
const { setSimulationPaths } = useSimulationPaths(); const { setSimulationPaths } = useSimulationPaths();
const { floorItems } = useFloorItems(); const { floorItems } = useFloorItems();
useEffect(() => { useEffect(() => {
const email = localStorage.getItem('email')
const organization = (email!.split("@")[1]).split(".")[0];
const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[] = []; const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[] = [];
floorItems.forEach((item: Types.FloorItemType) => { floorItems.forEach((item: Types.FloorItemType) => {
if (item.modelfileID === "672a090f80d91ac979f4d0bd") { if (item.modelfileID === "672a090f80d91ac979f4d0bd") {
// getAssetEventType(item.modelfileID, organization).then((res) => {
// console.log('res: ', res);
// });
const point1Position = new THREE.Vector3(0, 0.85, 2.2); const point1Position = new THREE.Vector3(0, 0.85, 2.2);
const middlePointPosition = new THREE.Vector3(0, 0.85, 0); const middlePointPosition = new THREE.Vector3(0, 0.85, 0);
const point2Position = new THREE.Vector3(0, 0.85, -2.2); const point2Position = new THREE.Vector3(0, 0.85, -2.2);
@ -67,7 +73,7 @@ function Behaviour() {
point: { point: {
uuid: pointUUID, uuid: pointUUID,
position: [pointPosition.x, pointPosition.y, pointPosition.z], position: [pointPosition.x, pointPosition.y, pointPosition.z],
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: '', hitCount: 1, end: '', buffer: 0 }, actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: {}, hitCount: 1, end: {}, buffer: 0 },
connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] }, connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
speed: 2, speed: 2,
}, },

View File

@ -96,24 +96,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
}; };
const existingTargets = path.point.connections.targets || []; const existingTargets = path.point.connections.targets || [];
// Check if we're trying to add a connection to a Conveyor // Check if target is a Conveyor
const toPath = simulationPaths.find(p => p.modeluuid === toPathUUID); const toPath = simulationPaths.find(p => p.modeluuid === toPathUUID);
const isConnectingToConveyor = toPath?.type === 'Conveyor'; if (toPath?.type !== 'Conveyor') {
console.log("Vehicle can only connect to Conveyors");
// Count existing connections
if (existingTargets.length >= 2) {
console.log("Vehicle can have maximum 2 connections");
return path; return path;
} }
// Check if we already have a Conveyor connection and trying to add another // Check if already has a connection
const hasConveyorConnection = existingTargets.some(target => { if (existingTargets.length >= 1) {
const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID); console.log("Vehicle can have only one connection");
return targetPath?.type === 'Conveyor';
});
if (hasConveyorConnection && isConnectingToConveyor) {
console.log("Vehicle can only have one connection to a Conveyor");
return path; return path;
} }
@ -141,24 +133,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
}; };
const existingTargets = path.point.connections.targets || []; const existingTargets = path.point.connections.targets || [];
// Check if we're receiving a connection from a Conveyor // Check if source is a Conveyor
const fromPath = simulationPaths.find(p => p.modeluuid === fromPathUUID); const fromPath = simulationPaths.find(p => p.modeluuid === fromPathUUID);
const isConnectingFromConveyor = fromPath?.type === 'Conveyor'; if (fromPath?.type !== 'Conveyor') {
console.log("Vehicle can only connect to Conveyors");
// Count existing connections
if (existingTargets.length >= 2) {
console.log("Vehicle can have maximum 2 connections");
return path; return path;
} }
// Check if we already have a Conveyor connection and trying to add another // Check if already has a connection
const hasConveyorConnection = existingTargets.some(target => { if (existingTargets.length >= 1) {
const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID); console.log("Vehicle can have only one connection");
return targetPath?.type === 'Conveyor';
});
if (hasConveyorConnection && isConnectingFromConveyor) {
console.log("Vehicle can only have one connection to a Conveyor");
return path; return path;
} }
@ -212,6 +196,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
drag = true; drag = true;
} }
}; };
const onContextMenu = (evt: MouseEvent) => { const onContextMenu = (evt: MouseEvent) => {
evt.preventDefault(); evt.preventDefault();
if (drag || evt.button === 0) return; if (drag || evt.button === 0) return;
@ -282,7 +267,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
return; return;
} }
// For Vehicles, skip the "already connected" check since they can have multiple connections // For Vehicles, check if they're already connected to anything
if (intersected.userData.path.type === 'Vehicle') {
const vehicleConnections = intersected.userData.path.point.connections.targets.length;
if (vehicleConnections >= 1) {
console.log("Vehicle can only have one connection");
return;
}
}
// For non-Vehicle paths, check if already connected
if (intersected.userData.path.type !== 'Vehicle') { if (intersected.userData.path.type !== 'Vehicle') {
const isAlreadyConnected = simulationPaths.some(path => { const isAlreadyConnected = simulationPaths.some(path => {
if (path.type === 'Conveyor') { if (path.type === 'Conveyor') {
@ -300,48 +294,14 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
} }
} }
// Check vehicle connection limits
const checkVehicleConnections = (pathUUID: string) => {
const path = simulationPaths.find(p => p.modeluuid === pathUUID);
if (path?.type === 'Vehicle') {
return path.point.connections.targets.length >= 2;
}
return false;
};
if (firstSelected) { if (firstSelected) {
// Check if either selected point is from a Vehicle with max connections // Check if trying to connect Vehicle to non-Conveyor
if (checkVehicleConnections(firstSelected.pathUUID) || if ((firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
checkVehicleConnections(pathUUID)) { (secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor')) {
console.log("Vehicle already has maximum connections"); console.log("Vehicle can only connect to Conveyors");
return; return;
} }
// Check if we're trying to add a second Conveyor connection to a Vehicle
if (firstPath?.type === 'Vehicle' && secondPath?.type === 'Conveyor') {
const hasConveyorConnection = firstPath.point.connections.targets.some(target => {
const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID);
return targetPath?.type === 'Conveyor';
});
if (hasConveyorConnection) {
console.log("Vehicle can only have one connection to a Conveyor");
return;
}
}
if (secondPath?.type === 'Vehicle' && firstPath?.type === 'Conveyor') {
const hasConveyorConnection = secondPath.point.connections.targets.some(target => {
const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID);
return targetPath?.type === 'Conveyor';
});
if (hasConveyorConnection) {
console.log("Vehicle can only have one connection to a Conveyor");
return;
}
}
// Prevent same-path connections // Prevent same-path connections
if (firstSelected.pathUUID === pathUUID) { if (firstSelected.pathUUID === pathUUID) {
console.log("Cannot connect spheres on the same path."); console.log("Cannot connect spheres on the same path.");
@ -478,28 +438,19 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
return false; return false;
}); });
// Check vehicle connection limits // Check vehicle connection rules
const isVehicleAtMaxConnections = pathData.type === 'Vehicle' && const isVehicleAtMaxConnections = pathData.type === 'Vehicle' &&
pathData.point.connections.targets.length >= 2; pathData.point.connections.targets.length >= 1;
const isVehicleConnectingToNonConveyor =
const isVehicleConveyorConflict = (firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
(firstPath?.type === 'Vehicle' && secondPath?.type === 'Conveyor' && (secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor');
firstPath.point.connections.targets.some(t => {
const targetPath = simulationPaths.find(p => p.modeluuid === t.pathUUID);
return targetPath?.type === 'Conveyor';
})) ||
(secondPath?.type === 'Vehicle' && firstPath?.type === 'Conveyor' &&
secondPath.point.connections.targets.some(t => {
const targetPath = simulationPaths.find(p => p.modeluuid === t.pathUUID);
return targetPath?.type === 'Conveyor';
}));
if ( if (
!isDuplicateConnection && !isDuplicateConnection &&
!isVehicleToVehicle && !isVehicleToVehicle &&
!isNonVehicleAlreadyConnected && !isNonVehicleAlreadyConnected &&
!isVehicleAtMaxConnections && !isVehicleAtMaxConnections &&
!isVehicleConveyorConflict && !isVehicleConnectingToNonConveyor &&
firstSelected.sphereUUID !== sphereUUID && firstSelected.sphereUUID !== sphereUUID &&
firstSelected.pathUUID !== pathUUID && firstSelected.pathUUID !== pathUUID &&
(firstSelected.isCorner || isConnectable) (firstSelected.isCorner || isConnectable)

View File

@ -1,8 +1,8 @@
import * as THREE from 'three'; import * as THREE from 'three';
import * as Types from '../../../types/world/worldTypes'; import * as Types from '../../../types/world/worldTypes';
import { useRef, useState, useEffect } from 'react'; import { useRef, useState, useEffect, useMemo } from 'react';
import { Sphere, TransformControls } from '@react-three/drei'; import { Sphere, TransformControls } from '@react-three/drei';
import { useIsConnecting, useRenderDistance, useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../../store/store'; import { useEditingPoint, useEyeDropMode, useIsConnecting, usePreviewPosition, useRenderDistance, useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../../store/store';
import { useFrame, useThree } from '@react-three/fiber'; import { useFrame, useThree } from '@react-three/fiber';
import { useSubModuleStore } from '../../../store/useModuleStore'; import { useSubModuleStore } from '../../../store/useModuleStore';
@ -10,13 +10,18 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
const { renderDistance } = useRenderDistance(); const { renderDistance } = useRenderDistance();
const { setSubModule } = useSubModuleStore(); const { setSubModule } = useSubModuleStore();
const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere(); const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere();
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
const { editingPoint, setEditingPoint } = useEditingPoint();
const { previewPosition, setPreviewPosition } = usePreviewPosition();
const { raycaster, camera, pointer, gl } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { setSelectedPath } = useSelectedPath(); const { setSelectedPath } = useSelectedPath();
const { simulationPaths, setSimulationPaths } = useSimulationPaths(); const { simulationPaths, setSimulationPaths } = useSimulationPaths();
const { isConnecting } = useIsConnecting(); const { isConnecting } = useIsConnecting();
const { camera } = useThree();
const groupRefs = useRef<{ [key: string]: THREE.Group }>({}); const groupRefs = useRef<{ [key: string]: THREE.Group }>({});
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
const isMovingRef = useRef(false);
const transformRef = useRef<any>(null); const transformRef = useRef<any>(null);
const [transformMode, setTransformMode] = useState<'translate' | 'rotate' | null>(null); const [transformMode, setTransformMode] = useState<'translate' | 'rotate' | null>(null);
@ -77,6 +82,83 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
setSimulationPaths(updatedPaths); setSimulationPaths(updatedPaths);
}; };
useFrame(() => {
if (eyeDropMode) {
raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (point) {
setPreviewPosition({ x: point.x, y: point.z });
}
} else {
setPreviewPosition(null);
}
});
useEffect(() => {
if (!camera) return;
const canvasElement = gl.domElement;
canvasElement.tabIndex = 0;
const onPointerDown = () => {
isMovingRef.current = false;
};
const onPointerMove = () => {
isMovingRef.current = true;
};
const onPointerUp = (event: PointerEvent) => {
if (!isMovingRef.current && eyeDropMode && event.button === 0 && previewPosition) {
event.preventDefault();
if (editingPoint) {
handlePointUpdate(editingPoint, previewPosition.x, previewPosition.y);
setEditingPoint(null);
setEyeDropMode(false);
}
}
};
if (eyeDropMode) {
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);
};
}, [eyeDropMode, editingPoint, previewPosition]);
const handlePointUpdate = (pointType: 'start' | 'end', x: number, z: number) => {
if (!selectedActionSphere?.point?.uuid) return;
const updatedPaths = simulationPaths.map((path) => {
if (path.type === "Vehicle" && path.point.uuid === selectedActionSphere.point.uuid) {
return {
...path,
point: {
...path.point,
actions: {
...path.point.actions,
[pointType]: {
...path.point.actions[pointType],
x: x,
y: z
}
}
}
};
}
return path;
});
setSimulationPaths(updatedPaths);
};
return ( return (
<group name='simulation-simulationPaths-group' ref={pathsGroupRef}> <group name='simulation-simulationPaths-group' ref={pathsGroupRef}>
@ -92,7 +174,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
position={path.assetPosition} position={path.assetPosition}
rotation={path.assetRotation} rotation={path.assetRotation}
onClick={(e) => { onClick={(e) => {
if (isConnecting) return; if (isConnecting || eyeDropMode) return;
e.stopPropagation(); e.stopPropagation();
setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); setSelectedPath({ path, group: groupRefs.current[path.modeluuid] });
setSelectedActionSphere(null); setSelectedActionSphere(null);
@ -100,6 +182,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
setSubModule('mechanics'); setSubModule('mechanics');
}} }}
onPointerMissed={() => { onPointerMissed={() => {
if (eyeDropMode) return;
setSelectedPath(null); setSelectedPath(null);
setSubModule('properties'); setSubModule('properties');
}} }}
@ -113,7 +196,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
name='events-sphere' name='events-sphere'
ref={el => (sphereRefs.current[point.uuid] = el!)} ref={el => (sphereRefs.current[point.uuid] = el!)}
onClick={(e) => { onClick={(e) => {
if (isConnecting) return; if (isConnecting || eyeDropMode) return;
e.stopPropagation(); e.stopPropagation();
setSelectedActionSphere({ setSelectedActionSphere({
path, path,
@ -124,6 +207,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
}} }}
userData={{ point, path }} userData={{ point, path }}
onPointerMissed={() => { onPointerMissed={() => {
if (eyeDropMode) return;
setSubModule('properties'); setSubModule('properties');
setSelectedActionSphere(null); setSelectedActionSphere(null);
}} }}
@ -155,7 +239,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
ref={el => (groupRefs.current[path.modeluuid] = el!)} ref={el => (groupRefs.current[path.modeluuid] = el!)}
position={path.assetPosition} position={path.assetPosition}
onClick={(e) => { onClick={(e) => {
if (isConnecting) return; if (isConnecting || eyeDropMode) return;
e.stopPropagation(); e.stopPropagation();
setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); setSelectedPath({ path, group: groupRefs.current[path.modeluuid] });
setSelectedActionSphere(null); setSelectedActionSphere(null);
@ -163,6 +247,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
setSubModule('mechanics'); setSubModule('mechanics');
}} }}
onPointerMissed={() => { onPointerMissed={() => {
if (eyeDropMode) return;
setSelectedPath(null); setSelectedPath(null);
setSubModule('properties'); setSubModule('properties');
}} }}
@ -175,7 +260,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
name='events-sphere' name='events-sphere'
ref={el => (sphereRefs.current[path.point.uuid] = el!)} ref={el => (sphereRefs.current[path.point.uuid] = el!)}
onClick={(e) => { onClick={(e) => {
if (isConnecting) return; if (isConnecting || eyeDropMode) return;
e.stopPropagation(); e.stopPropagation();
setSelectedActionSphere({ setSelectedActionSphere({
path, path,
@ -186,6 +271,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
}} }}
userData={{ point: path.point, path }} userData={{ point: path.point, path }}
onPointerMissed={() => { onPointerMissed={() => {
if (eyeDropMode) return;
setSubModule('properties'); setSubModule('properties');
setSelectedActionSphere(null); setSelectedActionSphere(null);
}} }}

View File

@ -1,6 +1,5 @@
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef, useMemo } from 'react';
import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../store/store'; import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../store/store';
import { useThree } from '@react-three/fiber';
import * as THREE from 'three'; import * as THREE from 'three';
import Behaviour from './behaviour/behaviour'; import Behaviour from './behaviour/behaviour';
import PathCreation from './path/pathCreation'; import PathCreation from './path/pathCreation';
@ -29,9 +28,10 @@ function Simulation() {
// } // }
// }, [selectedPath]); // }, [selectedPath]);
return ( return (
<> <>
<Behaviour/> <Behaviour />
{activeModule === 'simulation' && ( {activeModule === 'simulation' && (
<> <>
<PathCreation pathsGroupRef={pathsGroupRef} /> <PathCreation pathsGroupRef={pathsGroupRef} />

View File

@ -0,0 +1,26 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_TEST}`;
export const getAssetEventType = async (modelId: string, organization: string) => {
try {
const response = await fetch(`${url_Backend_dwinzo}/api/v2/pointData/${modelId}/${organization}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error("Failed to fetch model event type");
}
const result = await response.json();
console.log('result: ', result);
return result;
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
} else {
throw new Error("An unknown error occurred");
}
}
};

View File

@ -348,10 +348,30 @@ export const useStartSimulation = create<any>((set: any) => ({
startSimulation: false, startSimulation: false,
setStartSimulation: (x: any) => set({ startSimulation: x }), setStartSimulation: (x: any) => set({ startSimulation: x }),
})); }));
export const useEyeDropMode = create<any>((set: any) => ({
eyeDropMode: false,
setEyeDropMode: (x: any) => set({ eyeDropMode: x }),
}));
export const useEditingPoint = create<any>((set: any) => ({
editingPoint: false,
setEditingPoint: (x: any) => set({ editingPoint: x }),
}));
export const usePreviewPosition = create<{
previewPosition: { x: number; y: number } | null;
setPreviewPosition: (position: { x: number; y: number } | null) => void;
}>((set) => ({
previewPosition: null,
setPreviewPosition: (position) => set({ previewPosition: position }),
}));
export const usezoneTarget = create<any>((set: any) => ({ export const usezoneTarget = create<any>((set: any) => ({
zoneTarget: [], zoneTarget: [],
setZoneTarget: (x: any) => set({ zoneTarget: x }), setZoneTarget: (x: any) => set({ zoneTarget: x }),
})); }));
export const usezonePosition = create<any>((set: any) => ({ export const usezonePosition = create<any>((set: any) => ({
zonePosition: [], zonePosition: [],
setZonePosition: (x: any) => set({ zonePosition: x }), setZonePosition: (x: any) => set({ zonePosition: x }),
@ -371,6 +391,7 @@ export const useAsset3dWidget = create<any>((set: any) => ({
widgetSelect: "", widgetSelect: "",
setWidgetSelect: (x: any) => set({ widgetSelect: x }), setWidgetSelect: (x: any) => set({ widgetSelect: x }),
})); }));
export const useWidgetSubOption = create<any>((set: any) => ({ export const useWidgetSubOption = create<any>((set: any) => ({
widgetSubOption: "2D", widgetSubOption: "2D",
setWidgetSubOption: (x: any) => set({ widgetSubOption: x }), setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),

View File

@ -310,7 +310,7 @@ interface VehicleEventsSchema {
point: { point: {
uuid: string; uuid: string;
position: [number, number, number]; position: [number, number, number];
actions: { uuid: string; name: string; type: string; start: string, hitCount: number, end: string, buffer: number }; actions: { uuid: string; name: string; type: string; start: { x: number, y: number } | {}, hitCount: number, end: { x: number, y: number } | {}, buffer: number };
connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
speed: number; speed: number;
}; };