2025-06-10 15:28:23 +05:30
|
|
|
import * as THREE from 'three';
|
2025-06-25 15:26:53 +05:30
|
|
|
import { Base } from '@react-three/csg';
|
2025-06-10 15:28:23 +05:30
|
|
|
import { useMemo, useRef, useState } from 'react';
|
2025-06-25 15:26:53 +05:30
|
|
|
import { Decal, MeshDiscardMaterial } from '@react-three/drei';
|
|
|
|
|
import { useFrame, useThree } from '@react-three/fiber';
|
2025-06-10 15:28:23 +05:30
|
|
|
|
2025-06-23 09:37:53 +05:30
|
|
|
import defaultMaterial from '../../../../../assets/textures/floor/wall-tex.png';
|
|
|
|
|
import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg';
|
2025-06-25 15:26:53 +05:30
|
|
|
|
|
|
|
|
import useModuleStore from '../../../../../store/useModuleStore';
|
|
|
|
|
import { useSceneContext } from '../../../../scene/sceneContext';
|
2025-06-10 15:28:23 +05:30
|
|
|
import { useWallClassification } from './helpers/useWallClassification';
|
2025-06-25 15:26:53 +05:30
|
|
|
import { useToggleView, useWallVisibility } from '../../../../../store/builder/store';
|
|
|
|
|
import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
|
|
|
|
|
import * as Constants from '../../../../../types/world/worldConstants';
|
2025-06-25 17:20:35 +05:30
|
|
|
import DecalInstance from '../../../Decal/decalInstance';
|
2025-06-10 15:28:23 +05:30
|
|
|
|
|
|
|
|
function Wall({ wall }: { readonly wall: Wall }) {
|
2025-06-25 15:26:53 +05:30
|
|
|
const { wallStore } = useSceneContext();
|
2025-06-25 17:20:35 +05:30
|
|
|
const { walls, addDecal } = wallStore();
|
|
|
|
|
const { selectedWall, setSelectedWall, setSelectedDecal } = useBuilderStore();
|
2025-06-25 15:26:53 +05:30
|
|
|
const { togglView } = useToggleView();
|
|
|
|
|
const { activeModule } = useModuleStore();
|
Refactor error handling in API services to use console.error instead of throwing errors
- Updated various API service files to replace error throwing with console.error for better logging.
- This change affects services related to aisles, assets, cameras, collaboration, comments, environment, lines, marketplace, simulation, visualization, and zones.
- The modifications aim to improve error handling by logging errors to the console instead of interrupting the flow with thrown errors.
2025-06-24 09:31:45 +05:30
|
|
|
const { camera } = useThree();
|
|
|
|
|
const { wallVisibility } = useWallVisibility();
|
2025-06-23 09:37:53 +05:30
|
|
|
const { getWallType, isWallFlipped } = useWallClassification(walls);
|
2025-06-10 15:28:23 +05:30
|
|
|
const [visible, setVisible] = useState(true);
|
|
|
|
|
const meshRef = useRef<any>();
|
Refactor error handling in API services to use console.error instead of throwing errors
- Updated various API service files to replace error throwing with console.error for better logging.
- This change affects services related to aisles, assets, cameras, collaboration, comments, environment, lines, marketplace, simulation, visualization, and zones.
- The modifications aim to improve error handling by logging errors to the console instead of interrupting the flow with thrown errors.
2025-06-24 09:31:45 +05:30
|
|
|
const wallType = getWallType(wall);
|
2025-06-10 15:28:23 +05:30
|
|
|
|
2025-06-23 09:37:53 +05:30
|
|
|
const wallFlipped = isWallFlipped(wall);
|
|
|
|
|
|
|
|
|
|
const [rawStart, rawEnd] = wall.points;
|
|
|
|
|
const [startPoint, endPoint] = wallFlipped ? [rawStart, rawEnd] : [rawEnd, rawStart];
|
|
|
|
|
|
2025-06-10 15:28:23 +05:30
|
|
|
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();
|
|
|
|
|
|
2025-06-23 09:37:53 +05:30
|
|
|
const [defaultWallTexture, material1WallTexture] = useMemo(() => {
|
|
|
|
|
const inside = textureLoader.load(defaultMaterial);
|
2025-06-10 15:28:23 +05:30
|
|
|
inside.wrapS = inside.wrapT = THREE.RepeatWrapping;
|
|
|
|
|
inside.repeat.set(wallLength / 10, wall.wallHeight / 10);
|
|
|
|
|
inside.colorSpace = THREE.SRGBColorSpace;
|
|
|
|
|
|
2025-06-23 09:37:53 +05:30
|
|
|
const outside = textureLoader.load(material1);
|
2025-06-10 15:28:23 +05:30
|
|
|
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 [
|
2025-06-23 09:37:53 +05:30
|
|
|
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible }), // Left
|
|
|
|
|
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible }), // Right
|
|
|
|
|
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible }), // Top
|
|
|
|
|
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible }), // Bottom
|
2025-06-10 15:28:23 +05:30
|
|
|
new THREE.MeshStandardMaterial({
|
|
|
|
|
color: Constants.wallConfig.defaultColor,
|
|
|
|
|
side: THREE.DoubleSide,
|
2025-06-23 09:37:53 +05:30
|
|
|
map: wall.insideMaterial === 'Default Material' ? defaultWallTexture : material1WallTexture,
|
2025-06-10 15:28:23 +05:30
|
|
|
}),
|
|
|
|
|
new THREE.MeshStandardMaterial({
|
|
|
|
|
color: Constants.wallConfig.defaultColor,
|
|
|
|
|
side: THREE.DoubleSide,
|
2025-06-25 15:26:53 +05:30
|
|
|
map: wall.outsideMaterial === 'Default Material' ? defaultWallTexture : material1WallTexture,
|
2025-06-10 15:28:23 +05:30
|
|
|
}),
|
|
|
|
|
];
|
2025-06-23 09:37:53 +05:30
|
|
|
}, [defaultWallTexture, material1WallTexture, wall]);
|
2025-06-10 15:28:23 +05:30
|
|
|
|
2025-06-23 09:37:53 +05:30
|
|
|
const geometry = useMemo(() => new THREE.BoxGeometry(wallLength, wall.wallHeight, wall.wallThickness), [wallLength, wall.wallHeight, wall.wallThickness]);
|
2025-06-10 15:28:23 +05:30
|
|
|
|
|
|
|
|
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);
|
2025-06-23 09:37:53 +05:30
|
|
|
if (!u || !v) return;
|
2025-06-10 15:28:23 +05:30
|
|
|
setVisible((2 * v.dot(u)) <= 0.1);
|
|
|
|
|
} else {
|
|
|
|
|
setVisible(true);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return (
|
2025-06-23 09:37:53 +05:30
|
|
|
<mesh
|
2025-06-10 15:28:23 +05:30
|
|
|
name={`Wall-${wall.wallUuid}`}
|
2025-06-23 09:37:53 +05:30
|
|
|
key={wall.wallUuid}
|
2025-06-10 15:28:23 +05:30
|
|
|
userData={wall}
|
|
|
|
|
>
|
2025-06-23 09:37:53 +05:30
|
|
|
<Base
|
|
|
|
|
ref={meshRef}
|
|
|
|
|
geometry={geometry}
|
|
|
|
|
position={[centerX, centerY, centerZ]}
|
|
|
|
|
rotation={[0, -angle, 0]}
|
2025-06-25 15:26:53 +05:30
|
|
|
userData={wall}
|
2025-06-23 09:37:53 +05:30
|
|
|
>
|
2025-06-10 15:28:23 +05:30
|
|
|
{materials.map((material, index) => (
|
2025-06-23 09:37:53 +05:30
|
|
|
<primitive key={index} visible={visible} object={material} attach={`material-${index}`} />
|
2025-06-10 15:28:23 +05:30
|
|
|
))}
|
|
|
|
|
</Base>
|
2025-06-25 15:26:53 +05:30
|
|
|
<mesh
|
|
|
|
|
castShadow
|
|
|
|
|
geometry={geometry}
|
|
|
|
|
position={[centerX, centerY, centerZ]}
|
|
|
|
|
rotation={[0, -angle, 0]}
|
|
|
|
|
userData={wall}
|
2025-06-25 17:20:35 +05:30
|
|
|
name={`WallReference_${wall.wallUuid}`}
|
2025-06-25 15:26:53 +05:30
|
|
|
onClick={(e) => {
|
|
|
|
|
if (visible && !togglView && activeModule === 'builder') {
|
2025-06-25 17:20:35 +05:30
|
|
|
if (e.object.userData.wallUuid) {
|
|
|
|
|
setSelectedWall(e.object);
|
|
|
|
|
setSelectedDecal(null);
|
|
|
|
|
|
|
|
|
|
if (wall.decals.length > 0) return;
|
|
|
|
|
const decal: Decal = {
|
|
|
|
|
decalUuid: THREE.MathUtils.generateUUID(),
|
|
|
|
|
decalName: 'Decal',
|
|
|
|
|
decalId: 'Default Decal',
|
|
|
|
|
decalPosition: [0, 0, wall.wallThickness / 2 + 0.001],
|
|
|
|
|
decalRotation: 0,
|
|
|
|
|
decalScale: 1,
|
|
|
|
|
decalType: { type: 'Wall', wallUuid: wall.wallUuid }
|
|
|
|
|
}
|
|
|
|
|
addDecal(wall.wallUuid, decal);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
onPointerMissed={() => {
|
|
|
|
|
if (selectedWall && selectedWall.userData.wallUuid === wall.wallUuid) {
|
|
|
|
|
setSelectedWall(null);
|
2025-06-25 15:26:53 +05:30
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<MeshDiscardMaterial />
|
2025-06-25 17:20:35 +05:30
|
|
|
|
|
|
|
|
{wall.decals.map((decal) => (
|
|
|
|
|
<DecalInstance visible={visible} key={decal.decalUuid} decal={decal} />
|
|
|
|
|
))}
|
2025-06-25 15:26:53 +05:30
|
|
|
</mesh>
|
2025-06-23 09:37:53 +05:30
|
|
|
</mesh>
|
2025-06-10 15:28:23 +05:30
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default Wall;
|