feat: Implement socket responses for collaboration features including model updates, line management, and zone handling
feat: Add temporary markdown files for simulation actions, events, products, and triggers feat: Create events store with actions for managing events, points, actions, and triggers, including syncing with product store
This commit is contained in:
827
app/src/modules/collaboration/socket/socketResponses.dev.tsx
Normal file
827
app/src/modules/collaboration/socket/socketResponses.dev.tsx
Normal file
@@ -0,0 +1,827 @@
|
||||
import { useEffect } from "react";
|
||||
import * as THREE from 'three';
|
||||
import gsap from 'gsap';
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
|
||||
import { toast } from 'react-toastify';
|
||||
import { useSocketStore, useActiveLayer, useWallItems, useFloorItems, useLayers, useUpdateScene, useWalls, useDeletedLines, useNewLines, useZonePoints, useZones } from "../../../store/store";
|
||||
|
||||
import * as Types from "../../../types/world/worldTypes";
|
||||
import * as CONSTANTS from '../../../types/world/worldConstants';
|
||||
import TempLoader from "../../builder/geomentries/assets/tempLoader";
|
||||
|
||||
// import { setFloorItemApi } from "../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
||||
import objectLineToArray from "../../builder/geomentries/lines/lineConvertions/objectLineToArray";
|
||||
import addLineToScene from "../../builder/geomentries/lines/addLineToScene";
|
||||
import updateLinesPositions from "../../builder/geomentries/lines/updateLinesPositions";
|
||||
import updateLines from "../../builder/geomentries/lines/updateLines";
|
||||
import updateDistanceText from "../../builder/geomentries/lines/updateDistanceText";
|
||||
import updateFloorLines from "../../builder/geomentries/floors/updateFloorLines";
|
||||
import loadWalls from "../../builder/geomentries/walls/loadWalls";
|
||||
import RemoveConnectedLines from "../../builder/geomentries/lines/removeConnectedLines";
|
||||
import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibility";
|
||||
import { retrieveGLTF, storeGLTF } from "../../../utils/indexDB/idbUtils";
|
||||
import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi";
|
||||
|
||||
|
||||
export default function SocketResponses({
|
||||
floorPlanGroup,
|
||||
lines,
|
||||
floorGroup,
|
||||
floorGroupAisle,
|
||||
scene,
|
||||
onlyFloorlines,
|
||||
AssetConfigurations,
|
||||
itemsGroup,
|
||||
isTempLoader,
|
||||
tempLoader,
|
||||
currentLayerPoint,
|
||||
floorPlanGroupPoint,
|
||||
floorPlanGroupLine,
|
||||
zoneGroup,
|
||||
dragPointControls
|
||||
}: any) {
|
||||
|
||||
const { socket } = useSocketStore();
|
||||
const { activeLayer, setActiveLayer } = useActiveLayer();
|
||||
const { wallItems, setWallItems } = useWallItems();
|
||||
const { layers, setLayers } = useLayers();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { updateScene, setUpdateScene } = useUpdateScene();
|
||||
const { walls, setWalls } = useWalls();
|
||||
const { deletedLines, setDeletedLines } = useDeletedLines();
|
||||
const { newLines, setNewLines } = useNewLines();
|
||||
const { zones, setZones } = useZones();
|
||||
const { zonePoints, setZonePoints } = useZonePoints();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
|
||||
if (!socket) return
|
||||
|
||||
socket.on('cameraCreateResponse', (data: any) => {
|
||||
// console.log('data: ', data);
|
||||
})
|
||||
|
||||
socket.on('userConnectRespones', (data: any) => {
|
||||
// console.log('data: ', data);
|
||||
})
|
||||
|
||||
socket.on('userDisConnectRespones', (data: any) => {
|
||||
// console.log('data: ', data);
|
||||
})
|
||||
|
||||
socket.on('cameraUpdateResponse', (data: any) => {
|
||||
// console.log('data: ', data);
|
||||
})
|
||||
|
||||
socket.on('EnvironmentUpdateResponse', (data: any) => {
|
||||
// console.log('data: ', data);
|
||||
})
|
||||
|
||||
socket.on('model-asset:response:updates', async (data: any) => {
|
||||
// console.log('data: ', data);
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "Model created successfully") {
|
||||
const loader = new GLTFLoader();
|
||||
const dracoLoader = new DRACOLoader();
|
||||
|
||||
dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
|
||||
loader.setDRACOLoader(dracoLoader);
|
||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||
|
||||
try {
|
||||
isTempLoader.current = true;
|
||||
const cachedModel = THREE.Cache.get(data.data.modelname);
|
||||
let url;
|
||||
if (cachedModel) {
|
||||
// console.log(`Getting ${data.data.modelname} from cache`);
|
||||
const model = cachedModel.scene.clone();
|
||||
model.uuid = data.data.modeluuid;
|
||||
model.userData = { name: data.data.modelname, modelId: data.data.modelfileID, modeluuid: data.data.modeluuid };
|
||||
model.position.set(...data.data.position as [number, number, number]);
|
||||
model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z);
|
||||
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
|
||||
|
||||
model.traverse((child: any) => {
|
||||
if (child.isMesh) {
|
||||
// Clone the material to ensure changes are independent
|
||||
// child.material = child.material.clone();
|
||||
|
||||
child.castShadow = true;
|
||||
child.receiveShadow = true;
|
||||
}
|
||||
});
|
||||
|
||||
itemsGroup.current.add(model);
|
||||
|
||||
if (tempLoader.current) {
|
||||
tempLoader.current.material.dispose();
|
||||
tempLoader.current.geometry.dispose();
|
||||
itemsGroup.current.remove(tempLoader.current);
|
||||
tempLoader.current = undefined;
|
||||
}
|
||||
|
||||
const newFloorItem: Types.FloorItemType = {
|
||||
modeluuid: data.data.modeluuid,
|
||||
modelname: data.data.modelname,
|
||||
modelfileID: data.data.modelfileID,
|
||||
position: [...data.data.position as [number, number, number]],
|
||||
rotation: {
|
||||
x: model.rotation.x,
|
||||
y: model.rotation.y,
|
||||
z: model.rotation.z,
|
||||
},
|
||||
isLocked: data.data.isLocked,
|
||||
isVisible: data.data.isVisible,
|
||||
};
|
||||
|
||||
setFloorItems((prevItems: any) => {
|
||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
gsap.to(model.position, { y: data.data.position[1], duration: 1.5, ease: 'power2.out' });
|
||||
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out', onComplete: () => { toast.success("Model Added!") } });
|
||||
|
||||
} else {
|
||||
const indexedDBModel = await retrieveGLTF(data.data.modelname);
|
||||
if (indexedDBModel) {
|
||||
// console.log(`Getting ${data.data.modelname} from IndexedDB`);
|
||||
url = URL.createObjectURL(indexedDBModel);
|
||||
} else {
|
||||
// console.log(`Getting ${data.data.modelname} from Backend`);
|
||||
url = `${url_Backend_dwinzo}/api/v2/AssetFile/${data.data.modelfileID}`;
|
||||
const modelBlob = await fetch(url).then((res) => res.blob());
|
||||
await storeGLTF(data.data.modelfileID, modelBlob);
|
||||
}
|
||||
}
|
||||
|
||||
if (url) {
|
||||
loadModel(url);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching asset model:', error);
|
||||
}
|
||||
|
||||
function loadModel(url: string) {
|
||||
loader.load(url, (gltf) => {
|
||||
URL.revokeObjectURL(url);
|
||||
THREE.Cache.remove(url);
|
||||
const model = gltf.scene;
|
||||
model.uuid = data.data.modeluuid;
|
||||
model.userData = { name: data.data.modelname, modelId: data.data.modelfileID, modeluuid: data.data.modeluuid };
|
||||
model.position.set(...data.data.position as [number, number, number]);
|
||||
model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z);
|
||||
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
|
||||
|
||||
model.traverse((child: any) => {
|
||||
if (child.isMesh) {
|
||||
// Clone the material to ensure changes are independent
|
||||
// child.material = child.material.clone();
|
||||
|
||||
child.castShadow = true;
|
||||
child.receiveShadow = true;
|
||||
}
|
||||
});
|
||||
|
||||
itemsGroup.current.add(model);
|
||||
|
||||
if (tempLoader.current) {
|
||||
tempLoader.current.material.dispose();
|
||||
tempLoader.current.geometry.dispose();
|
||||
itemsGroup.current.remove(tempLoader.current);
|
||||
tempLoader.current = undefined;
|
||||
}
|
||||
|
||||
const newFloorItem: Types.FloorItemType = {
|
||||
modeluuid: data.data.modeluuid,
|
||||
modelname: data.data.modelname,
|
||||
modelfileID: data.data.modelfileID,
|
||||
position: [...data.data.position as [number, number, number]],
|
||||
rotation: {
|
||||
x: model.rotation.x,
|
||||
y: model.rotation.y,
|
||||
z: model.rotation.z,
|
||||
},
|
||||
isLocked: data.data.isLocked,
|
||||
isVisible: data.data.isVisible,
|
||||
};
|
||||
|
||||
setFloorItems((prevItems: any) => {
|
||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
gsap.to(model.position, { y: data.data.position[1], duration: 1.5, ease: 'power2.out' });
|
||||
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out', onComplete: () => { toast.success("Model Added!") } });
|
||||
|
||||
THREE.Cache.add(data.data.modelname, gltf);
|
||||
}, () => {
|
||||
TempLoader(new THREE.Vector3(...data.data.position), isTempLoader, tempLoader, itemsGroup);
|
||||
});
|
||||
}
|
||||
|
||||
} else if (data.message === "Model updated successfully") {
|
||||
itemsGroup.current?.children.forEach((item: THREE.Group) => {
|
||||
if (item.uuid === data.data.modeluuid) {
|
||||
item.position.set(...data.data.position as [number, number, number]);
|
||||
item.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z);
|
||||
}
|
||||
})
|
||||
|
||||
setFloorItems((prevItems: Types.FloorItems) => {
|
||||
if (!prevItems) {
|
||||
return
|
||||
}
|
||||
let updatedItem: any = null;
|
||||
const updatedItems = prevItems.map((item) => {
|
||||
if (item.modeluuid === data.data.modeluuid) {
|
||||
updatedItem = {
|
||||
...item,
|
||||
position: [...data.data.position] as [number, number, number],
|
||||
rotation: { x: data.data.rotation.x, y: data.data.rotation.y, z: data.data.rotation.z, },
|
||||
};
|
||||
return updatedItem;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return updatedItems;
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('model-asset:response:updates', (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "Model deleted successfully") {
|
||||
const deletedUUID = data.data.modeluuid;
|
||||
let items = JSON.parse(localStorage.getItem("FloorItems")!);
|
||||
|
||||
const updatedItems = items.filter(
|
||||
(item: { modeluuid: string }) => item.modeluuid !== deletedUUID
|
||||
);
|
||||
|
||||
const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]');
|
||||
const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => item.modeluuid !== deletedUUID);
|
||||
localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems));
|
||||
|
||||
itemsGroup.current.children.forEach((item: any) => {
|
||||
if (item.uuid === deletedUUID) {
|
||||
itemsGroup.current.remove(item);
|
||||
}
|
||||
})
|
||||
setFloorItems(updatedItems);
|
||||
toast.success("Model Removed!");
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('Line:response:update', (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "line updated") {
|
||||
const DraggedUUID = data.data.uuid;
|
||||
const DraggedPosition = new THREE.Vector3(data.data.position.x, data.data.position.y, data.data.position.z);
|
||||
|
||||
const point = floorPlanGroupPoint.current.getObjectByProperty('uuid', DraggedUUID);
|
||||
point.position.set(DraggedPosition.x, DraggedPosition.y, DraggedPosition.z);
|
||||
const affectedLines = updateLinesPositions({ uuid: DraggedUUID, position: DraggedPosition }, lines);
|
||||
|
||||
updateLines(floorPlanGroupLine, affectedLines);
|
||||
updateDistanceText(scene, floorPlanGroupLine, affectedLines);
|
||||
updateFloorLines(onlyFloorlines, { uuid: DraggedUUID, position: DraggedPosition });
|
||||
|
||||
loadWalls(lines, setWalls);
|
||||
setUpdateScene(true);
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('Line:response:delete', (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "line deleted") {
|
||||
const line = objectLineToArray(data.data);
|
||||
const linePoints = line;
|
||||
const connectedpoints = [linePoints[0][1], linePoints[1][1]];
|
||||
|
||||
|
||||
onlyFloorlines.current = onlyFloorlines.current.map((floorline: any) =>
|
||||
floorline.filter((line: any) => line[0][1] !== connectedpoints[0] && line[1][1] !== connectedpoints[1])
|
||||
).filter((floorline: any) => floorline.length > 0);
|
||||
|
||||
const removedLine = lines.current.find((item: any) => (item[0][1] === linePoints[0][1] && item[1][1] === linePoints[1][1] || (item[0][1] === linePoints[1][1] && item[1][1] === linePoints[0][1])));
|
||||
lines.current = lines.current.filter((item: any) => item !== removedLine);
|
||||
|
||||
floorPlanGroupLine.current.children.forEach((line: any) => {
|
||||
const linePoints = line.userData.linePoints as [number, string, number][];
|
||||
const uuid1 = linePoints[0][1];
|
||||
const uuid2 = linePoints[1][1];
|
||||
|
||||
if ((uuid1 === connectedpoints[0] && uuid2 === connectedpoints[1] || (uuid1 === connectedpoints[1] && uuid2 === connectedpoints[0]))) {
|
||||
line.material.dispose();
|
||||
line.geometry.dispose();
|
||||
floorPlanGroupLine.current.remove(line);
|
||||
setDeletedLines([line.userData.linePoints])
|
||||
}
|
||||
});
|
||||
|
||||
connectedpoints.forEach((pointUUID) => {
|
||||
let isConnected = false;
|
||||
floorPlanGroupLine.current.children.forEach((line: any) => {
|
||||
const linePoints = line.userData.linePoints;
|
||||
const uuid1 = linePoints[0][1];
|
||||
const uuid2 = linePoints[1][1];
|
||||
if (uuid1 === pointUUID || uuid2 === pointUUID) {
|
||||
isConnected = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!isConnected) {
|
||||
floorPlanGroupPoint.current.children.forEach((point: any) => {
|
||||
if (point.uuid === pointUUID) {
|
||||
point.material.dispose();
|
||||
point.geometry.dispose();
|
||||
floorPlanGroupPoint.current.remove(point);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
loadWalls(lines, setWalls);
|
||||
setUpdateScene(true);
|
||||
|
||||
toast.success("Line Removed!");
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('Line:response:delete:point', (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "point deleted") {
|
||||
const point = floorPlanGroupPoint.current?.getObjectByProperty('uuid', data.data);
|
||||
point.material.dispose();
|
||||
point.geometry.dispose();
|
||||
floorPlanGroupPoint.current.remove(point);
|
||||
|
||||
onlyFloorlines.current = onlyFloorlines.current.map((floorline: any) =>
|
||||
floorline.filter((line: any) => line[0][1] !== data.data && line[1][1] !== data.data)
|
||||
).filter((floorline: any) => floorline.length > 0);
|
||||
|
||||
RemoveConnectedLines(data.data, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines);
|
||||
|
||||
loadWalls(lines, setWalls);
|
||||
setUpdateScene(true);
|
||||
|
||||
toast.success("Point Removed!");
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('Line:response:delete:layer', async (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "layer deleted") {
|
||||
setActiveLayer(1)
|
||||
const removedLayer = data.data;
|
||||
const removedLines: Types.Lines = lines.current.filter((line: any) => line[0][2] === removedLayer);
|
||||
|
||||
////////// Remove Points and lines from the removed layer //////////
|
||||
|
||||
removedLines.forEach(async (line) => {
|
||||
line.forEach(async (removedPoint) => {
|
||||
const removableLines: THREE.Mesh[] = [];
|
||||
const connectedpoints: string[] = [];
|
||||
|
||||
floorPlanGroupLine.current.children.forEach((line: any) => {
|
||||
const linePoints = line.userData.linePoints as [number, string, number][];
|
||||
const uuid1 = linePoints[0][1];
|
||||
const uuid2 = linePoints[1][1];
|
||||
|
||||
if (uuid1 === removedPoint[1] || uuid2 === removedPoint[1]) {
|
||||
connectedpoints.push(uuid1 === removedPoint[1] ? uuid2 : uuid1);
|
||||
removableLines.push(line as THREE.Mesh);
|
||||
}
|
||||
});
|
||||
|
||||
if (removableLines.length > 0) {
|
||||
removableLines.forEach((line: any) => {
|
||||
lines.current = lines.current.filter((item: any) => JSON.stringify(item) !== JSON.stringify(line.userData.linePoints));
|
||||
line.material.dispose();
|
||||
line.geometry.dispose();
|
||||
floorPlanGroupLine.current.remove(line);
|
||||
});
|
||||
}
|
||||
|
||||
const point = floorPlanGroupPoint.current.getObjectByProperty('uuid', removedPoint[1]);
|
||||
if (point) {
|
||||
point.material.dispose();
|
||||
point.geometry.dispose();
|
||||
floorPlanGroupPoint.current.remove(point)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
////////// Update the remaining lines layer values in the userData and in lines.current //////////
|
||||
|
||||
let remaining = lines.current.filter((line: any) => line[0][2] !== removedLayer);
|
||||
let updatedLines: Types.Lines = [];
|
||||
remaining.forEach((line: any) => {
|
||||
let newLines = JSON.parse(JSON.stringify(line));
|
||||
if (newLines[0][2] > removedLayer) {
|
||||
newLines[0][2] -= 1;
|
||||
newLines[1][2] -= 1;
|
||||
}
|
||||
|
||||
const matchingLine = floorPlanGroupLine.current.children.find((l: any) => l.userData.linePoints[0][1] === line[0][1] && l.userData.linePoints[1][1] === line[1][1]);
|
||||
if (matchingLine) {
|
||||
const updatedUserData = JSON.parse(JSON.stringify(matchingLine.userData));
|
||||
updatedUserData.linePoints[0][2] = newLines[0][2];
|
||||
updatedUserData.linePoints[1][2] = newLines[1][2];
|
||||
matchingLine.userData = updatedUserData;
|
||||
}
|
||||
updatedLines.push(newLines);
|
||||
});
|
||||
|
||||
lines.current = updatedLines;
|
||||
localStorage.setItem("Lines", JSON.stringify(lines.current));
|
||||
|
||||
////////// Also remove OnlyFloorLines and update it in localstorage //////////
|
||||
|
||||
onlyFloorlines.current = onlyFloorlines.current.filter((floor: any) => {
|
||||
return floor[0][0][2] !== removedLayer;
|
||||
});
|
||||
const meshToRemove = floorGroup.current?.children.find((mesh: any) =>
|
||||
mesh.name === `Only_Floor_Line_${removedLayer}`
|
||||
);
|
||||
if (meshToRemove) {
|
||||
meshToRemove.geometry.dispose();
|
||||
meshToRemove.material.dispose();
|
||||
floorGroup.current?.remove(meshToRemove);
|
||||
}
|
||||
|
||||
const zonesData = await getZonesApi(organization);
|
||||
const highestLayer = Math.max(
|
||||
1,
|
||||
lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0),
|
||||
zonesData.data.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0)
|
||||
);
|
||||
|
||||
setLayers(highestLayer);
|
||||
|
||||
loadWalls(lines, setWalls);
|
||||
setUpdateScene(true);
|
||||
|
||||
toast.success("Layer Removed!");
|
||||
}
|
||||
})
|
||||
}, [socket])
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket) return
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
|
||||
socket.on('wallItemsDeleteResponse', (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "wallitem deleted") {
|
||||
const deletedUUID = data.data.modeluuid;
|
||||
let WallItemsRef = wallItems;
|
||||
const Items = WallItemsRef.filter((item: any) => item.model?.uuid !== deletedUUID);
|
||||
|
||||
setWallItems([]);
|
||||
setTimeout(async () => {
|
||||
WallItemsRef = Items;
|
||||
setWallItems(WallItemsRef);
|
||||
const WallItemsForStorage = WallItemsRef.map((item: any) => {
|
||||
const { model, ...rest } = item;
|
||||
return {
|
||||
...rest,
|
||||
modeluuid: model?.uuid,
|
||||
};
|
||||
});
|
||||
|
||||
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
||||
toast.success("Model Removed!");
|
||||
}, 50);
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('wallItemsUpdateResponse', (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "wallIitem created") {
|
||||
const loader = new GLTFLoader();
|
||||
loader.load(AssetConfigurations[data.data.modelname].modelUrl, async (gltf) => {
|
||||
const model = gltf.scene;
|
||||
model.uuid = data.data.modeluuid;
|
||||
model.children[0].children.forEach((child) => {
|
||||
if (child.name !== "CSG_REF") {
|
||||
child.castShadow = true;
|
||||
child.receiveShadow = true;
|
||||
}
|
||||
});
|
||||
|
||||
const newWallItem = {
|
||||
type: data.data.type,
|
||||
model: model,
|
||||
modelname: data.data.modelname,
|
||||
scale: data.data.scale,
|
||||
csgscale: data.data.csgscale,
|
||||
csgposition: data.data.csgposition,
|
||||
position: data.data.position,
|
||||
quaternion: data.data.quaternion
|
||||
};
|
||||
|
||||
setWallItems((prevItems: any) => {
|
||||
const updatedItems = [...prevItems, newWallItem];
|
||||
|
||||
const WallItemsForStorage = updatedItems.map(item => {
|
||||
const { model, ...rest } = item;
|
||||
return {
|
||||
...rest,
|
||||
modeluuid: model?.uuid,
|
||||
};
|
||||
});
|
||||
|
||||
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
||||
toast.success("Model Added!");
|
||||
|
||||
return updatedItems;
|
||||
});
|
||||
});
|
||||
} else if (data.message === "wallIitem updated") {
|
||||
const updatedUUID = data.data.modeluuid;
|
||||
|
||||
setWallItems((prevItems: any) => {
|
||||
const updatedItems = prevItems.map((item: any) => {
|
||||
if (item.model.uuid === updatedUUID) {
|
||||
return {
|
||||
...item,
|
||||
position: data.data.position,
|
||||
quaternion: data.data.quaternion,
|
||||
scale: data.data.scale,
|
||||
csgscale: data.data.csgscale,
|
||||
csgposition: data.data.csgposition,
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
const WallItemsForStorage = updatedItems.map((item: any) => {
|
||||
const { model, ...rest } = item;
|
||||
return {
|
||||
...rest,
|
||||
modeluuid: model?.uuid,
|
||||
};
|
||||
});
|
||||
|
||||
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
||||
toast.success("Model Updated!");
|
||||
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
return () => {
|
||||
socket.off('wallItemsDeleteResponse');
|
||||
socket.off('wallItemsUpdateResponse');
|
||||
};
|
||||
}, [wallItems])
|
||||
|
||||
function getPointColor(lineType: string | undefined): string {
|
||||
switch (lineType) {
|
||||
case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor;
|
||||
case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor;
|
||||
case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor;
|
||||
default: return CONSTANTS.pointConfig.defaultOuterColor;
|
||||
}
|
||||
}
|
||||
|
||||
function getLineColor(lineType: string | undefined): string {
|
||||
switch (lineType) {
|
||||
case CONSTANTS.lineConfig.wallName: return CONSTANTS.lineConfig.wallColor;
|
||||
case CONSTANTS.lineConfig.floorName: return CONSTANTS.lineConfig.floorColor;
|
||||
case CONSTANTS.lineConfig.aisleName: return CONSTANTS.lineConfig.aisleColor;
|
||||
default: return CONSTANTS.lineConfig.defaultColor;
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket) return
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
|
||||
socket.on('Line:response:create', async (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "line create") {
|
||||
const line: Types.Line = objectLineToArray(data.data);
|
||||
const type = line[0][3];
|
||||
const pointColour = getPointColor(type);
|
||||
const lineColour = getLineColor(type);
|
||||
setNewLines([line])
|
||||
|
||||
line.forEach((line) => {
|
||||
const existingPoint = floorPlanGroupPoint.current?.getObjectByProperty('uuid', line[1]);
|
||||
if (existingPoint) {
|
||||
return;
|
||||
}
|
||||
const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale);
|
||||
const material = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
uColor: { value: new THREE.Color(pointColour) }, // Blue color for the border
|
||||
uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square
|
||||
},
|
||||
vertexShader: `
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
varying vec2 vUv;
|
||||
uniform vec3 uColor;
|
||||
uniform vec3 uInnerColor;
|
||||
|
||||
void main() {
|
||||
// Define the size of the white square as a proportion of the face
|
||||
float borderThickness = 0.2; // Adjust this value for border thickness
|
||||
if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness &&
|
||||
vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
|
||||
gl_FragColor = vec4(uInnerColor, 1.0); // White inner square
|
||||
} else {
|
||||
gl_FragColor = vec4(uColor, 1.0); // Blue border
|
||||
}
|
||||
}
|
||||
`,
|
||||
});
|
||||
const point = new THREE.Mesh(geometry, material);
|
||||
point.name = "point";
|
||||
point.uuid = line[1];
|
||||
point.userData = { type: type, color: pointColour };
|
||||
point.position.set(line[0].x, line[0].y, line[0].z);
|
||||
currentLayerPoint.current.push(point);
|
||||
|
||||
floorPlanGroupPoint.current?.add(point);
|
||||
})
|
||||
if (dragPointControls.current) {
|
||||
dragPointControls.current!.objects = currentLayerPoint.current;
|
||||
}
|
||||
addLineToScene(
|
||||
new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z),
|
||||
new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z),
|
||||
lineColour,
|
||||
line,
|
||||
floorPlanGroupLine
|
||||
)
|
||||
lines.current.push(line);
|
||||
|
||||
const zonesData = await getZonesApi(organization);
|
||||
const highestLayer = Math.max(
|
||||
1,
|
||||
lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0),
|
||||
zonesData.data.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0)
|
||||
);
|
||||
|
||||
setLayers(highestLayer);
|
||||
|
||||
Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls)
|
||||
|
||||
loadWalls(lines, setWalls);
|
||||
setUpdateScene(true);
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
socket.off('Line:response:create');
|
||||
};
|
||||
}, [socket, activeLayer])
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket) return
|
||||
const email = localStorage.getItem('email');
|
||||
const organization = (email!.split("@")[1]).split(".")[0];
|
||||
|
||||
socket.on('zone:response:updates', (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
|
||||
if (data.message === "zone created") {
|
||||
const pointsArray: [number, number, number][] = data.data.points;
|
||||
const vector3Array = pointsArray.map(([x, y, z]) => new THREE.Vector3(x, y, z));
|
||||
const newZones = [...zones, data.data];
|
||||
setZones(newZones);
|
||||
const updatedZonePoints = [...zonePoints, ...vector3Array];
|
||||
setZonePoints(updatedZonePoints);
|
||||
|
||||
const highestLayer = Math.max(
|
||||
1,
|
||||
lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0),
|
||||
newZones.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0)
|
||||
);
|
||||
|
||||
setLayers(highestLayer);
|
||||
setUpdateScene(true);
|
||||
}
|
||||
|
||||
if (data.message === "zone updated") {
|
||||
const updatedZones = zones.map((zone: any) =>
|
||||
zone.zoneId === data.data.zoneId ? data.data : zone
|
||||
);
|
||||
setZones(updatedZones);
|
||||
setUpdateScene(true);
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
socket.on('zone:response:delete', (data: any) => {
|
||||
if (socket.id === data.socketId) {
|
||||
return
|
||||
}
|
||||
if (organization !== data.organization) {
|
||||
return
|
||||
}
|
||||
if (data.message === "zone deleted") {
|
||||
const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId);
|
||||
setZones(updatedZones);
|
||||
|
||||
const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === data.data.zoneId);
|
||||
if (zoneIndex !== -1) {
|
||||
const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4);
|
||||
setZonePoints(updatedzonePoints);
|
||||
}
|
||||
|
||||
const highestLayer = Math.max(
|
||||
1,
|
||||
lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0),
|
||||
updatedZones.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0)
|
||||
);
|
||||
|
||||
setLayers(highestLayer);
|
||||
setUpdateScene(true);
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
socket.off('zone:response:updates');
|
||||
socket.off('zone:response:delete');
|
||||
};
|
||||
}, [socket, zones, zonePoints])
|
||||
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user