diff --git a/app/src/components/layout/sidebarRight/Header.tsx b/app/src/components/layout/sidebarRight/Header.tsx index 0affe0e..3e29112 100644 --- a/app/src/components/layout/sidebarRight/Header.tsx +++ b/app/src/components/layout/sidebarRight/Header.tsx @@ -1,6 +1,6 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import orgImg from "../../../assets/image/orgTemp.png"; -import { useCamMode } from "../../../store/builder/store"; +import { useCamMode, useToggleView } from "../../../store/builder/store"; import CollaborationPopup from "../../templates/CollaborationPopup"; import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor"; import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore"; @@ -16,28 +16,37 @@ const Header: React.FC = () => { const { userId, userName } = getUserData(); const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore(); const { activeModule } = useModuleStore(); + const { toggleView } = useToggleView(); const guestUsers = collabUsers.filter((user) => user.userId !== userId); const [userManagement, setUserManagement] = useState(false); - const { setSelectedUser } = useSelectedUserStore(); + const { selectedUser, setSelectedUser, clearSelectedUser } = useSelectedUserStore(); const { setCamMode } = useCamMode(); - function handleUserFollow(user: any, index: number) { + useEffect(() => { + if ((activeModule !== "builder" && activeModule !== "simulation") || (toggleView && selectedUser)) { + clearSelectedUser(); + } + }, [toggleView, activeModule, selectedUser]); + + function handleUserFollow(user: CollabUsersScheme, index: number) { + if (toggleView || (activeModule !== "builder" && activeModule !== "simulation")) return; + const position = { - x: user.position?.x!, - y: user.position?.y!, - z: user.position?.z!, + x: user.camData.position.x, + y: user.camData.position.y, + z: user.camData.position.z, }; const target = { - x: user.target?.x!, - y: user.target?.y!, - z: user.target?.z!, + x: user.camData.position.x, + y: user.camData.position.y, + z: user.camData.position.z, }; const rotation = { - x: user.rotation?.x!, - y: user.rotation?.y!, - z: user.rotation?.z!, + x: user.camData.position.x, + y: user.camData.position.y, + z: user.camData.position.z, }; // retun on no data @@ -47,7 +56,7 @@ const Header: React.FC = () => { setSelectedUser({ color: getAvatarColor(index, user.userId), name: user.userName, - id: user.id, + id: user.userId, location: { position, rotation, target }, }); setCamMode("FollowPerson"); diff --git a/app/src/modules/collaboration/camera/collabCamFollow.tsx b/app/src/modules/collaboration/camera/collabCamFollow.tsx new file mode 100644 index 0000000..3da35de --- /dev/null +++ b/app/src/modules/collaboration/camera/collabCamFollow.tsx @@ -0,0 +1,26 @@ +import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore"; +import { useFrame } from "@react-three/fiber"; +import { CameraControls } from "@react-three/drei"; + +function CollabCamFollow() { + const { selectedUser } = useSelectedUserStore(); + + useFrame((state) => { + if (!selectedUser || !state.controls || !selectedUser.location) return; + const controls = state.controls as CameraControls; + + controls.setLookAt( + selectedUser.location.position.x, + selectedUser.location.position.y, + selectedUser.location.position.z, + selectedUser.location.target.x, + selectedUser.location.target.y, + selectedUser.location.target.z, + true + ); + }); + + return null; +} + +export default CollabCamFollow; diff --git a/app/src/modules/collaboration/camera/collabCams.tsx b/app/src/modules/collaboration/camera/collabCams.tsx index 88871ea..e6b4a04 100644 --- a/app/src/modules/collaboration/camera/collabCams.tsx +++ b/app/src/modules/collaboration/camera/collabCams.tsx @@ -3,6 +3,7 @@ import { Html, useGLTF } from "@react-three/drei"; import { useRef } from "react"; import { useFrame } from "@react-three/fiber"; import { useSceneContext } from "../../scene/sceneContext"; +import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore"; import { getUserData } from "../../../functions/getUserData"; import { getAvatarColor } from "../functions/getAvatarColor"; @@ -31,6 +32,7 @@ const CamModel = ({ user, model, index }: { user: CollabUsersScheme; model: THRE const targetPos = new THREE.Vector3(); const targetQuat = new THREE.Quaternion(); + const { selectedUser, updateLocation } = useSelectedUserStore(); useFrame((_, delta) => { if (ref.current) { @@ -40,11 +42,22 @@ const CamModel = ({ user, model, index }: { user: CollabUsersScheme; model: THRE ref.current.position.lerp(targetPos, 5 * delta); ref.current.quaternion.slerp(targetQuat, 5 * delta); + + if (selectedUser && selectedUser.id === user.userId) { + const pos = ref.current.position; + const rot = new THREE.Euler().setFromQuaternion(ref.current.quaternion); + + updateLocation({ + position: { x: pos.x, y: pos.y, z: pos.z }, + rotation: { x: rot.x, y: rot.y, z: rot.z }, + target: user.camData.target, + }); + } } }); return ( - + = ({ - userImage, - userName, - id, - color, - position, - rotation, - target, -}) => { +const CollabUserIcon: React.FC = ({ userImage, userName, id, color, position, rotation, target }) => { const { setSelectedUser } = useSelectedUserStore(); const { setCamMode } = useCamMode(); + return (
{userName} diff --git a/app/src/modules/collaboration/collaboration.tsx b/app/src/modules/collaboration/collaboration.tsx index 828e242..1f08719 100644 --- a/app/src/modules/collaboration/collaboration.tsx +++ b/app/src/modules/collaboration/collaboration.tsx @@ -1,5 +1,6 @@ import React from "react"; import CamModelsGroup from "./camera/collabCams"; +import CollabCamFollow from "./camera/collabCamFollow"; import ThreadsGroup from "./threads/threadsGroup"; import SocketResponses from "./socket/socketResponses"; @@ -8,6 +9,8 @@ const Collaboration: React.FC = () => { <> + + diff --git a/app/src/store/collaboration/useCollabStore.ts b/app/src/store/collaboration/useCollabStore.ts index 2f7721d..8e3eee1 100644 --- a/app/src/store/collaboration/useCollabStore.ts +++ b/app/src/store/collaboration/useCollabStore.ts @@ -4,33 +4,28 @@ interface SelectedUser { color: string; name: string; id: string; - location?: { - position: { - x: number; - y: number; - z: number; - }; - rotation?: { - x: number; - y: number; - z: number; - }; - target?: { - x: number; - y: number; - z: number; - }; - }; + location?: { position: { x: number; y: number; z: number }; rotation: { x: number; y: number; z: number }; target: { x: number; y: number; z: number } }; } interface SelectedUserStore { selectedUser: SelectedUser | null; setSelectedUser: (user: SelectedUser) => void; clearSelectedUser: () => void; + updateLocation: (location: { position: { x: number; y: number; z: number }; rotation: { x: number; y: number; z: number }; target: { x: number; y: number; z: number } }) => void; } export const useSelectedUserStore = create((set) => ({ selectedUser: null, setSelectedUser: (user) => set({ selectedUser: user }), clearSelectedUser: () => set({ selectedUser: null }), + updateLocation: (location) => + set((state) => { + if (!state.selectedUser) return state; + return { + selectedUser: { + ...state.selectedUser, + location: location, + }, + }; + }), }));