Merge remote-tracking branch 'origin/simulation' into realTimeVisulization

This commit is contained in:
gabriel 2025-04-01 19:14:03 +05:30
commit 2adbd7af24
23 changed files with 1003 additions and 228 deletions

View File

@ -7,8 +7,11 @@ REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000
# Base URL for the server REST API, used for HTTP requests to the backend server.
REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
# REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
REACT_APP_SERVER_MARKETPLACE_URL=192.168.0.111:3501
# Base URL for the server marketplace, used for market place model blob.
REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
# Base URL for the asset library server, used for asset library images and model blob id.
REACT_APP_SERVER_ASSET_LIBRARY_URL=192.168.0.111:3501
# base url for IoT socket server
REACT_APP_IOT_SOCKET_SERVER_URL =185.100.212.76:5010

View File

@ -29,13 +29,13 @@ export function DownloadIcon() {
fillRule="evenodd"
clipRule="evenodd"
d="M2.5 11.875C2.84518 11.875 3.125 12.1548 3.125 12.5C3.125 13.6962 3.12633 14.5304 3.21096 15.1599C3.29317 15.7714 3.44354 16.0952 3.67418 16.3258C3.90481 16.5565 4.22863 16.7068 4.8401 16.7891C5.46956 16.8737 6.30383 16.875 7.5 16.875H12.5C13.6962 16.875 14.5304 16.8737 15.1599 16.7891C15.7714 16.7068 16.0952 16.5565 16.3258 16.3258C16.5565 16.0952 16.7068 15.7714 16.7891 15.1599C16.8737 14.5304 16.875 13.6962 16.875 12.5C16.875 12.1548 17.1548 11.875 17.5 11.875C17.8452 11.875 18.125 12.1548 18.125 12.5V12.5458C18.125 13.6854 18.125 14.604 18.0279 15.3265C17.9271 16.0766 17.7113 16.7081 17.2097 17.2097C16.7081 17.7113 16.0766 17.9271 15.3265 18.0279C14.604 18.125 13.6854 18.125 12.5458 18.125H7.45428C6.31462 18.125 5.39602 18.125 4.67354 18.0279C3.92345 17.9271 3.29189 17.7113 2.79029 17.2097C2.28869 16.7081 2.07295 16.0766 1.9721 15.3265C1.87497 14.604 1.87498 13.6854 1.875 12.5458C1.875 12.5305 1.875 12.5152 1.875 12.5C1.875 12.1548 2.15483 11.875 2.5 11.875Z"
fill="#FCFDFD"
fill="var(--primary-color)"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10.0003 13.9583C10.1758 13.9583 10.3432 13.8846 10.4616 13.7551L13.7949 10.1093C14.0278 9.8545 14.0102 9.45917 13.7554 9.22625C13.5007 8.99333 13.1053 9.011 12.8724 9.26575L10.6253 11.7235V2.5C10.6253 2.15483 10.3455 1.875 10.0003 1.875C9.65516 1.875 9.37533 2.15483 9.37533 2.5V11.7235L7.12827 9.26575C6.89535 9.011 6.50002 8.99333 6.24527 9.22625C5.99052 9.45917 5.97281 9.8545 6.20573 10.1093L9.53908 13.7551C9.65749 13.8846 9.82483 13.9583 10.0003 13.9583Z"
fill="#FCFDFD"
fill="var(--primary-color)"
/>
</svg>
);
@ -52,13 +52,13 @@ export function EyeIconBig() {
>
<path
d="M2.75 11.918C6.05 4.58464 15.95 4.58464 19.25 11.918"
stroke="#2B3344"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M11 15.5859C10.6389 15.5859 10.2813 15.5148 9.94762 15.3766C9.61398 15.2384 9.31082 15.0358 9.05546 14.7805C8.80009 14.5251 8.59753 14.222 8.45933 13.8883C8.32113 13.5547 8.25 13.1971 8.25 12.8359C8.25 12.4748 8.32113 12.1172 8.45933 11.7836C8.59753 11.4499 8.80009 11.1468 9.05546 10.8914C9.31082 10.636 9.61398 10.4335 9.94762 10.2953C10.2813 10.1571 10.6389 10.0859 11 10.0859C11.7293 10.0859 12.4288 10.3757 12.9445 10.8914C13.4603 11.4071 13.75 12.1066 13.75 12.8359C13.75 13.5653 13.4603 14.2648 12.9445 14.7805C12.4288 15.2962 11.7293 15.5859 11 15.5859Z"
stroke="#2B3344"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
@ -80,7 +80,7 @@ export function CommentsIcon() {
fillRule="evenodd"
clipRule="evenodd"
d="M8 13C7.416 13 6.852 12.932 6.31 12.8165L3.956 14.2315L3.9875 11.912C2.183 10.827 1 9.033 1 7C1 3.6865 4.134 1 8 1C11.866 1 15 3.6865 15 7C15 10.314 11.866 13 8 13ZM8 0C3.582 0 0 3.1345 0 7C0 9.2095 1.1725 11.177 3 12.4595V16L6.5045 13.8735C6.9895 13.9535 7.4885 14 8 14C12.418 14 16 10.866 16 7C16 3.1345 12.418 0 8 0ZM11.5 5.5H4.5C4.224 5.5 4 5.724 4 6C4 6.2765 4.224 6.5 4.5 6.5H11.5C11.776 6.5 12 6.2765 12 6C12 5.724 11.776 5.5 11.5 5.5ZM10.5 8.5H5.5C5.224 8.5 5 8.7235 5 9C5 9.2765 5.224 9.5 5.5 9.5H10.5C10.776 9.5 11 9.2765 11 9C11 8.7235 10.776 8.5 10.5 8.5Z"
fill="#2B3344"
fill="var(--text-color)"
/>
</g>
<defs>
@ -105,7 +105,7 @@ export function VerifiedIcon() {
fillRule="evenodd"
clipRule="evenodd"
d="M4.7962 2.10014C4.67444 2.2039 4.61356 2.25579 4.54853 2.29937C4.39948 2.39927 4.23209 2.46861 4.05605 2.50336C3.97926 2.51853 3.89952 2.52489 3.74004 2.53761C3.33935 2.56959 3.139 2.58558 2.97186 2.64462C2.58526 2.78117 2.28117 3.08526 2.14462 3.47186C2.08558 3.639 2.06959 3.83935 2.03761 4.24004C2.02489 4.39952 2.01853 4.47926 2.00336 4.55605C1.96861 4.73209 1.89927 4.89948 1.79937 5.04853C1.75579 5.11356 1.70391 5.17444 1.60014 5.2962C1.33942 5.60215 1.20905 5.7551 1.13261 5.91505C0.955796 6.285 0.955796 6.715 1.13261 7.08495C1.20906 7.2449 1.33942 7.39785 1.60014 7.7038C1.70389 7.82555 1.75579 7.88645 1.79937 7.95145C1.89927 8.1005 1.96861 8.2679 2.00336 8.44395C2.01853 8.52075 2.02489 8.6005 2.03761 8.75995C2.06959 9.16065 2.08558 9.361 2.14462 9.52815C2.28117 9.91475 2.58526 10.2189 2.97186 10.3554C3.139 10.4144 3.33935 10.4304 3.74004 10.4624C3.89952 10.4751 3.97926 10.4815 4.05605 10.4966C4.23209 10.5314 4.39948 10.6007 4.54853 10.7007C4.61356 10.7442 4.67444 10.7961 4.7962 10.8998C5.10215 11.1606 5.2551 11.2909 5.41505 11.3674C5.785 11.5442 6.215 11.5442 6.58495 11.3674C6.7449 11.2909 6.89785 11.1606 7.2038 10.8998C7.32555 10.7961 7.38645 10.7442 7.45145 10.7007C7.6005 10.6007 7.7679 10.5314 7.94395 10.4966C8.02075 10.4815 8.1005 10.4751 8.25995 10.4624C8.66065 10.4304 8.861 10.4144 9.02815 10.3554C9.41475 10.2189 9.71885 9.91475 9.8554 9.52815C9.9144 9.361 9.9304 9.16065 9.9624 8.75995C9.9751 8.6005 9.9815 8.52075 9.99665 8.44395C10.0314 8.2679 10.1007 8.1005 10.2007 7.95145C10.2442 7.88645 10.2961 7.82555 10.3998 7.7038C10.6606 7.39785 10.7909 7.2449 10.8674 7.08495C11.0442 6.715 11.0442 6.285 10.8674 5.91505C10.7909 5.7551 10.6606 5.60215 10.3998 5.2962C10.2961 5.17444 10.2442 5.11356 10.2007 5.04853C10.1007 4.89948 10.0314 4.73209 9.99665 4.55605C9.9815 4.47926 9.9751 4.39952 9.9624 4.24004C9.9304 3.83935 9.9144 3.639 9.8554 3.47186C9.71885 3.08526 9.41475 2.78117 9.02815 2.64462C8.861 2.58558 8.66065 2.56959 8.25995 2.53761C8.1005 2.52489 8.02075 2.51853 7.94395 2.50336C7.7679 2.46861 7.6005 2.39927 7.45145 2.29937C7.38645 2.25579 7.32555 2.20391 7.2038 2.10014C6.89785 1.83942 6.7449 1.70906 6.58495 1.63261C6.215 1.4558 5.785 1.4558 5.41505 1.63261C5.2551 1.70905 5.10215 1.83942 4.7962 2.10014ZM8.18675 5.43157C8.34565 5.27265 8.34565 5.015 8.18675 4.85608C8.02785 4.69717 7.77015 4.69717 7.61125 4.85608L5.18615 7.2812L4.38873 6.4838C4.22982 6.3249 3.97216 6.3249 3.81325 6.4838C3.65433 6.6427 3.65433 6.90035 3.81325 7.0593L4.89839 8.14445C5.0573 8.30335 5.31495 8.30335 5.4739 8.14445L8.18675 5.43157Z"
fill="#6F42C1"
fill="var(--accent-color)"
/>
</svg>
);

View File

@ -40,7 +40,6 @@ const GlobalProperties: React.FC = () => {
}
function updateDistance(value: number) {
console.log("value: ", value);
setDistance(value);
setRenderDistance(value);
}
@ -61,7 +60,7 @@ const GlobalProperties: React.FC = () => {
!roofVisibility,
shadows
);
// console.log('data: ', data);
//
//using Socket
// const visData = {
@ -88,7 +87,7 @@ const GlobalProperties: React.FC = () => {
roofVisibility,
shadows
);
// console.log('data: ', data);
//
//using Socket
// const visData = {
@ -115,7 +114,7 @@ const GlobalProperties: React.FC = () => {
roofVisibility,
!shadows
);
// console.log('data: ', data);
//
//using Socket
// const visData = {

View File

@ -119,7 +119,7 @@ const Data = () => {
};
});
};
console.log("selectedChartId", selectedChartId);
// console.log("selectedChartId", selectedChartId);
return (
<div className="dataSideBar">

View File

@ -15,7 +15,6 @@ interface DisplayZoneProps {
[key: string]: {
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
widgets: Widget[];
zoneId: string;
@ -27,7 +26,6 @@ interface DisplayZoneProps {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
@ -45,7 +43,6 @@ interface DisplayZoneProps {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
@ -66,9 +63,9 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
selectedZone,
setSelectedZone,
}) => {
// Ref for the container element
// Refs
const containerRef = useRef<HTMLDivElement | null>(null);
const scrollContainerRef = useRef<HTMLDivElement | null>(null);
// State to track overflow visibility
const [showLeftArrow, setShowLeftArrow] = useState(false);
@ -78,8 +75,7 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
// Function to calculate overflow state
const updateOverflowState = useCallback(() => {
const container = containerRef.current;
const container = scrollContainerRef.current;
if (container) {
const isOverflowing = container.scrollWidth > container.clientWidth;
const canScrollLeft = container.scrollLeft > 0;
@ -92,59 +88,56 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
}, []);
useEffect(() => {
const container = containerRef.current;
const container = scrollContainerRef.current;
if (!container) return;
if (container) {
// Initial calculation after the DOM has been rendered
const handleInitialRender = () => {
requestAnimationFrame(updateOverflowState);
};
// Initial calculation after the DOM has been rendered
const observer = new ResizeObserver(updateOverflowState);
observer.observe(container);
handleInitialRender();
// Update on scroll
const handleScroll = () => updateOverflowState();
container.addEventListener("scroll", handleScroll);
// Update on window resize or scroll
const handleResize = () => updateOverflowState();
const handleScroll = () => updateOverflowState();
// Add mouse wheel listener for horizontal scrolling
const handleWheel = (event: WheelEvent) => {
if (Math.abs(event.deltaY) > Math.abs(event.deltaX)) {
event.preventDefault();
container.scrollBy({
left: event.deltaY * 2,
behavior: "smooth",
});
}
};
// Add mouse wheel listener for horizontal scrolling
const handleWheel = (event: WheelEvent) => {
event.preventDefault(); // Prevent default vertical scrolling
if (container) {
container.scrollBy({
left: event.deltaY * 2, // Translate vertical scroll to horizontal scroll
behavior: "smooth",
});
}
};
container.addEventListener("wheel", handleWheel, { passive: false });
container.addEventListener("scroll", handleScroll);
window.addEventListener("resize", handleResize);
container.addEventListener("wheel", handleWheel, { passive: false });
// Initial check
updateOverflowState();
return () => {
container.removeEventListener("scroll", handleScroll);
window.removeEventListener("resize", handleResize);
container.removeEventListener("wheel", handleWheel);
};
}
return () => {
observer.disconnect();
container.removeEventListener("scroll", handleScroll);
container.removeEventListener("wheel", handleWheel);
};
}, [updateOverflowState]);
// Handle scrolling with navigation arrows
const handleScrollLeft = () => {
const container = containerRef.current;
const container = scrollContainerRef.current;
if (container) {
container.scrollBy({
left: -200, // Scroll left by 200px
left: -200,
behavior: "smooth",
});
}
};
const handleScrollRight = () => {
const container = containerRef.current;
const container = scrollContainerRef.current;
if (container) {
container.scrollBy({
left: 200, // Scroll right by 200px
left: 200,
behavior: "smooth",
});
}
@ -158,19 +151,18 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
setSelectedChartId(null)
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
// Fetch data from backend
let response = await getSelect2dZoneData(zoneId, organization);
console.log('response: ', response);
let res = await getFloatingZoneData(zoneId, organization);
setFloatingWidget(res)
// Set the selected zone in the store
setFloatingWidget(res);
useDroppedObjectsStore.getState().setZone(zoneName, zoneId);
if (Array.isArray(res)) {
res.forEach((val) => {
useDroppedObjectsStore.getState().addObject(zoneName, val);
});
}
// Update selected zone state
setSelectedZone({
zoneName,
activeSides: response.activeSides || [],
@ -182,17 +174,14 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
zoneViewPortPosition: response.viewPortposition || {},
});
} catch (error) {
console.error(error);
}
}
return (
<div
ref={containerRef}
className={`zone-wrapper ${selectedZone?.activeSides?.includes("bottom") && "bottom"
}`}
className={`zone-wrapper ${selectedZone?.activeSides?.includes("bottom") ? "bottom" : ""}`}
>
{/* Left Arrow */}
{showLeftArrow && (
@ -201,28 +190,31 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
</button>
)}
{/* Zones Wrapper */}
{Object.keys(zonesData).length !== 0 ? (
<div ref={containerRef} className="zones-wrapper">
{Object.keys(zonesData).map((zoneName, index) => (
<div
key={index}
className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""
}`}
onClick={() => {
handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)
}}
>
{zoneName}
</div>
))}
</div>
) : (
<div className="no-zone">
<InfoIcon />
No zones? Create one!
</div>
)}
{/* Scrollable Zones Container */}
<div
ref={scrollContainerRef}
className="zones-wrapper"
style={{ overflowX: "auto", whiteSpace: "nowrap" }}
>
{Object.keys(zonesData).length !== 0 ? (
<>
{Object.keys(zonesData).map((zoneName, index) => (
<div
key={index}
className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""}`}
onClick={() => handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)}
>
{zoneName}
</div>
))}
</>
) : (
<div className="no-zone">
<InfoIcon />
No zones? Create one!
</div>
)}
</div>
{/* Right Arrow */}
{showRightArrow && (

View File

@ -1,93 +0,0 @@
import React from "react";
interface DistanceLinesProps {
obj: {
position: {
top?: number | "auto";
left?: number | "auto";
right?: number | "auto";
bottom?: number | "auto";
};
};
activeEdges: {
vertical: "top" | "bottom";
horizontal: "left" | "right";
} | null;
}
const DistanceLines: React.FC<DistanceLinesProps> = ({ obj, activeEdges }) => {
if (!activeEdges) return null;
return (
<>
{activeEdges.vertical === "top" && typeof obj.position.top === "number" && (
<div
className="distance-line top"
style={{
top: 0,
left:
activeEdges.horizontal === "left"
? `${(obj.position.left as number) + 125}px`
: `calc(100% - ${(obj.position.right as number) + 125}px)`,
height: `${obj.position.top}px`,
}}
>
<span className="distance-label">{obj.position.top.toFixed()}px</span>
</div>
)}
{activeEdges.vertical === "bottom" &&
typeof obj.position.bottom === "number" && (
<div
className="distance-line bottom"
style={{
bottom: 0,
left:
activeEdges.horizontal === "left"
? `${(obj.position.left as number) + 125}px`
: `calc(100% - ${(obj.position.right as number) + 125}px)`,
height: `${obj.position.bottom}px`,
}}
>
<span className="distance-label">{obj.position.bottom.toFixed()}px</span>
</div>
)}
{activeEdges.horizontal === "left" &&
typeof obj.position.left === "number" && (
<div
className="distance-line left"
style={{
left: 0,
top:
activeEdges.vertical === "top"
? `${(obj.position.top as number) + 41.5}px`
: `calc(100% - ${(obj.position.bottom as number) + 41.5}px)`,
width: `${obj.position.left}px`,
}}
>
<span className="distance-label">{obj.position.left.toFixed()}px</span>
</div>
)}
{activeEdges.horizontal === "right" &&
typeof obj.position.right === "number" && (
<div
className="distance-line right"
style={{
right: 0,
top:
activeEdges.vertical === "top"
? `${(obj.position.top as number) + 41.5}px`
: `calc(100% - ${(obj.position.bottom as number) + 41.5}px)`,
width: `${obj.position.right}px`,
}}
>
<span className="distance-label">{obj.position.right.toFixed()}px</span>
</div>
)}
</>
);
};
export default DistanceLines;

View File

@ -20,21 +20,31 @@ const DistanceLines: React.FC<DistanceLinesProps> = ({ obj, activeEdges }) => {
return (
<>
{activeEdges.vertical === "top" && typeof obj.position.top === "number" && (
<div
className="distance-line top"
style={{
top: 0,
left:
activeEdges.horizontal === "left"
? `${(obj.position.left as number) + 125}px`
: `calc(100% - ${(obj.position.right as number) + 125}px)`,
height: `${obj.position.top}px`,
}}
>
<span className="distance-label">{obj.position.top}px</span>
</div>
)}
{activeEdges.vertical === "top" &&
typeof obj.position.top === "number" && (
<div
className="distance-line top"
style={{
top: 0,
left:
activeEdges.horizontal === "left"
? `${(obj.position.left as number) + 125}px`
: `calc(100% - ${(obj.position.right as number) + 125}px)`,
height: `${obj.position.top}px`,
}}
>
<span
className="distance-label"
style={{
position: "absolute",
top: "50%",
transform: "translate(-50%,0%)",
}}
>
{obj.position.top}px
</span>
</div>
)}
{activeEdges.vertical === "bottom" &&
typeof obj.position.bottom === "number" && (
@ -49,7 +59,16 @@ const DistanceLines: React.FC<DistanceLinesProps> = ({ obj, activeEdges }) => {
height: `${obj.position.bottom}px`,
}}
>
<span className="distance-label">{obj.position.bottom}px</span>
<span
className="distance-label"
style={{
position: "absolute",
bottom: "50%",
transform: "translate(-50%,0%)",
}}
>
{obj.position.bottom}px
</span>
</div>
)}
@ -66,7 +85,16 @@ const DistanceLines: React.FC<DistanceLinesProps> = ({ obj, activeEdges }) => {
width: `${obj.position.left}px`,
}}
>
<span className="distance-label">{obj.position.left}px</span>
<span
className="distance-label"
style={{
position: "absolute",
left: "50%",
transform: "translate(0,-50%)",
}}
>
{obj.position.left}px
</span>
</div>
)}
@ -83,11 +111,20 @@ const DistanceLines: React.FC<DistanceLinesProps> = ({ obj, activeEdges }) => {
width: `${obj.position.right}px`,
}}
>
<span className="distance-label">{obj.position.right}px</span>
<span
className="distance-label"
style={{
position: "absolute",
right: "50%",
transform: "translate(0,-50%)",
}}
>
{obj.position.right}px
</span>
</div>
)}
</>
);
};
export default DistanceLines;
export default DistanceLines;

View File

@ -148,7 +148,6 @@ async function handleModelLoad(
const organization = email ? email.split("@")[1].split(".")[0] : "";
getAssetEventType(selectedItem.id, organization).then(async (res) => {
console.log('res: ', res);
if (res.type === "Conveyor") {
const pointUUIDs = res.points.map(() => THREE.MathUtils.generateUUID());

View File

@ -306,8 +306,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
}, [deleteModels, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool, activeModule]);
useEffect(() => {
console.log('floorItems: ', floorItems);
// console.log('floorItems: ', floorItems);
}, [floorItems])
useFrame(() => {

View File

@ -19,7 +19,6 @@ async function loadInitialFloorItems(
const organization = (email!.split("@")[1]).split(".")[0];
const items = await getFloorAssets(organization);
console.log('items: ', items);
localStorage.setItem("FloorItems", JSON.stringify(items));
await initializeDB();
@ -133,7 +132,7 @@ async function loadInitialFloorItems(
modelfileID: item.modelfileID,
isLocked: item.isLocked,
isVisible: item.isVisible,
eventData: item.eventData,
// eventData: item.eventData,
},
]);
} else {
@ -198,7 +197,7 @@ function processLoadedModel(
modelfileID: item.modelfileID,
isLocked: item.isLocked,
isVisible: item.isVisible,
eventData: item.eventData,
// eventData: item.eventData,
},
]);
} else {

View File

@ -1,6 +1,6 @@
import { useMemo } from "react";
import { Canvas } from "@react-three/fiber";
import { Environment, KeyboardControls } from "@react-three/drei";
import { Environment, KeyboardControls, Stars } from "@react-three/drei";
import World from "./world/world";
import Controls from "./controls/controls";
@ -50,7 +50,7 @@ export default function Scene() {
<ZoneCentreTarget />
<Simulation />
<PostProcessing />
{savedTheme !== "dark" && <Sun />}
{savedTheme !== "dark" ? <Sun /> : <></>}
<Shadows />
<CamModelsGroup />
<MqttEvents />

View File

@ -12,14 +12,15 @@ function Behaviour() {
floorItems.forEach((item: Types.FloorItemType) => {
if (item.modelfileID === "672a090f80d91ac979f4d0bd") {
console.log('item: ', item);
const point1Position = new THREE.Vector3(0, 0.85, 2.2);
const middlePointPosition = new THREE.Vector3(0, 0.85, 0);
const point2Position = new THREE.Vector3(0, 0.85, -2.2);
const point1UUID = THREE.MathUtils.generateUUID();
const middlePointUUID = THREE.MathUtils.generateUUID();
const point2UUID = THREE.MathUtils.generateUUID();
const newPath: Types.ConveyorEventsSchema = {
modeluuid: item.modeluuid,
modelName: item.modelname,
@ -29,7 +30,7 @@ function Behaviour() {
uuid: point1UUID,
position: [point1Position.x, point1Position.y, point1Position.z],
rotation: [0, 0, 0],
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }],
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
triggers: [],
connections: { source: { pathUUID: item.modeluuid, pointUUID: point1UUID }, targets: [] },
},
@ -37,7 +38,7 @@ function Behaviour() {
uuid: middlePointUUID,
position: [middlePointPosition.x, middlePointPosition.y, middlePointPosition.z],
rotation: [0, 0, 0],
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }],
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
triggers: [],
connections: { source: { pathUUID: item.modeluuid, pointUUID: middlePointUUID }, targets: [] },
},
@ -45,7 +46,7 @@ function Behaviour() {
uuid: point2UUID,
position: [point2Position.x, point2Position.y, point2Position.z],
rotation: [0, 0, 0],
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }],
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
triggers: [],
connections: { source: { pathUUID: item.modeluuid, pointUUID: point2UUID }, targets: [] },
},

View File

@ -0,0 +1,416 @@
import React, { useRef, useState, useEffect, useMemo } from "react";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import { GLTFLoader } from "three-stdlib";
import { useLoader, useFrame } from "@react-three/fiber";
import * as THREE from "three";
import { GLTF } from "three-stdlib";
import boxGltb from "../../../assets/gltf-glb/crate_box.glb";
interface PointAction {
uuid: string;
name: string;
type: "Inherit" | "Spawn" | "Despawn" | "Delay" | "Swap";
material: string;
delay: string | number;
spawnInterval: string | number;
isUsed: boolean;
}
interface ProcessPoint {
uuid: string;
position: number[];
rotation: number[];
actions: PointAction[];
connections: {
source: { pathUUID: string; pointUUID: string };
targets: { pathUUID: string; pointUUID: string }[];
};
}
interface ProcessPath {
modeluuid: string;
modelName: string;
points: ProcessPoint[];
pathPosition: number[];
pathRotation: number[];
speed: number;
}
interface ProcessData {
id: string;
paths: ProcessPath[];
animationPath: { x: number; y: number; z: number }[];
pointActions: PointAction[][];
speed: number;
}
interface AnimationState {
currentIndex: number;
progress: number;
isAnimating: boolean;
speed: number;
isDelaying: boolean;
delayStartTime: number;
currentDelayDuration: number;
delayComplete: boolean;
currentPathIndex: number;
spawnPoints: Record<
string,
{
position: THREE.Vector3;
interval: number;
lastSpawnTime: number;
}
>;
}
const MAX_SPAWNED_OBJECTS = 20;
const ProcessAnimator: React.FC<{ processes: ProcessData[] }> = ({
processes,
}) => {
console.log("processes: ", processes);
const gltf = useLoader(GLTFLoader, boxGltb) as GLTF;
const { isPlaying, setIsPlaying } = usePlayButtonStore();
const groupRef = useRef<THREE.Group>(null);
const meshRef = useRef<THREE.Mesh>(null);
const [visible, setVisible] = useState(false);
const spawnedObjectsRef = useRef<THREE.Object3D[]>([]);
const materials = useMemo(
() => ({
Wood: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
Box: new THREE.MeshStandardMaterial({
color: 0xcccccc,
metalness: 0.8,
roughness: 0.2,
}),
Crate: new THREE.MeshStandardMaterial({
color: 0x00aaff,
metalness: 0.1,
roughness: 0.5,
}),
Default: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
}),
[]
);
const [currentMaterial, setCurrentMaterial] = useState<THREE.Material>(
materials.Default
);
const { animationPath, currentProcess } = useMemo(() => {
const defaultProcess = {
animationPath: [],
pointActions: [],
speed: 1,
paths: [],
};
const cp = processes?.[0] || defaultProcess;
return {
animationPath:
cp.animationPath?.map((p) => new THREE.Vector3(p.x, p.y, p.z)) || [],
currentProcess: cp,
};
}, [processes]);
const animationStateRef = useRef<AnimationState>({
currentIndex: 0,
progress: 0,
isAnimating: false,
speed: currentProcess.speed,
isDelaying: false,
delayStartTime: 0,
currentDelayDuration: 0,
delayComplete: false,
currentPathIndex: 0,
spawnPoints: {},
});
const getPointDataForAnimationIndex = (index: number) => {
if (!processes[0]?.paths) return null;
if (index < 3) {
return processes[0].paths[0]?.points[index];
} else {
const path2Index = index - 3;
return processes[0].paths[1]?.points[path2Index];
}
};
useEffect(() => {
if (isPlaying) {
setVisible(true);
animationStateRef.current = {
currentIndex: 0,
progress: 0,
isAnimating: true,
speed: currentProcess.speed,
isDelaying: false,
delayStartTime: 0,
currentDelayDuration: 0,
delayComplete: false,
currentPathIndex: 0,
spawnPoints: {},
};
// Clear spawned objects
if (groupRef.current) {
spawnedObjectsRef.current.forEach((obj) => {
if (groupRef.current?.children.includes(obj)) {
groupRef.current.remove(obj);
}
if (obj instanceof THREE.Mesh) {
obj.material.dispose();
}
});
spawnedObjectsRef.current = [];
}
const currentRef = gltf?.scene ? groupRef.current : meshRef.current;
if (currentRef && animationPath.length > 0) {
currentRef.position.copy(animationPath[0]);
}
} else {
animationStateRef.current.isAnimating = false;
}
}, [isPlaying, currentProcess, animationPath]);
const handleMaterialSwap = (materialType: string) => {
const newMaterial =
materials[materialType as keyof typeof materials] || materials.Default;
setCurrentMaterial(newMaterial);
spawnedObjectsRef.current.forEach((obj) => {
if (obj instanceof THREE.Mesh) {
obj.material = newMaterial.clone();
}
});
};
const hasNonInheritActions = (actions: PointAction[] = []) => {
return actions.some((action) => action.isUsed && action.type !== "Inherit");
};
const handlePointActions = (
actions: PointAction[] = [],
currentTime: number,
currentPosition: THREE.Vector3
) => {
let shouldStopAnimation = false;
actions.forEach((action) => {
if (!action.isUsed) return;
switch (action.type) {
case "Delay":
if (
!animationStateRef.current.isDelaying &&
!animationStateRef.current.delayComplete
) {
const delayDuration =
typeof action.delay === "number"
? action.delay
: parseFloat(action.delay as string) || 0;
if (delayDuration > 0) {
animationStateRef.current.isDelaying = true;
animationStateRef.current.delayStartTime = currentTime;
animationStateRef.current.currentDelayDuration = delayDuration;
shouldStopAnimation = true;
}
}
break;
case "Despawn":
setVisible(false);
setIsPlaying(false);
animationStateRef.current.isAnimating = false;
shouldStopAnimation = true;
break;
case "Spawn":
const spawnInterval =
typeof action.spawnInterval === "number"
? action.spawnInterval
: parseFloat(action.spawnInterval as string) || 1;
const positionKey = currentPosition.toArray().join(",");
animationStateRef.current.spawnPoints[positionKey] = {
position: currentPosition.clone(),
interval: spawnInterval,
lastSpawnTime: currentTime - spawnInterval, // Force immediate spawn
};
break;
case "Swap":
if (action.material) {
handleMaterialSwap(action.material);
}
break;
case "Inherit":
break;
}
});
return shouldStopAnimation;
};
useFrame((state, delta) => {
const currentRef = gltf?.scene ? groupRef.current : meshRef.current;
if (
!currentRef ||
!animationStateRef.current.isAnimating ||
animationPath.length < 2
) {
return;
}
const currentTime = state.clock.getElapsedTime();
const path = animationPath;
const stateRef = animationStateRef.current;
if (stateRef.currentIndex === 3 && stateRef.currentPathIndex === 0) {
stateRef.currentPathIndex = 1;
}
const currentPointData = getPointDataForAnimationIndex(
stateRef.currentIndex
);
if (stateRef.progress === 0 && currentPointData?.actions) {
const shouldStop = handlePointActions(
currentPointData.actions,
currentTime,
currentRef.position
);
if (shouldStop) return;
}
if (stateRef.isDelaying) {
if (
currentTime - stateRef.delayStartTime >=
stateRef.currentDelayDuration
) {
stateRef.isDelaying = false;
stateRef.delayComplete = true;
} else {
return;
}
}
// Handle spawning - this is the key updated part
Object.entries(stateRef.spawnPoints).forEach(([key, spawnPoint]) => {
if (currentTime - spawnPoint.lastSpawnTime >= spawnPoint.interval) {
spawnPoint.lastSpawnTime = currentTime;
if (gltf?.scene && groupRef?.current) {
const newObject = gltf.scene.clone();
newObject.position.copy(spawnPoint.position);
newObject.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.material = currentMaterial.clone();
}
});
groupRef.current.add(newObject);
spawnedObjectsRef.current.push(newObject);
// Clean up old objects if needed
console.log(
"spawnedObjectsRef.current.length: ",
spawnedObjectsRef.current.length
);
if (spawnedObjectsRef.current.length > MAX_SPAWNED_OBJECTS) {
const oldest = spawnedObjectsRef.current.shift();
if (oldest && groupRef.current.children.includes(oldest)) {
groupRef.current.remove(oldest);
if (oldest instanceof THREE.Mesh) {
oldest.material.dispose();
}
}
}
}
}
});
const nextPointIdx = stateRef.currentIndex + 1;
const isLastPoint = nextPointIdx >= path.length;
if (isLastPoint) {
if (currentPointData?.actions) {
const shouldStop = !hasNonInheritActions(currentPointData.actions);
if (shouldStop) {
currentRef.position.copy(path[stateRef.currentIndex]);
setIsPlaying(false);
stateRef.isAnimating = false;
return;
}
}
}
if (!isLastPoint) {
const nextPoint = path[nextPointIdx];
const distance = path[stateRef.currentIndex].distanceTo(nextPoint);
const movement = stateRef.speed * delta;
stateRef.progress += movement / distance;
if (stateRef.progress >= 1) {
stateRef.currentIndex = nextPointIdx;
stateRef.progress = 0;
stateRef.delayComplete = false;
currentRef.position.copy(nextPoint);
} else {
currentRef.position.lerpVectors(
path[stateRef.currentIndex],
nextPoint,
stateRef.progress
);
}
}
});
useEffect(() => {
return () => {
if (groupRef.current) {
spawnedObjectsRef.current.forEach((obj) => {
if (groupRef.current?.children.includes(obj)) {
groupRef.current.remove(obj);
}
if (obj instanceof THREE.Mesh) {
obj.material.dispose();
}
});
spawnedObjectsRef.current = [];
}
};
}, []);
if (!processes || processes.length === 0) {
return null;
}
if (!gltf?.scene) {
return visible ? (
<mesh ref={meshRef} material={currentMaterial}>
<boxGeometry args={[1, 1, 1]} />
</mesh>
) : null;
}
return visible ? (
<group ref={groupRef}>
<primitive
object={gltf.scene.clone()}
scale={[1, 1, 1]}
material={currentMaterial}
/>
</group>
) : null;
};
export default ProcessAnimator;

View File

@ -0,0 +1,17 @@
import React, { useState } from "react";
import ProcessCreator from "./processCreator";
import ProcessAnimator from "./processAnimator";
const ProcessContainer: React.FC = () => {
const [processes, setProcesses] = useState<any[]>([]);
return (
<>
<ProcessCreator onProcessesCreated={setProcesses} />
{processes.length > 0 && <ProcessAnimator processes={processes} />}
</>
);
};
export default ProcessContainer;

View File

@ -0,0 +1,398 @@
import React, {
useEffect,
useMemo,
useState,
useCallback,
useRef,
} from "react";
import { useSimulationPaths } from "../../../store/store";
import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import {
ConveyorEventsSchema,
VehicleEventsSchema,
} from "../../../types/world/worldTypes";
// Type definitions
export interface PointAction {
uuid: string;
name: string;
type: string;
material: string;
delay: number | string;
spawnInterval: string | number;
isUsed: boolean;
}
export interface PathPoint {
uuid: string;
position: [number, number, number];
actions: PointAction[];
connections: {
targets: Array<{ pathUUID: string }>;
};
}
export interface SimulationPath {
modeluuid: string;
points: PathPoint[];
pathPosition: [number, number, number];
speed?: number;
}
export interface Process {
id: string;
paths: SimulationPath[];
animationPath: THREE.Vector3[];
pointActions: PointAction[][];
speed: number;
}
interface ProcessCreatorProps {
onProcessesCreated: (processes: Process[]) => void;
}
// Convert event schemas to SimulationPath
function convertToSimulationPath(
path: ConveyorEventsSchema | VehicleEventsSchema
): SimulationPath {
const { modeluuid } = path;
// Simplified normalizeAction function that preserves exact original properties
const normalizeAction = (action: any): PointAction => {
return { ...action }; // Return exact copy with no modifications
};
if (path.type === "Conveyor") {
return {
modeluuid,
points: path.points.map((point) => ({
uuid: point.uuid,
position: point.position,
actions: point.actions.map(normalizeAction), // Preserve exact actions
connections: {
targets: point.connections.targets.map((target) => ({
pathUUID: target.pathUUID,
})),
},
})),
pathPosition: path.position,
speed:
typeof path.speed === "string"
? parseFloat(path.speed) || 1
: path.speed || 1,
};
} else {
return {
modeluuid,
points: [
{
uuid: path.point.uuid,
position: path.point.position,
actions: Array.isArray(path.point.actions)
? path.point.actions.map(normalizeAction)
: [normalizeAction(path.point.actions)],
connections: {
targets: path.point.connections.targets.map((target) => ({
pathUUID: target.pathUUID,
})),
},
},
],
pathPosition: path.position,
speed: path.point.speed || 1,
};
}
}
// Custom shallow comparison for arrays
const areArraysEqual = (a: any[], b: any[]) => {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
};
// Helper function to create an empty process
const createEmptyProcess = (): Process => ({
id: `process-${Math.random().toString(36).substring(2, 11)}`,
paths: [],
animationPath: [],
pointActions: [],
speed: 1,
});
// Enhanced connection checking function
function shouldReverseNextPath(
currentPath: SimulationPath,
nextPath: SimulationPath
): boolean {
if (nextPath.points.length !== 3) return false;
const currentLastPoint = currentPath.points[currentPath.points.length - 1];
const nextFirstPoint = nextPath.points[0];
const nextLastPoint = nextPath.points[nextPath.points.length - 1];
// Check if current last connects to next last (requires reversal)
const connectsToLast = currentLastPoint.connections.targets.some(
(target) =>
target.pathUUID === nextPath.modeluuid &&
nextLastPoint.connections.targets.some(
(t) => t.pathUUID === currentPath.modeluuid
)
);
// Check if current last connects to next first (no reversal needed)
const connectsToFirst = currentLastPoint.connections.targets.some(
(target) =>
target.pathUUID === nextPath.modeluuid &&
nextFirstPoint.connections.targets.some(
(t) => t.pathUUID === currentPath.modeluuid
)
);
// Only reverse if connected to last point and not to first point
return connectsToLast && !connectsToFirst;
}
// Updated path adjustment function
function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] {
if (paths.length < 2) return paths;
const adjustedPaths = [...paths];
for (let i = 0; i < adjustedPaths.length - 1; i++) {
const currentPath = adjustedPaths[i];
const nextPath = adjustedPaths[i + 1];
if (shouldReverseNextPath(currentPath, nextPath)) {
const reversedPoints = [
nextPath.points[2],
nextPath.points[1],
nextPath.points[0],
];
adjustedPaths[i + 1] = {
...nextPath,
points: reversedPoints,
};
}
}
return adjustedPaths;
}
// Main hook for process creation
export function useProcessCreation() {
const { scene } = useThree();
const [processes, setProcesses] = useState<Process[]>([]);
const hasSpawnAction = useCallback((path: SimulationPath): boolean => {
return path.points.some((point) =>
point.actions.some((action) => action.type.toLowerCase() === "spawn")
);
}, []);
const createProcess = useCallback(
(paths: SimulationPath[]): Process => {
if (!paths || paths.length === 0) {
return createEmptyProcess();
}
const animationPath: THREE.Vector3[] = [];
const pointActions: PointAction[][] = [];
const processSpeed = paths[0]?.speed || 1;
for (const path of paths) {
for (const point of path.points) {
const obj = scene.getObjectByProperty("uuid", point.uuid);
if (!obj) {
console.warn(`Object with UUID ${point.uuid} not found in scene`);
continue;
}
const position = obj.getWorldPosition(new THREE.Vector3());
animationPath.push(position.clone());
pointActions.push(point.actions);
}
}
return {
id: `process-${Math.random().toString(36).substring(2, 11)}`,
paths,
animationPath,
pointActions,
speed: processSpeed,
};
},
[scene]
);
const getAllConnectedPaths = useCallback(
(
initialPath: SimulationPath,
allPaths: SimulationPath[],
visited: Set<string> = new Set()
): SimulationPath[] => {
const connectedPaths: SimulationPath[] = [];
const queue: SimulationPath[] = [initialPath];
visited.add(initialPath.modeluuid);
const pathMap = new Map<string, SimulationPath>();
allPaths.forEach((path) => pathMap.set(path.modeluuid, path));
while (queue.length > 0) {
const currentPath = queue.shift()!;
connectedPaths.push(currentPath);
// Process outgoing connections
for (const point of currentPath.points) {
for (const target of point.connections.targets) {
if (!visited.has(target.pathUUID)) {
const targetPath = pathMap.get(target.pathUUID);
if (targetPath) {
visited.add(target.pathUUID);
queue.push(targetPath);
}
}
}
}
// Process incoming connections
for (const [uuid, path] of pathMap) {
if (!visited.has(uuid)) {
const hasConnectionToCurrent = path.points.some((point) =>
point.connections.targets.some(
(t) => t.pathUUID === currentPath.modeluuid
)
);
if (hasConnectionToCurrent) {
visited.add(uuid);
queue.push(path);
}
}
}
}
return connectedPaths;
},
[]
);
const createProcessesFromPaths = useCallback(
(paths: SimulationPath[]): Process[] => {
if (!paths || paths.length === 0) return [];
const visited = new Set<string>();
const processes: Process[] = [];
const pathMap = new Map<string, SimulationPath>();
paths.forEach((path) => pathMap.set(path.modeluuid, path));
for (const path of paths) {
if (!visited.has(path.modeluuid) && hasSpawnAction(path)) {
const connectedPaths = getAllConnectedPaths(path, paths, visited);
const adjustedPaths = adjustPathPointsOrder(connectedPaths);
const process = createProcess(adjustedPaths);
processes.push(process);
}
}
return processes;
},
[createProcess, getAllConnectedPaths, hasSpawnAction]
);
return {
processes,
createProcessesFromPaths,
setProcesses,
};
}
const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
({ onProcessesCreated }) => {
const { simulationPaths } = useSimulationPaths();
const { createProcessesFromPaths } = useProcessCreation();
const prevPathsRef = useRef<SimulationPath[]>([]);
const prevProcessesRef = useRef<Process[]>([]);
const convertedPaths = useMemo((): SimulationPath[] => {
if (!simulationPaths) return [];
return simulationPaths.map((path) =>
convertToSimulationPath(
path as ConveyorEventsSchema | VehicleEventsSchema
)
);
}, [simulationPaths]);
const pathsDependency = useMemo(() => {
if (!convertedPaths) return null;
return convertedPaths.map((path) => ({
id: path.modeluuid,
hasSpawn: path.points.some((p: PathPoint) =>
p.actions.some((a: PointAction) => a.type.toLowerCase() === "spawn")
),
connections: path.points
.flatMap((p: PathPoint) =>
p.connections.targets.map((t: { pathUUID: string }) => t.pathUUID)
)
.join(","),
}));
}, [convertedPaths]);
useEffect(() => {
if (!convertedPaths || convertedPaths.length === 0) {
if (prevProcessesRef.current.length > 0) {
onProcessesCreated([]);
prevProcessesRef.current = [];
}
return;
}
if (areArraysEqual(prevPathsRef.current, convertedPaths)) {
return;
}
prevPathsRef.current = convertedPaths;
const newProcesses = createProcessesFromPaths(convertedPaths);
// console.log("--- Action Types in Paths ---");
// convertedPaths.forEach((path) => {
// path.points.forEach((point) => {
// point.actions.forEach((action) => {
// console.log(
// `Path ${path.modeluuid}, Point ${point.uuid}: ${action.type}`
// );
// });
// });
// });
// console.log("New processes:", newProcesses);
if (
newProcesses.length !== prevProcessesRef.current.length ||
!newProcesses.every(
(proc, i) =>
proc.paths.length === prevProcessesRef.current[i]?.paths.length &&
proc.paths.every(
(path, j) =>
path.modeluuid ===
prevProcessesRef.current[i]?.paths[j]?.modeluuid
)
)
) {
onProcessesCreated(newProcesses);
// prevProcessesRef.current = newProcesses;
}
}, [
pathsDependency,
onProcessesCreated,
convertedPaths,
createProcessesFromPaths,
]);
return null;
}
);
export default ProcessCreator;

View File

@ -5,6 +5,7 @@ import Behaviour from './behaviour/behaviour';
import PathCreation from './path/pathCreation';
import PathConnector from './path/pathConnector';
import useModuleStore from '../../store/useModuleStore';
import ProcessContainer from './process/processContainer';
function Simulation() {
const { activeModule } = useModuleStore();
@ -13,6 +14,7 @@ function Simulation() {
const [processes, setProcesses] = useState([]);
useEffect(() => {
// console.log('simulationPaths: ', simulationPaths);
}, [simulationPaths]);
// useEffect(() => {
@ -35,6 +37,7 @@ function Simulation() {
<>
<PathCreation pathsGroupRef={pathsGroupRef} />
<PathConnector pathsGroupRef={pathsGroupRef} />
<ProcessContainer />
</>
)}
</>

View File

@ -1,4 +1,4 @@
let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
let BackEnd_url = `http://${process.env.REACT_APP_SERVER_ASSET_LIBRARY_URL}`;
export const getCategoryAsset = async (categoryName: any) => {
try {
const response = await fetch(

View File

@ -58,7 +58,7 @@
--border-color: #{$border-color-dark}; // Border color for dark theme
// Shadow variables
--shadow-main-dark: #{$shadow-color-dark}; // Main shadow color
--shadow-main-dark: #{$shadow-color}; // Main shadow color
--box-shadow-light: 0px 2px 4px var(--shadow-main-dark); // Light shadow
--box-shadow-medium: 0px 4px 8px var(--shadow-main-dark); // Medium shadow
--box-shadow-heavy: 0px 8px 16px var(--shadow-main-dark); // Heavy shadow
@ -75,6 +75,7 @@
height: 100vh; // Full viewport height
width: 100vw; // Full viewport width
overflow: hidden; // Prevent scrollbars
background-color: #232323;
}
// Root overlay styles
@ -123,7 +124,7 @@ body {
/* Scrollbar handle color */
border-radius: 4px;
/* Rounded corners */
border: 2px solid #f4f4f4;
border: 2px solid var(--primary-color);
/* Padding around the scrollbar handle */
}

View File

@ -10,6 +10,7 @@ input {
border: 1px solid var(--border-color);
outline: none;
background: transparent;
color: var(--input-text-color);
&:focus,
&:active {
@ -552,6 +553,11 @@ input {
.input-value {
width: 40px;
text-align: center;
&::-webkit-inner-spin-button,
&::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
}
}
}

View File

@ -26,9 +26,6 @@
width: 100%;
height: 100%;
overflow: auto;
left: calc(120px / 2);
top: 100px;
padding: 14px;
padding-bottom: 60px;
display: flex;
flex-direction: column;
@ -39,6 +36,8 @@
display: flex;
align-items: center;
gap: 12px;
margin-top: 2px;
padding: 0 24px;
.search-wrapper {
min-width: 60%;
@ -143,6 +142,7 @@
.assets-container {
display: flex;
justify-content: space-between;
padding: 0;
.name-container {
display: flex;
@ -177,6 +177,9 @@
}
.vendor-icon {
display: flex;
align-items: center;
gap: 4px;
font-weight: #{$bold-weight};
font-size: $regular;
}

View File

@ -3,7 +3,7 @@
// Main Container
.realTime-viz {
background-color: var(--background-color);
background-color: #131313;
border-radius: 20px;
box-shadow: $box-shadow-medium;
width: calc(100% - (320px + 270px + 90px));
@ -22,7 +22,7 @@
min-height: 83px;
background: var(--background-color);
border: 1.23px solid var(--border-color);
box-shadow: var(--box-shadow-heavy);
box-shadow: 0px 4.91px 4.91px 0px #0000001c;
border-radius: $border-radius-medium;
padding: 18px;
position: absolute;
@ -31,7 +31,6 @@
.scene-container {
overflow: hidden;
background: #232323;
}
.icon {
@ -192,9 +191,9 @@
height: 25% !important;
min-height: 150px;
max-height: 100%;
border: 1px dashed #a9a9a9;
// border: 1px dashed var(--background-color-gray);
border-radius: 8px;
box-shadow: 0px 2px 6px 0px rgba(60, 60, 67, 0.1);
box-shadow: var(--box-shadow-medium);
padding: 6px 0;
background-color: var(--background-color);
position: relative;
@ -534,7 +533,7 @@
.zone {
padding: 10px;
border: 1px solid #ccc;
border: 1px solid var(--highlight-accent-color);
border-radius: 5px;
cursor: pointer;
}
@ -615,10 +614,6 @@
}
}
.distance-line {
position: absolute;
border-style: dashed;

View File

@ -69,7 +69,7 @@
}
.error-message {
color: #ff4d4f;
color: #f3453f;
font-size: 12px;
margin-bottom: 10px;
}
@ -89,7 +89,7 @@
border-radius: #{$border-radius-extra-large};
background: var(--background-color);
font-size: 14px;
color: #333;
color: var(--input-text-color);
&:focus {
border-color: var(--accent-color);

View File

@ -202,7 +202,7 @@ export const thirdPersonControls: ThirdPersonControls = {
maxDistance: 100, // Maximum distance from the target
maxPolarAngle: Math.PI / 2 - 0.05, // Maximum polar angle
minZoom: 6, // Minimum zoom level
maxZoom: 21, // Maximum zoom level
maxZoom: 100, // Maximum zoom level
targetOffset: 20, // Offset of the target from the camera
cameraHeight: 30, // Height of the camera
leftMouse: 2, // Mouse button for panning