Dwinzo_dev/app/src/modules/collaboration/collabCams.tsx

206 lines
6.3 KiB
TypeScript

import * as THREE from "three";
import { useEffect, useRef, useState } from "react";
import { useFrame } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import camModel from "../../assets/gltf-glb/camera face 2.gltf";
import getActiveUsersData from "../../services/factoryBuilder/collab/getActiveUsers";
import { useActiveUsers, useSocketStore } from "../../store/store";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { useNavigate } from "react-router-dom";
import { Html } from "@react-three/drei";
import CollabUserIcon from "./collabUserIcon";
import { getAvatarColor } from "./users/functions/getAvatarColor";
const CamModelsGroup = () => {
let navigate = useNavigate();
const groupRef = useRef<THREE.Group>(null);
const email = localStorage.getItem("email");
const { activeUsers, setActiveUsers } = useActiveUsers();
const { socket } = useSocketStore();
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
const [cams, setCams] = useState<any[]>([]);
const [models, setModels] = useState<
Record<
string,
{ targetPosition: THREE.Vector3; targetRotation: THREE.Euler }
>
>({});
dracoLoader.setDecoderPath("three/examples/jsm/libs/draco/gltf/");
loader.setDRACOLoader(dracoLoader);
useEffect(() => {
if (!email) {
navigate("/");
}
if (!socket) return;
const organization = email!.split("@")[1].split(".")[0];
socket.on("userConnectRespones", (data: any) => {
if (!groupRef.current) return;
if (data.data.userData.email === email) return;
if (socket.id === data.socketId || organization !== data.organization)
return;
const model = groupRef.current.getObjectByProperty(
"uuid",
data.data.userData._id
);
if (model) {
groupRef.current.remove(model);
}
loader.load(camModel, (gltf) => {
const newModel = gltf.scene.clone();
newModel.uuid = data.data.userData._id;
newModel.position.set(
data.data.position.x,
data.data.position.y,
data.data.position.z
);
newModel.rotation.set(
data.data.rotation.x,
data.data.rotation.y,
data.data.rotation.z
);
newModel.userData = data.data.userData;
setCams((prev) => [...prev, newModel]);
setActiveUsers([...activeUsers, data.data.userData]);
});
});
socket.on("userDisConnectRespones", (data: any) => {
if (!groupRef.current) return;
if (socket.id === data.socketId || organization !== data.organization)
return;
setCams((prev) =>
prev.filter((cam) => cam.uuid !== data.data.userData._id)
);
setActiveUsers(
activeUsers.filter((user: any) => user._id !== data.data.userData._id)
);
});
socket.on("cameraUpdateResponse", (data: any) => {
if (
!groupRef.current ||
socket.id === data.socketId ||
organization !== data.organization
)
return;
setModels((prev) => ({
...prev,
[data.data.userId]: {
targetPosition: new THREE.Vector3(
data.data.position.x,
data.data.position.y,
data.data.position.z
),
targetRotation: new THREE.Euler(
data.data.rotation.x,
data.data.rotation.y,
data.data.rotation.z
),
},
}));
});
return () => {
socket.off("userConnectRespones");
socket.off("userDisConnectRespones");
socket.off("cameraUpdateResponse");
};
}, [socket, activeUsers]);
useFrame(() => {
if (!groupRef.current) return;
Object.keys(models).forEach((uuid) => {
const model = groupRef.current!.getObjectByProperty("uuid", uuid);
if (!model) return;
const { targetPosition, targetRotation } = models[uuid];
model.position.lerp(targetPosition, 0.1);
model.rotation.x = THREE.MathUtils.lerp(
model.rotation.x,
targetRotation.x,
0.1
);
model.rotation.y = THREE.MathUtils.lerp(
model.rotation.y,
targetRotation.y,
0.1
);
model.rotation.z = THREE.MathUtils.lerp(
model.rotation.z,
targetRotation.z,
0.1
);
});
});
useEffect(() => {
if (!groupRef.current) return;
const organization = email!.split("@")[1].split(".")[0];
getActiveUsersData(organization).then((data) => {
const filteredData = data.cameraDatas.filter(
(camera: any) => camera.userData.email !== email
);
if (filteredData.length > 0) {
loader.load(camModel, (gltf) => {
const newCams = filteredData.map((cam: any) => {
const newModel = gltf.scene.clone();
newModel.uuid = cam.userData._id;
newModel.position.set(
cam.position.x,
cam.position.y,
cam.position.z
);
newModel.rotation.set(
cam.rotation.x,
cam.rotation.y,
cam.rotation.z
);
newModel.userData = cam.userData;
console.log('cam.userData: ', cam.userData);
setActiveUsers([...activeUsers, cam.userData]);
return newModel;
});
setCams((prev) => [...prev, ...newCams]);
});
}
});
}, []);
return (
<group ref={groupRef} name="Cam-Model-Group">
{cams.map((cam, index) => (
<primitive key={index} object={cam}>
<Html
as="div"
center
zIndexRange={[1, 0]}
sprite
style={{
color: "white",
textAlign: "center",
fontFamily: "Arial, sans-serif",
}}
position={[-0.015, 0, 0.7]}
>
<CollabUserIcon
userImage={""}
userName={cam.userData.userName}
index={index}
color={getAvatarColor(index)}
/>
</Html>
</primitive>
))}
</group>
);
};
export default CamModelsGroup;