2025-06-10 15:28:23 +05:30
|
|
|
import { useEffect } from "react";
|
|
|
|
|
import {
|
|
|
|
|
useObjectPosition,
|
|
|
|
|
useObjectRotation,
|
|
|
|
|
useSelectedWallItem,
|
|
|
|
|
useSocketStore,
|
|
|
|
|
useWallItems,
|
|
|
|
|
useSelectedItem,
|
2025-06-12 09:31:51 +05:30
|
|
|
useToolMode,
|
2025-06-10 15:28:23 +05:30
|
|
|
} from "../../../store/builder/store";
|
|
|
|
|
import { Csg } from "../csg/csg";
|
|
|
|
|
import * as Types from "../../../types/world/worldTypes";
|
|
|
|
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
|
|
|
|
import * as THREE from "three";
|
|
|
|
|
import { useThree } from "@react-three/fiber";
|
|
|
|
|
import handleMeshMissed from "../eventFunctions/handleMeshMissed";
|
|
|
|
|
import DeleteWallItems from "../geomentries/walls/deleteWallItems";
|
|
|
|
|
import loadInitialWallItems from "../IntialLoad/loadInitialWallItems";
|
|
|
|
|
import AddWallItems from "../geomentries/walls/addWallItems";
|
|
|
|
|
import useModuleStore from "../../../store/useModuleStore";
|
|
|
|
|
import { useParams } from "react-router-dom";
|
2025-06-23 09:37:53 +05:30
|
|
|
import { getUserData } from "../../../functions/getUserData";
|
|
|
|
|
import { useVersionContext } from "../version/versionContext";
|
2025-06-10 15:28:23 +05:30
|
|
|
|
|
|
|
|
const WallItemsGroup = ({
|
|
|
|
|
currentWallItem,
|
|
|
|
|
hoveredDeletableWallItem,
|
|
|
|
|
selectedItemsIndex,
|
|
|
|
|
setSelectedItemsIndex,
|
|
|
|
|
CSGGroup,
|
|
|
|
|
}: any) => {
|
|
|
|
|
const state = useThree();
|
|
|
|
|
const { socket } = useSocketStore();
|
|
|
|
|
const { pointer, camera, raycaster } = state;
|
2025-06-12 09:31:51 +05:30
|
|
|
const { toolMode } = useToolMode();
|
2025-06-10 15:28:23 +05:30
|
|
|
const { wallItems, setWallItems } = useWallItems();
|
|
|
|
|
const { setObjectPosition } = useObjectPosition();
|
|
|
|
|
const { setObjectRotation } = useObjectRotation();
|
|
|
|
|
const { setSelectedWallItem } = useSelectedWallItem();
|
|
|
|
|
const { activeModule } = useModuleStore();
|
|
|
|
|
const { selectedItem } = useSelectedItem();
|
2025-06-23 09:37:53 +05:30
|
|
|
const { selectedVersionStore } = useVersionContext();
|
|
|
|
|
const { selectedVersion } = selectedVersionStore();
|
2025-06-10 15:28:23 +05:30
|
|
|
const { projectId } = useParams();
|
2025-06-23 09:37:53 +05:30
|
|
|
const { userId, organization } = getUserData();
|
2025-06-10 15:28:23 +05:30
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
// Load Wall Items from the backend
|
2025-06-23 09:37:53 +05:30
|
|
|
if (!projectId || !selectedVersion) return;
|
|
|
|
|
loadInitialWallItems(setWallItems, projectId, selectedVersion?.versionId);
|
|
|
|
|
}, [selectedVersion?.versionId]);
|
2025-06-10 15:28:23 +05:30
|
|
|
|
|
|
|
|
////////// Update the Position value changes in the selected item //////////
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const canvasElement = state.gl.domElement;
|
|
|
|
|
function handlePointerMove(e: any) {
|
2025-06-12 09:31:51 +05:30
|
|
|
if (selectedItemsIndex !== null && toolMode === 'cursor' && e.buttons === 1) {
|
2025-06-10 15:28:23 +05:30
|
|
|
const Raycaster = state.raycaster;
|
|
|
|
|
const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true);
|
|
|
|
|
const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference"));
|
|
|
|
|
|
|
|
|
|
if (Object) {
|
|
|
|
|
(state.controls as any)!.enabled = false;
|
|
|
|
|
setWallItems((prevItems: any) => {
|
|
|
|
|
const updatedItems = [...prevItems];
|
|
|
|
|
let position: [number, number, number] = [0, 0, 0];
|
|
|
|
|
|
|
|
|
|
if (updatedItems[selectedItemsIndex].type === "fixed-move") {
|
|
|
|
|
position = [
|
|
|
|
|
Object!.point.x,
|
|
|
|
|
Math.floor(Object!.point.y / CONSTANTS.wallConfig.height) *
|
|
|
|
|
CONSTANTS.wallConfig.height,
|
|
|
|
|
Object!.point.z,
|
|
|
|
|
];
|
|
|
|
|
} else if (updatedItems[selectedItemsIndex].type === "free-move") {
|
|
|
|
|
position = [Object!.point.x, Object!.point.y, Object!.point.z];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
setObjectPosition(new THREE.Vector3(...position));
|
|
|
|
|
setObjectRotation({
|
|
|
|
|
x: THREE.MathUtils.radToDeg(Object!.object.rotation.x),
|
|
|
|
|
y: THREE.MathUtils.radToDeg(Object!.object.rotation.y),
|
|
|
|
|
z: THREE.MathUtils.radToDeg(Object!.object.rotation.z),
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
updatedItems[selectedItemsIndex] = {
|
|
|
|
|
...updatedItems[selectedItemsIndex],
|
|
|
|
|
position: position,
|
|
|
|
|
quaternion: Object!.object.quaternion.clone() as Types.QuaternionType,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return updatedItems;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handlePointerUp() {
|
|
|
|
|
const Raycaster = state.raycaster;
|
|
|
|
|
const intersects = Raycaster.intersectObjects(
|
|
|
|
|
CSGGroup.current?.children[0].children!,
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
const Object = intersects.find((child) =>
|
|
|
|
|
child.object.name.includes("WallRaycastReference")
|
|
|
|
|
);
|
|
|
|
|
if (Object) {
|
|
|
|
|
if (selectedItemsIndex !== null) {
|
|
|
|
|
let currentItem: any = null;
|
|
|
|
|
setWallItems((prevItems: any) => {
|
|
|
|
|
const updatedItems = [...prevItems];
|
|
|
|
|
const WallItemsForStorage = updatedItems.map((item) => {
|
|
|
|
|
const { model, ...rest } = item;
|
|
|
|
|
return {
|
|
|
|
|
...rest,
|
|
|
|
|
modelUuid: model?.uuid,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
currentItem = updatedItems[selectedItemsIndex];
|
|
|
|
|
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
|
|
|
|
return updatedItems;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
setTimeout(async () => {
|
|
|
|
|
|
|
|
|
|
//REST
|
|
|
|
|
|
|
|
|
|
// await setWallItem(
|
|
|
|
|
// organization,
|
|
|
|
|
// currentItem?.model?.uuid,
|
|
|
|
|
// currentItem.modelName,
|
2025-06-12 09:31:51 +05:30
|
|
|
// currentItem.assetId,
|
2025-06-10 15:28:23 +05:30
|
|
|
// currentItem.type!,
|
|
|
|
|
// currentItem.csgposition!,
|
|
|
|
|
// currentItem.csgscale!,
|
|
|
|
|
// currentItem.position,
|
|
|
|
|
// currentItem.quaternion,
|
|
|
|
|
// currentItem.scale!,
|
|
|
|
|
// )
|
|
|
|
|
|
|
|
|
|
//SOCKET
|
|
|
|
|
|
|
|
|
|
const data = {
|
2025-06-23 09:37:53 +05:30
|
|
|
organization,
|
2025-06-10 15:28:23 +05:30
|
|
|
modelUuid: currentItem.model?.uuid!,
|
2025-06-12 09:31:51 +05:30
|
|
|
assetId: currentItem.assetId,
|
2025-06-10 15:28:23 +05:30
|
|
|
modelName: currentItem.modelName!,
|
|
|
|
|
type: currentItem.type!,
|
|
|
|
|
csgposition: currentItem.csgposition!,
|
|
|
|
|
csgscale: currentItem.csgscale!,
|
|
|
|
|
position: currentItem.position!,
|
|
|
|
|
quaternion: currentItem.quaternion,
|
|
|
|
|
scale: currentItem.scale!,
|
|
|
|
|
socketId: socket.id,
|
2025-06-23 09:37:53 +05:30
|
|
|
versionId: selectedVersion?.versionId || '',
|
2025-06-10 15:28:23 +05:30
|
|
|
projectId,
|
|
|
|
|
userId
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// console.log('data: ', data);
|
|
|
|
|
socket.emit("v1:wallItems:set", data);
|
|
|
|
|
}, 0);
|
|
|
|
|
(state.controls as any)!.enabled = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
canvasElement.addEventListener("pointermove", handlePointerMove);
|
|
|
|
|
canvasElement.addEventListener("pointerup", handlePointerUp);
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
canvasElement.removeEventListener("pointermove", handlePointerMove);
|
|
|
|
|
canvasElement.removeEventListener("pointerup", handlePointerUp);
|
|
|
|
|
};
|
2025-06-23 09:37:53 +05:30
|
|
|
}, [selectedItemsIndex, selectedVersion?.versionId]);
|
2025-06-10 15:28:23 +05:30
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const canvasElement = state.gl.domElement;
|
|
|
|
|
let drag = false;
|
|
|
|
|
let isLeftMouseDown = false;
|
|
|
|
|
|
|
|
|
|
const onMouseDown = (evt: any) => {
|
|
|
|
|
if (evt.button === 0) {
|
|
|
|
|
isLeftMouseDown = true;
|
|
|
|
|
drag = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onMouseUp = (evt: any) => {
|
|
|
|
|
if (evt.button === 0) {
|
|
|
|
|
isLeftMouseDown = false;
|
2025-06-12 09:31:51 +05:30
|
|
|
if (!drag && toolMode === '3D-Delete' && activeModule === "builder") {
|
2025-06-10 15:28:23 +05:30
|
|
|
DeleteWallItems(
|
|
|
|
|
hoveredDeletableWallItem,
|
|
|
|
|
setWallItems,
|
|
|
|
|
wallItems,
|
2025-06-23 09:37:53 +05:30
|
|
|
socket,
|
|
|
|
|
projectId,
|
|
|
|
|
selectedVersion?.versionId || '',
|
2025-06-10 15:28:23 +05:30
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onMouseMove = () => {
|
|
|
|
|
if (isLeftMouseDown) {
|
|
|
|
|
drag = true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onDrop = (event: any) => {
|
|
|
|
|
if (selectedItem.category !== 'Fenestration') return;
|
|
|
|
|
|
|
|
|
|
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
|
|
|
|
|
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
|
|
|
|
|
|
|
|
|
raycaster.setFromCamera(pointer, camera);
|
|
|
|
|
|
2025-06-23 09:37:53 +05:30
|
|
|
if (selectedItem.id && selectedVersion && projectId) {
|
2025-06-10 15:28:23 +05:30
|
|
|
if (selectedItem.subCategory) {
|
|
|
|
|
AddWallItems(
|
|
|
|
|
selectedItem,
|
|
|
|
|
raycaster,
|
|
|
|
|
CSGGroup,
|
|
|
|
|
setWallItems,
|
|
|
|
|
socket,
|
2025-06-23 09:37:53 +05:30
|
|
|
projectId,
|
|
|
|
|
selectedVersion?.versionId || '',
|
2025-06-10 15:28:23 +05:30
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onDragOver = (event: any) => {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
canvasElement.addEventListener("mousedown", onMouseDown);
|
|
|
|
|
canvasElement.addEventListener("mouseup", onMouseUp);
|
|
|
|
|
canvasElement.addEventListener("mousemove", onMouseMove);
|
|
|
|
|
canvasElement.addEventListener("drop", onDrop);
|
|
|
|
|
canvasElement.addEventListener("dragover", onDragOver);
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
canvasElement.removeEventListener("mousedown", onMouseDown);
|
|
|
|
|
canvasElement.removeEventListener("mouseup", onMouseUp);
|
|
|
|
|
canvasElement.removeEventListener("mousemove", onMouseMove);
|
|
|
|
|
canvasElement.removeEventListener("drop", onDrop);
|
|
|
|
|
canvasElement.removeEventListener("dragover", onDragOver);
|
|
|
|
|
};
|
2025-06-23 09:37:53 +05:30
|
|
|
}, [toolMode, wallItems, selectedItem, camera, selectedVersion?.versionId]);
|
2025-06-10 15:28:23 +05:30
|
|
|
|
|
|
|
|
useEffect(() => {
|
2025-06-12 09:31:51 +05:30
|
|
|
if (toolMode && activeModule === "builder") {
|
2025-06-10 15:28:23 +05:30
|
|
|
handleMeshMissed(
|
|
|
|
|
currentWallItem,
|
|
|
|
|
setSelectedWallItem,
|
|
|
|
|
setSelectedItemsIndex
|
|
|
|
|
);
|
|
|
|
|
setSelectedWallItem(null);
|
|
|
|
|
setSelectedItemsIndex(null);
|
|
|
|
|
}
|
2025-06-12 09:31:51 +05:30
|
|
|
}, [toolMode]);
|
2025-06-10 15:28:23 +05:30
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{wallItems.map((item: Types.WallItem, index: number) => (
|
|
|
|
|
<group
|
|
|
|
|
key={index}
|
|
|
|
|
position={item.position}
|
|
|
|
|
quaternion={item.quaternion}
|
|
|
|
|
scale={item.scale}
|
|
|
|
|
>
|
|
|
|
|
<Csg
|
|
|
|
|
position={item.csgposition!}
|
|
|
|
|
scale={item.csgscale!}
|
|
|
|
|
model={item.model!}
|
|
|
|
|
hoveredDeletableWallItem={hoveredDeletableWallItem}
|
|
|
|
|
/>
|
|
|
|
|
</group>
|
|
|
|
|
))}
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default WallItemsGroup;
|