add initial components and utility functions for simulation and builder modules

This commit is contained in:
2025-03-25 14:00:03 +05:30
parent 61b3c4ee2c
commit 2303682a15
164 changed files with 13967 additions and 52 deletions

View File

@@ -0,0 +1,89 @@
import { useFrame, useThree } from '@react-three/fiber';
import React, { useEffect, useState } from 'react';
import * as CONSTANTS from '../../../types/world/worldConstants';
import { useCamMode, useToggleView } from '../../../store/store';
import { useKeyboardControls } from '@react-three/drei';
import switchToThirdPerson from './switchToThirdPerson';
import switchToFirstPerson from './switchToFirstPerson';
const CamMode: React.FC = () => {
const { camMode, setCamMode } = useCamMode();
const [, get] = useKeyboardControls()
const [isTransitioning, setIsTransitioning] = useState(false);
const state: any = useThree();
const { toggleView } = useToggleView();
useEffect(() => {
const handlePointerLockChange = async () => {
if (document.pointerLockElement && !toggleView) {
// console.log('Pointer is locked');
} else {
// console.log('Pointer is unlocked');
if (camMode === "FirstPerson" && !toggleView) {
setCamMode("ThirdPerson");
await switchToThirdPerson(state.controls, state.camera);
}
}
};
document.addEventListener('pointerlockchange', handlePointerLockChange);
return () => {
document.removeEventListener('pointerlockchange', handlePointerLockChange);
};
}, [camMode, toggleView, setCamMode, state.controls, state.camera]);
useEffect(() => {
const handleKeyPress = async (event: any) => {
if (!state.controls) return;
if (event.key === "/" && !isTransitioning && !toggleView) {
setIsTransitioning(true);
state.controls.mouseButtons.left = CONSTANTS.controlsTransition.leftMouse;
state.controls.mouseButtons.right = CONSTANTS.controlsTransition.rightMouse;
state.controls.mouseButtons.wheel = CONSTANTS.controlsTransition.wheelMouse;
state.controls.mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse;
if (camMode === 'ThirdPerson') {
setCamMode("FirstPerson");
await switchToFirstPerson(state.controls, state.camera);
} else if (camMode === "FirstPerson") {
setCamMode("ThirdPerson");
await switchToThirdPerson(state.controls, state.camera);
}
setIsTransitioning(false);
}
};
window.addEventListener("keydown", handleKeyPress);
return () => {
window.removeEventListener("keydown", handleKeyPress);
};
}, [camMode, isTransitioning, toggleView, state.controls, state.camera, setCamMode]);
useFrame(() => {
const { forward, backward, left, right } = get();
if (!state.controls) return
if (!state.controls || camMode === "ThirdPerson" || !document.pointerLockElement) return;
if (forward) {
state.controls.forward(CONSTANTS.firstPersonControls.forwardSpeed, true)
}
if (backward) {
state.controls.forward(CONSTANTS.firstPersonControls.backwardSpeed, true)
}
if (left) {
state.controls.truck(CONSTANTS.firstPersonControls.leftSpeed, 0, true)
}
if (right) {
state.controls.truck(CONSTANTS.firstPersonControls.rightSpeed, 0, true)
}
});
return (
<></>
);
};
export default CamMode;

View File

@@ -0,0 +1,25 @@
import * as THREE from 'three';
import * as CONSTANTS from '../../../types/world/worldConstants';
export default async function switchToFirstPerson(
controls: any,
camera: any
) {
if (!controls) return;
const cameraDirection = new THREE.Vector3();
camera.getWorldDirection(cameraDirection);
cameraDirection.normalize();
await controls.setPosition(camera.position.x, 2, camera.position.z, true);
controls.setTarget(camera.position.x, 2, camera.position.z, true);
controls.mouseButtons.left = CONSTANTS.firstPersonControls.leftMouse;
controls.lockPointer();
controls.azimuthRotateSpeed = CONSTANTS.firstPersonControls.azimuthRotateSpeed;
controls.polarRotateSpeed = CONSTANTS.firstPersonControls.polarRotateSpeed;
controls.truckSpeed = CONSTANTS.firstPersonControls.truckSpeed;
controls.minDistance = CONSTANTS.firstPersonControls.minDistance;
controls.maxDistance = CONSTANTS.firstPersonControls.maxDistance;
controls.maxPolarAngle = CONSTANTS.firstPersonControls.maxPolarAngle;
}

View File

@@ -0,0 +1,29 @@
import * as THREE from 'three';
import * as CONSTANTS from '../../../types/world/worldConstants';
export default async function switchToThirdPerson(
controls: any,
camera: any
) {
if (!controls) return;
controls.mouseButtons.left = CONSTANTS.thirdPersonControls.leftMouse;
controls.mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse;
controls.mouseButtons.middle = CONSTANTS.thirdPersonControls.middleMouse;
controls.mouseButtons.wheel = CONSTANTS.thirdPersonControls.wheelMouse;
controls.unlockPointer();
const cameraDirection = new THREE.Vector3();
camera.getWorldDirection(cameraDirection);
const targetOffset = cameraDirection.multiplyScalar(CONSTANTS.thirdPersonControls.targetOffset);
const targetPosition = new THREE.Vector3(camera.position.x, camera.position.y, camera.position.z).add(targetOffset);
controls.setPosition(camera.position.x, CONSTANTS.thirdPersonControls.cameraHeight, camera.position.z, true);
controls.setTarget(targetPosition.x, 0, targetPosition.z, true);
controls.azimuthRotateSpeed = CONSTANTS.thirdPersonControls.azimuthRotateSpeed;
controls.polarRotateSpeed = CONSTANTS.thirdPersonControls.polarRotateSpeed;
controls.truckSpeed = CONSTANTS.thirdPersonControls.truckSpeed;
controls.minDistance = CONSTANTS.threeDimension.minDistance;
controls.maxDistance = CONSTANTS.thirdPersonControls.maxDistance;
controls.maxPolarAngle = CONSTANTS.thirdPersonControls.maxPolarAngle;
}

View File

@@ -0,0 +1,70 @@
import * as THREE from "three";
import { useEffect, useRef } from "react";
import { useToggleView } from "../../../store/store";
import { useThree } from "@react-three/fiber";
import { getCamera } from "../../../services/factoryBuilder/camera/getCameraApi";
import * as CONSTANTS from '../../../types/world/worldConstants';
export default function SwitchView() {
const { toggleView } = useToggleView();
const state: any = useThree();
const { set } = useThree();
const perspectiveCamera = useRef<THREE.PerspectiveCamera | null>(null);
const orthoCamera = useRef<THREE.OrthographicCamera | null>(null);
orthoCamera.current = new THREE.OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 0.01, 1000);
perspectiveCamera.current = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 1000);
useEffect(() => {
if (!perspectiveCamera.current || !orthoCamera.current) return;
if (toggleView) {
orthoCamera.current.zoom = 10;
orthoCamera.current.position.set(...CONSTANTS.twoDimension.defaultPosition);
orthoCamera.current.lookAt(new THREE.Vector3(...CONSTANTS.twoDimension.defaultTarget));
orthoCamera.current.updateProjectionMatrix();
set({ camera: orthoCamera.current });
orthoCamera.current.updateProjectionMatrix();
} else if (!toggleView) {
perspectiveCamera.current.position.set(...CONSTANTS.threeDimension.defaultPosition);
perspectiveCamera.current.lookAt(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget));
set({ camera: perspectiveCamera.current });
}
}, [toggleView, set]);
useEffect(() => {
if (toggleView && state.controls) {
state.controls.mouseButtons.left = CONSTANTS.twoDimension.leftMouse;
state.controls.mouseButtons.right = CONSTANTS.twoDimension.rightMouse;
} else {
try {
const email = localStorage.getItem('email');
const organization = (email!.split("@")[1]).split(".")[0];
getCamera(organization, localStorage.getItem('userId')!).then((data) => {
if (data && data.position && data.target) {
state.controls?.setPosition(data.position.x, data.position.y, data.position.z);
state.controls?.setTarget(data.target.x, data.target.y, data.target.z);
localStorage.setItem("cameraPosition", JSON.stringify(data.position));
localStorage.setItem("controlTarget", JSON.stringify(data.target));
} else {
state.controls?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
state.controls?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
localStorage.setItem("cameraPosition", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition)));
localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget)));
}
});
} catch (error) {
console.error("Failed to retrieve camera position or target:", error);
state.controls?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
state.controls?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
}
if (state.controls) {
state.controls.mouseButtons.left = CONSTANTS.threeDimension.leftMouse;
state.controls.mouseButtons.right = CONSTANTS.threeDimension.rightMouse;
}
}
}, [toggleView, state.controls]);
return (
<></>
);
}

View File

@@ -0,0 +1,26 @@
import { Socket } from "socket.io-client";
import * as THREE from 'three';
export default function updateCamPosition(
controls: any,
socket: Socket,
position: THREE.Vector3,
rotation: THREE.Euler
) {
if (!controls.current) return;
const target = controls.current.getTarget(new THREE.Vector3());
const email = localStorage.getItem("email");
const organization = email!.split("@")[1].split(".")[0];
const camData = {
organization: organization,
userId: localStorage.getItem("userId")!,
position: position,
target: new THREE.Vector3(target.x, 0, target.z),
rotation: new THREE.Vector3(rotation.x, rotation.y, rotation.z),
socketId: socket.id,
};
socket.emit("v1:Camera:set", camData);
localStorage.setItem("cameraPosition", JSON.stringify(position));
localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(target.x, 0, target.z)));
}