added zone socket collab response

This commit is contained in:
2025-09-26 14:01:40 +05:30
parent 614c265071
commit 36623d1053
14 changed files with 560 additions and 254 deletions

View File

@@ -260,10 +260,10 @@ function FloorCreator() {
},
],
});
setTempPoints([]);
setIsCreating(false);
}
setTempPoints([]);
setIsCreating(false);
}
};

View File

@@ -10,6 +10,7 @@ import { useSelectedPoints } from "../../../../store/simulation/useSimulationSto
import useWallAssetResponseHandler from "../../../collaboration/responseHandler/useWallAssetResponseHandler";
import useWallResponseHandler from "../../../collaboration/responseHandler/useWallResponseHandler";
import useFloorResponseHandler from "../../../collaboration/responseHandler/useFloorResponseHandler";
import useZoneResponseHandler from "../../../collaboration/responseHandler/useZoneResponseHandler";
import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
import { deleteWallApi } from "../../../../services/factoryBuilder/wall/deleteWallApi";
@@ -40,10 +41,11 @@ export function useLineEventHandler({ points }: Readonly<LineProps>) {
const { getWallAssetsByWall } = wallAssetStore();
const { peekRemoveWallByPoints, setPosition: setWallPosition, getWallByPoints, getConnectedWallsByWallId } = wallStore();
const { peekRemoveFloorByPoints, setPosition: setFloorPosition, getFloorsByPointId, getFloorsByPoints } = floorStore();
const { removeZoneByPoints, setPosition: setZonePosition, getZonesByPointId, getZonesByPoints } = zoneStore();
const { peekRemoveZoneByPoints, setPosition: setZonePosition, getZonesByPointId, getZonesByPoints } = zoneStore();
const { updateWallAssetInScene, removeWallAssetFromScene } = useWallAssetResponseHandler();
const { updateWallInScene, removeWallFromScene } = useWallResponseHandler();
const { updateFloorInScene, removeFloorFromScene } = useFloorResponseHandler();
const { updateZoneInScene, removeZoneFromScene } = useZoneResponseHandler();
const { selectedVersion } = versionStore();
const { hoveredLine, setHoveredLine, hoveredPoint } = useBuilderStore();
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
@@ -311,7 +313,23 @@ export function useLineEventHandler({ points }: Readonly<LineProps>) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone);
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedZone, () => {
echo.info(`Updated zone: ${updatedZone.zoneName}`);
});
} else {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
});
} else {
// SOCKET
@@ -564,19 +582,35 @@ export function useLineEventHandler({ points }: Readonly<LineProps>) {
}
if (points[0].pointType === "Zone" && points[1].pointType === "Zone") {
const Zones = getZonesByPoints(points);
const { removedZones, updatedZones } = removeZoneByPoints(points);
const { removedZones, updatedZones } = peekRemoveZoneByPoints(points);
if (removedZones.length > 0) {
removedZones.forEach((zone) => {
removedZones.forEach((removedZone) => {
if (projectId) {
if (!builderSocket?.connected) {
// API
deleteZoneApi(projectId, selectedVersion?.versionId || "", zone.zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || "", removedZone.zoneUuid)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error removing zone`);
return;
}
if (data.message === "Zone Deleted Successfully") {
removeZoneFromScene(removedZone.zoneUuid, () => {
echo.info(`Removed zone: ${removedZone.zoneName}`);
});
} else {
echo.error(`Error removing zone: ${removedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error removing zone: ${removedZone.zoneName}`);
});
} else {
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
zoneUuid: removedZone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,
@@ -605,17 +639,33 @@ export function useLineEventHandler({ points }: Readonly<LineProps>) {
});
}
if (updatedZones.length > 0) {
updatedZones.forEach((zone) => {
updatedZones.forEach((updatedZone) => {
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedZone, () => {
echo.info(`Updated zone: ${updatedZone.zoneName}`);
});
} else {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
});
} else {
// SOCKET
const data = {
zoneData: zone,
zoneData: updatedZone,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,

View File

@@ -12,6 +12,7 @@ import useWallAssetResponseHandler from "../../../collaboration/responseHandler/
import useWallResponseHandler from "../../../collaboration/responseHandler/useWallResponseHandler";
import useAisleResponseHandler from "../../../collaboration/responseHandler/useAisleResponseHandler";
import useFloorResponseHandler from "../../../collaboration/responseHandler/useFloorResponseHandler";
import useZoneResponseHandler from "../../../collaboration/responseHandler/useZoneResponseHandler";
import { upsertAisleApi } from "../../../../services/factoryBuilder/aisle/upsertAisleApi";
import { deleteAisleApi } from "../../../../services/factoryBuilder/aisle/deleteAisleApi";
@@ -44,10 +45,11 @@ export function usePointEventHandler({ point }: { point: Point }) {
const { updateWallInScene, removeWallFromScene } = useWallResponseHandler();
const { updateAisleInScene, removeAisleFromScene } = useAisleResponseHandler();
const { updateFloorInScene, removeFloorFromScene } = useFloorResponseHandler();
const { updateZoneInScene, removeZoneFromScene } = useZoneResponseHandler();
const { setPosition: setAislePosition, peekRemovePoint: peekRemoveAislePoint, getAislesByPointId } = aisleStore();
const { setPosition: setWallPosition, peekRemovePoint: peekRemoveWallPoint, getWallsByPointId } = wallStore();
const { setPosition: setFloorPosition, peekRemovePoint: peekRemoveFloorPoint, getFloorsByPointId } = floorStore();
const { setPosition: setZonePosition, removePoint: removeZonePoint, getZonesByPointId } = zoneStore();
const { setPosition: setZonePosition, peekRemovePoint: peekRemoveZonePoint, getZonesByPointId } = zoneStore();
const { selectedVersion } = versionStore();
const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle, snapFloorPoint, snapFloorAngle, snapZonePoint, snapZoneAngle } = usePointSnapping({
uuid: point.pointUuid,
@@ -362,7 +364,23 @@ export function usePointEventHandler({ point }: { point: Point }) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone);
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedZone, () => {
echo.info(`Updated zone: ${updatedZone.zoneName}`);
});
} else {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
});
} else {
// SOCKET
@@ -683,20 +701,36 @@ export function usePointEventHandler({ point }: { point: Point }) {
}
if (point.pointType === "Zone") {
const Zones = getZonesByPointId(point.pointUuid);
const { removedZones, updatedZones } = removeZonePoint(point.pointUuid);
const { removedZones, updatedZones } = peekRemoveZonePoint(point.pointUuid);
setHoveredPoint(null);
if (removedZones.length > 0) {
removedZones.forEach((zone) => {
removedZones.forEach((removedZone) => {
if (projectId) {
if (!builderSocket?.connected) {
// API
deleteZoneApi(projectId, selectedVersion?.versionId || "", zone.zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || "", removedZone.zoneUuid)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error removing zone`);
return;
}
if (data.message === "Zone Deleted Successfully") {
removeZoneFromScene(removedZone.zoneUuid, () => {
echo.info(`Removed zone: ${removedZone.zoneName}`);
});
} else {
echo.error(`Error removing zone: ${removedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error removing zone: ${removedZone.zoneName}`);
});
} else {
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
zoneUuid: removedZone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,
@@ -725,17 +759,33 @@ export function usePointEventHandler({ point }: { point: Point }) {
});
}
if (updatedZones.length > 0) {
updatedZones.forEach((zone) => {
updatedZones.forEach((updatedZone) => {
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedZone, () => {
echo.info(`Updated zone: ${updatedZone.zoneName}`);
});
} else {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
});
} else {
// SOCKET
const data = {
zoneData: zone,
zoneData: updatedZone,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,

View File

@@ -9,6 +9,7 @@ import { useParams } from "react-router-dom";
import { getUserData } from "../../../../functions/getUserData";
import ReferencePoint from "../../point/reference/referencePoint";
import ReferenceZone from "./referenceZone";
import useZoneResponseHandler from "../../../collaboration/responseHandler/useZoneResponseHandler";
import getCenteroidPoint from "../../functions/getCenteroid";
import generateUniqueZoneName from "../functions/generateUniqueZoneName";
@@ -23,7 +24,8 @@ function ZoneCreator() {
const { activeLayer } = useActiveLayer();
const { builderSocket } = useSocketStore();
const { zoneStore, undoRedo2DStore, versionStore } = useSceneContext();
const { addZone, getZonePointById, zones } = zoneStore();
const { zones } = zoneStore();
const { addZoneToScene, removeZoneFromScene } = useZoneResponseHandler();
const { push2D } = undoRedo2DStore();
const drag = useRef(false);
const isLeftMouseDown = useRef(false);
@@ -57,6 +59,55 @@ function ZoneCreator() {
}
};
const addZoneToBackend = (zone: Zone) => {
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zone)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error adding or updating zone`);
setTempPoints([]);
setIsCreating(false);
return;
}
if (data.message === "Zone Created Successfully") {
addZoneToScene(zone, () => {
echo.info(`Added zone: ${zone.zoneName}`);
});
} else {
removeZoneFromScene(zone.zoneUuid, () => {
echo.error(`Error adding or updating zone: ${zone.zoneName}`);
setTempPoints([]);
setIsCreating(false);
});
}
})
.catch(() => {
echo.error(`Error adding or updating zone: ${zone.zoneName}`);
setTempPoints([]);
setIsCreating(false);
});
} else {
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
};
builderSocket.emit("v1:zone:add", data);
setTempPoints([]);
setIsCreating(false);
}
}
};
const onMouseClick = () => {
if (drag.current || !toggleView) return;
@@ -113,7 +164,7 @@ function ZoneCreator() {
viewPortTarget: viewPortPosition ? [viewPortPosition.x, 0, viewPortPosition.y] : [0, 0, 0],
};
addZone(zone);
addZoneToBackend(zone);
push2D({
type: "Draw",
@@ -129,25 +180,6 @@ function ZoneCreator() {
],
});
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
};
builderSocket.emit("v1:zone:add", data);
}
}
setTempPoints([]);
setIsCreating(false);
} else if (isCreating && snappedPoint && !tempPoints.some((p) => p.pointUuid === snappedPoint.pointUuid)) {
@@ -169,7 +201,7 @@ function ZoneCreator() {
viewPortTarget: viewPortPosition ? [viewPortPosition.x, 0, viewPortPosition.y] : [0, 0, 0],
};
addZone(zone);
addZoneToBackend(zone);
push2D({
type: "Draw",
@@ -185,25 +217,6 @@ function ZoneCreator() {
],
});
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
};
builderSocket.emit("v1:zone:add", data);
}
}
setTempPoints([]);
setIsCreating(false);
} else if (tempPoints.length === 0 || (tempPoints.length > 1 && !tempPoints.slice(1).some((p) => p.pointUuid === pointIntersects.object.uuid))) {
@@ -234,7 +247,7 @@ function ZoneCreator() {
viewPortTarget: viewPortPosition ? [viewPortPosition.x, 0, viewPortPosition.y] : [0, 0, 0],
};
addZone(zone);
addZoneToBackend(zone);
push2D({
type: "Draw",
@@ -249,27 +262,8 @@ function ZoneCreator() {
},
],
});
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
};
builderSocket.emit("v1:zone:add", data);
}
}
}
setTempPoints([]);
setIsCreating(false);
}
@@ -302,26 +296,7 @@ function ZoneCreator() {
canvasElement.removeEventListener("click", onMouseClick);
canvasElement.removeEventListener("contextmenu", onContext);
};
}, [
gl,
camera,
scene,
raycaster,
plane,
toggleView,
toolMode,
activeLayer,
builderSocket,
tempPoints,
isCreating,
zones,
addZone,
getZonePointById,
zoneColor,
zoneHeight,
snappedPosition,
snappedPoint,
]);
}, [gl, camera, raycaster, plane, toggleView, toolMode, activeLayer, builderSocket, tempPoints, isCreating, zones, zoneColor, zoneHeight, snappedPosition, snappedPoint]);
return (
<>

View File

@@ -7,6 +7,7 @@ import useWallAssetResponseHandler from "../responseHandler/useWallAssetResponse
import useWallResponseHandler from "../responseHandler/useWallResponseHandler";
import useAisleResponseHandler from "../responseHandler/useAisleResponseHandler";
import useFloorResponseHandler from "../responseHandler/useFloorResponseHandler";
import useZoneResponseHandler from "../responseHandler/useZoneResponseHandler";
function BuilderResponses() {
const { assetStore } = useSceneContext();
@@ -18,6 +19,7 @@ function BuilderResponses() {
const { addWallToScene, updateWallInScene, removeWallFromScene } = useWallResponseHandler();
const { addAisleToScene, updateAisleInScene, removeAisleFromScene } = useAisleResponseHandler();
const { addFloorToScene, updateFloorInScene, removeFloorFromScene } = useFloorResponseHandler();
const { addZoneToScene, updateZoneInScene, removeZoneFromScene } = useZoneResponseHandler();
//#region Asset
useEffect(() => {
@@ -478,15 +480,60 @@ function BuilderResponses() {
if (!builderSocket) return;
builderSocket.on("v1:zone:response:updates", (data: any) => {
if (!data.message) return;
if (data.message === "zone created successfully") {
} else if (data.message === "zone updated") {
if (!data.message || !data.data) {
echo.error(`Error adding or updating zone`);
return;
}
if (data.message === "Zone Created Successfully") {
const zone: Zone = {
zoneUuid: data.data.zoneUuid,
zoneName: data.data.zoneName,
zoneHeight: data.data.zoneHeight,
zoneColor: data.data.zoneColor,
points: data.data.points,
viewPortPosition: data.data.viewPortPosition,
viewPortTarget: data.data.viewPortTarget,
};
addZoneToScene(zone, () => {
echo.info(`Added zone: ${zone.zoneName}`);
});
} else if (data.message === "Zone Updated Successfully") {
const zone: Zone = {
zoneUuid: data.data.zoneUuid,
zoneName: data.data.zoneName,
zoneHeight: data.data.zoneHeight,
zoneColor: data.data.zoneColor,
points: data.data.points,
viewPortPosition: data.data.viewPortPosition,
viewPortTarget: data.data.viewPortTarget,
};
updateZoneInScene(zone, () => {
// if (selectedZone?.zoneData.zoneUuid === zone.zoneUuid) {
// setSelectedZone({ zoneData: zone, zoneMesh: selectedZone.zoneMesh });
// }
echo.info(`Updated zone: ${zone.zoneName}`);
});
} else {
removeZoneFromScene(data.data.zoneUuid, () => {
echo.error(`Error adding or updating zone: ${data?.data?.zoneName}`);
});
}
});
builderSocket.on("v1:zone:response:delete", (data: any) => {
if (!data.message) return;
if (data.message === "zone deleted created successfully") {
if (!data.message || !data.data) {
echo.error(`Error deleting zone`);
return;
}
if (data.message === "Zone Deleted Successfully") {
removeZoneFromScene(data.data.zoneUuid, () => {
echo.info(`Removed zone: ${data.data.zoneName}`);
});
} else {
echo.error(`Error removing zone: ${data?.data?.zoneName}`);
}
});

View File

@@ -10,6 +10,7 @@ import { useSceneStore } from "../../../store/scene/useSceneStore";
import CamMode from "../camera/camMode";
import SwitchView from "../camera/switchView";
import SyncCam from "../camera/syncCam";
// import GizmoControls from "./gizmoControls/gizmoControls";
import ContextControls from "./contextControls/contextControls";
import SelectionControls2D from "./selectionControls/selection2D/selectionControls2D";
import SelectionControls3D from "./selectionControls/selection3D/selectionControls3D";
@@ -166,7 +167,9 @@ export default function Controls() {
</CameraControls>
{/* 3D */}
{/* <GizmoControls /> */}
<SelectionControls3D />
<MoveControls3D />
@@ -180,7 +183,7 @@ export default function Controls() {
<ScaleControls3D />
<TransformControls3D />
{/* 2D */}
<SelectionControls2D />

View File

@@ -2,20 +2,14 @@ import { useEffect, useRef } from "react";
import { useThree, useFrame } from "@react-three/fiber";
import { ViewportGizmo } from "three-viewport-gizmo";
import { PerspectiveCamera, WebGLRenderer, Scene } from "three";
import { CameraControls } from "@react-three/drei";
type Controls = {
enabled: boolean;
setPosition: (...args: number[]) => void;
getTarget: (target: any) => void;
addEventListener: (type: string, listener: (...args: any[]) => void) => void;
};
export const Gizmo = () => {
const GizmoControls = () => {
const { camera, gl, scene, controls } = useThree<{
camera: PerspectiveCamera;
gl: WebGLRenderer;
scene: Scene;
controls?: Controls;
controls: CameraControls;
}>();
const gizmoRef = useRef<ViewportGizmo | null>(null);
@@ -23,6 +17,7 @@ export const Gizmo = () => {
useEffect(() => {
const gizmo = new ViewportGizmo(camera, gl, {});
gizmoRef.current = gizmo;
gizmoRef.current.renderOrder = 2;
const resize = () => {
const width = window.innerWidth;
@@ -65,3 +60,5 @@ export const Gizmo = () => {
return null;
};
export default GizmoControls;

View File

@@ -21,6 +21,7 @@ import useWallAssetResponseHandler from "../../../collaboration/responseHandler/
import useWallResponseHandler from "../../../collaboration/responseHandler/useWallResponseHandler";
import useAisleResponseHandler from "../../../collaboration/responseHandler/useAisleResponseHandler";
import useFloorResponseHandler from "../../../collaboration/responseHandler/useFloorResponseHandler";
import useZoneResponseHandler from "../../../collaboration/responseHandler/useZoneResponseHandler";
function MoveControls2D({ movedObjects, setMovedObjects, pastedObjects, setPastedObjects, duplicatedObjects, setDuplicatedObjects, rotatedObjects, setRotatedObjects }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
@@ -39,6 +40,7 @@ function MoveControls2D({ movedObjects, setMovedObjects, pastedObjects, setPaste
const { updateWallInScene } = useWallResponseHandler();
const { updateAisleInScene } = useAisleResponseHandler();
const { updateFloorInScene } = useFloorResponseHandler();
const { updateZoneInScene } = useZoneResponseHandler();
const { push2D } = undoRedo2DStore();
const { setPosition: setAislePosition, getAislesByPointId, getAisleById } = aisleStore();
const { setPosition: setWallPosition, getWallsByPointId, getWallById } = wallStore();
@@ -458,7 +460,23 @@ function MoveControls2D({ movedObjects, setMovedObjects, pastedObjects, setPaste
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone);
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedZone, () => {
echo.info(`Updated zone: ${updatedZone.zoneName}`);
});
} else {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
});
} else {
// SOCKET

View File

@@ -16,6 +16,7 @@ import useWallAssetResponseHandler from "../../../../collaboration/responseHandl
import useWallResponseHandler from "../../../../collaboration/responseHandler/useWallResponseHandler";
import useAisleResponseHandler from "../../../../collaboration/responseHandler/useAisleResponseHandler";
import useFloorResponseHandler from "../../../../collaboration/responseHandler/useFloorResponseHandler";
import useZoneResponseHandler from "../../../../collaboration/responseHandler/useZoneResponseHandler";
import MoveControls2D from "../../pointControls/moveControls2D";
import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
@@ -48,6 +49,7 @@ const SelectionControls2D: React.FC = () => {
const { removeWallFromScene } = useWallResponseHandler();
const { removeAisleFromScene } = useAisleResponseHandler();
const { removeFloorFromScene, updateFloorInScene } = useFloorResponseHandler();
const { removeZoneFromScene, updateZoneInScene } = useZoneResponseHandler();
const { push2D } = undoRedo2DStore();
const { peekRemovePoint: peekRemoveAislePoint } = aisleStore();
const { peekRemovePoint: peekRemoveWallPoint } = wallStore();
@@ -371,17 +373,33 @@ const SelectionControls2D: React.FC = () => {
const Zones = getZonesByPointId(point.pointUuid);
const { removedZones, updatedZones } = removeZonePoint(point.pointUuid);
if (removedZones.length > 0) {
removedZones.forEach((zone) => {
removedZones.forEach((removedZone) => {
if (projectId) {
if (!builderSocket?.connected) {
// API
deleteZoneApi(projectId, selectedVersion?.versionId || "", zone.zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || "", removedZone.zoneUuid)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error removing zone`);
return;
}
if (data.message === "Zone Deleted Successfully") {
removeZoneFromScene(removedZone.zoneUuid, () => {
echo.info(`Removed zone: ${removedZone.zoneName}`);
});
} else {
echo.error(`Error removing zone: ${removedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error removing zone: ${removedZone.zoneName}`);
});
} else {
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
zoneUuid: removedZone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,
@@ -402,17 +420,33 @@ const SelectionControls2D: React.FC = () => {
processedZones.push(...removedZonesData);
}
if (updatedZones.length > 0) {
updatedZones.forEach((zone) => {
updatedZones.forEach((updatedZone) => {
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedZone, () => {
echo.info(`Updated zone: ${updatedZone.zoneName}`);
});
} else {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedZone.zoneName}`);
});
} else {
// SOCKET
const data = {
zoneData: zone,
zoneData: updatedZone,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,

View File

@@ -5,6 +5,7 @@ import { useSocketStore } from "../../../../../store/socket/useSocketStore";
import useWallResponseHandler from "../../../../collaboration/responseHandler/useWallResponseHandler";
import useAisleResponseHandler from "../../../../collaboration/responseHandler/useAisleResponseHandler";
import useFloorResponseHandler from "../../../../collaboration/responseHandler/useFloorResponseHandler";
import useZoneResponseHandler from "../../../../collaboration/responseHandler/useZoneResponseHandler";
import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
@@ -19,12 +20,12 @@ import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/ups
import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
function use2DRedoHandler() {
const { undoRedo2DStore, zoneStore, versionStore } = useSceneContext();
const { undoRedo2DStore, versionStore } = useSceneContext();
const { redo2D, peekRedo2D } = undoRedo2DStore();
const { addWallToScene, removeWallFromScene, updateWallInScene } = useWallResponseHandler();
const { addAisleToScene, removeAisleFromScene, updateAisleInScene } = useAisleResponseHandler();
const { addFloorToScene, removeFloorFromScene, updateFloorInScene } = useFloorResponseHandler();
const { addZone, removeZone, updateZone } = zoneStore();
const { addZoneToScene, removeZoneFromScene, updateZoneInScene } = useZoneResponseHandler();
const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -241,19 +242,19 @@ function use2DRedoHandler() {
upsertFloorApi(projectId, selectedVersion?.versionId || "", floorData)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error adding floor`);
echo.error(`Error adding floor: ${floorData.floorName}`);
return;
}
if (data.message === "Floor Created Successfully") {
addFloorToScene(floorData, () => {
echo.info(`Added floor: ${floorData.floorUuid}`);
echo.info(`Added floor: ${floorData.floorName}`);
});
} else {
echo.error(`Error adding floor: ${floorData.floorUuid}`);
echo.error(`Error adding floor: ${floorData.floorName}`);
}
})
.catch(() => {
echo.error(`Error adding floor: ${floorData.floorUuid}`);
echo.error(`Error adding floor: ${floorData.floorName}`);
});
} else {
// SOCKET
@@ -279,7 +280,7 @@ function use2DRedoHandler() {
deleteFloorApi(projectId, selectedVersion?.versionId || "", floorUuid)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error removing floor`);
echo.error(`Error removing floor: ${floorUuid}`);
return;
}
if (data.message === "Floor Deleted Successfully") {
@@ -317,17 +318,17 @@ function use2DRedoHandler() {
upsertFloorApi(projectId, selectedVersion?.versionId || "", updatedData)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating floor`);
echo.error(`Error updating floor: ${updatedData.floorName}`);
return;
}
if (data.message === "Floor Updated Successfully") {
updateFloorInScene(updatedData, () => {
echo.info(`Updated floor: ${floorUuid}`);
echo.info(`Updated floor: ${updatedData.floorName}`);
});
}
})
.catch(() => {
echo.error(`Error updating floor: ${floorUuid}`);
echo.error(`Error updating floor: ${updatedData.floorName}`);
});
} else {
// SOCKET
@@ -346,12 +347,27 @@ function use2DRedoHandler() {
};
const createZoneFromBackend = (zoneData: Zone) => {
addZone(zoneData);
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zoneData);
upsertZoneApi(projectId, selectedVersion?.versionId || "", zoneData)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error adding zone: ${zoneData.zoneName}`);
return;
}
if (data.message === "Zone Created Successfully") {
addZoneToScene(zoneData, () => {
echo.info(`Added zone: ${zoneData.zoneName}`);
});
} else {
echo.error(`Error adding zone: ${zoneData.zoneName}`);
}
})
.catch(() => {
echo.error(`Error adding zone: ${zoneData.zoneName}`);
});
} else {
// SOCKET
@@ -369,12 +385,27 @@ function use2DRedoHandler() {
};
const removeZoneFromBackend = (zoneUuid: string) => {
removeZone(zoneUuid);
if (projectId) {
if (!builderSocket?.connected) {
// API
deleteZoneApi(projectId, selectedVersion?.versionId || "", zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || "", zoneUuid)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error removing zone: ${zoneUuid}`);
return;
}
if (data.message === "Zone Deleted Successfully") {
removeZoneFromScene(zoneUuid, () => {
echo.info(`Removed zone: ${zoneUuid}`);
});
} else {
echo.error(`Error removing zone: ${zoneUuid}`);
}
})
.catch(() => {
echo.error(`Error removing zone: ${zoneUuid}`);
});
} else {
// SOCKET
@@ -392,12 +423,25 @@ function use2DRedoHandler() {
};
const updateZoneFromBackend = (zoneUuid: string, updatedData: Zone) => {
updateZone(zoneUuid, updatedData);
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedData);
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedData)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedData.zoneName}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedData, () => {
echo.info(`Updated zone: ${updatedData.zoneName}`);
});
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedData.zoneName}`);
});
} else {
// SOCKET

View File

@@ -5,6 +5,7 @@ import { useSocketStore } from "../../../../../store/socket/useSocketStore";
import useWallResponseHandler from "../../../../collaboration/responseHandler/useWallResponseHandler";
import useAisleResponseHandler from "../../../../collaboration/responseHandler/useAisleResponseHandler";
import useFloorResponseHandler from "../../../../collaboration/responseHandler/useFloorResponseHandler";
import useZoneResponseHandler from "../../../../collaboration/responseHandler/useZoneResponseHandler";
import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
@@ -19,12 +20,12 @@ import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/ups
import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
function use2DUndoHandler() {
const { undoRedo2DStore, zoneStore, versionStore } = useSceneContext();
const { undoRedo2DStore, versionStore } = useSceneContext();
const { undo2D, peekUndo2D } = undoRedo2DStore();
const { addWallToScene, removeWallFromScene, updateWallInScene } = useWallResponseHandler();
const { addAisleToScene, removeAisleFromScene, updateAisleInScene } = useAisleResponseHandler();
const { addFloorToScene, removeFloorFromScene, updateFloorInScene } = useFloorResponseHandler();
const { addZone, removeZone, updateZone } = zoneStore();
const { addZoneToScene, removeZoneFromScene, updateZoneInScene } = useZoneResponseHandler();
const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -240,19 +241,19 @@ function use2DUndoHandler() {
upsertFloorApi(projectId, selectedVersion?.versionId || "", floorData)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error adding floor`);
echo.error(`Error adding floor: ${floorData.floorName}`);
return;
}
if (data.message === "Floor Created Successfully") {
addFloorToScene(floorData, () => {
echo.info(`Added floor: ${floorData.floorUuid}`);
echo.info(`Added floor: ${floorData.floorName}`);
});
} else {
echo.error(`Error adding floor: ${floorData.floorUuid}`);
echo.error(`Error adding floor: ${floorData.floorName}`);
}
})
.catch(() => {
echo.error(`Error adding floor: ${floorData.floorUuid}`);
echo.error(`Error adding floor: ${floorData.floorName}`);
});
} else {
// SOCKET
@@ -265,7 +266,6 @@ function use2DUndoHandler() {
organization: organization,
};
console.log('data: ', data);
builderSocket.emit("v1:model-Floor:add", data);
}
}
@@ -279,7 +279,7 @@ function use2DUndoHandler() {
deleteFloorApi(projectId, selectedVersion?.versionId || "", floorUuid)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error removing floor`);
echo.error(`Error removing floor: ${floorUuid}`);
return;
}
if (data.message === "Floor Deleted Successfully") {
@@ -317,17 +317,17 @@ function use2DUndoHandler() {
upsertFloorApi(projectId, selectedVersion?.versionId || "", updatedData)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating floor`);
echo.error(`Error updating floor: ${updatedData.floorName}`);
return;
}
if (data.message === "Floor Updated Successfully") {
updateFloorInScene(updatedData, () => {
echo.info(`Updated floor: ${updatedData.floorUuid}`);
echo.info(`Updated floor: ${updatedData.floorName}`);
});
}
})
.catch(() => {
echo.error(`Error updating floor: ${updatedData.floorUuid}`);
echo.error(`Error updating floor: ${updatedData.floorName}`);
});
} else {
// SOCKET
@@ -346,12 +346,27 @@ function use2DUndoHandler() {
};
const createZoneToBackend = (zoneData: Zone) => {
addZone(zoneData);
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", zoneData);
upsertZoneApi(projectId, selectedVersion?.versionId || "", zoneData)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error adding zone: ${zoneData.zoneName}`);
return;
}
if (data.message === "Zone Created Successfully") {
addZoneToScene(zoneData, () => {
echo.info(`Added zone: ${zoneData.zoneName}`);
});
} else {
echo.error(`Error adding zone: ${zoneData.zoneName}`);
}
})
.catch(() => {
echo.error(`Error adding zone: ${zoneData.zoneName}`);
});
} else {
// SOCKET
@@ -369,12 +384,27 @@ function use2DUndoHandler() {
};
const removeZoneToBackend = (zoneUuid: string) => {
removeZone(zoneUuid);
if (projectId) {
if (!builderSocket?.connected) {
// API
deleteZoneApi(projectId, selectedVersion?.versionId || "", zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || "", zoneUuid)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error removing zone: ${zoneUuid}`);
return;
}
if (data.message === "Zone Deleted Successfully") {
removeZoneFromScene(zoneUuid, () => {
echo.info(`Removed zone: ${zoneUuid}`);
});
} else {
echo.error(`Error removing zone: ${zoneUuid}`);
}
})
.catch(() => {
echo.error(`Error removing zone: ${zoneUuid}`);
});
} else {
// SOCKET
@@ -392,12 +422,25 @@ function use2DUndoHandler() {
};
const updateZoneToBackend = (zoneUuid: string, updatedData: Zone) => {
updateZone(zoneUuid, updatedData);
if (projectId) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedData);
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedData)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedData.zoneName}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedData, () => {
echo.info(`Updated zone: ${updatedData.zoneName}`);
});
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedData.zoneName}`);
});
} else {
// SOCKET

View File

@@ -7,9 +7,7 @@ type OnUpdateCallback = (object: THREE.Object3D) => void;
export default function useDraggableGLTF(onUpdate: OnUpdateCallback) {
const { camera, gl, controls, scene } = useThree();
const activeObjRef = useRef<THREE.Object3D | null>(null);
const planeRef = useRef<THREE.Plane>(
new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)
);
const planeRef = useRef<THREE.Plane>(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
const offsetRef = useRef<THREE.Vector3>(new THREE.Vector3());
const initialPositionRef = useRef<THREE.Vector3>(new THREE.Vector3());
@@ -80,22 +78,14 @@ export default function useDraggableGLTF(onUpdate: OnUpdateCallback) {
// Add offset for dragging
intersection.add(offsetRef.current);
console.log('intersection: ', intersection);
// Get the parent's world matrix if exists
const parent = activeObjRef.current.parent;
const targetPosition = new THREE.Vector3();
if (isShiftKeyPressed) {
console.log('isShiftKeyPressed: ', isShiftKeyPressed);
// For Y-axis only movement, maintain original X and Z
console.log('initialPositionRef: ', initialPositionRef);
console.log('intersection.y: ', intersection);
targetPosition.set(
initialPositionRef.current.x,
intersection.y,
initialPositionRef.current.z
);
targetPosition.set(initialPositionRef.current.x, intersection.y, initialPositionRef.current.z);
} else {
// For free movement
targetPosition.copy(intersection);
@@ -126,6 +116,3 @@ export default function useDraggableGLTF(onUpdate: OnUpdateCallback) {
return { handlePointerDown };
}

View File

@@ -1,5 +1,5 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
interface ZoneStore {
zones: Zone[];
@@ -10,13 +10,12 @@ interface ZoneStore {
setZoneHeight: (uuid: string, height: number) => void;
setZoneColor: (uuid: string, color: string) => void;
removeZone: (uuid: string) => void;
removePoint: (pointUuid: string) => { removedZones: Zone[], updatedZones: Zone[] };
removeZoneByPoints: (points: Point[]) => { removedZones: Zone[], updatedZones: Zone[] };
removePoint: (pointUuid: string) => { removedZones: Zone[]; updatedZones: Zone[] };
peekRemovePoint: (pointUuid: string) => { removedZones: Zone[]; updatedZones: Zone[] };
removeZoneByPoints: (points: Point[]) => { removedZones: Zone[]; updatedZones: Zone[] };
peekRemoveZoneByPoints: (points: Point[]) => { removedZones: Zone[]; updatedZones: Zone[] };
clearZones: () => void;
setPosition: (
pointUuid: string,
position: [number, number, number]
) => Zone[] | [];
setPosition: (pointUuid: string, position: [number, number, number]) => Zone[] | [];
setViewPort: (uuid: string, position: [number, number, number], target: [number, number, number]) => void;
getZoneById: (uuid: string) => Zone | undefined;
@@ -31,62 +30,69 @@ export const createZoneStore = () => {
immer((set, get) => ({
zones: [],
setZones: (zones) => set(state => {
state.zones = zones;
}),
setZones: (zones) =>
set((state) => {
state.zones = zones;
}),
addZone: (zone) => set(state => {
state.zones.push(zone);
}),
addZone: (zone) =>
set((state) => {
state.zones.push(zone);
}),
updateZone: (uuid, updated) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
Object.assign(zone, updated);
}
}),
updateZone: (uuid, updated) =>
set((state) => {
const zone = state.zones.find((z) => z.zoneUuid === uuid);
if (zone) {
Object.assign(zone, updated);
}
}),
setZoneName: (uuid, name) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
zone.zoneName = name;
}
}),
setZoneName: (uuid, name) =>
set((state) => {
const zone = state.zones.find((z) => z.zoneUuid === uuid);
if (zone) {
zone.zoneName = name;
}
}),
setZoneHeight: (uuid, height) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
zone.zoneHeight = height;
}
}),
setZoneHeight: (uuid, height) =>
set((state) => {
const zone = state.zones.find((z) => z.zoneUuid === uuid);
if (zone) {
zone.zoneHeight = height;
}
}),
setZoneColor: (uuid, color) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
zone.zoneColor = color;
}
}),
setZoneColor: (uuid, color) =>
set((state) => {
const zone = state.zones.find((z) => z.zoneUuid === uuid);
if (zone) {
zone.zoneColor = color;
}
}),
removeZone: (uuid) => set(state => {
state.zones = state.zones.filter(z => z.zoneUuid !== uuid);
}),
removeZone: (uuid) =>
set((state) => {
state.zones = state.zones.filter((z) => z.zoneUuid !== uuid);
}),
removePoint: (pointUuid) => {
const removedZones: Zone[] = [];
const updatedZones: Zone[] = [];
set(state => {
set((state) => {
const newZones: Zone[] = [];
for (const zone of state.zones) {
const pointIndex = zone.points.findIndex(p => p.pointUuid === pointUuid);
const pointIndex = zone.points.findIndex((p) => p.pointUuid === pointUuid);
if (pointIndex === -1) {
newZones.push(zone);
continue;
}
const remainingPoints = zone.points.filter(p => p.pointUuid !== pointUuid);
const remainingPoints = zone.points.filter((p) => p.pointUuid !== pointUuid);
if (remainingPoints.length <= 2) {
removedZones.push(JSON.parse(JSON.stringify(zone)));
@@ -104,37 +110,56 @@ export const createZoneStore = () => {
return { removedZones, updatedZones };
},
peekRemovePoint: (pointUuid: string) => {
const removedZones: Zone[] = [];
const updatedZones: Zone[] = [];
const zones = get().zones;
for (const zone of zones) {
const pointIndex = zone.points.findIndex((p) => p.pointUuid === pointUuid);
if (pointIndex === -1) continue;
const remainingPoints = zone.points.filter((p) => p.pointUuid !== pointUuid);
if (remainingPoints.length <= 2) {
removedZones.push(JSON.parse(JSON.stringify(zone)));
} else {
const updatedZone = { ...zone, points: remainingPoints };
updatedZones.push(JSON.parse(JSON.stringify(updatedZone)));
}
}
return { removedZones, updatedZones };
},
removeZoneByPoints: ([pointA, pointB]) => {
const removedZones: Zone[] = [];
const updatedZones: Zone[] = [];
set(state => {
set((state) => {
const newZones: Zone[] = [];
for (const zone of state.zones) {
const indices = zone.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
const idxA = indices.find(i => i.uuid === pointA.pointUuid)?.index ?? -1;
const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
const idxA = indices.find((i) => i.uuid === pointA.pointUuid)?.index ?? -1;
const idxB = indices.find((i) => i.uuid === pointB.pointUuid)?.index ?? -1;
if (idxA === -1 || idxB === -1) {
newZones.push(zone);
continue;
}
const areAdjacent =
Math.abs(idxA - idxB) === 1 ||
(idxA === 0 && idxB === zone.points.length - 1) ||
(idxB === 0 && idxA === zone.points.length - 1);
const areAdjacent = Math.abs(idxA - idxB) === 1 || (idxA === 0 && idxB === zone.points.length - 1) || (idxB === 0 && idxA === zone.points.length - 1);
if (!areAdjacent) {
newZones.push(zone);
continue;
}
const remainingPoints = zone.points.filter(
p => p.pointUuid !== pointA.pointUuid && p.pointUuid !== pointB.pointUuid
);
const remainingPoints = zone.points.filter((p) => p.pointUuid !== pointA.pointUuid && p.pointUuid !== pointB.pointUuid);
if (remainingPoints.length > 2) {
const updatedZone = { ...zone, points: remainingPoints };
@@ -151,9 +176,45 @@ export const createZoneStore = () => {
return { removedZones, updatedZones };
},
clearZones: () => set(state => {
state.zones = [];
}),
peekRemoveZoneByPoints: ([pointA, pointB]) => {
const removedZones: Zone[] = [];
const updatedZones: Zone[] = [];
const zones = get().zones;
for (const zone of zones) {
const indices = zone.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
const idxA = indices.find((i) => i.uuid === pointA.pointUuid)?.index ?? -1;
const idxB = indices.find((i) => i.uuid === pointB.pointUuid)?.index ?? -1;
if (idxA === -1 || idxB === -1) {
continue;
}
const areAdjacent = Math.abs(idxA - idxB) === 1 || (idxA === 0 && idxB === zone.points.length - 1) || (idxB === 0 && idxA === zone.points.length - 1);
if (!areAdjacent) {
continue;
}
const remainingPoints = zone.points.filter((p) => p.pointUuid !== pointA.pointUuid && p.pointUuid !== pointB.pointUuid);
if (remainingPoints.length > 2) {
const updatedZone = { ...zone, points: remainingPoints };
updatedZones.push(JSON.parse(JSON.stringify(updatedZone)));
} else {
removedZones.push(JSON.parse(JSON.stringify(zone)));
}
}
return { removedZones, updatedZones };
},
clearZones: () =>
set((state) => {
state.zones = [];
}),
setPosition: (pointUuid, position) => {
let updatedZone: Zone[] = [];
@@ -169,21 +230,22 @@ export const createZoneStore = () => {
return updatedZone;
},
setViewPort: (uuid, position, target) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
zone.viewPortPosition = position;
zone.viewPortTarget = target;
}
}),
setViewPort: (uuid, position, target) =>
set((state) => {
const zone = state.zones.find((z) => z.zoneUuid === uuid);
if (zone) {
zone.viewPortPosition = position;
zone.viewPortTarget = target;
}
}),
getZoneById: (uuid) => {
return get().zones.find(z => z.zoneUuid === uuid);
return get().zones.find((z) => z.zoneUuid === uuid);
},
getZonesByPointId: (pointUuid) => {
return get().zones.filter(zone => {
return zone.points.some(p => p.pointUuid === pointUuid);
return get().zones.filter((zone) => {
return zone.points.some((p) => p.pointUuid === pointUuid);
});
},
@@ -193,17 +255,14 @@ export const createZoneStore = () => {
for (const zone of get().zones) {
const indices = zone.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
const idxA = indices.find(i => i.uuid === pointA.pointUuid)?.index ?? -1;
const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
const idxA = indices.find((i) => i.uuid === pointA.pointUuid)?.index ?? -1;
const idxB = indices.find((i) => i.uuid === pointB.pointUuid)?.index ?? -1;
if (idxA === -1 || idxB === -1) {
continue;
}
const areAdjacent =
Math.abs(idxA - idxB) === 1 ||
(idxA === 0 && idxB === zone.points.length - 1) ||
(idxB === 0 && idxA === zone.points.length - 1);
const areAdjacent = Math.abs(idxA - idxB) === 1 || (idxA === 0 && idxB === zone.points.length - 1) || (idxB === 0 && idxA === zone.points.length - 1);
if (!areAdjacent) {
continue;
@@ -217,7 +276,7 @@ export const createZoneStore = () => {
getZonePointById: (pointUuid) => {
for (const zone of get().zones) {
const point = zone.points.find(p => p.pointUuid === pointUuid);
const point = zone.points.find((p) => p.pointUuid === pointUuid);
if (point) return point;
}
return undefined;
@@ -226,15 +285,14 @@ export const createZoneStore = () => {
getConnectedPoints: (pointUuid) => {
const connected: Point[] = [];
for (const zone of get().zones) {
if (zone.points.some(p => p.pointUuid === pointUuid)) {
connected.push(...zone.points.filter(p => p.pointUuid !== pointUuid));
if (zone.points.some((p) => p.pointUuid === pointUuid)) {
connected.push(...zone.points.filter((p) => p.pointUuid !== pointUuid));
}
}
return connected;
}
},
}))
);
};
export type ZoneStoreType = ReturnType<typeof createZoneStore>;
export type ZoneStoreType = ReturnType<typeof createZoneStore>;

View File

@@ -135,8 +135,8 @@ interface Zone {
zoneHeight: number;
zoneColor: string;
points: Point[];
viewPortTarget: [number, number, number];
viewPortPosition: [number, number, number];
viewPortTarget: [number, number, number];
}
type Zones = Zone[];