first person camera bug and new project loading screen stuck bug fixed

This commit is contained in:
2025-09-04 13:36:49 +05:30
parent 0d7f5d280f
commit 8271e3c6ce
5 changed files with 187 additions and 219 deletions

View File

@@ -1,12 +1,12 @@
import React from "react"; import React from "react";
import { import {
DocumentationIcon, DocumentationIcon,
HelpIcon, HelpIcon,
HomeIcon, HomeIcon,
LogoutIcon, LogoutIcon,
NotificationIcon, NotificationIcon,
ProjectsIcon, ProjectsIcon,
TutorialsIcon, TutorialsIcon,
} from "../icons/DashboardIcon"; } from "../icons/DashboardIcon";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import darkThemeImage from "../../assets/image/darkThemeProject.png"; import darkThemeImage from "../../assets/image/darkThemeProject.png";
@@ -15,180 +15,174 @@ import { SettingsIcon, TrashIcon } from "../icons/ExportCommonIcons";
import { getUserData } from "../../functions/getUserData"; import { getUserData } from "../../functions/getUserData";
import { useLoadingProgress, useSocketStore } from "../../store/builder/store"; import { useLoadingProgress, useSocketStore } from "../../store/builder/store";
// import { createProject } from "../../services/dashboard/createProject";
interface SidePannelProps { interface SidePannelProps {
setActiveTab: React.Dispatch<React.SetStateAction<string>>; setActiveTab: React.Dispatch<React.SetStateAction<string>>;
activeTab: string; activeTab: string;
} }
const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => { const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
const { email, userName, userId, organization } = getUserData(); const { email, userName, userId, organization } = getUserData();
const navigate = useNavigate(); const navigate = useNavigate();
const { setLoadingProgress } = useLoadingProgress(); const { setLoadingProgress } = useLoadingProgress();
const { projectSocket } = useSocketStore(); const { projectSocket, initializeSocket } = useSocketStore();
const savedTheme = localStorage.getItem("theme") ?? "light"; const savedTheme = localStorage.getItem("theme") ?? "light";
function generateProjectId() { function generateProjectId() {
const randomBytes = new Uint8Array(12); const randomBytes = new Uint8Array(12);
crypto.getRandomValues(randomBytes); crypto.getRandomValues(randomBytes);
return Array.from(randomBytes, (byte) => return Array.from(randomBytes, (byte) =>
byte.toString(16).padStart(2, "0") byte.toString(16).padStart(2, "0")
).join(""); ).join("");
}
const handleCreateNewProject = async () => {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken");
if (!token || !refreshToken) {
console.error('token expired');
return;
} }
try {
const projectId = generateProjectId();
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
//API for creating new Project const handleCreateNewProject = async () => {
// const project = await createProject( const token = localStorage.getItem("token");
// projectId, const refreshToken = localStorage.getItem("refreshToken");
// userId, if (!token || !refreshToken) {
// savedTheme === "dark" ? darkThemeImage : lightThemeImage, console.error('token expired');
// organization return;
// ); }
const addProject = { const projectId = generateProjectId();
userId, initializeSocket(email, organization, token, refreshToken);
thumbnail: savedTheme === "dark" ? darkThemeImage : lightThemeImage,
organization: organization,
projectUuid: projectId,
};
if (projectSocket) { if (projectSocket?.connected) {
const handleResponse = (data: any) => { // SOCKET
if (data.message === "Project created successfully") { const addProject = {
setLoadingProgress(1); userId,
navigate(`/projects/${data.data.projectId}`); thumbnail: savedTheme === "dark" ? darkThemeImage : lightThemeImage,
} organization: organization,
projectSocket.off("v1-project:response:add", handleResponse); // Clean up projectUuid: projectId,
}; };
projectSocket.on("v1-project:response:add", handleResponse); const handleResponse = (data: any) => {
if (data.message === "Project created successfully") {
setLoadingProgress(1);
navigate(`/projects/${data.data.projectId}`);
}
projectSocket.off("v1-project:response:add", handleResponse);
};
projectSocket.on("v1-project:response:add", handleResponse);
projectSocket.emit("v1:project:add", addProject); projectSocket.emit("v1:project:add", addProject);
} else { } else {
console.error("Socket is not connected."); // API
} // const project = await createProject(
} catch (error) { // projectId,
console.error("Error creating project:", error); // userId,
} // savedTheme === "dark" ? darkThemeImage : lightThemeImage,
}; // organization
// );
}
};
return ( return (
<div className="side-pannel-container"> <div className="side-pannel-container">
<div className="side-pannel-header"> <div className="side-pannel-header">
<div className="user-container"> <div className="user-container">
<div className="user-profile"> <div className="user-profile">
{userName?.charAt(0).toUpperCase()} {userName?.charAt(0).toUpperCase()}
</div> </div>
<div className="user-name"> <div className="user-name">
{userName {userName ? userName.charAt(0).toUpperCase() + userName.slice(1).toLowerCase() : "Anonymous"}
? userName.charAt(0).toUpperCase() + </div>
userName.slice(1).toLowerCase() </div>
: "Anonymous"} <div className="notifications-container">
</div> <NotificationIcon />
</div>
</div>
<div
className="new-project-button"
style={{ cursor: "pointer" }}
onClick={handleCreateNewProject}
>
+ New project
</div>
<div className="side-bar-content-container">
<div className="side-bar-options-container">
<div
className={
activeTab === "Home" ? "option-list active" : "option-list"
}
onClick={() => setActiveTab("Home")}
>
<HomeIcon />
Home
</div>
<div
className={
activeTab === "Projects" ? "option-list active" : "option-list"
}
title="Projects"
onClick={() => setActiveTab("Projects")}
>
<ProjectsIcon />
Projects
</div>
<div
className={
activeTab === "Trash" ? "option-list active" : "option-list"
}
title="Trash"
onClick={() => setActiveTab("Trash")}
>
<TrashIcon />
Trash
</div>
<div
className={
activeTab === "Tutorials" ? "option-list active" : "option-list"
}
title="coming soon"
onClick={() => {
// setActiveTab("Tutorials");
console.warn("Tutorials comming soon");
}}
>
<TutorialsIcon />
Tutorials
</div>
<div
className={
activeTab === "Documentation"
? "option-list active"
: "option-list"
}
title="coming soon"
onClick={() => {
// setActiveTab("Documentation");
console.warn("Documentation comming soon");
}}
>
<DocumentationIcon />
Documentation
</div>
</div>
<div className="side-bar-options-container">
<div className="option-list" title="coming soon">
<SettingsIcon />
Settings
</div>
<div
className="option-list"
style={{ cursor: "pointer" }}
onClick={() => {
localStorage.clear();
navigate("/");
}}
>
<LogoutIcon />
Log out
</div>
<div className="option-list" title="coming soon">
<HelpIcon />
Help & Feedback
</div>
</div>
</div>
</div> </div>
<div className="notifications-container"> );
<NotificationIcon />
</div>
</div>
<div
className="new-project-button"
style={{ cursor: "pointer" }}
onClick={handleCreateNewProject}
>
+ New project
</div>
<div className="side-bar-content-container">
<div className="side-bar-options-container">
<div
className={
activeTab === "Home" ? "option-list active" : "option-list"
}
onClick={() => setActiveTab("Home")}
>
<HomeIcon />
Home
</div>
<div
className={
activeTab === "Projects" ? "option-list active" : "option-list"
}
title="Projects"
onClick={() => setActiveTab("Projects")}
>
<ProjectsIcon />
Projects
</div>
<div
className={
activeTab === "Trash" ? "option-list active" : "option-list"
}
title="Trash"
onClick={() => setActiveTab("Trash")}
>
<TrashIcon />
Trash
</div>
<div
className={
activeTab === "Tutorials" ? "option-list active" : "option-list"
}
title="coming soon"
onClick={() => {
// setActiveTab("Tutorials");
console.warn("Tutorials comming soon");
}}
>
<TutorialsIcon />
Tutorials
</div>
<div
className={
activeTab === "Documentation"
? "option-list active"
: "option-list"
}
title="coming soon"
onClick={() => {
// setActiveTab("Documentation");
console.warn("Documentation comming soon");
}}
>
<DocumentationIcon />
Documentation
</div>
</div>
<div className="side-bar-options-container">
<div className="option-list" title="coming soon">
<SettingsIcon />
Settings
</div>
<div
className="option-list"
style={{ cursor: "pointer" }}
onClick={() => {
localStorage.clear();
navigate("/");
}}
>
<LogoutIcon />
Log out
</div>
<div className="option-list" title="coming soon">
<HelpIcon />
Help & Feedback
</div>
</div>
</div>
</div>
);
}; };
export default SidePannel; export default SidePannel;

View File

@@ -72,11 +72,13 @@ function MainScene() {
if (versionHistory.length > 0 && organization && userId) { if (versionHistory.length > 0 && organization && userId) {
recentlyViewed(organization, userId).then((projects) => { recentlyViewed(organization, userId).then((projects) => {
const recent_opened_verisionID = (Object.values(projects?.RecentlyViewed || {})[0] as any)?.Present_version._id; const recent_opened_verisionID = (Object.values(projects?.RecentlyViewed || {})[0] as any)?.Present_version._id;
if (recent_opened_verisionID) { if (recent_opened_verisionID && projects.RecentlyViewed[0]._id === projectId) {
const version = versionHistory.find((ver) => ver.versionId === recent_opened_verisionID); const version = versionHistory.find((ver) => ver.versionId === recent_opened_verisionID);
if (version) { if (version) {
setSelectedVersion(version); setSelectedVersion(version);
} }
} else {
setSelectedVersion(versionHistory[0]);
} }
}) })
} }

View File

@@ -7,7 +7,6 @@ import { useCamMode, useToggleView } from "../../../store/builder/store";
import switchToThirdPerson from "./functions/switchToThirdPerson"; import switchToThirdPerson from "./functions/switchToThirdPerson";
import switchToFirstPerson from "./functions/switchToFirstPerson"; import switchToFirstPerson from "./functions/switchToFirstPerson";
import { detectModifierKeys } from "../../../utils/shortcutkeys/detectModifierKeys"; import { detectModifierKeys } from "../../../utils/shortcutkeys/detectModifierKeys";
import { firstPersonCamera } from "./functions/firstPersonCamera";
const CamMode: React.FC = () => { const CamMode: React.FC = () => {
const { camMode, setCamMode } = useCamMode(); const { camMode, setCamMode } = useCamMode();
@@ -41,14 +40,22 @@ const CamMode: React.FC = () => {
const keyCombination = detectModifierKeys(event); const keyCombination = detectModifierKeys(event);
if (keyCombination === "/" && !isTransitioning && !toggleView) { if (keyCombination === "/" && !isTransitioning && !toggleView) {
firstPersonCamera({ setIsTransitioning && setIsTransitioning(true);
setIsTransitioning,
state, state.controls.mouseButtons.left = CONSTANTS.controlsTransition.leftMouse;
camMode, state.controls.mouseButtons.right = CONSTANTS.controlsTransition.rightMouse;
setCamMode, state.controls.mouseButtons.wheel = CONSTANTS.controlsTransition.wheelMouse;
switchToFirstPerson, state.controls.mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse;
switchToThirdPerson,
}); if (camMode === "ThirdPerson") {
setCamMode("FirstPerson");
await switchToFirstPerson(state.controls, state.camera);
} else if (camMode === "FirstPerson") {
setCamMode("ThirdPerson");
await switchToThirdPerson(state.controls, state.camera);
}
setIsTransitioning && setIsTransitioning(false);
} }
if (keyCombination === 'Shift') { if (keyCombination === 'Shift') {
@@ -77,7 +84,7 @@ const CamMode: React.FC = () => {
if (!state.controls) return; if (!state.controls) return;
if (camMode === "ThirdPerson" || !document.pointerLockElement) return; if (camMode === "ThirdPerson" || !document.pointerLockElement) return;
const speedMultiplier = isShiftActive ? 4 : 1; const speedMultiplier = isShiftActive ? CONSTANTS.firstPersonControls.sprintSpeed : CONSTANTS.firstPersonControls.walkSpeed;
if (forward) { if (forward) {
state.controls.forward(CONSTANTS.firstPersonControls.forwardSpeed * speedMultiplier, true); state.controls.forward(CONSTANTS.firstPersonControls.forwardSpeed * speedMultiplier, true);

View File

@@ -1,39 +0,0 @@
import * as CONSTANTS from "../../../../types/world/worldConstants";
interface FirstPersonCameraProps {
setIsTransitioning?: (value: boolean) => void;
state: any;
}
interface FirstPersonCameraParams extends FirstPersonCameraProps {
camMode: string;
setCamMode: (mode: string) => void;
switchToFirstPerson: (controls: any, camera: any) => Promise<void>;
switchToThirdPerson: (controls: any, camera: any) => Promise<void>;
}
export async function firstPersonCamera({
setIsTransitioning,
state,
camMode,
setCamMode,
switchToFirstPerson,
switchToThirdPerson
}: FirstPersonCameraParams): Promise<void> {
setIsTransitioning && 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 && setIsTransitioning(false);
}

View File

@@ -12,6 +12,8 @@ export type Controls = {
backwardSpeed: number; backwardSpeed: number;
leftSpeed: number; leftSpeed: number;
rightSpeed: number; rightSpeed: number;
walkSpeed: number;
sprintSpeed: number;
}; };
export type ThirdPersonControls = { export type ThirdPersonControls = {
@@ -199,6 +201,8 @@ export const firstPersonControls: Controls = {
backwardSpeed: -0.1, // Speed of backward movement backwardSpeed: -0.1, // Speed of backward movement
leftSpeed: -0.1, // Speed of left movement leftSpeed: -0.1, // Speed of left movement
rightSpeed: 0.1, // Speed of right movement rightSpeed: 0.1, // Speed of right movement
walkSpeed: 1, // Walk speed
sprintSpeed: 4 // Sprint Speed
}; };
export const thirdPersonControls: ThirdPersonControls = { export const thirdPersonControls: ThirdPersonControls = {