Merge remote-tracking branch 'origin/main' into v2-ui
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 472 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 850 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
@@ -230,7 +230,7 @@ const Assets: React.FC = () => {
|
||||
(asset) => asset.category === category
|
||||
);
|
||||
return (
|
||||
<button
|
||||
<div
|
||||
key={`${index}-${category}`}
|
||||
className="category"
|
||||
id={category}
|
||||
@@ -243,7 +243,7 @@ const Assets: React.FC = () => {
|
||||
draggable={false}
|
||||
/>
|
||||
<div className="category-name">{category}</div>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import orgImg from "../../../assets/orgTemp.png";
|
||||
import orgImg from "../../../assets/image/orgTemp.png";
|
||||
import { useActiveUsers, useCamMode } from "../../../store/store";
|
||||
import { ActiveUser } from "../../../types/users";
|
||||
import CollaborationPopup from "../../templates/CollaborationPopup";
|
||||
|
||||
@@ -38,450 +38,360 @@ import {
|
||||
useFloatingWidget,
|
||||
} from "../../store/visualization/useDroppedObjectsStore";
|
||||
|
||||
const Tools: React.FC = () => {
|
||||
const { templates } = useTemplateStore();
|
||||
const { activeSubTool, setActiveSubTool } = useActiveSubTool();
|
||||
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
|
||||
const { setToggleUI } = useToggleStore();
|
||||
// Utility component
|
||||
const ToolButton = ({ icon: Icon, active, onClick, tooltip }: any) => (
|
||||
<button className={`tool-button ${active ? "active" : ""}`} onClick={onClick}>
|
||||
<div className="tooltip">{tooltip}</div>
|
||||
<Icon isActive={active} />
|
||||
</button>
|
||||
);
|
||||
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const [openDrop, setOpenDrop] = useState(false);
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
const Tools: React.FC = () => {
|
||||
const { activeModule } = useModuleStore();
|
||||
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
|
||||
const { isPlaying, setIsPlaying } = usePlayButtonStore();
|
||||
const { addTemplate } = useTemplateStore();
|
||||
|
||||
const {
|
||||
activeTool,
|
||||
setActiveTool,
|
||||
setToolMode,
|
||||
setAddAction,
|
||||
setDeleteTool,
|
||||
setDeletePointOrLine,
|
||||
setTransformMode,
|
||||
} = useStoreHooks();
|
||||
|
||||
const { setActiveSubTool, activeSubTool } = useActiveSubTool();
|
||||
const { setSelectedWallItem } = useSelectedWallItem();
|
||||
const { setRefTextUpdate } = useRefTextUpdate();
|
||||
const { setToggleUI } = useToggleStore();
|
||||
const { setToggleView, toggleView } = useToggleView();
|
||||
|
||||
const { addTemplate, templates } = useTemplateStore();
|
||||
const { selectedZone } = useSelectedZoneStore();
|
||||
const { floatingWidget } = useFloatingWidget();
|
||||
|
||||
const { widgets3D } = use3DWidget();
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
|
||||
// wall options
|
||||
const { toggleView, setToggleView } = useToggleView();
|
||||
const { setDeleteTool } = useDeleteTool();
|
||||
const { setAddAction } = useAddAction();
|
||||
const { setSelectedWallItem } = useSelectedWallItem();
|
||||
const dropdownRef = useRef<HTMLButtonElement>(null);
|
||||
const [openDrop, setOpenDrop] = useState(false);
|
||||
|
||||
const { setTransformMode } = useTransformMode();
|
||||
const { setDeletePointOrLine } = useDeletePointOrLine();
|
||||
const { setToolMode } = useToolMode();
|
||||
const { activeTool, setActiveTool } = useActiveTool();
|
||||
const { setRefTextUpdate } = useRefTextUpdate();
|
||||
|
||||
// Reset activeTool whenever activeModule changes
|
||||
// 1. Set UI toggles on initial render
|
||||
useEffect(() => {
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft")
|
||||
? localStorage.getItem("navBarUiLeft") === "true"
|
||||
: true,
|
||||
localStorage.getItem("navBarUiRight")
|
||||
? localStorage.getItem("navBarUiRight") === "true"
|
||||
: true
|
||||
localStorage.getItem("navBarUiLeft") !== "false",
|
||||
localStorage.getItem("navBarUiRight") !== "false"
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
// 2. Update tool based on subtool and module
|
||||
useEffect(() => {
|
||||
setActiveTool(activeSubTool);
|
||||
setActiveSubTool(activeSubTool);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [activeModule]);
|
||||
|
||||
const toggleSwitch = () => {
|
||||
if (toggleThreeD) {
|
||||
setSelectedWallItem(null);
|
||||
setDeleteTool(false);
|
||||
setAddAction(null);
|
||||
setToggleView(true);
|
||||
// localStorage.setItem("navBarUi", JSON.stringify(!toggleThreeD));
|
||||
} else {
|
||||
setToggleView(false);
|
||||
}
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft")
|
||||
? localStorage.getItem("navBarUiLeft") === "true"
|
||||
: true,
|
||||
localStorage.getItem("navBarUiRight")
|
||||
? localStorage.getItem("navBarUiRight") === "true"
|
||||
: true
|
||||
);
|
||||
setToggleThreeD(!toggleThreeD);
|
||||
setActiveSubTool("cursor");
|
||||
setActiveTool("cursor");
|
||||
};
|
||||
|
||||
// 3. Update tools behavior based on selected tool and view mode
|
||||
useEffect(() => {
|
||||
const handleOutsideClick = (event: MouseEvent) => {
|
||||
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(event.target as Node)
|
||||
!dropdownRef.current.contains(e.target as Node)
|
||||
) {
|
||||
setOpenDrop(false); // Close the dropdown
|
||||
setOpenDrop(false);
|
||||
}
|
||||
};
|
||||
document.addEventListener("mousedown", handleOutsideClick);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleOutsideClick);
|
||||
};
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (!toggleThreeD) {
|
||||
setToggleUI(false, false);
|
||||
}
|
||||
}, [toggleThreeD]);
|
||||
|
||||
useEffect(() => {
|
||||
const resetTools = () => {
|
||||
setToolMode(null);
|
||||
setDeleteTool(false);
|
||||
setAddAction(null);
|
||||
setTransformMode(null);
|
||||
setDeletePointOrLine(false);
|
||||
setRefTextUpdate((prevUpdate) => prevUpdate - 1);
|
||||
setRefTextUpdate((prev) => prev - 1);
|
||||
};
|
||||
|
||||
switch (activeTool) {
|
||||
const updateToolBehavior = (tool: string, is2D: boolean) => {
|
||||
switch (tool) {
|
||||
case "cursor":
|
||||
if (toggleView) {
|
||||
setToolMode("move");
|
||||
} else {
|
||||
setTransformMode("translate");
|
||||
}
|
||||
is2D ? setToolMode("move") : setTransformMode("translate");
|
||||
break;
|
||||
|
||||
case "Rotate":
|
||||
if (!toggleView) {
|
||||
setTransformMode("rotate");
|
||||
}
|
||||
if (!is2D) setTransformMode("rotate");
|
||||
break;
|
||||
|
||||
case "Scale":
|
||||
if (!toggleView) {
|
||||
setTransformMode("scale");
|
||||
}
|
||||
if (!is2D) setTransformMode("scale");
|
||||
break;
|
||||
|
||||
case "draw-wall":
|
||||
if (toggleView) {
|
||||
setToolMode("Wall");
|
||||
}
|
||||
is2D && setToolMode("Wall");
|
||||
break;
|
||||
|
||||
case "draw-aisle":
|
||||
if (toggleView) {
|
||||
setToolMode("Aisle");
|
||||
}
|
||||
is2D && setToolMode("Aisle");
|
||||
break;
|
||||
|
||||
case "draw-zone":
|
||||
if (toggleView) {
|
||||
setToolMode("Zone");
|
||||
}
|
||||
is2D && setToolMode("Zone");
|
||||
break;
|
||||
|
||||
case "draw-floor":
|
||||
if (toggleView) {
|
||||
setToolMode("Floor");
|
||||
}
|
||||
is2D && setToolMode("Floor");
|
||||
break;
|
||||
|
||||
case "measure":
|
||||
setToolMode("MeasurementScale");
|
||||
break;
|
||||
|
||||
case "Add pillar":
|
||||
if (!toggleView) {
|
||||
setAddAction("pillar");
|
||||
}
|
||||
if (!is2D) setAddAction("pillar");
|
||||
break;
|
||||
|
||||
case "delete":
|
||||
if (toggleView) {
|
||||
setDeletePointOrLine(true);
|
||||
} else {
|
||||
setDeleteTool(true);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
is2D ? setDeletePointOrLine(true) : setDeleteTool(true);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
setActiveTool(activeTool);
|
||||
}, [activeTool, toggleView]);
|
||||
const toggle2D3D = () => {
|
||||
setToggleThreeD(!toggleThreeD);
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft") !== "false",
|
||||
localStorage.getItem("navBarUiRight") !== "false"
|
||||
);
|
||||
setSelectedWallItem(null);
|
||||
setActiveSubTool("cursor");
|
||||
setActiveTool("cursor");
|
||||
setToggleView(!toggleThreeD);
|
||||
};
|
||||
|
||||
if (isPlaying && activeModule !== "simulation") {
|
||||
return (
|
||||
<button className="exitPlay" onClick={() => setIsPlaying(false)}>
|
||||
X
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
const renderBuilderTools = () => (
|
||||
<>
|
||||
{!toggleThreeD && (
|
||||
<div className="draw-tools">
|
||||
<ToolButton
|
||||
icon={WallIcon}
|
||||
tooltip="draw wall (q)"
|
||||
active={activeTool === "draw-wall"}
|
||||
onClick={() => setActiveTool("draw-wall")}
|
||||
/>
|
||||
<ToolButton
|
||||
icon={ZoneIcon}
|
||||
tooltip="draw zone (e)"
|
||||
active={activeTool === "draw-zone"}
|
||||
onClick={() => setActiveTool("draw-zone")}
|
||||
/>
|
||||
<ToolButton
|
||||
icon={AsileIcon}
|
||||
tooltip="draw aisle (r)"
|
||||
active={activeTool === "draw-aisle"}
|
||||
onClick={() => setActiveTool("draw-aisle")}
|
||||
/>
|
||||
<ToolButton
|
||||
icon={FloorIcon}
|
||||
tooltip="draw floor (t)"
|
||||
active={activeTool === "draw-floor"}
|
||||
onClick={() => setActiveTool("draw-floor")}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="draw-tools">
|
||||
<ToolButton
|
||||
icon={MeasureToolIcon}
|
||||
tooltip="measure scale (m)"
|
||||
active={activeTool === "measure"}
|
||||
onClick={() => setActiveTool("measure")}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderSimulationTools = () => (
|
||||
<div className="draw-tools">
|
||||
<ToolButton
|
||||
icon={PenIcon}
|
||||
tooltip="pen"
|
||||
active={activeTool === "pen"}
|
||||
onClick={() => setActiveTool("pen")}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderVisualizationTools = () => (
|
||||
<div className="draw-tools">
|
||||
<ToolButton
|
||||
icon={SaveTemplateIcon}
|
||||
tooltip="save template"
|
||||
active={false}
|
||||
onClick={() =>
|
||||
handleSaveTemplate({
|
||||
addTemplate,
|
||||
floatingWidget,
|
||||
widgets3D,
|
||||
selectedZone,
|
||||
templates,
|
||||
visualizationSocket,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderModeSwitcher = () => (
|
||||
<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;
|
||||
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} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isPlaying ? (
|
||||
<div className="tools-container">
|
||||
<div className="drop-down-icons">
|
||||
<div className="activeDropicon">
|
||||
{activeSubTool == "cursor" && (
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "cursor" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("cursor");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">cursor (v)</div>
|
||||
<CursorIcon isActive={activeTool === "cursor"} />
|
||||
</div>
|
||||
)}
|
||||
{activeSubTool == "free-hand" && (
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "free-hand" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("free-hand");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">free hand (h)</div>
|
||||
<FreeMoveIcon isActive={activeTool === "free-hand"} />
|
||||
</div>
|
||||
)}
|
||||
{activeSubTool == "delete" && (
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "delete" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("delete");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">delete (x)</div>
|
||||
<DeleteIcon isActive={activeTool === "delete"} />
|
||||
</div>
|
||||
)}
|
||||
{activeModule !== "visualization" && (
|
||||
<div
|
||||
className="drop-down-option-button"
|
||||
ref={dropdownRef}
|
||||
onClick={() => {
|
||||
setOpenDrop(!openDrop);
|
||||
}}
|
||||
>
|
||||
<ArrowIcon />
|
||||
{openDrop && (
|
||||
<div className="drop-down-container">
|
||||
<div
|
||||
className="option-list"
|
||||
onClick={() => {
|
||||
setOpenDrop(false);
|
||||
setActiveTool("cursor");
|
||||
setActiveSubTool("cursor");
|
||||
}}
|
||||
>
|
||||
<div className="active-option">
|
||||
{activeSubTool === "cursor" && <TickIcon />}
|
||||
</div>
|
||||
<CursorIcon isActive={false} />
|
||||
<div className="option">Cursor</div>
|
||||
</div>
|
||||
<div
|
||||
className="option-list"
|
||||
onClick={() => {
|
||||
setOpenDrop(false);
|
||||
setActiveTool("free-hand");
|
||||
setActiveSubTool("free-hand");
|
||||
}}
|
||||
>
|
||||
<div className="active-option">
|
||||
{activeSubTool === "free-hand" && <TickIcon />}
|
||||
</div>
|
||||
<FreeMoveIcon isActive={false} />
|
||||
<div className="option">Free Hand</div>
|
||||
</div>
|
||||
<div
|
||||
className="option-list"
|
||||
onClick={() => {
|
||||
setOpenDrop(false);
|
||||
setActiveTool("delete");
|
||||
setActiveSubTool("delete");
|
||||
}}
|
||||
>
|
||||
<div className="active-option">
|
||||
{activeSubTool === "delete" && <TickIcon />}
|
||||
</div>
|
||||
<DeleteIcon isActive={false} />
|
||||
<div className="option">Delete</div>
|
||||
</div>
|
||||
<div className="tools-container">
|
||||
<div className="activeDropicon">
|
||||
{/* Tool Picker (cursor, delete, etc.) */}
|
||||
{["cursor", "free-hand", "delete"].map(
|
||||
(tool) =>
|
||||
activeSubTool === tool && (
|
||||
<ToolButton
|
||||
key={tool}
|
||||
icon={getIconByTool(tool)}
|
||||
tooltip={`${tool} (${getTooltipShortcut(tool)})`}
|
||||
active={activeTool === tool}
|
||||
onClick={() => setActiveTool(tool)}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{/* Dropdown Menu */}
|
||||
{activeModule !== "visualization" && (
|
||||
<button
|
||||
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}
|
||||
className="option-list"
|
||||
onClick={() => {
|
||||
setActiveTool(option);
|
||||
setActiveSubTool(option);
|
||||
setOpenDrop(false);
|
||||
}}
|
||||
>
|
||||
<div className="active-option">
|
||||
{activeSubTool === option && <TickIcon />}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{!toggleThreeD && activeModule === "builder" && (
|
||||
<>
|
||||
<div className="split"></div>
|
||||
<div className="draw-tools">
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "draw-wall" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("draw-wall");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">draw wall (q)</div>
|
||||
<WallIcon isActive={activeTool === "draw-wall"} />
|
||||
</div>
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "draw-zone" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("draw-zone");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">draw zone (e)</div>
|
||||
<ZoneIcon isActive={activeTool === "draw-zone"} />
|
||||
</div>
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "draw-aisle" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("draw-aisle");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">draw asile (r)</div>
|
||||
<AsileIcon isActive={activeTool === "draw-aisle"} />
|
||||
</div>
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "draw-floor" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("draw-floor");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">draw floor (t)</div>
|
||||
<FloorIcon isActive={activeTool === "draw-floor"} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{activeModule === "builder" && (
|
||||
<>
|
||||
<div className="split"></div>
|
||||
<div className="draw-tools">
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "measure" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("measure");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">measure scale (m)</div>
|
||||
<MeasureToolIcon isActive={activeTool === "measure"} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{activeModule === "simulation" && (
|
||||
<>
|
||||
<div className="split"></div>
|
||||
<div className="draw-tools">
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "pen" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("pen");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">pen</div>
|
||||
<PenIcon isActive={activeTool === "pen"} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{activeModule === "visualization" && (
|
||||
<>
|
||||
<div className="split"></div>
|
||||
<div className="draw-tools">
|
||||
<div
|
||||
className={`tool-button`}
|
||||
onClick={() => {
|
||||
handleSaveTemplate({
|
||||
addTemplate,
|
||||
floatingWidget,
|
||||
widgets3D,
|
||||
selectedZone,
|
||||
templates,
|
||||
visualizationSocket,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">save template</div>
|
||||
<SaveTemplateIcon isActive={false} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="split"></div>
|
||||
<div className="general-options">
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "comment" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveTool("comment");
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">comment</div>
|
||||
<CommentIcon isActive={activeTool === "comment"} />
|
||||
</div>
|
||||
{toggleThreeD && (
|
||||
<div
|
||||
className={`tool-button ${
|
||||
activeTool === "play" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setIsPlaying(!isPlaying);
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">play (ctrl + p)</div>
|
||||
<PlayIcon isActive={activeTool === "play"} />
|
||||
{getIconComponent(option)}
|
||||
<div className="option">{option}</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{activeModule === "builder" && (
|
||||
<>
|
||||
<div className="split"></div>
|
||||
<div
|
||||
className={`toggle-threed-button${
|
||||
toggleThreeD ? " toggled" : ""
|
||||
}`}
|
||||
onClick={toggleSwitch}
|
||||
>
|
||||
<div className="tooltip">toggle view (tab)</div>
|
||||
<div
|
||||
className={`toggle-option${!toggleThreeD ? " active" : ""}`}
|
||||
>
|
||||
2d
|
||||
</div>
|
||||
<div
|
||||
className={`toggle-option${toggleThreeD ? " active" : ""}`}
|
||||
>
|
||||
3d
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="split"></div>
|
||||
{activeModule === "builder" && renderBuilderTools()}
|
||||
{activeModule === "simulation" && renderSimulationTools()}
|
||||
{activeModule === "visualization" && renderVisualizationTools()}
|
||||
|
||||
<div className="split"></div>
|
||||
<div className="general-options">
|
||||
<ToolButton
|
||||
icon={CommentIcon}
|
||||
tooltip="comment"
|
||||
active={activeTool === "comment"}
|
||||
onClick={() => setActiveTool("comment")}
|
||||
/>
|
||||
{toggleThreeD && (
|
||||
<ToolButton
|
||||
icon={PlayIcon}
|
||||
tooltip="play (ctrl + p)"
|
||||
active={activeTool === "play"}
|
||||
onClick={() => setIsPlaying(!isPlaying)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{activeModule === "builder" && (
|
||||
<>
|
||||
{activeModule !== "simulation" && (
|
||||
<button className="exitPlay" onClick={() => setIsPlaying(false)}>
|
||||
X
|
||||
</button>
|
||||
)}
|
||||
<div className="split"></div>
|
||||
{renderModeSwitcher()}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Extracted common store logic
|
||||
const useStoreHooks = () => {
|
||||
return {
|
||||
...useActiveTool(),
|
||||
...useToolMode(),
|
||||
...useDeleteTool(),
|
||||
...useAddAction(),
|
||||
...useTransformMode(),
|
||||
...useDeletePointOrLine(),
|
||||
...useRefTextUpdate(),
|
||||
};
|
||||
};
|
||||
|
||||
export default Tools;
|
||||
|
||||
@@ -11,9 +11,9 @@ import ReferenceDistanceText from "./geomentries/lines/distanceText/referenceDis
|
||||
|
||||
////////// Assests Imports //////////
|
||||
|
||||
import arch from "../../assets/gltf-glb/arch.glb";
|
||||
import door from "../../assets/gltf-glb/door.glb";
|
||||
import Window from "../../assets/gltf-glb/window.glb";
|
||||
// import arch from "../../assets/gltf-glb/arch.glb";
|
||||
// import door from "../../assets/gltf-glb/door.glb";
|
||||
// import Window from "../../assets/gltf-glb/window.glb";
|
||||
|
||||
////////// Zustand State Imports //////////
|
||||
|
||||
@@ -129,30 +129,30 @@ export default function Builder() {
|
||||
////////// Assest Configuration Values //////////
|
||||
|
||||
const AssetConfigurations: Types.AssetConfigurations = {
|
||||
arch: {
|
||||
modelUrl: arch,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [2, 4, 0.5],
|
||||
csgposition: [0, 2, 0],
|
||||
positionY: () => 0,
|
||||
type: "Fixed-Move",
|
||||
},
|
||||
door: {
|
||||
modelUrl: door,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [2, 4, 0.5],
|
||||
csgposition: [0, 2, 0],
|
||||
positionY: () => 0,
|
||||
type: "Fixed-Move",
|
||||
},
|
||||
window: {
|
||||
modelUrl: Window,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [5, 3, 0.5],
|
||||
csgposition: [0, 1.5, 0],
|
||||
positionY: (intersectionPoint) => intersectionPoint.point.y,
|
||||
type: "Free-Move",
|
||||
},
|
||||
// arch: {
|
||||
// modelUrl: arch,
|
||||
// scale: [0.75, 0.75, 0.75],
|
||||
// csgscale: [2, 4, 0.5],
|
||||
// csgposition: [0, 2, 0],
|
||||
// positionY: () => 0,
|
||||
// type: "Fixed-Move",
|
||||
// },
|
||||
// door: {
|
||||
// modelUrl: door,
|
||||
// scale: [0.75, 0.75, 0.75],
|
||||
// csgscale: [2, 4, 0.5],
|
||||
// csgposition: [0, 2, 0],
|
||||
// positionY: () => 0,
|
||||
// type: "Fixed-Move",
|
||||
// },
|
||||
// window: {
|
||||
// modelUrl: Window,
|
||||
// scale: [0.75, 0.75, 0.75],
|
||||
// csgscale: [5, 3, 0.5],
|
||||
// csgposition: [0, 1.5, 0],
|
||||
// positionY: (intersectionPoint) => intersectionPoint.point.y,
|
||||
// type: "Free-Move",
|
||||
// },
|
||||
};
|
||||
|
||||
////////// All Toggle's //////////
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { Suspense, useEffect } from "react";
|
||||
import assetImage from "../../assets/image/image.png";
|
||||
import React, { Suspense } from "react";
|
||||
import { FilledStarsIconSmall } from "../../components/icons/marketPlaceIcons";
|
||||
import { Canvas, useThree } from "@react-three/fiber";
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
import { ContactShadows, OrbitControls, Text } from "@react-three/drei";
|
||||
import GltfLoader from "./GltfLoader";
|
||||
import * as THREE from "three";
|
||||
@@ -14,17 +13,26 @@ interface SelectedCard {
|
||||
rating: number;
|
||||
views: number;
|
||||
description: string;
|
||||
AssetID: string;
|
||||
}
|
||||
|
||||
// Define the props type for AssetPreview
|
||||
interface AssetPreviewProps {
|
||||
selectedCard: SelectedCard;
|
||||
modelUrl: string;
|
||||
setSelectedCard: React.Dispatch<React.SetStateAction<SelectedCard | null>>; // Type for setter function
|
||||
}
|
||||
|
||||
const savedTheme: string | null = localStorage.getItem("theme");
|
||||
|
||||
function Ui() {
|
||||
return (
|
||||
<Text color="#6f42c1" anchorX="center" anchorY="middle" scale={0.3}>
|
||||
<Text
|
||||
color={savedTheme === "dark" ? "#d2baff" : "#6f42c1"}
|
||||
anchorX="center"
|
||||
anchorY="middle"
|
||||
scale={0.3}
|
||||
>
|
||||
Loading preview...
|
||||
</Text>
|
||||
);
|
||||
@@ -33,16 +41,8 @@ function Ui() {
|
||||
const AssetPreview: React.FC<AssetPreviewProps> = ({
|
||||
selectedCard,
|
||||
setSelectedCard,
|
||||
modelUrl,
|
||||
}) => {
|
||||
// Ensure rating is a valid number between 0 and 5
|
||||
const rating = Math.max(
|
||||
0,
|
||||
Math.min(5, isNaN(selectedCard.rating) ? 0 : selectedCard.rating)
|
||||
);
|
||||
|
||||
// Ensure that the rating is a valid positive integer for array length
|
||||
const starsArray = Array.from({ length: rating }, (_, index) => index);
|
||||
|
||||
return (
|
||||
<div className="assetPreview-wrapper">
|
||||
<div className="assetPreview">
|
||||
@@ -53,18 +53,19 @@ const AssetPreview: React.FC<AssetPreviewProps> = ({
|
||||
<Canvas
|
||||
flat
|
||||
shadows
|
||||
color="#FFFFFF"
|
||||
camera={{ fov: 75 }}
|
||||
gl={{
|
||||
preserveDrawingBuffer: true,
|
||||
}}
|
||||
onCreated={({ scene }) => {
|
||||
scene.background = new THREE.Color(0xffffff);
|
||||
scene.background = new THREE.Color(
|
||||
savedTheme === "dark" ? 0x19191d : 0xfcfdfd
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Suspense fallback={<Ui />}>
|
||||
{selectedCard.assetName && (
|
||||
<GltfLoader fromServer={selectedCard.assetName} />
|
||||
{selectedCard.assetName && modelUrl && (
|
||||
<GltfLoader fromServer={modelUrl} />
|
||||
)}
|
||||
<OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} />
|
||||
<ContactShadows
|
||||
@@ -113,9 +114,9 @@ const AssetPreview: React.FC<AssetPreviewProps> = ({
|
||||
</div>
|
||||
|
||||
{/* close button */}
|
||||
<div className="closeButton" onClick={() => setSelectedCard(null)}>
|
||||
<button className="closeButton" onClick={() => setSelectedCard(null)}>
|
||||
{`<-back`}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React from "react";
|
||||
import {
|
||||
CommentsIcon,
|
||||
DownloadIcon,
|
||||
EyeIconBig,
|
||||
FilledStarsIconSmall,
|
||||
StarsIconSmall,
|
||||
VerifiedIcon,
|
||||
} from "../../components/icons/marketPlaceIcons";
|
||||
|
||||
import assetImage from "../../assets/image/image.png";
|
||||
import { getAssetDownload } from "../../services/marketplace/getAssetDownload";
|
||||
|
||||
interface CardProps {
|
||||
assetName: string;
|
||||
@@ -19,6 +16,7 @@ interface CardProps {
|
||||
views: number;
|
||||
image: string;
|
||||
description: string;
|
||||
AssetID: string;
|
||||
onSelectCard: (cardData: {
|
||||
assetName: string;
|
||||
uploadedOn: number;
|
||||
@@ -26,6 +24,7 @@ interface CardProps {
|
||||
rating: number;
|
||||
views: number;
|
||||
description: string;
|
||||
AssetID: string;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
@@ -38,9 +37,18 @@ const Card: React.FC<CardProps> = ({
|
||||
image,
|
||||
description,
|
||||
onSelectCard,
|
||||
AssetID,
|
||||
}) => {
|
||||
const handleCardSelect = () => {
|
||||
onSelectCard({ assetName, uploadedOn, price, rating, views, description });
|
||||
onSelectCard({
|
||||
assetName,
|
||||
uploadedOn,
|
||||
price,
|
||||
rating,
|
||||
views,
|
||||
description,
|
||||
AssetID,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -81,22 +89,22 @@ const Card: React.FC<CardProps> = ({
|
||||
<div className="stars-container">
|
||||
<div className="stars-wrapper">
|
||||
{[...Array(5)].map((_, index) => (
|
||||
<>
|
||||
<React.Fragment key={index} >
|
||||
{index < 3 ? (
|
||||
<FilledStarsIconSmall key={index} />
|
||||
<FilledStarsIconSmall />
|
||||
) : (
|
||||
<StarsIconSmall key={index} />
|
||||
<StarsIconSmall />
|
||||
)}
|
||||
</>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
<div className="units">
|
||||
₹ {price}/<span>unit</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="buy-now-button" onClick={handleCardSelect}>
|
||||
<button className="buy-now-button" onClick={handleCardSelect}>
|
||||
Buy now
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import Card from "./Card";
|
||||
import AssetPreview from "./AssetPreview";
|
||||
import { fetchGltfUrl } from "../../services/marketplace/fetchGltfUrl";
|
||||
|
||||
interface ModelData {
|
||||
CreatedBy: string;
|
||||
@@ -15,12 +16,14 @@ interface ModelData {
|
||||
uploadDate: number;
|
||||
_id: string;
|
||||
price: number;
|
||||
AssetID: string;
|
||||
}
|
||||
interface ModelsProps {
|
||||
models: ModelData[];
|
||||
}
|
||||
|
||||
const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
|
||||
const [modelUrl, setModelUrl] = useState<string>("");
|
||||
const [selectedCard, setSelectedCard] = useState<{
|
||||
assetName: string;
|
||||
uploadedOn: number;
|
||||
@@ -28,19 +31,23 @@ const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
|
||||
rating: number;
|
||||
views: number;
|
||||
description: string;
|
||||
AssetID: string;
|
||||
} | null>(null);
|
||||
|
||||
const handleCardSelect = (cardData: {
|
||||
const handleCardSelect = async (cardData: {
|
||||
assetName: string;
|
||||
uploadedOn: number;
|
||||
price: number;
|
||||
rating: number;
|
||||
views: number;
|
||||
description: string;
|
||||
AssetID: string;
|
||||
}) => {
|
||||
setSelectedCard(cardData);
|
||||
const res = await fetchGltfUrl(cardData.assetName, cardData.AssetID);
|
||||
console.log("res: ", res);
|
||||
setModelUrl(res.url);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="cards-container-wrapper">
|
||||
<div className="cards-container-container">
|
||||
@@ -48,23 +55,26 @@ const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
|
||||
<div className="cards-wrapper-container">
|
||||
{models.length > 0 &&
|
||||
models.map((assetDetail) => (
|
||||
<Card
|
||||
key={assetDetail._id}
|
||||
assetName={assetDetail?.filename}
|
||||
uploadedOn={assetDetail.uploadDate}
|
||||
price={assetDetail?.price}
|
||||
rating={4.5}
|
||||
views={800}
|
||||
onSelectCard={handleCardSelect}
|
||||
image={assetDetail.thumbnail}
|
||||
description={assetDetail.description}
|
||||
/>
|
||||
<React.Fragment key={assetDetail._id}>
|
||||
<Card
|
||||
assetName={assetDetail?.filename}
|
||||
uploadedOn={assetDetail.uploadDate}
|
||||
price={assetDetail?.price}
|
||||
rating={4.5}
|
||||
views={800}
|
||||
onSelectCard={handleCardSelect}
|
||||
AssetID={assetDetail.AssetID}
|
||||
image={assetDetail.thumbnail}
|
||||
description={assetDetail.description}
|
||||
/>
|
||||
</React.Fragment>
|
||||
))}
|
||||
{/* <RenderOverlay> */}
|
||||
{selectedCard && (
|
||||
<AssetPreview
|
||||
selectedCard={selectedCard}
|
||||
setSelectedCard={setSelectedCard}
|
||||
modelUrl={modelUrl}
|
||||
/>
|
||||
)}
|
||||
{/* </RenderOverlay> */}
|
||||
|
||||
@@ -16,6 +16,7 @@ interface ModelData {
|
||||
uploadDate: number;
|
||||
_id: string;
|
||||
price: number;
|
||||
AssetID: string;
|
||||
}
|
||||
|
||||
interface ModelsProps {
|
||||
@@ -44,7 +45,7 @@ const FilterSearch: React.FC<ModelsProps> = ({
|
||||
const descending = [...models].sort((a, b) => b.filename.localeCompare(a.filename));
|
||||
setModels(descending);
|
||||
}
|
||||
}, [activeOption]);
|
||||
}, [activeOption, models, setModels]);
|
||||
|
||||
const handleSearch = (val: string) => {
|
||||
const filteredModel = filteredModels.filter((model) =>
|
||||
@@ -73,13 +74,13 @@ const FilterSearch: React.FC<ModelsProps> = ({
|
||||
<div className="label">Rating</div>
|
||||
<div className="stars">
|
||||
{[0, 1, 2, 3, 4].map((i) => (
|
||||
<div
|
||||
<button
|
||||
key={i}
|
||||
onClick={() => handleStarClick(i)}
|
||||
className={`star-wrapper ${i < rating ? "filled" : "empty"}`}
|
||||
>
|
||||
<StarsIcon />
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useFrame } from "@react-three/fiber";
|
||||
import { Stage, useGLTF } from "@react-three/drei";
|
||||
import { AnimationMixer, AnimationAction, Object3D } from "three";
|
||||
import * as THREE from "three";
|
||||
import { fetchGltfUrl } from "../../services/marketplace/fetchGltfUrl";
|
||||
|
||||
interface GltfLoaderProps {
|
||||
glbdata?: boolean;
|
||||
@@ -13,7 +12,6 @@ interface GltfLoaderProps {
|
||||
setSelectedAnimation?: (animation: string) => void;
|
||||
}
|
||||
|
||||
// const getGLTFUrl = (url: string) => url; // Placeholder for your actual function
|
||||
|
||||
const GltfLoader: React.FC<GltfLoaderProps> = ({
|
||||
glbdata,
|
||||
@@ -21,12 +19,10 @@ const GltfLoader: React.FC<GltfLoaderProps> = ({
|
||||
setAnimations,
|
||||
selectedAnimation,
|
||||
}) => {
|
||||
const modelUrl: any = fromServer ? fetchGltfUrl(fromServer) : glbdata;
|
||||
const { scene, animations } = useGLTF(modelUrl ?? "") as {
|
||||
const { scene, animations } = useGLTF(fromServer ?? "") as {
|
||||
scene: Object3D;
|
||||
animations: THREE.AnimationClip[];
|
||||
};
|
||||
|
||||
const mixer = useRef<AnimationMixer | null>(
|
||||
scene ? new AnimationMixer(scene) : null
|
||||
);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import FilterSearch from "./FilterSearch";
|
||||
import CardsContainer from "./CardsContainer";
|
||||
import { fetchAssets } from "../../services/marketplace/fetchAssets";
|
||||
import { getAssetImages } from "../../services/factoryBuilder/assest/assets/getAssetImages";
|
||||
import SkeletonUI from "../../components/templates/SkeletonUI";
|
||||
interface ModelData {
|
||||
@@ -17,6 +16,7 @@ interface ModelData {
|
||||
uploadDate: number;
|
||||
_id: string;
|
||||
price: number;
|
||||
AssetID: string;
|
||||
}
|
||||
const MarketPlace = () => {
|
||||
const [models, setModels] = useState<ModelData[]>([]);
|
||||
|
||||
@@ -4,7 +4,7 @@ import PostProcessing from '../postProcessing/postProcessing'
|
||||
import Controls from '../controls/controls';
|
||||
import { Environment } from '@react-three/drei'
|
||||
|
||||
import background from "../../../assets/hdr/mudroadpuresky2k.hdr";
|
||||
import background from "../../../assets/textures/hdr/mudroadpuresky2k.hdr";
|
||||
|
||||
function Setup() {
|
||||
return (
|
||||
|
||||
@@ -14,7 +14,7 @@ export function useDefaultHandler() {
|
||||
const material = getMaterialById(materialId);
|
||||
if (!material) return;
|
||||
|
||||
defaultLogStatus(material.materialId, `performed Default action`);
|
||||
defaultLogStatus(material.materialName, `performed Default action`);
|
||||
|
||||
}, [getMaterialById]);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export function useDespawnHandler() {
|
||||
|
||||
removeMaterial(material.materialId);
|
||||
|
||||
deSpawnLogStatus(material.materialId, `Despawned`);
|
||||
deSpawnLogStatus(material.materialName, `Despawned`);
|
||||
|
||||
}, [getMaterialById, removeMaterial]);
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ export function useSpawnHandler() {
|
||||
if (elapsed >= adjustedInterval) {
|
||||
const createdMaterial = createNewMaterial(material, action);
|
||||
if (createdMaterial) {
|
||||
spawnLogStatus(createdMaterial.materialId, `[${elapsed.toFixed(2)}ms] Spawned ${material} (1/${totalCount})`);
|
||||
spawnLogStatus(createdMaterial.materialName, `[${elapsed.toFixed(2)}ms] Spawned ${material} (1/${totalCount})`);
|
||||
}
|
||||
spawn.lastSpawnTime = currentTime;
|
||||
spawn.spawnCount = 1;
|
||||
@@ -162,7 +162,7 @@ export function useSpawnHandler() {
|
||||
const count = spawn.spawnCount + 1;
|
||||
const createdMaterial = createNewMaterial(material, action);
|
||||
if (createdMaterial) {
|
||||
spawnLogStatus(createdMaterial.materialId, `[${timeSinceLast.toFixed(2)}ms] Spawned ${material} (${count}/${totalCount})`);
|
||||
spawnLogStatus(createdMaterial.materialName, `[${timeSinceLast.toFixed(2)}ms] Spawned ${material} (${count}/${totalCount})`);
|
||||
}
|
||||
spawn.lastSpawnTime = currentTime;
|
||||
spawn.spawnCount = count;
|
||||
|
||||
@@ -16,7 +16,7 @@ export function useSwapHandler() {
|
||||
if (!material) return;
|
||||
|
||||
setMaterial(material.materialId, newMaterialType);
|
||||
swapLogStatus(material.materialId, `Swapped to ${newMaterialType}`);
|
||||
swapLogStatus(material.materialName, `Swapped to ${newMaterialType}`);
|
||||
|
||||
}, [getMaterialById, setMaterial]);
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ export function useProcessHandler() {
|
||||
|
||||
addCurrentAction(modelUuid, action.actionUuid, newMaterialType, material.materialId);
|
||||
|
||||
processLogStatus(material.materialId, `Swapped to ${newMaterialType}`);
|
||||
processLogStatus(material.materialId, `starts Process action`);
|
||||
processLogStatus(material.materialName, `Swapped to ${newMaterialType}`);
|
||||
processLogStatus(material.materialName, `starts Process action`);
|
||||
|
||||
}, [getMaterialById]);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ export function usePickAndPlaceHandler() {
|
||||
material.materialId
|
||||
);
|
||||
|
||||
pickAndPlaceLogStatus(material.materialId, `is going to be picked by armBot ${modelUuid}`);
|
||||
pickAndPlaceLogStatus(material.materialName, `is going to be picked by armBot ${modelUuid}`);
|
||||
|
||||
}, [getMaterialById, getModelUuidByActionUuid, selectedProduct.productId, addCurrentAction]);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ export function useStoreHandler() {
|
||||
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
|
||||
updateCurrentLoad(modelUuid, 1);
|
||||
|
||||
storeLogStatus(material.materialId, `performed Store action`);
|
||||
storeLogStatus(material.materialName, `performed Store action`);
|
||||
|
||||
}, [getMaterialById]);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ export function useTravelHandler() {
|
||||
incrementVehicleLoad(modelUuid, 1);
|
||||
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
|
||||
|
||||
travelLogStatus(material.materialId, `is triggering travel from ${modelUuid}`);
|
||||
travelLogStatus(material.materialName, `is triggering travel from ${modelUuid}`);
|
||||
|
||||
}, [addCurrentMaterial, getMaterialById, getModelUuidByActionUuid, incrementVehicleLoad, selectedProduct.productId]);
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@ import { useGLTF } from '@react-three/drei'
|
||||
import { useMemo } from 'react';
|
||||
import * as THREE from 'three';
|
||||
|
||||
import defaultMaterial from '../../../../../assets/gltf-glb/default.glb';
|
||||
import material1 from '../../../../../assets/gltf-glb/material1.glb';
|
||||
import material2 from '../../../../../assets/gltf-glb/material2.glb';
|
||||
import material3 from '../../../../../assets/gltf-glb/material3.glb';
|
||||
import defaultMaterial from '../../../../../assets/gltf-glb/materials/default.glb';
|
||||
import material1 from '../../../../../assets/gltf-glb/materials/material1.glb';
|
||||
import material2 from '../../../../../assets/gltf-glb/materials/material2.glb';
|
||||
import material3 from '../../../../../assets/gltf-glb/materials/material3.glb';
|
||||
|
||||
const modelPaths: Record<string, string> = {
|
||||
'Default material': defaultMaterial,
|
||||
|
||||
@@ -8,8 +8,8 @@ import PickDropPoints from './PickDropPoints';
|
||||
import useDraggableGLTF from './useDraggableGLTF';
|
||||
import * as THREE from 'three';
|
||||
|
||||
import armPick from "../../../../assets/gltf-glb/arm_ui_pick.glb";
|
||||
import armDrop from "../../../../assets/gltf-glb/arm_ui_drop.glb";
|
||||
import armPick from "../../../../assets/gltf-glb/ui/arm_ui_pick.glb";
|
||||
import armDrop from "../../../../assets/gltf-glb/ui/arm_ui_drop.glb";
|
||||
import { upsertProductOrEventApi } from '../../../../services/simulation/UpsertProductOrEventApi';
|
||||
|
||||
type Positions = {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
import startPoint from "../../../../assets/gltf-glb/arrow_green.glb";
|
||||
import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
|
||||
import { useGLTF } from "@react-three/drei";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import {
|
||||
@@ -15,6 +13,9 @@ import { useProductStore } from "../../../../store/simulation/useProductStore";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
|
||||
import { DoubleSide, Group, Plane, Vector3 } from "three";
|
||||
|
||||
import startPoint from "../../../../assets/gltf-glb/ui/arrow_green.glb";
|
||||
import startEnd from "../../../../assets/gltf-glb/ui/arrow_red.glb";
|
||||
|
||||
const VehicleUI = () => {
|
||||
const { scene: startScene } = useGLTF(startPoint) as any;
|
||||
const { scene: endScene } = useGLTF(startEnd) as any;
|
||||
|
||||
@@ -1,7 +1,26 @@
|
||||
let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||
export const fetchGltfUrl = (filename: string) => {
|
||||
if (filename) {
|
||||
return `${BackEnd_url}/api/v1/getAssetFile/${filename}`;
|
||||
export const fetchGltfUrl = async (filename: string, AssetID: string) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${BackEnd_url}/api/v2/assetDetails/${filename}/${AssetID}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
// body: JSON.stringify(assetData),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch asset details");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
//
|
||||
throw new Error(error.message);
|
||||
}
|
||||
return null; // or handle the case when filename is not provided
|
||||
};
|
||||
}
|
||||
@@ -2,9 +2,6 @@
|
||||
@use "../../abstracts/mixins.scss" as *;
|
||||
|
||||
.marketplace-wrapper {
|
||||
// transform: scale(0.65);
|
||||
/* Start at 90% width */
|
||||
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
z-index: #{$z-index-marketplace};
|
||||
@@ -14,7 +11,6 @@
|
||||
top: 0;
|
||||
padding: 10px;
|
||||
padding-top: 100px;
|
||||
// animation: growWidth 0.4s ease-in-out 0.5s forwards;
|
||||
|
||||
.marketplace-container {
|
||||
position: relative;
|
||||
@@ -43,8 +39,6 @@
|
||||
width: 100%;
|
||||
|
||||
.skeleton-content {
|
||||
|
||||
|
||||
width: calc(25% - 14px) !important;
|
||||
height: 100%;
|
||||
border-radius: #{$border-radius-xlarge};
|
||||
@@ -79,7 +73,6 @@
|
||||
}
|
||||
|
||||
.button {
|
||||
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
border-radius: 20px;
|
||||
@@ -143,8 +136,7 @@
|
||||
|
||||
.star-wrapper.filled {
|
||||
svg {
|
||||
|
||||
fill: #F3A50C;
|
||||
fill: #f3a50c;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,10 +182,6 @@
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
|
||||
.assets-container {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
@@ -208,7 +196,7 @@
|
||||
.image-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
max-height: 180px;
|
||||
height: 180px;
|
||||
justify-content: center;
|
||||
border-radius: #{$border-radius-medium};
|
||||
overflow: hidden;
|
||||
@@ -224,7 +212,7 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0;
|
||||
|
||||
height: auto;
|
||||
.name-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -299,7 +287,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.assetPreview-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -307,15 +294,18 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 3;
|
||||
padding: 0 10px;
|
||||
|
||||
.assetPreview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--background-color);
|
||||
backdrop-filter: blur(18px);
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
overflow: hidden;
|
||||
border-radius: #{$border-radius-extra-large};
|
||||
outline: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
// Image Preview Section
|
||||
@@ -352,8 +342,8 @@
|
||||
min-width: 26px;
|
||||
border-radius: #{$border-radius-circle};
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--background-color);
|
||||
background: var(--accent-color);
|
||||
color: var(--text-button-color);
|
||||
background: var(--background-color-button);
|
||||
}
|
||||
|
||||
.organization-details {
|
||||
@@ -361,9 +351,7 @@
|
||||
flex-direction: column;
|
||||
|
||||
.organization-name {
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
|
||||
font-weight: #{$bold-weight};
|
||||
font-size: $regular;
|
||||
}
|
||||
@@ -380,35 +368,31 @@
|
||||
margin-top: 20px;
|
||||
|
||||
.asset-name {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
font-weight: #{$bold-weight};
|
||||
font-size: $large;
|
||||
font-size: var(--font-size-large);
|
||||
}
|
||||
|
||||
.asset-description {
|
||||
margin-bottom: 20px;
|
||||
color: #666;
|
||||
color: var(--input-text-color);
|
||||
}
|
||||
|
||||
.asset-review {
|
||||
width: fit-content;
|
||||
padding: 5px 10px;
|
||||
padding: 5px 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
outline: 1px solid #909090cc;
|
||||
border-radius: #{$border-radius-small};
|
||||
outline: 1px solid var(--border-color);
|
||||
border-radius: #{$border-radius-large};
|
||||
|
||||
.asset-rating {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-right: 10px;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
|
||||
font-weight: #{$bold-weight};
|
||||
font-size: $regular;
|
||||
|
||||
@@ -442,25 +426,25 @@
|
||||
}
|
||||
|
||||
.button {
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border-radius: #{$border-radius-small};
|
||||
color: var(--text-button-color);
|
||||
padding: 8px 26px;
|
||||
border-radius: #{$border-radius-extra-large};
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
|
||||
&:first-child {
|
||||
outline: 1px solid var(--accent-color);
|
||||
color: var(--accent-color);
|
||||
outline: 1px solid var(--background-color-button);
|
||||
color: var(--highlight-text-color);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
background: var(--accent-color);
|
||||
color: var(--background-color);
|
||||
background: var(--background-color-button);
|
||||
color: var(--text-button-color);
|
||||
}
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
color: var(--accent-color);
|
||||
color: var(--highlight-text-color);
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: 18px;
|
||||
@@ -468,4 +452,4 @@
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-large);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +305,6 @@
|
||||
.header-container {
|
||||
@include flex-space-between;
|
||||
padding: 10px;
|
||||
padding-left: 16px;
|
||||
width: 100%;
|
||||
gap: 8px;
|
||||
height: 52px;
|
||||
|
||||
@@ -108,26 +108,39 @@ const KeyPressListener: React.FC = () => {
|
||||
|
||||
|
||||
const handleSidebarShortcuts = (key: string) => {
|
||||
if (activeModule !== "market") {
|
||||
if (key === "Ctrl+\\") {
|
||||
if (activeModule === "market") return;
|
||||
|
||||
const updateLocalStorage = (left: boolean, right: boolean) => {
|
||||
localStorage.setItem("navBarUiLeft", JSON.stringify(left));
|
||||
localStorage.setItem("navBarUiRight", JSON.stringify(right));
|
||||
};
|
||||
|
||||
switch (key) {
|
||||
case "Ctrl+\\":
|
||||
if (toggleUILeft === toggleUIRight) {
|
||||
setToggleUI(!toggleUILeft, !toggleUIRight);
|
||||
}
|
||||
else {
|
||||
const newState = !toggleUILeft;
|
||||
setToggleUI(newState, newState);
|
||||
updateLocalStorage(newState, newState);
|
||||
} else {
|
||||
setToggleUI(true, true);
|
||||
updateLocalStorage(true, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (key === "Ctrl+]") {
|
||||
setToggleUI(toggleUILeft, !toggleUIRight);
|
||||
return;
|
||||
}
|
||||
if (key === "Ctrl+[") {
|
||||
setToggleUI(!toggleUILeft, toggleUIRight);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case "Ctrl+]":
|
||||
setToggleUI(toggleUILeft, !toggleUIRight);
|
||||
updateLocalStorage(toggleUILeft, !toggleUIRight);
|
||||
break;
|
||||
|
||||
case "Ctrl+[":
|
||||
setToggleUI(!toggleUILeft, toggleUIRight);
|
||||
updateLocalStorage(!toggleUILeft, toggleUIRight);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleKeyPress = (event: KeyboardEvent) => {
|
||||
|
||||
Reference in New Issue
Block a user