v3-ui #98
Binary file not shown.
After Width: | Height: | Size: 1.9 MiB |
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
|
@ -1,27 +1,35 @@
|
||||||
import React from 'react'
|
import React from "react";
|
||||||
import { useLoadingProgress, useSaveVersion, useSocketStore, useWidgetSubOption } from '../../../store/builder/store';
|
import {
|
||||||
import useModuleStore, { useThreeDStore } from '../../../store/useModuleStore';
|
useLoadingProgress,
|
||||||
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
useSaveVersion,
|
||||||
import { useSelectedZoneStore } from '../../../store/visualization/useZoneStore';
|
useSocketStore,
|
||||||
import { useFloatingWidget } from '../../../store/visualization/useDroppedObjectsStore';
|
useWidgetSubOption,
|
||||||
import { useSelectedUserStore } from '../../../store/collaboration/useCollabStore';
|
} from "../../../store/builder/store";
|
||||||
import KeyPressListener from '../../../utils/shortcutkeys/handleShortcutKeys';
|
import useModuleStore, { useThreeDStore } from "../../../store/useModuleStore";
|
||||||
import LoadingPage from '../../templates/LoadingPage';
|
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||||
import ModuleToggle from '../../ui/ModuleToggle';
|
import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
|
||||||
import SideBarLeft from '../sidebarLeft/SideBarLeft';
|
import { useFloatingWidget } from "../../../store/visualization/useDroppedObjectsStore";
|
||||||
import SideBarRight from '../sidebarRight/SideBarRight';
|
import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore";
|
||||||
import RealTimeVisulization from '../../../modules/visualization/RealTimeVisulization';
|
import KeyPressListener from "../../../utils/shortcutkeys/handleShortcutKeys";
|
||||||
import MarketPlace from '../../../modules/market/MarketPlace';
|
import LoadingPage from "../../templates/LoadingPage";
|
||||||
import Tools from '../../ui/Tools';
|
import ModuleToggle from "../../ui/ModuleToggle";
|
||||||
import SimulationPlayer from '../../ui/simulation/simulationPlayer';
|
import SideBarLeft from "../sidebarLeft/SideBarLeft";
|
||||||
import ControlsPlayer from '../controls/ControlsPlayer';
|
import SideBarRight from "../sidebarRight/SideBarRight";
|
||||||
import SelectFloorPlan from '../../temporary/SelectFloorPlan';
|
import RealTimeVisulization from "../../../modules/visualization/RealTimeVisulization";
|
||||||
import { createHandleDrop } from '../../../modules/visualization/functions/handleUiDrop';
|
import MarketPlace from "../../../modules/market/MarketPlace";
|
||||||
import Scene from '../../../modules/scene/scene';
|
import Tools from "../../ui/Tools";
|
||||||
import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore';
|
import SimulationPlayer from "../../ui/simulation/simulationPlayer";
|
||||||
import { useProductContext } from '../../../modules/simulation/products/productContext';
|
import ControlsPlayer from "../controls/ControlsPlayer";
|
||||||
import { useProductStore } from '../../../store/simulation/useProductStore';
|
import SelectFloorPlan from "../../temporary/SelectFloorPlan";
|
||||||
import RegularDropDown from '../../ui/inputs/RegularDropDown';
|
import { createHandleDrop } from "../../../modules/visualization/functions/handleUiDrop";
|
||||||
|
import Scene from "../../../modules/scene/scene";
|
||||||
|
import {
|
||||||
|
useComparisonProduct,
|
||||||
|
useMainProduct,
|
||||||
|
} from "../../../store/simulation/useSimulationStore";
|
||||||
|
import { useProductContext } from "../../../modules/simulation/products/productContext";
|
||||||
|
import { useProductStore } from "../../../store/simulation/useProductStore";
|
||||||
|
import RegularDropDown from "../../ui/inputs/RegularDropDown";
|
||||||
|
|
||||||
function MainScene() {
|
function MainScene() {
|
||||||
const { products } = useProductStore();
|
const { products } = useProductStore();
|
||||||
|
@ -65,8 +73,11 @@ function MainScene() {
|
||||||
{activeModule !== "market" && !isPlaying && !isVersionSaved && (
|
{activeModule !== "market" && !isPlaying && !isVersionSaved && (
|
||||||
<Tools />
|
<Tools />
|
||||||
)}
|
)}
|
||||||
{(isPlaying || comparisonProduct !== null) && activeModule === "simulation" && <SimulationPlayer />}
|
{(isPlaying || comparisonProduct !== null) &&
|
||||||
{(isPlaying || comparisonProduct !== null) && activeModule !== "simulation" && <ControlsPlayer />}
|
activeModule === "simulation" &&
|
||||||
|
loadingProgress == 0 && <SimulationPlayer />}
|
||||||
|
{(isPlaying || comparisonProduct !== null) &&
|
||||||
|
activeModule !== "simulation" && <ControlsPlayer />}
|
||||||
|
|
||||||
{/* remove this later */}
|
{/* remove this later */}
|
||||||
{activeModule === "builder" && !toggleThreeD && <SelectFloorPlan />}
|
{activeModule === "builder" && !toggleThreeD && <SelectFloorPlan />}
|
||||||
|
@ -108,7 +119,7 @@ function MainScene() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MainScene
|
export default MainScene;
|
||||||
|
|
|
@ -0,0 +1,213 @@
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import InputWithDropDown from "../../../../ui/inputs/InputWithDropDown";
|
||||||
|
import { AddIcon, RemoveIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
|
|
||||||
|
// Texture Imports
|
||||||
|
import wallTexture1 from "../../../../../assets/image/wallTextures/wallTexture.png";
|
||||||
|
import defaultTexture from "../../../../../assets/image/wallTextures/defaultTexture.jpg";
|
||||||
|
|
||||||
|
// Define Material type
|
||||||
|
type Material = {
|
||||||
|
texture: string;
|
||||||
|
textureName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initial and default material
|
||||||
|
const initialMaterial: Material = {
|
||||||
|
texture: wallTexture1,
|
||||||
|
textureName: "Grunge Concrete Wall",
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultMaterial: Material = {
|
||||||
|
texture: defaultTexture,
|
||||||
|
textureName: "Default Material",
|
||||||
|
};
|
||||||
|
|
||||||
|
const WallProperties = () => {
|
||||||
|
const [wallProperties, setWallProperties] = useState({
|
||||||
|
height: "10",
|
||||||
|
thickness: "10",
|
||||||
|
length: "10",
|
||||||
|
});
|
||||||
|
|
||||||
|
const [activeSide, setActiveSide] = useState<"side1" | "side2">("side1");
|
||||||
|
|
||||||
|
const [materials, setMaterials] = useState<Material[]>([initialMaterial]);
|
||||||
|
|
||||||
|
const [selectedMaterials, setSelectedMaterials] = useState<{
|
||||||
|
side1: Material | null;
|
||||||
|
side2: Material | null;
|
||||||
|
}>({
|
||||||
|
side1: null,
|
||||||
|
side2: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Select initial material for both sides on mount
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedMaterials({
|
||||||
|
side1: initialMaterial,
|
||||||
|
side2: initialMaterial,
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleInputChange = (
|
||||||
|
key: keyof typeof wallProperties,
|
||||||
|
newValue: string
|
||||||
|
) => {
|
||||||
|
setWallProperties((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[key]: newValue,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddMaterial = () => {
|
||||||
|
const newMaterial: Material = {
|
||||||
|
texture: defaultMaterial.texture,
|
||||||
|
textureName: `Material ${materials.length + 1}`,
|
||||||
|
};
|
||||||
|
setMaterials([...materials, newMaterial]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectMaterial = (material: Material) => {
|
||||||
|
setSelectedMaterials((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[activeSide]: material,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveMaterial = (index: number) => {
|
||||||
|
const updatedMaterials = materials.filter((_, i) => i !== index);
|
||||||
|
|
||||||
|
// Ensure there's always at least one material
|
||||||
|
const newMaterials =
|
||||||
|
updatedMaterials.length === 0 ? [defaultMaterial] : updatedMaterials;
|
||||||
|
setMaterials(newMaterials);
|
||||||
|
|
||||||
|
// Deselect the material if it's the one removed
|
||||||
|
setSelectedMaterials((prev) => {
|
||||||
|
const updated = { ...prev };
|
||||||
|
["side1", "side2"].forEach((side) => {
|
||||||
|
if (
|
||||||
|
updated[side as "side1" | "side2"]?.texture ===
|
||||||
|
materials[index].texture
|
||||||
|
) {
|
||||||
|
updated[side as "side1" | "side2"] = defaultMaterial;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="wall-properties-container">
|
||||||
|
<div className="header">Wall</div>
|
||||||
|
<div className="wall-properties">
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Height"
|
||||||
|
value={wallProperties.height}
|
||||||
|
onChange={(val) => handleInputChange("height", val)}
|
||||||
|
/>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Thickness"
|
||||||
|
value={wallProperties.thickness}
|
||||||
|
onChange={(val) => handleInputChange("thickness", val)}
|
||||||
|
/>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Length"
|
||||||
|
value={wallProperties.length}
|
||||||
|
onChange={(val) => handleInputChange("length", val)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<div className="header-wrapper">
|
||||||
|
<div className="header">Materials</div>
|
||||||
|
<button className="addMaterial" onClick={handleAddMaterial}>
|
||||||
|
<AddIcon />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="material-preview">
|
||||||
|
<div className="sides-wrapper">
|
||||||
|
<div
|
||||||
|
className={`side-wrapper ${
|
||||||
|
activeSide === "side1" ? "active" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => setActiveSide("side1")}
|
||||||
|
>
|
||||||
|
<div className="label">Side 1</div>
|
||||||
|
<div className="texture-image">
|
||||||
|
{selectedMaterials.side1 && (
|
||||||
|
<img
|
||||||
|
src={selectedMaterials.side1.texture}
|
||||||
|
alt={selectedMaterials.side1.textureName}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={`side-wrapper ${
|
||||||
|
activeSide === "side2" ? "active" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => setActiveSide("side2")}
|
||||||
|
>
|
||||||
|
<div className="label">Side 2</div>
|
||||||
|
<div className="texture-image">
|
||||||
|
{selectedMaterials.side2 && (
|
||||||
|
<img
|
||||||
|
src={selectedMaterials.side2.texture}
|
||||||
|
alt={selectedMaterials.side2.textureName}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="preview">
|
||||||
|
{selectedMaterials[activeSide] && (
|
||||||
|
<img
|
||||||
|
src={selectedMaterials[activeSide]!.texture}
|
||||||
|
alt={selectedMaterials[activeSide]!.textureName}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="materials">
|
||||||
|
{materials.length === 0 ? (
|
||||||
|
<div className="no-materials">No materials added yet.</div>
|
||||||
|
) : (
|
||||||
|
<div className="material-container">
|
||||||
|
{materials.map((material, index) => (
|
||||||
|
<div
|
||||||
|
className="material-wrapper"
|
||||||
|
key={`${material.textureName}_${index}`}
|
||||||
|
onClick={() => handleSelectMaterial(material)}
|
||||||
|
>
|
||||||
|
<div className="material-property">
|
||||||
|
<div className="material-image">
|
||||||
|
<img src={material.texture} alt={material.textureName} />
|
||||||
|
</div>
|
||||||
|
<div className="material-name">{material.textureName}</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="delete-material"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleRemoveMaterial(index);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RemoveIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WallProperties;
|
|
@ -4,6 +4,7 @@ import { LogoIconLarge } from "../icons/Logo";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useProjectName } from "../../store/builder/store";
|
import { useProjectName } from "../../store/builder/store";
|
||||||
import { getAllProjects } from "../../services/dashboard/getAllProjects";
|
import { getAllProjects } from "../../services/dashboard/getAllProjects";
|
||||||
|
import { useComparisonProduct } from "../../store/simulation/useSimulationStore";
|
||||||
|
|
||||||
interface LoadingPageProps {
|
interface LoadingPageProps {
|
||||||
progress: number; // Expect progress as a percentage (0-100)
|
progress: number; // Expect progress as a percentage (0-100)
|
||||||
|
@ -12,6 +13,8 @@ interface LoadingPageProps {
|
||||||
const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
|
const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
|
||||||
const { projectName, setProjectName } = useProjectName();
|
const { projectName, setProjectName } = useProjectName();
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
|
const { comparisonProduct } = useComparisonProduct();
|
||||||
|
|
||||||
const validatedProgress = Math.min(100, Math.max(0, progress));
|
const validatedProgress = Math.min(100, Math.max(0, progress));
|
||||||
const generateThumbnail = async () => {
|
const generateThumbnail = async () => {
|
||||||
const email = localStorage.getItem("email");
|
const email = localStorage.getItem("email");
|
||||||
|
@ -30,25 +33,24 @@ const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
|
||||||
|
|
||||||
const domainParts = emailParts[1].split(".");
|
const domainParts = emailParts[1].split(".");
|
||||||
const Organization = domainParts[0];
|
const Organization = domainParts[0];
|
||||||
const projects = await getAllProjects(
|
const projects = await getAllProjects(userId, Organization);
|
||||||
userId, Organization
|
const filterProject = projects?.Projects.find(
|
||||||
|
(val: any) => val.projectUuid === projectId || val._id === projectId
|
||||||
);
|
);
|
||||||
const filterProject = projects?.Projects.find((val: any) => val.projectUuid === projectId || val._id
|
|
||||||
=== projectId)
|
|
||||||
|
|
||||||
setProjectName(filterProject.projectName)
|
setProjectName(filterProject.projectName);
|
||||||
|
} catch {}
|
||||||
}
|
};
|
||||||
catch {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
generateThumbnail();
|
generateThumbnail();
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<RenderOverlay>
|
<RenderOverlay>
|
||||||
<div className="loading-wrapper">
|
<div
|
||||||
|
className={`loading-wrapper ${
|
||||||
|
comparisonProduct != null ? "comparisionLoading" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<div className="loading-container">
|
<div className="loading-container">
|
||||||
<div className="project-name">{projectName}</div>
|
<div className="project-name">{projectName}</div>
|
||||||
<div className="loading-hero-container">
|
<div className="loading-hero-container">
|
||||||
|
|
|
@ -4,7 +4,10 @@ import {
|
||||||
LayoutIcon,
|
LayoutIcon,
|
||||||
ResizerIcon,
|
ResizerIcon,
|
||||||
} from "../../icons/SimulationIcons";
|
} from "../../icons/SimulationIcons";
|
||||||
import { useLoadingProgress, useSaveVersion } from "../../../store/builder/store";
|
import {
|
||||||
|
useLoadingProgress,
|
||||||
|
useSaveVersion,
|
||||||
|
} from "../../../store/builder/store";
|
||||||
import Search from "../inputs/Search";
|
import Search from "../inputs/Search";
|
||||||
import OuterClick from "../../../utils/outerClick";
|
import OuterClick from "../../../utils/outerClick";
|
||||||
import { useProductStore } from "../../../store/simulation/useProductStore";
|
import { useProductStore } from "../../../store/simulation/useProductStore";
|
||||||
|
@ -13,7 +16,8 @@ import { useComparisonProduct } from "../../../store/simulation/useSimulationSto
|
||||||
import { usePauseButtonStore, usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
import { usePauseButtonStore, usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||||
|
|
||||||
const CompareLayOut = () => {
|
const CompareLayOut = () => {
|
||||||
const { comparisonProduct, setComparisonProduct, clearComparisonProduct } = useComparisonProduct();
|
const { comparisonProduct, setComparisonProduct, clearComparisonProduct } =
|
||||||
|
useComparisonProduct();
|
||||||
const { products } = useProductStore();
|
const { products } = useProductStore();
|
||||||
const { setLoadingProgress } = useLoadingProgress();
|
const { setLoadingProgress } = useLoadingProgress();
|
||||||
const [width, setWidth] = useState("50vw");
|
const [width, setWidth] = useState("50vw");
|
||||||
|
@ -23,6 +27,7 @@ const CompareLayOut = () => {
|
||||||
const startWidthRef = useRef<number>(0);
|
const startWidthRef = useRef<number>(0);
|
||||||
const startXRef = useRef<number>(0);
|
const startXRef = useRef<number>(0);
|
||||||
const { setIsVersionSaved } = useSaveVersion();
|
const { setIsVersionSaved } = useSaveVersion();
|
||||||
|
const { loadingProgress } = useLoadingProgress();
|
||||||
const { setIsPlaying } = usePlayButtonStore();
|
const { setIsPlaying } = usePlayButtonStore();
|
||||||
const { setIsPaused } = usePauseButtonStore();
|
const { setIsPaused } = usePauseButtonStore();
|
||||||
|
|
||||||
|
@ -124,6 +129,7 @@ const CompareLayOut = () => {
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
style={{ width }}
|
style={{ width }}
|
||||||
>
|
>
|
||||||
|
{loadingProgress == 0 && (
|
||||||
<button
|
<button
|
||||||
title="resize-canvas"
|
title="resize-canvas"
|
||||||
id="compare-resize-slider-btn"
|
id="compare-resize-slider-btn"
|
||||||
|
@ -132,6 +138,7 @@ const CompareLayOut = () => {
|
||||||
>
|
>
|
||||||
<ResizerIcon />
|
<ResizerIcon />
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
<div className="chooseLayout-container">
|
<div className="chooseLayout-container">
|
||||||
{comparisonProduct && (
|
{comparisonProduct && (
|
||||||
<div className="compare-layout-canvas-container">
|
<div className="compare-layout-canvas-container">
|
||||||
|
@ -158,7 +165,7 @@ const CompareLayOut = () => {
|
||||||
{showLayoutDropdown && (
|
{showLayoutDropdown && (
|
||||||
<div className="displayLayouts-container">
|
<div className="displayLayouts-container">
|
||||||
<div className="header">Layouts</div>
|
<div className="header">Layouts</div>
|
||||||
<Search onChange={() => { }} />
|
<Search onChange={() => {}} />
|
||||||
<div className="layouts-container">
|
<div className="layouts-container">
|
||||||
{products.map((layout) => (
|
{products.map((layout) => (
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -2,16 +2,19 @@ import React from "react";
|
||||||
import MachineInstance from "./machineInstance/machineInstance";
|
import MachineInstance from "./machineInstance/machineInstance";
|
||||||
import MachineContentUi from "../../ui3d/MachineContentUi";
|
import MachineContentUi from "../../ui3d/MachineContentUi";
|
||||||
import { useSceneContext } from "../../../scene/sceneContext";
|
import { useSceneContext } from "../../../scene/sceneContext";
|
||||||
|
import { useViewSceneStore } from "../../../../store/builder/store";
|
||||||
|
|
||||||
function MachineInstances() {
|
function MachineInstances() {
|
||||||
const { machineStore } = useSceneContext();
|
const { machineStore } = useSceneContext();
|
||||||
const { machines } = machineStore();
|
const { machines } = machineStore();
|
||||||
|
const { viewSceneLabels } = useViewSceneStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{machines.map((machine: MachineStatus) => (
|
{machines.map((machine: MachineStatus) => (
|
||||||
<React.Fragment key={machine.modelUuid}>
|
<React.Fragment key={machine.modelUuid}>
|
||||||
<MachineInstance machineDetail={machine} />
|
<MachineInstance machineDetail={machine} />
|
||||||
<MachineContentUi machine={machine} />
|
{viewSceneLabels && <MachineContentUi machine={machine} />}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
import React from 'react'
|
import React from "react";
|
||||||
import StorageUnitInstance from './storageUnitInstance/storageUnitInstance'
|
import StorageUnitInstance from "./storageUnitInstance/storageUnitInstance";
|
||||||
import StorageContentUi from '../../ui3d/StorageContentUi';
|
import StorageContentUi from "../../ui3d/StorageContentUi";
|
||||||
import { useSceneContext } from '../../../scene/sceneContext';
|
import { useSceneContext } from "../../../scene/sceneContext";
|
||||||
|
import { useViewSceneStore } from "../../../../store/builder/store";
|
||||||
|
|
||||||
function StorageUnitInstances() {
|
function StorageUnitInstances() {
|
||||||
const { storageUnitStore } = useSceneContext();
|
const { storageUnitStore } = useSceneContext();
|
||||||
const { storageUnits } = storageUnitStore();
|
const { storageUnits } = storageUnitStore();
|
||||||
|
const { viewSceneLabels } = useViewSceneStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{storageUnits.map((storageUnit: StorageUnitStatus) => (
|
{storageUnits.map((storageUnit: StorageUnitStatus) => (
|
||||||
<React.Fragment key={storageUnit.modelUuid}>
|
<React.Fragment key={storageUnit.modelUuid}>
|
||||||
<StorageUnitInstance storageUnit={storageUnit} />
|
<StorageUnitInstance storageUnit={storageUnit} />
|
||||||
<StorageContentUi storageUnit={storageUnit} />
|
{viewSceneLabels && <StorageContentUi storageUnit={storageUnit} />}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default StorageUnitInstances
|
export default StorageUnitInstances;
|
||||||
|
|
|
@ -2,17 +2,19 @@ import React from "react";
|
||||||
import VehicleInstance from "./instance/vehicleInstance";
|
import VehicleInstance from "./instance/vehicleInstance";
|
||||||
import VehicleContentUi from "../../ui3d/VehicleContentUi";
|
import VehicleContentUi from "../../ui3d/VehicleContentUi";
|
||||||
import { useSceneContext } from "../../../scene/sceneContext";
|
import { useSceneContext } from "../../../scene/sceneContext";
|
||||||
|
import { useViewSceneStore } from "../../../../store/builder/store";
|
||||||
|
|
||||||
function VehicleInstances() {
|
function VehicleInstances() {
|
||||||
const { vehicleStore } = useSceneContext();
|
const { vehicleStore } = useSceneContext();
|
||||||
const { vehicles } = vehicleStore();
|
const { vehicles } = vehicleStore();
|
||||||
|
const { viewSceneLabels } = useViewSceneStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{vehicles.map((vehicle: VehicleStatus) => (
|
{vehicles.map((vehicle: VehicleStatus) => (
|
||||||
<React.Fragment key={vehicle.modelUuid}>
|
<React.Fragment key={vehicle.modelUuid}>
|
||||||
<VehicleInstance agvDetail={vehicle} />
|
<VehicleInstance agvDetail={vehicle} />
|
||||||
<VehicleContentUi vehicle={vehicle} />
|
{viewSceneLabels && <VehicleContentUi vehicle={vehicle} />}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
useUserName,
|
useUserName,
|
||||||
useWallItems,
|
useWallItems,
|
||||||
useSaveVersion,
|
useSaveVersion,
|
||||||
|
useViewSceneStore,
|
||||||
useProjectName,
|
useProjectName,
|
||||||
useRenameModeStore,
|
useRenameModeStore,
|
||||||
useSelectedFloorItem,
|
useSelectedFloorItem,
|
||||||
|
|
|
@ -680,3 +680,31 @@ export const useVersionStore = create<VersionListStore>((set) => ({
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface ViewSceneState {
|
||||||
|
viewSceneLabels: boolean;
|
||||||
|
setViewSceneLabels: (value: boolean | ((prev: boolean) => boolean)) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useViewSceneStore = create<ViewSceneState>((set) => ({
|
||||||
|
viewSceneLabels: getInitialViewSceneLabels(),
|
||||||
|
setViewSceneLabels: (value) => {
|
||||||
|
set((state) => {
|
||||||
|
const newValue =
|
||||||
|
typeof value === 'function' ? value(state.viewSceneLabels) : value;
|
||||||
|
|
||||||
|
// Store in localStorage manually
|
||||||
|
localStorage.setItem('viewSceneLabels', JSON.stringify(newValue));
|
||||||
|
|
||||||
|
return { viewSceneLabels: newValue };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
function getInitialViewSceneLabels(): boolean {
|
||||||
|
if (typeof window === 'undefined') return false; // SSR safety
|
||||||
|
const saved = localStorage.getItem('viewSceneLabels');
|
||||||
|
return saved ? JSON.parse(saved) : false;
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ textarea {
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="number"] {
|
input[type="number"] {
|
||||||
|
|
||||||
// Chrome, Safari, Edge, Opera
|
// Chrome, Safari, Edge, Opera
|
||||||
&::-webkit-outer-spin-button,
|
&::-webkit-outer-spin-button,
|
||||||
&::-webkit-inner-spin-button {
|
&::-webkit-inner-spin-button {
|
||||||
|
@ -146,6 +147,7 @@ input[type="number"] {
|
||||||
border-radius: #{$border-radius-large};
|
border-radius: #{$border-radius-large};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--background-color-secondary);
|
background: var(--background-color-secondary);
|
||||||
}
|
}
|
||||||
|
@ -337,6 +339,7 @@ input[type="number"] {
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #333333;
|
background: #333333;
|
||||||
}
|
}
|
||||||
|
@ -413,6 +416,7 @@ input[type="number"] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
border-radius: #{$border-radius-large};
|
border-radius: #{$border-radius-large};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
background: var(--highlight-accent-color);
|
background: var(--highlight-accent-color);
|
||||||
|
@ -483,6 +487,7 @@ input[type="number"] {
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
|
||||||
.check-box-style {
|
.check-box-style {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
@ -714,21 +719,26 @@ input[type="number"] {
|
||||||
.input-header-container {
|
.input-header-container {
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
@include flex-space-between;
|
@include flex-space-between;
|
||||||
|
|
||||||
.arrow-container {
|
.arrow-container {
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-custom-asset-button {
|
.upload-custom-asset-button {
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
@include flex-space-between;
|
@include flex-space-between;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-button {
|
.upload-button {
|
||||||
width: 60%;
|
width: 60%;
|
||||||
background: var(--highlight-accent-color);
|
background: var(--highlight-accent-color);
|
||||||
|
@ -738,6 +748,7 @@ input[type="number"] {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.canvas-wrapper {
|
.canvas-wrapper {
|
||||||
height: 150px;
|
height: 150px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -745,6 +756,7 @@ input[type="number"] {
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.canvas-container {
|
.canvas-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
transition: transform 0.1s ease;
|
transition: transform 0.1s ease;
|
||||||
z-index: 10;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chooseLayout-container {
|
.chooseLayout-container {
|
||||||
|
@ -161,9 +161,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(
|
background-color: var(--highlight-text-color) !important;
|
||||||
--highlight-text-color
|
|
||||||
) !important;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
|
@ -254,6 +252,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-value {
|
.metric-value {
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
font-size: var(--font-size-xlarge);
|
font-size: var(--font-size-xlarge);
|
||||||
|
@ -289,6 +288,7 @@
|
||||||
top: -57%;
|
top: -57%;
|
||||||
left: 220%;
|
left: 220%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -300,21 +300,19 @@
|
||||||
background-color: #b7b7c6;
|
background-color: #b7b7c6;
|
||||||
|
|
||||||
// Custom polygon shape (adjust if needed)
|
// Custom polygon shape (adjust if needed)
|
||||||
clip-path: polygon(
|
clip-path: polygon(96% 52%,
|
||||||
96% 52%,
|
|
||||||
96% 54%,
|
96% 54%,
|
||||||
45% 53%,
|
45% 53%,
|
||||||
3% 100%,
|
3% 100%,
|
||||||
0 100%,
|
0 100%,
|
||||||
42% 52%
|
42% 52%);
|
||||||
);
|
|
||||||
|
|
||||||
z-index: 0; // Behind any inner content
|
z-index: 0; // Behind any inner content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional: content above the shape
|
// Optional: content above the shape
|
||||||
> * {
|
>* {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
@ -322,12 +320,14 @@
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
grid-column-start: 1;
|
grid-column-start: 1;
|
||||||
grid-row-start: 2;
|
grid-row-start: 2;
|
||||||
|
|
||||||
.metric-label {
|
.metric-label {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
left: 230%;
|
left: 230%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(3) {
|
&:nth-child(3) {
|
||||||
grid-row: span 2 / span 2;
|
grid-row: span 2 / span 2;
|
||||||
grid-column-start: 2;
|
grid-column-start: 2;
|
||||||
|
@ -367,21 +367,19 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
background: var(--background-color, wheat);
|
background: var(--background-color, wheat);
|
||||||
clip-path: polygon(
|
clip-path: polygon(25% 0%,
|
||||||
25% 0%,
|
|
||||||
75% 0%,
|
75% 0%,
|
||||||
100% 50%,
|
100% 50%,
|
||||||
75% 100%,
|
75% 100%,
|
||||||
25% 100%,
|
25% 100%,
|
||||||
0% 50%
|
0% 50%);
|
||||||
);
|
|
||||||
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.25));
|
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.25));
|
||||||
|
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content stays above the shape
|
// Content stays above the shape
|
||||||
> * {
|
>* {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,16 @@
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
background: var(--background-color-solid);
|
background: var(--background-color-solid);
|
||||||
|
|
||||||
|
&.comparisionLoading {
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
height: 100vh;
|
||||||
|
width: 50vw;
|
||||||
|
}
|
||||||
|
|
||||||
.loading-container {
|
.loading-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -59,6 +69,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-container {
|
.progress-container {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
.progress-value {
|
.progress-value {
|
||||||
font-family: #{$font-josefin-sans};
|
font-family: #{$font-josefin-sans};
|
||||||
font-weight: #{$thin-weight};
|
font-weight: #{$thin-weight};
|
||||||
|
@ -69,7 +85,7 @@
|
||||||
|
|
||||||
.progress-indicator-container {
|
.progress-indicator-container {
|
||||||
height: 6px;
|
height: 6px;
|
||||||
width: 60vw;
|
width: 60%;
|
||||||
background: var(--highlight-accent-color);
|
background: var(--highlight-accent-color);
|
||||||
border-radius: #{$border-radius-small};
|
border-radius: #{$border-radius-small};
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -4,11 +4,21 @@
|
||||||
.distance-text-wrapper,
|
.distance-text-wrapper,
|
||||||
.zone-name-wrapper,
|
.zone-name-wrapper,
|
||||||
.pointer-none {
|
.pointer-none {
|
||||||
pointer-events: none !important;
|
pointer-events: auto !important;
|
||||||
|
background-color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zone-name-wrapper {
|
||||||
|
background: var(--background-color-accent);
|
||||||
|
color: var(--text-button-color);
|
||||||
|
outline: 1px solid var(--border-color);
|
||||||
|
border-radius: #{$border-radius-medium};
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.distance-text {
|
.distance-text {
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transform: translate(-50%, -50%) scale(0.8);
|
transform: translate(-50%, -50%) scale(0.8);
|
||||||
|
@ -22,18 +32,16 @@
|
||||||
border-radius: #{$border-radius-medium};
|
border-radius: #{$border-radius-medium};
|
||||||
box-shadow: var(--box-shadow-light);
|
box-shadow: var(--box-shadow-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.area {
|
.area {
|
||||||
background: #008cff;
|
background: #008cff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.zone-name{
|
.zone-name {
|
||||||
background: var(--background-color);
|
padding: 2px 10px;
|
||||||
padding: 2px 8px;
|
|
||||||
text-wrap: nowrap;
|
text-wrap: nowrap;
|
||||||
backdrop-filter: blur(12px);
|
color: var(--text-button-color);
|
||||||
border-radius: #{$border-radius-medium};
|
|
||||||
outline: 1px solid var(--border-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -54,19 +62,55 @@
|
||||||
border-radius: #{$border-radius-large};
|
border-radius: #{$border-radius-large};
|
||||||
outline: 1px solid var(--border-color);
|
outline: 1px solid var(--border-color);
|
||||||
transform: translate(-50%, 12px);
|
transform: translate(-50%, 12px);
|
||||||
z-index: 100;
|
z-index: 2;
|
||||||
|
|
||||||
.presets-container {
|
.presets-container {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|
||||||
.preset {
|
.preset {
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
border-radius: #{$border-radius-large};
|
border-radius: #{$border-radius-large};
|
||||||
outline: 1px solid var(--border-color);
|
outline: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
background: var(--background-color-accent);
|
background: var(--background-color-accent);
|
||||||
color: var(--text-button-color);
|
color: var(--text-button-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.label-toogler {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 4%;
|
||||||
|
right: 1.5%;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
// background: var(--background-color);
|
||||||
|
// backdrop-filter: blur(10px);
|
||||||
|
// outline: 1px solid var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.input-toggle-container {
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: end;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.check-box {
|
||||||
|
width: 35px;
|
||||||
|
height: 20px;
|
||||||
|
|
||||||
|
.check-box-style {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background: var(--text-button-color) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import {
|
||||||
useShortcutStore,
|
useShortcutStore,
|
||||||
useToggleView,
|
useToggleView,
|
||||||
useToolMode,
|
useToolMode,
|
||||||
|
useViewSceneStore,
|
||||||
} from "../../store/builder/store";
|
} from "../../store/builder/store";
|
||||||
import useCameraModeStore, {
|
import useCameraModeStore, {
|
||||||
usePlayButtonStore,
|
usePlayButtonStore,
|
||||||
|
@ -41,6 +42,7 @@ const KeyPressListener: React.FC = () => {
|
||||||
const { setIsVersionSaved } = useSaveVersion();
|
const { setIsVersionSaved } = useSaveVersion();
|
||||||
const { isLogListVisible, setIsLogListVisible } = useLogger();
|
const { isLogListVisible, setIsLogListVisible } = useLogger();
|
||||||
const { hidePlayer, setHidePlayer } = usePlayerStore();
|
const { hidePlayer, setHidePlayer } = usePlayerStore();
|
||||||
|
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
|
||||||
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
|
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
|
||||||
const { selectedFloorItem } = useSelectedFloorItem();
|
const { selectedFloorItem } = useSelectedFloorItem();
|
||||||
|
|
||||||
|
@ -158,6 +160,12 @@ const KeyPressListener: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleKeyPress = (event: KeyboardEvent) => {
|
const handleKeyPress = (event: KeyboardEvent) => {
|
||||||
|
console.log(
|
||||||
|
"isTextInput(document.activeElement): ",
|
||||||
|
isTextInput(document.activeElement)
|
||||||
|
);
|
||||||
|
if (isTextInput(document.activeElement)) return;
|
||||||
|
|
||||||
const keyCombination = detectModifierKeys(event);
|
const keyCombination = detectModifierKeys(event);
|
||||||
|
|
||||||
if (isTextInput(document.activeElement) && keyCombination !== "ESCAPE")
|
if (isTextInput(document.activeElement) && keyCombination !== "ESCAPE")
|
||||||
|
@ -183,6 +191,7 @@ const KeyPressListener: React.FC = () => {
|
||||||
keyCombination === "Ctrl+R"
|
keyCombination === "Ctrl+R"
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
console.log("keyCombination: ", keyCombination);
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
@ -211,6 +220,10 @@ const KeyPressListener: React.FC = () => {
|
||||||
if (keyCombination === "Ctrl+Shift+?") {
|
if (keyCombination === "Ctrl+Shift+?") {
|
||||||
setShowShortcuts(!showShortcuts);
|
setShowShortcuts(!showShortcuts);
|
||||||
}
|
}
|
||||||
|
if (keyCombination === "U") {
|
||||||
|
console.log("viewSceneLabels: ", viewSceneLabels);
|
||||||
|
setViewSceneLabels((prev) => !prev);
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedFloorItem && keyCombination === "F2") {
|
if (selectedFloorItem && keyCombination === "F2") {
|
||||||
setIsRenameMode(true);
|
setIsRenameMode(true);
|
||||||
|
|
Loading…
Reference in New Issue