Compare commits

...

30 Commits

Author SHA1 Message Date
a3b2d258cf socket and api integerated successfully 2025-09-02 10:48:58 +05:30
4bfd0cf937 Merge branch 'main-dev' into dev-api-socket-coordination 2025-09-02 09:50:37 +05:30
ae4fd2ff01 store optimization 2025-09-02 09:46:27 +05:30
d5d064b875 Merge remote-tracking branch 'origin/main-demo' into main-dev 2025-09-02 09:17:08 +05:30
cfc1f2dee8 Merge branch 'main-dev' of http://185.100.212.76:7778/Dwinzo-Beta/Dwinzo_Demo into main-dev 2025-09-02 09:16:45 +05:30
0ac2bde6d3 code optimization 2025-09-02 09:16:41 +05:30
1cef2987a6 logout theme fix 2025-09-01 18:30:03 +05:30
0ab0510daf refactor: remove unused handleDecalUp function and clean up event handlers 2025-09-01 18:22:27 +05:30
6f9da9e9c0 bug fix 2025-09-01 18:04:59 +05:30
8e7c5a1aa0 added api fallback for sockets 2025-09-01 17:36:40 +05:30
765f4acb57 store optimization 2025-09-01 15:29:06 +05:30
ef98b3c1a3 optimized old zustand store and post processing outlines 2025-09-01 15:09:04 +05:30
09c909c377 decal drop bug fix 2025-09-01 12:37:09 +05:30
7d7100893c simulation and decal bug fix 2025-09-01 11:42:24 +05:30
9825c3ef12 worker img update 2025-08-29 17:58:37 +05:30
3bc0e28267 - online off line status updated
- echo added to rename
2025-08-29 17:47:29 +05:30
f9d314b69f decal default scale scale update 2025-08-29 17:16:50 +05:30
b956ed57e8 human resource management profile ui fix 2025-08-29 17:07:00 +05:30
df36ee0366 Merge remote-tracking branch 'origin/dev-resourceManagement' into main-demo 2025-08-29 16:58:27 +05:30
ef9c3a9c63 dashboard sidebar updated 2025-08-29 16:39:14 +05:30
62ddc1c25f styles file name updated 2025-08-29 16:26:49 +05:30
1b161b2176 - 404-page added and fallback for project not found
- page nav handling for project-not-found updated
2025-08-29 16:24:03 +05:30
a14f7fcf6a dashboard kebab bug fix 2025-08-29 15:14:24 +05:30
b6783f99d3 refactor: reorganize asset management components and enhance search functionality 2025-08-29 13:47:07 +05:30
b2311ab186 Merge remote-tracking branch 'origin/decal-list' into main-demo 2025-08-29 12:52:50 +05:30
e23e339ed3 decal scale fix 2025-08-29 10:10:54 +05:30
1d2a42b7bd Merge branch 'main-demo' into dev-resourceManagement 2025-08-26 09:36:42 +05:30
6fa4d5323d feat: add asset thumbnail fetching and update worker data display in Hrm component 2025-08-26 09:36:09 +05:30
6026c3b82b refactor: remove unnecessary console logs in asset management and thumbnail fetching 2025-08-25 18:16:02 +05:30
358ce22767 feat: implement asset thumbnail fetching and update Hrm and AssetManagement components to use asset data 2025-08-25 18:13:57 +05:30
140 changed files with 4562 additions and 4444 deletions

View File

@@ -7,6 +7,7 @@ import UserAuth from "./pages/UserAuth";
import "./styles/main.scss";
import { LoggerProvider } from "./components/ui/log/LoggerContext";
import ForgotPassword from "./pages/ForgotPassword";
import PageNotFound from "./pages/PageNotFound";
const App: React.FC = () => {
@@ -23,6 +24,7 @@ const App: React.FC = () => {
<Route path="/forgot" element={<ForgotPassword />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/projects/:projectId" element={<Project />} />
<Route path="*" element={<PageNotFound />} />
</Routes>
</Router>
</LoggerProvider>

View File

@@ -0,0 +1,9 @@
<svg width="435" height="192" viewBox="0 0 435 192" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M434.294 35.8327L419.597 87.2712C406.577 88.0129 399.354 88.9272 386.529 90.946L393.877 59.3474L332.885 112.991L377.711 126.218L379.915 115.93C393.611 111.893 401.218 109.947 414.453 107.847L407.84 134.301L427.681 140.18L419.597 167.37L401.226 162.226L392.407 191.62L362.279 183.537L369.627 151.938L297.612 132.097L304.961 104.173L398.286 24.8093L434.294 35.8327Z" fill="#0F0F0F"/>
<path d="M107.287 110.787L127.128 106.378L132.271 133.567L113.9 137.976L119.779 168.84L86.7109 176.923L80.833 144.59L63.9316 148.999C72.6686 121.327 81.38 109.098 102.144 91.6804L107.287 110.787Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M204.287 0.55928C212.617 -0.162914 217.275 -0.209574 225.598 0.55928C254.396 3.22002 271.652 31.4235 274.832 50.529C276.587 61.0745 277.015 67.0381 277.037 77.7185C265.905 97.6708 263.444 104.779 252.787 126.218C243.954 141.438 233.146 152.429 218.249 162.226C186.397 160.022 167.896 140.12 157.991 109.317C154.89 92.6487 155.445 73.5003 156.521 59.3474C158.678 31.0003 174.892 6.89136 204.287 0.55928ZM217.147 23.9997C197.265 23.9997 181.147 48.624 181.147 78.9997C181.147 109.375 197.265 134 217.147 134C237.029 133.999 253.147 109.375 253.147 78.9997C253.147 48.6243 237.029 24.0001 217.147 23.9997Z" fill="#0F0F0F"/>
<path d="M99.2041 71.1052L66.1357 81.3923L60.2568 50.529L29.3936 126.953L66.1357 120.34C58.6892 132.967 56.9985 139.297 54.3779 150.468L7.34766 160.757L0 131.362L49.2344 17.4606L85.2422 10.113L99.2041 71.1052Z" fill="#0F0F0F"/>
<path d="M277.037 96.8249C275.203 113.08 274.273 122.314 268.953 134.301C257.417 152.202 250.176 154.67 237.354 160.021C254.909 142.239 264.111 127.901 277.037 96.8249Z" fill="#0F0F0F"/>
<path d="M99.2041 81.3923C89.3926 88.8475 83.8084 94.1174 73.4844 109.317L68.3398 91.6804L99.2041 81.3923Z" fill="#0F0F0F"/>
<path d="M383.59 100.499C397.029 98.1517 404.407 97.8166 417.393 98.2946C404.464 99.701 397.094 100.893 383.59 104.173V100.499Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -1,4 +1,5 @@
import React, { useState, useRef, useEffect, act } from "react";
import React, { useState, useRef } from "react";
import { createPortal } from "react-dom";
import img from "../../assets/image/image.png";
import { useNavigate } from "react-router-dom";
import { getUserData } from "../../functions/getUserData";
@@ -7,11 +8,11 @@ import {
useProjectName,
useSocketStore,
} from "../../store/builder/store";
import { viewProject } from "../../services/dashboard/viewProject";
import OuterClick from "../../utils/outerClick";
import { KebabIcon } from "../icons/ExportCommonIcons";
import { getAllProjects } from "../../services/dashboard/getAllProjects";
import { updateProject } from "../../services/dashboard/updateProject";
// import { viewProject } from "../../services/dashboard/viewProject";
// import { updateProject } from "../../services/dashboard/updateProject";
interface DashBoardCardProps {
projectName: string;
@@ -69,9 +70,9 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
const kebabRef = useRef<HTMLDivElement>(null);
const navigateToProject = async (e: any) => {
if (active && active == "trash") return;
if (active && active === "trash") return;
try {
const viewProjects = await viewProject(organization, projectId, userId);
// const viewProjects = await viewProject(organization, projectId, userId);
setLoadingProgress(1);
setProjectName(projectName);
@@ -96,13 +97,13 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
case "open in new tab":
try {
if (active === "shared" && createdBy) {
const newTab = await viewProject(
organization,
projectId,
createdBy?._id
);
// const newTab = await viewProject(
// organization,
// projectId,
// createdBy?._id
// );
} else {
const newTab = await viewProject(organization, projectId, userId);
// const newTab = await viewProject(organization, projectId, userId);
setProjectName(projectName);
setIsKebabOpen(false);
@@ -226,7 +227,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
className="dashboard-card-container"
onClick={navigateToProject}
title={projectName}
onMouseLeave={() => setIsKebabOpen(false)}
// onMouseLeave={() => setIsKebabOpen(false)}
>
<div className="dashboard-card-wrapper">
<div className="preview-container">
@@ -267,7 +268,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
)}
{createdAt && (
<div className="project-data">
{active && active == "trash" ? `Trashed by you` : `Edited `}{" "}
{active && active === "trash" ? `Trashed by you` : `Edited `}{" "}
{getRelativeTime(createdAt)}
</div>
)}
@@ -292,22 +293,37 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
</div>
</div>
</div>
{isKebabOpen && (
<div className="kebab-options-wrapper">
{getOptions().map((option) => (
<button
key={option}
className="option"
onClick={(e) => {
e.stopPropagation();
handleOptionClick(option);
}}
>
{option}
</button>
))}
</div>
)}
{isKebabOpen &&
createPortal(
<div
className="kebab-options-wrapper"
style={{
position: "fixed",
zIndex: 9999,
top: kebabRef.current
? kebabRef.current.getBoundingClientRect().bottom +
window.scrollY
: 0,
left: kebabRef.current
? kebabRef.current.getBoundingClientRect().left + window.scrollX
: 0,
}}
>
{getOptions().map((option) => (
<button
key={option}
className="option"
onClick={(e) => {
e.stopPropagation();
handleOptionClick(option);
}}
>
{option}
</button>
))}
</div>,
document.body
)}
</button>
);
};

View File

@@ -39,7 +39,7 @@ const DashboardHome: React.FC = () => {
if (JSON.stringify(projects) !== JSON.stringify(recentProjects)) {
setRecentProjects(projects);
}
} catch (error) {}
} catch (error) { }
};
const handleRecentProjectSearch = async (inputValue: string) => {
@@ -66,7 +66,7 @@ const DashboardHome: React.FC = () => {
// );
//
//socket for delete Project
// SOCKET for delete Project
const deleteProject = {
projectId,
organization,
@@ -90,7 +90,7 @@ const DashboardHome: React.FC = () => {
};
});
setIsSearchActive(false);
} catch (error) {}
} catch (error) { }
};
const handleDuplicateRecentProject = async (
@@ -98,15 +98,18 @@ const DashboardHome: React.FC = () => {
projectName: string,
thumbnail: string
) => {
const duplicateRecentProjectData = {
userId,
thumbnail,
organization,
projectUuid: generateUniqueId(),
refProjectID: projectId,
projectName,
};
projectSocket.emit("v1:project:Duplicate", duplicateRecentProjectData);
if (projectSocket) {
const duplicateRecentProjectData = {
userId,
thumbnail,
organization,
projectUuid: generateUniqueId(),
refProjectID: projectId,
projectName,
};
projectSocket.emit("v1:project:Duplicate", duplicateRecentProjectData);
}
};
const renderProjects = () => {

View File

@@ -60,7 +60,7 @@ const DashboardProjects: React.FC = () => {
if (JSON.stringify(projects) !== JSON.stringify(workspaceProjects)) {
setWorkspaceProjects(projects);
}
} catch (error) {}
} catch (error) { }
};
const handleDeleteProject = async (projectId: any) => {
@@ -77,7 +77,7 @@ const DashboardProjects: React.FC = () => {
userId,
};
//socket for deleting the project
// SOCKET for deleting the project
if (projectSocket) {
projectSocket.emit("v1:project:delete", deleteProjects);
} else {
@@ -95,7 +95,7 @@ const DashboardProjects: React.FC = () => {
};
});
setIsSearchActive(false);
} catch (error) {}
} catch (error) { }
};
const handleDuplicateWorkspaceProject = async (
@@ -110,16 +110,17 @@ const DashboardProjects: React.FC = () => {
// projectName
// );
// console.log("duplicatedProject: ", duplicatedProject);
const duplicateProjectData = {
userId,
thumbnail,
organization,
projectUuid: generateUniqueId(),
refProjectID: projectId,
projectName,
};
projectSocket.emit("v1:project:Duplicate", duplicateProjectData);
if (projectSocket) {
const duplicateProjectData = {
userId,
thumbnail,
organization,
projectUuid: generateUniqueId(),
refProjectID: projectId,
projectName,
};
projectSocket.emit("v1:project:Duplicate", duplicateProjectData);
}
};
const renderProjects = () => {
@@ -166,7 +167,7 @@ const DashboardProjects: React.FC = () => {
try {
const sharedWithMe = await sharedWithMeProjects();
setSharedWithMeProjects(sharedWithMe);
} catch {}
} catch { }
};
useEffect(() => {

View File

@@ -38,12 +38,13 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
const handleCreateNewProject = async () => {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken");
console.log("refreshToken: ", refreshToken);
if (!token || !refreshToken) {
console.error('token expired');
return;
}
try {
const projectId = generateProjectId();
useSocketStore
.getState()
.initializeSocket(email, organization, token, refreshToken);
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
//API for creating new Project
// const project = await createProject(
@@ -60,11 +61,10 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
projectUuid: projectId,
};
console.log("projectSocket: ", projectSocket);
if (projectSocket) {
const handleResponse = (data: any) => {
if (data.message === "Project created successfully") {
setLoadingProgress(1)
setLoadingProgress(1);
navigate(`/projects/${data.data.projectId}`);
}
projectSocket.off("v1-project:response:add", handleResponse); // Clean up
@@ -90,7 +90,7 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
<div className="user-name">
{userName
? userName.charAt(0).toUpperCase() +
userName.slice(1).toLowerCase()
userName.slice(1).toLowerCase()
: "Anonymous"}
</div>
</div>
@@ -141,7 +141,10 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
activeTab === "Tutorials" ? "option-list active" : "option-list"
}
title="coming soon"
onClick={() => setActiveTab("Tutorials")}
onClick={() => {
// setActiveTab("Tutorials");
console.warn("Tutorials comming soon");
}}
>
<TutorialsIcon />
Tutorials
@@ -153,14 +156,17 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
: "option-list"
}
title="coming soon"
onClick={() => setActiveTab("Documentation")}
onClick={() => {
// setActiveTab("Documentation");
console.warn("Documentation comming soon");
}}
>
<DocumentationIcon />
Documentation
</div>
</div>
<div className="side-bar-options-container" title="coming soon">
<div className="option-list">
<div className="side-bar-options-container">
<div className="option-list" title="coming soon">
<SettingsIcon />
Settings
</div>
@@ -175,7 +181,7 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
<LogoutIcon />
Log out
</div>
<div className="option-list">
<div className="option-list" title="coming soon">
<HelpIcon />
Help & Feedback
</div>

View File

@@ -1,5 +1,5 @@
import React, { useEffect } from "react";
import { HelpIcon } from "../icons/DashboardIcon";
import React, { useEffect, useState } from "react";
import { HelpIcon, WifiIcon } from "../icons/DashboardIcon";
import { useLogger } from "../ui/log/LoggerContext";
import { GetLogIcon } from "./getLogIcons";
import {
@@ -31,6 +31,27 @@ const Footer: React.FC = () => {
const { Leftnote, Middlenote, Rightnote } = useMouseNoteStore();
const [isOnline, setIsOnline] = useState<boolean>(navigator.onLine);
useEffect(() => {
const handleOnline = () => {
echo.success('You are back Online');
setIsOnline(true);
};
const handleOffline = () => {
echo.warn('Changes made now might not be saved');
echo.error('You are now Offline.');
setIsOnline(false);
};
window.addEventListener("online", handleOnline);
window.addEventListener("offline", handleOffline);
return () => {
window.removeEventListener("online", handleOnline);
window.removeEventListener("offline", handleOffline);
};
}, []);
const mouseButtons = [
{
icon: <CurserLeftIcon />,
@@ -98,6 +119,16 @@ const Footer: React.FC = () => {
<HelpIcon />
</div>
</div>
<div
className={`wifi-connection ${
isOnline ? "connected" : "disconnected"
}`}
>
<div className="icon">
<WifiIcon />
</div>
<div className="tooltip">{isOnline ? "Online" : "Offline"}</div>
</div>
</div>
</div>

View File

@@ -336,18 +336,35 @@ export const MachineIcon = () => {
);
};
export const CraneIcon = () => {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M18.5 5.7502L12.875 1.3752C12.6875 1.1877 12.375 1.1877 12.125 1.3127L5.4375 5.6252H1.875C1.5 5.6252 1.25 5.8752 1.25 6.2502C1.25 6.6252 1.5 6.8752 1.875 6.8752H4.375V10.0002H1.875C1.5 10.0002 1.25 10.2502 1.25 10.6252V13.7502C1.25 14.1252 1.5 14.3752 1.875 14.3752H8.125C8.5 14.3752 8.75 14.1252 8.75 13.7502V10.6252C8.75 10.2502 8.5 10.0002 8.125 10.0002H5.625V6.8752H10.625V15.9377L8.375 17.6252C8.1875 17.8127 8.0625 18.0627 8.1875 18.3127C8.25 18.5627 8.5 18.7502 8.75 18.7502H16.25C16.5 18.7502 16.75 18.5627 16.8125 18.3127C16.875 18.0627 16.8125 17.7502 16.625 17.6252L14.375 15.9377V6.8752H18.125C18.375 6.8752 18.625 6.6877 18.6875 6.4377C18.8125 6.1877 18.75 5.9377 18.5 5.7502ZM3.6875 11.2502L2.5 12.7502V11.2502H3.6875ZM5 11.6252L6.1875 13.1252H3.8125L5 11.6252ZM7.5 12.7502L6.3125 11.2502H7.5V12.7502ZM11.875 3.0002V5.6252H11.25H7.75L11.875 3.0002ZM13.75 5.6252H13.125V3.1252L16.3125 5.6252H13.75Z"
fill="white"
/>
</svg>
);
};
type TypeBasedAssetIconsProps = {
assetType: string;
};
export function TypeBasedAssetIcons({ assetType }: TypeBasedAssetIconsProps) {
console.log("assetType: ", assetType);
return (
<div>
{assetType === "machine" && <MachineIcon />}
{assetType === "vehicle" && <ForkLiftIcon />}
{assetType === "transfer" && <ConveyorIcon />}
{assetType === "roboticArm" && <RoboticArmIcon />}
{assetType === "StaticMachine" && <MachineIcon />}
{assetType === "Vehicle" && <ForkLiftIcon />}
{assetType === "Conveyor" && <ConveyorIcon />}
{assetType === "Crane" && <CraneIcon />}
{assetType === "ArmBot" && <RoboticArmIcon />}
</div>
);
}

View File

@@ -253,3 +253,20 @@ export function LogoutIcon() {
</svg>
);
}
export function WifiIcon() {
return (
<svg
width="12"
height="12"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6.78458 7.91952C6.35145 7.4864 5.64945 7.4864 5.21633 7.91952C4.7832 8.35265 4.7832 9.05465 5.21633 9.48777C5.64945 9.9209 6.35145 9.9209 6.78458 9.48777C7.2177 9.05465 7.2177 8.35265 6.78458 7.91952ZM9.7902 6.48215L8.67945 7.5929C7.20008 6.11352 4.8012 6.11352 3.32183 7.5929L2.21108 6.48215C4.30395 4.38927 7.69733 4.38927 9.7902 6.48215ZM10.574 5.69802C8.04795 3.17202 3.95258 3.17202 1.42658 5.69802L0.283203 4.55465C3.4407 1.39715 8.55983 1.39715 11.7173 4.55465L10.574 5.69802Z"
fill="white"
/>
</svg>
);
}

View File

@@ -1,13 +1,11 @@
import React, { useEffect } from "react";
import {
useLoadingProgress,
useRenameModeStore,
useSaveVersion,
useSelectedAssets,
useSelectedComment,
useSelectedFloorItem,
useSocketStore,
useWidgetSubOption,
useLoadingProgress,
useRenameModeStore,
useSaveVersion,
useSelectedComment,
useSocketStore,
useWidgetSubOption,
} from "../../../store/builder/store";
import useModuleStore, { useThreeDStore } from "../../../store/useModuleStore";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
@@ -27,10 +25,7 @@ import ControlsPlayer from "../controls/ControlsPlayer";
import SelectFloorPlan from "../../temporary/SelectFloorPlan";
import { createHandleDrop } from "../../../modules/visualization/functions/handleUiDrop";
import Scene from "../../../modules/scene/scene";
import {
useComparisonProduct,
useMainProduct,
} from "../../../store/simulation/useSimulationStore";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
import { useProductContext } from "../../../modules/simulation/products/productContext";
import RegularDropDown from "../../ui/inputs/RegularDropDown";
import RenameTooltip from "../../ui/features/RenameTooltip";
@@ -42,184 +37,172 @@ import { useVersionContext } from "../../../modules/builder/version/versionConte
import VersionSaved from "../sidebarRight/versionHisory/VersionSaved";
import Footer from "../../footer/Footer";
import ThreadChat from "../../ui/collaboration/ThreadChat";
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
function MainScene() {
const { setMainProduct } = useMainProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { isVersionSaved, setIsVersionSaved } = useSaveVersion();
const { activeModule } = useModuleStore();
const { selectedUser } = useSelectedUserStore();
const { loadingProgress } = useLoadingProgress();
const { toggleThreeD } = useThreeDStore();
const { isPlaying } = usePlayButtonStore();
const { widgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
const { selectedZone } = useSelectedZoneStore();
const { setFloatingWidget } = useFloatingWidget();
const { clearComparisonProduct } = useComparisonProduct();
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const { assetStore, productStore } = useSceneContext();
const { products } = productStore();
const { setName } = assetStore();
const { projectId } = useParams()
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
const { versionHistory } = useVersionHistoryStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion, setSelectedVersion } = selectedVersionStore();
const { selectedComment, commentPositionState } = useSelectedComment();
const { setMainProduct } = useMainProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { isVersionSaved, setIsVersionSaved } = useSaveVersion();
const { activeModule } = useModuleStore();
const { selectedUser } = useSelectedUserStore();
const { loadingProgress } = useLoadingProgress();
const { toggleThreeD } = useThreeDStore();
const { isPlaying } = usePlayButtonStore();
const { widgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
const { selectedZone } = useSelectedZoneStore();
const { setFloatingWidget } = useFloatingWidget();
const { clearComparisonProduct } = useComparisonProduct();
const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { assetStore, productStore } = useSceneContext();
const { products } = productStore();
const { setName, selectedAssets, setSelectedAssets } = assetStore();
const { projectId } = useParams()
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
const { versionHistory } = useVersionHistoryStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion, setSelectedVersion } = selectedVersionStore();
const { selectedComment, commentPositionState } = useSelectedComment();
useEffect(() => {
if (activeModule !== 'simulation') {
clearComparisonProduct();
setIsVersionSaved(false);
}
}, [activeModule, clearComparisonProduct, setIsVersionSaved])
useEffect(() => {
if (versionHistory.length > 0) {
setSelectedVersion(versionHistory[0])
}
}, [setSelectedVersion, versionHistory])
const handleSelectVersion = (option: string) => {
const version = versionHistory.find((version) => version.versionName === option);
if (version) {
setSelectedVersion(version);
}
};
const handleSelectProduct = (option: string) => {
const product = products.find((product) => product.productName === option);
if (product) {
setMainProduct(product.productUuid, product.productName);
}
};
const handleObjectRename = async (newName: string) => {
if (!projectId) return
if (selectedFloorItem) {
console.log('selectedFloorItem.userData.modelUuid: ', selectedFloorItem.userData.modelUuid);
console.log(' newName: ', newName);
console.log('projectId: ', projectId);
setAssetsApi({
modelUuid: selectedFloorItem.userData.modelUuid,
modelName: newName,
projectId,
versionId: selectedVersion?.versionId || ''
}).then(() => {
selectedFloorItem.userData = {
...selectedFloorItem.userData,
modelName: newName
};
setSelectedFloorItem(selectedFloorItem);
setIsRenameMode(false);
setName(selectedFloorItem.userData.modelUuid, newName);
})
} else if (selectedAssets.length === 1) {
setAssetsApi({
modelUuid: selectedAssets[0].userData.modelUuid,
modelName: newName,
projectId,
versionId: selectedVersion?.versionId || ''
}).then(() => {
selectedAssets[0].userData = {
...selectedAssets[0].userData,
modelName: newName
};
setSelectedAssets(selectedAssets);
setIsRenameMode(false);
setName(selectedAssets[0].userData.modelUuid, newName);
})
}
}
return (
<>
{!selectedUser && (
<>
<KeyPressListener />
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
{!isPlaying && (
<>
{toggleThreeD && !isVersionSaved && <ModuleToggle />}
<SideBarLeft />
<SideBarRight />
</>
)}
<RealTimeVisulization />
{activeModule === "market" && <MarketPlace />}
{activeModule !== "market" && !isPlaying && !isVersionSaved && (
<Tools />
)}
{(isPlaying) &&
activeModule === "simulation" &&
loadingProgress === 0 && <SimulationPlayer />}
{(isPlaying) &&
activeModule !== "simulation" && <ControlsPlayer />}
{isRenameMode && (selectedFloorItem?.userData.modelName || selectedAssets.length === 1) && <RenameTooltip name={selectedFloorItem?.userData.modelName || selectedAssets[0].userData.modelName} onSubmit={handleObjectRename} />}
{/* remove this later */}
{activeModule === "builder" && !toggleThreeD && <SelectFloorPlan />}
</>
)}
<div
className="scene-container"
id="work-space-three-d-canvas"
style={{
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
borderRadius:
isPlaying || activeModule !== "visualization" ? "" : "6px",
}}
role="application"
onDrop={(event) =>
createHandleDrop({
widgetSubOption,
visualizationSocket,
selectedZone,
setFloatingWidget,
event,
projectId,
versionId: selectedVersion?.versionId || '',
})
useEffect(() => {
if (activeModule !== 'simulation') {
clearComparisonProduct();
setIsVersionSaved(false);
}
onDragOver={(event) => event.preventDefault()}
>
<Scene layout="Main Layout" />
</div>
}, [activeModule, clearComparisonProduct, setIsVersionSaved])
{selectedProduct && selectedVersion && isVersionSaved && !isPlaying && activeModule === "simulation" && (
<div className="selectLayout-wrapper">
<RegularDropDown
header={selectedVersion.versionName}
options={versionHistory.map((v) => v.versionName)} // Pass layout names as options
onSelect={handleSelectVersion}
search={false}
/>
<br />
<RegularDropDown
header={selectedProduct.productName}
options={products.map((l) => l.productName)} // Pass layout names as options
onSelect={handleSelectProduct}
search={false}
/>
</div>
)}
useEffect(() => {
if (versionHistory.length > 0) {
setSelectedVersion(versionHistory[0])
}
}, [setSelectedVersion, versionHistory])
{activeModule !== "market" && !selectedUser && <Footer />}
const handleSelectVersion = (option: string) => {
const version = versionHistory.find((version) => version.versionName === option);
if (version) {
setSelectedVersion(version);
}
};
<VersionSaved />
const handleSelectProduct = (option: string) => {
const product = products.find((product) => product.productName === option);
if (product) {
setMainProduct(product.productUuid, product.productName);
}
};
{
(commentPositionState !== null || selectedComment !== null) &&
<ThreadChat />
}
const handleObjectRename = async (newName: string) => {
if (!projectId) return
if (selectedFloorAsset) {
setAssetsApi({
modelUuid: selectedFloorAsset.userData.modelUuid,
modelName: newName,
projectId,
versionId: selectedVersion?.versionId || ''
}).then(() => {
selectedFloorAsset.userData = { ...selectedFloorAsset.userData, modelName: newName };
setSelectedFloorAsset(selectedFloorAsset);
setIsRenameMode(false);
setName(selectedFloorAsset.userData.modelUuid, newName);
})
} else if (selectedAssets.length === 1) {
setAssetsApi({
modelUuid: selectedAssets[0].userData.modelUuid,
modelName: newName,
projectId,
versionId: selectedVersion?.versionId || ''
}).then(() => {
selectedAssets[0].userData = { ...selectedAssets[0].userData, modelName: newName };
setSelectedAssets(selectedAssets);
setIsRenameMode(false);
setName(selectedAssets[0].userData.modelUuid, newName);
})
}
}
</>
);
return (
<>
{!selectedUser && (
<>
<KeyPressListener />
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
{!isPlaying && (
<>
{toggleThreeD && !isVersionSaved && <ModuleToggle />}
<SideBarLeft />
<SideBarRight />
</>
)}
<RealTimeVisulization />
{activeModule === "market" && <MarketPlace />}
{activeModule !== "market" && !isPlaying && !isVersionSaved && (
<Tools />
)}
{(isPlaying) && activeModule === "simulation" && loadingProgress === 0 && <SimulationPlayer />}
{(isPlaying) && activeModule !== "simulation" && <ControlsPlayer />}
{isRenameMode && (selectedFloorAsset?.userData.modelName || selectedAssets.length === 1) && <RenameTooltip name={selectedFloorAsset?.userData.modelName || selectedAssets[0].userData.modelName} onSubmit={handleObjectRename} />}
{/* remove this later */}
{activeModule === "builder" && !toggleThreeD && <SelectFloorPlan />}
</>
)}
<div
className="scene-container"
id="work-space-three-d-canvas"
style={{
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
borderRadius:
isPlaying || activeModule !== "visualization" ? "" : "6px",
}}
role="application"
onDrop={(event) =>
createHandleDrop({
widgetSubOption,
visualizationSocket,
selectedZone,
setFloatingWidget,
event,
projectId,
versionId: selectedVersion?.versionId || '',
})
}
onDragOver={(event) => event.preventDefault()}
>
<Scene layout="Main Layout" />
</div>
{selectedProduct && selectedVersion && isVersionSaved && !isPlaying && activeModule === "simulation" && (
<div className="selectLayout-wrapper">
<RegularDropDown
header={selectedVersion.versionName}
options={versionHistory.map((v) => v.versionName)} // Pass layout names as options
onSelect={handleSelectVersion}
search={false}
/>
<br />
<RegularDropDown
header={selectedProduct.productName}
options={products.map((l) => l.productName)} // Pass layout names as options
onSelect={handleSelectProduct}
search={false}
/>
</div>
)}
{activeModule !== "market" && !selectedUser && <Footer />}
<VersionSaved />
{
(commentPositionState !== null || selectedComment !== null) &&
<ThreadChat />
}
</>
);
}
export default MainScene;

View File

@@ -1,474 +0,0 @@
import React, { useEffect, useState } from "react";
import Search from "../../ui/inputs/Search";
import { getCategoryAsset } from "../../../services/factoryBuilder/asset/assets/getCategoryAsset";
import { fetchAssets } from "../../../services/marketplace/fetchAssets";
import {
useDecalStore,
useDroppedDecal,
useSelectedItem,
} from "../../../store/builder/store";
// images -------------------
import vehicle from "../../../assets/image/categories/vehicles.png";
import workStation from "../../../assets/image/categories/workStation.png";
import machines from "../../../assets/image/categories/machines.png";
import worker from "../../../assets/image/categories/worker.png";
import storage from "../../../assets/image/categories/storage.png";
import office from "../../../assets/image/categories/office.png";
import safety from "../../../assets/image/categories/safety.png";
import feneration from "../../../assets/image/categories/feneration.png";
import decal from "../../../assets/image/categories/decal.png";
import SkeletonUI from "../../templates/SkeletonUI";
import {
AlertIcon,
ArrowIcon,
DecalInfoIcon,
HangTagIcon,
NavigationIcon,
} from "../../icons/ExportCommonIcons";
import { getCategoryDecals } from "../../../services/factoryBuilder/asset/decals/getCategoryDecals";
// -------------------------------------
interface AssetProp {
filename: string;
thumbnail?: string;
category: string;
description?: string;
tags: string;
url?: string;
uploadDate?: number;
isArchieve?: boolean;
animated?: boolean;
price?: number;
CreatedBy?: string;
}
interface CategoryListProp {
assetImage?: string;
assetName?: string;
categoryImage: string;
category: string;
}
const Assets: React.FC = () => {
const { setSelectedItem } = useSelectedItem();
const { setDroppedDecal } = useDroppedDecal();
const [searchValue, setSearchValue] = useState<string>("");
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
const [categoryAssets, setCategoryAssets] = useState<AssetProp[]>([]);
const [decalAsset, setDecalAsset] = useState<any>();
const [filtereredAssets, setFiltereredAssets] = useState<AssetProp[] | []>(
[]
);
const [categoryList, setCategoryList] = useState<CategoryListProp[]>([]);
const [isLoading, setisLoading] = useState<boolean>(false); // Loading state for assets
const { selectedSubCategory, setSelectedSubCategory } = useDecalStore();
const handleSearchChange = (value: string) => {
const searchTerm = searchValue
? searchValue.toLowerCase()
: value.toLowerCase();
setSearchValue(value);
if (searchTerm.trim() === "" && !selectedCategory) {
setCategoryAssets([]);
return;
}
if (selectedCategory === "Decals" || selectedSubCategory) {
const filteredModels = decalAsset?.filter((model: any) =>
model.decalName?.toLowerCase().includes(searchTerm.toLowerCase())
);
setCategoryAssets(filteredModels);
} else {
const filteredModels = filtereredAssets?.filter((model) => {
if (!model?.tags || !model?.filename || !model?.category) return false;
if (searchTerm.startsWith(":") && searchTerm.length > 1) {
const tagSearchTerm = searchTerm.slice(1);
return model.tags.toLowerCase().includes(tagSearchTerm);
} else if (selectedCategory) {
return (
model.category
.toLowerCase()
.includes(selectedCategory.toLowerCase()) &&
model.filename.toLowerCase().includes(searchTerm)
);
} else {
return model.filename.toLowerCase().includes(searchTerm);
}
});
setCategoryAssets(filteredModels);
}
};
useEffect(() => {
if (selectedCategory === "Decals") return;
const filteredAssets = async () => {
try {
const filt = await fetchAssets();
setFiltereredAssets(filt);
} catch {
echo.error("Filter asset not found");
}
};
filteredAssets();
}, [categoryAssets, selectedCategory]);
useEffect(() => {
if (
(searchValue.trim() === "" && selectedCategory === "Decals") ||
selectedSubCategory
) {
const filteredModels = decalAsset?.filter((model: any) =>
model.decalName?.toLowerCase().includes(searchValue.toLowerCase())
);
setCategoryAssets(filteredModels);
}
}, [selectedSubCategory, decalAsset, searchValue]);
useEffect(() => {
setCategoryList([
{ category: "Fenestration", categoryImage: feneration },
{ category: "Decals", categoryImage: decal },
{ category: "Vehicles", categoryImage: vehicle },
{ category: "Workstation", categoryImage: workStation },
{ category: "Machines", categoryImage: machines },
{ category: "Workers", categoryImage: worker },
{ category: "Storage", categoryImage: storage },
{ category: "Safety", categoryImage: safety },
{ category: "Office", categoryImage: office },
]);
}, []);
const fetchCategoryAssets = async (asset: any) => {
setisLoading(true);
setSelectedCategory(asset);
try {
const res = await getCategoryAsset(asset);
setCategoryAssets(res);
setFiltereredAssets(res);
setisLoading(false); // End loading
// eslint-disable-next-line
} catch (error) {
echo.error("failed to fetch assets");
setisLoading(false);
}
if (asset === "Decals") {
fetchCategoryDecals("Safety");
}
};
const fetchCategoryDecals = async (asset: any) => {
setisLoading(true);
// setSelectedCategory(asset);
try {
const res = await getCategoryDecals(asset);
setCategoryAssets(res);
setFiltereredAssets(res);
setDecalAsset(res);
setisLoading(false); // End loading
// eslint-disable-next-line
} catch (error) {
echo.error("failed to fetch assets");
setisLoading(false);
}
};
const activeSubcategories = [
{ name: "Safety", icon: <AlertIcon /> },
{ name: "Navigation", icon: <NavigationIcon /> },
{ name: "Branding", icon: <HangTagIcon /> },
{ name: "Informational", icon: <DecalInfoIcon /> },
];
return (
<div className="assets-container-main">
<Search onChange={handleSearchChange} value={searchValue} />
<div className="assets-list-section">
<section>
{(() => {
if (isLoading) {
return <SkeletonUI type="asset" />; // Show skeleton when loading
}
if (searchValue) {
return (
<div className="assets-result">
<div className="assets-wrapper">
<div className="searched-content">
<p>
Results for{" "}
<span className="search-for">'{searchValue}'</span>
</p>
</div>
<div className="assets-container">
{selectedCategory == "Decals" ? (
<>
<div className="catogory-asset-filter">
{activeSubcategories.map((cat, index) => (
<div
key={index}
className={`catogory-asset-filter-wrapper ${
selectedSubCategory === cat.name
? "active"
: ""
}`}
onClick={() => {
fetchCategoryDecals(cat.name);
setSelectedSubCategory(cat.name);
}}
>
<div className="sub-catagory">{cat.icon}</div>
<div className="sub-catagory">{cat.name}</div>
</div>
))}
</div>
{categoryAssets?.map((asset: any, index: number) => (
<div
key={`${index}-${asset}`}
className="assets"
id={asset.decalName}
title={asset.decalName}
>
<img
src={asset?.decalImage}
alt={asset.decalName}
className="asset-image"
onPointerDown={() => {
setSelectedItem({
name: asset.decalName,
id: asset.id,
type:
asset.type === "undefined"
? undefined
: asset.type,
category: asset.category,
// subType: asset.subType,
});
}}
/>
<div className="asset-name">
{asset.decalName
.split("_")
.map(
(word: any) =>
word.charAt(0).toUpperCase() +
word.slice(1)
)
.join(" ")}
</div>
</div>
))}
</>
) : (
categoryAssets?.map((asset: any, index: number) => (
<div
key={`${index}-${asset.filename}`}
className="assets"
id={asset.filename}
title={asset.filename}
>
<img
src={asset?.thumbnail}
alt={asset.filename}
className="asset-image"
onPointerDown={() => {
setSelectedItem({
name: asset.filename,
id: asset.AssetID,
type:
asset.type === "undefined"
? undefined
: asset.type,
});
}}
/>
<div className="asset-name">
{asset.filename
.split("_")
.map(
(word: any) =>
word.charAt(0).toUpperCase() + word.slice(1)
)
.join(" ")}
</div>
</div>
))
)}
</div>
</div>
</div>
);
}
if (selectedCategory) {
return (
<div className="assets-wrapper">
<h2 className="header">
{selectedCategory}
<button
className="back-button"
id="asset-backButtom"
onClick={() => {
setSelectedCategory(null);
setSelectedSubCategory(null);
setCategoryAssets([]);
}}
>
<div className="back-arrow">
<ArrowIcon />
</div>
Back
</button>
</h2>
{selectedCategory === "Decals" && (
<>
<div className="catogory-asset-filter">
{activeSubcategories.map((cat, index) => (
<div
key={index}
className={`catogory-asset-filter-wrapper ${
selectedSubCategory === cat.name ? "active" : ""
}`}
onClick={() => {
fetchCategoryDecals(cat.name);
setSelectedSubCategory(cat.name);
}}
>
<div className="sub-catagory">{cat.icon}</div>
<div className="sub-catagory">{cat.name}</div>
</div>
))}
</div>
</>
)}
{selectedCategory !== "Decals" && !selectedSubCategory ? (
<div className="assets-container">
{categoryAssets?.map((asset: any, index: number) => (
<div
key={`${index}-${asset}`}
className="assets"
id={asset.filename}
title={asset.filename}
>
<img
src={asset?.thumbnail}
alt={asset.filename}
className="asset-image"
onPointerDown={() => {
setSelectedItem({
name: asset.filename,
id: asset.AssetID,
type:
asset.type === "undefined"
? undefined
: asset.type,
category: asset.category,
subType: asset.subType,
});
}}
/>
<div className="asset-name">
{asset.filename
.split("_")
.map(
(word: any) =>
word.charAt(0).toUpperCase() + word.slice(1)
)
.join(" ")}
</div>
</div>
))}
{categoryAssets.length === 0 && (
<div className="no-asset">
🚧 The asset shelf is empty. We're working on filling
it up!
</div>
)}
</div>
) : (
<div className="assets-container">
{categoryAssets?.map((asset: any, index: number) => (
<div
key={`${index}-${asset}`}
className="assets"
id={asset.decalName}
title={asset.decalName}
>
<img
src={asset?.decalImage}
alt={asset.decalName}
className="asset-image"
onPointerDown={() => {
setDroppedDecal({
category: asset.category,
decalName: asset.decalName,
decalImage: asset.decalImage,
decalId: asset.id,
});
}}
/>
<div className="asset-name">
{asset.decalName
.split("_")
.map(
(word: any) =>
word.charAt(0).toUpperCase() + word.slice(1)
)
.join(" ")}
</div>
</div>
))}
{categoryAssets.length === 0 && (
<div className="no-asset">
🚧 The asset shelf is empty. We're working on filling
it up!
</div>
)}
</div>
)}
</div>
);
}
return (
<div className="assets-wrapper">
<h2 className="categories-header">Categories</h2>
<div className="categories-container">
{Array.from(
new Set(categoryList.map((asset) => asset.category))
).map((category, index) => {
const categoryInfo = categoryList.find(
(asset) => asset.category === category
);
return (
<div
key={`${index}-${category}`}
className="category"
id={category}
onClick={() => {
fetchCategoryAssets(category);
}}
>
<img
src={categoryInfo?.categoryImage ?? ""}
alt={category}
className="category-image"
draggable={false}
/>
<div className="category-name">{category}</div>
</div>
);
})}
</div>
</div>
);
})()}
</section>
</div>
</div>
);
};
export default Assets;

View File

@@ -3,7 +3,7 @@ import ToggleHeader from "../../ui/inputs/ToggleHeader";
import Outline from "./Outline";
import Header from "./Header";
import { useToggleStore } from "../../../store/useUIToggleStore";
import Assets from "./Assets";
import Assets from "./assetList/Assets";
import useModuleStore from "../../../store/useModuleStore";
import Widgets from "./visualization/widgets/Widgets";
import Templates from "../../../modules/visualization/template/Templates";

View File

@@ -0,0 +1,176 @@
import React, { useState, useEffect, useMemo, useCallback } from "react";
import { getFilteredAssets } from "./assetsHelpers/filteredAssetsHelper";
import { fetchCategoryDecals } from "./assetsHelpers/fetchDecalsHelper";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import {
fetchAllAssets,
fetchCategoryAssets,
} from "./assetsHelpers/fetchAssetsHelper";
import Search from "../../../ui/inputs/Search";
import SkeletonUI from "../../../templates/SkeletonUI";
import { RenderAsset } from "./assetsHelpers/renderAssetHelper";
import {
ACTIVE_DECAL_SUBCATEGORIES,
CATEGORY_LIST,
} from "./assetsHelpers/constants";
import { ArrowIcon } from "../../../icons/ExportCommonIcons";
const Assets: React.FC = () => {
const { selectedDecalCategory, setSelectedDecalCategory } = useBuilderStore();
const [searchValue, setSearchValue] = useState<string | null>(null);
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
const [assets, setAssets] = useState<AssetProp[] | DecalProp[]>([]);
const [globalResults, setGlobalResults] = useState<(AssetProp | DecalProp)[]>(
[]
);
const [isLoading, setIsLoading] = useState(false);
const filteredAssets = useMemo(
() =>
getFilteredAssets({
assets,
searchValue,
selectedCategory,
selectedDecalCategory,
}),
[assets, searchValue, selectedCategory, selectedDecalCategory]
);
const handleFetchCategory = useCallback(
async (category: string) => {
setIsLoading(true);
setSelectedCategory(category);
if (category === "Decals") {
const res = await fetchCategoryDecals("Safety");
setAssets(res);
setSelectedDecalCategory("Safety");
} else {
const res = await fetchCategoryAssets(category);
setAssets(res);
}
setIsLoading(false);
},
[setSelectedDecalCategory]
);
const fetchGlobalSearch = useCallback(async (term: string) => {
setIsLoading(true);
const allAssets = await fetchAllAssets();
const lowerTerm = term.toLowerCase();
const matches = allAssets.filter(
(a) =>
a.filename.toLowerCase().includes(lowerTerm) ||
a.tags?.toLowerCase().includes(lowerTerm) ||
a.category?.toLowerCase().includes(lowerTerm)
);
setGlobalResults(matches);
setIsLoading(false);
}, []);
useEffect(() => {
if (!selectedCategory && searchValue?.trim())
fetchGlobalSearch(searchValue);
else setGlobalResults([]);
}, [searchValue, selectedCategory, fetchGlobalSearch]);
return (
<div className="assets-container-main">
<Search debounced onChange={setSearchValue} value={searchValue} />
<div className="assets-list-section">
<section>
{isLoading ? (
<SkeletonUI type="asset" />
) : searchValue || selectedCategory ? (
<div className="assets-wrapper">
{selectedCategory ? (
<>
<h2 className="header">
{selectedCategory}
<button
className="back-button"
onClick={() => {
setSelectedCategory(null);
setSelectedDecalCategory(null);
setAssets([]);
setSearchValue(null);
}}
>
<div className="back-arrow">
<ArrowIcon />
</div>{" "}
Back
</button>
</h2>
{selectedCategory === "Decals" && (
<div className="catogory-asset-filter">
{ACTIVE_DECAL_SUBCATEGORIES.map((cat) => (
<div
key={cat.name}
className={`catogory-asset-filter-wrapper ${selectedDecalCategory === cat.name ? "active" : ""
}`}
onClick={async () => {
setIsLoading(true);
const res = await fetchCategoryDecals(cat.name);
setAssets(res);
setSelectedDecalCategory(cat.name);
setIsLoading(false);
}}
>
<div className="sub-catagory">{cat.icon}</div>
<div className="sub-catagory">{cat.name}</div>
</div>
))}
</div>
)}
<div className="assets-container">
{filteredAssets.map((a, i) => (
<RenderAsset key={i} asset={a} index={i} />
))}
{filteredAssets.length === 0 && (
<div className="no-asset">🚧 No assets found</div>
)}
</div>
</>
) : (
<>
<h2 className="header">Global Search Results</h2>
<div className="assets-container">
{globalResults.map((a, i) => (
<RenderAsset key={i} asset={a} index={i} />
))}
{globalResults.length === 0 && (
<div className="no-asset">🔎 No matches found</div>
)}
</div>
</>
)}
</div>
) : (
<div className="assets-wrapper">
<h2 className="categories-header">Categories</h2>
<div className="categories-container">
{CATEGORY_LIST.map((cat) => (
<div
key={cat.category}
className="category"
onClick={() => handleFetchCategory(cat.category)}
>
<img
src={cat.categoryImage}
alt={cat.category}
className="category-image"
draggable={false}
/>
<div className="category-name">{cat.category}</div>
</div>
))}
</div>
</div>
)}
</section>
</div>
</div>
);
};
export default Assets;

View File

@@ -0,0 +1,34 @@
import vehicle from "../../../../../assets/image/categories/vehicles.png";
import workStation from "../../../../../assets/image/categories/workStation.png";
import machines from "../../../../../assets/image/categories/machines.png";
import worker from "../../../../../assets/image/categories/worker.png";
import storage from "../../../../../assets/image/categories/storage.png";
import office from "../../../../../assets/image/categories/office.png";
import safety from "../../../../../assets/image/categories/safety.png";
import feneration from "../../../../../assets/image/categories/feneration.png";
import decal from "../../../../../assets/image/categories/decal.png";
import {
AlertIcon,
DecalInfoIcon,
HangTagIcon,
NavigationIcon,
} from "../../../../icons/ExportCommonIcons";
export const CATEGORY_LIST: CategoryListProp[] = [
{ category: "Fenestration", categoryImage: feneration },
{ category: "Decals", categoryImage: decal },
{ category: "Vehicles", categoryImage: vehicle },
{ category: "Workstation", categoryImage: workStation },
{ category: "Machines", categoryImage: machines },
{ category: "Workers", categoryImage: worker },
{ category: "Storage", categoryImage: storage },
{ category: "Safety", categoryImage: safety },
{ category: "Office", categoryImage: office },
];
export const ACTIVE_DECAL_SUBCATEGORIES = [
{ name: "Safety", icon: <AlertIcon /> },
{ name: "Navigation", icon: <NavigationIcon /> },
{ name: "Branding", icon: <HangTagIcon /> },
{ name: "Informational", icon: <DecalInfoIcon /> },
];

View File

@@ -0,0 +1,22 @@
import { getCategoryAsset } from "../../../../../services/factoryBuilder/asset/assets/getCategoryAsset";
import { fetchAssets } from "../../../../../services/marketplace/fetchAssets";
export const fetchCategoryAssets = async (category: string): Promise<AssetProp[]> => {
if (category === "Decals") return []; // handled separately
try {
const res = await getCategoryAsset(category);
return res;
} catch (err) {
console.error("Failed to fetch category assets", err);
return [];
}
};
export const fetchAllAssets = async (): Promise<AssetProp[]> => {
try {
return await fetchAssets();
} catch (err) {
console.error("Failed to fetch all assets", err);
return [];
}
};

View File

@@ -0,0 +1,11 @@
import { getCategoryDecals } from "../../../../../services/factoryBuilder/asset/decals/getCategoryDecals";
export const fetchCategoryDecals = async (subcategory: string): Promise<DecalProp[]> => {
try {
const res = await getCategoryDecals(subcategory);
return res;
} catch (err) {
console.error("Failed to fetch decals", err);
return [];
}
};

View File

@@ -0,0 +1,34 @@
interface FilterProps {
assets: AssetProp[] | DecalProp[];
searchValue: string | null;
selectedCategory: string | null;
selectedDecalCategory: string | null;
}
export const getFilteredAssets = ({
assets,
searchValue,
selectedCategory,
selectedDecalCategory,
}: FilterProps) => {
const term = searchValue?.trim().toLowerCase();
if (!term) return assets;
if (selectedCategory === "Decals" || selectedDecalCategory) {
return (assets as DecalProp[]).filter((a) =>
a.decalName?.toLowerCase().includes(term)
);
}
return (assets as AssetProp[]).filter((a) => {
const tags = a.tags?.toLowerCase() ?? "";
const filename = a.filename?.toLowerCase() ?? "";
const category = a.category?.toLowerCase() ?? "";
if (term.startsWith(":")) return tags.includes(term.slice(1));
if (selectedCategory)
return category.includes(selectedCategory.toLowerCase()) && filename.includes(term);
return filename.includes(term);
});
};

View File

@@ -0,0 +1,59 @@
import React from "react";
import { useSelectedItem } from "../../../../../store/builder/store";
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
export const RenderAsset: React.FC<{ asset: AssetProp | DecalProp; index: number }> = ({ asset, index }) => {
const { setSelectedItem } = useSelectedItem();
const { setDroppedDecal } = useBuilderStore();
if ("decalName" in asset) {
return (
<div key={`${index}-${asset.decalName}`} className="assets" id={asset.decalName} title={asset.decalName}>
<img
src={asset.decalImage}
alt={asset.decalName}
className="asset-image"
onPointerDown={() => {
setDroppedDecal({
category: asset.category,
decalName: asset.decalName,
decalImage: asset.decalImage,
decalId: asset.id,
})
}}
/>
<div className="asset-name">
{asset.decalName
.split("_")
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
.join(" ")}
</div>
</div>
);
}
return (
<div key={`${index}-${asset.filename}`} className="assets" id={asset.filename} title={asset.filename}>
<img
src={asset.thumbnail}
alt={asset.filename}
className="asset-image"
onPointerDown={() =>
setSelectedItem({
name: asset.filename,
id: asset.AssetID,
type: asset.type === "undefined" ? undefined : asset.type,
category: asset.category,
subType: asset.subType,
})
}
/>
<div className="asset-name">
{asset.filename
.split("_")
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
.join(" ")}
</div>
</div>
);
};

View File

@@ -6,7 +6,7 @@ import { useToggleStore } from "../../../store/useUIToggleStore";
import Visualization from "./visualization/Visualization";
import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations";
import useVersionHistoryVisibleStore, { useSaveVersion, useSelectedFloorItem, useToolMode } from "../../../store/builder/store";
import useVersionHistoryVisibleStore, { useSaveVersion, useToolMode } from "../../../store/builder/store";
import { useSelectedEventData, useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import GlobalProperties from "./properties/GlobalProperties";
@@ -48,8 +48,7 @@ const SideBarRight: React.FC = () => {
const { toggleUIRight } = useToggleStore();
const { toolMode } = useToolMode();
const { subModule, setSubModule } = useSubModuleStore();
const { selectedFloorItem } = useSelectedFloorItem();
const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore();
const { selectedWall, selectedFloor, selectedAisle, selectedFloorAsset } = useBuilderStore();
const { selectedEventData } = useSelectedEventData();
const { selectedEventSphere } = useSelectedEventSphere();
const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore();
@@ -108,31 +107,31 @@ const SideBarRight: React.FC = () => {
}
if (subModule === "properties" && activeModule !== "visualization") {
if (selectedFloorItem) {
if (selectedFloorAsset) {
setDisplayComponent("assetProperties");
return;
}
if (!selectedFloorItem && !selectedFloor && !selectedAisle && !selectedDecal && selectedWall) {
if (!selectedFloorAsset && !selectedFloor && !selectedAisle && !selectedDecal && selectedWall) {
setDisplayComponent("selectedWallProperties");
return;
}
if (!selectedFloorItem && !selectedWall && !selectedAisle && !selectedDecal && selectedFloor) {
if (!selectedFloorAsset && !selectedWall && !selectedAisle && !selectedDecal && selectedFloor) {
setDisplayComponent("selectedFloorProperties");
return;
}
if (viewVersionHistory && !selectedFloorItem && !selectedWall && !selectedAisle && !selectedFloor && !selectedDecal) {
if (viewVersionHistory && !selectedFloorAsset && !selectedWall && !selectedAisle && !selectedFloor && !selectedDecal) {
setDisplayComponent("versionHistory");
return;
}
if (!selectedFloorItem && !selectedFloor && !selectedAisle && !selectedWall && selectedDecal) {
if (!selectedFloorAsset && !selectedFloor && !selectedAisle && !selectedWall && selectedDecal) {
setDisplayComponent("selectedDecalProperties");
return;
}
if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal && selectedAisle) {
if (!selectedFloorAsset && !selectedFloor && !selectedWall && !selectedDecal && selectedAisle) {
setDisplayComponent("selectedAisleProperties");
return;
}
if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle) {
if (!selectedFloorAsset && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle) {
if (toolMode === "Aisle") {
setDisplayComponent("aisleProperties");
return;
@@ -156,7 +155,7 @@ const SideBarRight: React.FC = () => {
}
setDisplayComponent("none");
}, [viewVersionHistory, activeModule, subModule, isVersionSaved, selectedFloorItem, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal]);
}, [viewVersionHistory, activeModule, subModule, isVersionSaved, selectedFloorAsset, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal]);
const renderComponent = () => {
switch (displayComponent) {
@@ -198,7 +197,7 @@ const SideBarRight: React.FC = () => {
};
return (
<div className={`sidebar-right-wrapper ${toggleUIRight && (!isVersionSaved || activeModule !== "simulation") ? "open" : "closed"}`}>
<div className={`sidebar-right-wrapper ${toggleUIRight && (!isVersionSaved || activeModule !== "simulation") ? "open" : "closed"}`} onPointerDown={(e) => e.stopPropagation()}>
<Header />
{toggleUIRight && (
<>

View File

@@ -98,27 +98,27 @@ const AisleProperties: React.FC = () => {
const dashLengthValue = useMemo(() => {
return dashLength.toString();
}, [aisleType, dashLength]);
}, [dashLength]);
const dotRadiusValue = useMemo(() => {
return dotRadius.toString();
}, [aisleType, dotRadius]);
}, [dotRadius]);
const gapLengthValue = useMemo(() => {
return gapLength.toString();
}, [aisleType, gapLength]);
}, [gapLength]);
const aisleWidthValue = useMemo(() => {
return aisleWidth.toString();
}, [aisleType, aisleWidth]);
}, [aisleWidth]);
const aisleLengthValue = useMemo(() => {
return aisleLength.toString();
}, [aisleType, aisleLength]);
}, [aisleLength]);
const aisleIsFlipped = useMemo(() => {
return isFlipped;
}, [aisleType, isFlipped]);
}, [isFlipped]);
const renderAdvancedProperties = () => {
switch (aisleType) {
@@ -282,11 +282,11 @@ const AisleProperties: React.FC = () => {
<button
key={val.id}
title={val.brief || val.id}
className={`aisle-list ${aisleColor === val.color ? "selected" : ""}`}
className={`aisle-list ${aisleColor === val.id ? "selected" : ""}`}
onClick={() => setAisleColor(val.id)}
aria-pressed={aisleColor === val.id}
>
<div
<div
className={`texture-display ${val.id}`}
style={{ background: val.id }}
>

View File

@@ -4,143 +4,138 @@ import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { RemoveIcon } from "../../../icons/ExportCommonIcons";
import PositionInput from "../customInput/PositionInputs";
import RotationInput from "../customInput/RotationInput";
import {
useSelectedFloorItem,
useObjectPosition,
useObjectRotation,
} from "../../../../store/builder/store";
import { useObjectPosition, useObjectRotation } from "../../../../store/builder/store";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
interface UserData {
id: number;
label: string;
value: string;
id: number;
label: string;
value: string;
}
const AssetProperties: React.FC = () => {
const [userData, setUserData] = useState<UserData[]>([]);
const { selectedFloorItem } = useSelectedFloorItem();
const { objectPosition } = useObjectPosition();
const { objectRotation } = useObjectRotation();
const { assetStore } = useSceneContext();
const { assets, setCurrentAnimation } = assetStore();
const { loopAnimation } = useBuilderStore();
const [hoveredIndex, setHoveredIndex] = useState<any>(null);
const [userData, setUserData] = useState<UserData[]>([]);
const { objectPosition } = useObjectPosition();
const { objectRotation } = useObjectRotation();
const { assetStore } = useSceneContext();
const { assets, setCurrentAnimation } = assetStore();
const { loopAnimation, selectedFloorAsset } = useBuilderStore();
const [hoveredIndex, setHoveredIndex] = useState<any>(null);
const handleAddUserData = () => {
setUserData([]);
};
const handleAddUserData = () => {
setUserData([]);
};
const handleUserDataChange = (id: number, newValue: string) => { };
const handleUserDataChange = (id: number, newValue: string) => { };
const handleRemoveUserData = (id: number) => { };
const handleRemoveUserData = (id: number) => { };
const handleAnimationClick = (animation: string) => {
if (selectedFloorItem) {
setCurrentAnimation(
selectedFloorItem.uuid,
animation,
true,
loopAnimation,
true
);
}
};
if (!selectedFloorItem) return null;
return (
<div className="asset-properties-container">
{/* Name */}
<div className="header">{selectedFloorItem.userData.modelName}</div>
<section>
{objectPosition && (
<PositionInput
disabled={true}
onChange={() => { }}
value1={parseFloat(objectPosition.x.toFixed(5))}
value2={parseFloat(objectPosition.z.toFixed(5))}
/>
)}
{objectRotation && (
<RotationInput
disabled={true}
onChange={() => { }}
value={parseFloat(objectRotation.y.toFixed(5))}
/>
)}
</section>
<div className="header">Render settings</div>
<section>
<InputToggle inputKey="visible" label="Visible" />
<InputToggle inputKey="frustumCull" label="Frustum cull" />
</section>
<section>
<div className="header">User Data</div>
{userData.map((data, i) => (
<div className="input-container" key={i}>
<InputWithDropDown
key={data.id}
label={data.label}
value={data.value}
editableLabel
onChange={(newValue) => handleUserDataChange(data.id, newValue)}
/>
<div
className="remove-button"
onClick={() => handleRemoveUserData(data.id)}
>
<RemoveIcon />
</div>
</div>
))}
{/* Add new user data */}
<div className="optimize-button" onClick={handleAddUserData}>
+ Add
</div>
</section>
<div className="header">Animations</div>
<section className="animations-lists">
{assets.map((asset, i) => {
if (asset.modelUuid !== selectedFloorItem.uuid || !asset.animations)
return (
i === 0 && (
<div className="no-animation" key={i}>
Looks like there are no preset animations yet. Stay tuned for
future additions!
</div>
)
const handleAnimationClick = (animation: string) => {
if (selectedFloorAsset) {
setCurrentAnimation(
selectedFloorAsset.uuid,
animation,
true,
loopAnimation,
true
);
}
};
return asset.animations.map((animation, index) => (
<div key={index} className="animations-list-wrapper">
<div
onClick={() => handleAnimationClick(animation)}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
className="animations-list"
style={{
background:
hoveredIndex === index
? "var(--background-color-button)"
: "var(--background-color)",
color:
hoveredIndex === index ? "var(--text-button-color)" : "",
}}
>
{animation.charAt(0).toUpperCase() +
animation.slice(1).toLowerCase()}
</div>
</div>
));
})}
</section>
</div>
);
if (!selectedFloorAsset) return null;
return (
<div className="asset-properties-container">
{/* Name */}
<div className="header">{selectedFloorAsset.userData.modelName}</div>
<section>
{objectPosition && (
<PositionInput
disabled={true}
onChange={() => { }}
value1={parseFloat(objectPosition.x.toFixed(5))}
value2={parseFloat(objectPosition.z.toFixed(5))}
/>
)}
{objectRotation && (
<RotationInput
disabled={true}
onChange={() => { }}
value={parseFloat(objectRotation.y.toFixed(5))}
/>
)}
</section>
<div className="header">Render settings</div>
<section>
<InputToggle inputKey="visible" label="Visible" />
<InputToggle inputKey="frustumCull" label="Frustum cull" />
</section>
<section>
<div className="header">User Data</div>
{userData.map((data, i) => (
<div className="input-container" key={i}>
<InputWithDropDown
key={data.id}
label={data.label}
value={data.value}
editableLabel
onChange={(newValue) => handleUserDataChange(data.id, newValue)}
/>
<div
className="remove-button"
onClick={() => handleRemoveUserData(data.id)}
>
<RemoveIcon />
</div>
</div>
))}
{/* Add new user data */}
<div className="optimize-button" onClick={handleAddUserData}>
+ Add
</div>
</section>
<div className="header">Animations</div>
<section className="animations-lists">
{assets.map((asset, i) => {
if (asset.modelUuid !== selectedFloorAsset.uuid || !asset.animations)
return (
i === 0 && (
<div className="no-animation" key={i}>
Looks like there are no preset animations yet. Stay tuned for
future additions!
</div>
)
);
return asset.animations.map((animation, index) => (
<div key={index} className="animations-list-wrapper">
<div
onClick={() => handleAnimationClick(animation)}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
className="animations-list"
style={{
background:
hoveredIndex === index
? "var(--background-color-button)"
: "var(--background-color)",
color:
hoveredIndex === index ? "var(--text-button-color)" : "",
}}
>
{animation.charAt(0).toUpperCase() +
animation.slice(1).toLowerCase()}
</div>
</div>
));
})}
</section>
</div>
);
};
export default AssetProperties;

View File

@@ -3,27 +3,13 @@ import InputRange from "../../../ui/inputs/InputRange";
import InputToggle from "../../../ui/inputs/InputToggle";
import { AIIcon } from "../../../icons/ExportCommonIcons";
import LabeledButton from "../../../ui/inputs/LabledButton";
import {
useAzimuth,
useElevation,
useLimitDistance,
useRenderDistance,
useResetCamera,
useRoofVisibility,
useSelectedWallItem,
useShadows,
useSocketStore,
useTileDistance,
useToggleView,
useWallVisibility,
} from "../../../../store/builder/store";
import { useAzimuth, useElevation, useLimitDistance, useRenderDistance, useResetCamera, useRoofVisibility, useShadows, useSocketStore, useTileDistance, useToggleView, useWallVisibility } from "../../../../store/builder/store";
import { setEnvironment } from "../../../../services/factoryBuilder/environment/setEnvironment";
import * as CONSTANTS from "../../../../types/world/worldConstants";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../functions/getUserData";
const GlobalProperties: React.FC = () => {
const { toggleView, setToggleView } = useToggleView();
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
const { roofVisibility, setRoofVisibility } = useRoofVisibility();
const { wallVisibility, setWallVisibility } = useWallVisibility();
const { shadows, setShadows } = useShadows();
@@ -90,16 +76,6 @@ const GlobalProperties: React.FC = () => {
setDistance(value);
setRenderDistance(value);
}
function updateGridDistance(value: number) {
setGridDistance(value);
// setGridValue({ size: value * 100, divisions: (value * 100) / 4 });
// setPlaneValue({ height: value * 100, width: value * 100 });
}
function updatedGrid(value: number) {
// console.log(" (value * 100) / 4 : ", (value * 100) / 4);
setGridValue({ size: value * 100, divisions: (value * 100) / 4 });
setPlaneValue({ height: value * 100, width: value * 100 });
}
const updatedDist = async (value: number) => {
setRenderDistance(value);
@@ -145,7 +121,7 @@ const GlobalProperties: React.FC = () => {
setRoofVisibility(!roofVisibility); // Toggle roof visibility
};
// Function to toggle wall visibility
const changeWallVisibility = async () => {
//using REST
const data = await setEnvironment(
@@ -203,20 +179,10 @@ const GlobalProperties: React.FC = () => {
const toggleResetCamera = () => {
if (!toggleView) {
setResetCamera(true); // Trigger reset camera action
setResetCamera(true);
}
};
// function changeRenderDistance(e: any) {
// if (parseInt(e.target.value) < 20) {
// setRenderDistance(20);
// } else if (parseInt(e.target.value) > 75) {
// setRenderDistance(75);
// } else {
// setRenderDistance(parseInt(e.target.value));
// }
// }
return (
<div className="global-properties-container">
<section>
@@ -253,16 +219,10 @@ const GlobalProperties: React.FC = () => {
/>
<div className="split"></div>
{/* //visibleEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor} */}
<InputToggle
inputKey="4"
label="Limit Render Distance"
value={limitDistance}
// onClick={() => {
// setLimitDistance(!limitDistance);
// // setDistance(75);
// // setRenderDistance(75);
// }}
onClick={async () => {
await limitRenderDistance(); // Call the function here
}}
@@ -277,26 +237,6 @@ const GlobalProperties: React.FC = () => {
onPointerUp={updatedDist}
key={"6"}
/>
{/* <div className="split"></div>
<InputToggle
inputKey="6"
label="Display Grid"
value={limitGridDistance}
onClick={() => {
setLimitGridDistance(!limitGridDistance);
}}
/>
<InputRange
label="Tile Distance"
disabled={!limitGridDistance}
value={gridDistance}
key={"7"}
min={1}
max={5}
onChange={(value: number) => updateGridDistance(value)}
onPointerUp={updatedGrid}
/> */}
</section>
</div>
);

View File

@@ -20,6 +20,8 @@ import { useSocketStore } from "../../../../store/builder/store";
import { getUserData } from "../../../../functions/getUserData";
import { aisleTextureList } from "./AisleProperties";
import { upsertAisleApi } from "../../../../services/factoryBuilder/aisle/upsertAisleApi";
const SelectedAisleProperties: React.FC = () => {
const [collapsePresets, setCollapsePresets] = useState(false);
const [collapseTexture, setCollapseTexture] = useState(true);
@@ -44,23 +46,28 @@ const SelectedAisleProperties: React.FC = () => {
const updateBackend = (updatedAisle: Aisle) => {
if (updatedAisle && projectId) {
// API
if (!socket?.connected) {
// upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
// API
// SOCKET
upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: updatedAisle.aisleUuid,
points: updatedAisle.points,
type: updatedAisle.type
} else {
// SOCKET
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: updatedAisle.aisleUuid,
points: updatedAisle.points,
type: updatedAisle.type
}
socket.emit('v1:model-aisle:add', data);
}
socket.emit('v1:model-aisle:add', data);
}
}

View File

@@ -7,8 +7,8 @@ import { useSocketStore } from "../../../../store/builder/store";
import InputRange from "../../../ui/inputs/InputRange";
import { getUserData } from "../../../../functions/getUserData";
// import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
// import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi";
import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi";
const SelectedDecalProperties = () => {
const { selectedDecal, setSelectedDecal } = useBuilderStore();
@@ -24,39 +24,45 @@ const SelectedDecalProperties = () => {
const updateBackend = (updatedData: Wall | Floor) => {
if ('wallUuid' in updatedData) {
if (projectId && updatedData) {
// API
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData);
} else {
// SOCKET
// SOCKET
const data = {
wallData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
} else if ('floorUuid' in updatedData) {
if (projectId && updatedData) {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
}
}
@@ -146,7 +152,7 @@ const SelectedDecalProperties = () => {
label="Scale"
value={selectedDecal.decalData.decalScale || 1}
min={0.1}
max={5}
max={2}
step={0.1}
onChange={(value: number) => handleScaleChange(value)}
/>

View File

@@ -10,7 +10,7 @@ import { getUserData } from "../../../../functions/getUserData";
import { useSocketStore } from "../../../../store/builder/store";
import { materials } from "./FloorProperties";
// import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi";
import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi";
const SelectedFloorProperties = () => {
const [depth, setDepth] = useState("");
@@ -43,22 +43,25 @@ const SelectedFloorProperties = () => {
if (!isNaN(parsed) && floor) {
const updatedFloor = updateFloor(floor.floorUuid, { floorDepth: parsed });
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
}
};
@@ -69,10 +72,40 @@ const SelectedFloorProperties = () => {
if (!isNaN(parsed) && floor) {
const updatedFloor = updateFloor(floor.floorUuid, { bevelStrength: parsed });
if (projectId) {
if (!socket?.connected) {
// API
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
}
}
};
const handleIsBeveledToggle = () => {
setIsBeveled(!isBeveled);
if (!floor) return;
const updatedFloor = updateFloor(floor.floorUuid, { isBeveled: !floor.isBeveled });
if (projectId) {
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
@@ -87,30 +120,6 @@ const SelectedFloorProperties = () => {
socket.emit('v1:model-Floor:add', data);
}
}
};
const handleIsBeveledToggle = () => {
setIsBeveled(!isBeveled);
if (!floor) return;
const updatedFloor = updateFloor(floor.floorUuid, { isBeveled: !floor.isBeveled });
if (projectId) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
};
@@ -119,22 +128,25 @@ const SelectedFloorProperties = () => {
const key = activeSurface === "top" ? "topMaterial" : "sideMaterial";
const updatedFloor = updateFloor(floor.floorUuid, { [key]: material.textureId });
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
};

View File

@@ -11,7 +11,7 @@ import { useParams } from "react-router-dom";
import { getUserData } from "../../../../functions/getUserData";
import { useSocketStore } from "../../../../store/builder/store";
// import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
const SelectedWallProperties = () => {
const [height, setHeight] = useState("");
@@ -47,22 +47,25 @@ const SelectedWallProperties = () => {
if (!isNaN(height) && wall) {
const updatedWall = updateWall(wall.wallUuid, { wallHeight: height });
if (updatedWall && projectId) {
if (!socket?.connected) {
// API
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
// SOCKET
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
}
};
@@ -73,10 +76,41 @@ const SelectedWallProperties = () => {
if (!isNaN(thickness) && wall) {
const updatedWall = updateWall(wall.wallUuid, { wallThickness: thickness });
if (updatedWall && projectId) {
if (!socket?.connected) {
// API
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
}
}
};
const handleSelectMaterial = (material: { textureId: string; textureName: string }) => {
if (!wall) return;
const updated = (activeSide === "side1" ? { insideMaterial: material.textureId } : { outsideMaterial: material.textureId })
const updatedWall = updateWall(wall.wallUuid, updated);
if (updatedWall && projectId) {
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
// SOCKET
@@ -93,31 +127,6 @@ const SelectedWallProperties = () => {
}
};
const handleSelectMaterial = (material: { textureId: string; textureName: string }) => {
if (!wall) return;
const updated = (activeSide === "side1" ? { insideMaterial: material.textureId } : { outsideMaterial: material.textureId })
const updatedWall = updateWall(wall.wallUuid, updated);
if (updatedWall && projectId) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
};
if (!wall) return null;
const selectedMaterials = {

View File

@@ -1,199 +1,225 @@
import { useEffect, useState } from 'react'
import { ClockThreeIcon, LocationPinIcon, TargetIcon } from '../../../../icons/ExportCommonIcons'
import { useSceneContext } from '../../../../../modules/scene/sceneContext';
import { useProductContext } from '../../../../../modules/simulation/products/productContext';
import RenameInput from '../../../../ui/inputs/RenameInput';
import { useResourceManagementId } from '../../../../../store/builder/store';
import { set } from 'immer/dist/internal';
import { useEffect, useState } from "react";
import {
ClockThreeIcon,
LocationPinIcon,
TargetIcon,
} from "../../../../icons/ExportCommonIcons";
import { useSceneContext } from "../../../../../modules/scene/sceneContext";
import RenameInput from "../../../../ui/inputs/RenameInput";
import { useResourceManagementId } from "../../../../../store/builder/store";
import { getAssetThumbnail } from "../../../../../services/factoryBuilder/asset/assets/getAssetThumbnail";
// import NavigateCatagory from '../NavigateCatagory'
const Hrm = () => {
const [selectedCard, setSelectedCard] = useState(0);
const [workers, setWorkers] = useState<any[]>([]);
const { productStore } = useSceneContext();
const { products, getProductById } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { setResourceManagementId } = useResourceManagementId();
useEffect(() => {
if (selectedProduct) {
const productDetails = getProductById(selectedProduct.productUuid);
const workerDetails = productDetails?.eventDatas || [];
const formattedWorkers = workerDetails
.filter((worker: any) => worker.type === "human")
.map((worker: any, index: number) => ({
employee: {
image: "",
name: worker.modelName,
modelId: worker.modelUuid,
employee_id: `HR-${204 + index}`,
status: "Active",
},
task: {
status: "Ongoing",
title: worker.taskTitle || "No Task Assigned",
location: {
floor: worker.floor || 0,
zone: worker.zone || "N/A"
},
planned_time_hours: worker.plannedTime || 0,
time_spent_hours: worker.timeSpent || 0,
total_tasks: worker.totalTasks || 0,
completed_tasks: worker.completedTasks || 0
},
actions: [
"Assign Task",
"Reassign Task",
"Pause",
"Emergency Stop"
],
location: `Floor ${worker.floor || "-"} . Zone ${worker.zone || "-"}`
}));
setWorkers(formattedWorkers);
}
}, [selectedProduct, getProductById]);
useEffect(() => {
//
}, [workers]);
// const employee_details = [
// {
// "employee": {
// image: "",
// "name": "John Doe",
// "employee_id": "HR-204",
// "status": "Active",
// },
// "task": {
// "status": "Ongoing",
// "title": "Inspecting Machine X",
// "location": {
// "floor": 4,
// "zone": "B"
// },
// "planned_time_hours": 6,
// "time_spent_hours": 2,
// "total_tasks": 12,
// "completed_tasks": 3
// },
// "actions": [
// "Assign Task",
// "Reassign Task",
// "Pause",
// "Emergency Stop"
// ],
// "location": "Floor 4 . Zone B"
// },
// {
// "employee": {
// image: "",
// "name": "Alice Smith",
// "employee_id": "HR-205",
// "status": "Active",
// },
// "task": {
// "status": "Ongoing",
// "title": "Calibrating Sensor Y",
// "location": {
// "floor": 2,
// "zone": "A"
// },
// "planned_time_hours": 4,
// "time_spent_hours": 1.5,
// "total_tasks": 10,
// "completed_tasks": 2
// },
// "actions": [
// "Assign Task",
// "Reassign Task",
// "Pause",
// "Emergency Stop"
// ],
// "location": "Floor 4 . Zone B"
// },
// {
// "employee": {
// image: "",
// "name": "Michael Lee",
// "employee_id": "HR-206",
// "status": "Active",
// },
// "task": {
// "status": "Ongoing",
// "title": "Testing Conveyor Belt Z",
// "location": {
// "floor": 5,
// "zone": "C"
// },
// "planned_time_hours": 5,
// "time_spent_hours": 3,
// "total_tasks": 8,
// "completed_tasks": 5
// },
// "actions": [
// "Assign Task",
// "Reassign Task",
// "Pause",
// "Emergency Stop"
// ],
// "location": "Floor 4 . Zone B"
// },
// ]
function handleRenameWorker(newName: string) {
//
const [selectedCard, setSelectedCard] = useState(0);
const [workers, setWorkers] = useState<any[]>([]);
const { setResourceManagementId } = useResourceManagementId();
const { assetStore } = useSceneContext();
const { assets: allAssets } = assetStore();
async function getAsset(assetId: string) {
let thumbnail = await getAssetThumbnail(assetId);
if (thumbnail.thumbnail) {
let assetImage = thumbnail.thumbnail;
return assetImage;
}
function handleHumanClick(employee: any) {
if (employee.modelId) {
setResourceManagementId(employee.modelId);
}
}
useEffect(() => {
if (allAssets.length > 0) {
const fetchWorkers = async () => {
const humans = allAssets.filter(
(worker: any) => worker.eventData.type === "Human"
);
const formattedWorkers = await Promise.all(
humans.map(async (worker: any, index: number) => {
const assetImage = await getAsset(worker.assetId);
return {
employee: {
image: assetImage,
name: worker.modelName,
modelId: worker.modelUuid,
employee_id: `HR-${204 + index}`,
status: "Active",
},
task: {
status: "Ongoing",
title: worker.taskTitle ?? "No Task Assigned",
location: {
floor: worker.floor ?? 0,
zone: worker.zone ?? "N/A",
},
planned_time_hours: worker.plannedTime ?? 0,
time_spent_hours: worker.timeSpent ?? 0,
total_tasks: worker.totalTasks ?? 0,
completed_tasks: worker.completedTasks ?? 0,
},
actions: [
"Assign Task",
"Reassign Task",
"Pause",
"Emergency Stop",
],
location: `Floor ${worker.floor || "-"} . Zone ${
worker.zone || "-"
}`,
};
})
);
setWorkers(formattedWorkers);
};
fetchWorkers();
}
}, [allAssets]);
// const employee_details = [
// {
// "employee": {
// image: "",
// "name": "John Doe",
// "employee_id": "HR-204",
// "status": "Active",
return (
<>
{/* <NavigateCatagory
// },
// "task": {
// "status": "Ongoing",
// "title": "Inspecting Machine X",
// "location": {
// "floor": 4,
// "zone": "B"
// },
// "planned_time_hours": 6,
// "time_spent_hours": 2,
// "total_tasks": 12,
// "completed_tasks": 3
// },
// "actions": [
// "Assign Task",
// "Reassign Task",
// "Pause",
// "Emergency Stop"
// ],
// "location": "Floor 4 . Zone B"
// },
// {
// "employee": {
// image: "",
// "name": "Alice Smith",
// "employee_id": "HR-205",
// "status": "Active",
// },
// "task": {
// "status": "Ongoing",
// "title": "Calibrating Sensor Y",
// "location": {
// "floor": 2,
// "zone": "A"
// },
// "planned_time_hours": 4,
// "time_spent_hours": 1.5,
// "total_tasks": 10,
// "completed_tasks": 2
// },
// "actions": [
// "Assign Task",
// "Reassign Task",
// "Pause",
// "Emergency Stop"
// ],
// "location": "Floor 4 . Zone B"
// },
// {
// "employee": {
// image: "",
// "name": "Michael Lee",
// "employee_id": "HR-206",
// "status": "Active",
// },
// "task": {
// "status": "Ongoing",
// "title": "Testing Conveyor Belt Z",
// "location": {
// "floor": 5,
// "zone": "C"
// },
// "planned_time_hours": 5,
// "time_spent_hours": 3,
// "total_tasks": 8,
// "completed_tasks": 5
// },
// "actions": [
// "Assign Task",
// "Reassign Task",
// "Pause",
// "Emergency Stop"
// ],
// "location": "Floor 4 . Zone B"
// },
// ]
function handleRenameWorker(newName: string) {}
function handleHumanClick(employee: any) {
if (employee.modelId) {
setResourceManagementId(employee.modelId);
}
}
return (
<>
{/* <NavigateCatagory
category={["All People", "Technician", "Operator", "Supervisor", "Safety Officer"]}
selectedCategory={selectedCategory}
setSelectedCategory={setSelectedCategory}
/> */}
<div className='hrm-container assetManagement-wrapper'>
{workers.map((employee, index) => (
<div
className={`analysis-wrapper ${selectedCard === index ? "active" : ""}`}
onClick={() => setSelectedCard(index)}
key={index}
>
<header>
<div className="user-details">
<div className="user-image-wrapper">
<img className='user-image' src={employee.employee.image} alt="" />
<div className={`status ${employee.employee.status}`}></div>
</div>
<div className="details" >
{/* <div className="employee-name">{employee.employee.name}</div> */}
<RenameInput value={employee.employee.name} onRename={handleRenameWorker} />
<div className="employee-id">{employee.employee.employee_id}</div>
</div>
</div>
<div className="hrm-container assetManagement-wrapper">
{workers.map((employee, index) => (
<div
className={`analysis-wrapper ${
selectedCard === index ? "active" : ""
}`}
onClick={() => setSelectedCard(index)}
key={index}
>
<header>
<div className="user-details">
<div className="user-image-wrapper">
<img
className="user-image"
src={employee.employee.image}
alt=""
/>
<div className={`status ${employee.employee.status}`}></div>
</div>
<div className="details">
{/* <div className="employee-name">{employee.employee.name}</div> */}
<RenameInput
value={employee.employee.name}
onRename={handleRenameWorker}
/>
<div className="employee-id">
{employee.employee.employee_id}
</div>
</div>
</div>
<div className="see-more" onClick={() => { handleHumanClick(employee.employee) }}>View in Scene</div>
</header>
<div
className="see-more"
onClick={() => {
handleHumanClick(employee.employee);
}}
>
View in Scene
</div>
</header>
<div className="content">
{/* <div className="task-info">
<div className="content">
{/* <div className="task-info">
<div className="task-wrapper">
<div className="task-label">
<span className='label-icon'><ListTaskIcon /></span>
@@ -214,17 +240,20 @@ const Hrm = () => {
</div>
</div> */}
<div className="task-stats">
<div className="stat-item">
<div className="task-stats">
<div className="stat-item">
<div className="stat-wrapper">
<span className="stat-icon">
<ClockThreeIcon />
</span>
<span>Planned time:</span>
</div>
<div className="stat-wrapper">
<span className="stat-icon"><ClockThreeIcon /></span>
<span>Planned time:</span>
</div>
<span className='stat-value'>{employee.task.planned_time_hours} hr</span>
</div>
{/* <div className="stat-item">
<span className="stat-value">
{employee.task.planned_time_hours} hr
</span>
</div>
{/* <div className="stat-item">
<div className="stat-wrapper">
<span className="stat-icon"><SlectedTickIcon /></span>
@@ -242,39 +271,41 @@ const Hrm = () => {
<span className='stat-value'>{employee.task.time_spent_hours} hr</span>
</div> */}
<div className="stat-item">
<div className="stat-item">
<div className="stat-wrapper">
<span className="stat-icon">
<TargetIcon />
</span>
<span>Cost per hr:</span>
</div>
<div className="stat-wrapper">
<span className="stat-icon"><TargetIcon /></span>
<span>Cost per hr:</span>
</div>
<span className="stat-value">
{employee.task.completed_tasks}
</span>
</div>
</div>
<span className='stat-value'>{employee.task.completed_tasks}</span>
</div>
</div>
<div className="location-wrapper">
<div className="location-header">
<div className="icon">
<LocationPinIcon />
</div>
<div className="header">Location:</div>
</div>
<div className="location-value">{employee.location}</div>
</div>
<div className="task-actions">
{/* <button className="btn btn-default">Assign Task</button>
<button className="btn btn-default">Reassign Task</button> */}
<button className="btn btn-default">Pause</button>
<button className="btn btn-danger">Emergency Stop</button>
</div>
</div>
</div>
))}
<div className="location-wrapper">
<div className="location-header">
<div className="icon">
<LocationPinIcon />
</div>
<div className="header">Location:</div>
</div>
<div className="location-value">{employee.location}</div>
</div>
{/* <div className="task-actions">
<button className="btn btn-default">Assign Task</button>
<button className="btn btn-default">Reassign Task</button>
<button className="btn btn-default">Pause</button>
<button className="btn btn-danger">Emergency Stop</button>
</div> */}
</div>
</>
)
}
</div>
))}
</div>
</>
);
};
export default Hrm
export default Hrm;

View File

@@ -1,65 +1,70 @@
import { useEffect, useState } from 'react'
// import NavigateCatagory from '../../NavigateCatagory'
import { EyeIcon, KebabIcon, LocationPinIcon, RightHalfFillCircleIcon } from '../../../../../icons/ExportCommonIcons';
import assetImage from "../../../../../../assets/image/asset-image.png"
import assetImageFallback from "../../../../../../assets/image/asset-image.png"
import { useSceneContext } from '../../../../../../modules/scene/sceneContext';
import { useProductContext } from '../../../../../../modules/simulation/products/productContext';
import RenameInput from '../../../../../ui/inputs/RenameInput';
import { useResourceManagementId } from '../../../../../../store/builder/store';
import { getAssetThumbnail } from '../../../../../../services/factoryBuilder/asset/assets/getAssetThumbnail';
import { TypeBasedAssetIcons } from '../../../../../icons/AssetTypeIcons';
const AssetManagement = () => {
// const [selectedCategory, setSelectedCategory] = useState("All Assets");
const [expandedAssetId, setExpandedAssetId] = useState<string | null>(null);
const [assets, setAssets] = useState<any[]>([]);
const { productStore } = useSceneContext();
const { getProductById } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { setResourceManagementId } = useResourceManagementId();
const { assetStore } = useSceneContext();
const { assets: allAssets } = assetStore();
async function getAsset(assetId: string) {
let thumbnail = await getAssetThumbnail(assetId)
if (thumbnail.thumbnail) {
let assetImage = thumbnail.thumbnail ?? assetImageFallback;
return assetImage;
}
}
useEffect(() => {
if (selectedProduct) {
const productDetails = getProductById(selectedProduct.productUuid);
const productAssets = productDetails?.eventDatas || [];
const grouped: Record<string, any> = {};
productAssets.forEach((asset: any) => {
if (asset.type === "storageUnit" || asset.type === "human") return;
if (!grouped[asset.modelName]) {
grouped[asset.modelName] = {
id: asset.modelUuid,
name: asset.modelName,
type: asset.type,
model: asset.modelCode || "N/A",
status: asset.status || "Online",
usageRate: asset.usageRate || 15,
level: asset.level || "Level 1",
image: assetImage,
description: asset.description || "No description",
cost: asset.cost || 0,
count: 1,
};
} else {
grouped[asset.modelName].count += 1;
}
});
if (allAssets.length > 0) {
const fetchAssets = async () => {
const grouped: Record<string, any> = {};
setAssets(Object.values(grouped));
// Use Promise.all to handle all async operations
await Promise.all(allAssets.map(async (asset: any) => {
if (asset.eventData.type === "Storage" || asset.eventData.type === "Human") return;
const assetImage = await getAsset(asset.assetId);
if (!grouped[asset.assetId]) {
//
grouped[asset.assetId] = {
id: asset.modelUuid,
assetId: asset.assetId,
name: asset.modelName,
type: asset.eventData.type,
model: asset.modelCode ?? "N/A",
status: asset.status ?? "Online",
usageRate: asset.usageRate ?? 15,
level: asset.level ?? "Level 1",
image: assetImage,
description: asset.description ?? "No description",
cost: asset.cost ?? 0,
count: 1,
};
} else {
grouped[asset.assetId].count += 1;
}
}));
setAssets(Object.values(grouped));
}
fetchAssets();
}
// eslint-disable-next-line
}, [selectedProduct]);
}, [allAssets]);
function handleRenameAsset(newName: string) {
//
// if (expandedAssetId) {
// setAssets(prevAssets =>
// prevAssets.map(asset =>
// asset.id === expandedAssetId ? { ...asset, name: newName } : asset
// )
// );
// }
}
useEffect(() => {
@@ -68,8 +73,6 @@ const AssetManagement = () => {
}, [assets]);
function handleAssetClick(id: string) {
setResourceManagementId(id);
}
@@ -126,7 +129,6 @@ const AssetManagement = () => {
<div className={`assetManagement-card-wrapper ${expandedAssetId === asset.id ? "openViewMore" : ""}`} key={index}>
<header>
<div className="header-wrapper">
{expandedAssetId === asset.id ?
<>
<div className="drop-icon" onClick={() => setExpandedAssetId(null)}></div>
@@ -173,9 +175,9 @@ const AssetManagement = () => {
</div>
</div>
<div className="asset-estimate__view-button">
<div className="asset-estimate__view-button" onClick={() => handleAssetClick(asset.id)}>
<EyeIcon isClosed={false} />
<div className="asset-estimate__view-text" onClick={() => handleAssetClick(asset.id)}>View in Scene</div>
<div className="asset-estimate__view-text">View in Scene</div>
</div>
</div>

View File

@@ -11,9 +11,9 @@ import { getUserData } from "../../../../functions/getUserData";
import { useVersionContext } from "../../../../modules/builder/version/versionContext";
const VersionSaved = () => {
const { versionHistory, addVersion, createNewVersion, setCreateNewVersion } = useVersionHistoryStore();
const { addVersion, createNewVersion, setCreateNewVersion } = useVersionHistoryStore();
const { selectedVersionStore } = useVersionContext();
const { setSelectedVersion } = selectedVersionStore();
const { selectedVersion, setSelectedVersion } = selectedVersionStore();
const [newName, setNewName] = useState(new Date().toLocaleString("en-US", {
month: "short",
day: "numeric",
@@ -26,8 +26,6 @@ const VersionSaved = () => {
const { projectId } = useParams();
const { userId } = getUserData();
const latestVersion = versionHistory?.[0];
useEffect(() => {
if (createNewVersion) {
const defaultName = new Date().toLocaleString("en-US", {
@@ -43,12 +41,12 @@ const VersionSaved = () => {
}, [createNewVersion]);
const handleSave = () => {
if (!latestVersion || !projectId) return;
if (!selectedVersion || !projectId) return;
const updatedName = (newName.trim() || latestVersion.versionName) ?? latestVersion.timeStamp;
const updatedDescription = (description.trim() || latestVersion.versionName) ?? latestVersion.timeStamp;
const updatedName = (newName.trim() || selectedVersion.versionName) ?? selectedVersion.timeStamp;
const updatedDescription = (description.trim() || selectedVersion.versionName) ?? selectedVersion.timeStamp;
createVersionApi(projectId, userId, latestVersion.versionId, updatedName, updatedDescription).then((data) => {
createVersionApi(projectId, userId, selectedVersion.versionId, updatedName, updatedDescription).then((data) => {
setSaveFinish(true);
setCreateNewVersion(false);
@@ -84,7 +82,7 @@ const VersionSaved = () => {
setCreateNewVersion(false);
};
if (!latestVersion) return null;
if (!selectedVersion) return null;
return (
<div className={`versionSaved`}>
@@ -105,7 +103,7 @@ const VersionSaved = () => {
placeholder="Enter new version name"
/>
<div className="label">
by @{latestVersion.createdBy}{" "}{new Date(latestVersion.timeStamp).toLocaleDateString("en-US", {
by @{selectedVersion.createdBy}{" "}{new Date(selectedVersion.timeStamp).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "2-digit",

View File

@@ -3,7 +3,7 @@ import RenameInput from "./inputs/RenameInput";
import { ArrowIcon } from "../icons/ExportCommonIcons";
import MenuBar from "./menu/menu";
import { ProjectIcon } from "../icons/HeaderIcons";
import { useProjectName, useSocketStore } from "../../store/builder/store";
import { useProjectName } from "../../store/builder/store";
import { useParams } from "react-router-dom";
import { getAllProjects } from "../../services/dashboard/getAllProjects";
import { updateProject } from "../../services/dashboard/updateProject";
@@ -14,7 +14,7 @@ const FileMenu: React.FC = () => {
const containerRef = useRef<HTMLButtonElement>(null);
let clickTimeout: NodeJS.Timeout | null = null;
const { projectName, setProjectName } = useProjectName();
const { dashBoardSocket } = useSocketStore();
// const { dashBoardSocket } = useSocketStore();
const { projectId } = useParams();
const { userId, organization, email } = getUserData();

View File

@@ -1,17 +1,17 @@
import React, { useEffect, useRef, useState } from "react";
import {
AsileIcon,
CommentIcon,
CursorIcon,
DeleteIcon,
FloorIcon,
FreeMoveIcon,
MeasureToolIcon,
PenIcon,
PlayIcon,
SaveTemplateIcon,
WallIcon,
ZoneIcon,
AsileIcon,
CommentIcon,
CursorIcon,
DeleteIcon,
FloorIcon,
FreeMoveIcon,
MeasureToolIcon,
PenIcon,
PlayIcon,
SaveTemplateIcon,
WallIcon,
ZoneIcon,
} from "../icons/ExportToolsIcons";
import { ArrowIcon, TickIcon } from "../icons/ExportCommonIcons";
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
@@ -20,420 +20,417 @@ import { usePlayButtonStore } from "../../store/usePlayButtonStore";
import useTemplateStore from "../../store/useTemplateStore";
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
import {
useActiveTool,
useAddAction,
useSelectedWallItem,
useSocketStore,
useToggleView,
useToolMode,
useActiveSubTool,
useShortcutStore,
useActiveTool,
useAddAction,
useSocketStore,
useToggleView,
useToolMode,
useActiveSubTool,
useShortcutStore,
} from "../../store/builder/store";
import { useToggleStore } from "../../store/useUIToggleStore";
import {
use3DWidget,
useFloatingWidget,
use3DWidget,
useFloatingWidget,
} from "../../store/visualization/useDroppedObjectsStore";
import { useParams } from "react-router-dom";
import { useVersionContext } from "../../modules/builder/version/versionContext";
import { MoveIcon, RotateIcon } from "../icons/ShortcutIcons";
import { useBuilderStore } from "../../store/builder/useBuilderStore";
// Utility component
const ToolButton = ({
toolKey,
toolId,
icon: Icon,
active,
onClick,
tooltip,
toolKey,
toolId,
icon: Icon,
active,
onClick,
tooltip,
}: any) => (
<button
key={toolKey} // used in rendering list
id={toolId}
className={`tool-button ${active ? "active" : ""}`}
onClick={onClick}
>
<div className="tooltip">{tooltip}</div>
<div className="tool" id={toolId}>
<Icon isActive={active} />
</div>
</button>
<button
key={toolKey} // used in rendering list
id={toolId}
className={`tool-button ${active ? "active" : ""}`}
onClick={onClick}
>
<div className="tooltip">{tooltip}</div>
<div className="tool" id={toolId}>
<Icon isActive={active} />
</div>
</button>
);
const Tools: React.FC = () => {
const { activeModule } = useModuleStore();
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
const { isPlaying, setIsPlaying } = usePlayButtonStore();
const { showShortcuts } = useShortcutStore();
const { activeModule } = useModuleStore();
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
const { isPlaying, setIsPlaying } = usePlayButtonStore();
const { showShortcuts } = useShortcutStore();
const { activeTool, setActiveTool, setToolMode, setAddAction } = useStoreHooks();
const { setSelectedWallAsset } = useBuilderStore();
const { setActiveSubTool, activeSubTool } = useActiveSubTool();
const { setToggleUI } = useToggleStore();
const { setToggleView, toggleView } = useToggleView();
const { activeTool, setActiveTool, setToolMode, setAddAction } =
useStoreHooks();
const { addTemplate, templates } = useTemplateStore();
const { selectedZone } = useSelectedZoneStore();
const { floatingWidget } = useFloatingWidget();
const { widgets3D } = use3DWidget();
const { setActiveSubTool, activeSubTool } = useActiveSubTool();
const { setSelectedWallItem } = useSelectedWallItem();
const { setToggleUI } = useToggleStore();
const { setToggleView, toggleView } = useToggleView();
const { visualizationSocket } = useSocketStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
const { addTemplate, templates } = useTemplateStore();
const { selectedZone } = useSelectedZoneStore();
const { floatingWidget } = useFloatingWidget();
const { widgets3D } = use3DWidget();
const dropdownRef = useRef<HTMLButtonElement>(null);
const [openDrop, setOpenDrop] = useState(false);
const { visualizationSocket } = useSocketStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
// 1. Set UI toggles on initial render
useEffect(() => {
setToggleUI(
localStorage.getItem("navBarUiLeft") !== "false",
localStorage.getItem("navBarUiRight") !== "false"
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const dropdownRef = useRef<HTMLButtonElement>(null);
const [openDrop, setOpenDrop] = useState(false);
// 2. Update tool based on subtool and module
useEffect(() => {
setActiveTool(activeSubTool);
setActiveSubTool(activeSubTool);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeModule]);
// 1. Set UI toggles on initial render
useEffect(() => {
setToggleUI(
localStorage.getItem("navBarUiLeft") !== "false",
localStorage.getItem("navBarUiRight") !== "false"
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// 3. Update tools behavior based on selected tool and view mode
useEffect(() => {
resetTools();
updateToolBehavior(activeTool, toggleView);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeTool, toggleView]);
// 2. Update tool based on subtool and module
useEffect(() => {
setActiveTool(activeSubTool);
setActiveSubTool(activeSubTool);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeModule]);
// 4. Dropdown auto-close
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(e.target as Node)
) {
setOpenDrop(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
// 3. Update tools behavior based on selected tool and view mode
useEffect(() => {
resetTools();
updateToolBehavior(activeTool, toggleView);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeTool, toggleView]);
// 4. Dropdown auto-close
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(e.target as Node)
) {
setOpenDrop(false);
}
const resetTools = () => {
setToolMode(null);
setAddAction(null);
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
const resetTools = () => {
setToolMode(null);
setAddAction(null);
};
const updateToolBehavior = (tool: string, is2D: boolean) => {
switch (tool) {
case "cursor":
is2D ? setToolMode("move") : setToolMode("cursor");
break;
case "draw-wall":
is2D && setToolMode("Wall");
break;
case "draw-aisle":
is2D && setToolMode("Aisle");
break;
case "draw-zone":
is2D && setToolMode("Zone");
break;
case "draw-floor":
is2D && setToolMode("Floor");
break;
case "move":
if (!is2D) setToolMode("Move-Asset");
break;
case "rotate":
if (!is2D) setToolMode("Rotate-Asset");
break;
case "measure":
setToolMode("MeasurementScale");
break;
case "Add pillar":
if (!is2D) setAddAction("Pillar");
break;
case "delete":
is2D ? setToolMode("2D-Delete") : setToolMode("3D-Delete");
break;
}
};
const toggle2D3D = () => {
const toggleTo2D = toggleView;
setToggleView(!toggleTo2D);
setToggleThreeD(toggleTo2D);
setToggleUI(toggleTo2D, toggleTo2D);
if (toggleTo2D) {
setSelectedWallItem(null);
setAddAction(null);
}
setActiveTool("cursor");
setActiveSubTool("cursor");
setToggleUI(
localStorage.getItem("navBarUiLeft") !== "false",
localStorage.getItem("navBarUiRight") !== "false"
);
};
const renderBuilderTools = () => (
<>
{!toggleThreeD && (
<div className="draw-tools">
<ToolButton
toolId="drawWall"
icon={WallIcon}
tooltip="draw wall (q)"
active={activeTool === "draw-wall"}
onClick={() => setActiveTool("draw-wall")}
/>
<ToolButton
toolId="drawZone"
icon={ZoneIcon}
tooltip="draw zone (e)"
active={activeTool === "draw-zone"}
onClick={() => setActiveTool("draw-zone")}
/>
<ToolButton
toolId="drawAisle"
icon={AsileIcon}
tooltip="draw aisle (r)"
active={activeTool === "draw-aisle"}
onClick={() => setActiveTool("draw-aisle")}
/>
<ToolButton
toolId="drawFloor"
icon={FloorIcon}
tooltip="draw floor (t)"
active={activeTool === "draw-floor"}
onClick={() => setActiveTool("draw-floor")}
/>
</div>
)}
<div className="draw-tools">
<ToolButton
toolId="measureScale"
icon={MeasureToolIcon}
tooltip="measure scale (m)"
active={activeTool === "measure"}
onClick={() => setActiveTool("measure")}
/>
</div>
</>
);
const renderSimulationTools = () => (
<div className="draw-tools">
<ToolButton
toolId="pen"
icon={PenIcon}
tooltip="pen"
active={activeTool === "pen"}
onClick={() => setActiveTool("pen")}
/>
</div>
);
const renderVisualizationTools = () => (
<div className="draw-tools">
<ToolButton
toolId="saveTemplate"
icon={SaveTemplateIcon}
tooltip="save template"
active={false}
onClick={() =>
handleSaveTemplate({
addTemplate,
floatingWidget,
widgets3D,
selectedZone,
templates,
visualizationSocket,
projectId,
versionId: selectedVersion?.versionId || "",
})
const updateToolBehavior = (tool: string, is2D: boolean) => {
switch (tool) {
case "cursor":
is2D ? setToolMode("move") : setToolMode("cursor");
break;
case "draw-wall":
is2D && setToolMode("Wall");
break;
case "draw-aisle":
is2D && setToolMode("Aisle");
break;
case "draw-zone":
is2D && setToolMode("Zone");
break;
case "draw-floor":
is2D && setToolMode("Floor");
break;
case "move":
if (!is2D) setToolMode("Move-Asset");
break;
case "rotate":
if (!is2D) setToolMode("Rotate-Asset");
break;
case "measure":
setToolMode("MeasurementScale");
break;
case "Add pillar":
if (!is2D) setAddAction("Pillar");
break;
case "delete":
is2D ? setToolMode("2D-Delete") : setToolMode("3D-Delete");
break;
}
/>
</div>
);
};
const renderModeSwitcher = () => (
<button
id="toggle-threed-button"
className={`toggle-threed-button${toggleThreeD ? " toggled" : ""}`}
onClick={toggle2D3D}
>
<div className="tooltip">toggle view (tab)</div>
<div className={`toggle-option${!toggleThreeD ? " active" : ""}`}>2d</div>
<div className={`toggle-option${toggleThreeD ? " active" : ""}`}>3d</div>
</button>
);
const toggle2D3D = () => {
const toggleTo2D = toggleView;
setToggleView(!toggleTo2D);
setToggleThreeD(toggleTo2D);
setToggleUI(toggleTo2D, toggleTo2D);
if (toggleTo2D) {
setSelectedWallAsset(null);
setAddAction(null);
}
setActiveTool("cursor");
setActiveSubTool("cursor");
setToggleUI(
localStorage.getItem("navBarUiLeft") !== "false",
localStorage.getItem("navBarUiRight") !== "false"
);
};
const getIconByTool = (tool: string) => {
switch (tool) {
case "cursor":
return CursorIcon;
case "free-hand":
return FreeMoveIcon;
case "delete":
return DeleteIcon;
case "move":
return MoveIcon;
case "rotate":
return RotateIcon;
default:
return CursorIcon;
}
};
const getTooltipShortcut = (tool: string) => {
switch (tool) {
case "cursor":
return "v";
case "free-hand":
return "h";
case "delete":
return "x";
default:
return "";
}
};
const getIconComponent = (option: string) => {
switch (option) {
case "cursor":
return <CursorIcon isActive={false} />;
case "free-hand":
return <FreeMoveIcon isActive={false} />;
case "delete":
return <DeleteIcon isActive={false} />;
case "move":
return <MoveIcon />;
case "rotate":
return <RotateIcon />;
default:
return null;
}
};
return (
<div className={`tools-container ${showShortcuts ? "visible" : ""}`}>
<div className="activeDropicon">
{/* Tool Picker (cursor, delete, etc.) */}
{["cursor", "free-hand", "delete"].map(
(tool) =>
activeSubTool === tool && (
<ToolButton
key={tool}
toolId={tool}
icon={getIconByTool(tool)}
tooltip={`${tool} (${getTooltipShortcut(tool)})`}
active={activeTool === tool}
onClick={() => setActiveTool(tool)}
/>
)
)}
{/* Dropdown Menu */}
{activeModule !== "visualization" && (
<button
id="drop-down-button"
title="drop-down"
className="drop-down-option-button"
ref={dropdownRef}
onClick={() => setOpenDrop(!openDrop)}
>
<ArrowIcon />
{openDrop && (
<div className="drop-down-container">
{["cursor", "free-hand", "delete"].map((option) => (
<button
key={option}
id={`${option}-tool`}
className="option-list"
onClick={() => {
setActiveTool(option);
setActiveSubTool(option);
setOpenDrop(false);
}}
>
<div className="active-option">
{activeSubTool === option && <TickIcon />}
</div>
{getIconComponent(option)}
<div className="option">{option}</div>
</button>
))}
</div>
const renderBuilderTools = () => (
<>
{!toggleThreeD && (
<div className="draw-tools">
<ToolButton
toolId="drawWall"
icon={WallIcon}
tooltip="draw wall (q)"
active={activeTool === "draw-wall"}
onClick={() => setActiveTool("draw-wall")}
/>
<ToolButton
toolId="drawZone"
icon={ZoneIcon}
tooltip="draw zone (e)"
active={activeTool === "draw-zone"}
onClick={() => setActiveTool("draw-zone")}
/>
<ToolButton
toolId="drawAisle"
icon={AsileIcon}
tooltip="draw aisle (r)"
active={activeTool === "draw-aisle"}
onClick={() => setActiveTool("draw-aisle")}
/>
<ToolButton
toolId="drawFloor"
icon={FloorIcon}
tooltip="draw floor (t)"
active={activeTool === "draw-floor"}
onClick={() => setActiveTool("draw-floor")}
/>
</div>
)}
</button>
)}
</div>
{toggleThreeD && activeModule !== "visualization" && (
<>
<div className="split"></div>
<div className="transform-tools">
{["move", "rotate"].map((tool) => (
<ToolButton
key={tool}
toolId={tool}
icon={getIconByTool(tool)}
tooltip={`${tool}`}
active={activeTool === tool}
onClick={() => setActiveTool(tool)}
/>
))}
</div>
<div className="draw-tools">
<ToolButton
toolId="measureScale"
icon={MeasureToolIcon}
tooltip="measure scale (m)"
active={activeTool === "measure"}
onClick={() => setActiveTool("measure")}
/>
</div>
</>
)}
);
<div className="split"></div>
{activeModule === "builder" && renderBuilderTools()}
{activeModule === "simulation" && renderSimulationTools()}
{activeModule === "visualization" && renderVisualizationTools()}
const renderSimulationTools = () => (
<div className="draw-tools">
<ToolButton
toolId="pen"
icon={PenIcon}
tooltip="pen"
active={activeTool === "pen"}
onClick={() => setActiveTool("pen")}
/>
</div>
);
<div className="split"></div>
<div className="general-options">
<ToolButton
toolId="comment"
icon={CommentIcon}
tooltip="comment"
active={activeTool === "comment"}
onClick={() => setActiveTool("comment")}
/>
{toggleThreeD && (
<ToolButton
toolId="play"
icon={PlayIcon}
tooltip="play (ctrl + p)"
active={activeTool === "play"}
onClick={() => setIsPlaying(!isPlaying)}
/>
)}
</div>
const renderVisualizationTools = () => (
<div className="draw-tools">
<ToolButton
toolId="saveTemplate"
icon={SaveTemplateIcon}
tooltip="save template"
active={false}
onClick={() =>
handleSaveTemplate({
addTemplate,
floatingWidget,
widgets3D,
selectedZone,
templates,
visualizationSocket,
projectId,
versionId: selectedVersion?.versionId || "",
})
}
/>
</div>
);
{activeModule === "builder" && (
<>
<div className="split"></div>
{renderModeSwitcher()}
</>
)}
</div>
);
const renderModeSwitcher = () => (
<button
id="toggle-threed-button"
className={`toggle-threed-button${toggleThreeD ? " toggled" : ""}`}
onClick={toggle2D3D}
>
<div className="tooltip">toggle view (tab)</div>
<div className={`toggle-option${!toggleThreeD ? " active" : ""}`}>2d</div>
<div className={`toggle-option${toggleThreeD ? " active" : ""}`}>3d</div>
</button>
);
const getIconByTool = (tool: string) => {
switch (tool) {
case "cursor":
return CursorIcon;
case "free-hand":
return FreeMoveIcon;
case "delete":
return DeleteIcon;
case "move":
return MoveIcon;
case "rotate":
return RotateIcon;
default:
return CursorIcon;
}
};
const getTooltipShortcut = (tool: string) => {
switch (tool) {
case "cursor":
return "v";
case "free-hand":
return "h";
case "delete":
return "x";
default:
return "";
}
};
const getIconComponent = (option: string) => {
switch (option) {
case "cursor":
return <CursorIcon isActive={false} />;
case "free-hand":
return <FreeMoveIcon isActive={false} />;
case "delete":
return <DeleteIcon isActive={false} />;
case "move":
return <MoveIcon />;
case "rotate":
return <RotateIcon />;
default:
return null;
}
};
return (
<div className={`tools-container ${showShortcuts ? "visible" : ""}`}>
<div className="activeDropicon">
{/* Tool Picker (cursor, delete, etc.) */}
{["cursor", "free-hand", "delete"].map(
(tool) =>
activeSubTool === tool && (
<ToolButton
key={tool}
toolId={tool}
icon={getIconByTool(tool)}
tooltip={`${tool} (${getTooltipShortcut(tool)})`}
active={activeTool === tool}
onClick={() => setActiveTool(tool)}
/>
)
)}
{/* Dropdown Menu */}
{activeModule !== "visualization" && (
<button
id="drop-down-button"
title="drop-down"
className="drop-down-option-button"
ref={dropdownRef}
onClick={() => setOpenDrop(!openDrop)}
>
<ArrowIcon />
{openDrop && (
<div className="drop-down-container">
{["cursor", "free-hand", "delete"].map((option) => (
<button
key={option}
id={`${option}-tool`}
className="option-list"
onClick={() => {
setActiveTool(option);
setActiveSubTool(option);
setOpenDrop(false);
}}
>
<div className="active-option">
{activeSubTool === option && <TickIcon />}
</div>
{getIconComponent(option)}
<div className="option">{option}</div>
</button>
))}
</div>
)}
</button>
)}
</div>
{toggleThreeD && activeModule !== "visualization" && (
<>
<div className="split"></div>
<div className="transform-tools">
{["move", "rotate"].map((tool) => (
<ToolButton
key={tool}
toolId={tool}
icon={getIconByTool(tool)}
tooltip={`${tool}`}
active={activeTool === tool}
onClick={() => setActiveTool(tool)}
/>
))}
</div>
</>
)}
<div className="split"></div>
{activeModule === "builder" && renderBuilderTools()}
{activeModule === "simulation" && renderSimulationTools()}
{activeModule === "visualization" && renderVisualizationTools()}
<div className="split"></div>
<div className="general-options">
<ToolButton
toolId="comment"
icon={CommentIcon}
tooltip="comment"
active={activeTool === "comment"}
onClick={() => setActiveTool("comment")}
/>
{toggleThreeD && (
<ToolButton
toolId="play"
icon={PlayIcon}
tooltip="play (ctrl + p)"
active={activeTool === "play"}
onClick={() => setIsPlaying(!isPlaying)}
/>
)}
</div>
{activeModule === "builder" && (
<>
<div className="split"></div>
{renderModeSwitcher()}
</>
)}
</div>
);
};
// Extracted common store logic
const useStoreHooks = () => {
return {
...useActiveTool(),
...useToolMode(),
...useAddAction(),
};
return {
...useActiveTool(),
...useToolMode(),
...useAddAction(),
};
};
export default Tools;

View File

@@ -65,32 +65,34 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
if (isEditableThread && editedThread) {
try {
// const editThreadTitle = await editThreadTitleApi(projectId, (val as CommentSchema).threadId, value, selectedVersion?.versionId || "")
// if (editThreadTitle.message == "ThreadTitle updated Successfully") {
// const editedThread: CommentSchema = {
// state: 'active',
// threadId: editThreadTitle.data.replyId,
// creatorId: userId,
// createdAt: getRelativeTime(editThreadTitle.data.createdAt),
// threadTitle: value,
// lastUpdatedAt: new Date().toISOString(),
// position: editThreadTitle.data.position,
// rotation: [0, 0, 0],
// comments: [],
// }
// updateComment((val as CommentSchema).threadId, editedThread)
// }
// projectId, userId, threadTitle, organization, threadId
const threadEdit = {
projectId,
userId,
threadTitle: value,
organization,
threadId: (val as CommentSchema).threadId || selectedComment.threadId,
versionId: selectedVersion?.versionId || ""
}
if (!threadSocket?.active) {
const editThreadTitle = await editThreadTitleApi(projectId, (val as CommentSchema).threadId, value, selectedVersion?.versionId || "")
if (editThreadTitle.message == "ThreadTitle updated Successfully") {
const editedThread: CommentSchema = {
state: 'active',
threadId: editThreadTitle.data.replyId,
creatorId: userId,
createdAt: getRelativeTime(editThreadTitle.data.createdAt),
threadTitle: value,
lastUpdatedAt: new Date().toISOString(),
position: editThreadTitle.data.position,
rotation: [0, 0, 0],
comments: [],
}
updateComment((val as CommentSchema).threadId, editedThread)
}
} else {
const threadEdit = {
projectId,
userId,
threadTitle: value,
organization,
threadId: (val as CommentSchema).threadId || selectedComment.threadId,
versionId: selectedVersion?.versionId || ""
}
threadSocket.emit('v1:thread:updateTitle', threadEdit)
threadSocket.emit('v1:thread:updateTitle', threadEdit)
}
} catch {
}
} else {
@@ -277,7 +279,7 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
<div className="message">
{"comment" in val ? val.comment : val.threadTitle}
</div>
</div>
</div >
)}

View File

@@ -4,7 +4,6 @@ import {
useLeftData,
useTopData,
} from "../../../store/visualization/useZone3DWidgetStore";
import { useRenameModeStore } from "../../../store/builder/store";
type RenameTooltipProps = {
name: string;
@@ -20,6 +19,7 @@ const RenameTooltip: React.FC<RenameTooltipProps> = ({ name, onSubmit }) => {
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
onSubmit(value.trim());
echo.info(`Selected Object has been renamed to ${value.trim()}`);
setTop(0);
setLeft(0);
};

View File

@@ -12,7 +12,12 @@ interface RenameInputProps {
canEdit?: boolean;
}
const RenameInput: React.FC<RenameInputProps> = ({ value, onRename, checkDuplicate, canEdit = true }) => {
const RenameInput: React.FC<RenameInputProps> = ({
value,
onRename,
checkDuplicate,
canEdit = true,
}) => {
const [isEditing, setIsEditing] = useState(false);
const [text, setText] = useState(value);
const [isDuplicate, setIsDuplicate] = useState(false);
@@ -36,10 +41,10 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename, checkDuplica
};
const handleBlur = () => {
if (isDuplicate) return
if (isDuplicate) return;
setIsEditing(false);
if (onRename && !isDuplicate) {
echo.info(`Selected Object has been renamed to ${text}`)
onRename(text);
}
};
@@ -52,6 +57,7 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename, checkDuplica
if (e.key === "Enter" && !isDuplicate) {
setIsEditing(false);
if (onRename) {
echo.info(`Selected Object has been renamed to ${text}`)
onRename(text);
}
}
@@ -80,4 +86,4 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename, checkDuplica
</>
);
};
export default RenameInput
export default RenameInput;

View File

@@ -1,16 +1,18 @@
import React, { ChangeEvent, useState } from "react";
import React, { ChangeEvent, useEffect, useState } from "react";
import { CloseIcon, SearchIcon } from "../../icons/ExportCommonIcons";
interface SearchProps {
value?: string; // The current value of the search input
value?: string | null; // The current value of the search input
placeholder?: string; // Placeholder text for the input
onChange: (value: string) => void; // Callback function to handle input changes
debounced?: boolean; // New prop: whether to debounce onChange
}
const Search: React.FC<SearchProps> = ({
value = "",
placeholder = "Search",
onChange,
debounced = false, // Default false
}) => {
// State to track the input value and focus status
const [inputValue, setInputValue] = useState(value);
@@ -19,28 +21,49 @@ const Search: React.FC<SearchProps> = ({
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.value;
setInputValue(newValue);
onChange(newValue); // Call the onChange prop with the new value
if (!debounced) {
onChange(newValue); // Immediate call if not debounced
}
};
useEffect(() => {
if (value === null) {
setInputValue("");
handleBlur();
}
}, [value]);
// Handle debounced effect
useEffect(() => {
if (!debounced) return;
const timer = setTimeout(() => {
onChange(inputValue ?? "");
}, 500);
return () => clearTimeout(timer);
}, [inputValue, debounced, onChange]);
const handleClear = () => {
console.warn("Search field cleared.");
setInputValue("");
onChange(""); // Clear the input value
onChange(""); // Clear immediately
};
const handleFocus = () => {
setIsFocused(true); // Set focus state to true
setIsFocused(true);
};
const handleBlur = () => {
setIsFocused(false); // Set focus state to false
setIsFocused(false);
};
return (
<div className="search-wrapper">
<div
className={`search-container ${
isFocused || inputValue ? "active" : ""
}`}
className={`search-container ${isFocused || inputValue ? "active" : ""
}`}
>
<div className="icon-container">
<SearchIcon />
@@ -48,7 +71,7 @@ const Search: React.FC<SearchProps> = ({
<input
type="text"
className="search-input"
value={inputValue}
value={inputValue ?? ""}
placeholder={placeholder}
onChange={handleInputChange}
onFocus={handleFocus}
@@ -68,4 +91,4 @@ const Search: React.FC<SearchProps> = ({
);
};
export default Search;
export default Search;

View File

@@ -5,7 +5,9 @@ import { toggleTheme } from "../../../utils/theme";
import useVersionHistoryVisibleStore, {
useShortcutStore,
} from "../../../store/builder/store";
import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore";
import useModuleStore, {
useSubModuleStore,
} from "../../../store/useModuleStore";
import { useVersionHistoryStore } from "../../../store/builder/useVersionHistoryStore";
interface MenuBarProps {
@@ -21,11 +23,12 @@ interface MenuItem {
}
const MenuBar: React.FC<MenuBarProps> = ({ setOpenMenu }) => {
const navigate = useNavigate();
const [activeMenu, setActiveMenu] = useState<string | null>(null);
const [activeSubMenu, setActiveSubMenu] = useState<string | null>(null);
const [selectedItems, setSelectedItems] = useState<Record<string, boolean>>({});
const [selectedItems, setSelectedItems] = useState<Record<string, boolean>>(
{}
);
const { setCreateNewVersion } = useVersionHistoryStore();
const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
@@ -49,7 +52,9 @@ const MenuBar: React.FC<MenuBarProps> = ({ setOpenMenu }) => {
};
const handleLogout = () => {
const theme = localStorage.getItem("theme") ?? "light";
localStorage.clear();
localStorage.setItem("theme", theme);
navigate("/");
};
@@ -61,7 +66,7 @@ const MenuBar: React.FC<MenuBarProps> = ({ setOpenMenu }) => {
setCreateNewVersion(true);
setVersionHistoryVisible(true);
setSubModule("properties");
setActiveModule('builder');
setActiveModule("builder");
}
const menus: Record<string, MenuItem[]> = {
@@ -222,7 +227,7 @@ const MenuBar: React.FC<MenuBarProps> = ({ setOpenMenu }) => {
onClick={() => {
setVersionHistoryVisible(true);
setSubModule("properties");
setActiveModule('builder');
setActiveModule("builder");
}}
>
<div className="menu-button">

View File

@@ -2,21 +2,22 @@ import { MathUtils } from 'three';
import { useEffect } from 'react';
import { useThree } from '@react-three/fiber';
import { useParams } from 'react-router-dom';
import { useDroppedDecal, useSocketStore } from '../../../../store/builder/store';
import { useSocketStore } from '../../../../store/builder/store';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
import useModuleStore from '../../../../store/useModuleStore';
import { useSceneContext } from '../../../scene/sceneContext';
import { useVersionContext } from '../../version/versionContext';
import { getUserData } from '../../../../functions/getUserData';
// import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
// import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
function DecalCreator() {
const { wallStore, floorStore } = useSceneContext();
const { addDecal: addDecalOnWall, getWallById } = wallStore();
const { addDecal: addDecalOnFloor, getFloorById } = floorStore();
const { droppedDecal } = useDroppedDecal();
const { droppedDecal, setDroppedDecal } = useBuilderStore();
const { activeModule } = useModuleStore();
const { userId, organization } = getUserData();
const { selectedVersionStore } = useVersionContext();
@@ -30,13 +31,13 @@ function DecalCreator() {
const onDrop = (event: DragEvent) => {
if (droppedDecal) {
setDroppedDecal(null);
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
const wallIntersect = intersects.find(i => i.object.userData && i.object.userData.wallUuid);
const floorIntersect = intersects.find(i => i.object.userData && i.object.userData.floorUuid);
console.log('wallIntersect: ', wallIntersect);
if (wallIntersect) {
const wall = getWallById(wallIntersect.object.userData.wallUuid);
@@ -55,7 +56,7 @@ function DecalCreator() {
decalPosition: [point.x, point.y, (wall.wallThickness / 2 + 0.001) * (wallIntersect.normal?.z || 1)],
decalRotation: 0,
decalOpacity: 1,
decalScale: 1,
decalScale: 0.5,
}
addDecalOnWall(wallIntersect.object.userData.wallUuid, decal);
@@ -63,22 +64,25 @@ function DecalCreator() {
setTimeout(() => {
const updatedWall = getWallById(wallIntersect.object.userData.wallUuid);
if (updatedWall) {
if (projectId && updatedWall) {
// API
if (projectId) {
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
// SOCKET
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
}
}, 0)
@@ -99,7 +103,7 @@ function DecalCreator() {
decalPosition: [point.x, point.y, -0.001],
decalRotation: 0,
decalOpacity: 1,
decalScale: 1,
decalScale: 0.5,
}
addDecalOnFloor(floorIntersect.object.userData.floorUuid, decal);
@@ -107,21 +111,24 @@ function DecalCreator() {
setTimeout(() => {
const updatedFloor = getFloorById(floorIntersect.object.userData.floorUuid);
if (projectId && updatedFloor) {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
}, 0)
}

View File

@@ -10,9 +10,6 @@ import { useEffect, useRef, useState } from 'react';
import { useDecalEventHandlers } from '../eventHandler/useDecalEventHandlers';
// import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
// import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalPosition[2] }: { parent: Wall | Floor; visible?: boolean, decal: Decal, zPosition?: number }) {
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
const { selectedDecal, deletableDecal, setSelectedDecal, setDeletableDecal } = useBuilderStore();
@@ -25,6 +22,7 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP
if (selectedDecal?.decalData.decalUuid === decal.decalUuid && !selectedDecal.decalMesh) {
setSelectedDecal({ decalData: selectedDecal.decalData, decalMesh: decalRef.current });
}
// eslint-disable-next-line
}, [selectedDecal])
const { handlePointerMissed, handlePointerLeave, handleClick, handlePointerDown, handlePointerEnter } = useDecalEventHandlers({ parent, decal, visible });
@@ -126,6 +124,7 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP
} else {
loadDefaultTexture();
}
// eslint-disable-next-line
}, [decal.decalId]);
useEffect(() => {
@@ -140,6 +139,7 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP
if (selectedDecal) setSelectedDecal(null);
if (deletableDecal) setDeletableDecal(null);
}
// eslint-disable-next-line
}, [toggleView, toolMode, activeModule, selectedDecal, deletableDecal]);
return (

View File

@@ -1,7 +1,7 @@
import * as THREE from 'three';
import { CameraControls } from '@react-three/drei';
import { ThreeEvent, useFrame, useThree } from '@react-three/fiber';
import { useEffect, useRef } from 'react';
import { useEffect, useState } from 'react';
import { useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
import useModuleStore from '../../../../store/useModuleStore';
@@ -10,8 +10,11 @@ import { useVersionContext } from '../../version/versionContext';
import { useParams } from 'react-router-dom';
import { useSceneContext } from '../../../scene/sceneContext';
// import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
// import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
import { detectModifierKeys } from '../../../../utils/shortcutkeys/detectModifierKeys';
import handleDecalPositionSnap from '../functions/handleDecalPositionSnap';
import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
export function useDecalEventHandlers({
parent,
@@ -34,6 +37,7 @@ export function useDecalEventHandlers({
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
const { socket } = useSocketStore();
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "">("");
const { raycaster, pointer, camera, scene, gl, controls } = useThree();
useFrame(() => {
@@ -51,14 +55,22 @@ export function useDecalEventHandlers({
const wallUuid = wallIntersect.object.userData.wallUuid;
const point = wallIntersect.object.worldToLocal(wallIntersect.point.clone());
let finalPos;
if (keyEvent === "Ctrl") {
finalPos = handleDecalPositionSnap(point, offset, parent, decal, 0.05)
} else {
finalPos = point
}
if ("wallUuid" in parent && parent.wallUuid === wallUuid && decal.decalType.type === 'Wall') {
updateDecalPositionInWall(decal.decalUuid, [point.x + offset.x, point.y + offset.y, decal.decalPosition[2]]);
updateDecalPositionInWall(decal.decalUuid, [finalPos.x + offset.x, finalPos.y + offset.y, decal.decalPosition[2]]);
} else if (decal.decalType.type === 'Wall' && wallUuid) {
deleteDecal(decal.decalUuid, parent);
const addedDecal = addDecalToWall(wallUuid, {
...decal,
decalPosition: [point.x + offset.x, point.y + offset.y, decal.decalPosition[2]],
decalPosition: [finalPos.x + offset.x, finalPos.y + offset.y, decal.decalPosition[2]],
decalType: { type: 'Wall', wallUuid: wallUuid }
});
@@ -72,7 +84,7 @@ export function useDecalEventHandlers({
const addedDecal = addDecalToWall(wallUuid, {
...decal,
decalPosition: [point.x + offset.x, point.y + offset.y, wall.wallThickness / 2 + 0.001],
decalPosition: [finalPos.x + offset.x, finalPos.y + offset.y, wall.wallThickness / 2 + 0.001],
decalType: { type: 'Wall', wallUuid: wallUuid }
});
@@ -84,14 +96,22 @@ export function useDecalEventHandlers({
const floorUuid = floorIntersect.object.userData.floorUuid;
const point = floorIntersect.object.worldToLocal(floorIntersect.point.clone());
let finalPos;
if (keyEvent === "Ctrl") {
finalPos = handleDecalPositionSnap(point, offset, parent, decal, 0.25)
} else {
finalPos = point
}
if ("floorUuid" in parent && parent.floorUuid === floorUuid && decal.decalType.type === 'Floor') {
updateDecalPositionInFloor(decal.decalUuid, [point.x + offset.x, point.y + offset.y, decal.decalPosition[2]]);
updateDecalPositionInFloor(decal.decalUuid, [finalPos.x + offset.x, finalPos.y + offset.y, decal.decalPosition[2]]);
} else if (decal.decalType.type === 'Floor' && floorUuid) {
deleteDecal(decal.decalUuid, parent);
const addedDecal = addDecalToFloor(floorUuid, {
...decal,
decalPosition: [point.x + offset.x, point.y + offset.y, decal.decalPosition[2]],
decalPosition: [finalPos.x + offset.x, finalPos.y + offset.y, decal.decalPosition[2]],
decalType: { type: 'Floor', floorUuid: floorUuid }
});
@@ -105,7 +125,7 @@ export function useDecalEventHandlers({
const addedDecal = addDecalToFloor(floorUuid, {
...decal,
decalPosition: [point.x + offset.x, point.y + offset.y, -0.001],
decalPosition: [finalPos.x + offset.x, finalPos.y + offset.y, -0.001],
decalType: { type: 'Floor', floorUuid: floorUuid }
});
@@ -116,7 +136,7 @@ export function useDecalEventHandlers({
}
});
const handlePointerUp = (e: PointerEvent) => {
const handlePointerUp = () => {
if (controls) {
(controls as CameraControls).enabled = true;
}
@@ -127,22 +147,25 @@ export function useDecalEventHandlers({
setTimeout(() => {
const updatedWall = getWallById(parent.wallUuid);
if (updatedWall) {
if (projectId && updatedWall) {
// API
if (projectId) {
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
// SOCKET
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
}
}, 0)
@@ -151,21 +174,24 @@ export function useDecalEventHandlers({
const updatedFloor = parent;
if (projectId && updatedFloor) {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
}, 0)
}
@@ -177,54 +203,59 @@ export function useDecalEventHandlers({
const updatedWall = removeDecalInWall(decalUuid);
if (projectId && updatedWall) {
// API
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
// SOCKET
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
} else if ('floorUuid' in parent) {
const updatedFloor = removeDecalInFloor(decalUuid);
if (projectId && updatedFloor) {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
}
}
const handlePointerDown = (e: ThreeEvent<MouseEvent>) => {
if (visible && !toggleView && activeModule === 'builder') {
if (e.object.userData.decalUuid && toolMode === 'cursor') {
if (e.object.userData.decalUuid && toolMode === 'cursor' && (selectedDecal && selectedDecal.decalData.decalUuid === decal.decalUuid)) {
e.stopPropagation();
setDecalDragState(true, decal.decalUuid, null);
if (controls) {
(controls as CameraControls).enabled = false;
}
setSelectedDecal({ decalMesh: e.object, decalData: decal });
setSelectedWall(null);
setSelectedFloor(null);
@@ -275,19 +306,46 @@ export function useDecalEventHandlers({
const handlePointerMissed = () => {
if (selectedDecal && selectedDecal.decalMesh && selectedDecal.decalMesh.userData.decalUuid === decal.decalUuid) {
setSelectedDecal(null);
setKeyEvent("");
}
};
const onKeyUp = (event: KeyboardEvent) => {
const keyCombination = detectModifierKeys(event);
if (keyCombination === "") {
setKeyEvent("");
} else if (keyCombination === "Ctrl") {
setKeyEvent(keyCombination);
}
};
const onKeyDown = (event: KeyboardEvent) => {
const keyCombination = detectModifierKeys(event);
if (keyCombination !== keyEvent) {
if (keyCombination === "Ctrl") {
setKeyEvent(keyCombination);
} else {
setKeyEvent("");
}
}
}
useEffect(() => {
const canvasElement = gl.domElement;
if (activeModule === 'builder' && !toggleView && selectedDecal && selectedDecal.decalData.decalUuid === decal.decalUuid) {
canvasElement.addEventListener('pointerup', handlePointerUp);
canvasElement?.addEventListener("keyup", onKeyUp);
canvasElement.addEventListener("keydown", onKeyDown);
}
return () => {
canvasElement.removeEventListener('pointerup', handlePointerUp);
canvasElement?.removeEventListener("keyup", onKeyUp);
canvasElement.removeEventListener("keydown", onKeyDown);
};
// eslint-disable-next-line
}, [gl, activeModule, toggleView, selectedDecal, camera, controls, visible, parent, decal, decalDragState]);
return {

View File

@@ -0,0 +1,43 @@
import * as THREE from 'three';
function snapToFixedPoint(
position: [number, number, number],
snapInterval: number = 0.1
): [number, number, number] {
return [
Math.round(position[0] / snapInterval) * snapInterval,
Math.round(position[1] / snapInterval) * snapInterval,
Math.round(position[2] / snapInterval) * snapInterval,
];
}
function handleDecalPositionSnap(
point: THREE.Vector3,
offset: THREE.Vector3,
parent: Wall | Floor,
decal: Decal,
snapInterval: number = 0.1
): THREE.Vector3 {
let rawPos: [number, number, number];
if ("wallUuid" in parent) {
// snap relative to wall
rawPos = [
point.x + offset.x,
point.y + offset.y,
decal.decalPosition[2], // keep depth as-is
];
} else {
// snap relative to floor
rawPos = [
point.x + offset.x,
point.y + offset.y,
decal.decalPosition[2],
];
}
const snapped = snapToFixedPoint(rawPos, snapInterval);
return new THREE.Vector3(snapped[0], snapped[1], snapped[2]);
}
export default handleDecalPositionSnap;

View File

@@ -10,7 +10,7 @@ import ReferenceAisle from './referenceAisle';
import ReferencePoint from '../../point/reference/referencePoint';
import { getUserData } from '../../../../functions/getUserData';
// import { upsertAisleApi } from '../../../../services/factoryBuilder/aisle/upsertAisleApi';
import { upsertAisleApi } from '../../../../services/factoryBuilder/aisle/upsertAisleApi';
function AisleCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -93,431 +93,70 @@ function AisleCreator() {
}
}
if (aisleType === 'solid-aisle') {
const aisleConfigs: Record<string, (color: string) => any> = {
"solid-aisle": (color) => ({ aisleType: "solid-aisle", aisleColor: color, aisleWidth }),
"dashed-aisle": (color) => ({ aisleType: "dashed-aisle", aisleColor: color, aisleWidth, dashLength, gapLength }),
"dotted-aisle": (color) => ({ aisleType: "dotted-aisle", aisleColor: color, dotRadius, gapLength }),
"arrow-aisle": (color) => ({ aisleType: "arrow-aisle", aisleColor: color, aisleWidth }),
"arrows-aisle": (color) => ({ aisleType: "arrows-aisle", aisleColor: color, aisleWidth, aisleLength, gapLength }),
"arc-aisle": (color) => ({ aisleType: "arc-aisle", aisleColor: color, aisleWidth, isFlipped }),
"circle-aisle": (color) => ({ aisleType: "circle-aisle", aisleColor: color, aisleWidth }),
"junction-aisle": (color) => ({ aisleType: "junction-aisle", aisleColor: color, aisleWidth, isFlipped })
};
if (!aisleType || !(aisleType in aisleConfigs)) return;
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
return;
}
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: aisleConfigs[aisleType](aisleColor)
};
addAisle(aisle);
push2D({
type: "Draw",
actions: [{
actionType: "Line-Create",
point: { type: "Aisle", lineData: aisle, timeStamp: new Date().toISOString() }
}]
});
addAilseToBackend(aisle);
setTempPoints([newPoint]);
};
const addAilseToBackend = (aisle: Aisle) => {
if (projectId) {
if (!socket?.connected) {
// API
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
} else {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: {
aisleType: 'solid-aisle',
aisleColor: aisleColor,
aisleWidth: aisleWidth
}
};
addAisle(aisle);
// SOCKET
push2D({
type: 'Draw',
actions: [
{
actionType: 'Line-Create',
point: {
type: 'Aisle',
lineData: aisle,
timeStamp: new Date().toISOString(),
}
}
],
})
if (projectId) {
// API
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
})
}
setTempPoints([newPoint]);
}
} else if (aisleType === 'dashed-aisle') {
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
} else {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: {
aisleType: 'dashed-aisle',
aisleColor: aisleColor,
aisleWidth: aisleWidth,
dashLength: dashLength,
gapLength: gapLength
}
};
addAisle(aisle);
push2D({
type: 'Draw',
actions: [
{
actionType: 'Line-Create',
point: {
type: 'Aisle',
lineData: aisle,
timeStamp: new Date().toISOString(),
}
}
],
})
if (projectId) {
// API
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
})
}
setTempPoints([newPoint]);
}
} else if (aisleType === 'dotted-aisle') {
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
} else {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: {
aisleType: 'dotted-aisle',
aisleColor: aisleColor,
dotRadius: dotRadius,
gapLength: gapLength
}
};
addAisle(aisle);
push2D({
type: 'Draw',
actions: [
{
actionType: 'Line-Create',
point: {
type: 'Aisle',
lineData: aisle,
timeStamp: new Date().toISOString(),
}
}
],
})
if (projectId) {
// API
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
})
}
setTempPoints([newPoint]);
}
} else if (aisleType === 'arrow-aisle') {
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
} else {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: {
aisleType: 'arrow-aisle',
aisleColor: aisleColor,
aisleWidth: aisleWidth
}
};
addAisle(aisle);
push2D({
type: 'Draw',
actions: [
{
actionType: 'Line-Create',
point: {
type: 'Aisle',
lineData: aisle,
timeStamp: new Date().toISOString(),
}
}
],
})
if (projectId) {
// API
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
})
}
setTempPoints([newPoint]);
}
} else if (aisleType === 'arrows-aisle') {
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
} else {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: {
aisleType: 'arrows-aisle',
aisleColor: aisleColor,
aisleWidth: aisleWidth,
aisleLength: aisleLength,
gapLength: gapLength
}
};
addAisle(aisle);
push2D({
type: 'Draw',
actions: [
{
actionType: 'Line-Create',
point: {
type: 'Aisle',
lineData: aisle,
timeStamp: new Date().toISOString(),
}
}
],
})
if (projectId) {
// API
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
})
}
setTempPoints([newPoint]);
}
} else if (aisleType === 'arc-aisle') {
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
} else {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: {
aisleType: 'arc-aisle',
aisleColor: aisleColor,
aisleWidth: aisleWidth,
isFlipped: isFlipped
}
};
addAisle(aisle);
push2D({
type: 'Draw',
actions: [
{
actionType: 'Line-Create',
point: {
type: 'Aisle',
lineData: aisle,
timeStamp: new Date().toISOString(),
}
}
],
})
if (projectId) {
// API
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
})
}
setTempPoints([newPoint]);
}
} else if (aisleType === 'circle-aisle') {
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
} else {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: {
aisleType: 'circle-aisle',
aisleColor: aisleColor,
aisleWidth: aisleWidth
}
};
addAisle(aisle);
push2D({
type: 'Draw',
actions: [
{
actionType: 'Line-Create',
point: {
type: 'Aisle',
lineData: aisle,
timeStamp: new Date().toISOString(),
}
}
],
})
if (projectId) {
// API
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
})
}
setTempPoints([newPoint]);
}
} else if (aisleType === 'junction-aisle') {
if (tempPoints.length === 0) {
setTempPoints([newPoint]);
setIsCreating(true);
} else {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
type: {
aisleType: 'junction-aisle',
aisleColor: aisleColor,
aisleWidth: aisleWidth,
isFlipped: isFlipped
}
};
addAisle(aisle);
push2D({
type: 'Draw',
actions: [
{
actionType: 'Line-Create',
point: {
type: 'Aisle',
lineData: aisle,
timeStamp: new Date().toISOString(),
}
}
],
})
if (projectId) {
// API
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
})
}
setTempPoints([newPoint]);
socket.emit("v1:model-aisle:add", {
projectId,
versionId: selectedVersion?.versionId || "",
userId,
organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
type: aisle.type
});
}
}
};
}
const onContext = (event: any) => {
event.preventDefault();

View File

@@ -1,7 +1,7 @@
import * as THREE from "three"
import { useEffect } from 'react'
import { getFloorAssets } from '../../../services/factoryBuilder/asset/floorAsset/getFloorItemsApi';
import { useLoadingProgress, useRenameModeStore, useSelectedFloorItem, useSelectedItem, useSocketStore } from '../../../store/builder/store';
import { useLoadingProgress, useRenameModeStore, useSelectedItem, useSocketStore } from '../../../store/builder/store';
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { FloorItems, RefMesh } from "../../../types/world/worldTypes";
@@ -15,6 +15,7 @@ import { useLeftData, useTopData } from "../../../store/visualization/useZone3DW
import { getUserData } from "../../../functions/getUserData";
import { useSceneContext } from "../../scene/sceneContext";
import { useVersionContext } from "../version/versionContext";
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
const gltfLoaderWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js", import.meta.url));
@@ -28,7 +29,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
const { selectedVersion } = selectedVersionStore();
const { setAssets, addAsset, clearAssets } = assetStore();
const { addEvent, clearEvents } = eventStore();
const { setSelectedFloorItem } = useSelectedFloorItem();
const { setSelectedFloorAsset } = useBuilderStore();
const { selectedItem, setSelectedItem } = useSelectedItem();
const { projectId } = useParams();
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
@@ -377,7 +378,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
if ((controls as CameraControls)) {
const target = (controls as CameraControls).getTarget(new THREE.Vector3());
(controls as CameraControls).setTarget(target.x, 0, target.z, true);
setSelectedFloorItem(null);
setSelectedFloorAsset(null);
}
}

View File

@@ -7,14 +7,14 @@ import * as CONSTANTS from "../../../../types/world/worldConstants";
import PointsCalculator from "../../../simulation/events/points/functions/pointsCalculator";
import { getUserData } from "../../../../functions/getUserData";
// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
async function addAssetModel(
scene: THREE.Scene,
raycaster: THREE.Raycaster,
camera: THREE.Camera,
pointer: THREE.Vector2,
socket: Socket<any>,
socket: Socket<any> | null,
selectedItem: any,
setSelectedItem: any,
addEvent: (event: EventsSchema) => void,
@@ -106,7 +106,7 @@ async function handleModelLoad(
selectedItem: any,
addEvent: (event: EventsSchema) => void,
addAsset: (asset: Asset) => void,
socket: Socket<any>,
socket: Socket<any> | null,
versionId: string,
projectId?: string,
userId?: string
@@ -140,22 +140,6 @@ async function handleModelLoad(
opacity: 1,
};
// API
// await setAssetsApi(
// organization,
// newFloorItem.modelUuid,
// newFloorItem.modelName,
// newFloorItem.assetId,
// newFloorItem.position,
// { x: 0, y: 0, z: 0 },
// false,
// true,
// );
// SOCKET
if (selectedItem.type) {
const data = PointsCalculator(
selectedItem.type,
@@ -449,14 +433,34 @@ async function handleModelLoad(
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z, },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id || '',
eventData: eventData,
versionId: versionId,
projectId: projectId,
userId: userId,
};
socket.emit("v1:model-asset:add", completeData);
if (!socket?.connected) {
// API
setAssetsApi({
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
position: newFloorItem.position,
assetId: newFloorItem.assetId,
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z, },
eventData: eventData,
isLocked: false,
isVisible: true,
versionId: versionId,
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", completeData);
}
const asset: Asset = {
modelUuid: completeData.modelUuid,
@@ -482,13 +486,32 @@ async function handleModelLoad(
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z, },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id || '',
versionId: versionId,
projectId: projectId,
userId: userId,
};
socket.emit("v1:model-asset:add", data);
if (!socket?.connected) {
// API
setAssetsApi({
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
position: newFloorItem.position,
assetId: newFloorItem.assetId,
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z, },
isLocked: false,
isVisible: true,
versionId: versionId,
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", data);
}
const asset = {
modelUuid: data.modelUuid,

View File

@@ -3,9 +3,8 @@ import { CameraControls } from '@react-three/drei';
import { ThreeEvent, useThree } from '@react-three/fiber';
import { useCallback, useEffect, useRef } from 'react';
import { useActiveTool, useDeletableFloorItem, useResourceManagementId, useSelectedFloorItem, useToggleView, useZoneAssetId } from '../../../../../../store/builder/store';
import { useActiveTool, useResourceManagementId, useToggleView, useZoneAssetId, useSocketStore } from '../../../../../../store/builder/store';
import useModuleStore, { useSubModuleStore } from '../../../../../../store/useModuleStore';
import { useSocketStore } from '../../../../../../store/builder/store';
import { useSceneContext } from '../../../../../scene/sceneContext';
import { useProductContext } from '../../../../../simulation/products/productContext';
import { useVersionContext } from '../../../../version/versionContext';
@@ -13,9 +12,10 @@ import { useParams } from 'react-router-dom';
import { getUserData } from '../../../../../../functions/getUserData';
import { useLeftData, useTopData } from '../../../../../../store/visualization/useZone3DWidgetStore';
import { useSelectedAsset } from '../../../../../../store/simulation/useSimulationStore';
import { upsertProductOrEventApi } from '../../../../../../services/simulation/products/UpsertProductOrEventApi';
import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore';
// import { deleteFloorItem } from '../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
import { upsertProductOrEventApi } from '../../../../../../services/simulation/products/UpsertProductOrEventApi';
import { deleteFloorItem } from '../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
export function useModelEventHandlers({
boundingBox,
@@ -40,8 +40,7 @@ export function useModelEventHandlers({
const { removeEvent, getEventByModelUuid } = eventStore();
const { getIsEventInProduct, addPoint, deleteEvent } = productStore();
const { setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
const { deletableFloorAsset, setDeletableFloorAsset, selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { selectedVersionStore } = useVersionContext();
@@ -89,10 +88,10 @@ export function useModelEventHandlers({
}, [resourceManagementId])
useEffect(() => {
if (!selectedFloorItem) {
if (!selectedFloorAsset) {
setZoneAssetId(null);
}
}, [selectedFloorItem])
}, [selectedFloorAsset])
const handleDblClick = (asset: Asset) => {
if (asset && activeTool === "cursor" && boundingBox && groupRef.current && (activeModule === 'builder' || (activeModule === 'simulation' && resourceManagementId))) {
@@ -137,33 +136,37 @@ export function useModelEventHandlers({
(controls as CameraControls).setLookAt(newCameraPos.x, newCameraPos.y, newCameraPos.z, collisionPos.x, 0, collisionPos.z, true);
}
setSelectedFloorItem(groupRef.current);
setSelectedFloorAsset(groupRef.current);
setResourceManagementId("");
}
};
const handleClick = async (evt: ThreeEvent<MouseEvent>, asset: Asset) => {
if (leftDrag.current || toggleView) return;
if (activeTool === 'delete' && deletableFloorItem && deletableFloorItem.uuid === asset.modelUuid) {
if (activeTool === 'delete' && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
//REST
if (!socket?.connected) {
// const response = await deleteFloorItem(organization, asset.modelUuid, asset.modelName);
// REST
//SOCKET
deleteFloorItem(organization, asset.modelUuid, asset.modelName);
const data = {
organization,
modelUuid: asset.modelUuid,
modelName: asset.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
} else {
// SOCKET
const data = {
organization,
modelUuid: asset.modelUuid,
modelName: asset.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
socket.emit('v1:model-asset:delete', data)
}
const response = socket.emit('v1:model-asset:delete', data)
removeEvent(asset.modelUuid);
const updatedEvents = deleteEvent(asset.modelUuid);
@@ -176,27 +179,24 @@ export function useModelEventHandlers({
);
})
if (response) {
removeAsset(asset.modelUuid);
removeAsset(asset.modelUuid);
push3D({
type: 'Scene',
actions: [
{
module: "builder",
actionType: "Asset-Delete",
asset: {
type: "Asset",
assetData: asset,
timeStap: new Date().toISOString()
}
push3D({
type: 'Scene',
actions: [
{
module: "builder",
actionType: "Asset-Delete",
asset: {
type: "Asset",
assetData: asset,
timeStap: new Date().toISOString()
}
]
});
}
]
});
echo.success("Model Removed!");
}
echo.success("Model Removed!");
} else if (activeModule === 'simulation' && subModule === "simulations" && activeTool === 'pen') {
if (asset.eventData && asset.eventData.type === 'Conveyor') {
@@ -236,19 +236,19 @@ export function useModelEventHandlers({
const handlePointerOver = useCallback((asset: Asset) => {
if (activeTool === "delete" && activeModule === 'builder') {
if (deletableFloorItem && deletableFloorItem.uuid === asset.modelUuid) {
if (deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
return;
} else {
setDeletableFloorItem(groupRef.current);
setDeletableFloorAsset(groupRef.current);
}
}
}, [activeTool, activeModule, deletableFloorItem]);
}, [activeTool, activeModule, deletableFloorAsset]);
const handlePointerOut = useCallback((evt: ThreeEvent<MouseEvent>, asset: Asset) => {
if (evt.intersections.length === 0 && activeTool === "delete" && deletableFloorItem && deletableFloorItem.uuid === asset.modelUuid) {
setDeletableFloorItem(null);
if (evt.intersections.length === 0 && activeTool === "delete" && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
setDeletableFloorAsset(null);
}
}, [activeTool, deletableFloorItem]);
}, [activeTool, deletableFloorAsset]);
const handleContextMenu = (asset: Asset, evt: ThreeEvent<MouseEvent>) => {
if (rightDrag.current || toggleView) return;

View File

@@ -2,8 +2,9 @@ import * as THREE from 'three';
import { useEffect, useRef, useState } from 'react';
import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { useDeletableFloorItem, useSelectedAssets, useSelectedFloorItem, useToggleView, useToolMode } from '../../../../../store/builder/store';
import { useToggleView, useToolMode } from '../../../../../store/builder/store';
import { AssetBoundingBox } from '../../functions/assetBoundingBox';
import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
import useModuleStore from '../../../../../store/useModuleStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { SkeletonUtils } from 'three-stdlib';
@@ -19,15 +20,13 @@ function Model({ asset, isRendered, loader }: { readonly asset: Asset, isRendere
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
const { assetStore } = useSceneContext();
const { resetAnimation } = assetStore();
const { setDeletableFloorItem } = useDeletableFloorItem();
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
const { resetAnimation, selectedAssets } = assetStore();
const { setDeletableFloorAsset, selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const [gltfScene, setGltfScene] = useState<GLTF["scene"] | null>(null);
const [boundingBox, setBoundingBox] = useState<THREE.Box3 | null>(null);
const [isSelected, setIsSelected] = useState(false);
const groupRef = useRef<THREE.Group>(null);
const [fieldData, setFieldData] = useState<any>();
const { selectedAssets } = useSelectedAssets();
useEffect(() => {
if (!fieldData && asset.eventData) {
@@ -53,17 +52,17 @@ function Model({ asset, isRendered, loader }: { readonly asset: Asset, isRendere
}, [asset.modelUuid, fieldData])
useEffect(() => {
setDeletableFloorItem(null);
if (selectedFloorItem === null || selectedFloorItem.userData.modelUuid !== asset.modelUuid) {
setDeletableFloorAsset(null);
if (selectedFloorAsset === null || selectedFloorAsset.userData.modelUuid !== asset.modelUuid) {
resetAnimation(asset.modelUuid);
}
}, [activeModule, toolMode, selectedFloorItem])
}, [activeModule, toolMode, selectedFloorAsset])
useEffect(() => {
if (selectedFloorItem && selectedFloorItem.userData.modelUuid === asset.modelUuid) {
setSelectedFloorItem(groupRef.current);
if (selectedFloorAsset && selectedFloorAsset.userData.modelUuid === asset.modelUuid) {
setSelectedFloorAsset(groupRef.current);
}
}, [isRendered, selectedFloorItem])
}, [isRendered, selectedFloorAsset])
useEffect(() => {
if (selectedAssets.length > 0) {

View File

@@ -2,9 +2,10 @@ import { useEffect, useRef, useState } from "react";
import { useThree, useFrame } from "@react-three/fiber";
import { Group, Vector3 } from "three";
import { CameraControls } from '@react-three/drei';
import { useLimitDistance, useRenderDistance, useSelectedFloorItem, useToggleView } from '../../../../store/builder/store';
import { useLimitDistance, useRenderDistance } from '../../../../store/builder/store';
import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
import { useSceneContext } from '../../../scene/sceneContext';
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import Model from './model/model';
import { GLTFLoader } from "three/examples/jsm/Addons";
@@ -16,7 +17,7 @@ function Models({ loader }: { loader: GLTFLoader }) {
const assetGroupRef = useRef<Group>(null);
const { assetStore } = useSceneContext();
const { assets } = assetStore();
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const { limitDistance } = useLimitDistance();
const { renderDistance } = useRenderDistance();
@@ -49,10 +50,10 @@ function Models({ loader }: { loader: GLTFLoader }) {
ref={assetGroupRef}
onPointerMissed={(e) => {
e.stopPropagation();
if (selectedFloorItem) {
if (selectedFloorAsset) {
const target = (controls as CameraControls).getTarget(new Vector3());
(controls as CameraControls).setTarget(target.x, 0, target.z, true);
setSelectedFloorItem(null);
setSelectedFloorAsset(null);
}
if (selectedAsset) {
clearSelectedAsset();

View File

@@ -9,6 +9,8 @@ import { useVersionContext } from '../version/versionContext';
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import { useSceneContext } from '../../scene/sceneContext';
import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
/**
* DxfFile component handles the rendering and manipulation of DXf file data in a 3D scene.
* It processes the DXF data to create points and lines representing walls and allows
@@ -39,20 +41,25 @@ const DxfFile = () => {
if (dfxWallGenerate) {
dfxWallGenerate.map((wall: Wall) => {
const data = {
wallData: wall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
addWall(wall);
socket.emit('v1:model-Wall:add', data);
// API
if (projectId) {
if (!socket?.connected) {
// API
// if (projectId) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', wall);
// }
upsertWallApi(projectId, selectedVersion?.versionId || '', wall);
} else {
// SOCKET
const data = {
wallData: wall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
addWall(wall);
socket.emit('v1:model-Wall:add', data);
}
}
})
}
}, [dfxWallGenerate]);

View File

@@ -10,7 +10,7 @@ import { getUserData } from '../../../../functions/getUserData';
import ReferencePoint from '../../point/reference/referencePoint';
import ReferenceFloor from './referenceFloor';
// import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
function FloorCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -120,23 +120,25 @@ function FloorCreator() {
})
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
setTempPoints([]);
setIsCreating(false);
@@ -174,23 +176,25 @@ function FloorCreator() {
})
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
setTempPoints([]);
setIsCreating(false);
@@ -238,23 +242,25 @@ function FloorCreator() {
})
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
}
setTempPoints([]);

View File

@@ -13,14 +13,14 @@ import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCurso
import { useSelectedPoints } from '../../../store/simulation/useSimulationStore';
import { calculateAssetTransformationOnWall } from '../wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall';
// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
// import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
// import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
// import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
// import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
// import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
// import { deleteWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
import { deleteWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
interface LineProps {
points: [Point, Point];
@@ -120,43 +120,48 @@ function Line({ points }: Readonly<LineProps>) {
if (projectId && asset) {
removeWallAsset(asset.modelUuid);
if (!socket?.connected) {
// API
// API
// deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
wallUuid: asset.wallUuid
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
wallUuid: asset.wallUuid
}
socket.emit('v1:wall-asset:delete', data);
}
socket.emit('v1:wall-asset:delete', data);
}
})
if (!socket?.connected) {
// API
// API
// deleteWallApi(projectId, selectedVersion?.versionId || '', removedWall.wallUuid);
deleteWallApi(projectId, selectedVersion?.versionId || '', removedWall.wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
wallUuid: removedWall.wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallUuid: removedWall.wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:delete', data);
}
socket.emit('v1:model-Wall:delete', data);
push2D({
type: 'Draw',
actions: [
@@ -180,22 +185,25 @@ function Line({ points }: Readonly<LineProps>) {
if (removedFloors.length > 0) {
removedFloors.forEach(floor => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
} else {
// SOCKET
// SOCKET
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:delete', data);
}
socket.emit('v1:model-Floor:delete', data);
}
});
@@ -218,22 +226,25 @@ function Line({ points }: Readonly<LineProps>) {
if (updatedFloors.length > 0) {
updatedFloors.forEach(floor => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
});
@@ -263,22 +274,25 @@ function Line({ points }: Readonly<LineProps>) {
if (removedZones.length > 0) {
removedZones.forEach(zone => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
} else {
// SOCKET
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:delete', data);
}
socket.emit('v1:zone:delete', data);
}
});
@@ -301,22 +315,25 @@ function Line({ points }: Readonly<LineProps>) {
if (updatedZones.length > 0) {
updatedZones.forEach(zone => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
}
});
@@ -435,40 +452,47 @@ function Line({ points }: Readonly<LineProps>) {
});
if (projectId && updatedWallAsset) {
// API
if (!socket?.connected) {
// API
// upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
} else {
// SOCKET
// SOCKET
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:wall-asset:add', data);
}
socket.emit('v1:wall-asset:add', data);
}
});
}
// API
if (!socket?.connected) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
// API
// SOCKET
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
})
if (initialPositions.walls && initialPositions.walls.length > 0) {
@@ -495,22 +519,25 @@ function Line({ points }: Readonly<LineProps>) {
if (updatedFloors.length > 0 && projectId) {
updatedFloors.forEach(updatedFloor => {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
})
if (initialPositions.floors && initialPositions.floors.length > 0) {
@@ -537,22 +564,25 @@ function Line({ points }: Readonly<LineProps>) {
if (updatedZones.length > 0 && projectId) {
updatedZones.forEach(updatedZone => {
if (!socket?.connected) {
// API
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: updatedZone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: updatedZone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
})
if (initialPositions.zones && initialPositions.zones.length > 0) {

View File

@@ -11,16 +11,16 @@ import { useParams } from 'react-router-dom';
import { useVersionContext } from '../version/versionContext';
import { useSceneContext } from '../../scene/sceneContext';
// import { upsertAisleApi } from '../../../services/factoryBuilder/aisle/upsertAisleApi';
// import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
// import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
// import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
// import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
// import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
// import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
// import { deleteWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
import { upsertAisleApi } from '../../../services/factoryBuilder/aisle/upsertAisleApi';
import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
import { deleteWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
import { getUserData } from '../../../functions/getUserData';
import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors';
@@ -190,22 +190,25 @@ function Point({ point }: { readonly point: Point }) {
const updatedAisles = getAislesByPointId(point.pointUuid);
if (updatedAisles.length > 0 && projectId) {
updatedAisles.forEach((updatedAisle) => {
if (!socket?.connected) {
// API
// API
// upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
} else {
// SOCKET
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: updatedAisle.aisleUuid,
points: updatedAisle.points,
type: updatedAisle.type
})
socket.emit('v1:model-aisle:add', {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: updatedAisle.aisleUuid,
points: updatedAisle.points,
type: updatedAisle.type
})
}
})
if (initialStates.aisles && initialStates.aisles.length > 0) {
@@ -244,40 +247,47 @@ function Point({ point }: { readonly point: Point }) {
});
if (projectId && updatedWallAsset) {
// API
if (!socket?.connected) {
// API
// upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
} else {
// SOCKET
// SOCKET
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:wall-asset:add', data);
}
socket.emit('v1:wall-asset:add', data);
}
});
}
// API
if (!socket?.connected) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
// API
// SOCKET
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
});
}
@@ -301,22 +311,25 @@ function Point({ point }: { readonly point: Point }) {
const updatedFloors = getFloorsByPointId(point.pointUuid);
if (updatedFloors && updatedFloors.length > 0 && projectId) {
updatedFloors.forEach((updatedFloor) => {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
});
}
@@ -340,22 +353,25 @@ function Point({ point }: { readonly point: Point }) {
const updatedZones = getZonesByPointId(point.pointUuid);
if (updatedZones && updatedZones.length > 0 && projectId) {
updatedZones.forEach((updatedZone) => {
if (!socket?.connected) {
// API
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: updatedZone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: updatedZone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
});
}
@@ -388,23 +404,26 @@ function Point({ point }: { readonly point: Point }) {
if (removedAisles.length > 0) {
removedAisles.forEach(aisle => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');
deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');
} else {
// SOCKET
// SOCKET
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid
}
socket.emit('v1:model-aisle:delete', data);
}
socket.emit('v1:model-aisle:delete', data);
}
});
@@ -436,44 +455,50 @@ function Point({ point }: { readonly point: Point }) {
if (projectId && asset) {
removeWallAsset(asset.modelUuid);
if (!socket?.connected) {
// API
// API
// deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
wallUuid: asset.wallUuid
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
wallUuid: asset.wallUuid
}
socket.emit('v1:wall-asset:delete', data);
}
socket.emit('v1:wall-asset:delete', data);
}
})
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:delete', data);
}
socket.emit('v1:model-Wall:delete', data);
}
});
@@ -501,22 +526,25 @@ function Point({ point }: { readonly point: Point }) {
if (removedFloors.length > 0) {
removedFloors.forEach(floor => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
} else {
// SOCKET
// SOCKET
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:delete', data);
}
socket.emit('v1:model-Floor:delete', data);
}
});
@@ -539,22 +567,25 @@ function Point({ point }: { readonly point: Point }) {
if (updatedFloors.length > 0) {
updatedFloors.forEach(floor => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
});
@@ -583,22 +614,25 @@ function Point({ point }: { readonly point: Point }) {
if (removedZones.length > 0) {
removedZones.forEach(zone => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
} else {
// SOCKET
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:delete', data);
}
socket.emit('v1:zone:delete', data);
}
});
@@ -621,22 +655,25 @@ function Point({ point }: { readonly point: Point }) {
if (updatedZones.length > 0) {
updatedZones.forEach(zone => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
}
});

View File

@@ -12,8 +12,8 @@ import getClosestIntersection from '../../line/helpers/getClosestIntersection';
import ReferencePoint from '../../point/reference/referencePoint';
import ReferenceWall from './referenceWall';
// import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
// import { deleteWallApi } from '../../../../services/factoryBuilder/wall/deleteWallApi';
import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
import { deleteWallApi } from '../../../../services/factoryBuilder/wall/deleteWallApi';
function WallCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -94,23 +94,26 @@ function WallCreator() {
removeWall(wall.wallUuid);
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:delete', data);
}
socket.emit('v1:model-Wall:delete', data);
}
const point1: Point = {
@@ -147,24 +150,27 @@ function WallCreator() {
addWall(wall2);
// API
if (projectId) {
if (!socket?.connected) {
// API
// if (projectId) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', wall2);
// }
upsertWallApi(projectId, selectedVersion?.versionId || '', wall2);
} else {
// SOCKET
// SOCKET
const data = {
wallData: wall2,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: wall2,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
}
socket.emit('v1:model-Wall:add', data);
const wall3: Wall = {
wallUuid: THREE.MathUtils.generateUUID(),
points: [point2, newPoint],
@@ -204,24 +210,27 @@ function WallCreator() {
],
})
// API
if (projectId) {
if (!socket?.connected) {
// API
// if (projectId) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', wall3);
// }
upsertWallApi(projectId, selectedVersion?.versionId || '', wall3);
} else {
// SOCKET
// SOCKET
const data2 = {
wallData: wall3,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data2 = {
wallData: wall3,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data2);
}
}
socket.emit('v1:model-Wall:add', data2);
setTempPoints([newPoint]);
setIsCreating(true);
} else {
@@ -237,24 +246,27 @@ function WallCreator() {
addWall(wall1);
// API
if (projectId) {
if (!socket?.connected) {
// API
// if (projectId) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', wall1);
// }
upsertWallApi(projectId, selectedVersion?.versionId || '', wall1);
} else {
// SOCKET
// SOCKET
const data = {
wallData: wall1,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: wall1,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
}
socket.emit('v1:model-Wall:add', data);
const wall2: Wall = {
wallUuid: THREE.MathUtils.generateUUID(),
points: [point1, newPoint],
@@ -267,24 +279,27 @@ function WallCreator() {
addWall(wall2);
// API
if (projectId) {
if (!socket?.connected) {
// API
// if (projectId) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', wall2);
// }
upsertWallApi(projectId, selectedVersion?.versionId || '', wall2);
} else {
// SOCKET
// SOCKET
const data1 = {
wallData: wall2,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data1 = {
wallData: wall2,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data1);
}
}
socket.emit('v1:model-Wall:add', data1);
const wall3: Wall = {
wallUuid: THREE.MathUtils.generateUUID(),
points: [point2, newPoint],
@@ -328,24 +343,27 @@ function WallCreator() {
],
})
// API
if (projectId) {
if (!socket?.connected) {
// API
// if (projectId) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', wall3);
// }
upsertWallApi(projectId, selectedVersion?.versionId || '', wall3);
} else {
// SOCKET
// SOCKET
const data3 = {
wallData: wall3,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data3 = {
wallData: wall3,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data3);
}
}
socket.emit('v1:model-Wall:add', data3);
setTempPoints([newPoint]);
}
@@ -411,24 +429,27 @@ function WallCreator() {
],
})
// API
if (projectId) {
if (!socket?.connected) {
// API
// if (projectId) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', wall);
// }
upsertWallApi(projectId, selectedVersion?.versionId || '', wall);
} else {
// SOCKET
// SOCKET
const data = {
wallData: wall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: wall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
}
socket.emit('v1:model-Wall:add', data);
setTempPoints([newPoint]);
}

View File

@@ -14,8 +14,8 @@ import { useVersionContext } from '../../../version/versionContext';
import { getUserData } from '../../../../../functions/getUserData';
import closestPointOnLineSegment from '../../../line/helpers/getClosestPointOnLineSegment';
// import { upsertWallAssetApi } from '../../../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
// import { deleteWallAssetApi } from '../../../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
import { upsertWallAssetApi } from '../../../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
import { deleteWallAssetApi } from '../../../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) {
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
@@ -126,23 +126,25 @@ function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) {
const updatedWallAsset = getWallAssetById(wallAsset.modelUuid);
if (projectId && updatedWallAsset) {
if (!socket?.connected) {
// API
// API
// upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
} else {
// SOCKET
// SOCKET
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:wall-asset:add', data);
}
socket.emit('v1:wall-asset:add', data);
}
}
}
@@ -194,24 +196,26 @@ function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) {
const removedWallAsset = removeWallAsset(wallAsset.modelUuid);
if (projectId && removedWallAsset) {
if (!socket?.connected) {
// API
// API
// deleteWallAssetApi(projectId, selectedVersion?.versionId || '', removedWallAsset.modelUuid, removedWallAsset.wallUuid);
deleteWallAssetApi(projectId, selectedVersion?.versionId || '', removedWallAsset.modelUuid, removedWallAsset.wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
modelUuid: removedWallAsset.modelUuid,
wallUuid: removedWallAsset.wallUuid
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
modelUuid: removedWallAsset.modelUuid,
wallUuid: removedWallAsset.wallUuid
}
socket.emit('v1:wall-asset:delete', data);
}
socket.emit('v1:wall-asset:delete', data);
}
}
}, [activeTool, activeModule, deletableWallAsset, socket])
@@ -288,7 +292,7 @@ function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) {
setSelectedWallAsset(null);
}
}}
onPointerOver={(e) => {
onPointerEnter={(e) => {
if (!toggleView) {
e.stopPropagation();
let currentObject = e.object as THREE.Object3D;

View File

@@ -9,7 +9,7 @@ import { useVersionContext } from '../version/versionContext';
import { getUserData } from '../../../functions/getUserData';
import closestPointOnLineSegment from '../line/helpers/getClosestPointOnLineSegment';
// import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
function WallAssetCreator() {
const { socket } = useSocketStore();
@@ -62,23 +62,25 @@ function WallAssetCreator() {
addWallAsset(newWallAsset);
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertWallAssetApi(projectId, selectedVersion?.versionId || '', newWallAsset);
upsertWallAssetApi(projectId, selectedVersion?.versionId || '', newWallAsset);
} else {
// SOCKET
// SOCKET
const data = {
wallAssetData: newWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallAssetData: newWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:wall-asset:add', data);
}
socket.emit('v1:wall-asset:add', data);
}
}
}

View File

@@ -10,7 +10,7 @@ import { getUserData } from '../../../../functions/getUserData';
import ReferencePoint from '../../point/reference/referencePoint';
import ReferenceZone from './referenceZone';
// import { upsertZoneApi } from '../../../../services/factoryBuilder/zone/upsertZoneApi';
import { upsertZoneApi } from '../../../../services/factoryBuilder/zone/upsertZoneApi';
function ZoneCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -33,7 +33,6 @@ function ZoneCreator() {
const [isCreating, setIsCreating] = useState(false);
const { zoneColor, zoneHeight, snappedPosition, snappedPoint, setSnappedPoint, setSnappedPosition } = useBuilderStore();
useEffect(() => {
const canvasElement = gl.domElement;
@@ -119,23 +118,25 @@ function ZoneCreator() {
})
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
}
setTempPoints([]);
setIsCreating(false);
@@ -171,23 +172,25 @@ function ZoneCreator() {
})
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
}
setTempPoints([]);
setIsCreating(false);
@@ -233,23 +236,25 @@ function ZoneCreator() {
})
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
}
}
setTempPoints([]);

View File

@@ -5,12 +5,16 @@ export default function SocketResponses() {
const { socket } = useSocketStore();
useEffect(() => {
socket.on("v1:model-asset:response:add", (data: any) => {
// console.log('data: ', data);
});
if (socket) {
socket.on("v1:model-asset:response:add", (data: any) => {
// console.log('data: ', data);
});
}
return () => {
socket.off("v1:model-asset:response:add");
if (socket) {
socket.off("v1:model-asset:response:add");
}
}
}, [socket])

View File

@@ -1,26 +1,41 @@
import { Socket } from "socket.io-client";
import * as THREE from "three";
import { getUserData } from "../../../../functions/getUserData";
import { CameraControls } from "@react-three/drei";
import { setCameraApi } from "../../../../services/factoryBuilder/camera/setCameraApi";
export default function updateCamPosition(
controls: any,
socket: Socket,
position: THREE.Vector3,
rotation: THREE.Euler,
projectId?: string
controls: React.RefObject<CameraControls>,
socket: Socket,
position: THREE.Vector3,
rotation: THREE.Euler,
projectId?: string
) {
const { userId, organization } = getUserData();
if (!controls.current) return;
const target = controls.current.getTarget(new THREE.Vector3());
const { userId, organization } = getUserData();
if (!controls.current || !projectId) return;
const target = controls.current.getTarget(new THREE.Vector3());
const camData = {
organization,
userId: userId,
position: position,
target: new THREE.Vector3(target.x, 0, target.z),
rotation: new THREE.Vector3(rotation.x, rotation.y, rotation.z),
socketId: socket.id,
projectId,
};
socket.emit("v1:Camera:set", camData);
if (!socket?.connected) {
// API
setCameraApi(
projectId,
position,
new THREE.Vector3(target.x, 0, target.z),
new THREE.Vector3(rotation.x, rotation.y, rotation.z),
)
} else {
// SOCKET
const camData = {
organization,
userId: userId,
position: position,
target: new THREE.Vector3(target.x, 0, target.z),
rotation: new THREE.Vector3(rotation.x, rotation.y, rotation.z),
socketId: socket.id,
projectId,
};
socket.emit("v1:Camera:set", camData);
}
}

View File

@@ -5,6 +5,11 @@ import type { CameraControls } from "@react-three/drei";
const CameraShortcutsControls = () => {
const { camera, controls } = useThree();
const isTextInput = (element: Element | null): boolean =>
element instanceof HTMLInputElement ||
element instanceof HTMLTextAreaElement ||
element?.getAttribute("contenteditable") === "true";
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
@@ -21,6 +26,8 @@ const CameraShortcutsControls = () => {
const dir = new THREE.Vector3().subVectors(camera.position, target).normalize();
if (isTextInput(document.activeElement)) return;
switch (e.key) {
case "1": // Front
pos = new THREE.Vector3(0, 0, distance).add(target);

View File

@@ -4,7 +4,7 @@ import * as THREE from 'three';
import { PerspectiveCamera, OrthographicCamera, CameraControls } from '@react-three/drei';
import { useParams } from "react-router-dom";
import * as CONSTANTS from '../../../types/world/worldConstants';
import { getCamera } from "../../../services/factoryBuilder/camera/getCameraApi";
import { getCameraApi } from "../../../services/factoryBuilder/camera/getCameraApi";
import { getUserData } from "../../../functions/getUserData";
import { useToggleView } from "../../../store/builder/store";
@@ -20,7 +20,7 @@ export default function SwitchView() {
(controls as any).mouseButtons.right = CONSTANTS.twoDimension.rightMouse;
} else {
try {
getCamera(organization, localStorage.getItem('userId')!, projectId).then((data) => {
getCameraApi(organization, localStorage.getItem('userId')!, projectId).then((data) => {
if (data && data.position && data.target) {
(controls as CameraControls)?.setPosition(data.position.x, data.position.y, data.position.z);
(controls as CameraControls)?.setTarget(data.target.x, data.target.y, data.target.z);

View File

@@ -1,9 +1,10 @@
import { useEffect, useRef, useState } from "react";
import { useThree } from "@react-three/fiber";
import { CameraControls, Html, ScreenSpace } from "@react-three/drei";
import { useContextActionStore, useRenameModeStore, useSelectedAssets, useToggleView, useToolMode, } from "../../../../store/builder/store";
import { useContextActionStore, useRenameModeStore, useToggleView, useToolMode, } from "../../../../store/builder/store";
import ContextMenu from "../../../../components/ui/menu/contextMenu";
import useModuleStore from "../../../../store/useModuleStore";
import { useSceneContext } from "../../sceneContext";
function ContextControls() {
const { gl, controls } = useThree();
@@ -27,7 +28,8 @@ function ContextControls() {
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
const { toolMode } = useToolMode();
const { selectedAssets } = useSelectedAssets();
const { assetStore } = useSceneContext();
const { selectedAssets, movedObjects, rotatedObjects, duplicatedObjects, copiedObjects } = assetStore();
const { setContextAction } = useContextActionStore();
const { setIsRenameMode } = useRenameModeStore();
const rightDrag = useRef(false);
@@ -112,7 +114,10 @@ function ContextControls() {
if (rightDrag.current) return;
if (selectedAssets.length > 0) {
setMenuPosition({ x: event.clientX - gl.domElement.width / 2, y: event.clientY - gl.domElement.height / 2, });
setCanRender(true);
setTimeout(() => {
setCanRender(true);
}, 0)
if (controls) {
(controls as CameraControls).enabled = false;
}
@@ -124,7 +129,7 @@ function ContextControls() {
}
};
if (selectedAssets.length > 0 && !toggleView && activeModule === "builder" && toolMode === 'cursor') {
if (selectedAssets.length > 0 && !toggleView && activeModule === "builder" && toolMode === 'cursor' && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0 && copiedObjects.length === 0) {
canvasElement.addEventListener("pointerdown", onPointerDown);
canvasElement.addEventListener("pointermove", onPointerMove);
canvasElement.addEventListener("pointerup", onPointerUp);
@@ -143,7 +148,7 @@ function ContextControls() {
canvasElement.removeEventListener("pointerup", onPointerUp);
canvasElement.removeEventListener("contextmenu", handleContextClick);
};
}, [controls, gl, selectedAssets, toggleView, activeModule, toolMode]);
}, [controls, gl, selectedAssets, toggleView, activeModule, toolMode, duplicatedObjects, movedObjects, rotatedObjects, copiedObjects]);
const handleAssetRename = () => {
setCanRender(false);

View File

@@ -17,7 +17,8 @@ import CameraShortcutsControls from "../camera/shortcutsControls/cameraShortcuts
import { useParams } from "react-router-dom";
import { getUserData } from "../../../functions/getUserData";
import { getCamera } from "../../../services/factoryBuilder/camera/getCameraApi";
import { getCameraApi } from "../../../services/factoryBuilder/camera/getCameraApi";
import { setCameraApi } from "../../../services/factoryBuilder/camera/setCameraApi";
import updateCamPosition from "../camera/functions/updateCameraPosition";
export default function Controls() {
@@ -36,7 +37,7 @@ export default function Controls() {
(controlsRef.current as any).mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse;
}
getCamera(organization, userId, projectId).then((data) => {
getCameraApi(organization, userId, projectId).then((data) => {
if (data && data.position && data.target) {
controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z);
controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z);
@@ -48,21 +49,30 @@ export default function Controls() {
}, []);
useEffect(() => {
if (resetCamera) {
if (resetCamera && projectId) {
controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth);
const camData = {
organization,
userId: userId,
position: new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition),
target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
socketId: socket.id,
projectId
};
socket.emit('v1:Camera:set', camData)
if (!socket?.connected) {
setCameraApi(
projectId,
new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition),
new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
)
} else {
const camData = {
organization,
userId: userId,
position: new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition),
target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
socketId: socket.id,
projectId
};
socket.emit('v1:Camera:set', camData)
}
setResetCamera(false);
}
@@ -75,7 +85,7 @@ export default function Controls() {
let intervalId: NodeJS.Timeout | null = null;
const handleRest = () => {
if (hasInteracted && controlsRef.current && state.camera.position && !toggleView) {
if (hasInteracted && controlsRef.current && state.camera.position && !toggleView && socket) {
const position = state.camera.position;
if (position.x === 0 && position.y === 0 && position.z === 0) return;
updateCamPosition(controlsRef, socket, position, state.camera.rotation, projectId);
@@ -139,7 +149,7 @@ export default function Controls() {
<CamMode />
<CameraShortcutsControls/>
<CameraShortcutsControls />
</CameraControls>

View File

@@ -11,10 +11,11 @@ import { useSelectedPoints } from "../../../../../store/simulation/useSimulation
import useModuleStore from "../../../../../store/useModuleStore";
import { calculateAssetTransformationOnWall } from "../../../../builder/wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall";
// import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
// import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
// import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
// import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
import { upsertWallAssetApi } from "../../../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi";
function MoveControls2D({
movedObjects,
@@ -270,21 +271,24 @@ function MoveControls2D({
if (updatedAisles.length > 0 && projectId) {
updatedAisles.forEach((updatedAisle) => {
// API
if (!socket?.connected) {
// API
// upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
} else {
// SOCKET
// SOCKET
socket.emit('v1:model-aisle:add', {
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization,
aisleUuid: updatedAisle.aisleUuid,
points: updatedAisle.points,
type: updatedAisle.type
});
socket.emit('v1:model-aisle:add', {
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization,
aisleUuid: updatedAisle.aisleUuid,
points: updatedAisle.points,
type: updatedAisle.type
});
}
const old = initialStates[movedObject.uuid];
if (old) {
@@ -330,19 +334,22 @@ function MoveControls2D({
});
}
// API
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
} else {
// SOCKET
// SOCKET
socket.emit('v1:model-Wall:add', {
wallData: updatedWall,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
});
socket.emit('v1:model-Wall:add', {
wallData: updatedWall,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
});
}
const old = initialStates[movedObject.uuid];
if (old) {
@@ -371,19 +378,22 @@ function MoveControls2D({
if (updatedFloors?.length && projectId) {
updatedFloors.forEach(updatedFloor => {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
} else {
// SOCKET
// SOCKET
socket.emit('v1:model-Floor:add', {
floorData: updatedFloor,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
});
socket.emit('v1:model-Floor:add', {
floorData: updatedFloor,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
});
}
const updatedFloorsData = updatedFloors.map((floor) => {
const originalFloor = Floors.find(f => f.floorUuid === floor.floorUuid) || floor;
@@ -410,19 +420,22 @@ function MoveControls2D({
if (updatedZones?.length && projectId) {
updatedZones.forEach(updatedZone => {
// API
if (!socket?.connected) {
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
} else {
// SOCKET
// SOCKET
socket.emit('v1:zone:add', {
zoneData: updatedZone,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
});
socket.emit('v1:zone:add', {
zoneData: updatedZone,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
});
}
const updatedZonesData = updatedZones.map((zone) => {
const originalZone = Zones.find(z => z.zoneUuid === zone.zoneUuid) || zone;
@@ -459,21 +472,24 @@ function MoveControls2D({
rotation: updatedWallAsset.rotation
});
// API
if (!socket?.connected) {
// API
// upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
} else {
// SOCKET
// SOCKET
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:wall-asset:add', data);
}
socket.emit('v1:wall-asset:add', data);
}
});
}

View File

@@ -14,12 +14,13 @@ import { useSelectedPoints } from "../../../../../store/simulation/useSimulation
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
import MoveControls2D from "./moveControls2D";
// import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
// import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
// import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
// import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
// import { deleteZoneApi } from "../../../../../services/factoryBuilder/zone/deleteZoneApi";
// import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
import { deleteZoneApi } from "../../../../../services/factoryBuilder/zone/deleteZoneApi";
import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
import { deleteWallAssetApi } from "../../../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi";
const SelectionControls2D: React.FC = () => {
const { camera, controls, gl, scene, pointer } = useThree();
@@ -240,22 +241,25 @@ const SelectionControls2D: React.FC = () => {
if (removedAisles.length > 0) {
removedAisles.forEach(aisle => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');
deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');
} else {
// SOCKET
// SOCKET
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
aisleUuid: aisle.aisleUuid
}
socket.emit('v1:model-aisle:delete', data);
}
socket.emit('v1:model-aisle:delete', data);
}
});
@@ -280,43 +284,49 @@ const SelectionControls2D: React.FC = () => {
removeWallAsset(asset.modelUuid);
// API
if (!socket?.connected) {
// deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
// API
// SOCKET
deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
} else {
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
wallUuid: asset.wallUuid
// SOCKET
const data = {
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
wallUuid: asset.wallUuid
}
socket.emit('v1:wall-asset:delete', data);
}
socket.emit('v1:wall-asset:delete', data);
}
})
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:delete', data);
}
socket.emit('v1:model-Wall:delete', data);
}
});
@@ -335,22 +345,25 @@ const SelectionControls2D: React.FC = () => {
if (removedFloors.length > 0) {
removedFloors.forEach(floor => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
} else {
// SOCKET
// SOCKET
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:delete', data);
}
socket.emit('v1:model-Floor:delete', data);
}
});
@@ -365,22 +378,25 @@ const SelectionControls2D: React.FC = () => {
if (updatedFloors.length > 0) {
updatedFloors.forEach(floor => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: floor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
});
@@ -400,22 +416,25 @@ const SelectionControls2D: React.FC = () => {
if (removedZones.length > 0) {
removedZones.forEach(zone => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
} else {
// SOCKET
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:delete', data);
}
socket.emit('v1:zone:delete', data);
}
});
@@ -430,22 +449,25 @@ const SelectionControls2D: React.FC = () => {
if (updatedZones.length > 0) {
updatedZones.forEach(zone => {
if (projectId) {
if (!socket?.connected) {
// API
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: zone,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
}
});

View File

@@ -1,7 +1,7 @@
import { Line } from "@react-three/drei";
import { useMemo } from "react";
import * as THREE from "three";
import { useSelectedAssets } from "../../../../../store/builder/store";
import { useMemo } from "react";
import { Line } from "@react-three/drei";
import { useSceneContext } from "../../../sceneContext";
interface BoundingBoxProps {
boundingBoxRef?: any;
@@ -26,7 +26,8 @@ const getBoxLines = (min: THREE.Vector3, max: THREE.Vector3) => [
];
const BoundingBox = ({ boundingBoxRef, isPerAsset = true }: BoundingBoxProps) => {
const { selectedAssets } = useSelectedAssets();
const { assetStore } = useSceneContext();
const { selectedAssets } = assetStore();
const savedTheme: string = localStorage.getItem("theme") || "light";
const boxes = useMemo(() => {
@@ -88,9 +89,9 @@ const BoundingBox = ({ boundingBoxRef, isPerAsset = true }: BoundingBoxProps) =>
>
<Line
name="SelectionGroupBoundingBox"
depthWrite={false}
points={box.points}
color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"}
depthWrite={false}
lineWidth={2.7}
segments
position={[box.position[0], box.position[1], box.position[2]]}

View File

@@ -2,7 +2,7 @@ import * as THREE from "three";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { SkeletonUtils } from "three-stdlib";
import { useContextActionStore, useSelectedAssets, useSocketStore, useToggleView } from "../../../../../store/builder/store";
import { useContextActionStore, useSocketStore, useToggleView } from "../../../../../store/builder/store";
import * as Types from "../../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import { useParams } from "react-router-dom";
@@ -10,19 +10,18 @@ import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useVersionContext } from "../../../../builder/version/versionContext";
// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
const CopyPasteControls3D = () => {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
const { toggleView } = useToggleView();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { socket } = useSocketStore();
const { assetStore, eventStore, undoRedo3DStore } = useSceneContext();
const { push3D } = undoRedo3DStore();
const { addEvent } = eventStore();
const { projectId } = useParams();
const { assets, addAsset, updateAsset, removeAsset, getAssetById, copiedObjects, setCopiedObjects, pastedObjects, setPastedObjects, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore();
const { assets, addAsset, updateAsset, removeAsset, getAssetById, selectedAssets, setSelectedAssets, copiedObjects, setCopiedObjects, pastedObjects, setPastedObjects, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { userId, organization } = getUserData();
@@ -482,20 +481,34 @@ const CopyPasteControls3D = () => {
rotation: { x: pastedAsset.rotation.x, y: pastedAsset.rotation.y, z: pastedAsset.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id,
eventData: eventData,
versionId: selectedVersion?.versionId || '',
userId,
projectId
};
//REST
if (!socket?.connected) {
// REST
// await setAssetsApi(data);
setAssetsApi({
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: [position.x, 0, position.z],
rotation: { x: pastedAsset.rotation.x, y: pastedAsset.rotation.y, z: pastedAsset.rotation.z },
isLocked: false,
isVisible: true,
eventData: eventData,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
const asset: Asset = {
modelUuid: data.modelUuid,
@@ -521,13 +534,32 @@ const CopyPasteControls3D = () => {
rotation: { x: pastedAsset.rotation.x, y: pastedAsset.rotation.y, z: pastedAsset.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
};
socket.emit("v1:model-asset:add", data);
if (!socket?.connected) {
// REST
setAssetsApi({
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: [position.x, 0, position.z],
rotation: { x: pastedAsset.rotation.x, y: pastedAsset.rotation.y, z: pastedAsset.rotation.z },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", data);
}
const asset: Asset = {
modelUuid: data.modelUuid,

View File

@@ -2,7 +2,7 @@ import * as THREE from "three";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { SkeletonUtils } from "three-stdlib";
import { useContextActionStore, useSelectedAssets, useSocketStore, useToggleView } from "../../../../../store/builder/store";
import { useContextActionStore, useSocketStore, useToggleView } from "../../../../../store/builder/store";
import * as Types from "../../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import { useParams } from "react-router-dom";
@@ -11,19 +11,18 @@ import { useSceneContext } from "../../../sceneContext";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap";
// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
const DuplicationControls3D = () => {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
const { toggleView } = useToggleView();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { socket } = useSocketStore();
const { assetStore, eventStore, undoRedo3DStore } = useSceneContext();
const { push3D } = undoRedo3DStore();
const { addEvent } = eventStore();
const { projectId } = useParams();
const { assets, addAsset, updateAsset, removeAsset, getAssetById, duplicatedObjects, setDuplicatedObjects, setPastedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore();
const { assets, addAsset, updateAsset, removeAsset, getAssetById, selectedAssets, setSelectedAssets, duplicatedObjects, setDuplicatedObjects, setPastedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { userId, organization } = getUserData();
@@ -551,20 +550,35 @@ const DuplicationControls3D = () => {
rotation: { x: duplicatedAsset.rotation.x, y: duplicatedAsset.rotation.y, z: duplicatedAsset.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id,
eventData: eventData,
versionId: selectedVersion?.versionId || '',
userId,
projectId
};
//REST
console.log('socket: ', socket);
if (!socket?.connected) {
// REST
// await setAssetsApi(data);
setAssetsApi({
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: [position.x, position.y, position.z],
rotation: { x: duplicatedAsset.rotation.x, y: duplicatedAsset.rotation.y, z: duplicatedAsset.rotation.z },
isLocked: false,
isVisible: true,
eventData: eventData,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
const asset: Asset = {
modelUuid: data.modelUuid,
@@ -590,14 +604,32 @@ const DuplicationControls3D = () => {
rotation: { x: duplicatedAsset.rotation.x, y: duplicatedAsset.rotation.y, z: duplicatedAsset.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
};
socket.emit("v1:model-asset:add", data);
if (!socket?.connected) {
// REST
setAssetsApi({
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: [position.x, position.y, position.z],
rotation: { x: duplicatedAsset.rotation.x, y: duplicatedAsset.rotation.y, z: duplicatedAsset.rotation.z },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", data);
}
const asset: Asset = {
modelUuid: data.modelUuid,
modelName: data.modelName,

View File

@@ -1,7 +1,7 @@
import * as THREE from "three";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { useContextActionStore, useSelectedAssets, useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
import { useContextActionStore, useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
import * as Types from "../../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
@@ -14,7 +14,7 @@ import { useSceneContext } from "../../../sceneContext";
import { useVersionContext } from "../../../../builder/version/versionContext";
import useModuleStore from "../../../../../store/useModuleStore";
// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
function MoveControls3D({ boundingBoxRef }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
@@ -23,7 +23,6 @@ function MoveControls3D({ boundingBoxRef }: any) {
const { toggleView } = useToggleView();
const { toolMode } = useToolMode();
const { activeModule } = useModuleStore();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { socket } = useSocketStore();
@@ -31,7 +30,7 @@ function MoveControls3D({ boundingBoxRef }: any) {
const { projectId } = useParams();
const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext();
const { push3D } = undoRedo3DStore();
const { updateAsset, getAssetById, movedObjects, setMovedObjects, pastedObjects, setPastedObjects, duplicatedObjects, setDuplicatedObjects, rotatedObjects, setRotatedObjects } = assetStore();
const { updateAsset, getAssetById, selectedAssets, setSelectedAssets, movedObjects, setMovedObjects, pastedObjects, setPastedObjects, duplicatedObjects, setDuplicatedObjects, rotatedObjects, setRotatedObjects } = assetStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
@@ -421,19 +420,32 @@ function MoveControls3D({ boundingBoxRef }: any) {
rotation: { x: movedAsset.rotation.x, y: movedAsset.rotation.y, z: movedAsset.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
};
//REST
if (!socket?.connected) {
// REST
// await setAssetsApi(data);
setAssetsApi({
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: newFloorItem.position,
rotation: { x: movedAsset.rotation.x, y: movedAsset.rotation.y, z: movedAsset.rotation.z },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
}
});

View File

@@ -1,7 +1,7 @@
import * as THREE from "three";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { useContextActionStore, useSelectedAssets, useSocketStore, useToggleView, useToolMode } from "../../../../../store/builder/store";
import { useContextActionStore, useSocketStore, useToggleView, useToolMode } from "../../../../../store/builder/store";
import * as Types from "../../../../../types/world/worldTypes";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useParams } from "react-router-dom";
@@ -13,7 +13,7 @@ import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModi
import { handleAssetRotationSnap } from "./functions/handleAssetRotationSnap";
import useModuleStore from "../../../../../store/useModuleStore";
// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
function RotateControls3D() {
const { camera, gl, scene, pointer, raycaster } = useThree();
@@ -21,7 +21,6 @@ function RotateControls3D() {
const { toggleView } = useToggleView();
const { toolMode } = useToolMode();
const { activeModule } = useModuleStore();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { socket } = useSocketStore();
@@ -29,7 +28,7 @@ function RotateControls3D() {
const { projectId } = useParams();
const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext();
const { push3D } = undoRedo3DStore();
const { updateAsset, rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, pastedObjects, setPastedObjects, duplicatedObjects, setDuplicatedObjects } = assetStore();
const { updateAsset, rotatedObjects, setRotatedObjects, selectedAssets, setSelectedAssets, movedObjects, setMovedObjects, pastedObjects, setPastedObjects, duplicatedObjects, setDuplicatedObjects } = assetStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
@@ -365,19 +364,32 @@ function RotateControls3D() {
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
};
//REST
if (!socket?.connected) {
// REST
// await setAssetsApi(data);
setAssetsApi({
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: newFloorItem.position,
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
}
});

View File

@@ -10,28 +10,29 @@ import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { useProductContext } from "../../../../simulation/products/productContext";
import { useContextActionStore, useSelectedAssets, useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
import { useContextActionStore, useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
import DuplicationControls3D from "./duplicationControls3D";
import CopyPasteControls3D from "./copyPasteControls3D";
import MoveControls3D from "./moveControls3D";
import RotateControls3D from "./rotateControls3D";
import TransformControls3D from "./transformControls3D";
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
// import { deleteFloorItem } from '../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
import { deleteFloorItem } from '../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
const SelectionControls3D: React.FC = () => {
const { camera, controls, gl, scene, raycaster, pointer } = useThree();
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
const { toolMode } = useToolMode();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const boundingBoxRef = useRef<THREE.Mesh>();
const { socket } = useSocketStore();
const { contextAction, setContextAction } = useContextActionStore()
const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext();
const { selectedDecal, selectedWall, selectedAisle, selectedFloor, selectedFloorAsset, selectedWallAsset } = useBuilderStore();
const { push3D } = undoRedo3DStore();
const { removeAsset, getAssetById, movedObjects, rotatedObjects, copiedObjects, pastedObjects, duplicatedObjects, setPastedObjects, setDuplicatedObjects } = assetStore();
const { removeAsset, getAssetById, selectedAssets, setSelectedAssets, movedObjects, rotatedObjects, copiedObjects, pastedObjects, duplicatedObjects, setPastedObjects, setDuplicatedObjects } = assetStore();
const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
@@ -203,7 +204,7 @@ const SelectionControls3D: React.FC = () => {
rightClickMoved.current = false;
};
if (!toggleView && activeModule === "builder" && (toolMode === 'cursor' || toolMode === 'Move-Asset' || toolMode === 'Rotate-Asset')) {
if (!toggleView && activeModule === "builder" && (toolMode === 'cursor' || toolMode === 'Move-Asset' || toolMode === 'Rotate-Asset') && (!selectedDecal && !selectedWall && !selectedAisle && !selectedFloor && !selectedFloorAsset && !selectedWallAsset) && duplicatedObjects.length === 0 && pastedObjects.length === 0) {
helper.enabled = true;
canvasElement.addEventListener("pointermove", onPointerMove);
canvasElement.addEventListener("pointerup", onPointerUp);
@@ -225,7 +226,7 @@ const SelectionControls3D: React.FC = () => {
helper.dispose();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, rotatedObjects, activeModule, toolMode]);
}, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, rotatedObjects, activeModule, toolMode, selectedDecal, selectedWall, selectedAisle, selectedFloor, selectedFloorAsset, selectedWallAsset]);
useEffect(() => {
if (activeModule !== "builder" || (toolMode !== 'cursor' && toolMode !== 'Move-Asset' && toolMode !== 'Rotate-Asset') || toggleView) {
@@ -283,23 +284,28 @@ const SelectionControls3D: React.FC = () => {
const asset = getAssetById(selectedMesh.userData.modelUuid);
if (!asset) return;
//REST
// const response = deleteFloorItem(organization, selectedMesh.userData.modelUuid, selectedMesh.userData.modelName);
if (!socket?.connected) {
//SOCKET
// REST
const data = {
organization,
modelUuid: selectedMesh.userData.modelUuid,
modelName: selectedMesh.userData.modelName,
socketId: socket.id,
projectId,
versionId: selectedVersion?.versionId || '',
userId
};
deleteFloorItem(organization, selectedMesh.userData.modelUuid, selectedMesh.userData.modelName);
} else {
const response = socket.emit("v1:model-asset:delete", data);
// SOCKET
const data = {
organization,
modelUuid: selectedMesh.userData.modelUuid,
modelName: selectedMesh.userData.modelName,
socketId: socket.id,
projectId,
versionId: selectedVersion?.versionId || '',
userId
};
socket.emit("v1:model-asset:delete", data);
}
eventStore.getState().removeEvent(selectedMesh.uuid);
const updatedEvents = productStore.getState().deleteEvent(selectedMesh.uuid);
@@ -313,12 +319,9 @@ const SelectionControls3D: React.FC = () => {
);
})
if (response) {
removeAsset(selectedMesh.uuid);
removeAsset(selectedMesh.uuid);
echo.success("Model Removed!");
}
echo.success("Model Removed!");
selectedMesh.traverse((child: THREE.Object3D) => {
if (child instanceof THREE.Mesh) {

View File

@@ -2,7 +2,7 @@ import * as THREE from 'three';
import { useRef, useEffect, useState, useCallback } from 'react';
import { useThree } from '@react-three/fiber';
import { TransformControls } from '@react-three/drei';
import { useSelectedAssets, useSocketStore, useToolMode } from '../../../../../store/builder/store';
import { useSocketStore, useToolMode } from '../../../../../store/builder/store';
import { useProductContext } from '../../../../simulation/products/productContext';
import { useVersionContext } from '../../../../builder/version/versionContext';
import { useSceneContext } from '../../../sceneContext';
@@ -11,10 +11,9 @@ import { useParams } from 'react-router-dom';
import { getUserData } from '../../../../../functions/getUserData';
import { upsertProductOrEventApi } from '../../../../../services/simulation/products/UpsertProductOrEventApi';
import { detectModifierKeys } from '../../../../../utils/shortcutkeys/detectModifierKeys';
// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
function TransformControls3D() {
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const { toolMode } = useToolMode();
const { camera, scene, gl } = useThree();
const transformControlsRef = useRef<any>(null);
@@ -25,7 +24,7 @@ function TransformControls3D() {
const { selectedProduct } = selectedProductStore();
const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext();
const { push3D, subscribeUndoRedo } = undoRedo3DStore();
const { updateAsset, getAssetById } = assetStore();
const { updateAsset, getAssetById, selectedAssets, setSelectedAssets } = assetStore();
const { userId, organization } = getUserData();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
@@ -136,37 +135,42 @@ function TransformControls3D() {
}
}
//REST
// setAssetsApi(
// organization,
// asset.modelUuid,
// asset.modelName,
// [obj.position.x, 0, obj.position.z],
// { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
// asset.assetId,
// false,
// true,
// );
if (!socket?.connected) {
// API
//SOCKET
setAssetsApi({
modelUuid: asset.modelUuid,
modelName: asset.modelName,
assetId: asset.assetId,
position: [obj.position.x, obj.position.y, obj.position.z],
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
const data = {
organization,
modelUuid: asset.modelUuid,
modelName: asset.modelName,
assetId: asset.assetId,
position: [obj.position.x, obj.position.y, obj.position.z],
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
versionId: selectedVersion?.versionId || '',
userId,
projectId
};
// SOCKET
socket.emit("v1:model-asset:add", data);
const data = {
organization,
modelUuid: asset.modelUuid,
modelName: asset.modelName,
assetId: asset.assetId,
position: [obj.position.x, obj.position.y, obj.position.z],
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
versionId: selectedVersion?.versionId || '',
userId,
projectId
};
socket.emit("v1:model-asset:add", data);
}
});
}, [selectedAssets, setSelectedAssets, getAssetById, updateAsset, eventStore, productStore, selectedProduct, updateBackend, projectId, organization, socket, selectedVersion, userId, push3D]);

View File

@@ -7,17 +7,18 @@ import { useProductContext } from "../../../simulation/products/productContext";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../sceneContext";
import { useVersionContext } from "../../../builder/version/versionContext";
import { useSelectedFloorItem, useObjectPosition, useObjectRotation, useActiveTool, useSocketStore } from "../../../../store/builder/store";
import { useObjectPosition, useObjectRotation, useActiveTool, useSocketStore } from "../../../../store/builder/store";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
// import { setAssetsApi } from "../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { setAssetsApi } from "../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
export default function TransformControl() {
const state = useThree();
const ref = useRef(null);
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { setObjectPosition } = useObjectPosition();
const { setObjectRotation } = useObjectRotation();
const { activeTool } = useActiveTool();
@@ -48,26 +49,27 @@ export default function TransformControl() {
};
function handleObjectChange() {
if (selectedFloorItem) {
setObjectPosition(selectedFloorItem.position);
if (selectedFloorAsset) {
setObjectPosition(selectedFloorAsset.position);
setObjectRotation({
x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x),
y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y),
z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z),
x: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.x),
y: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.y),
z: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.z),
});
}
}
function handleMouseUp() {
if (selectedFloorItem) {
setObjectPosition(selectedFloorItem.position);
if (!selectedProduct || !selectedFloorAsset) return;
if (selectedFloorAsset) {
setObjectPosition(selectedFloorAsset.position);
setObjectRotation({
x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x),
y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y),
z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z),
x: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.x),
y: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.y),
z: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.z),
});
}
const asset = getAssetById(selectedFloorItem?.uuid);
const asset = getAssetById(selectedFloorAsset.uuid);
if (asset) {
if (asset.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(asset.modelUuid);
@@ -75,8 +77,8 @@ export default function TransformControl() {
if (eventData) {
eventStore.getState().updateEvent(asset.modelUuid, {
position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z] as [number, number, number],
rotation: [selectedFloorItem.rotation.x, selectedFloorItem.rotation.y, selectedFloorItem.rotation.z] as [number, number, number],
position: [selectedFloorAsset.position.x, 0, selectedFloorAsset.position.z] as [number, number, number],
rotation: [selectedFloorAsset.rotation.x, selectedFloorAsset.rotation.y, selectedFloorAsset.rotation.z] as [number, number, number],
});
}
@@ -87,8 +89,8 @@ export default function TransformControl() {
selectedProduct.productUuid,
asset.modelUuid,
{
position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z] as [number, number, number],
rotation: [selectedFloorItem.rotation.x, selectedFloorItem.rotation.y, selectedFloorItem.rotation.z] as [number, number, number],
position: [selectedFloorAsset.position.x, 0, selectedFloorAsset.position.z] as [number, number, number],
rotation: [selectedFloorAsset.rotation.x, selectedFloorAsset.rotation.y, selectedFloorAsset.rotation.z] as [number, number, number],
}
);
@@ -104,41 +106,46 @@ export default function TransformControl() {
}
updateAsset(asset.modelUuid, {
position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z],
rotation: [selectedFloorItem.rotation.x, selectedFloorItem.rotation.y, selectedFloorItem.rotation.z] as [number, number, number],
position: [selectedFloorAsset.position.x, 0, selectedFloorAsset.position.z],
rotation: [selectedFloorAsset.rotation.x, selectedFloorAsset.rotation.y, selectedFloorAsset.rotation.z] as [number, number, number],
});
//REST
if (!socket?.connected) {
// await setAssetsApi(
// organization,
// asset.modelUuid,
// asset.modelName,
// [selectedFloorItem.position.x, 0, selectedFloorItem.position.z,
// { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z },
// asset.assetId,
// false,
// true,
// );
// API
//SOCKET
setAssetsApi({
modelUuid: asset.modelUuid,
modelName: asset.modelName,
assetId: asset.assetId,
position: [selectedFloorAsset.position.x, 0, selectedFloorAsset.position.z] as [number, number, number],
rotation: { x: selectedFloorAsset.rotation.x, y: selectedFloorAsset.rotation.y, z: selectedFloorAsset.rotation.z },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
const data = {
organization,
modelUuid: asset.modelUuid,
modelName: asset.modelName,
assetId: asset.assetId,
position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z] as [number, number, number],
rotation: { x: selectedFloorItem.rotation.x, y: selectedFloorItem.rotation.y, z: selectedFloorItem.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
versionId: selectedVersion?.versionId || '',
userId,
projectId
};
// SOCKET
socket.emit("v1:model-asset:add", data);
const data = {
organization,
modelUuid: asset.modelUuid,
modelName: asset.modelName,
assetId: asset.assetId,
position: [selectedFloorAsset.position.x, 0, selectedFloorAsset.position.z] as [number, number, number],
rotation: { x: selectedFloorAsset.rotation.x, y: selectedFloorAsset.rotation.y, z: selectedFloorAsset.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
versionId: selectedVersion?.versionId || '',
userId,
projectId
};
socket.emit("v1:model-asset:add", data);
}
push3D({
type: 'Scene',
@@ -151,8 +158,8 @@ export default function TransformControl() {
assetData: asset,
newData: {
...asset,
position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z],
rotation: [selectedFloorItem.rotation.x, selectedFloorItem.rotation.y, selectedFloorItem.rotation.z],
position: [selectedFloorAsset.position.x, 0, selectedFloorAsset.position.z],
rotation: [selectedFloorAsset.rotation.x, selectedFloorAsset.rotation.y, selectedFloorAsset.rotation.z],
},
timeStap: new Date().toISOString()
}
@@ -170,7 +177,7 @@ export default function TransformControl() {
element?.getAttribute("contenteditable") === "true";
if (isTextInput(document.activeElement)) return;
const keyCombination = detectModifierKeys(e);
if (!selectedFloorItem) return;
if (!selectedFloorAsset) return;
if (keyCombination === "G") {
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
}
@@ -179,13 +186,13 @@ export default function TransformControl() {
}
};
if (selectedFloorItem) {
if (selectedFloorAsset) {
window.addEventListener("keydown", handleKeyDown);
setObjectPosition(selectedFloorItem.position);
setObjectPosition(selectedFloorAsset.position);
setObjectRotation({
x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x),
y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y),
z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z),
x: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.x),
y: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.y),
z: THREE.MathUtils.radToDeg(selectedFloorAsset.rotation.z),
});
} else {
setTransformMode(null);
@@ -194,7 +201,7 @@ export default function TransformControl() {
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [selectedFloorItem]);
}, [selectedFloorAsset, setObjectPosition, setObjectRotation]);
useEffect(() => {
if (activeTool === "delete") {
@@ -202,21 +209,21 @@ export default function TransformControl() {
const target = (state.controls as any).getTarget(new THREE.Vector3());
(state.controls as any).setTarget(target.x, 0, target.z, true);
}
setSelectedFloorItem(null);
setSelectedFloorAsset(null);
setObjectPosition({ x: undefined, y: undefined, z: undefined });
setObjectRotation({ x: undefined, y: undefined, z: undefined });
}
}, [activeTool]);
}, [activeTool, setObjectPosition, setObjectRotation, setSelectedFloorAsset, state.controls]);
return (
<>
{(selectedFloorItem && transformMode) &&
{(selectedFloorAsset && transformMode) &&
<TransformControls
ref={ref}
showX={transformMode === "translate"}
showY={transformMode === "rotate" || transformMode === "translate"}
showZ={transformMode === "translate"}
object={selectedFloorItem}
object={selectedFloorAsset}
mode={transformMode}
onObjectChange={handleObjectChange}
onMouseUp={handleMouseUp}

View File

@@ -4,17 +4,17 @@ import { useVersionContext } from "../../../../builder/version/versionContext";
import { useSceneContext } from "../../../sceneContext";
import { useSocketStore } from "../../../../../store/builder/store";
// import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
// import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
// import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
// import { deleteZoneApi } from "../../../../../services/factoryBuilder/zone/deleteZoneApi";
import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
import { deleteZoneApi } from "../../../../../services/factoryBuilder/zone/deleteZoneApi";
// import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
// import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
// import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
// import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
function use2DRedoHandler() {
const { undoRedo2DStore, wallStore, floorStore, zoneStore, aisleStore } = useSceneContext();
@@ -100,252 +100,288 @@ function use2DRedoHandler() {
const createWallFromBackend = (wallData: Wall) => {
addWall(wallData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', wallData);
upsertWallApi(projectId, selectedVersion?.versionId || '', wallData);
} else {
// SOCKET
// SOCKET
const data = {
wallData: wallData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: wallData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
};
const removeWallFromBackend = (wallUuid: string) => {
removeWall(wallUuid);
if (projectId) {
// API
if (!socket?.connected) {
// API
// deleteWallApi(projectId, selectedVersion?.versionId || '', wallUuid);
deleteWallApi(projectId, selectedVersion?.versionId || '', wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
wallUuid: wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallUuid: wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:delete', data);
}
socket.emit('v1:model-Wall:delete', data);
}
};
const updateWallFromBackend = (wallUuid: string, updatedData: Wall) => {
updateWall(wallUuid, updatedData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData);
} else {
// SOCKET
// SOCKET
const data = {
wallData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
};
const createFloorFromBackend = (floorData: Floor) => {
addFloor(floorData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floorData);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floorData);
} else {
// SOCKET
// SOCKET
const data = {
floorData: floorData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: floorData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
};
const removeFloorFromBackend = (floorUuid: string) => {
removeFloor(floorUuid);
if (projectId) {
// API
if (!socket?.connected) {
// API
// deleteFloorApi(projectId, selectedVersion?.versionId || '', floorUuid);
deleteFloorApi(projectId, selectedVersion?.versionId || '', floorUuid);
} else {
// SOCKET
// SOCKET
const data = {
floorUuid: floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorUuid: floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:delete', data);
}
socket.emit('v1:model-Floor:delete', data);
}
};
const updateFloorFromBackend = (floorUuid: string, updatedData: Floor) => {
updateFloor(floorUuid, updatedData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
};
const createZoneFromBackend = (zoneData: Zone) => {
addZone(zoneData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zoneData);
upsertZoneApi(projectId, selectedVersion?.versionId || '', zoneData);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: zoneData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: zoneData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
}
};
const removeZoneFromBackend = (zoneUuid: string) => {
removeZone(zoneUuid);
if (projectId) {
// API
if (!socket?.connected) {
// API
// deleteZoneApi(projectId, selectedVersion?.versionId || '', zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || '', zoneUuid);
} else {
// SOCKET
// SOCKET
const data = {
zoneUuid,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
zoneUuid,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:zone:delete', data);
socket.emit('v1:zone:delete', data);
}
}
};
const updateZoneFromBackend = (zoneUuid: string, updatedData: Zone) => {
updateZone(zoneUuid, updatedData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedData);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: updatedData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
zoneData: updatedData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:zone:add', data);
socket.emit('v1:zone:add', data);
}
}
};
const createAisleFromBackend = (aisleData: Aisle) => {
addAisle(aisleData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertAisleApi(projectId, selectedVersion?.versionId || '', aisleData);
upsertAisleApi(aisleData.aisleUuid, aisleData.points, aisleData.type, projectId, selectedVersion?.versionId || '');
} else {
// SOCKET
// SOCKET
const data = {
...aisleData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
...aisleData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:model-aisle:add', data);
socket.emit('v1:model-aisle:add', data);
}
}
};
const removeAisleFromBackend = (aisleUuid: string) => {
removeAisle(aisleUuid);
if (projectId) {
// API
if (!socket?.connected) {
// API
// deleteAisleApi(projectId, selectedVersion?.versionId || '', aisleUuid);
deleteAisleApi(projectId, selectedVersion?.versionId || '', aisleUuid);
} else {
// SOCKET
// SOCKET
const data = {
aisleUuid,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
aisleUuid,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:model-aisle:delete', data);
socket.emit('v1:model-aisle:delete', data);
}
}
};
const updateAisleFromBackend = (aisleUuid: string, updatedData: Aisle) => {
updateAisle(aisleUuid, updatedData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertAisleApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertAisleApi(updatedData.aisleUuid, updatedData.points, updatedData.type, projectId, selectedVersion?.versionId || '');
} else {
// SOCKET
// SOCKET
const data = {
...updatedData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
...updatedData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:model-aisle:add', data);
socket.emit('v1:model-aisle:add', data);
}
}
};

View File

@@ -4,17 +4,17 @@ import { useVersionContext } from "../../../../builder/version/versionContext";
import { useSceneContext } from "../../../sceneContext";
import { useSocketStore } from "../../../../../store/builder/store";
// import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
// import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
// import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
// import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
import { deleteZoneApi } from "../../../../../services/factoryBuilder/zone/deleteZoneApi";
// import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
// import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
// import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
// import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
function use2DUndoHandler() {
const { undoRedo2DStore, wallStore, floorStore, zoneStore, aisleStore } = useSceneContext();
@@ -100,252 +100,288 @@ function use2DUndoHandler() {
const createWallToBackend = (wallData: Wall) => {
addWall(wallData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', wallData);
upsertWallApi(projectId, selectedVersion?.versionId || '', wallData);
} else {
// SOCKET
// SOCKET
const data = {
wallData: wallData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: wallData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
};
const removeWallToBackend = (wallUuid: string) => {
removeWall(wallUuid);
if (projectId) {
// API
if (!socket?.connected) {
// API
// deleteWallApi(projectId, selectedVersion?.versionId || '', wallUuid);
deleteWallApi(projectId, selectedVersion?.versionId || '', wallUuid);
} else {
// SOCKET
// SOCKET
const data = {
wallUuid: wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallUuid: wallUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:delete', data);
}
socket.emit('v1:model-Wall:delete', data);
}
};
const updateWallToBackend = (wallUuid: string, updatedData: Wall) => {
updateWall(wallUuid, updatedData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData);
} else {
// SOCKET
// SOCKET
const data = {
wallData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
wallData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
socket.emit('v1:model-Wall:add', data);
}
};
const createFloorToBackend = (floorData: Floor) => {
addFloor(floorData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floorData);
upsertFloorApi(projectId, selectedVersion?.versionId || '', floorData);
} else {
// SOCKET
// SOCKET
const data = {
floorData: floorData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: floorData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
};
const removeFloorToBackend = (floorUuid: string) => {
removeFloor(floorUuid);
if (projectId) {
// API
if (!socket?.connected) {
// API
// deleteFloorApi(projectId, selectedVersion?.versionId || '', floorUuid);
deleteFloorApi(projectId, selectedVersion?.versionId || '', floorUuid);
} else {
// SOCKET
// SOCKET
const data = {
floorUuid: floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorUuid: floorUuid,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:delete', data);
}
socket.emit('v1:model-Floor:delete', data);
}
};
const updateFloorToBackend = (floorUuid: string, updatedData: Floor) => {
updateFloor(floorUuid, updatedData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData);
} else {
// SOCKET
// SOCKET
const data = {
floorData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
floorData: updatedData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
socket.emit('v1:model-Floor:add', data);
}
};
const createZoneToBackend = (zoneData: Zone) => {
addZone(zoneData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zoneData);
upsertZoneApi(projectId, selectedVersion?.versionId || '', zoneData);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: zoneData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
const data = {
zoneData: zoneData,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:zone:add', data);
}
socket.emit('v1:zone:add', data);
}
};
const removeZoneToBackend = (zoneUuid: string) => {
removeZone(zoneUuid);
if (projectId) {
// API
if (!socket?.connected) {
// API
// deleteZoneApi(projectId, selectedVersion?.versionId || '', zoneUuid);
deleteZoneApi(projectId, selectedVersion?.versionId || '', zoneUuid);
} else {
// SOCKET
// SOCKET
const data = {
zoneUuid,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
zoneUuid,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:zone:delete', data);
socket.emit('v1:zone:delete', data);
}
}
};
const updateZoneToBackend = (zoneUuid: string, updatedData: Zone) => {
updateZone(zoneUuid, updatedData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedData);
} else {
// SOCKET
// SOCKET
const data = {
zoneData: updatedData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
zoneData: updatedData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:zone:add', data);
socket.emit('v1:zone:add', data);
}
}
};
const createAisleToBackend = (aisleData: Aisle) => {
addAisle(aisleData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertAisleApi(projectId, selectedVersion?.versionId || '', aisleData);
upsertAisleApi(aisleData.aisleUuid, aisleData.points, aisleData.type, projectId, selectedVersion?.versionId || '');
} else {
// SOCKET
// SOCKET
const data = {
...aisleData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
...aisleData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:model-aisle:add', data);
socket.emit('v1:model-aisle:add', data);
}
}
};
const removeAisleToBackend = (aisleUuid: string) => {
removeAisle(aisleUuid);
if (projectId) {
// API
if (!socket?.connected) {
// API
// deleteAisleApi(projectId, selectedVersion?.versionId || '', aisleUuid);
deleteAisleApi(projectId, selectedVersion?.versionId || '', aisleUuid);
} else {
// SOCKET
// SOCKET
const data = {
aisleUuid,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
aisleUuid,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:model-aisle:delete', data);
socket.emit('v1:model-aisle:delete', data);
}
}
};
const updateAisleToBackend = (aisleUuid: string, updatedData: Aisle) => {
updateAisle(aisleUuid, updatedData);
if (projectId) {
// API
if (!socket?.connected) {
// API
// upsertAisleApi(projectId, selectedVersion?.versionId || '', updatedData);
upsertAisleApi(updatedData.aisleUuid, updatedData.points, updatedData.type, projectId, selectedVersion?.versionId || '');
} else {
// SOCKET
// SOCKET
const data = {
...updatedData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
const data = {
...updatedData,
projectId,
versionId: selectedVersion?.versionId || '',
userId,
organization
};
socket.emit('v1:model-aisle:add', data);
socket.emit('v1:model-aisle:add', data);
}
}
};

View File

@@ -7,8 +7,8 @@ import { useSocketStore } from "../../../../../store/builder/store";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
// import { deleteFloorItem } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi";
import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { deleteFloorItem } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi";
function use3DRedoHandler() {
const { undoRedo3DStore, assetStore, productStore, eventStore } = useSceneContext();
@@ -138,7 +138,7 @@ function use3DRedoHandler() {
isLocked: false,
isVisible: true,
eventData: {},
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
@@ -149,35 +149,52 @@ function use3DRedoHandler() {
addEvent(assetData.eventData as EventsSchema);
}
// API
if (!socket?.connected) {
// REST
// setAssetsApi(data);
setAssetsApi({
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
assetId: assetData.assetId,
position: assetData.position,
rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
isLocked: false,
isVisible: true,
eventData: data.eventData,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
}
}
const deleteAssetToBackend = (assetData: Asset) => {
//REST
if (!socket?.connected) {
// REST
// const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
} else {
//SOCKET
// SOCKET
const data = {
organization,
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
const data = {
organization,
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
socket.emit('v1:model-asset:delete', data)
}
const response = socket.emit('v1:model-asset:delete', data)
removeEvent(assetData.modelUuid);
const updatedEvents = deleteEvent(assetData.modelUuid);
@@ -190,10 +207,7 @@ function use3DRedoHandler() {
);
})
if (response) {
removeAsset(assetData.modelUuid);
}
removeAsset(assetData.modelUuid);
}
const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => {
@@ -208,19 +222,32 @@ function use3DRedoHandler() {
rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
};
// API
if (!socket?.connected) {
// REST
// setAssetsApi(data);
setAssetsApi({
modelUuid: updatedData.modelUuid,
modelName: updatedData.modelName,
assetId: updatedData.assetId,
position: updatedData.position,
rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
}
}
@@ -237,7 +264,7 @@ function use3DRedoHandler() {
isLocked: false,
isVisible: true,
eventData: {},
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
@@ -248,13 +275,27 @@ function use3DRedoHandler() {
addEvent(assetData.eventData as EventsSchema);
}
// API
if (!socket?.connected) {
// REST
// setAssetsApi(data);
setAssetsApi({
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
assetId: assetData.assetId,
position: assetData.position,
rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
isLocked: false,
isVisible: true,
eventData: data.eventData,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
}
}
@@ -271,7 +312,7 @@ function use3DRedoHandler() {
isLocked: false,
isVisible: true,
eventData: {},
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
@@ -282,13 +323,27 @@ function use3DRedoHandler() {
addEvent(assetData.eventData as EventsSchema);
}
// API
if (!socket?.connected) {
//REST
// setAssetsApi(data);
setAssetsApi({
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
assetId: assetData.assetId,
position: assetData.position,
rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
isLocked: false,
isVisible: true,
eventData: data.eventData,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
//SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
}
}

View File

@@ -7,8 +7,8 @@ import { useSocketStore } from "../../../../../store/builder/store";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
// import { deleteFloorItem } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi";
import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { deleteFloorItem } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi";
function use3DUndoHandler() {
const { undoRedo3DStore, assetStore, productStore, eventStore } = useSceneContext();
@@ -137,7 +137,7 @@ function use3DUndoHandler() {
isLocked: false,
isVisible: true,
eventData: {},
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
@@ -148,35 +148,52 @@ function use3DUndoHandler() {
addEvent(assetData.eventData as EventsSchema);
}
// API
if (!socket?.connected) {
// REST
// setAssetsApi(data);
setAssetsApi({
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
assetId: assetData.assetId,
position: assetData.position,
rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
isLocked: false,
isVisible: true,
eventData: data.eventData,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
}
}
const deleteAssetToBackend = (assetData: Asset) => {
//REST
if (!socket?.connected) {
// REST
// const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
} else {
//SOCKET
// SOCKET
const data = {
organization,
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
const data = {
organization,
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
socket.emit('v1:model-asset:delete', data)
}
const response = socket.emit('v1:model-asset:delete', data)
removeEvent(assetData.modelUuid);
const updatedEvents = deleteEvent(assetData.modelUuid);
@@ -189,10 +206,7 @@ function use3DUndoHandler() {
);
})
if (response) {
removeAsset(assetData.modelUuid);
}
removeAsset(assetData.modelUuid);
}
const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => {
@@ -207,41 +221,57 @@ function use3DUndoHandler() {
rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
isLocked: false,
isVisible: true,
socketId: socket.id,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
projectId,
userId
};
// API
if (!socket?.connected) {
// REST
// setAssetsApi(data);
setAssetsApi({
modelUuid: updatedData.modelUuid,
modelName: updatedData.modelName,
assetId: updatedData.assetId,
position: updatedData.position,
rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
projectId: projectId,
});
} else {
//SOCKET
// SOCKET
socket.emit("v1:model-asset:add", data);
socket.emit("v1:model-asset:add", data);
}
}
}
const copyAssetToBackend = (assetData: Asset) => {
//REST
if (!socket?.connected) {
// REST
// const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
} else {
//SOCKET
// SOCKET
const data = {
organization,
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
const data = {
organization,
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
socket.emit('v1:model-asset:delete', data)
}
const response = socket.emit('v1:model-asset:delete', data)
removeEvent(assetData.modelUuid);
const updatedEvents = deleteEvent(assetData.modelUuid);
@@ -254,31 +284,31 @@ function use3DUndoHandler() {
);
})
if (response) {
removeAsset(assetData.modelUuid);
}
removeAsset(assetData.modelUuid);
}
const duplicateAssetToBackend = (assetData: Asset) => {
//REST
if (!socket?.connected) {
// REST
// const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
} else {
//SOCKET
// SOCKET
const data = {
organization,
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
const data = {
organization,
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
socket.emit('v1:model-asset:delete', data)
}
const response = socket.emit('v1:model-asset:delete', data)
removeEvent(assetData.modelUuid);
const updatedEvents = deleteEvent(assetData.modelUuid);
@@ -291,10 +321,7 @@ function use3DUndoHandler() {
);
})
if (response) {
removeAsset(assetData.modelUuid);
}
removeAsset(assetData.modelUuid);
}
const addWallAssetToBackend = (assetData: WallAsset) => {

View File

@@ -0,0 +1,41 @@
import { Outline } from "@react-three/postprocessing";
import { BlendFunction } from "postprocessing";
import { Object3D } from "three";
type OutlineInstanceProps = {
selection?: Object3D | Object3D[] | null;
color: number;
xRay?: boolean;
width?: number;
edgeStrength?: number;
};
function OutlineInstance({
selection,
color,
xRay = true,
width = 2000,
edgeStrength = 5,
}: OutlineInstanceProps) {
if (!selection) return null;
const sel = Array.isArray(selection) ? selection : [selection];
return (
<Outline
selection={sel}
selectionLayer={10}
width={width}
blendFunction={BlendFunction.ALPHA}
edgeStrength={edgeStrength}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={color}
hiddenEdgeColor={color}
blur
xRay={xRay}
/>
);
}
export default OutlineInstance

View File

@@ -0,0 +1,88 @@
import { Object3D } from "three";
import { useDeletableEventSphere, useSelectedEventSphere } from "../../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import * as CONSTANTS from "../../../../types/world/worldConstants";
import OutlineInstance from "./outlineInstance/outlineInstance";
function flattenChildren(children: Object3D[]): Object3D[] {
return children.flatMap((child) => [child, ...flattenChildren(child.children)]);
}
function OutlineInstances() {
const { selectedEventSphere } = useSelectedEventSphere();
const { deletableEventSphere } = useDeletableEventSphere();
const { selectedAisle, selectedWall, selectedDecal, selectedFloor, selectedWallAsset, deletableWallAsset, selectedFloorAsset, deletableFloorAsset, deletableDecal } = useBuilderStore();
return (
<>
<OutlineInstance
key="selectedWallAsset"
selection={selectedWallAsset && flattenChildren(selectedWallAsset.children)}
color={CONSTANTS.outlineConfig.assetSelectColor}
/>
<OutlineInstance
key="selectedFloorAsset"
selection={selectedFloorAsset && flattenChildren(selectedFloorAsset.children)}
color={CONSTANTS.outlineConfig.assetSelectColor}
/>
<OutlineInstance
key="deletableWallAsset"
selection={deletableWallAsset && flattenChildren(deletableWallAsset.children)}
color={CONSTANTS.outlineConfig.assetDeleteColor}
/>
<OutlineInstance
key="deletableFloorAsset"
selection={deletableFloorAsset && flattenChildren(deletableFloorAsset.children)}
color={CONSTANTS.outlineConfig.assetDeleteColor}
/>
{/* Aisle / Wall / Floor */}
<OutlineInstance
key="selectedAisle"
selection={selectedAisle?.aisleMesh && flattenChildren(selectedAisle.aisleMesh.children)}
color={CONSTANTS.outlineConfig.assetSelectColor}
/>
<OutlineInstance
key="selectedWall"
selection={selectedWall ? [selectedWall] : null}
color={CONSTANTS.outlineConfig.assetSelectColor}
/>
<OutlineInstance
key="selectedFloor"
selection={selectedFloor ? [selectedFloor] : null}
color={CONSTANTS.outlineConfig.assetSelectColor}
/>
{/* Decals */}
<OutlineInstance
key="selectedDecal"
selection={selectedDecal?.decalMesh ? [selectedDecal.decalMesh] : null}
color={CONSTANTS.outlineConfig.assetSelectColor}
/>
<OutlineInstance
key="deletableDecal"
selection={deletableDecal ? [deletableDecal] : null}
color={CONSTANTS.outlineConfig.assetDeleteColor}
width={3000}
/>
{/* Event Spheres */}
<OutlineInstance
key="selectedEventSphere"
selection={selectedEventSphere ? [selectedEventSphere] : null}
color={0x6f42c1}
edgeStrength={10}
width={1000}
/>
<OutlineInstance
key="deletableEventSphere"
selection={deletableEventSphere ? [deletableEventSphere] : null}
color={CONSTANTS.outlineConfig.assetDeleteColor}
edgeStrength={10}
width={1000}
/>
</>
)
}
export default OutlineInstances;

View File

@@ -1,273 +1,27 @@
import { EffectComposer, N8AO } from "@react-three/postprocessing";
import OutlineInstances from "./outlineInstances/outlineInstances";
import { useDeletableEventSphere, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
import { useEffect } from "react";
import { BlendFunction } from "postprocessing";
import { DepthOfField, Bloom, EffectComposer, N8AO, Outline } from "@react-three/postprocessing";
import { useDeletableFloorItem, useSelectedWallItem, useSelectedFloorItem, } from "../../../store/builder/store";
import { useDeletableEventSphere, useSelectedEventSphere, useSelectedPoints } from "../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import * as CONSTANTS from "../../../types/world/worldConstants";
export default function PostProcessing() {
const { selectedPoints } = useSelectedPoints();
const { deletableFloorItem } = useDeletableFloorItem();
const { selectedWallItem } = useSelectedWallItem();
const { selectedFloorItem } = useSelectedFloorItem();
const { selectedEventSphere } = useSelectedEventSphere();
const { deletableEventSphere } = useDeletableEventSphere();
const { selectedAisle, selectedWall, selectedDecal, selectedFloor, selectedWallAsset, deletableWallAsset, deletableDecal } = useBuilderStore();
function flattenChildren(children: any[]) {
const allChildren: any[] = [];
children.forEach((child) => {
allChildren.push(child);
if (child.children && child.children.length > 0) {
allChildren.push(...flattenChildren(child.children));
}
});
return allChildren;
}
useEffect(() => {
// console.log('selectedFloorItem: ', selectedFloorItem);
}, [selectedFloorItem])
useEffect(() => {
// console.log('selectedFloorItem: ', deletableFloorItem);
}, [deletableFloorItem])
useEffect(() => {
// console.log('selectedAisle: ', selectedAisle);
}, [selectedAisle])
useEffect(() => {
// console.log('selectedWall: ', selectedWall);
}, [selectedWall])
useEffect(() => {
// console.log('selectedFloor: ', selectedFloor);
}, [selectedFloor])
useEffect(() => {
// console.log('selectedWallAsset: ', selectedWallAsset);
}, [selectedWallAsset])
useEffect(() => {
// console.log('deletableWallAsset: ', deletableWallAsset);
}, [deletableWallAsset])
useEffect(() => {
// console.log('deletableEventSphere: ', deletableEventSphere);
}, [deletableEventSphere])
useEffect(() => {
// console.log('selectedPoints: ', selectedPoints);
}, [selectedPoints])
useEffect(() => {
// console.log('deletableDecal: ', deletableDecal);
}, [deletableDecal])
}, [selectedEventSphere, deletableEventSphere])
return (
<EffectComposer autoClear={false}>
<N8AO
color="black"
aoRadius={20}
intensity={7}
distanceFalloff={4}
aoSamples={32}
denoiseRadius={6}
denoiseSamples={16}
/>
{/* <DepthOfField
focusDistance={0}
focalLength={0.15}
bokehScale={2}
/> */}
{/* <Bloom
intensity={0.1}
luminanceThreshold={0.9}
luminanceSmoothing={0.025}
mipmapBlur={false}
/> */}
{selectedWallAsset && (
<Outline
selection={flattenChildren(selectedWallAsset.children)}
selectionLayer={10}
width={2000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={true}
/>
)}
{deletableWallAsset && (
<Outline
selection={flattenChildren(deletableWallAsset.children)}
selectionLayer={10}
width={2000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
blur={true}
xRay={true}
/>
)}
{selectedAisle && (
<Outline
selection={flattenChildren(selectedAisle.aisleMesh?.children || [])}
selectionLayer={10}
width={2000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={false}
/>
)}
{selectedWall && (
<Outline
selection={selectedWall}
selectionLayer={10}
width={2000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={true}
/>
)}
{selectedFloor && (
<Outline
selection={selectedFloor}
selectionLayer={10}
width={2000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={true}
/>
)}
{selectedDecal && (
<Outline
selection={selectedDecal.decalMesh || undefined}
selectionLayer={10}
width={2000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={true}
/>
)}
{deletableDecal && (
<Outline
selection={deletableDecal}
selectionLayer={10}
width={3000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
blur={true}
xRay={true}
/>
)}
{deletableFloorItem && (
<Outline
selection={flattenChildren(deletableFloorItem.children)}
selectionLayer={10}
width={3000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
blur={true}
xRay={true}
/>
)}
{selectedWallItem && (
<Outline
selection={flattenChildren(selectedWallItem.children)}
selectionLayer={10}
width={3000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={true}
/>
)}
{selectedFloorItem && (
<Outline
selection={flattenChildren(selectedFloorItem.children)}
selectionLayer={10}
width={3000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={true}
/>
)}
{selectedEventSphere && (
<Outline
selection={[selectedEventSphere]}
selectionLayer={10}
width={1000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={10}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={0x6f42c1}
hiddenEdgeColor={0x6f42c1}
blur={true}
xRay={true}
/>
)}
{deletableEventSphere && (
<Outline
selection={[deletableEventSphere]}
selectionLayer={10}
width={1000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={10}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
blur={true}
xRay={true}
/>
)}
<N8AO color="black" aoRadius={20} intensity={7} distanceFalloff={4} aoSamples={32} denoiseRadius={6} denoiseSamples={16} />
{/* <DepthOfField focusDistance={0} focalLength={0.15} bokehScale={2} /> */}
{/* <Bloom intensity={0.1} luminanceThreshold={0.9} luminanceSmoothing={0.025} mipmapBlur={false} /> */}
<OutlineInstances />
</EffectComposer>
);
}
};

View File

@@ -34,11 +34,11 @@ export default function Scene({ layout }: { readonly layout: "Main Layout" | "Co
useEffect(() => {
if (!projectId || loadingProgress !== 0) return;
getAllProjects(userId, organization).then((projects) => {
if (!projects || !projects.Projects) return;
if (!projects.Projects) return;
let project = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId);
const canvas = document.getElementById("sceneCanvas")?.getElementsByTagName("canvas")[0];
if (!canvas) return;
compressImage((canvas as HTMLCanvasElement)?.toDataURL("image/png")).then((screenshotDataUrl) => {
compressImage(canvas.toDataURL("image/png")).then((screenshotDataUrl) => {
const updateProjects = {
projectId: project?._id,
organization,

View File

@@ -116,7 +116,7 @@ function MachineInstance({ machineDetail }: { readonly machineDetail: MachineSta
function handleCallBack() {
if (currentPhase == "processing") {
setMachineState(machineDetail.modelUuid, 'idle');
setMachineActive(machineDetail.modelUuid, true);
setMachineActive(machineDetail.modelUuid, false);
setCurrentPhase("idle")
isIncrememtable.current = true;
machineStatus(machineDetail.modelUuid, "Machine has completed the processing")

View File

@@ -206,47 +206,17 @@ export function useTriggerHandler() {
} else if (model?.type === 'machine') {
const armBot = getArmBotById(trigger.triggeredAsset?.triggeredModel.modelUuid);
if (armBot) {
if (armBot.isActive === false && armBot.state === 'idle') {
const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
setIsPaused(materialId, true);
addArmBotToMonitor(armBot.modelUuid, () => {
const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (machine) {
if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) {
setIsPaused(materialId, true);
setIsPaused(materialId, true);
addMachineToMonitor(machine.modelUuid, () => {
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addMachineToMonitor(machine.modelUuid,
() => {
handleAction(action, materialId);
}
)
}
})
}
} else {
setIsPaused(materialId, true);
addArmBotToMonitor(armBot.modelUuid, () => {
const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (machine) {
if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) {
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addMachineToMonitor(machine.modelUuid,
() => {
handleAction(action, materialId);
}
)
}
}
}
);
}
});
}
} else {
if (armBot.isActive === false && armBot.state === 'idle') {

View File

@@ -1,7 +1,5 @@
import React, { useEffect, useState } from "react";
import {
useSocketStore
} from "../store/builder/store";
import { useSocketStore } from "../store/builder/store";
import DashboardHome from "../components/Dashboard/DashboardHome";
import DashboardProjects from "../components/Dashboard/DashboardProjects";
import DashboardTrash from "../components/Dashboard/DashboardTrash";
@@ -10,29 +8,27 @@ import SidePannel from "../components/Dashboard/SidePannel";
import DashboardTutorial from "../components/Dashboard/DashboardTutorial";
const Dashboard: React.FC = () => {
const [activeTab, setActiveTab] = useState<string>("Home");
const { socket } = useSocketStore();
const { organization, email } = getUserData();
const [activeTab, setActiveTab] = useState<string>("Home");
const { socket } = useSocketStore();
const { organization, email } = getUserData();
useEffect(() => {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken")
if (token) {
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
} else {
useEffect(() => {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken")
if (token && refreshToken) {
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
}
}, [socket, email, organization]);
}
}, [socket]);
return (
<div className="dashboard-main">
<SidePannel setActiveTab={setActiveTab} activeTab={activeTab} />
{activeTab == "Home" && <DashboardHome />}
{activeTab == "Projects" && <DashboardProjects />}
{activeTab == "Trash" && <DashboardTrash />}
{activeTab == "Tutorials" && <DashboardTutorial />}
</div>
);
return (
<div className="dashboard-main">
<SidePannel setActiveTab={setActiveTab} activeTab={activeTab} />
{activeTab === "Home" && <DashboardHome />}
{activeTab === "Projects" && <DashboardProjects />}
{activeTab === "Trash" && <DashboardTrash />}
{activeTab === "Tutorials" && <DashboardTutorial />}
</div>
);
};
export default Dashboard;

View File

@@ -0,0 +1,57 @@
import { useLocation, useNavigate } from "react-router-dom";
import text404 from "../assets/image/404/404.svg";
import hero from "../assets/image/404/404_bk.png";
const PageNotFound = () => {
const savedTheme = localStorage.getItem("theme");
const isLogedIn = localStorage.getItem("userId");
const navigate = useNavigate();
const { hash } = useLocation();
function getErrorContext() {
const contexts = hash.split("#");
const context = contexts[1];
const info = contexts.length > 1 ? contexts[2] : "";
switch (context) {
case "project_not_found":
return `Project Not found - The project ${
info !== "" && `with ID (${info})`
} was not found.`;
default:
return "Page not Found - looks like we have hit a roadblock";
}
}
return (
<div className="page-not-found-wrapper">
<div className="page-not-found-container">
<div className="text-404">
<img
src={text404}
alt=""
style={savedTheme === "dark" ? { filter: "invert(1)" } : {}}
/>
</div>
<div className="hero-container">
<img src={hero} alt="" />
</div>
<div className="context">{getErrorContext()}</div>
<button
className="back-to-home"
id="go-back-home-404-btn"
onClick={() => {
if (isLogedIn) {
navigate("/Dashboard");
} else {
navigate("/");
}
}}
>
Go Back to Home
</button>
</div>
</div>
);
};
export default PageNotFound;

View File

@@ -2,8 +2,6 @@ import React, { useEffect } from "react";
import useModuleStore from "../store/useModuleStore";
import {
useSocketStore,
useOrganization,
useUserName,
useProjectName,
useActiveTool,
} from "../store/builder/store";
@@ -29,8 +27,6 @@ const Project: React.FC = () => {
let navigate = useNavigate();
const echo = useLogger();
const { setActiveModule } = useModuleStore();
const { setUserName } = useUserName();
const { setOrganization } = useOrganization();
const { projectId } = useParams();
const { setProjectName } = useProjectName();
const { userId, email, organization, userName } = getUserData();
@@ -42,6 +38,7 @@ const Project: React.FC = () => {
useEffect(() => {
if (!email || !userId) {
console.error("User data not found in localStorage");
navigate("/page-not-found");
return;
}
@@ -60,6 +57,7 @@ const Project: React.FC = () => {
await viewProject(organization, matchedProject._id, userId);
} else {
console.warn("Project not found with given ID:", projectId);
navigate(`/not_found#project_not_found#${projectId}`);
}
} catch (error) {
console.error("Error fetching projects:", error);
@@ -72,6 +70,7 @@ const Project: React.FC = () => {
useEffect(() => {
if (!projectId) return;
getVersionHistoryApi(projectId)
.then((data) => {
const versions: VersionHistory = [];
@@ -98,16 +97,13 @@ const Project: React.FC = () => {
if (email) {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken");
if (token) {
echo.warn('Validating token');
if (token && refreshToken) {
useSocketStore
.getState()
.initializeSocket(email, organization, token, refreshToken);
}
if (organization && userName) {
setOrganization(organization);
setUserName(userName);
}
echo.success("Log in successful");
echo.success("Project initialized and loaded successfully");
} else {
navigate("/");
}

View File

@@ -4,8 +4,6 @@ import { LogoIconLarge } from "../components/icons/Logo";
import { EyeIcon } from "../components/icons/ExportCommonIcons";
import {
useLoadingProgress,
useOrganization,
useUserName,
} from "../store/builder/store";
import { signInApi } from "../services/factoryBuilder/signInSignUp/signInApi";
import { signUpApi } from "../services/factoryBuilder/signInSignUp/signUpApi";
@@ -19,8 +17,8 @@ const UserAuth: React.FC = () => {
const [showPassword, setShowPassword] = useState(false);
const [error, setError] = useState("");
const [isSignIn, setIsSignIn] = useState(true);
const { userName, setUserName } = useUserName();
const { setOrganization } = useOrganization();
const { userName } = getUserData();
const [name, setName] = useState<string>(userName || '');
const { setLoadingProgress } = useLoadingProgress();
const [fingerprint, setFingerprint] = useState("");
@@ -36,8 +34,6 @@ const UserAuth: React.FC = () => {
initializeFingerprint();
}, []);
const { userId, organization } = getUserData();
const handleLogin = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const organization = email.split("@")[1].split(".")[0];
@@ -45,8 +41,6 @@ const UserAuth: React.FC = () => {
const res = await signInApi(email, password, organization, fingerprint);
if (res.message.message === "login successfull") {
setError("");
setOrganization(organization);
setUserName(res.message.name);
localStorage.setItem("userId", res.message.userId);
localStorage.setItem("email", res.message.email);
localStorage.setItem("userName", res.message.name);
@@ -115,11 +109,11 @@ const UserAuth: React.FC = () => {
const handleRegister = async (e: FormEvent) => {
e.preventDefault();
if (email && password && userName) {
if (email && password && name) {
setError("");
try {
const organization = email.split("@")[1].split(".")[0];
const res = await signUpApi(userName, email, password, organization);
const res = await signUpApi(name, email, password, organization);
if (res.message === "New User created") {
setIsSignIn(true);
@@ -180,9 +174,9 @@ const UserAuth: React.FC = () => {
{!isSignIn && (
<input
type="text"
value={userName}
value={name}
placeholder="Username"
onChange={(e) => setUserName(e.target.value)}
onChange={(e) => setName(e.target.value)}
required
/>
)}

View File

@@ -0,0 +1,33 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
export const getAssetThumbnail = async (assetId: String) => {
try {
const response = await fetch(
`${url_Backend_dwinzo}/api/v2/getAssetThumbnail/${assetId}`,
{
method: "GET",
headers: {
Authorization: "Bearer <access_token>",
"Content-Type": "application/json",
token: localStorage.getItem("token") || "",
refresh_token: localStorage.getItem("refreshToken") || "",
},
}
);
const newAccessToken = response.headers.get("x-access-token");
if (newAccessToken) {
localStorage.setItem("token", newAccessToken);
}
if (!response.ok) {
throw new Error("Failed to fetch assets");
}
//
return await response.json();
} catch (error: any) {
echo.error("Failed to get asset image");
}
};

View File

@@ -1,6 +1,6 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const getCamera = async (organization: string, userId: string, projectId?: string) => {
export const getCameraApi = async (organization: string, userId: string, projectId?: string) => {
try {
const response = await fetch(
`${url_Backend_dwinzo}/api/V1/cameras/${projectId}`,

View File

@@ -1,47 +1,44 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const setCamera = async (
organization: string,
userId: string,
position: Object,
target: Object,
rotation: Object
export const setCameraApi = async (
projectId: string,
position: Object,
target: Object,
rotation: Object
) => {
try {
const response = await fetch(`${url_Backend_dwinzo}/api/v1/setCamera`, {
method: "POST",
headers: {
Authorization: "Bearer <access_token>",
"Content-Type": "application/json",
token: localStorage.getItem("token") || "",
refresh_token: localStorage.getItem("refreshToken") || "",
},
body: JSON.stringify({
organization,
userId,
position,
target,
rotation,
}),
});
const newAccessToken = response.headers.get("x-access-token");
if (newAccessToken) {
//console.log("New token received:", newAccessToken);
localStorage.setItem("token", newAccessToken);
}
try {
const response = await fetch(`${url_Backend_dwinzo}/api/V1/builder/setCamera`, {
method: "POST",
headers: {
Authorization: "Bearer <access_token>",
"Content-Type": "application/json",
token: localStorage.getItem("token") || "",
refresh_token: localStorage.getItem("refreshToken") || "",
},
body: JSON.stringify({
projectId,
position,
target,
rotation,
}),
});
const newAccessToken = response.headers.get("x-access-token");
if (newAccessToken) {
localStorage.setItem("token", newAccessToken);
}
if (!response.ok) {
console.error("Failed to set Camera Position and Target");
}
if (!response.ok) {
console.error("Failed to set Camera Position and Target");
}
const result = await response.json();
return result;
} catch (error) {
echo.error("Failed to set camera");
if (error instanceof Error) {
console.log(error.message);
} else {
console.log("An unknown error occurred");
const result = await response.json();
return result;
} catch (error) {
echo.error("Failed to set camera");
if (error instanceof Error) {
console.log(error.message);
} else {
console.log("An unknown error occurred");
}
}
}
};

View File

@@ -25,6 +25,7 @@ export const renameProductApi = async (body: {
if (!response.ok) {
console.error("Failed to rename product");
echo.error("Failed to rename product");
}
const result = await response.json();
@@ -32,11 +33,11 @@ export const renameProductApi = async (body: {
return result;
} catch (error) {
echo.error("Failed to rename product Api");
if (error instanceof Error) {
console.log(error.message);
} else {
console.log("An unknown error occurred");
echo.log("An unknown error occurred");
}
}
};

View File

@@ -1,10 +1,28 @@
import { Object3D } from "three";
import { create } from "zustand";
import { io } from "socket.io-client";
import * as CONSTANTS from "../../types/world/worldConstants";
export const useSocketStore = create<any>((set: any, get: any) => ({
type SocketStore = {
socket: ReturnType<typeof io> | null;
visualizationSocket?: ReturnType<typeof io> | null;
dashBoardSocket?: ReturnType<typeof io> | null;
projectSocket?: ReturnType<typeof io> | null;
threadSocket?: ReturnType<typeof io> | null;
initializeSocket: (
email?: string,
organization?: string,
token?: string,
refreshToken?: string
) => void;
disconnectSocket: () => void;
};
export const useSocketStore = create<SocketStore>((set, get) => ({
socket: null,
visualizationSocket: null,
dashBoardSocket: null,
projectSocket: null,
threadSocket: null,
initializeSocket: (
email?: string,
organization?: string,
@@ -63,71 +81,22 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
});
},
disconnectSocket: () => {
set((state: any) => {
set((state) => {
state.socket?.disconnect();
state.visualizationSocket?.disconnect();
state.dashBoardSocket?.disconnect();
state.projectSocket?.disconnect();
state.threadSocket?.disconnect();
return { socket: null };
return {
socket: null,
visualizationSocket: null,
dashBoardSocket: null,
projectSocket: null,
threadSocket: null,
};
});
},
}));
// export const useSocketStore = create<any>((set: any, get: any) => ({
// socket: null,
// initializeSocket: (
// email: string,
// organization: string,
// userId?: string,
// token?: string
// ) => {
// const existingSocket = get().socket;
// if (existingSocket) {
// return;
// }
// const socket = io(
// `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`,
// {
// reconnection: true,
// auth: { email, organization },
// }
// );
// const visualizationSocket = io(
// `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization`,
// {
// reconnection: true,
// auth: { email, organization },
// }
// );
// const dashBoardSocket = io(
// `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
// {
// reconnection: true,
// auth: { token },
// }
// );
// // const dashBoardSocket = io(
// // `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`,
// // {
// // reconnection: true,
// // auth: { token },
// // }
// // );
// set({ socket, visualizationSocket, dashBoardSocket });
// },
// disconnectSocket: () => {
// set((state: any) => {
// state.socket?.disconnect();
// state.visualizationSocket?.disconnect();
// state.dashBoardSocket?.disconnect();
// return { socket: null };
// });
// },
// }));
export const useLoadingProgress = create<{
loadingProgress: number;
@@ -137,11 +106,6 @@ export const useLoadingProgress = create<{
setLoadingProgress: (x: number) => set({ loadingProgress: x }),
}));
export const useOrganization = create<any>((set: any) => ({
organization: "",
setOrganization: (x: any) => set(() => ({ organization: x })),
}));
export const useToggleView = create<any>((set: any) => ({
toggleView: false,
setToggleView: (x: any) => set(() => ({ toggleView: x })),
@@ -163,76 +127,16 @@ export const useSelectedItem = create<any>((set: any) => ({
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
}));
type DroppedDecalType = {
category: string;
decalName: string;
decalImage: string;
decalId: string;
};
export const useDroppedDecal = create<{
droppedDecal: DroppedDecalType | null;
setDroppedDecal: (x: DroppedDecalType | null) => void;
}>((set) => ({
droppedDecal: null,
setDroppedDecal: (x) => set({ droppedDecal: x }),
}));
export const useNavMesh = create<any>((set: any) => ({
navMesh: null,
setNavMesh: (x: any) => set({ navMesh: x }),
}));
type SelectedAssetsState = {
selectedAssets: Object3D[];
setSelectedAssets: (assets: Object3D[]) => void;
};
export const useSelectedAssets = create<SelectedAssetsState>((set) => ({
selectedAssets: [],
setSelectedAssets: (assets) => set({ selectedAssets: assets }),
}));
export const useLayers = create<any>((set: any) => ({
Layers: 1,
setLayers: (x: any) => set(() => ({ Layers: x })),
}));
export const useCamPosition = create<any>((set: any) => ({
camPosition: { x: undefined, y: undefined, z: undefined },
setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
}));
export const useMenuVisible = create<any>((set: any) => ({
menuVisible: false,
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
}));
export const useToolMode = create<any>((set: any) => ({
toolMode: null,
setToolMode: (x: any) => set(() => ({ toolMode: x })),
}));
export const useSelectedWallItem = create<any>((set: any) => ({
selectedWallItem: null,
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
}));
export const useSelectedFloorItem = create<any>((set: any) => ({
selectedFloorItem: null,
setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
}));
export const useDeletableFloorItem = create<any>((set: any) => ({
deletableFloorItem: null,
setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })),
}));
export const useSetScale = create<any>((set: any) => ({
scale: null,
setScale: (x: any) => set(() => ({ scale: x })),
}));
export const useRoofVisibility = create<any>((set: any) => ({
roofVisibility: false,
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
@@ -254,16 +158,6 @@ export const useSunPosition = create<any>((set: any) => ({
set({ sunPosition: newSuntPosition }),
}));
export const useRemoveLayer = create<any>((set: any) => ({
removeLayer: false,
setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
}));
export const useRemovedLayer = create<any>((set: any) => ({
removedLayer: null,
setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
}));
export const useProjectName = create<any>((set: any) => ({
projectName: "Creating Your Project",
setProjectName: (x: any) => set({ projectName: x }),
@@ -314,11 +208,6 @@ export const useCamMode = create<any>((set: any) => ({
setCamMode: (x: any) => set({ camMode: x }),
}));
export const useUserName = create<any>((set: any) => ({
userName: "",
setUserName: (x: any) => set({ userName: x }),
}));
export const useRenameModeStore = create<any>((set: any) => ({
isRenameMode: false,
setIsRenameMode: (state: boolean) => set({ isRenameMode: state }),
@@ -426,12 +315,6 @@ export const useTileDistance = create<any>((set: any) => ({
})),
}));
export const usePlayAgv = create<any>((set, get) => ({
PlayAgv: [],
setPlayAgv: (updateFn: (prev: any[]) => any[]) =>
set({ PlayAgv: updateFn(get().PlayAgv) }),
}));
// Define the Asset type
type Asset = {
id: string;
@@ -492,14 +375,17 @@ export const useMachineCount = create<any>((set: any) => ({
machineCount: 0,
setMachineCount: (x: any) => set({ machineCount: x }),
}));
export const useMachineUptime = create<any>((set: any) => ({
machineActiveTime: 0,
setMachineActiveTime: (x: any) => set({ machineActiveTime: x }),
}));
export const useMachineDowntime = create<any>((set: any) => ({
machineIdleTime: 0,
setMachineIdleTime: (x: any) => set({ machineIdleTime: x }),
}));
export const useMaterialCycle = create<any>((set: any) => ({
materialCycleTime: 0,
setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }),
@@ -509,6 +395,7 @@ export const useThroughPutData = create<any>((set: any) => ({
throughputData: 0,
setThroughputData: (x: any) => set({ throughputData: x }),
}));
export const useProductionCapacityData = create<any>((set: any) => ({
productionCapacityData: 0,
setProductionCapacityData: (x: any) => set({ productionCapacityData: x }),
@@ -518,6 +405,7 @@ export const useProcessBar = create<any>((set: any) => ({
processBar: [],
setProcessBar: (x: any) => set({ processBar: x }),
}));
export const useDfxUpload = create<any>((set: any) => ({
dfxuploaded: [],
dfxWallGenerate: [],
@@ -622,6 +510,7 @@ function getInitialViewSceneLabels(): boolean {
const saved = localStorage.getItem("viewSceneLabels");
return saved ? JSON.parse(saved) : false;
}
export interface CompareProduct {
productUuid: string;
productName: string;
@@ -660,6 +549,7 @@ export const useSelectedComment = create<any>((set: any) => ({
commentPositionState: null,
setCommentPositionState: (x: any) => set({ commentPositionState: x }),
}));
export const useSelectedPath = create<any>((set: any) => ({
selectedPath: "auto",
setSelectedPath: (x: any) => set({ selectedPath: x }),
@@ -668,17 +558,4 @@ export const useSelectedPath = create<any>((set: any) => ({
export const useContextActionStore = create<any>((set: any) => ({
contextAction: null,
setContextAction: (x: any) => set({ contextAction: x }),
}));
// Define the store's state and actions type
interface DecalStore {
selectedSubCategory: string | null;
setSelectedSubCategory: (subCategory: string | null) => void;
}
// Create the Zustand store with types
export const useDecalStore = create<DecalStore>((set) => ({
selectedSubCategory: 'Safety',
setSelectedSubCategory: (subCategory: string | null) => set({ selectedSubCategory: subCategory }),
}));
}));

View File

@@ -4,6 +4,7 @@ import { immer } from 'zustand/middleware/immer';
interface AssetsStore {
assets: Assets;
selectedAssets: Object3D[];
movedObjects: Object3D[];
rotatedObjects: Object3D[];
copiedObjects: Object3D[];
@@ -18,6 +19,7 @@ interface AssetsStore {
resetAsset: (modelUuid: string) => void;
setAssets: (assets: Assets) => void;
setSelectedAssets: (objects: Object3D[]) => void;
setMovedObjects: (objects: Object3D[]) => Object3D[];
setRotatedObjects: (objects: Object3D[]) => Object3D[];
setCopiedObjects: (objects: Object3D[]) => Object3D[];
@@ -56,6 +58,7 @@ export const createAssetStore = () => {
return create<AssetsStore>()(
immer((set, get) => ({
assets: [],
selectedAssets: [],
movedObjects: [],
rotatedObjects: [],
copiedObjects: [],
@@ -111,6 +114,12 @@ export const createAssetStore = () => {
});
},
setSelectedAssets: (objects) => {
set((state) => {
state.selectedAssets = objects;
});
},
setMovedObjects: (objects) => {
set((state) => {
state.movedObjects = objects;

View File

@@ -15,6 +15,7 @@ interface BuilderState {
// Floor Asset
selectedFloorAsset: Object3D | null;
deletableFloorAsset: Object3D | null;
loopAnimation: boolean;
// Wall Settings
@@ -45,9 +46,16 @@ interface BuilderState {
draggingDecalUuid: string | null,
dragOffset: Vector3 | null,
},
selectedDecalCategory: string | null,
droppedDecal: {
category: string;
decalName: string;
decalImage: string;
decalId: string;
} | null,
// Aisle General
selectedAisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null;
selectedAisle: { aisleMesh: Object3D | null, aisleData: Aisle } | null;
aisleType: AisleTypes;
aisleWidth: number;
aisleColor: AisleColors;
@@ -71,6 +79,7 @@ interface BuilderState {
// Setters - Floor Asset
setSelectedFloorAsset: (asset: Object3D | null) => void;
setDeletableFloorAsset: (asset: Object3D | null) => void;
setLoopAnimation: (loop: boolean) => void;
// Setters - Wall
@@ -95,9 +104,11 @@ interface BuilderState {
setSelectedDecal: (decal: { decalMesh: Object3D | null, decalData: Decal } | null) => void;
setDeletableDecal: (decal: Object3D | null) => void;
setDecalDragState: (isDragging: boolean, draggingDecalUuid: string | null, dragOffset: Vector3 | null) => void;
setSelectedDecalCategory: (subCategory: string | null) => void,
setDroppedDecal: (droppedDecal: { category: string, decalName: string, decalImage: string, decalId: string } | null) => void,
// Setters - Aisle General
setSelectedAisle: (aisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null) => void;
setSelectedAisle: (aisle: { aisleMesh: Object3D | null, aisleData: Aisle } | null) => void;
setAisleType: (type: AisleTypes) => void;
setAisleWidth: (width: number) => void;
setAisleColor: (color: AisleColors) => void;
@@ -128,6 +139,7 @@ export const useBuilderStore = create<BuilderState>()(
deletableWallAsset: null,
selectedFloorAsset: null,
deletableFloorAsset: null,
loopAnimation: true,
selectedWall: null,
@@ -154,6 +166,8 @@ export const useBuilderStore = create<BuilderState>()(
draggingDecalUuid: null,
dragOffset: null,
},
selectedDecalCategory: 'Safety',
droppedDecal: null,
selectedAisle: null,
aisleType: 'solid-aisle',
@@ -214,6 +228,12 @@ export const useBuilderStore = create<BuilderState>()(
});
},
setDeletableFloorAsset(asset: Object3D | null) {
set((state) => {
state.deletableFloorAsset = asset;
});
},
setLoopAnimation(loopAnimation: boolean) {
set((state) => {
state.loopAnimation = loopAnimation;
@@ -323,9 +343,21 @@ export const useBuilderStore = create<BuilderState>()(
})
},
setSelectedDecalCategory: (subCategory: string | null) => {
set((state) => {
state.selectedDecalCategory = subCategory;
})
},
setDroppedDecal: (droppedDecal: { category: string, decalName: string, decalImage: string, decalId: string } | null) => {
set((state) => {
state.droppedDecal = droppedDecal;
})
},
// === Setters: Aisle General ===
setSelectedAisle: (aisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null) => {
setSelectedAisle: (aisle: { aisleMesh: Object3D | null, aisleData: Aisle } | null) => {
set((state) => {
state.selectedAisle = aisle;
});

Some files were not shown because too many files have changed in this diff Show More