added follow cam
This commit is contained in:
@@ -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");
|
||||
|
||||
26
app/src/modules/collaboration/camera/collabCamFollow.tsx
Normal file
26
app/src/modules/collaboration/camera/collabCamFollow.tsx
Normal file
@@ -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;
|
||||
@@ -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 (
|
||||
<group ref={ref}>
|
||||
<group visible={false} ref={ref}>
|
||||
<primitive object={model.clone()} />
|
||||
<Html
|
||||
as="div"
|
||||
|
||||
@@ -25,17 +25,10 @@ interface CollabUserIconProps {
|
||||
};
|
||||
}
|
||||
|
||||
const CollabUserIcon: React.FC<CollabUserIconProps> = ({
|
||||
userImage,
|
||||
userName,
|
||||
id,
|
||||
color,
|
||||
position,
|
||||
rotation,
|
||||
target,
|
||||
}) => {
|
||||
const CollabUserIcon: React.FC<CollabUserIconProps> = ({ userImage, userName, id, color, position, rotation, target }) => {
|
||||
const { setSelectedUser } = useSelectedUserStore();
|
||||
const { setCamMode } = useCamMode();
|
||||
|
||||
return (
|
||||
<div className="collab-user-live-container">
|
||||
<button
|
||||
@@ -53,11 +46,7 @@ const CollabUserIcon: React.FC<CollabUserIconProps> = ({
|
||||
setCamMode("FollowPerson");
|
||||
}}
|
||||
>
|
||||
{userImage ? (
|
||||
<img className="user-image" src={userImage} alt={userName} />
|
||||
) : (
|
||||
<CustomAvatar name={userName} color={color} />
|
||||
)}
|
||||
{userImage ? <img className="user-image" src={userImage} alt={userName} /> : <CustomAvatar name={userName} color={color} />}
|
||||
</button>
|
||||
<div className="user-name" style={{ backgroundColor: color }}>
|
||||
{userName}
|
||||
|
||||
@@ -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 = () => {
|
||||
<>
|
||||
<CamModelsGroup />
|
||||
|
||||
<CollabCamFollow />
|
||||
|
||||
<ThreadsGroup />
|
||||
|
||||
<SocketResponses />
|
||||
|
||||
@@ -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<SelectedUserStore>((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,
|
||||
},
|
||||
};
|
||||
}),
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user