Merge branch 'v2' into simulation-armbot-v2
This commit is contained in:
@@ -187,7 +187,7 @@ function processLoadedModel(
|
||||
},
|
||||
]);
|
||||
|
||||
if (item.eventData.type === "vehicle") {
|
||||
if (item.eventData.type === "Vehicle") {
|
||||
const vehicleEvent: VehicleEventSchema = {
|
||||
modelUuid: item.modelUuid,
|
||||
modelName: item.modelName,
|
||||
@@ -202,7 +202,7 @@ function processLoadedModel(
|
||||
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Vehicle Action",
|
||||
actionName: "Action 1",
|
||||
actionType: "travel",
|
||||
unLoadDuration: 5,
|
||||
loadCapacity: 10,
|
||||
@@ -254,7 +254,7 @@ function processLoadedModel(
|
||||
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Process Action",
|
||||
actionName: "Action 1",
|
||||
actionType: "process",
|
||||
processTime: 10,
|
||||
swapMaterial: "material-id",
|
||||
@@ -279,7 +279,7 @@ function processLoadedModel(
|
||||
actions: [
|
||||
{
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Pick and Place",
|
||||
actionName: "Action 1",
|
||||
actionType: "pickAndPlace",
|
||||
process: {
|
||||
startPoint: [0, 0, 0],
|
||||
|
||||
@@ -186,22 +186,59 @@ async function handleModelLoad(
|
||||
state: "idle",
|
||||
type: 'transfer',
|
||||
speed: 1,
|
||||
points: data.points.map((point: THREE.Vector3, index: number) => ({
|
||||
uuid: THREE.MathUtils.generateUUID(),
|
||||
position: [point.x, point.y, point.z],
|
||||
rotation: [0, 0, 0],
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: `Action ${index}`,
|
||||
actionType: 'default',
|
||||
material: 'Default Material',
|
||||
delay: 0,
|
||||
spawnInterval: 5,
|
||||
spawnCount: 1,
|
||||
triggers: []
|
||||
points: data.points.map((point: THREE.Vector3, index: number) => {
|
||||
const triggers: TriggerSchema[] = [];
|
||||
|
||||
if (data.points && index < data.points.length - 1) {
|
||||
triggers.push({
|
||||
triggerUuid: THREE.MathUtils.generateUUID(),
|
||||
triggerName: `Trigger 1`,
|
||||
triggerType: "onComplete",
|
||||
delay: 0,
|
||||
triggeredAsset: {
|
||||
triggeredModel: {
|
||||
modelName: newFloorItem.modelName,
|
||||
modelUuid: newFloorItem.modelUuid
|
||||
},
|
||||
triggeredPoint: {
|
||||
pointName: `Point`,
|
||||
pointUuid: ""
|
||||
},
|
||||
triggeredAction: {
|
||||
actionName: `Action 1`,
|
||||
actionUuid: ""
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}))
|
||||
|
||||
return {
|
||||
uuid: THREE.MathUtils.generateUUID(),
|
||||
position: [point.x, point.y, point.z],
|
||||
rotation: [0, 0, 0],
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: `Action 1`,
|
||||
actionType: 'default',
|
||||
material: 'Default Material',
|
||||
delay: 0,
|
||||
spawnInterval: 5,
|
||||
spawnCount: 1,
|
||||
triggers: triggers
|
||||
}
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
for (let i = 0; i < ConveyorEvent.points.length - 1; i++) {
|
||||
const currentPoint = ConveyorEvent.points[i];
|
||||
const nextPoint = ConveyorEvent.points[i + 1];
|
||||
|
||||
if (currentPoint.action.triggers.length > 0) {
|
||||
currentPoint.action.triggers[0].triggeredAsset!.triggeredPoint.pointUuid = nextPoint.uuid;
|
||||
currentPoint.action.triggers[0].triggeredAsset!.triggeredAction!.actionUuid = nextPoint.action.actionUuid;
|
||||
}
|
||||
}
|
||||
addEvent(ConveyorEvent);
|
||||
eventData.points = ConveyorEvent.points.map(point => ({
|
||||
uuid: point.uuid,
|
||||
@@ -228,7 +265,7 @@ async function handleModelLoad(
|
||||
actionType: "travel",
|
||||
unLoadDuration: 5,
|
||||
loadCapacity: 10,
|
||||
steeringAngle:0,
|
||||
steeringAngle: 0,
|
||||
pickUpPoint: null,
|
||||
unLoadPoint: null,
|
||||
triggers: []
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Suspense, useEffect } from "react";
|
||||
import assetImage from "../../assets/image/image.png";
|
||||
import { FiileedStarsIconSmall } from "../../components/icons/marketPlaceIcons";
|
||||
import { FilledStarsIconSmall } from "../../components/icons/marketPlaceIcons";
|
||||
import { Canvas, useThree } from "@react-three/fiber";
|
||||
import { ContactShadows, OrbitControls, Text } from "@react-three/drei";
|
||||
import GltfLoader from "./GltfLoader";
|
||||
@@ -98,7 +98,7 @@ const AssetPreview: React.FC<AssetPreviewProps> = ({
|
||||
</div>
|
||||
<div className="asset-review">
|
||||
<div className="asset-rating">
|
||||
<FiileedStarsIconSmall />
|
||||
<FilledStarsIconSmall />
|
||||
{selectedCard.rating}
|
||||
</div>
|
||||
<div className="asset-view">{selectedCard.views} views</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
CommentsIcon,
|
||||
DownloadIcon,
|
||||
EyeIconBig,
|
||||
FilledStarsIconSmall,
|
||||
StarsIconSmall,
|
||||
VerifiedIcon,
|
||||
} from "../../components/icons/marketPlaceIcons";
|
||||
@@ -80,7 +81,13 @@ const Card: React.FC<CardProps> = ({
|
||||
<div className="stars-container">
|
||||
<div className="stars-wrapper">
|
||||
{[...Array(5)].map((_, index) => (
|
||||
<StarsIconSmall key={index} />
|
||||
<>
|
||||
{index < 3 ? (
|
||||
<FilledStarsIconSmall key={index} />
|
||||
) : (
|
||||
<StarsIconSmall key={index} />
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
<div className="units">
|
||||
|
||||
@@ -9,6 +9,7 @@ import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifie
|
||||
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
|
||||
import { useProductStore } from "../../../../store/simulation/useProductStore";
|
||||
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
|
||||
|
||||
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
|
||||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||
@@ -16,10 +17,28 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
const itemsData = useRef<Types.FloorItems>([]);
|
||||
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
|
||||
const updateBackend = (
|
||||
productName: string,
|
||||
productId: string,
|
||||
organization: string,
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productId: productId,
|
||||
organization: organization,
|
||||
eventDatas: eventData
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!camera || !scene || toggleView || !itemsGroupRef.current) return;
|
||||
|
||||
@@ -190,10 +209,19 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
})
|
||||
}
|
||||
if (productData) {
|
||||
useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
|
||||
const event = useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
|
||||
position: [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
|
||||
})
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productId,
|
||||
organization,
|
||||
event
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,9 +231,6 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
|
||||
//REST
|
||||
|
||||
// await setFloorItemApi(
|
||||
|
||||
@@ -8,6 +8,7 @@ import * as Types from "../../../../types/world/worldTypes";
|
||||
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
|
||||
import { useProductStore } from "../../../../store/simulation/useProductStore";
|
||||
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
|
||||
|
||||
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
|
||||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||
@@ -15,10 +16,28 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
const itemsData = useRef<Types.FloorItems>([]);
|
||||
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
|
||||
const updateBackend = (
|
||||
productName: string,
|
||||
productId: string,
|
||||
organization: string,
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productId: productId,
|
||||
organization: organization,
|
||||
eventDatas: eventData
|
||||
})
|
||||
}
|
||||
|
||||
const prevPointerPosition = useRef<THREE.Vector2 | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -190,10 +209,19 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
})
|
||||
}
|
||||
if (productData) {
|
||||
useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
|
||||
const event = useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
|
||||
position: [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
|
||||
})
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productId,
|
||||
organization,
|
||||
event
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,9 +231,6 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
|
||||
//REST
|
||||
|
||||
// await setFloorItemApi(
|
||||
|
||||
@@ -1,22 +1,29 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import * as THREE from "three";
|
||||
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
|
||||
import useModuleStore from "../../../../../store/useModuleStore";
|
||||
import useModuleStore, { useSubModuleStore } from "../../../../../store/useModuleStore";
|
||||
import { TransformControls } from "@react-three/drei";
|
||||
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
|
||||
import {
|
||||
useSelectedEventSphere,
|
||||
useSelectedEventData,
|
||||
useIsDragging,
|
||||
useIsRotating,
|
||||
} from "../../../../../store/simulation/useSimulationStore";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
|
||||
function PointsCreator() {
|
||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
const transformRef = useRef<any>(null);
|
||||
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||
const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere, } = useSelectedEventSphere();
|
||||
const { selectedEventData, setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
|
||||
const { selectedEventData,setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
|
||||
const { isDragging } = useIsDragging();
|
||||
const { isRotating } = useIsRotating();
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedEventSphere) {
|
||||
@@ -75,6 +82,53 @@ function PointsCreator() {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const canvasElement = gl.domElement;
|
||||
|
||||
let drag = false;
|
||||
let isMouseDown = false;
|
||||
|
||||
const onMouseDown = () => {
|
||||
isMouseDown = true;
|
||||
drag = false;
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
if (selectedEventSphere && !drag) {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersects = raycaster
|
||||
.intersectObjects(scene.children, true)
|
||||
.filter(
|
||||
(intersect) =>
|
||||
intersect.object.name === ('Event-Sphere')
|
||||
);
|
||||
if (intersects.length === 0) {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onMouseMove = () => {
|
||||
if (isMouseDown) {
|
||||
drag = true;
|
||||
}
|
||||
};
|
||||
|
||||
if (subModule === 'mechanics') {
|
||||
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||
}
|
||||
|
||||
return () => {
|
||||
canvasElement.removeEventListener("mousedown", onMouseDown);
|
||||
canvasElement.removeEventListener("mouseup", onMouseUp);
|
||||
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||
};
|
||||
|
||||
}, [gl, subModule, selectedEventSphere]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeModule === "simulation" && (
|
||||
@@ -133,10 +187,6 @@ function PointsCreator() {
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(null);
|
||||
}}
|
||||
position={new THREE.Vector3(...event.point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
|
||||
@@ -1,7 +1,43 @@
|
||||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import MachineInstances from './instances/machineInstances'
|
||||
import { useMachineStore } from '../../../store/simulation/useMachineStore'
|
||||
import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
|
||||
|
||||
function Machine() {
|
||||
const { addMachine, addCurrentAction, removeMachine } = useMachineStore();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
|
||||
const machineSample: MachineEventSchema[] = [
|
||||
{
|
||||
modelUuid: "machine-1234-5678-9012",
|
||||
modelName: "CNC Milling Machine",
|
||||
position: [10, 0, 5],
|
||||
rotation: [0, 0, 0],
|
||||
state: "idle",
|
||||
type: "machine",
|
||||
point: {
|
||||
uuid: "machine-point-9876-5432-1098",
|
||||
position: [10, 0.5, 5.2],
|
||||
rotation: [0, 0, 0],
|
||||
action: {
|
||||
actionUuid: "machine-action-2468-1357-8024",
|
||||
actionName: "Metal Processing",
|
||||
actionType: "process",
|
||||
processTime: 10,
|
||||
swapMaterial: "steel",
|
||||
triggers: []
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
removeMachine(machineSample[0].modelUuid);
|
||||
addMachine(selectedProduct.productId, machineSample[0]);
|
||||
|
||||
// addCurrentAction(machineSample[0].modelUuid, machineSample[0].point.action.actionUuid);
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
|
||||
@@ -53,7 +53,17 @@ function AddOrRemoveEventsInProducts() {
|
||||
const canvasElement = gl.domElement;
|
||||
if (!canvasElement) return;
|
||||
|
||||
let intersects = raycaster.intersectObjects(scene.children, true);
|
||||
const intersects = raycaster
|
||||
.intersectObjects(scene.children, true)
|
||||
.filter(
|
||||
(intersect) =>
|
||||
!intersect.object.name.includes("Roof") &&
|
||||
!intersect.object.name.includes("MeasurementReference") &&
|
||||
!intersect.object.name.includes("agv-collider") &&
|
||||
!(intersect.object.type === "GridHelper") &&
|
||||
!(intersect.object?.parent?.name.includes('zones')) &&
|
||||
!(intersect.object?.parent?.name.includes('Zone'))
|
||||
);
|
||||
if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) {
|
||||
let currentObject = intersects[0].object;
|
||||
|
||||
@@ -116,6 +126,7 @@ function AddOrRemoveEventsInProducts() {
|
||||
};
|
||||
|
||||
}, [gl, subModule, selectedProduct, selectedAsset]);
|
||||
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProd
|
||||
import { getAllProductsApi } from '../../../services/simulation/getallProductsApi';
|
||||
|
||||
function Products() {
|
||||
const { products, addProduct, setProducts } = useProductStore();
|
||||
const { addProduct, setProducts } = useProductStore();
|
||||
const { setSelectedProduct } = useSelectedProduct();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -27,9 +27,6 @@ function Products() {
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
|
||||
@@ -258,6 +258,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
}
|
||||
const logStatus = (id: string, status: string) => {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,7 +23,7 @@ function Simulation() {
|
||||
}, [events])
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('products: ', products);
|
||||
console.log('products: ', products);
|
||||
}, [products])
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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 { useSubModuleStore } from "../../../../store/useModuleStore";
|
||||
import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
|
||||
@@ -7,21 +7,28 @@ 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 { QuadraticBezierLine } from "@react-three/drei";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
|
||||
import { useDeleteTool } from "../../../../store/store";
|
||||
|
||||
interface ConnectionLine {
|
||||
id: string;
|
||||
start: THREE.Vector3;
|
||||
end: THREE.Vector3;
|
||||
mid: THREE.Vector3;
|
||||
startPointUuid: string;
|
||||
endPointUuid: string;
|
||||
trigger: TriggerSchema;
|
||||
}
|
||||
|
||||
function TriggerConnector() {
|
||||
const { gl, raycaster, scene } = useThree();
|
||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, addEvent, getEventByModelUuid } = useProductStore();
|
||||
const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, removeTrigger, addEvent, getEventByModelUuid, getProductById } = useProductStore();
|
||||
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
|
||||
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<{
|
||||
productId: string;
|
||||
@@ -32,52 +39,99 @@ function TriggerConnector() {
|
||||
|
||||
const [connections, setConnections] = useState<ConnectionLine[]>([]);
|
||||
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
|
||||
const updateBackend = (
|
||||
productName: string,
|
||||
productId: string,
|
||||
organization: string,
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productId: productId,
|
||||
organization: organization,
|
||||
eventDatas: eventData
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const newConnections: ConnectionLine[] = [];
|
||||
|
||||
products.forEach(product => {
|
||||
product.eventDatas.forEach(event => {
|
||||
if ('points' in event) {
|
||||
event.points.forEach(point => {
|
||||
if ('action' in point && point.action?.triggers) {
|
||||
point.action.triggers.forEach(trigger => {
|
||||
if (trigger.triggeredAsset) {
|
||||
const targetPoint = getPointByUuid(
|
||||
product.productId,
|
||||
trigger.triggeredAsset.triggeredModel.modelUuid,
|
||||
trigger.triggeredAsset.triggeredPoint.pointUuid
|
||||
);
|
||||
const product = getProductById(selectedProduct.productId);
|
||||
if (!product || products.length === 0) return;
|
||||
|
||||
if (targetPoint) {
|
||||
const startPos = new THREE.Vector3(...point.position);
|
||||
const endPos = new THREE.Vector3(...targetPoint.position);
|
||||
const midPos = new THREE.Vector3()
|
||||
.addVectors(startPos, endPos)
|
||||
.multiplyScalar(0.5)
|
||||
.add(new THREE.Vector3(0, 2, 0));
|
||||
|
||||
newConnections.push({
|
||||
id: `${point.uuid}-${targetPoint.uuid}-${trigger.triggerUuid}`,
|
||||
start: startPos,
|
||||
end: endPos,
|
||||
mid: midPos,
|
||||
trigger
|
||||
});
|
||||
}
|
||||
}
|
||||
product.eventDatas.forEach(event => {
|
||||
// Handle Conveyor points
|
||||
if (event.type === "transfer" && 'points' in event) {
|
||||
event.points.forEach(point => {
|
||||
if (point.action?.triggers) {
|
||||
point.action.triggers.forEach(trigger => {
|
||||
if (trigger.triggeredAsset) {
|
||||
newConnections.push({
|
||||
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||
startPointUuid: point.uuid,
|
||||
endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||
trigger
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// Handle Vehicle point
|
||||
else if (event.type === "vehicle" && 'point' in event) {
|
||||
const point = event.point;
|
||||
if (point.action?.triggers) {
|
||||
point.action.triggers.forEach(trigger => {
|
||||
if (trigger.triggeredAsset) {
|
||||
newConnections.push({
|
||||
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||
startPointUuid: point.uuid,
|
||||
endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||
trigger
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// Handle Robotic Arm points
|
||||
else if (event.type === "roboticArm" && 'point' in event) {
|
||||
const point = event.point;
|
||||
point.actions?.forEach(action => {
|
||||
action.triggers?.forEach(trigger => {
|
||||
if (trigger.triggeredAsset) {
|
||||
newConnections.push({
|
||||
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||
startPointUuid: point.uuid,
|
||||
endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||
trigger
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
// Handle Machine point
|
||||
else if (event.type === "machine" && 'point' in event) {
|
||||
const point = event.point;
|
||||
if (point.action?.triggers) {
|
||||
point.action.triggers.forEach(trigger => {
|
||||
if (trigger.triggeredAsset) {
|
||||
newConnections.push({
|
||||
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||
startPointUuid: point.uuid,
|
||||
endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||
trigger
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setConnections(newConnections);
|
||||
}, [products]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('connections: ', connections);
|
||||
}, connections)
|
||||
}, [products, selectedProduct.productId]);
|
||||
|
||||
useEffect(() => {
|
||||
const canvasElement = gl.domElement;
|
||||
@@ -111,15 +165,31 @@ function TriggerConnector() {
|
||||
if (drag) return;
|
||||
evt.preventDefault();
|
||||
|
||||
const intersects = raycaster.intersectObjects(scene.children, true);
|
||||
if (intersects.length === 0) return;
|
||||
const intersects = raycaster
|
||||
.intersectObjects(scene.children, true)
|
||||
.filter(
|
||||
(intersect) =>
|
||||
intersect.object.name === ('Event-Sphere')
|
||||
);
|
||||
if (intersects.length === 0) {
|
||||
setFirstSelectedPoint(null);
|
||||
return;
|
||||
};
|
||||
|
||||
const currentObject = intersects[0].object;
|
||||
if (!currentObject || currentObject.name !== 'Event-Sphere') return;
|
||||
if (!currentObject || currentObject.name !== 'Event-Sphere') {
|
||||
setFirstSelectedPoint(null);
|
||||
return;
|
||||
};
|
||||
|
||||
const modelUuid = currentObject.userData.modelUuid;
|
||||
const pointUuid = currentObject.userData.pointUuid;
|
||||
|
||||
if (firstSelectedPoint && firstSelectedPoint.pointUuid === pointUuid) {
|
||||
setFirstSelectedPoint(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedProduct && getIsEventInProduct(selectedProduct.productId, modelUuid)) {
|
||||
|
||||
const point = getPointByUuid(
|
||||
@@ -128,7 +198,12 @@ function TriggerConnector() {
|
||||
pointUuid
|
||||
);
|
||||
|
||||
if (!point) return;
|
||||
const event = getEventByModelUuid(selectedProduct.productId, modelUuid);
|
||||
|
||||
if (!point || !event) {
|
||||
setFirstSelectedPoint(null);
|
||||
return;
|
||||
};
|
||||
|
||||
let actionUuid: string | undefined;
|
||||
if ('action' in point && point.action) {
|
||||
@@ -152,12 +227,12 @@ function TriggerConnector() {
|
||||
delay: 0,
|
||||
triggeredAsset: {
|
||||
triggeredModel: {
|
||||
modelName: currentObject.parent?.parent?.name || 'Unknown',
|
||||
modelName: event.modelName || 'Unknown',
|
||||
modelUuid: modelUuid
|
||||
},
|
||||
triggeredPoint: {
|
||||
pointName: currentObject.name,
|
||||
pointUuid: pointUuid
|
||||
pointName: 'Point',
|
||||
pointUuid: point.uuid
|
||||
},
|
||||
triggeredAction: actionUuid ? {
|
||||
actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action',
|
||||
@@ -167,7 +242,16 @@ function TriggerConnector() {
|
||||
};
|
||||
|
||||
if (firstSelectedPoint.actionUuid) {
|
||||
addTrigger(firstSelectedPoint.actionUuid, trigger);
|
||||
const event = addTrigger(selectedProduct.productId, firstSelectedPoint.actionUuid, trigger);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productId,
|
||||
organization,
|
||||
event
|
||||
);
|
||||
}
|
||||
}
|
||||
setFirstSelectedPoint(null);
|
||||
}
|
||||
@@ -184,7 +268,12 @@ function TriggerConnector() {
|
||||
pointUuid
|
||||
);
|
||||
|
||||
if (!point) return;
|
||||
const event = getEventByModelUuid(selectedProduct.productId, modelUuid);
|
||||
|
||||
if (!point || !event) {
|
||||
setFirstSelectedPoint(null);
|
||||
return;
|
||||
};
|
||||
|
||||
let actionUuid: string | undefined;
|
||||
if ('action' in point && point.action) {
|
||||
@@ -200,12 +289,12 @@ function TriggerConnector() {
|
||||
delay: 0,
|
||||
triggeredAsset: {
|
||||
triggeredModel: {
|
||||
modelName: currentObject.parent?.parent?.name || 'Unknown',
|
||||
modelName: event.modelName || 'Unknown',
|
||||
modelUuid: modelUuid
|
||||
},
|
||||
triggeredPoint: {
|
||||
pointName: currentObject.name,
|
||||
pointUuid: pointUuid
|
||||
pointName: 'Point',
|
||||
pointUuid: point.uuid
|
||||
},
|
||||
triggeredAction: actionUuid ? {
|
||||
actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action',
|
||||
@@ -215,13 +304,24 @@ function TriggerConnector() {
|
||||
};
|
||||
|
||||
if (firstSelectedPoint.actionUuid) {
|
||||
addTrigger(firstSelectedPoint.actionUuid, trigger);
|
||||
const event = addTrigger(selectedProduct.productId, firstSelectedPoint.actionUuid, trigger);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productId,
|
||||
organization,
|
||||
event
|
||||
);
|
||||
}
|
||||
}
|
||||
setFirstSelectedPoint(null);
|
||||
} else if (firstSelectedPoint) {
|
||||
setFirstSelectedPoint(null);
|
||||
}
|
||||
};
|
||||
|
||||
if (subModule === 'simulations') {
|
||||
if (subModule === 'simulations' && !deleteTool) {
|
||||
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||
@@ -235,11 +335,149 @@ function TriggerConnector() {
|
||||
canvasElement.removeEventListener('contextmenu', handleRightClick);
|
||||
};
|
||||
|
||||
}, [gl, subModule, selectedProduct, firstSelectedPoint]);
|
||||
}, [gl, subModule, selectedProduct, firstSelectedPoint, deleteTool]);
|
||||
|
||||
|
||||
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.parent?.name.includes("Zone") &&
|
||||
!(intersect.object.type === "GridHelper") &&
|
||||
!(intersect.object.type === "Line2")
|
||||
);
|
||||
|
||||
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'));
|
||||
|
||||
if (sphereIntersects.length > 0 && sphereIntersects[0].object.uuid === firstSelectedPoint.pointUuid) {
|
||||
setHelperLineColor('red');
|
||||
setCurrentLine(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const startPoint = getWorldPositionFromScene(firstSelectedPoint.pointUuid);
|
||||
|
||||
if (point && startPoint) {
|
||||
if (sphereIntersects.length > 0) {
|
||||
point = sphereIntersects[0].object.getWorldPosition(new THREE.Vector3());
|
||||
}
|
||||
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
|
||||
);
|
||||
|
||||
const endPoint = point;
|
||||
|
||||
setCurrentLine({
|
||||
start: startPoint,
|
||||
mid: midPoint,
|
||||
end: endPoint,
|
||||
});
|
||||
|
||||
setHelperLineColor(sphereIntersects.length > 0 ? "#6cf542" : "red");
|
||||
} else {
|
||||
setCurrentLine(null);
|
||||
}
|
||||
} else {
|
||||
setCurrentLine(null);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const getWorldPositionFromScene = (pointUuid: string): THREE.Vector3 | null => {
|
||||
const pointObj = scene.getObjectByProperty("uuid", pointUuid);
|
||||
if (!pointObj) return null;
|
||||
|
||||
const worldPosition = new THREE.Vector3();
|
||||
pointObj.getWorldPosition(worldPosition);
|
||||
return worldPosition;
|
||||
};
|
||||
|
||||
const removeConnection = (connection: ConnectionLine) => {
|
||||
if (connection.trigger.triggerUuid) {
|
||||
const event = removeTrigger(selectedProduct.productId, connection.trigger.triggerUuid);
|
||||
if (event) {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productId,
|
||||
organization,
|
||||
event
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
</>
|
||||
<group name="simulationConnectionGroup" >
|
||||
{connections.map((connection) => {
|
||||
const startPoint = getWorldPositionFromScene(connection.startPointUuid);
|
||||
const endPoint = getWorldPositionFromScene(connection.endPointUuid);
|
||||
|
||||
if (!startPoint || !endPoint) return null;
|
||||
|
||||
const distance = startPoint.distanceTo(endPoint);
|
||||
const heightFactor = Math.max(0.5, distance * 0.2);
|
||||
const midPoint = new THREE.Vector3(
|
||||
(startPoint.x + endPoint.x) / 2,
|
||||
Math.max(startPoint.y, endPoint.y) + heightFactor,
|
||||
(startPoint.z + endPoint.z) / 2
|
||||
);
|
||||
|
||||
return (
|
||||
<QuadraticBezierLine
|
||||
key={connection.id}
|
||||
ref={(el) => (groupRefs.current[connection.id] = el!)}
|
||||
start={startPoint.toArray()}
|
||||
end={endPoint.toArray()}
|
||||
mid={midPoint.toArray()}
|
||||
color={deleteTool && hoveredLineKey === connection.id ? "red" : "#42a5f5"}
|
||||
lineWidth={4}
|
||||
dashed={deleteTool && hoveredLineKey === connection.id ? false : true}
|
||||
dashSize={0.75}
|
||||
dashScale={20}
|
||||
onPointerOver={() => setHoveredLineKey(connection.id)}
|
||||
onPointerOut={() => setHoveredLineKey(null)}
|
||||
onClick={() => {
|
||||
if (deleteTool) {
|
||||
setHoveredLineKey(null);
|
||||
setCurrentLine(null);
|
||||
removeConnection(connection);
|
||||
}
|
||||
}}
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
import startPoint from "../../../../assets/gltf-glb/arrow_green.glb";
|
||||
import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
|
||||
import * as THREE from "three";
|
||||
import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
|
||||
import { useGLTF } from '@react-three/drei';
|
||||
import { useFrame, useThree } from '@react-three/fiber';
|
||||
import { useSelectedEventSphere } from '../../../../store/simulation/useSimulationStore';
|
||||
import { useSelectedEventSphere, useIsDragging, useIsRotating } from '../../../../store/simulation/useSimulationStore';
|
||||
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
|
||||
import { upsertProductOrEventApi } from '../../../../services/simulation/UpsertProductOrEventApi';
|
||||
|
||||
const VehicleUI = () => {
|
||||
const { scene: startScene } = useGLTF(startPoint) as any;
|
||||
const { scene: endScene } = useGLTF(startEnd) as any;
|
||||
@@ -14,67 +18,60 @@ const VehicleUI = () => {
|
||||
const endMarker = useRef<THREE.Group>(null);
|
||||
const prevMousePos = useRef({ x: 0, y: 0 });
|
||||
const { selectedEventSphere } = useSelectedEventSphere();
|
||||
const { vehicles, updateVehicle } = useVehicleStore();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const { getVehicleById } = useVehicleStore();
|
||||
const { updateEvent } = useProductStore();
|
||||
const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 0, 0]);
|
||||
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 0, 0]);
|
||||
const [startRotation, setStartRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||
const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||
const [isDragging, setIsDragging] = useState<"start" | "end" | null>(null);
|
||||
const [isRotating, setIsRotating] = useState<"start" | "end" | null>(null);
|
||||
const { isDragging, setIsDragging } = useIsDragging();
|
||||
const { isRotating, setIsRotating } = useIsRotating();
|
||||
const { raycaster } = useThree();
|
||||
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
|
||||
const state: Types.ThreeState = useThree();
|
||||
const controls: any = state.controls;
|
||||
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
|
||||
const updateBackend = (
|
||||
productName: string,
|
||||
productId: string,
|
||||
organization: string,
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productId: productId,
|
||||
organization: organization,
|
||||
eventDatas: eventData
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedEventSphere) return;
|
||||
const selectedVehicle = vehicles.find(
|
||||
(vehicle: any) => vehicle.modelUuid === selectedEventSphere.userData.modelUuid
|
||||
);
|
||||
const selectedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid);
|
||||
|
||||
if (selectedVehicle?.point?.action) {
|
||||
const { pickUpPoint, unLoadPoint } = selectedVehicle.point.action;
|
||||
|
||||
if (pickUpPoint) {
|
||||
const pickupPosition = new THREE.Vector3(
|
||||
pickUpPoint.position.x,
|
||||
pickUpPoint.position.y,
|
||||
pickUpPoint.position.z
|
||||
);
|
||||
const pickupRotation = new THREE.Vector3(
|
||||
pickUpPoint.rotation.x,
|
||||
pickUpPoint.rotation.y,
|
||||
pickUpPoint.rotation.z
|
||||
);
|
||||
pickupPosition.y = 0;
|
||||
setStartPosition([pickupPosition.x, 0, pickupPosition.z]);
|
||||
setStartRotation([pickupRotation.x, pickupRotation.y, pickupRotation.z]);
|
||||
setStartPosition([pickUpPoint.position.x, 0, pickUpPoint.position.z]);
|
||||
setStartRotation([pickUpPoint.rotation.x, pickUpPoint.rotation.y, pickUpPoint.rotation.z]);
|
||||
} else {
|
||||
const defaultLocal = new THREE.Vector3(0, 0, 1.5);
|
||||
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
|
||||
defaultWorld.y = 0;
|
||||
setStartPosition([defaultWorld.x, 0, defaultWorld.z]);
|
||||
setStartRotation([0, 0, 0]);
|
||||
}
|
||||
|
||||
if (unLoadPoint) {
|
||||
const unLoadPosition = new THREE.Vector3(
|
||||
unLoadPoint.position.x,
|
||||
unLoadPoint.position.y,
|
||||
unLoadPoint.position.z
|
||||
);
|
||||
const unLoadRotation = new THREE.Vector3(
|
||||
unLoadPoint.rotation.x,
|
||||
unLoadPoint.rotation.y,
|
||||
unLoadPoint.position.z
|
||||
);
|
||||
unLoadPosition.y = 0; // Force y to 0
|
||||
setEndPosition([unLoadPosition.x, 0, unLoadPosition.z]);
|
||||
setEndRotation([unLoadRotation.x, unLoadRotation.y, unLoadRotation.z]);
|
||||
setEndPosition([unLoadPoint.position.x, 0, unLoadPoint.position.z]);
|
||||
setEndRotation([unLoadPoint.rotation.x, unLoadPoint.rotation.y, unLoadPoint.rotation.z]);
|
||||
} else {
|
||||
const defaultLocal = new THREE.Vector3(0, 0, -1.5);
|
||||
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
|
||||
defaultWorld.y = 0; // Force y to 0
|
||||
setEndPosition([defaultWorld.x, 0, defaultWorld.z]);
|
||||
setEndRotation([0, 0, 0]);
|
||||
}
|
||||
@@ -87,7 +84,6 @@ const VehicleUI = () => {
|
||||
const intersects = raycaster.ray.intersectPlane(plane.current, intersectPoint);
|
||||
|
||||
if (intersects) {
|
||||
intersectPoint.y = 0; // Force y to 0
|
||||
if (isDragging === "start") {
|
||||
setStartPosition([intersectPoint.x, 0, intersectPoint.z]);
|
||||
}
|
||||
@@ -108,12 +104,12 @@ const VehicleUI = () => {
|
||||
|
||||
if (marker) {
|
||||
const rotationSpeed = 10;
|
||||
marker.rotation.y += deltaX * rotationSpeed;
|
||||
if (isRotating === 'start') {
|
||||
setStartRotation([marker.rotation.x, marker.rotation.y, marker.rotation.z])
|
||||
const y = startRotation[1] + deltaX * rotationSpeed;
|
||||
setStartRotation([0, y, 0]);
|
||||
} else {
|
||||
|
||||
setEndRotation([marker.rotation.x, marker.rotation.y, marker.rotation.z])
|
||||
const y = endRotation[1] + deltaX * rotationSpeed;
|
||||
setEndRotation([0, y, 0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -142,43 +138,34 @@ const VehicleUI = () => {
|
||||
setIsRotating(null);
|
||||
|
||||
if (selectedEventSphere?.userData.modelUuid) {
|
||||
const updatedVehicle = vehicles.find(
|
||||
(vehicle) => vehicle.modelUuid === selectedEventSphere.userData.modelUuid
|
||||
);
|
||||
const updatedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid);
|
||||
|
||||
if (updatedVehicle) {
|
||||
updateVehicle(selectedEventSphere.userData.modelUuid, {
|
||||
const event = updateEvent(selectedProduct.productId, selectedEventSphere.userData.modelUuid, {
|
||||
point: {
|
||||
...updatedVehicle.point,
|
||||
action: {
|
||||
...updatedVehicle.point?.action,
|
||||
pickUpPoint: {
|
||||
position: {
|
||||
x: startPosition[0],
|
||||
y: startPosition[1],
|
||||
z: startPosition[2],
|
||||
},
|
||||
rotation: {
|
||||
x: startRotation[0],
|
||||
y: startRotation[1],
|
||||
z: startRotation[2],
|
||||
},
|
||||
position: { x: startPosition[0], y: startPosition[1], z: startPosition[2], },
|
||||
rotation: { x: 0, y: startRotation[1], z: 0, },
|
||||
},
|
||||
unLoadPoint: {
|
||||
position: {
|
||||
x: endPosition[0],
|
||||
y: endPosition[1],
|
||||
z: endPosition[2],
|
||||
},
|
||||
rotation: {
|
||||
x: endRotation[0],
|
||||
y: endRotation[1],
|
||||
z: endRotation[2],
|
||||
},
|
||||
position: { x: endPosition[0], y: endPosition[1], z: endPosition[2], },
|
||||
rotation: { x: 0, y: endRotation[1], z: 0, },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productId,
|
||||
organization,
|
||||
event
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -208,6 +195,7 @@ const VehicleUI = () => {
|
||||
object={startScene}
|
||||
ref={startMarker}
|
||||
position={startPosition}
|
||||
rotation={startRotation}
|
||||
onPointerDown={(e: any) => {
|
||||
e.stopPropagation();
|
||||
handlePointerDown(e, "start", "start");
|
||||
@@ -224,6 +212,7 @@ const VehicleUI = () => {
|
||||
object={endScene}
|
||||
ref={endMarker}
|
||||
position={endPosition}
|
||||
rotation={endRotation}
|
||||
onPointerDown={(e: any) => {
|
||||
e.stopPropagation();
|
||||
handlePointerDown(e, "end", "end");
|
||||
|
||||
@@ -11,7 +11,7 @@ interface VehicleAnimatorProps {
|
||||
reset: () => void;
|
||||
currentPhase: string;
|
||||
agvUuid: number;
|
||||
agvDetail: any;
|
||||
agvDetail: VehicleStatus;
|
||||
}
|
||||
|
||||
function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) {
|
||||
@@ -32,7 +32,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
||||
let startTime: number;
|
||||
let fixedInterval: number;
|
||||
let coveredDistance = progressRef.current;
|
||||
let objectRotation = (agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) as { x: number; y: number; z: number };
|
||||
let objectRotation = (agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) as { x: number; y: number; z: number } | undefined;
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
@@ -67,10 +67,9 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
||||
setRestingRotation(true);
|
||||
decrementVehicleLoad(agvDetail.modelUuid, 0);
|
||||
const object = scene.getObjectByProperty('uuid', agvUuid);
|
||||
console.log('currentPhase: ', currentPhase);
|
||||
if (object) {
|
||||
object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]);
|
||||
object.rotation.set(objectRotation.x, objectRotation.y, objectRotation.z);
|
||||
object.rotation.set(agvDetail.rotation[0], agvDetail.rotation[1], agvDetail.rotation[2]);
|
||||
}
|
||||
}
|
||||
}, [isReset, isPlaying])
|
||||
@@ -132,7 +131,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
||||
}
|
||||
|
||||
if (progressRef.current >= totalDistance) {
|
||||
if (restRotation) {
|
||||
if (restRotation && objectRotation) {
|
||||
const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(objectRotation.x, objectRotation.y, objectRotation.z));
|
||||
object.quaternion.slerp(targetQuaternion, delta * 2);
|
||||
const angleDiff = object.quaternion.angleTo(targetQuaternion);
|
||||
|
||||
@@ -30,7 +30,8 @@ function VehicleInstance({ agvDetail }: any) {
|
||||
);
|
||||
|
||||
function vehicleStatus(modelId: string, status: string) {
|
||||
// console.log(`${modelId} , ${status});
|
||||
// console.log(`${modelId} , ${status}`);
|
||||
|
||||
}
|
||||
|
||||
// Function to reset everything
|
||||
@@ -44,7 +45,7 @@ function VehicleInstance({ agvDetail }: any) {
|
||||
const increment = () => {
|
||||
if (isIncrememtable.current) {
|
||||
|
||||
incrementVehicleLoad(agvDetail.modelUuid, 2);
|
||||
incrementVehicleLoad(agvDetail.modelUuid, 10);
|
||||
isIncrememtable.current = false;
|
||||
}
|
||||
}
|
||||
@@ -69,6 +70,7 @@ function VehicleInstance({ agvDetail }: any) {
|
||||
increment();
|
||||
}, 5000);
|
||||
|
||||
|
||||
if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity) {
|
||||
const toDrop = computePath(
|
||||
agvDetail.point.action.pickUpPoint.position,
|
||||
|
||||
@@ -1,220 +1,48 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import VehicleInstances from "./instances/vehicleInstances";
|
||||
import { useVehicleStore } from "../../../store/simulation/useVehicleStore";
|
||||
import { useFloorItems } from "../../../store/store";
|
||||
import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
||||
import { useSelectedEventData, useSelectedEventSphere, useSelectedProduct } from "../../../store/simulation/useSimulationStore";
|
||||
import VehicleUI from "../ui/vehicle/vehicleUI";
|
||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||
function Vehicles() {
|
||||
import { useProductStore } from "../../../store/simulation/useProductStore";
|
||||
|
||||
const { vehicles, addVehicle } = useVehicleStore();
|
||||
function Vehicles() {
|
||||
const { products, getProductById } = useProductStore();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const { vehicles, addVehicle, clearvehicles } = useVehicleStore();
|
||||
const { selectedEventSphere } = useSelectedEventSphere();
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { floorItems } = useFloorItems();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
|
||||
const [vehicleStatusSample, setVehicleStatusSample] = useState<
|
||||
VehicleEventSchema[]
|
||||
>([
|
||||
{
|
||||
modelUuid: "9356f710-4727-4b50-bdb2-9c1e747ecc74",
|
||||
modelName: "AGV",
|
||||
position: [97.9252965204558, 0, 37.96138815638661],
|
||||
rotation: [0, 0, 0],
|
||||
state: "idle",
|
||||
type: "vehicle",
|
||||
speed: 2.5,
|
||||
point: {
|
||||
uuid: "point-789",
|
||||
position: [0, 1, 0],
|
||||
rotation: [0, 0, 0],
|
||||
action: {
|
||||
actionUuid: "action-456",
|
||||
actionName: "Deliver to Zone A",
|
||||
actionType: "travel",
|
||||
unLoadDuration: 10,
|
||||
loadCapacity: 2,
|
||||
steeringAngle:0,
|
||||
pickUpPoint: { position: { x: 98.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } },
|
||||
unLoadPoint: { position: { x: 105.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } },
|
||||
triggers: [
|
||||
{
|
||||
triggerUuid: "trig-001",
|
||||
triggerName: "Start Travel",
|
||||
triggerType: "onComplete",
|
||||
delay: 0,
|
||||
triggeredAsset: {
|
||||
triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
|
||||
triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
|
||||
triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
|
||||
}
|
||||
},
|
||||
{
|
||||
triggerUuid: "trig-002",
|
||||
triggerName: "Complete Travel",
|
||||
triggerType: "onComplete",
|
||||
delay: 2,
|
||||
triggeredAsset: null
|
||||
}
|
||||
]
|
||||
}
|
||||
useEffect(() => {
|
||||
if (selectedProduct.productId) {
|
||||
const product = getProductById(selectedProduct.productId);
|
||||
if (product) {
|
||||
clearvehicles();
|
||||
product.eventDatas.forEach(events => {
|
||||
if (events.type === 'vehicle') {
|
||||
addVehicle(selectedProduct.productId, events);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
modelUuid: "b06960bb-3d2e-41f7-a646-335f389c68b4",
|
||||
modelName: "AGV",
|
||||
position: [89.61609306554463, 0, 33.634136622267356],
|
||||
rotation: [0, 0, 0],
|
||||
state: "idle",
|
||||
type: "vehicle",
|
||||
speed: 2.5,
|
||||
point: {
|
||||
uuid: "point-789",
|
||||
position: [0, 1, 0],
|
||||
rotation: [0, 0, 0],
|
||||
action: {
|
||||
actionUuid: "action-456",
|
||||
actionName: "Deliver to Zone A",
|
||||
actionType: "travel",
|
||||
unLoadDuration: 10,
|
||||
loadCapacity: 2,
|
||||
steeringAngle:0,
|
||||
pickUpPoint: null,
|
||||
unLoadPoint: null,
|
||||
triggers: [
|
||||
{
|
||||
triggerUuid: "trig-001",
|
||||
triggerName: "Start Travel",
|
||||
triggerType: "onStart",
|
||||
delay: 0,
|
||||
triggeredAsset: {
|
||||
triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
|
||||
triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
|
||||
triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
|
||||
}
|
||||
},
|
||||
{
|
||||
triggerUuid: "trig-002",
|
||||
triggerName: "Complete Travel",
|
||||
triggerType: "onComplete",
|
||||
delay: 2,
|
||||
triggeredAsset: null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
// {
|
||||
// modelUuid: "cd7d0584-0684-42b4-b051-9e882c1914aa",
|
||||
// modelName: "AGV",
|
||||
// position: [105.90938758014703, 0, 31.584209911095215],
|
||||
// rotation: [0, 0, 0],
|
||||
// state: "idle",
|
||||
// type: "vehicle",
|
||||
// speed: 2.5,
|
||||
// point: {
|
||||
// uuid: "point-789",
|
||||
// position: [0, 1, 0],
|
||||
// rotation: [0, 0, 0],
|
||||
// action: {
|
||||
// actionUuid: "action-456",
|
||||
// actionName: "Deliver to Zone A",
|
||||
// actionType: "travel",
|
||||
// unLoadDuration: 10,
|
||||
// loadCapacity: 2,
|
||||
// steeringAngle:0,
|
||||
// pickUpPoint: null,
|
||||
// unLoadPoint: null,
|
||||
// triggers: [
|
||||
// {
|
||||
// triggerUuid: "trig-001",
|
||||
// triggerName: "Start Travel",
|
||||
// triggerType: "onStart",
|
||||
// delay: 0,
|
||||
// triggeredAsset: {
|
||||
// triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
|
||||
// triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
|
||||
// triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// triggerUuid: "trig-002",
|
||||
// triggerName: "Complete Travel",
|
||||
// triggerType: "onComplete",
|
||||
// delay: 2,
|
||||
// triggeredAsset: null
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79",
|
||||
// modelName: "forklift",
|
||||
// position: [98.85729337188162, 0, 38.36616546567653],
|
||||
// rotation: [0, 0, 0],
|
||||
// state: "idle",
|
||||
// type: "vehicle",
|
||||
// speed: 2.5,
|
||||
// point: {
|
||||
// uuid: "point-789",
|
||||
// position: [0, 1, 0],
|
||||
// rotation: [0, 0, 0],
|
||||
// action: {
|
||||
// actionUuid: "action-456",
|
||||
// actionName: "Deliver to Zone A",
|
||||
// actionType: "travel",
|
||||
// unLoadDuration: 15,
|
||||
// loadCapacity: 5,
|
||||
// steeringAngle:0,
|
||||
// pickUpPoint: null,
|
||||
// unLoadPoint: null,
|
||||
// triggers: [
|
||||
// {
|
||||
// triggerUuid: "trig-001",
|
||||
// triggerName: "Start Travel",
|
||||
// triggerType: "onStart",
|
||||
// delay: 0,
|
||||
// triggeredAsset: {
|
||||
// triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
|
||||
// triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
|
||||
// triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// triggerUuid: "trig-002",
|
||||
// triggerName: "Complete Travel",
|
||||
// triggerType: "onComplete",
|
||||
// delay: 2,
|
||||
// triggeredAsset: null
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
]);
|
||||
}
|
||||
}, [selectedProduct, products]);
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('vehicles: ', vehicles);
|
||||
}, [vehicles])
|
||||
|
||||
useEffect(() => {
|
||||
addVehicle("123", vehicleStatusSample[0]);
|
||||
addVehicle('123', vehicleStatusSample[1]);
|
||||
// addVehicle('123', vehicleStatusSample[2]);
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<VehicleInstances />
|
||||
|
||||
{selectedEventSphere && selectedEventData?.data.type === "vehicle" && !isPlaying &&
|
||||
< VehicleUI />
|
||||
}
|
||||
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Vehicles;
|
||||
|
||||
|
||||
|
||||
export default Vehicles;
|
||||
@@ -11,10 +11,7 @@ import {
|
||||
useDroppedObjectsStore,
|
||||
useFloatingWidget,
|
||||
} from "../../store/visualization/useDroppedObjectsStore";
|
||||
import {
|
||||
useSocketStore,
|
||||
useWidgetSubOption,
|
||||
} from "../../store/store";
|
||||
import { useSocketStore, useWidgetSubOption } from "../../store/store";
|
||||
import { getZone2dData } from "../../services/visulization/zone/getZoneData";
|
||||
import { generateUniqueId } from "../../functions/generateUniqueId";
|
||||
import { determinePosition } from "./functions/determinePosition";
|
||||
@@ -76,6 +73,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||
const { widgetSubOption } = useWidgetSubOption();
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
const { setSelectedChartId } = useWidgetStore();
|
||||
const [waitingPanels, setWaitingPanels] = useState(null);
|
||||
|
||||
OuterClick({
|
||||
contextClassName: [
|
||||
@@ -377,6 +375,8 @@ const RealTimeVisulization: React.FC = () => {
|
||||
setHiddenPanels={setHiddenPanels}
|
||||
selectedZone={selectedZone}
|
||||
setSelectedZone={setSelectedZone}
|
||||
waitingPanels={waitingPanels}
|
||||
setWaitingPanels={setWaitingPanels}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -385,6 +385,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||
setSelectedZone={setSelectedZone}
|
||||
hiddenPanels={hiddenPanels}
|
||||
setZonesData={setZonesData}
|
||||
waitingPanels={waitingPanels}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
CleanPannel,
|
||||
EyeIcon,
|
||||
@@ -6,8 +6,6 @@ import {
|
||||
} from "../../../../components/icons/RealTimeVisulationIcons";
|
||||
import { AddIcon } from "../../../../components/icons/ExportCommonIcons";
|
||||
import { useSocketStore } from "../../../../store/store";
|
||||
import { clearPanel } from "../../../../services/visulization/zone/clearPanel";
|
||||
import { lockPanel } from "../../../../services/visulization/zone/lockPanel";
|
||||
|
||||
// Define the type for `Side`
|
||||
type Side = "top" | "bottom" | "left" | "right";
|
||||
@@ -57,6 +55,8 @@ interface ButtonsProps {
|
||||
>;
|
||||
hiddenPanels: HiddenPanels; // Updated prop type
|
||||
setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type
|
||||
waitingPanels: any;
|
||||
setWaitingPanels: any;
|
||||
}
|
||||
|
||||
const AddButtons: React.FC<ButtonsProps> = ({
|
||||
@@ -64,6 +64,8 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||
setSelectedZone,
|
||||
setHiddenPanels,
|
||||
hiddenPanels,
|
||||
waitingPanels,
|
||||
setWaitingPanels,
|
||||
}) => {
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
|
||||
@@ -174,65 +176,62 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||
|
||||
// Function to handle "+" button click
|
||||
const handlePlusButtonClick = async (side: Side) => {
|
||||
const zoneId = selectedZone.zoneId;
|
||||
|
||||
if (selectedZone.activeSides.includes(side)) {
|
||||
console.log("open");
|
||||
// Panel already exists: Remove widgets from that side and update activeSides
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
|
||||
// Already active: Schedule removal
|
||||
|
||||
// Remove all widgets associated with the side and update active sides
|
||||
const cleanedWidgets = selectedZone.widgets.filter(
|
||||
(widget) => widget.panel !== side
|
||||
);
|
||||
const newActiveSides = selectedZone.activeSides.filter((s) => s !== side);
|
||||
setWaitingPanels(side); // Mark as waiting
|
||||
|
||||
const updatedZone = {
|
||||
...selectedZone,
|
||||
widgets: cleanedWidgets,
|
||||
activeSides: newActiveSides,
|
||||
panelOrder: newActiveSides,
|
||||
};
|
||||
setTimeout(() => {
|
||||
console.log("Removing after wait...");
|
||||
|
||||
let deletePanel = {
|
||||
organization: organization,
|
||||
panelName: side,
|
||||
zoneId: selectedZone.zoneId,
|
||||
};
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-panel:delete", deletePanel);
|
||||
}
|
||||
setSelectedZone(updatedZone);
|
||||
|
||||
if (hiddenPanels[selectedZone.zoneId]?.includes(side)) {
|
||||
setHiddenPanels((prev) => ({
|
||||
...prev,
|
||||
[selectedZone.zoneId]: prev[selectedZone.zoneId].filter(
|
||||
(s) => s !== side
|
||||
),
|
||||
}));
|
||||
}
|
||||
|
||||
// if(hiddenPanels[selectedZone.zoneId].includes(side))
|
||||
|
||||
// API call to delete the panel
|
||||
// try {
|
||||
// const response = await deletePanelApi(selectedZone.zoneId, side, organization);
|
||||
//
|
||||
// if (response.message === "Panel deleted successfully") {
|
||||
// } else {
|
||||
//
|
||||
// }
|
||||
// } catch (error) {
|
||||
//
|
||||
// }
|
||||
} else {
|
||||
// Panel does not exist: Create panel
|
||||
try {
|
||||
// Get email and organization safely with a default fallback
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
const organization = email?.split("@")[1]?.split(".")[0] || "";
|
||||
|
||||
// Remove widgets for that side
|
||||
const cleanedWidgets = selectedZone.widgets.filter(
|
||||
(widget) => widget.panel !== side
|
||||
);
|
||||
const newActiveSides = selectedZone.activeSides.filter(
|
||||
(s) => s !== side
|
||||
);
|
||||
|
||||
const updatedZone = {
|
||||
...selectedZone,
|
||||
widgets: cleanedWidgets,
|
||||
activeSides: newActiveSides,
|
||||
panelOrder: newActiveSides,
|
||||
};
|
||||
|
||||
const deletePanel = {
|
||||
organization,
|
||||
panelName: side,
|
||||
zoneId,
|
||||
};
|
||||
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-panel:delete", deletePanel);
|
||||
}
|
||||
|
||||
setSelectedZone(updatedZone);
|
||||
|
||||
if (hiddenPanels[zoneId]?.includes(side)) {
|
||||
setHiddenPanels((prev) => ({
|
||||
...prev,
|
||||
[zoneId]: prev[zoneId].filter((s) => s !== side),
|
||||
}));
|
||||
}
|
||||
|
||||
// Remove from waiting state
|
||||
setWaitingPanels(null);
|
||||
}, 500); // Wait for 2 seconds
|
||||
} else {
|
||||
// Panel does not exist: Add it
|
||||
try {
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0] || "";
|
||||
|
||||
// Prevent duplicate side entries
|
||||
const newActiveSides = selectedZone.activeSides.includes(side)
|
||||
? [...selectedZone.activeSides]
|
||||
: [...selectedZone.activeSides, side];
|
||||
@@ -242,32 +241,31 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||
activeSides: newActiveSides,
|
||||
panelOrder: newActiveSides,
|
||||
};
|
||||
let addPanel = {
|
||||
organization: organization,
|
||||
zoneId: selectedZone.zoneId,
|
||||
|
||||
const addPanel = {
|
||||
organization,
|
||||
zoneId,
|
||||
panelOrder: newActiveSides,
|
||||
};
|
||||
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-panel:add", addPanel);
|
||||
}
|
||||
setSelectedZone(updatedZone);
|
||||
// API call to create panels
|
||||
// const response = await panelData(organization, selectedZone.zoneId, newActiveSides);
|
||||
//
|
||||
|
||||
// if (response.message === "Panels created successfully") {
|
||||
// } else {
|
||||
//
|
||||
// }
|
||||
} catch (error) {}
|
||||
setSelectedZone(updatedZone);
|
||||
} catch (error) {
|
||||
console.error("Error adding panel:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
|
||||
<div key={side} className={`side-button-container ${side}`}>
|
||||
{/* "+" Button */}
|
||||
|
||||
<button
|
||||
className={`side-button ${side}${
|
||||
selectedZone.activeSides.includes(side) ? " active" : ""
|
||||
@@ -286,7 +284,17 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||
|
||||
{/* Extra Buttons */}
|
||||
{selectedZone.activeSides.includes(side) && (
|
||||
<div className="extra-Bs">
|
||||
<div
|
||||
className={`extra-Bs
|
||||
${waitingPanels === side ? "extra-Bs-addclosing" : ""}
|
||||
${
|
||||
!hiddenPanels[selectedZone.zoneId]?.includes(side) &&
|
||||
waitingPanels !== side
|
||||
? "extra-Bs-addopening"
|
||||
: ""
|
||||
}
|
||||
`}
|
||||
>
|
||||
{/* Hide Panel */}
|
||||
<div
|
||||
className={`icon ${
|
||||
@@ -305,7 +313,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||
fill={
|
||||
hiddenPanels[selectedZone.zoneId]?.includes(side)
|
||||
? "var(--icon-default-color-active)"
|
||||
: "var(--icon-default-color)"
|
||||
: "var(--text-color)"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
@@ -342,7 +350,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||
fill={
|
||||
selectedZone.lockedPanels.includes(side)
|
||||
? "var(--icon-default-color-active)"
|
||||
: "var(--icon-default-color)"
|
||||
: "var(--text-color)"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -43,6 +43,7 @@ interface PanelProps {
|
||||
>;
|
||||
hiddenPanels: any;
|
||||
setZonesData: React.Dispatch<React.SetStateAction<any>>;
|
||||
waitingPanels: any;
|
||||
}
|
||||
|
||||
const generateUniqueId = () =>
|
||||
@@ -53,6 +54,7 @@ const Panel: React.FC<PanelProps> = ({
|
||||
setSelectedZone,
|
||||
hiddenPanels,
|
||||
setZonesData,
|
||||
waitingPanels,
|
||||
}) => {
|
||||
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
|
||||
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
|
||||
@@ -108,8 +110,9 @@ const Panel: React.FC<PanelProps> = ({
|
||||
case "bottom":
|
||||
return {
|
||||
minWidth: "170px",
|
||||
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
||||
}px)`,
|
||||
width: `calc(100% - ${
|
||||
(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
|
||||
}px)`,
|
||||
minHeight: "170px",
|
||||
height: `${panelSize}px`,
|
||||
left: leftActive ? `${panelSize}px` : "0",
|
||||
@@ -122,8 +125,9 @@ const Panel: React.FC<PanelProps> = ({
|
||||
minWidth: "170px",
|
||||
width: `${panelSize}px`,
|
||||
minHeight: "170px",
|
||||
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
||||
}px)`,
|
||||
height: `calc(100% - ${
|
||||
(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
|
||||
}px)`,
|
||||
top: topActive ? `${panelSize}px` : "0",
|
||||
bottom: bottomActive ? `${panelSize}px` : "0",
|
||||
[side]: "0",
|
||||
@@ -149,7 +153,6 @@ const Panel: React.FC<PanelProps> = ({
|
||||
const currentWidgetsCount = getCurrentWidgetCount(panel);
|
||||
const maxCapacity = calculatePanelCapacity(panel);
|
||||
|
||||
|
||||
if (currentWidgetsCount < maxCapacity) {
|
||||
addWidgetToPanel(draggedAsset, panel);
|
||||
}
|
||||
@@ -283,8 +286,9 @@ const Panel: React.FC<PanelProps> = ({
|
||||
<div
|
||||
key={side}
|
||||
id="panel-wrapper"
|
||||
className={`panel ${side}-panel absolute ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : ""
|
||||
}`}
|
||||
className={`panel ${side}-panel absolute ${
|
||||
hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : ""
|
||||
}`}
|
||||
style={getPanelStyle(side)}
|
||||
onDrop={(e) => handleDrop(e, side)}
|
||||
onDragOver={(e) => e.preventDefault()}
|
||||
@@ -297,11 +301,18 @@ const Panel: React.FC<PanelProps> = ({
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`panel-content ${isPlaying && "fullScreen"}`}
|
||||
className={`panel-content
|
||||
${waitingPanels === side ? `${side}-closing` : ""}
|
||||
${
|
||||
!hiddenPanels[selectedZone.zoneId]?.includes(side) && waitingPanels !== side
|
||||
? `${side}-opening`
|
||||
: ""
|
||||
}
|
||||
${isPlaying ? "fullScreen" : ""}`}
|
||||
style={{
|
||||
pointerEvents:
|
||||
selectedZone.lockedPanels.includes(side) ||
|
||||
hiddenPanels[selectedZone.zoneId]?.includes(side)
|
||||
hiddenPanels[selectedZone.zoneId]?.includes(side)
|
||||
? "none"
|
||||
: "auto",
|
||||
opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
|
||||
|
||||
Reference in New Issue
Block a user