Merge branch 'main' into realTimeVisulization
This commit is contained in:
commit
5cc3b83e43
app
.gitignorepackage-lock.json
src
components
modules/builder/groups
pages
styles
|
@ -1,29 +1,29 @@
|
||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
/package-lock.json
|
/package-lock.json
|
||||||
/.pnp
|
/.pnp
|
||||||
.pnp.js
|
.pnp.js
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env.local
|
.env.local
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
|
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
|
|
||||||
# remove zip
|
# remove zip
|
||||||
*.zip
|
*.zip
|
||||||
**/temp/
|
**/temp/
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -107,7 +107,7 @@ export function StockIncreseIcon() {
|
||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<g clip-path="url(#clip0_3050_69519)">
|
<g clipPath="url(#clip0_3050_69519)">
|
||||||
<path
|
<path
|
||||||
d="M7.80766 6.99219H1.17811C0.752382 6.99219 0.407227 7.33734 0.407227 7.76307C0.407227 8.18879 0.752382 8.53395 1.17811 8.53395H7.80766C8.23339 8.53395 8.57854 8.18879 8.57854 7.76307C8.57854 7.33733 8.23339 6.99219 7.80766 6.99219Z"
|
d="M7.80766 6.99219H1.17811C0.752382 6.99219 0.407227 7.33734 0.407227 7.76307C0.407227 8.18879 0.752382 8.53395 1.17811 8.53395H7.80766C8.23339 8.53395 8.57854 8.18879 8.57854 7.76307C8.57854 7.33733 8.23339 6.99219 7.80766 6.99219Z"
|
||||||
fill="white"
|
fill="white"
|
||||||
|
@ -142,8 +142,8 @@ export function StockIncreseIcon() {
|
||||||
y2="8.53122"
|
y2="8.53122"
|
||||||
gradientUnits="userSpaceOnUse"
|
gradientUnits="userSpaceOnUse"
|
||||||
>
|
>
|
||||||
<stop stop-color="#31B2B9" />
|
<stop stopColor="#31B2B9" />
|
||||||
<stop offset="1" stop-color="#FBD8B8" />
|
<stop offset="1" stopColor="#FBD8B8" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<clipPath id="clip0_3050_69519">
|
<clipPath id="clip0_3050_69519">
|
||||||
<rect
|
<rect
|
||||||
|
|
|
@ -3,9 +3,12 @@ import { ToggleSidebarIcon } from "../../icons/HeaderIcons";
|
||||||
import { LogoIcon } from "../../icons/Logo";
|
import { LogoIcon } from "../../icons/Logo";
|
||||||
import FileMenu from "../../ui/FileMenu";
|
import FileMenu from "../../ui/FileMenu";
|
||||||
import useToggleStore from "../../../store/useUIToggleStore";
|
import useToggleStore from "../../../store/useUIToggleStore";
|
||||||
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
|
|
||||||
const Header: React.FC = () => {
|
const Header: React.FC = () => {
|
||||||
const { toggleUI, setToggleUI } = useToggleStore();
|
const { toggleUI, setToggleUI } = useToggleStore();
|
||||||
|
const { activeModule } = useModuleStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="header-container">
|
<div className="header-container">
|
||||||
<div className="header-content">
|
<div className="header-content">
|
||||||
|
@ -19,7 +22,7 @@ const Header: React.FC = () => {
|
||||||
<div
|
<div
|
||||||
className={`toggle-sidebar-ui-button ${!toggleUI ? "active" : ""}`}
|
className={`toggle-sidebar-ui-button ${!toggleUI ? "active" : ""}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setToggleUI(!toggleUI);
|
if (activeModule !== "market") setToggleUI(!toggleUI);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ToggleSidebarIcon />
|
<ToggleSidebarIcon />
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Header from "./Header";
|
import Header from "./Header";
|
||||||
import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore";
|
import useModuleStore, {
|
||||||
|
useSubModuleStore,
|
||||||
|
} from "../../../store/useModuleStore";
|
||||||
import {
|
import {
|
||||||
AnalysisIcon,
|
AnalysisIcon,
|
||||||
MechanicsIcon,
|
MechanicsIcon,
|
||||||
|
@ -15,6 +17,7 @@ import AsstePropertiies from "./properties/AssetProperties";
|
||||||
import Analysis from "./analysis/Analysis";
|
import Analysis from "./analysis/Analysis";
|
||||||
import Simulations from "./simulation/Simulations";
|
import Simulations from "./simulation/Simulations";
|
||||||
import { useSelectedActionSphere } from "../../../store/store";
|
import { useSelectedActionSphere } from "../../../store/store";
|
||||||
|
import ZoneProperties from "./properties/ZoneProperties";
|
||||||
|
|
||||||
const SideBarRight: React.FC = () => {
|
const SideBarRight: React.FC = () => {
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
@ -24,7 +27,8 @@ const SideBarRight: React.FC = () => {
|
||||||
|
|
||||||
// Reset subModule whenever activeModule changes
|
// Reset subModule whenever activeModule changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSubModule("properties");
|
if (activeModule !== "simulation") setSubModule("properties");
|
||||||
|
if (activeModule === "simulation") setSubModule("mechanics");
|
||||||
}, [activeModule]);
|
}, [activeModule]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -32,32 +36,38 @@ const SideBarRight: React.FC = () => {
|
||||||
<Header />
|
<Header />
|
||||||
{toggleUI && (
|
{toggleUI && (
|
||||||
<div className="sidebar-actions-container">
|
<div className="sidebar-actions-container">
|
||||||
<div
|
{/* {activeModule === "builder" && ( */}
|
||||||
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""
|
<div
|
||||||
|
className={`sidebar-action-list ${
|
||||||
|
subModule === "properties" ? "active" : ""
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setSubModule("properties")}
|
onClick={() => setSubModule("properties")}
|
||||||
>
|
>
|
||||||
<PropertiesIcon isActive={subModule === "properties"} />
|
<PropertiesIcon isActive={subModule === "properties"} />
|
||||||
</div>
|
</div>
|
||||||
|
{/* )} */}
|
||||||
{activeModule === "simulation" && (
|
{activeModule === "simulation" && (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
|
className={`sidebar-action-list ${
|
||||||
}`}
|
subModule === "mechanics" ? "active" : ""
|
||||||
|
}`}
|
||||||
onClick={() => setSubModule("mechanics")}
|
onClick={() => setSubModule("mechanics")}
|
||||||
>
|
>
|
||||||
<MechanicsIcon isActive={subModule === "mechanics"} />
|
<MechanicsIcon isActive={subModule === "mechanics"} />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
|
className={`sidebar-action-list ${
|
||||||
}`}
|
subModule === "simulations" ? "active" : ""
|
||||||
|
}`}
|
||||||
onClick={() => setSubModule("simulations")}
|
onClick={() => setSubModule("simulations")}
|
||||||
>
|
>
|
||||||
<SimulationIcon isActive={subModule === "simulations"} />
|
<SimulationIcon isActive={subModule === "simulations"} />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
|
className={`sidebar-action-list ${
|
||||||
}`}
|
subModule === "analysis" ? "active" : ""
|
||||||
|
}`}
|
||||||
onClick={() => setSubModule("analysis")}
|
onClick={() => setSubModule("analysis")}
|
||||||
>
|
>
|
||||||
<AnalysisIcon isActive={subModule === "analysis"} />
|
<AnalysisIcon isActive={subModule === "analysis"} />
|
||||||
|
@ -73,6 +83,7 @@ const SideBarRight: React.FC = () => {
|
||||||
<div className="sidebar-right-container">
|
<div className="sidebar-right-container">
|
||||||
<div className="sidebar-right-content-container">
|
<div className="sidebar-right-content-container">
|
||||||
<GlobalProperties />
|
<GlobalProperties />
|
||||||
|
{/* <ZoneProperties /> */}
|
||||||
{/* <AsstePropertiies /> */}
|
{/* <AsstePropertiies /> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -82,17 +93,17 @@ const SideBarRight: React.FC = () => {
|
||||||
|
|
||||||
{toggleUI && activeModule === "simulation" && (
|
{toggleUI && activeModule === "simulation" && (
|
||||||
<>
|
<>
|
||||||
{(subModule === "mechanics" && selectedActionSphere) && (
|
{subModule === "mechanics" && selectedActionSphere && (
|
||||||
<div className="sidebar-right-container">
|
<div className="sidebar-right-container">
|
||||||
<div className="sidebar-right-content-container">
|
<div className="sidebar-right-content-container">
|
||||||
<MachineMechanics />
|
<MachineMechanics />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{(subModule === "mechanics" && !selectedActionSphere) && (
|
{subModule === "mechanics" && !selectedActionSphere && (
|
||||||
<div className="sidebar-right-container">
|
<div className="sidebar-right-container">
|
||||||
<div className="sidebar-right-content-container">
|
<div className="sidebar-right-content-container">
|
||||||
{/* <MachineMechanics /> */}
|
<MachineMechanics />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import React from "react";
|
||||||
|
import { EyeDroperIcon } from "../../../icons/ExportCommonIcons";
|
||||||
|
|
||||||
|
interface PositionInputProps {
|
||||||
|
onChange: (value: string) => void; // Callback for value change
|
||||||
|
header: string;
|
||||||
|
placeholder?: string; // Optional placeholder
|
||||||
|
type?: string; // Input type (e.g., text, number, email)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector3Input: React.FC<PositionInputProps> = ({
|
||||||
|
onChange,
|
||||||
|
header,
|
||||||
|
placeholder = "Enter value", // Default placeholder
|
||||||
|
type = "number", // Default type
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="custom-input-container">
|
||||||
|
<div className="header">
|
||||||
|
{header}{" "}
|
||||||
|
<div className="eyedrop-button">
|
||||||
|
<EyeDroperIcon isActive={false} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="inputs-container">
|
||||||
|
<div className="input-container">
|
||||||
|
<div className="custom-input-label">X : </div>
|
||||||
|
<input
|
||||||
|
className="custom-input-field"
|
||||||
|
type={type}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
placeholder={placeholder}
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-container">
|
||||||
|
<div className="custom-input-label">Y : </div>
|
||||||
|
<input
|
||||||
|
className="custom-input-field"
|
||||||
|
type={type}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
placeholder={placeholder}
|
||||||
|
disabled
|
||||||
|
min={0}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-container">
|
||||||
|
<div className="custom-input-label">Z : </div>
|
||||||
|
<input
|
||||||
|
className="custom-input-field"
|
||||||
|
type={type}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
placeholder={placeholder}
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Vector3Input;
|
|
@ -14,8 +14,8 @@ import EyeDropInput from "../../../ui/inputs/EyeDropInput";
|
||||||
import { useSelectedActionSphere } from "../../../../store/store";
|
import { useSelectedActionSphere } from "../../../../store/store";
|
||||||
|
|
||||||
const MachineMechanics: React.FC = () => {
|
const MachineMechanics: React.FC = () => {
|
||||||
const { selectedActionSphere, setSelectedActionSphere } = useSelectedActionSphere();
|
const { selectedActionSphere } = useSelectedActionSphere();
|
||||||
console.log('selectedActionSphere: ', selectedActionSphere);
|
console.log("selectedActionSphere: ", selectedActionSphere);
|
||||||
const [actionList, setActionList] = useState<string[]>([]);
|
const [actionList, setActionList] = useState<string[]>([]);
|
||||||
const [triggerList, setTriggerList] = useState<string[]>([]);
|
const [triggerList, setTriggerList] = useState<string[]>([]);
|
||||||
const [selectedItem, setSelectedItem] = useState<{
|
const [selectedItem, setSelectedItem] = useState<{
|
||||||
|
@ -71,7 +71,9 @@ const MachineMechanics: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="machine-mechanics-container">
|
<div className="machine-mechanics-container">
|
||||||
<div className="machine-mechanics-header">{selectedActionSphere.path.modelName}</div>
|
<div className="machine-mechanics-header">
|
||||||
|
{selectedActionSphere?.path?.modelName || "path name not found"}
|
||||||
|
</div>
|
||||||
{/* <div className="process-list-container">
|
{/* <div className="process-list-container">
|
||||||
<div className="label">Process:</div>
|
<div className="label">Process:</div>
|
||||||
<RegularDropDown
|
<RegularDropDown
|
||||||
|
@ -100,11 +102,12 @@ const MachineMechanics: React.FC = () => {
|
||||||
{actionList.map((action, index) => (
|
{actionList.map((action, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={`list-item ${selectedItem?.type === "action" &&
|
className={`list-item ${
|
||||||
|
selectedItem?.type === "action" &&
|
||||||
selectedItem.name === action
|
selectedItem.name === action
|
||||||
? "active"
|
? "active"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="value"
|
className="value"
|
||||||
|
@ -146,11 +149,12 @@ const MachineMechanics: React.FC = () => {
|
||||||
{triggerList.map((trigger, index) => (
|
{triggerList.map((trigger, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={`list-item ${selectedItem?.type === "trigger" &&
|
className={`list-item ${
|
||||||
|
selectedItem?.type === "trigger" &&
|
||||||
selectedItem.name === trigger
|
selectedItem.name === trigger
|
||||||
? "active"
|
? "active"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="value"
|
className="value"
|
||||||
|
@ -188,7 +192,7 @@ const MachineMechanics: React.FC = () => {
|
||||||
label="Speed"
|
label="Speed"
|
||||||
value=""
|
value=""
|
||||||
activeOption=".mm"
|
activeOption=".mm"
|
||||||
onChange={() => { }}
|
onChange={() => {}}
|
||||||
/>
|
/>
|
||||||
<EyeDropInput />
|
<EyeDropInput />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||||
|
import Vector3Input from "../customInput/Vector3Input";
|
||||||
|
|
||||||
|
const ZoneProperties: React.FC = () => {
|
||||||
|
const [Edit, setEdit] = useState(false);
|
||||||
|
|
||||||
|
function handleSetView() {
|
||||||
|
setEdit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEditView() {
|
||||||
|
if (Edit) {
|
||||||
|
setEdit(false);
|
||||||
|
} else {
|
||||||
|
setEdit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="zone-properties-container">
|
||||||
|
<div className="header">
|
||||||
|
<RenameInput value="Selected Zone Name" />
|
||||||
|
<div className="button" onClick={handleEditView}>
|
||||||
|
{Edit ? "Cancel" : "Edit"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Vector3Input onChange={() => {}} header="Viewport Target" />
|
||||||
|
<Vector3Input onChange={() => {}} header="Viewport Position" />
|
||||||
|
{Edit && (
|
||||||
|
<div className="button-save" onClick={handleSetView}>
|
||||||
|
Set View
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ZoneProperties;
|
|
@ -28,7 +28,7 @@ const DropList: React.FC<DropListProps> = ({ val }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{val.pathName}
|
{val.pathName}
|
||||||
<div className="arrow-container">
|
<div className={`arrow-container${openDrop ? " active" : ""}`}>
|
||||||
<ArrowIcon />
|
<ArrowIcon />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -87,8 +87,9 @@ const Simulations: React.FC = () => {
|
||||||
{productsList.map((action, index) => (
|
{productsList.map((action, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={`list-item ${selectedItem === action ? "active" : ""
|
className={`list-item ${
|
||||||
}`}
|
selectedItem === action ? "active" : ""
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="value"
|
className="value"
|
||||||
|
|
|
@ -6,15 +6,20 @@ import {
|
||||||
SimulationIcon,
|
SimulationIcon,
|
||||||
VisualizationIcon,
|
VisualizationIcon,
|
||||||
} from "../icons/ExportModuleIcons";
|
} from "../icons/ExportModuleIcons";
|
||||||
|
import useToggleStore from "../../store/useUIToggleStore";
|
||||||
|
|
||||||
const ModuleToggle: React.FC = () => {
|
const ModuleToggle: React.FC = () => {
|
||||||
const { activeModule, setActiveModule } = useModuleStore();
|
const { activeModule, setActiveModule } = useModuleStore();
|
||||||
|
const { setToggleUI } = useToggleStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="module-toggle-container">
|
<div className="module-toggle-container">
|
||||||
<div
|
<div
|
||||||
className={`module-list ${activeModule === "builder" && "active"}`}
|
className={`module-list ${activeModule === "builder" && "active"}`}
|
||||||
onClick={() => setActiveModule("builder")}
|
onClick={() => {
|
||||||
|
setActiveModule("builder");
|
||||||
|
setToggleUI(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<BuilderIcon isActive={activeModule === "builder"} />
|
<BuilderIcon isActive={activeModule === "builder"} />
|
||||||
|
@ -23,7 +28,10 @@ const ModuleToggle: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`module-list ${activeModule === "simulation" && "active"}`}
|
className={`module-list ${activeModule === "simulation" && "active"}`}
|
||||||
onClick={() => setActiveModule("simulation")}
|
onClick={() => {
|
||||||
|
setActiveModule("simulation");
|
||||||
|
setToggleUI(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<SimulationIcon isActive={activeModule === "simulation"} />
|
<SimulationIcon isActive={activeModule === "simulation"} />
|
||||||
|
@ -34,7 +42,10 @@ const ModuleToggle: React.FC = () => {
|
||||||
className={`module-list ${
|
className={`module-list ${
|
||||||
activeModule === "visualization" && "active"
|
activeModule === "visualization" && "active"
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setActiveModule("visualization")}
|
onClick={() => {
|
||||||
|
setActiveModule("visualization");
|
||||||
|
setToggleUI(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<VisualizationIcon isActive={activeModule === "visualization"} />
|
<VisualizationIcon isActive={activeModule === "visualization"} />
|
||||||
|
@ -42,10 +53,11 @@ const ModuleToggle: React.FC = () => {
|
||||||
<div className="module">Visualization</div>
|
<div className="module">Visualization</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`module-list ${
|
className={`module-list ${activeModule === "market" && "active"}`}
|
||||||
activeModule === "market" && "active"
|
onClick={() => {
|
||||||
}`}
|
setActiveModule("market");
|
||||||
onClick={() => setActiveModule("market")}
|
setToggleUI(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<CartIcon isActive={activeModule === "market"} />
|
<CartIcon isActive={activeModule === "market"} />
|
||||||
|
|
|
@ -5,6 +5,7 @@ import AddButtons from "./AddButtons";
|
||||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
||||||
import DisplayZone from "./DisplayZone";
|
import DisplayZone from "./DisplayZone";
|
||||||
import Scene from "../../../modules/scene/scene";
|
import Scene from "../../../modules/scene/scene";
|
||||||
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones";
|
import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones";
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,6 +39,8 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
|
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
const { activeModule } = useModuleStore();
|
||||||
|
|
||||||
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
||||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||||
|
|
||||||
|
@ -98,34 +101,44 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
id="real-time-vis-canvas"
|
id="real-time-vis-canvas"
|
||||||
className={`realTime-viz canvas ${!isPlaying ? "playActiveFalse" : ""}`}
|
className={`realTime-viz canvas ${!isPlaying ? "playActiveFalse" : ""}`}
|
||||||
style={{
|
style={{
|
||||||
height: isPlaying ? "100vh" : "",
|
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
|
||||||
left: isPlaying ? "0%" : "",
|
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
|
||||||
|
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="scene-container"
|
className="scene-container"
|
||||||
style={{ height: "100%", width: "100%" }}
|
style={{
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Scene />
|
<Scene />
|
||||||
</div>
|
</div>
|
||||||
{!isPlaying && (
|
{activeModule === "visualization" && (
|
||||||
<AddButtons
|
<>
|
||||||
hiddenPanels={hiddenPanels}
|
<DisplayZone
|
||||||
setHiddenPanels={setHiddenPanels}
|
zonesData={zonesData}
|
||||||
selectedZone={selectedZone}
|
selectedZone={selectedZone}
|
||||||
setSelectedZone={setSelectedZone}
|
setSelectedZone={setSelectedZone}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{!isPlaying && (
|
||||||
|
<AddButtons
|
||||||
|
hiddenPanels={hiddenPanels}
|
||||||
|
setHiddenPanels={setHiddenPanels}
|
||||||
|
selectedZone={selectedZone}
|
||||||
|
setSelectedZone={setSelectedZone}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Panel
|
||||||
|
selectedZone={selectedZone}
|
||||||
|
setSelectedZone={setSelectedZone}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<DisplayZone
|
|
||||||
zonesData={zonesData}
|
|
||||||
selectedZone={selectedZone}
|
|
||||||
setSelectedZone={setSelectedZone}
|
|
||||||
/>
|
|
||||||
<Panel
|
|
||||||
selectedZone={selectedZone}
|
|
||||||
hiddenPanels={hiddenPanels}
|
|
||||||
setSelectedZone={setSelectedZone}
|
|
||||||
/>{" "}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,466 +1,509 @@
|
||||||
import React, { useState, useEffect, useMemo, useRef } from "react";
|
import React, { useState, useEffect, useMemo, useRef } from "react";
|
||||||
import { Line, Sphere } from "@react-three/drei";
|
import { Line, Sphere } from "@react-three/drei";
|
||||||
import { useThree, useFrame } from "@react-three/fiber";
|
import { useThree, useFrame } from "@react-three/fiber";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useActiveLayer, useDeleteModels, useDeletePointOrLine, useMovePoint, useSocketStore, useToggleView, useToolMode, useRemovedLayer, useZones, useZonePoints } from "../../../store/store";
|
import { useActiveLayer, useDeleteModels, useDeletePointOrLine, useMovePoint, useSocketStore, useToggleView, useToolMode, useRemovedLayer, useZones, useZonePoints } from "../../../store/store";
|
||||||
// import { setZonesApi } from "../../../services/factoryBuilder/zones/setZonesApi";
|
// import { setZonesApi } from "../../../services/factoryBuilder/zones/setZonesApi";
|
||||||
// import { deleteZonesApi } from "../../../services/factoryBuilder/zones/deleteZoneApi";
|
// import { deleteZonesApi } from "../../../services/factoryBuilder/zones/deleteZoneApi";
|
||||||
import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi";
|
import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi";
|
||||||
|
|
||||||
import * as CONSTANTS from '../../../types/world/worldConstants';
|
import * as CONSTANTS from '../../../types/world/worldConstants';
|
||||||
|
|
||||||
const ZoneGroup: React.FC = () => {
|
const ZoneGroup: React.FC = () => {
|
||||||
const { camera, pointer, gl, raycaster, scene, controls } = useThree();
|
const { camera, pointer, gl, raycaster, scene, controls } = useThree();
|
||||||
const [startPoint, setStartPoint] = useState<THREE.Vector3 | null>(null);
|
const [startPoint, setStartPoint] = useState<THREE.Vector3 | null>(null);
|
||||||
const [endPoint, setEndPoint] = useState<THREE.Vector3 | null>(null);
|
const [endPoint, setEndPoint] = useState<THREE.Vector3 | null>(null);
|
||||||
const { zones, setZones } = useZones();
|
const { zones, setZones } = useZones();
|
||||||
const { zonePoints, setZonePoints } = useZonePoints();
|
const { zonePoints, setZonePoints } = useZonePoints();
|
||||||
const [isDragging, setIsDragging] = useState(false);
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
const [draggedSphere, setDraggedSphere] = useState<THREE.Vector3 | null>(null);
|
const [draggedSphere, setDraggedSphere] = useState<THREE.Vector3 | null>(null);
|
||||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||||
const { toggleView } = useToggleView();
|
const { toggleView } = useToggleView();
|
||||||
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
|
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
|
||||||
const { removedLayer, setRemovedLayer } = useRemovedLayer();
|
const { removedLayer, setRemovedLayer } = useRemovedLayer();
|
||||||
const { toolMode, setToolMode } = useToolMode();
|
const { toolMode, setToolMode } = useToolMode();
|
||||||
const { movePoint, setMovePoint } = useMovePoint();
|
const { movePoint, setMovePoint } = useMovePoint();
|
||||||
const { deleteModels, setDeleteModels } = useDeleteModels();
|
const { deleteModels, setDeleteModels } = useDeleteModels();
|
||||||
const { activeLayer, setActiveLayer } = useActiveLayer();
|
const { activeLayer, setActiveLayer } = useActiveLayer();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
|
|
||||||
const groupsRef = useRef<any>();
|
const groupsRef = useRef<any>();
|
||||||
|
|
||||||
const zoneMaterial = useMemo(() => new THREE.ShaderMaterial({
|
const zoneMaterial = useMemo(() => new THREE.ShaderMaterial({
|
||||||
side: THREE.DoubleSide,
|
side: THREE.DoubleSide,
|
||||||
vertexShader: `
|
vertexShader: `
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
void main(){
|
void main(){
|
||||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||||
vUv = uv;
|
vUv = uv;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
fragmentShader: `
|
fragmentShader: `
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
uniform vec3 uColor;
|
uniform vec3 uColor;
|
||||||
void main(){
|
void main(){
|
||||||
float alpha = 1.0 - vUv.y;
|
float alpha = 1.0 - vUv.y;
|
||||||
gl_FragColor = vec4(uColor, alpha);
|
gl_FragColor = vec4(uColor, alpha);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
uniforms: {
|
uniforms: {
|
||||||
uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) },
|
uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) },
|
||||||
},
|
},
|
||||||
transparent: true,
|
transparent: true,
|
||||||
}), []);
|
}), []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchZones = async () => {
|
const fetchZones = async () => {
|
||||||
const email = localStorage.getItem('email');
|
const email = localStorage.getItem('email');
|
||||||
if (!email) return;
|
if (!email) return;
|
||||||
|
|
||||||
const organization = email.split("@")[1].split(".")[0];
|
const organization = email.split("@")[1].split(".")[0];
|
||||||
const data = await getZonesApi(organization);
|
const data = await getZonesApi(organization);
|
||||||
|
|
||||||
if (data.data && data.data.length > 0) {
|
if (data.data && data.data.length > 0) {
|
||||||
const fetchedZones = data.data.map((zone: any) => ({
|
const fetchedZones = data.data.map((zone: any) => ({
|
||||||
zoneId: zone.zoneId,
|
zoneId: zone.zoneId,
|
||||||
zoneName: zone.zoneName,
|
zoneName: zone.zoneName,
|
||||||
points: zone.points,
|
points: zone.points,
|
||||||
layer: zone.layer
|
layer: zone.layer
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setZones(fetchedZones);
|
setZones(fetchedZones);
|
||||||
|
|
||||||
const fetchedPoints = data.data.flatMap((zone: any) =>
|
const fetchedPoints = data.data.flatMap((zone: any) =>
|
||||||
zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point))
|
zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point))
|
||||||
);
|
);
|
||||||
|
|
||||||
setZonePoints(fetchedPoints);
|
setZonePoints(fetchedPoints);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchZones();
|
fetchZones();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
localStorage.setItem('zones', JSON.stringify(zones));
|
localStorage.setItem('zones', JSON.stringify(zones));
|
||||||
|
|
||||||
}, [zones])
|
}, [zones])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (removedLayer) {
|
if (removedLayer) {
|
||||||
const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer);
|
const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer);
|
||||||
setZones(updatedZones);
|
setZones(updatedZones);
|
||||||
|
|
||||||
const updatedzonePoints = zonePoints.filter((_: any, index: any) => {
|
const updatedzonePoints = zonePoints.filter((_: any, index: any) => {
|
||||||
const zoneIndex = Math.floor(index / 4);
|
const zoneIndex = Math.floor(index / 4);
|
||||||
return zones[zoneIndex]?.layer !== removedLayer;
|
return zones[zoneIndex]?.layer !== removedLayer;
|
||||||
});
|
});
|
||||||
setZonePoints(updatedzonePoints);
|
setZonePoints(updatedzonePoints);
|
||||||
|
|
||||||
zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => {
|
zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => {
|
||||||
deleteZoneFromBackend(zone.zoneId);
|
deleteZoneFromBackend(zone.zoneId);
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemovedLayer(null);
|
setRemovedLayer(null);
|
||||||
}
|
}
|
||||||
}, [removedLayer]);
|
}, [removedLayer]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (toolMode !== "Zone") {
|
if (toolMode !== "Zone") {
|
||||||
setStartPoint(null);
|
setStartPoint(null);
|
||||||
setEndPoint(null);
|
setEndPoint(null);
|
||||||
} else {
|
} else {
|
||||||
setDeletePointOrLine(false);
|
setDeletePointOrLine(false);
|
||||||
setMovePoint(false);
|
setMovePoint(false);
|
||||||
setDeleteModels(false);
|
setDeleteModels(false);
|
||||||
}
|
}
|
||||||
if (!toggleView) {
|
if (!toggleView) {
|
||||||
setStartPoint(null);
|
setStartPoint(null);
|
||||||
setEndPoint(null);
|
setEndPoint(null);
|
||||||
}
|
}
|
||||||
}, [toolMode, toggleView]);
|
}, [toolMode, toggleView]);
|
||||||
|
|
||||||
|
|
||||||
const addZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
|
const addZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
|
||||||
|
|
||||||
const email = localStorage.getItem('email');
|
const email = localStorage.getItem('email');
|
||||||
const userId = localStorage.getItem('userId');
|
const userId = localStorage.getItem('userId');
|
||||||
const organization = (email!.split("@")[1]).split(".")[0];
|
const organization = (email!.split("@")[1]).split(".")[0];
|
||||||
|
|
||||||
const input = {
|
const calculateCenter = (points: number[][]) => {
|
||||||
userId: userId,
|
if (!points || points.length === 0) return null;
|
||||||
organization: organization,
|
|
||||||
zoneData: {
|
let sumX = 0, sumY = 0, sumZ = 0;
|
||||||
zoneName: zone.zoneName,
|
const numPoints = points.length;
|
||||||
zoneId: zone.zoneId,
|
|
||||||
points: zone.points,
|
points.forEach(([x, y, z]) => {
|
||||||
layer: zone.layer
|
sumX += x;
|
||||||
}
|
sumY += y;
|
||||||
}
|
sumZ += z;
|
||||||
|
});
|
||||||
socket.emit('v2:zone:set', input);
|
|
||||||
};
|
return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [number, number, number];
|
||||||
|
};
|
||||||
const updateZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
|
|
||||||
|
const target: [number, number, number] | null = calculateCenter(zone.points);
|
||||||
const email = localStorage.getItem('email');
|
if (!target) return;
|
||||||
const userId = localStorage.getItem('userId');
|
const position = [target[0], 75, target[2]];
|
||||||
const organization = (email!.split("@")[1]).split(".")[0];
|
|
||||||
|
const input = {
|
||||||
const input = {
|
userId: userId,
|
||||||
userId: userId,
|
organization: organization,
|
||||||
organization: organization,
|
zoneData: {
|
||||||
zoneData: {
|
zoneName: zone.zoneName,
|
||||||
zoneName: zone.zoneName,
|
zoneId: zone.zoneId,
|
||||||
zoneId: zone.zoneId,
|
points: zone.points,
|
||||||
points: zone.points,
|
viewPortCenter: target,
|
||||||
layer: zone.layer
|
viewPortposition: position,
|
||||||
}
|
layer: zone.layer
|
||||||
}
|
}
|
||||||
|
}
|
||||||
socket.emit('v2:zone:set', input);
|
|
||||||
};
|
socket.emit('v2:zone:set', input);
|
||||||
|
};
|
||||||
const deleteZoneFromBackend = async (zoneId: string) => {
|
|
||||||
|
const updateZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
|
||||||
const email = localStorage.getItem('email');
|
|
||||||
const userId = localStorage.getItem('userId');
|
const email = localStorage.getItem('email');
|
||||||
const organization = (email!.split("@")[1]).split(".")[0];
|
const userId = localStorage.getItem('userId');
|
||||||
|
const organization = (email!.split("@")[1]).split(".")[0];
|
||||||
const input = {
|
|
||||||
userId: userId,
|
const calculateCenter = (points: number[][]) => {
|
||||||
organization: organization,
|
if (!points || points.length === 0) return null;
|
||||||
zoneId: zoneId
|
|
||||||
}
|
let sumX = 0, sumY = 0, sumZ = 0;
|
||||||
|
const numPoints = points.length;
|
||||||
socket.emit('v2:zone:delete', input);
|
|
||||||
};
|
points.forEach(([x, y, z]) => {
|
||||||
|
sumX += x;
|
||||||
const handleDeleteZone = (zoneId: string) => {
|
sumY += y;
|
||||||
const updatedZones = zones.filter((zone: any) => zone.zoneId !== zoneId);
|
sumZ += z;
|
||||||
setZones(updatedZones);
|
});
|
||||||
|
|
||||||
const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === zoneId);
|
return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [number, number, number];
|
||||||
if (zoneIndex !== -1) {
|
};
|
||||||
const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4);
|
|
||||||
zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point));
|
const target: [number, number, number] | null = calculateCenter(zone.points);
|
||||||
const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4);
|
if (!target) return;
|
||||||
setZonePoints(updatedzonePoints);
|
const position = [target[0], 75, target[2]];
|
||||||
}
|
|
||||||
|
const input = {
|
||||||
deleteZoneFromBackend(zoneId);
|
userId: userId,
|
||||||
};
|
organization: organization,
|
||||||
|
zoneData: {
|
||||||
useEffect(() => {
|
zoneName: zone.zoneName,
|
||||||
if (!camera || !toggleView) return;
|
zoneId: zone.zoneId,
|
||||||
const canvasElement = gl.domElement;
|
points: zone.points,
|
||||||
|
viewPortCenter: target,
|
||||||
let drag = false;
|
viewPortposition: position,
|
||||||
let isLeftMouseDown = false;
|
layer: zone.layer
|
||||||
|
}
|
||||||
const onMouseDown = (evt: any) => {
|
}
|
||||||
if (evt.button === 0) {
|
|
||||||
isLeftMouseDown = true;
|
socket.emit('v2:zone:set', input);
|
||||||
drag = false;
|
};
|
||||||
|
|
||||||
raycaster.setFromCamera(pointer, camera);
|
|
||||||
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
|
const deleteZoneFromBackend = async (zoneId: string) => {
|
||||||
|
|
||||||
if (intersects.length > 0 && movePoint) {
|
const email = localStorage.getItem('email');
|
||||||
const clickedObject = intersects[0].object;
|
const userId = localStorage.getItem('userId');
|
||||||
const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position));
|
const organization = (email!.split("@")[1]).split(".")[0];
|
||||||
if (sphereIndex !== -1) {
|
|
||||||
(controls as any).enabled = false;
|
const input = {
|
||||||
setDraggedSphere(zonePoints[sphereIndex]);
|
userId: userId,
|
||||||
setIsDragging(true);
|
organization: organization,
|
||||||
}
|
zoneId: zoneId
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
socket.emit('v2:zone:delete', input);
|
||||||
|
};
|
||||||
const onMouseUp = (evt: any) => {
|
|
||||||
if (evt.button === 0 && !drag && !isDragging && !deletePointOrLine) {
|
const handleDeleteZone = (zoneId: string) => {
|
||||||
isLeftMouseDown = false;
|
const updatedZones = zones.filter((zone: any) => zone.zoneId !== zoneId);
|
||||||
|
setZones(updatedZones);
|
||||||
if (!startPoint && !movePoint) {
|
|
||||||
raycaster.setFromCamera(pointer, camera);
|
const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === zoneId);
|
||||||
const intersectionPoint = new THREE.Vector3();
|
if (zoneIndex !== -1) {
|
||||||
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4);
|
||||||
if (point) {
|
zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point));
|
||||||
setStartPoint(point);
|
const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4);
|
||||||
setEndPoint(null);
|
setZonePoints(updatedzonePoints);
|
||||||
}
|
}
|
||||||
} else if (startPoint && !movePoint) {
|
|
||||||
raycaster.setFromCamera(pointer, camera);
|
deleteZoneFromBackend(zoneId);
|
||||||
const intersectionPoint = new THREE.Vector3();
|
};
|
||||||
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
|
||||||
if (!point) return;
|
useEffect(() => {
|
||||||
|
if (!camera || !toggleView) return;
|
||||||
const points = [
|
const canvasElement = gl.domElement;
|
||||||
[startPoint.x, 0.15, startPoint.z],
|
|
||||||
[point.x, 0.15, startPoint.z],
|
let drag = false;
|
||||||
[point.x, 0.15, point.z],
|
let isLeftMouseDown = false;
|
||||||
[startPoint.x, 0.15, point.z],
|
|
||||||
[startPoint.x, 0.15, startPoint.z],
|
const onMouseDown = (evt: any) => {
|
||||||
] as [number, number, number][];
|
if (evt.button === 0) {
|
||||||
|
isLeftMouseDown = true;
|
||||||
const zoneName = `Zone ${zones.length + 1}`;
|
drag = false;
|
||||||
const zoneId = THREE.MathUtils.generateUUID();
|
|
||||||
const newZone = {
|
raycaster.setFromCamera(pointer, camera);
|
||||||
zoneId,
|
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
|
||||||
zoneName,
|
|
||||||
points: points,
|
if (intersects.length > 0 && movePoint) {
|
||||||
layer: activeLayer
|
const clickedObject = intersects[0].object;
|
||||||
};
|
const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position));
|
||||||
|
if (sphereIndex !== -1) {
|
||||||
const newZones = [...zones, newZone];
|
(controls as any).enabled = false;
|
||||||
|
setDraggedSphere(zonePoints[sphereIndex]);
|
||||||
setZones(newZones);
|
setIsDragging(true);
|
||||||
|
}
|
||||||
const newzonePoints = [
|
}
|
||||||
new THREE.Vector3(startPoint.x, 0.15, startPoint.z),
|
}
|
||||||
new THREE.Vector3(point.x, 0.15, startPoint.z),
|
};
|
||||||
new THREE.Vector3(point.x, 0.15, point.z),
|
|
||||||
new THREE.Vector3(startPoint.x, 0.15, point.z),
|
const onMouseUp = (evt: any) => {
|
||||||
];
|
if (evt.button === 0 && !drag && !isDragging && !deletePointOrLine) {
|
||||||
|
isLeftMouseDown = false;
|
||||||
const updatedZonePoints = [...zonePoints, ...newzonePoints];
|
|
||||||
setZonePoints(updatedZonePoints);
|
if (!startPoint && !movePoint) {
|
||||||
|
raycaster.setFromCamera(pointer, camera);
|
||||||
addZoneToBackend(newZone);
|
const intersectionPoint = new THREE.Vector3();
|
||||||
|
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||||
setStartPoint(null);
|
if (point) {
|
||||||
setEndPoint(null);
|
setStartPoint(point);
|
||||||
}
|
setEndPoint(null);
|
||||||
} else if (evt.button === 0 && !drag && !isDragging && deletePointOrLine) {
|
}
|
||||||
raycaster.setFromCamera(pointer, camera);
|
} else if (startPoint && !movePoint) {
|
||||||
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
|
raycaster.setFromCamera(pointer, camera);
|
||||||
|
const intersectionPoint = new THREE.Vector3();
|
||||||
if (intersects.length > 0) {
|
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||||
const clickedObject = intersects[0].object;
|
if (!point) return;
|
||||||
|
|
||||||
const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position));
|
const points = [
|
||||||
if (sphereIndex !== -1) {
|
[startPoint.x, 0.15, startPoint.z],
|
||||||
const zoneIndex = Math.floor(sphereIndex / 4);
|
[point.x, 0.15, startPoint.z],
|
||||||
const zoneId = zones[zoneIndex].zoneId;
|
[point.x, 0.15, point.z],
|
||||||
handleDeleteZone(zoneId);
|
[startPoint.x, 0.15, point.z],
|
||||||
return;
|
[startPoint.x, 0.15, startPoint.z],
|
||||||
}
|
] as [number, number, number][];
|
||||||
}
|
|
||||||
}
|
const zoneName = `Zone ${zones.length + 1}`;
|
||||||
|
const zoneId = THREE.MathUtils.generateUUID();
|
||||||
if (evt.button === 0) {
|
const newZone = {
|
||||||
if (isDragging && draggedSphere) {
|
zoneId,
|
||||||
setIsDragging(false);
|
zoneName,
|
||||||
setDraggedSphere(null);
|
points: points,
|
||||||
|
layer: activeLayer
|
||||||
const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
|
};
|
||||||
if (sphereIndex !== -1) {
|
|
||||||
const zoneIndex = Math.floor(sphereIndex / 4);
|
const newZones = [...zones, newZone];
|
||||||
|
|
||||||
if (zoneIndex !== -1 && zones[zoneIndex]) {
|
setZones(newZones);
|
||||||
updateZoneToBackend(zones[zoneIndex]);
|
|
||||||
}
|
const newzonePoints = [
|
||||||
}
|
new THREE.Vector3(startPoint.x, 0.15, startPoint.z),
|
||||||
}
|
new THREE.Vector3(point.x, 0.15, startPoint.z),
|
||||||
}
|
new THREE.Vector3(point.x, 0.15, point.z),
|
||||||
};
|
new THREE.Vector3(startPoint.x, 0.15, point.z),
|
||||||
|
];
|
||||||
const onMouseMove = () => {
|
|
||||||
if (isLeftMouseDown) {
|
const updatedZonePoints = [...zonePoints, ...newzonePoints];
|
||||||
drag = true;
|
setZonePoints(updatedZonePoints);
|
||||||
}
|
|
||||||
raycaster.setFromCamera(pointer, camera);
|
addZoneToBackend(newZone);
|
||||||
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
|
|
||||||
|
setStartPoint(null);
|
||||||
if (intersects.length > 0 && intersects[0].object.name.includes('point')) {
|
setEndPoint(null);
|
||||||
gl.domElement.style.cursor = movePoint ? "pointer" : "default";
|
}
|
||||||
} else {
|
} else if (evt.button === 0 && !drag && !isDragging && deletePointOrLine) {
|
||||||
gl.domElement.style.cursor = "default";
|
raycaster.setFromCamera(pointer, camera);
|
||||||
}
|
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
|
||||||
if (isDragging && draggedSphere) {
|
|
||||||
raycaster.setFromCamera(pointer, camera);
|
if (intersects.length > 0) {
|
||||||
const intersectionPoint = new THREE.Vector3();
|
const clickedObject = intersects[0].object;
|
||||||
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
|
||||||
if (point) {
|
const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position));
|
||||||
draggedSphere.set(point.x, 0.15, point.z);
|
if (sphereIndex !== -1) {
|
||||||
|
const zoneIndex = Math.floor(sphereIndex / 4);
|
||||||
const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
|
const zoneId = zones[zoneIndex].zoneId;
|
||||||
if (sphereIndex !== -1) {
|
handleDeleteZone(zoneId);
|
||||||
const zoneIndex = Math.floor(sphereIndex / 4);
|
return;
|
||||||
const cornerIndex = sphereIndex % 4;
|
}
|
||||||
|
}
|
||||||
const updatedZones = zones.map((zone: any, index: number) => {
|
}
|
||||||
if (index === zoneIndex) {
|
|
||||||
const updatedPoints = [...zone.points];
|
if (evt.button === 0) {
|
||||||
updatedPoints[cornerIndex] = [point.x, 0.15, point.z];
|
if (isDragging && draggedSphere) {
|
||||||
updatedPoints[4] = updatedPoints[0];
|
setIsDragging(false);
|
||||||
return { ...zone, points: updatedPoints };
|
setDraggedSphere(null);
|
||||||
}
|
|
||||||
return zone;
|
const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
|
||||||
});
|
if (sphereIndex !== -1) {
|
||||||
|
const zoneIndex = Math.floor(sphereIndex / 4);
|
||||||
setZones(updatedZones);
|
|
||||||
}
|
if (zoneIndex !== -1 && zones[zoneIndex]) {
|
||||||
}
|
updateZoneToBackend(zones[zoneIndex]);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
const onContext = (event: any) => {
|
}
|
||||||
event.preventDefault();
|
};
|
||||||
setStartPoint(null);
|
|
||||||
setEndPoint(null);
|
const onMouseMove = () => {
|
||||||
};
|
if (isLeftMouseDown) {
|
||||||
|
drag = true;
|
||||||
if (toolMode === 'Zone' || deletePointOrLine || movePoint) {
|
}
|
||||||
canvasElement.addEventListener("mousedown", onMouseDown);
|
raycaster.setFromCamera(pointer, camera);
|
||||||
canvasElement.addEventListener("mouseup", onMouseUp);
|
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
|
||||||
canvasElement.addEventListener("mousemove", onMouseMove);
|
|
||||||
canvasElement.addEventListener("contextmenu", onContext);
|
if (intersects.length > 0 && intersects[0].object.name.includes('point')) {
|
||||||
}
|
gl.domElement.style.cursor = movePoint ? "pointer" : "default";
|
||||||
return () => {
|
} else {
|
||||||
canvasElement.removeEventListener("mousedown", onMouseDown);
|
gl.domElement.style.cursor = "default";
|
||||||
canvasElement.removeEventListener("mouseup", onMouseUp);
|
}
|
||||||
canvasElement.removeEventListener("mousemove", onMouseMove);
|
if (isDragging && draggedSphere) {
|
||||||
canvasElement.removeEventListener("contextmenu", onContext);
|
raycaster.setFromCamera(pointer, camera);
|
||||||
};
|
const intersectionPoint = new THREE.Vector3();
|
||||||
}, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, deletePointOrLine, zonePoints, draggedSphere, movePoint, activeLayer]);
|
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||||
|
if (point) {
|
||||||
useFrame(() => {
|
draggedSphere.set(point.x, 0.15, point.z);
|
||||||
if (!startPoint) return;
|
|
||||||
raycaster.setFromCamera(pointer, camera);
|
const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
|
||||||
const intersectionPoint = new THREE.Vector3();
|
if (sphereIndex !== -1) {
|
||||||
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
const zoneIndex = Math.floor(sphereIndex / 4);
|
||||||
if (point) {
|
const cornerIndex = sphereIndex % 4;
|
||||||
setEndPoint(point);
|
|
||||||
}
|
const updatedZones = zones.map((zone: any, index: number) => {
|
||||||
});
|
if (index === zoneIndex) {
|
||||||
return (
|
const updatedPoints = [...zone.points];
|
||||||
<group ref={groupsRef} name='zoneGroup' >
|
updatedPoints[cornerIndex] = [point.x, 0.15, point.z];
|
||||||
<group name="zones" visible={!toggleView}>
|
updatedPoints[4] = updatedPoints[0];
|
||||||
{zones
|
return { ...zone, points: updatedPoints };
|
||||||
.map((zone: any) => (
|
}
|
||||||
<group key={zone.zoneId} name={zone.zoneName}>
|
return zone;
|
||||||
{zone.points.slice(0, -1).map((point: [number, number, number], index: number) => {
|
});
|
||||||
const nextPoint = zone.points[index + 1];
|
|
||||||
|
setZones(updatedZones);
|
||||||
const point1 = new THREE.Vector3(point[0], point[1], point[2]);
|
}
|
||||||
const point2 = new THREE.Vector3(nextPoint[0], nextPoint[1], nextPoint[2]);
|
}
|
||||||
|
}
|
||||||
const planeWidth = point1.distanceTo(point2);
|
};
|
||||||
const planeHeight = CONSTANTS.wallConfig.height;
|
|
||||||
|
const onContext = (event: any) => {
|
||||||
const midpoint = new THREE.Vector3((point1.x + point2.x) / 2, (CONSTANTS.wallConfig.height / 2) + ((zone.layer - 1) * CONSTANTS.wallConfig.height), (point1.z + point2.z) / 2);
|
event.preventDefault();
|
||||||
|
setStartPoint(null);
|
||||||
const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x);
|
setEndPoint(null);
|
||||||
|
};
|
||||||
return (
|
|
||||||
<mesh
|
if (toolMode === 'Zone' || deletePointOrLine || movePoint) {
|
||||||
key={index}
|
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||||
position={midpoint}
|
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||||
rotation={[0, -angle, 0]}
|
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||||
>
|
canvasElement.addEventListener("contextmenu", onContext);
|
||||||
<planeGeometry args={[planeWidth, planeHeight]} />
|
}
|
||||||
<primitive
|
return () => {
|
||||||
object={zoneMaterial.clone()}
|
canvasElement.removeEventListener("mousedown", onMouseDown);
|
||||||
attach="material"
|
canvasElement.removeEventListener("mouseup", onMouseUp);
|
||||||
/>
|
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||||
</mesh>
|
canvasElement.removeEventListener("contextmenu", onContext);
|
||||||
);
|
};
|
||||||
})}
|
}, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, deletePointOrLine, zonePoints, draggedSphere, movePoint, activeLayer]);
|
||||||
</group>
|
|
||||||
))}
|
useFrame(() => {
|
||||||
</group>
|
if (!startPoint) return;
|
||||||
<group name='zoneLines' visible={toggleView}>
|
raycaster.setFromCamera(pointer, camera);
|
||||||
{zones
|
const intersectionPoint = new THREE.Vector3();
|
||||||
.filter((zone: any) => zone.layer === activeLayer)
|
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||||
.map((zone: any) => (
|
if (point) {
|
||||||
<Line
|
setEndPoint(point);
|
||||||
key={zone.zoneId}
|
}
|
||||||
points={zone.points}
|
});
|
||||||
color="#007BFF"
|
return (
|
||||||
lineWidth={3}
|
<group ref={groupsRef} name='zoneGroup' >
|
||||||
onClick={(e) => {
|
<group name="zones" visible={!toggleView}>
|
||||||
e.stopPropagation();
|
{zones
|
||||||
if (deletePointOrLine) {
|
.map((zone: any) => (
|
||||||
handleDeleteZone(zone.zoneId);
|
<group key={zone.zoneId} name={zone.zoneName}>
|
||||||
}
|
{zone.points.slice(0, -1).map((point: [number, number, number], index: number) => {
|
||||||
}}
|
const nextPoint = zone.points[index + 1];
|
||||||
/>
|
|
||||||
))}
|
const point1 = new THREE.Vector3(point[0], point[1], point[2]);
|
||||||
</group>
|
const point2 = new THREE.Vector3(nextPoint[0], nextPoint[1], nextPoint[2]);
|
||||||
<group name="zonePoints" visible={toggleView}>
|
|
||||||
{zones.filter((zone: any) => zone.layer === activeLayer).flatMap((zone: any) => (
|
const planeWidth = point1.distanceTo(point2);
|
||||||
zone.points.slice(0, 4).map((point: any, pointIndex: number) => (
|
const planeHeight = CONSTANTS.wallConfig.height;
|
||||||
<Sphere
|
|
||||||
key={`${zone.zoneId}-point-${pointIndex}`}
|
const midpoint = new THREE.Vector3((point1.x + point2.x) / 2, (CONSTANTS.wallConfig.height / 2) + ((zone.layer - 1) * CONSTANTS.wallConfig.height), (point1.z + point2.z) / 2);
|
||||||
position={new THREE.Vector3(...point)}
|
|
||||||
args={[0.3, 16, 16]}
|
const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x);
|
||||||
name={`point-${zone.zoneId}-${pointIndex}`}
|
|
||||||
>
|
return (
|
||||||
<meshBasicMaterial color="red" />
|
<mesh
|
||||||
</Sphere>
|
key={index}
|
||||||
))
|
position={midpoint}
|
||||||
))}
|
rotation={[0, -angle, 0]}
|
||||||
</group>
|
>
|
||||||
<group name="tempGroup" visible={toggleView}>
|
<planeGeometry args={[planeWidth, planeHeight]} />
|
||||||
{startPoint && endPoint && (
|
<primitive
|
||||||
<Line
|
object={zoneMaterial.clone()}
|
||||||
points={[
|
attach="material"
|
||||||
[startPoint.x, 0.15, startPoint.z],
|
/>
|
||||||
[endPoint.x, 0.15, startPoint.z],
|
</mesh>
|
||||||
[endPoint.x, 0.15, endPoint.z],
|
);
|
||||||
[startPoint.x, 0.15, endPoint.z],
|
})}
|
||||||
[startPoint.x, 0.15, startPoint.z],
|
</group>
|
||||||
]}
|
))}
|
||||||
color="#C164FF"
|
</group>
|
||||||
lineWidth={3}
|
<group name='zoneLines' visible={toggleView}>
|
||||||
/>
|
{zones
|
||||||
)}
|
.filter((zone: any) => zone.layer === activeLayer)
|
||||||
</group>
|
.map((zone: any) => (
|
||||||
</group>
|
<Line
|
||||||
);
|
key={zone.zoneId}
|
||||||
};
|
points={zone.points}
|
||||||
|
color="#007BFF"
|
||||||
|
lineWidth={3}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (deletePointOrLine) {
|
||||||
|
handleDeleteZone(zone.zoneId);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</group>
|
||||||
|
<group name="zonePoints" visible={toggleView}>
|
||||||
|
{zones.filter((zone: any) => zone.layer === activeLayer).flatMap((zone: any) => (
|
||||||
|
zone.points.slice(0, 4).map((point: any, pointIndex: number) => (
|
||||||
|
<Sphere
|
||||||
|
key={`${zone.zoneId}-point-${pointIndex}`}
|
||||||
|
position={new THREE.Vector3(...point)}
|
||||||
|
args={[0.3, 16, 16]}
|
||||||
|
name={`point-${zone.zoneId}-${pointIndex}`}
|
||||||
|
>
|
||||||
|
<meshBasicMaterial color="red" />
|
||||||
|
</Sphere>
|
||||||
|
))
|
||||||
|
))}
|
||||||
|
</group>
|
||||||
|
<group name="tempGroup" visible={toggleView}>
|
||||||
|
{startPoint && endPoint && (
|
||||||
|
<Line
|
||||||
|
points={[
|
||||||
|
[startPoint.x, 0.15, startPoint.z],
|
||||||
|
[endPoint.x, 0.15, startPoint.z],
|
||||||
|
[endPoint.x, 0.15, endPoint.z],
|
||||||
|
[startPoint.x, 0.15, endPoint.z],
|
||||||
|
[startPoint.x, 0.15, startPoint.z],
|
||||||
|
]}
|
||||||
|
color="#C164FF"
|
||||||
|
lineWidth={3}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default ZoneGroup;
|
export default ZoneGroup;
|
|
@ -22,8 +22,8 @@ const Project: React.FC = () => {
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
|
||||||
const { userName, setUserName } = useUserName();
|
const { setUserName } = useUserName();
|
||||||
const { organization, setOrganization } = useOrganization();
|
const { setOrganization } = useOrganization();
|
||||||
const { setFloorItems } = useFloorItems();
|
const { setFloorItems } = useFloorItems();
|
||||||
const { setWallItems } = useWallItems();
|
const { setWallItems } = useWallItems();
|
||||||
const { setZones } = useZones();
|
const { setZones } = useZones();
|
||||||
|
@ -50,21 +50,15 @@ const Project: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<div className="project-main">
|
<div className="project-main">
|
||||||
<ModuleToggle />
|
<ModuleToggle />
|
||||||
|
<SideBarLeft />
|
||||||
{!isPlaying && <SideBarLeft />}
|
<SideBarRight />
|
||||||
{!isPlaying && <SideBarRight />}
|
<RealTimeVisulization />
|
||||||
{activeModule === "visualization" && <RealTimeVisulization />}
|
{activeModule !== "market" && <Tools />}
|
||||||
{/* {activeModule !== "visualization" && <Scene />} */}
|
|
||||||
<Tools />
|
|
||||||
|
|
||||||
{/* <Scene /> */}
|
|
||||||
{/* <SimulationUI /> */}
|
{/* <SimulationUI /> */}
|
||||||
<div
|
<div
|
||||||
className="canvas-container"
|
className="canvas-container"
|
||||||
style={{ height: "100vh", width: "100vw" }}
|
style={{ height: "100vh", width: "100vw" }}
|
||||||
>
|
></div>
|
||||||
{activeModule !== "visualization" && <Scene />}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -141,7 +141,7 @@ const UserAuth: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
{!isSignIn && (
|
{!isSignIn && (
|
||||||
<div className="policy-checkbox">
|
<div className="policy-checkbox">
|
||||||
<input type="checkbox" name="" id="" />
|
<input type="checkbox" name="" id="" required/>
|
||||||
<div className="label">
|
<div className="label">
|
||||||
I have read and agree to the terms of service
|
I have read and agree to the terms of service
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
transition: width 0.2s;
|
transition: width 0.2s;
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
z-index: #{$z-index-tools};
|
z-index: #{$z-index-default};
|
||||||
.split {
|
.split {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 2px;
|
width: 2px;
|
||||||
|
|
|
@ -662,16 +662,30 @@
|
||||||
.collapse-header-container {
|
.collapse-header-container {
|
||||||
@include flex-space-between;
|
@include flex-space-between;
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
|
margin-top: 8px;
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
.header {
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.process-container {
|
.process-container {
|
||||||
|
padding: 0 12px;
|
||||||
|
margin: 6px 0;
|
||||||
.value {
|
.value {
|
||||||
|
@include flex-space-between;
|
||||||
.arrow-container {
|
.arrow-container {
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
}
|
}
|
||||||
.active {
|
.active {
|
||||||
|
rotate: 90deg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.children-drop {
|
.children-drop {
|
||||||
.value {
|
.value {
|
||||||
|
padding: 6px;
|
||||||
|
border-left: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -716,12 +730,17 @@
|
||||||
}
|
}
|
||||||
.global-properties-container,
|
.global-properties-container,
|
||||||
.analysis-main-container,
|
.analysis-main-container,
|
||||||
.asset-properties-container {
|
.asset-properties-container,
|
||||||
|
.zone-properties-container {
|
||||||
.header {
|
.header {
|
||||||
|
@include flex-space-between;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border-top: 1px solid var(--highlight-accent-color);
|
border-top: 1px solid var(--highlight-accent-color);
|
||||||
border-bottom: 1px solid var(--highlight-accent-color);
|
border-bottom: 1px solid var(--highlight-accent-color);
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
|
.input-value {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.input-container {
|
.input-container {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
|
@ -740,7 +759,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.optimize-button,
|
.optimize-button,
|
||||||
.generate-report-button {
|
.generate-report-button,
|
||||||
|
.button-save {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
|
@ -759,7 +779,11 @@
|
||||||
}
|
}
|
||||||
.custom-input-container {
|
.custom-input-container {
|
||||||
.header {
|
.header {
|
||||||
|
@include flex-space-between;
|
||||||
border: none;
|
border: none;
|
||||||
|
.eyedrop-button {
|
||||||
|
@include flex-center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.inputs-container {
|
.inputs-container {
|
||||||
@include flex-space-between;
|
@include flex-space-between;
|
||||||
|
|
|
@ -1,35 +1,155 @@
|
||||||
@use "../abstracts/variables.scss" as *;
|
@use "../abstracts/variables.scss" as *;
|
||||||
@use "../abstracts/mixins.scss" as *;
|
|
||||||
|
|
||||||
// Main Container
|
// Main Container
|
||||||
.realTime-viz {
|
.realTime-viz {
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
box-shadow: $box-shadow-medium;
|
box-shadow: $box-shadow-medium;
|
||||||
width: 100%;
|
width: calc(100% - (320px + 270px + 90px));
|
||||||
height: 100%;
|
height: calc(100% - (200px + 80px));
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 50%;
|
||||||
left: 0;
|
left: calc(270px + 45px);
|
||||||
transform: scale(1);
|
transform: translate(0, -50%);
|
||||||
|
border-radius: #{$border-radius-medium};
|
||||||
|
transition: all 0.2s;
|
||||||
|
z-index: #{$z-index-default};
|
||||||
|
|
||||||
.scene-container {
|
.scene-container {
|
||||||
width: 100%;
|
overflow: hidden;
|
||||||
height: 100%;
|
}
|
||||||
|
|
||||||
canvas {
|
.icon {
|
||||||
width: 100vw !important;
|
display: flex;
|
||||||
height: 100% !important;
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icons-container {
|
||||||
|
.icon {
|
||||||
|
&:first-child {
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Panels
|
|
||||||
|
.zoon-wrapper {
|
||||||
|
display: flex;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
gap: 6px;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 8px;
|
||||||
|
max-width: 80%;
|
||||||
|
overflow: auto;
|
||||||
|
max-width: calc(100% - 450px);
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zone {
|
||||||
|
width: auto;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: $small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
color: var(--background-color);
|
||||||
|
// color: #FCFDFD !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoon-wrapper.bottom {
|
||||||
|
bottom: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
width: 80%; // Increase width to take more space on smaller screens
|
||||||
|
height: 500px; // Reduce height to fit smaller screens
|
||||||
|
left: 50%; // Center horizontally
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
margin: 0 15px; // Reduce margin for better spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoon-wrapper {
|
||||||
|
bottom: 5px; // Adjust position for smaller screens
|
||||||
|
|
||||||
|
&.bottom {
|
||||||
|
bottom: 150px; // Adjust for bottom placement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-container {
|
||||||
|
display: flex;
|
||||||
|
height: 100vh;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
height: 600px;
|
||||||
|
background-color: rgb(235, 235, 235);
|
||||||
|
margin: 0 30px;
|
||||||
|
transition: height 0.3s ease, margin 0.3s ease;
|
||||||
|
|
||||||
|
.zoon-wrapper {
|
||||||
|
display: flex;
|
||||||
|
background-color: rgba(224, 223, 255, 0.5);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
gap: 6px;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 8px;
|
||||||
|
max-width: 80%;
|
||||||
|
overflow: auto;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zone {
|
||||||
|
width: auto;
|
||||||
|
background-color: $background-color;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bottom {
|
||||||
|
bottom: 210px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: white;
|
background: white;
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
overflow: hidden;
|
overflow: visible !important;
|
||||||
|
|
||||||
.panel-content {
|
.panel-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -46,7 +166,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-container {
|
.chart-container {
|
||||||
width: 229px;
|
width: 100%;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
border: 1px dotted #a9a9a9;
|
border: 1px dotted #a9a9a9;
|
||||||
|
@ -66,125 +186,54 @@
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Panels for each side
|
&.top-panel,
|
||||||
.left-panel,
|
&.bottom-panel {
|
||||||
.right-panel {
|
left: 0;
|
||||||
.chart-container {
|
right: 0;
|
||||||
padding: 10px;
|
|
||||||
width: 100% !important;
|
|
||||||
height: 250px !important;
|
|
||||||
|
|
||||||
}
|
.fullScreen {
|
||||||
}
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
.top-panel,
|
.panel-content {
|
||||||
.bottom-panel {
|
display: flex;
|
||||||
.chart-container {
|
flex-direction: row;
|
||||||
padding: 10px;
|
|
||||||
width: 300px !important;
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zone Wrapper
|
.chart-container {
|
||||||
.zoon-wrapper {
|
height: 100%;
|
||||||
display: flex;
|
width: 200px;
|
||||||
background-color: var(--background-color);
|
}
|
||||||
position: absolute;
|
}
|
||||||
bottom: 10px;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, 0);
|
|
||||||
gap: 6px;
|
|
||||||
padding: 4px;
|
|
||||||
border-radius: 8px;
|
|
||||||
max-width: 80%;
|
|
||||||
overflow: auto;
|
|
||||||
max-width: calc(100% - 450px);
|
|
||||||
z-index: 11000000000;
|
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.zone {
|
&.top-panel {
|
||||||
width: auto;
|
top: 0;
|
||||||
background-color: var(--background-color);
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
white-space: nowrap;
|
|
||||||
font-size: $small;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
&.bottom-panel {
|
||||||
background-color: var(--accent-color);
|
bottom: 0;
|
||||||
color: var(--background-color);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.zoon-wrapper.bottom {
|
&.left-panel {
|
||||||
bottom: 250px;
|
left: 0;
|
||||||
}
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
.content-container {
|
.chart-container {
|
||||||
display: flex;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 180px;
|
||||||
transition: all 0.3s ease;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-container {
|
&.right-panel {
|
||||||
position: relative;
|
right: 0;
|
||||||
flex: 1;
|
top: 0;
|
||||||
height: 600px;
|
bottom: 0;
|
||||||
background-color: rgb(235, 235, 235);
|
}
|
||||||
margin: 0 30px;
|
|
||||||
transition: height 0.3s ease, margin 0.3s ease;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.playActiveFalse {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: calc(270px + 45px);
|
|
||||||
transform-origin: left;
|
|
||||||
transform: translate(0, -50%) scaleX(0.6) scaleY(0.65);
|
|
||||||
width: calc((100vw * 1.65) - (320px + 270px + 70px) / 0.6);
|
|
||||||
z-index: 100;
|
|
||||||
|
|
||||||
.scene-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
canvas {
|
|
||||||
width: calc((100vw * 1.65) - (320px + 270px + 70px) / 0.6) !important;
|
|
||||||
height: 100% !important;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.top {
|
|
||||||
transform: scale(1.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.right {
|
|
||||||
transform: scale(1.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.bottom {
|
|
||||||
transform: scale(1.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.left {
|
|
||||||
transform: scale(1.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoon-wrapper {
|
|
||||||
transform: translate(-50%, 0) scale(1.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Side Buttons
|
// Side Buttons
|
||||||
.side-button-container {
|
.side-button-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -224,6 +273,7 @@
|
||||||
height: 18px;
|
height: 18px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
// align-items: center;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--background-color);
|
color: var(--background-color);
|
||||||
|
@ -231,54 +281,116 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.top {
|
&.top {
|
||||||
top: -35px;
|
top: -30px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
transform: scale(1.5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.right {
|
&.right {
|
||||||
right: -35px;
|
right: -30px;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
transform: scale(1.5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.bottom {
|
&.bottom {
|
||||||
bottom: -35px;
|
bottom: -30px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
transform: scale(1.5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.left {
|
&.left {
|
||||||
left: -35px;
|
left: -30px;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
transform: scale(1.5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.right.side-button-container,
|
.right.side-button-container {
|
||||||
|
.extra-Bs {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.left.side-button-container {
|
.left.side-button-container {
|
||||||
.extra-Bs {
|
.extra-Bs {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-panel,
|
// Theme Container
|
||||||
.bottom-panel {
|
.theme-container {
|
||||||
.panel-content {
|
width: 250px;
|
||||||
|
padding: 12px;
|
||||||
|
box-shadow: 1px -3px 4px 0px rgba(0, 0, 0, 0.11);
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: white;
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: -100%;
|
||||||
|
transform: translate(-0%, 0);
|
||||||
|
|
||||||
display: flex;
|
h2 {
|
||||||
flex-direction: row !important;
|
font-size: 12px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: #2b3344;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
.theme-preset-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.theme-preset {
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border: 1px solid $border-color;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: border 0.3s ease;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border: 1px solid var(--primary-color);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
left: 1px;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-color {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.color-displayer {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid var(--accent-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 5px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue