feat: Implement wall asset management features including creation, instances, and rendering; enhance wall properties input validation

This commit is contained in:
2025-06-30 16:21:54 +05:30
parent 943ad3ba49
commit 997775c27e
15 changed files with 313 additions and 47 deletions

View File

@@ -0,0 +1,85 @@
import { useThree } from '@react-three/fiber';
import { useEffect } from 'react'
import { useSelectedItem, useSocketStore, useToggleView } from '../../../store/builder/store';
import useModuleStore from '../../../store/useModuleStore';
import { MathUtils, Vector3 } from 'three';
import { useSceneContext } from '../../scene/sceneContext';
function WallAssetCreator() {
const { socket } = useSocketStore();
const { pointer, camera, raycaster, scene, gl } = useThree();
const { togglView } = useToggleView();
const { activeModule } = useModuleStore();
const { wallAssetStore } = useSceneContext();
const { addWallAsset } = wallAssetStore();
const { selectedItem, setSelectedItem } = useSelectedItem();
function closestPointOnLineSegment(p: Vector3, a: Vector3, b: Vector3) {
const ab = new Vector3().subVectors(b, a);
const ap = new Vector3().subVectors(p, a);
const abLengthSq = ab.lengthSq();
const dot = ap.dot(ab);
const t = Math.max(0, Math.min(1, dot / abLengthSq));
return new Vector3().copy(a).add(ab.multiplyScalar(t));
}
useEffect(() => {
const canvasElement = gl.domElement;
const onDrop = (event: DragEvent) => {
if (!event.dataTransfer?.files[0]) return;
if (selectedItem.id !== "" && event.dataTransfer?.files[0] && selectedItem.category === 'Fenestration') {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
const intersect = intersects.find((intersect) => intersect.object.name.includes('WallReference'));
if (intersect) {
const wall = intersect.object.userData as Wall;
const closestPoint = closestPointOnLineSegment(
new Vector3(intersect.point.x, 0, intersect.point.z),
new Vector3(...wall.points[0].position),
new Vector3(...wall.points[1].position)
)
const wallRotation = intersect.object.rotation.clone();
const newWallAsset: WallAsset = {
modelName: selectedItem.name,
modelUuid: MathUtils.generateUUID(),
wallUuid: wall.wallUuid,
wallAssetType: selectedItem.subCategory,
assetId: selectedItem.id,
position: [closestPoint.x, selectedItem.subCategory === "fixed-move" ? 0 : intersect.point.y, closestPoint.z],
rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
isLocked: false,
isVisible: true,
opacity: 1,
};
addWallAsset(newWallAsset);
}
}
};
if (!togglView && activeModule === 'builder') {
canvasElement.addEventListener('drop', onDrop);
}
return () => {
canvasElement.removeEventListener('drop', onDrop);
};
}, [gl, camera, togglView, activeModule, socket, selectedItem, setSelectedItem]);
return (
<>
</>
)
}
export default WallAssetCreator