Refactor AssetProperties layout, enhance PositionInput component with optional properties, and implement new asset event fetching logic
This commit is contained in:
parent
dd03216393
commit
6e4c8282c5
|
@ -1,23 +1,32 @@
|
|||
import React from "react";
|
||||
import { EyeDroperIcon } from "../../../icons/ExportCommonIcons";
|
||||
|
||||
interface PositionInputProps {
|
||||
label?: string; // Optional label for the input
|
||||
onChange: (value: string) => void; // Callback for value change
|
||||
placeholder?: string; // Optional placeholder
|
||||
type?: string; // Input type (e.g., text, number, email)
|
||||
value1?: 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> = ({
|
||||
onChange,
|
||||
label = "Position", // Default label
|
||||
placeholder = "Enter value", // Default placeholder
|
||||
type = "number", // Default type
|
||||
value1 = "number",
|
||||
value2 = "number",
|
||||
disabled = false, // Default disabled value
|
||||
isEyedrop = false, // Default isEyedrop value
|
||||
handleEyeDropClick = () => { }, // Default function for eye drop click
|
||||
}) => {
|
||||
return (
|
||||
<div className="custom-input-container">
|
||||
<div className="header">Position</div>
|
||||
<div className="header">{label}</div>
|
||||
<div className="inputs-container">
|
||||
<div className="input-container">
|
||||
<div className="custom-input-label">X : </div>
|
||||
|
@ -26,7 +35,8 @@ const PositionInput: React.FC<PositionInputProps> = ({
|
|||
type={type}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
value={value2}
|
||||
value={value1}
|
||||
disabled={disabled} // Apply disabled prop
|
||||
/>
|
||||
</div>
|
||||
<div className="input-container">
|
||||
|
@ -36,10 +46,16 @@ const PositionInput: React.FC<PositionInputProps> = ({
|
|||
type={type}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
value={value1}
|
||||
value={value2}
|
||||
disabled={disabled} // Apply disabled prop
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{isEyedrop && (
|
||||
<div className="eye-picker-button" onClick={handleEyeDropClick}>
|
||||
<EyeDroperIcon isActive={false} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import React, { useRef, useMemo } from "react";
|
||||
import { InfoIcon } from "../../../icons/ExportCommonIcons";
|
||||
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 LabledDropdown from "../../../ui/inputs/LabledDropdown";
|
||||
import PositionInput from "../customInput/PositionInputs";
|
||||
|
||||
const VehicleMechanics: React.FC = () => {
|
||||
const { selectedActionSphere } = useSelectedActionSphere();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
|
||||
const { editingPoint, setEditingPoint } = useEditingPoint();
|
||||
const { previewPosition, setPreviewPosition } = usePreviewPosition();
|
||||
|
||||
const propertiesContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
|
@ -59,12 +62,10 @@ const VehicleMechanics: React.FC = () => {
|
|||
setSimulationPaths(updatedPaths);
|
||||
}, [selectedActionSphere?.point?.uuid, simulationPaths, setSimulationPaths]);
|
||||
|
||||
const handleStartPointChange = React.useCallback((uuid: string) => {
|
||||
handleActionUpdate({ start: uuid });
|
||||
const handleStartPointChange = React.useCallback((position: { x: number, y: number }) => {
|
||||
}, [handleActionUpdate]);
|
||||
|
||||
const handleEndPointChange = React.useCallback((uuid: string) => {
|
||||
handleActionUpdate({ end: uuid });
|
||||
const handleEndPointChange = React.useCallback((position: { x: number, y: number }) => {
|
||||
}, [handleActionUpdate]);
|
||||
|
||||
const handleHitCountChange = React.useCallback((hitCount: number) => {
|
||||
|
@ -94,6 +95,16 @@ const VehicleMechanics: React.FC = () => {
|
|||
setSimulationPaths(updatedPaths);
|
||||
}, [selectedActionSphere?.point?.uuid, simulationPaths, setSimulationPaths]);
|
||||
|
||||
const handleStartEyeDropClick = () => {
|
||||
setEditingPoint('start');
|
||||
setEyeDropMode(true);
|
||||
};
|
||||
|
||||
const handleEndEyeDropClick = () => {
|
||||
setEditingPoint('end');
|
||||
setEyeDropMode(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="machine-mechanics-container" key={selectedPoint?.uuid}>
|
||||
<div className="machine-mechanics-header">
|
||||
|
@ -106,20 +117,49 @@ const VehicleMechanics: React.FC = () => {
|
|||
|
||||
{selectedPoint && (
|
||||
<>
|
||||
<LabledDropdown
|
||||
key={`start-${selectedPoint.uuid}`}
|
||||
<PositionInput
|
||||
label="Start Point"
|
||||
defaultOption={selectedPoint.actions.start || "Select start point"}
|
||||
options={connectedPointUuids}
|
||||
onSelect={handleStartPointChange}
|
||||
onChange={() => { }}
|
||||
disabled={true}
|
||||
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
|
||||
key={`end-${selectedPoint.uuid}`}
|
||||
<PositionInput
|
||||
label="End Point"
|
||||
defaultOption={selectedPoint.actions.end || "Select end point"}
|
||||
options={connectedPointUuids}
|
||||
onSelect={handleEndPointChange}
|
||||
onChange={() => { }}
|
||||
disabled={true}
|
||||
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
|
||||
|
|
|
@ -55,8 +55,6 @@ const AssetProperties: React.FC = () => {
|
|||
{/* Name */}
|
||||
<div className="header">{selectedFloorItem.userData.name}</div>
|
||||
|
||||
<div className="split"></div>
|
||||
|
||||
<PositionInput
|
||||
onChange={() => {}}
|
||||
value1={xValue.toFixed(5)}
|
||||
|
|
|
@ -42,6 +42,8 @@ const SelectionControls: React.FC = () => {
|
|||
itemsGroupRef.current = itemsGroup;
|
||||
|
||||
let isSelecting = false;
|
||||
let isRightClick = false;
|
||||
let rightClickMoved = false;
|
||||
let isCtrlSelecting = false;
|
||||
|
||||
const helper = new SelectionHelper(gl);
|
||||
|
@ -52,16 +54,23 @@ const SelectionControls: React.FC = () => {
|
|||
}
|
||||
|
||||
const onPointerDown = (event: PointerEvent) => {
|
||||
if (event.button !== 0) return
|
||||
isSelecting = false;
|
||||
isCtrlSelecting = event.ctrlKey;
|
||||
if (event.ctrlKey && duplicatedObjects.length === 0) {
|
||||
if (controls) (controls as any).enabled = false;
|
||||
selectionBox.startPoint.set(pointer.x, pointer.y, 0);
|
||||
if (event.button === 2) {
|
||||
isRightClick = true;
|
||||
rightClickMoved = false;
|
||||
} else if (event.button === 0) {
|
||||
isSelecting = false;
|
||||
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) => {
|
||||
if (isRightClick) {
|
||||
rightClickMoved = true;
|
||||
}
|
||||
isSelecting = true;
|
||||
if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) {
|
||||
selectionBox.endPoint.set(pointer.x, pointer.y, 0);
|
||||
|
@ -69,6 +78,14 @@ const SelectionControls: React.FC = () => {
|
|||
};
|
||||
|
||||
const onPointerUp = (event: PointerEvent) => {
|
||||
if (event.button === 2) {
|
||||
isRightClick = false;
|
||||
if (!rightClickMoved) {
|
||||
clearSelection();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSelecting && isCtrlSelecting) {
|
||||
isCtrlSelecting = false;
|
||||
isSelecting = false;
|
||||
|
@ -94,10 +111,13 @@ const SelectionControls: React.FC = () => {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
const onContextMenu = (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
clearSelection();
|
||||
}
|
||||
if (!rightClickMoved) {
|
||||
clearSelection();
|
||||
}
|
||||
};
|
||||
|
||||
if (!toggleView && activeModule === "builder") {
|
||||
helper.enabled = true;
|
||||
|
|
|
@ -2,16 +2,22 @@ import { useFloorItems, useSimulationPaths } from '../../../store/store';
|
|||
import * as THREE from 'three';
|
||||
import * as Types from '../../../types/world/worldTypes';
|
||||
import { useEffect } from 'react';
|
||||
import { getAssetEventType } from '../../../services/simulation/getAssetEventType';
|
||||
|
||||
function Behaviour() {
|
||||
const { setSimulationPaths } = useSimulationPaths();
|
||||
const { floorItems } = useFloorItems();
|
||||
|
||||
useEffect(() => {
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[] = [];
|
||||
|
||||
floorItems.forEach((item: Types.FloorItemType) => {
|
||||
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 middlePointPosition = new THREE.Vector3(0, 0.85, 0);
|
||||
const point2Position = new THREE.Vector3(0, 0.85, -2.2);
|
||||
|
@ -67,7 +73,7 @@ function Behaviour() {
|
|||
point: {
|
||||
uuid: pointUUID,
|
||||
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: [] },
|
||||
speed: 2,
|
||||
},
|
||||
|
|
|
@ -96,24 +96,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||
};
|
||||
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 isConnectingToConveyor = toPath?.type === 'Conveyor';
|
||||
|
||||
// Count existing connections
|
||||
if (existingTargets.length >= 2) {
|
||||
console.log("Vehicle can have maximum 2 connections");
|
||||
if (toPath?.type !== 'Conveyor') {
|
||||
console.log("Vehicle can only connect to Conveyors");
|
||||
return path;
|
||||
}
|
||||
|
||||
// Check if we already have a Conveyor connection and trying to add another
|
||||
const hasConveyorConnection = existingTargets.some(target => {
|
||||
const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID);
|
||||
return targetPath?.type === 'Conveyor';
|
||||
});
|
||||
|
||||
if (hasConveyorConnection && isConnectingToConveyor) {
|
||||
console.log("Vehicle can only have one connection to a Conveyor");
|
||||
// Check if already has a connection
|
||||
if (existingTargets.length >= 1) {
|
||||
console.log("Vehicle can have only one connection");
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -141,24 +133,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||
};
|
||||
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 isConnectingFromConveyor = fromPath?.type === 'Conveyor';
|
||||
|
||||
// Count existing connections
|
||||
if (existingTargets.length >= 2) {
|
||||
console.log("Vehicle can have maximum 2 connections");
|
||||
if (fromPath?.type !== 'Conveyor') {
|
||||
console.log("Vehicle can only connect to Conveyors");
|
||||
return path;
|
||||
}
|
||||
|
||||
// Check if we already have a Conveyor connection and trying to add another
|
||||
const hasConveyorConnection = existingTargets.some(target => {
|
||||
const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID);
|
||||
return targetPath?.type === 'Conveyor';
|
||||
});
|
||||
|
||||
if (hasConveyorConnection && isConnectingFromConveyor) {
|
||||
console.log("Vehicle can only have one connection to a Conveyor");
|
||||
// Check if already has a connection
|
||||
if (existingTargets.length >= 1) {
|
||||
console.log("Vehicle can have only one connection");
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -212,6 +196,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||
drag = true;
|
||||
}
|
||||
};
|
||||
|
||||
const onContextMenu = (evt: MouseEvent) => {
|
||||
evt.preventDefault();
|
||||
if (drag || evt.button === 0) return;
|
||||
|
@ -282,7 +267,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||
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') {
|
||||
const isAlreadyConnected = simulationPaths.some(path => {
|
||||
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) {
|
||||
// Check if either selected point is from a Vehicle with max connections
|
||||
if (checkVehicleConnections(firstSelected.pathUUID) ||
|
||||
checkVehicleConnections(pathUUID)) {
|
||||
console.log("Vehicle already has maximum connections");
|
||||
// Check if trying to connect Vehicle to non-Conveyor
|
||||
if ((firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
|
||||
(secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor')) {
|
||||
console.log("Vehicle can only connect to Conveyors");
|
||||
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
|
||||
if (firstSelected.pathUUID === pathUUID) {
|
||||
console.log("Cannot connect spheres on the same path.");
|
||||
|
@ -478,28 +438,19 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||
return false;
|
||||
});
|
||||
|
||||
// Check vehicle connection limits
|
||||
// Check vehicle connection rules
|
||||
const isVehicleAtMaxConnections = pathData.type === 'Vehicle' &&
|
||||
pathData.point.connections.targets.length >= 2;
|
||||
|
||||
const isVehicleConveyorConflict =
|
||||
(firstPath?.type === 'Vehicle' && secondPath?.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';
|
||||
}));
|
||||
pathData.point.connections.targets.length >= 1;
|
||||
const isVehicleConnectingToNonConveyor =
|
||||
(firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
|
||||
(secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor');
|
||||
|
||||
if (
|
||||
!isDuplicateConnection &&
|
||||
!isVehicleToVehicle &&
|
||||
!isNonVehicleAlreadyConnected &&
|
||||
!isVehicleAtMaxConnections &&
|
||||
!isVehicleConveyorConflict &&
|
||||
!isVehicleConnectingToNonConveyor &&
|
||||
firstSelected.sphereUUID !== sphereUUID &&
|
||||
firstSelected.pathUUID !== pathUUID &&
|
||||
(firstSelected.isCorner || isConnectable)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import * as THREE from 'three';
|
||||
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 { 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 { useSubModuleStore } from '../../../store/useModuleStore';
|
||||
|
||||
|
@ -10,13 +10,18 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
const { renderDistance } = useRenderDistance();
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
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 { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { isConnecting } = useIsConnecting();
|
||||
const { camera } = useThree();
|
||||
|
||||
|
||||
const groupRefs = useRef<{ [key: string]: THREE.Group }>({});
|
||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||
const isMovingRef = useRef(false);
|
||||
const transformRef = useRef<any>(null);
|
||||
const [transformMode, setTransformMode] = useState<'translate' | 'rotate' | null>(null);
|
||||
|
||||
|
@ -77,6 +82,83 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
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 (
|
||||
<group name='simulation-simulationPaths-group' ref={pathsGroupRef}>
|
||||
|
@ -92,7 +174,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
position={path.assetPosition}
|
||||
rotation={path.assetRotation}
|
||||
onClick={(e) => {
|
||||
if (isConnecting) return;
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedPath({ path, group: groupRefs.current[path.modeluuid] });
|
||||
setSelectedActionSphere(null);
|
||||
|
@ -100,6 +182,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
setSubModule('mechanics');
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSelectedPath(null);
|
||||
setSubModule('properties');
|
||||
}}
|
||||
|
@ -113,7 +196,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
name='events-sphere'
|
||||
ref={el => (sphereRefs.current[point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
if (isConnecting) return;
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedActionSphere({
|
||||
path,
|
||||
|
@ -124,6 +207,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
}}
|
||||
userData={{ point, path }}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSubModule('properties');
|
||||
setSelectedActionSphere(null);
|
||||
}}
|
||||
|
@ -155,7 +239,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
ref={el => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.assetPosition}
|
||||
onClick={(e) => {
|
||||
if (isConnecting) return;
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedPath({ path, group: groupRefs.current[path.modeluuid] });
|
||||
setSelectedActionSphere(null);
|
||||
|
@ -163,6 +247,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
setSubModule('mechanics');
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSelectedPath(null);
|
||||
setSubModule('properties');
|
||||
}}
|
||||
|
@ -175,7 +260,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
name='events-sphere'
|
||||
ref={el => (sphereRefs.current[path.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
if (isConnecting) return;
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedActionSphere({
|
||||
path,
|
||||
|
@ -186,6 +271,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
|
|||
}}
|
||||
userData={{ point: path.point, path }}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSubModule('properties');
|
||||
setSelectedActionSphere(null);
|
||||
}}
|
||||
|
|
|
@ -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 { useThree } from '@react-three/fiber';
|
||||
import * as THREE from 'three';
|
||||
import Behaviour from './behaviour/behaviour';
|
||||
import PathCreation from './path/pathCreation';
|
||||
|
@ -29,9 +28,10 @@ function Simulation() {
|
|||
// }
|
||||
// }, [selectedPath]);
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Behaviour/>
|
||||
<Behaviour />
|
||||
{activeModule === 'simulation' && (
|
||||
<>
|
||||
<PathCreation pathsGroupRef={pathsGroupRef} />
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
};
|
|
@ -348,10 +348,30 @@ export const useStartSimulation = create<any>((set: any) => ({
|
|||
startSimulation: false,
|
||||
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) => ({
|
||||
zoneTarget: [],
|
||||
setZoneTarget: (x: any) => set({ zoneTarget: x }),
|
||||
}));
|
||||
|
||||
export const usezonePosition = create<any>((set: any) => ({
|
||||
zonePosition: [],
|
||||
setZonePosition: (x: any) => set({ zonePosition: x }),
|
||||
|
@ -371,6 +391,7 @@ export const useAsset3dWidget = create<any>((set: any) => ({
|
|||
widgetSelect: "",
|
||||
setWidgetSelect: (x: any) => set({ widgetSelect: x }),
|
||||
}));
|
||||
|
||||
export const useWidgetSubOption = create<any>((set: any) => ({
|
||||
widgetSubOption: "2D",
|
||||
setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),
|
||||
|
|
|
@ -310,7 +310,7 @@ interface VehicleEventsSchema {
|
|||
point: {
|
||||
uuid: string;
|
||||
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 }[] };
|
||||
speed: number;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue