import * as THREE from 'three'; import { Base } from '@react-three/csg'; import { useMemo, useRef, useState } from 'react'; import { MeshDiscardMaterial } from '@react-three/drei'; import { useFrame, useThree } from '@react-three/fiber'; import useModuleStore from '../../../../../store/useModuleStore'; import { useSceneContext } from '../../../../scene/sceneContext'; import { useWallClassification } from './helpers/useWallClassification'; import { useToggleView, useWallVisibility } from '../../../../../store/builder/store'; import { useBuilderStore } from '../../../../../store/builder/useBuilderStore'; import * as Constants from '../../../../../types/world/worldConstants'; import DecalInstance from '../../../Decal/decalInstance'; import defaultMaterial from '../../../../../assets/textures/floor/wall-tex.png'; import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg'; function Wall({ wall }: { readonly wall: Wall }) { const { wallStore, wallAssetStore } = useSceneContext(); const { walls, addDecal } = wallStore(); const { wallAssets, getAssetsByWall } = wallAssetStore(); const assets = getAssetsByWall(wall.wallUuid); const { selectedWall, setSelectedWall, setSelectedDecal } = useBuilderStore(); const { togglView } = useToggleView(); const { activeModule } = useModuleStore(); const { camera } = useThree(); const { wallVisibility } = useWallVisibility(); const { getWallType, isWallFlipped } = useWallClassification(walls); const [visible, setVisible] = useState(true); const meshRef = useRef(); const wallType = getWallType(wall); const wallFlipped = isWallFlipped(wall); const [rawStart, rawEnd] = wall.points; const [startPoint, endPoint] = wallFlipped ? [rawStart, rawEnd] : [rawEnd, rawStart]; const startX = startPoint.position[0]; const startZ = startPoint.position[2]; const endX = endPoint.position[0]; const endZ = endPoint.position[2]; const wallLength = Math.sqrt((endX - startX) ** 2 + (endZ - startZ) ** 2); const angle = Math.atan2(endZ - startZ, endX - startX); const centerX = (startX + endX) / 2; const centerZ = (startZ + endZ) / 2; const centerY = wall.wallHeight / 2; const textureLoader = new THREE.TextureLoader(); const [defaultWallTexture, material1WallTexture] = useMemo(() => { const inside = textureLoader.load(defaultMaterial); inside.wrapS = inside.wrapT = THREE.RepeatWrapping; inside.repeat.set(wallLength / 10, wall.wallHeight / 10); inside.colorSpace = THREE.SRGBColorSpace; const outside = textureLoader.load(material1); outside.wrapS = outside.wrapT = THREE.RepeatWrapping; outside.repeat.set(wallLength / 10, wall.wallHeight / 10); outside.colorSpace = THREE.SRGBColorSpace; return [inside, outside]; }, [wallLength, wall.wallHeight]); const materials = useMemo(() => { return [ new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Left new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Right new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Top new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Bottom new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, map: wall.insideMaterial === 'Default Material' ? defaultWallTexture : material1WallTexture, }), new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, map: wall.outsideMaterial === 'Default Material' ? defaultWallTexture : material1WallTexture, }), ]; }, [defaultWallTexture, material1WallTexture, wall]); const geometry = useMemo(() => new THREE.BoxGeometry(wallLength, wall.wallHeight, wall.wallThickness), [wallLength, wall.wallHeight, wall.wallThickness]); useFrame(() => { if (!meshRef.current) return; const v = new THREE.Vector3(); const u = new THREE.Vector3(); if (!wallVisibility && wallType.type === 'room') { meshRef.current.getWorldDirection(v); camera.getWorldDirection(u); if (!u || !v) return; setVisible((2 * v.dot(u)) <= 0.1); } else { setVisible(true); } }) return ( {(assets.length > 0 || (walls[0].wallUuid === wall.wallUuid && wallAssets.length > 0)) ? {materials.map((material, index) => ( ))} : {materials.map((material, index) => ( ))} } { if (visible && !togglView && activeModule === 'builder') { if (e.object.userData.wallUuid) { e.stopPropagation(); setSelectedWall(e.object); setSelectedDecal(null); } } }} onPointerMissed={() => { if (selectedWall && selectedWall.userData.wallUuid === wall.wallUuid) { setSelectedWall(null); } }} > {wall.decals.map((decal) => ( ))} ); } export default Wall;