feat: Implement wall asset management features including creation, instances, and rendering; enhance wall properties input validation
This commit is contained in:
85
app/src/modules/builder/wallAsset/wallAssetCreator.tsx
Normal file
85
app/src/modules/builder/wallAsset/wallAssetCreator.tsx
Normal 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
|
||||
Reference in New Issue
Block a user