feat: Log camera update response data for debugging purposes; adjust user position parameter in findEnvironment function

This commit is contained in:
Jerald-Golden-B 2025-04-05 17:40:46 +05:30
parent 58d82da349
commit c5d4507400
6 changed files with 211 additions and 188 deletions

View File

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

View File

@ -20,7 +20,24 @@ const CollabUserIcon: React.FC<CollabUserIconProps> = ({
{userImage ? ( {userImage ? (
<img className="user-image" src={userImage} alt={userName} /> <img className="user-image" src={userImage} alt={userName} />
) : ( ) : (
<CustomAvatar name={userName} index={index} /> <CustomAvatar name={userName} index={index} color={color} />
// <div
// className="user-image"
// style={{
// lineHeight: "30px",
// textTransform: "uppercase",
// textAlign: "center",
// fontSize: "16px",
// borderRadius: "50%",
// backgroundColor: color,
// overflow: "hidden",
// backgroundSize: "cover",
// backgroundPosition: "center",
// color: "white",
// fontWeight: "bold",
// }}>
// {userName[0]}
// </div>
)} )}
</div> </div>
<div className="user-name" style={{ backgroundColor: color }}> <div className="user-name" style={{ backgroundColor: color }}>

View File

@ -233,7 +233,7 @@ export default function SocketResponses({
} }
} else if (data.message === "Model updated successfully") { } else if (data.message === "Model updated successfully") {
itemsGroup.current.children.forEach((item: THREE.Group) => { itemsGroup.current?.children.forEach((item: THREE.Group) => {
if (item.uuid === data.data.modeluuid) { if (item.uuid === data.data.modeluuid) {
item.position.set(...data.data.position as [number, number, number]); item.position.set(...data.data.position as [number, number, number]);
item.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); item.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z);

View File

@ -7,6 +7,7 @@ interface AvatarProps {
size?: number; size?: number;
index?: number; index?: number;
textColor?: string; textColor?: string;
color?: string; // Optional color prop for future use
} }
const CustomAvatar: React.FC<AvatarProps> = ({ const CustomAvatar: React.FC<AvatarProps> = ({
@ -14,6 +15,7 @@ const CustomAvatar: React.FC<AvatarProps> = ({
size = 100, size = 100,
index = 0, index = 0,
textColor = "#ffffff", textColor = "#ffffff",
color, // Optional color prop for future use
}) => { }) => {
const [imageSrc, setImageSrc] = useState<string | null>(null); const [imageSrc, setImageSrc] = useState<string | null>(null);
@ -26,7 +28,7 @@ const CustomAvatar: React.FC<AvatarProps> = ({
const initials = getInitials(name); // Convert name to initials if needed const initials = getInitials(name); // Convert name to initials if needed
// Draw background // Draw background
ctx.fillStyle = getAvatarColor(index); ctx.fillStyle = color || getAvatarColor(index); // Use color prop or generate color based on index
ctx.fillRect(0, 0, size, size); ctx.fillRect(0, 0, size, size);
// Draw initials // Draw initials
@ -40,7 +42,7 @@ const CustomAvatar: React.FC<AvatarProps> = ({
const dataURL = canvas.toDataURL("image/png"); const dataURL = canvas.toDataURL("image/png");
setImageSrc(dataURL); setImageSrc(dataURL);
} }
}, [name, size, textColor]); }, [name, size, textColor, index]);
if (!imageSrc) { if (!imageSrc) {
return null; // Return null while the image is being generated return null; // Return null while the image is being generated
@ -53,6 +55,18 @@ const CustomAvatar: React.FC<AvatarProps> = ({
alt="User Avatar" alt="User Avatar"
style={{ width: "100%", height: "100%" }} style={{ width: "100%", height: "100%" }}
/> />
// <div
// className="user-image"
// style={{
// width: size,
// height: size,
// borderRadius: "50%",
// overflow: "hidden",
// backgroundSize: "cover",
// backgroundPosition: "center",
// }}>
// {name[0]}
// </div>
); );
}; };

View File

@ -26,7 +26,7 @@ export const findEnvironment = async (organization: string, userId: string) => {
false, false,
false, false,
false, false,
0, 40,
true true
); );
return userpos; return userpos;

View File

@ -14,7 +14,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
const socket = io( const socket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`, `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`,
{ {
reconnection: false, reconnection: true,
auth: { email, organization }, auth: { email, organization },
} }
); );
@ -22,7 +22,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
const visualizationSocket = io( const visualizationSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization`, `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization`,
{ {
reconnection: false, reconnection: true,
auth: { email, organization }, auth: { email, organization },
} }
); );
@ -302,7 +302,13 @@ export const useDrieTemp = create<any>((set: any) => ({
export const useActiveUsers = create<any>((set: any) => ({ export const useActiveUsers = create<any>((set: any) => ({
activeUsers: [], activeUsers: [],
setActiveUsers: (x: any) => set({ activeUsers: x }), setActiveUsers: (callback: (prev: any[]) => any[] | any[]) =>
set((state: { activeUsers: any[] }) => ({
activeUsers:
typeof callback === "function"
? callback(state.activeUsers)
: callback,
})),
})); }));
export const useDrieUIValue = create<any>((set: any) => ({ export const useDrieUIValue = create<any>((set: any) => ({