@@ -237,14 +239,14 @@ export const DraggableWidget = ({
title={widget.title}
fontSize={widget.fontSize}
fontWeight={widget.fontWeight}
- data={{
- measurements: [
- { name: "testDevice", fields: "powerConsumption" },
- { name: "furnace", fields: "powerConsumption" },
- ],
- interval: 1000,
- duration: "1h",
- }}
+ // data={{
+ // measurements: [
+ // { name: "testDevice", fields: "powerConsumption" },
+ // { name: "furnace", fields: "powerConsumption" },
+ // ],
+ // interval: 1000,
+ // duration: "1h",
+ // }}
/>
)}
{widget.type === "bar" && (
@@ -253,14 +255,14 @@ export const DraggableWidget = ({
title={widget.title}
fontSize={widget.fontSize}
fontWeight={widget.fontWeight}
- data={{
- measurements: [
- { name: "testDevice", fields: "powerConsumption" },
- { name: "furnace", fields: "powerConsumption" },
- ],
- interval: 1000,
- duration: "1h",
- }}
+ // data={{
+ // measurements: [
+ // { name: "testDevice", fields: "powerConsumption" },
+ // { name: "furnace", fields: "powerConsumption" },
+ // ],
+ // interval: 1000,
+ // duration: "1h",
+ // }}
/>
)}
{widget.type === "pie" && (
@@ -269,14 +271,14 @@ export const DraggableWidget = ({
title={widget.title}
fontSize={widget.fontSize}
fontWeight={widget.fontWeight}
- data={{
- measurements: [
- { name: "testDevice", fields: "powerConsumption" },
- { name: "furnace", fields: "powerConsumption" },
- ],
- interval: 1000,
- duration: "1h",
- }}
+ // data={{
+ // measurements: [
+ // { name: "testDevice", fields: "powerConsumption" },
+ // { name: "furnace", fields: "powerConsumption" },
+ // ],
+ // interval: 1000,
+ // duration: "1h",
+ // }}
/>
)}
{widget.type === "doughnut" && (
diff --git a/app/src/components/ui/componets/Dropped3dWidget.tsx b/app/src/components/ui/componets/Dropped3dWidget.tsx
new file mode 100644
index 0000000..e0e2a7d
--- /dev/null
+++ b/app/src/components/ui/componets/Dropped3dWidget.tsx
@@ -0,0 +1,79 @@
+
+import { useThree } from "@react-three/fiber";
+import React, { useState, useEffect } from "react";
+import { useAsset3dWidget } from "../../../store/store";
+import useModuleStore from "../../../store/useModuleStore";
+import { ThreeState } from "../../../types/world/worldTypes";
+import * as THREE from "three";
+import Throughput from "../../layout/3D-cards/cards/Throughput";
+import ProductionCapacity from "../../layout/3D-cards/cards/ProductionCapacity";
+import ReturnOfInvestment from "../../layout/3D-cards/cards/ReturnOfInvestment";
+import StateWorking from "../../layout/3D-cards/cards/StateWorking";
+
+export default function Dropped3dWidgets() {
+ const { widgetSelect } = useAsset3dWidget();
+ const { activeModule } = useModuleStore();
+ const { raycaster, gl, scene }: ThreeState = useThree();
+
+ // 🔥 Store multiple instances per widget type
+ const [widgetPositions, setWidgetPositions] = useState
>({});
+
+ useEffect(() => {
+ if (activeModule !== "visualization") return;
+ const canvasElement = gl.domElement;
+
+ const onDrop = (event: DragEvent) => {
+ event.preventDefault(); // Prevent default browser behavior
+
+ if (!widgetSelect.startsWith("ui")) return;
+
+
+ const group1 = scene.getObjectByName("itemsGroup");
+ if (!group1) return;
+
+
+
+ const Assets = group1.children
+ .map((val) => scene.getObjectByProperty("uuid", val.uuid))
+ .filter(Boolean) as THREE.Object3D[];
+
+
+ const intersects = raycaster.intersectObjects(Assets);
+
+ if (intersects.length > 0) {
+ const { x, y, z } = intersects[0].point;
+
+
+ // ✅ Allow multiple instances by storing positions in an array
+ setWidgetPositions((prev) => ({
+ ...prev,
+ [widgetSelect]: [...(prev[widgetSelect] || []), [x, y, z]],
+ }));
+ }
+ };
+
+ canvasElement.addEventListener("drop", onDrop);
+
+ return () => {
+ canvasElement.removeEventListener("drop", onDrop);
+ };
+ }, [widgetSelect, activeModule]);
+
+ return (
+ <>
+ {widgetPositions["ui-Widget 1"]?.map((pos, index) => (
+
+ ))}
+ {widgetPositions["ui-Widget 2"]?.map((pos, index) => (
+
+ ))}
+ {widgetPositions["ui-Widget 3"]?.map((pos, index) => (
+
+ ))}
+ {widgetPositions["ui-Widget 4"]?.map((pos, index) => (
+
+ ))}
+ >
+ );
+}
+
diff --git a/app/src/components/ui/componets/DroppedFloatingWidgets.tsx b/app/src/components/ui/componets/DroppedFloatingWidgets.tsx
index 95668f9..ffddc23 100644
--- a/app/src/components/ui/componets/DroppedFloatingWidgets.tsx
+++ b/app/src/components/ui/componets/DroppedFloatingWidgets.tsx
@@ -8,7 +8,6 @@ import { useDroppedObjectsStore, Zones } from "../../../store/useDroppedObjectsS
const DroppedObjects: React.FC = () => {
const zones = useDroppedObjectsStore((state) => state.zones);
-
const updateObjectPosition = useDroppedObjectsStore((state) => state.updateObjectPosition);
const [draggingIndex, setDraggingIndex] = useState<{ zone: string; index: number } | null>(null);
const [offset, setOffset] = useState<[number, number] | null>(null);
diff --git a/app/src/components/ui/componets/Panel.tsx b/app/src/components/ui/componets/Panel.tsx
index 3fee476..1d4cc44 100644
--- a/app/src/components/ui/componets/Panel.tsx
+++ b/app/src/components/ui/componets/Panel.tsx
@@ -3,6 +3,7 @@ import { useWidgetStore } from "../../../store/useWidgetStore";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import { DraggableWidget } from "./DraggableWidget";
import { arrayMove } from "@dnd-kit/sortable";
+import { addingWidgets } from "../../../services/realTimeVisulization/zoneData/addWidgets";
type Side = "top" | "bottom" | "left" | "right";
@@ -19,6 +20,7 @@ interface PanelProps {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
+
lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
@@ -30,6 +32,7 @@ interface PanelProps {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
+
lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
@@ -72,9 +75,8 @@ const Panel: React.FC = ({
case "top":
case "bottom":
return {
- width: `calc(100% - ${
- (leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
- }px)`,
+ width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
+ }px)`,
height: `${panelSize - 2}px`,
left: leftActive ? `${panelSize}px` : "0",
right: rightActive ? `${panelSize}px` : "0",
@@ -84,9 +86,8 @@ const Panel: React.FC = ({
case "right":
return {
width: `${panelSize - 2}px`,
- height: `calc(100% - ${
- (topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
- }px)`,
+ height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
+ }px)`,
top: topActive ? `${panelSize}px` : "0",
bottom: bottomActive ? `${panelSize}px` : "0",
[side]: "0",
@@ -99,6 +100,7 @@ const Panel: React.FC = ({
);
const handleDrop = (e: React.DragEvent, panel: Side) => {
+
e.preventDefault();
const { draggedAsset } = useWidgetStore.getState();
if (!draggedAsset) return;
@@ -109,8 +111,6 @@ const Panel: React.FC = ({
if (currentWidgetsCount >= maxCapacity) return;
- console.log("draggedAsset: ", draggedAsset);
- console.log("panel: ", panel);
addWidgetToPanel(draggedAsset, panel);
};
@@ -139,17 +139,27 @@ const Panel: React.FC = ({
};
// while dublicate check this and add
- const addWidgetToPanel = (asset: any, panel: Side) => {
+ const addWidgetToPanel = async (asset: any, panel: Side) => {
+ const email = localStorage.getItem("email") || "";
+ const organization = email?.split("@")[1]?.split(".")[0]
const newWidget = {
...asset,
id: generateUniqueId(),
panel,
};
+ try {
+ let response = await addingWidgets(selectedZone.zoneId, organization, newWidget);
+ console.log("response: ", response);
+ if (response.message === "Widget created successfully") {
+ setSelectedZone((prev) => ({
+ ...prev,
+ widgets: [...prev.widgets, newWidget],
+ }));
+ }
+ } catch (error) {
+ console.error("Error adding widget:", error);
+ }
- setSelectedZone((prev) => ({
- ...prev,
- widgets: [...prev.widgets, newWidget],
- }));
};
useEffect(() => {
@@ -180,7 +190,7 @@ const Panel: React.FC = ({
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
if (!selectedZone) return; // Ensure selectedZone is not null
- console.log("selectedZone: ", selectedZone);
+
setSelectedZone((prev) => {
if (!prev) return prev; // Ensure prev is not null
diff --git a/app/src/components/ui/componets/RealTimeVisulization.tsx b/app/src/components/ui/componets/RealTimeVisulization.tsx
index be0f574..27044b1 100644
--- a/app/src/components/ui/componets/RealTimeVisulization.tsx
+++ b/app/src/components/ui/componets/RealTimeVisulization.tsx
@@ -9,7 +9,9 @@ import useModuleStore from "../../../store/useModuleStore";
import DroppedObjects from "./DroppedFloatingWidgets";
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
-import { useZones } from "../../../store/store";
+import { useAsset3dWidget, useZones } from "../../../store/store";
+import { getZoneData } from "../../../services/realTimeVisulization/zoneData/getZones";
+import { getZone2dData } from "../../../services/realTimeVisulization/zoneData/getZoneData";
type Side = "top" | "bottom" | "left" | "right";
@@ -19,6 +21,7 @@ type FormattedZoneData = Record<
{
activeSides: Side[];
panelOrder: Side[];
+
lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
@@ -43,25 +46,38 @@ const RealTimeVisulization: React.FC = () => {
const [zonesData, setZonesData] = useState({});
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { zones } = useZones()
-
+ const [floatingWidgets, setFloatingWidgets] = useState>({});
+ const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
useEffect(() => {
- const data = Array.isArray(zones) ? zones : [];
+ async function GetZoneData() {
+ const email = localStorage.getItem("email") || "";
+ const organization = email?.split("@")[1]?.split(".")[0];
+ try {
+ const response = await getZone2dData(organization);
+ if (!Array.isArray(response)) {
+ return;
+ }
+ const formattedData = response.reduce((acc, zone) => {
+ acc[zone.zoneName] = {
+ activeSides: [],
+ panelOrder: [],
+ lockedPanels: [],
+ zoneId: zone.zoneId,
+ zoneViewPortTarget: zone.viewPortCenter,
+ zoneViewPortPosition: zone.viewPortposition,
+ widgets: [],
+ };
+ return acc;
+ }, {});
+ setZonesData(formattedData);
+ } catch (error) {
+ console.log('error: ', error);
+ }
+ }
- const formattedData = data.reduce((acc, zone) => {
- acc[zone.zoneName] = {
- activeSides: [],
- panelOrder: [],
- lockedPanels: [],
- zoneId: zone.zoneId,
- zoneViewPortTarget: zone.viewPortCenter,
- zoneViewPortPosition: zone.viewPortposition,
- widgets: [],
- };
- return acc;
- }, {});
+ GetZoneData();
+ }, []); // Removed `zones` from dependencies
- setZonesData(formattedData);
- }, [zones]);
useEffect(() => {
setZonesData((prev) => {
@@ -81,37 +97,47 @@ const RealTimeVisulization: React.FC = () => {
};
});
}, [selectedZone]);
+
+ useEffect(() => {
+
+ }, [floatingWidgets])
const handleDrop = (event: React.DragEvent) => {
event.preventDefault();
const data = event.dataTransfer.getData("text/plain");
- if (!data || !selectedZone.zoneName) return;
-
+ if (widgetSelect !== "") return;
+ if (!data || selectedZone.zoneName === "") return;
+
const droppedData = JSON.parse(data);
const canvasElement = document.getElementById("real-time-vis-canvas");
if (!canvasElement) return;
-
+
const canvasRect = canvasElement.getBoundingClientRect();
const relativeX = event.clientX - canvasRect.left;
const relativeY = event.clientY - canvasRect.top;
-
+
const newObject = {
...droppedData,
position: [relativeY, relativeX], // Y first because of top/left style
};
-
- console.log("newObject: ", newObject);
-
// Only set zone if it’s not already in the store (prevents overwriting objects)
const existingZone = useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
if (!existingZone) {
useDroppedObjectsStore.getState().setZone(selectedZone.zoneName, selectedZone.zoneId);
}
-
// Add the dropped object to the zone
useDroppedObjectsStore.getState().addObject(selectedZone.zoneName, newObject);
+ setFloatingWidgets((prevWidgets) => ({
+ ...prevWidgets,
+ [selectedZone.zoneName]: {
+ ...prevWidgets[selectedZone.zoneName],
+ zoneName: selectedZone.zoneName,
+ zoneId: selectedZone.zoneId,
+ objects: [...(prevWidgets[selectedZone.zoneName]?.objects || []), newObject],
+ },
+ }));
};
-
+
return (
{
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
}}
+
>
{
+// const canvasRef = useRef
(null);
+// const { themeColor } = useThemeStore();
+// const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
+// labels: [],
+// datasets: [],
+// });
+
+// const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
+
+// const defaultData = {
+// labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
+// datasets: [
+// {
+// label: "Dataset",
+// data: [12, 19, 3, 5, 2, 3],
+// backgroundColor: ["#6f42c1"],
+// borderColor: "#ffffff",
+// borderWidth: 2,
+// },
+// ],
+// };
+
+// // Memoize Theme Colors to Prevent Unnecessary Recalculations
+// const buttonActionColor = useMemo(
+// () => themeColor[0] || "#5c87df",
+// [themeColor]
+// );
+// const buttonAbortColor = useMemo(
+// () => themeColor[1] || "#ffffff",
+// [themeColor]
+// );
+
+// // Memoize Font Weight Mapping
+// const chartFontWeightMap = useMemo(
+// () => ({
+// Light: "lighter" as const,
+// Regular: "normal" as const,
+// Bold: "bold" as const,
+// }),
+// []
+// );
+
+// // Parse and Memoize Font Size
+// const fontSizeValue = useMemo(
+// () => (fontSize ? parseInt(fontSize) : 12),
+// [fontSize]
+// );
+
+// // Determine and Memoize Font Weight
+// const fontWeightValue = useMemo(
+// () => chartFontWeightMap[fontWeight],
+// [fontWeight, chartFontWeightMap]
+// );
+
+// // Memoize Chart Font Style
+// const chartFontStyle = useMemo(
+// () => ({
+// family: fontFamily || "Arial",
+// size: fontSizeValue,
+// weight: fontWeightValue,
+// }),
+// [fontFamily, fontSizeValue, fontWeightValue]
+// );
+
+// // Memoize Chart Data
+// // const data = useMemo(() => propsData, [propsData]);
+
+// // Memoize Chart Options
+// const options = useMemo(
+// () => ({
+// responsive: true,
+// maintainAspectRatio: false,
+// plugins: {
+// title: {
+// display: true,
+// text: title,
+// font: chartFontStyle,
+// },
+// legend: {
+// display: false,
+// },
+// },
+// scales: {
+// x: {
+// ticks: {
+// display: true, // This hides the x-axis labels
+// },
+// },
+// },
+// }),
+// [title, chartFontStyle]
+// );
+
+// const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
+
+// useEffect(() => {
+
+// const socket = io(`http://${iotApiUrl}`);
+
+// if ( measurements.length > 0 ) {
+// var inputes = {
+// measurements: measurements,
+// duration: duration,
+// interval: 1000,
+// }
+
+// // Start stream
+// const startStream = () => {
+// socket.emit("lineInput", inputes);
+// }
+
+// socket.on('connect', startStream);
+
+// socket.on("lineOutput", (response) => {
+// const responceData = response.data;
+// console.log("Received data:", responceData);
+
+// // Extract timestamps and values
+// const labels = responceData.time;
+// const datasets = measurements.map((measurement: any) => {
+// const key = `${measurement.name}.${measurement.fields}`;
+// return {
+// label: key,
+// data: responceData[key]?.values ?? [], // Ensure it exists
+// backgroundColor: "#6f42c1",
+// borderColor: "#ffffff",
+// };
+// });
+
+// setChartData({ labels, datasets });
+// });
+// }
+
+// return () => {
+// socket.off("lineOutput");
+// socket.emit("stop_stream"); // Stop streaming when component unmounts
+// };
+// }, [measurements, duration]);
+
+// // useEffect(() => {
+// // if (!canvasRef.current) return;
+// // const ctx = canvasRef.current.getContext("2d");
+// // if (!ctx) return;
+
+// // const chart = new Chart(ctx, {
+// // type,
+// // data: chartData,
+// // options: options,
+// // });
+
+// // return () => chart.destroy();
+// // }, [chartData, type, title]);
+
+// return 0 ? chartData : defaultData} options={options} />;
+// };
+
+// export default LineGraphComponent;
+
+
+
+import React, { useEffect, useMemo, useState } from "react";
import { Bar } from "react-chartjs-2";
+import io from "socket.io-client";
+import { useThemeStore } from "../../../../store/useThemeStore";
+import useChartStore from "../../../../store/useChartStore";
interface ChartComponentProps {
type: any;
@@ -8,16 +197,42 @@ interface ChartComponentProps {
fontFamily?: string;
fontSize?: string;
fontWeight?: "Light" | "Regular" | "Bold";
- data: any;
}
-const LineGraphComponent = ({
+const BarGraphComponent = ({
+ type,
title,
fontFamily,
fontSize,
fontWeight = "Regular",
}: ChartComponentProps) => {
- // Memoize Font Weight Mapping
+ const { themeColor } = useThemeStore();
+ const { measurements, duration } = useChartStore(); // Zustand Store
+ const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
+ labels: [],
+ datasets: [],
+ });
+
+ const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
+
+ const defaultData = {
+ labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
+ datasets: [
+ {
+ label: "Dataset",
+ data: [12, 19, 3, 5, 2, 3],
+ backgroundColor: ["#6f42c1"],
+ borderColor: "#b392f0",
+ borderWidth: 1,
+ },
+ ],
+ };
+
+ // Memoize Theme Colors
+ const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
+ const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
+
+ // Memoize Font Styling
const chartFontWeightMap = useMemo(
() => ({
Light: "lighter" as const,
@@ -27,19 +242,9 @@ const LineGraphComponent = ({
[]
);
- // Parse and Memoize Font Size
- const fontSizeValue = useMemo(
- () => (fontSize ? parseInt(fontSize) : 12),
- [fontSize]
- );
+ const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]);
+ const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]);
- // Determine and Memoize Font Weight
- const fontWeightValue = useMemo(
- () => chartFontWeightMap[fontWeight],
- [fontWeight, chartFontWeightMap]
- );
-
- // Memoize Chart Font Style
const chartFontStyle = useMemo(
() => ({
family: fontFamily || "Arial",
@@ -49,6 +254,7 @@ const LineGraphComponent = ({
[fontFamily, fontSizeValue, fontWeightValue]
);
+ // Memoized Chart Options
const options = useMemo(
() => ({
responsive: true,
@@ -66,7 +272,7 @@ const LineGraphComponent = ({
scales: {
x: {
ticks: {
- display: false, // This hides the x-axis labels
+ display: true,
},
},
},
@@ -74,21 +280,53 @@ const LineGraphComponent = ({
[title, chartFontStyle]
);
- const chartData = {
- labels: ["January", "February", "March", "April", "May", "June", "July"],
- datasets: [
- {
- label: "My First Dataset",
- data: [65, 59, 80, 81, 56, 55, 40],
- backgroundColor: "#6f42c1",
- borderColor: "#ffffff",
- borderWidth: 2,
- fill: false,
- },
- ],
- };
+ useEffect(() => {
+ if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
- return ;
+ const socket = io(`http://${iotApiUrl}`);
+
+ const inputData = {
+ measurements,
+ duration,
+ interval: 1000,
+ };
+
+ const startStream = () => {
+ socket.emit("lineInput", inputData);
+ };
+
+ socket.on("connect", startStream);
+
+ socket.on("lineOutput", (response) => {
+ const responseData = response.data;
+ console.log("Received data:", responseData);
+
+ // Extract timestamps and values
+ const labels = responseData.time;
+ const datasets = Object.keys(measurements).map((key) => {
+ const measurement = measurements[key];
+ const datasetKey = `${measurement.name}.${measurement.fields}`;
+ return {
+ label: datasetKey,
+ data: responseData[datasetKey]?.values ?? [],
+ backgroundColor: "#6f42c1",
+ borderColor: "#b392f0",
+ borderWidth: 1,
+ };
+ });
+
+ setChartData({ labels, datasets });
+ });
+
+ return () => {
+ socket.off("lineOutput");
+ socket.emit("stop_stream"); // Stop streaming when component unmounts
+ socket.disconnect();
+ };
+ }, [measurements, duration, iotApiUrl]);
+
+ return 0 ? chartData : defaultData} options={options} />;
};
-export default LineGraphComponent;
+export default BarGraphComponent;
+
diff --git a/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx
index cc40187..fcc5aeb 100644
--- a/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx
+++ b/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx
@@ -1,115 +1,15 @@
-// import { useMemo } from "react";
-// import { Line } from "react-chartjs-2";
-
-// interface ChartComponentProps {
-// type: any;
-// title: string;
-// fontFamily?: string;
-// fontSize?: string;
-// fontWeight?: "Light" | "Regular" | "Bold";
-// data: any;
-// }
-
-// const LineGraphComponent = ({
-// title,
-// fontFamily,
-// fontSize,
-// fontWeight = "Regular",
-// }: ChartComponentProps) => {
-// // Memoize Font Weight Mapping
-// const chartFontWeightMap = useMemo(
-// () => ({
-// Light: "lighter" as const,
-// Regular: "normal" as const,
-// Bold: "bold" as const,
-// }),
-// []
-// );
-
-// // Parse and Memoize Font Size
-// const fontSizeValue = useMemo(
-// () => (fontSize ? parseInt(fontSize) : 12),
-// [fontSize]
-// );
-
-// // Determine and Memoize Font Weight
-// const fontWeightValue = useMemo(
-// () => chartFontWeightMap[fontWeight],
-// [fontWeight, chartFontWeightMap]
-// );
-
-// // Memoize Chart Font Style
-// const chartFontStyle = useMemo(
-// () => ({
-// family: fontFamily || "Arial",
-// size: fontSizeValue,
-// weight: fontWeightValue,
-// }),
-// [fontFamily, fontSizeValue, fontWeightValue]
-// );
-
-// const options = useMemo(
-// () => ({
-// responsive: true,
-// maintainAspectRatio: false,
-// plugins: {
-// title: {
-// display: true,
-// text: title,
-// font: chartFontStyle,
-// },
-// legend: {
-// display: false,
-// },
-// },
-// scales: {
-// x: {
-// ticks: {
-// display: true, // This hides the x-axis labels
-// },
-// },
-// },
-// }),
-// [title, chartFontStyle]
-// );
-
-// const chartData = {
-// labels: ["January", "February", "March", "April", "May", "June", "July"],
-// datasets: [
-// {
-// label: "My First Dataset",
-// data: [65, 59, 80, 81, 56, 55, 40],
-// backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple)
-// borderColor: "#ffffff", // Keeping border color white
-// borderWidth: 2,
-// fill: false,
-// },
-// ],
-// };
-
-// return ;
-// };
-
-// export default LineGraphComponent;
-
-
-import React, { useEffect, useRef, useMemo, useState } from "react";
-import { Chart } from "chart.js/auto";
-import { useThemeStore } from "../../../../store/useThemeStore";
+import React, { useEffect, useMemo, useState } from "react";
+import { Line } from "react-chartjs-2";
import io from "socket.io-client";
-import { Line } from 'react-chartjs-2';
+import { useThemeStore } from "../../../../store/useThemeStore";
import useChartStore from "../../../../store/useChartStore";
-// WebSocket Connection
-// const socket = io("http://localhost:5000"); // Adjust to your backend URL
-
interface ChartComponentProps {
type: any;
title: string;
fontFamily?: string;
fontSize?: string;
fontWeight?: "Light" | "Regular" | "Bold";
- data: any;
}
const LineGraphComponent = ({
@@ -118,60 +18,55 @@ const LineGraphComponent = ({
fontFamily,
fontSize,
fontWeight = "Regular",
- data,
}: ChartComponentProps) => {
- const canvasRef = useRef(null);
const { themeColor } = useThemeStore();
+ const { measurements, duration } = useChartStore(); // Zustand Store
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
labels: [],
datasets: [],
});
- // Memoize Theme Colors to Prevent Unnecessary Recalculations
- const buttonActionColor = useMemo(
- () => themeColor[0] || "#5c87df",
- [themeColor]
- );
- const buttonAbortColor = useMemo(
- () => themeColor[1] || "#ffffff",
- [themeColor]
- );
-
- // Memoize Font Weight Mapping
- const chartFontWeightMap = useMemo(
- () => ({
- Light: "lighter" as const,
- Regular: "normal" as const,
- Bold: "bold" as const,
- }),
- []
- );
-
- // Parse and Memoize Font Size
- const fontSizeValue = useMemo(
- () => (fontSize ? parseInt(fontSize) : 12),
- [fontSize]
- );
-
- // Determine and Memoize Font Weight
- const fontWeightValue = useMemo(
- () => chartFontWeightMap[fontWeight],
- [fontWeight, chartFontWeightMap]
- );
-
- // Memoize Chart Font Style
- const chartFontStyle = useMemo(
- () => ({
- family: fontFamily || "Arial",
- size: fontSizeValue,
- weight: fontWeightValue,
- }),
- [fontFamily, fontSizeValue, fontWeightValue]
- );
-
- // Memoize Chart Data
- // const data = useMemo(() => propsData, [propsData]);
-
+ const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
+
+ const defaultData = {
+ labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
+ datasets: [
+ {
+ label: "Dataset",
+ data: [12, 19, 3, 5, 2, 3],
+ backgroundColor: ["#6f42c1"],
+ borderColor: "#b392f0",
+ borderWidth: 1,
+ },
+ ],
+ };
+
+ // Memoize Theme Colors
+ const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
+ const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
+
+ // Memoize Font Styling
+ const chartFontWeightMap = useMemo(
+ () => ({
+ Light: "lighter" as const,
+ Regular: "normal" as const,
+ Bold: "bold" as const,
+ }),
+ []
+ );
+
+ const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]);
+ const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]);
+
+ const chartFontStyle = useMemo(
+ () => ({
+ family: fontFamily || "Arial",
+ size: fontSizeValue,
+ weight: fontWeightValue,
+ }),
+ [fontFamily, fontSizeValue, fontWeightValue]
+ );
+
// Memoize Chart Options
const options = useMemo(
() => ({
@@ -198,67 +93,54 @@ const LineGraphComponent = ({
[title, chartFontStyle]
);
- const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
+ useEffect(() => {console.log(measurements);
+ },[measurements])
useEffect(() => {
+ if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
- const socket = io("http://192.168.0.192:5010");
+ const socket = io(`http://${iotApiUrl}`);
- if ( measurements.length > 0 ) {
- var inputes = {
- measurements: measurements,
- duration: duration,
- interval: 1000,
- }
+ const inputData = {
+ measurements,
+ duration,
+ interval: 1000,
+ };
- // Start stream
const startStream = () => {
- socket.emit("lineInput", inputes);
- }
+ socket.emit("lineInput", inputData);
+ };
- socket.on('connect', startStream);
+ socket.on("connect", startStream);
socket.on("lineOutput", (response) => {
- const responceData = response.data;
- console.log("Received data:", responceData);
+ const responseData = response.data;
// Extract timestamps and values
- const labels = responceData.time;
- const datasets = measurements.map((measurement: any) => {
- const key = `${measurement.name}.${measurement.fields}`;
+ const labels = responseData.time;
+ const datasets = Object.keys(measurements).map((key) => {
+ const measurement = measurements[key];
+ const datasetKey = `${measurement.name}.${measurement.fields}`;
return {
- label: key,
- data: responceData[key]?.values ?? [], // Ensure it exists
- backgroundColor: themeColor[0] || "#5c87df",
- borderColor: themeColor[1] || "#ffffff",
+ label: datasetKey,
+ data: responseData[datasetKey]?.values ?? [],
+ backgroundColor: "#6f42c1",
+ borderColor: "#b392f0",
+ borderWidth: 1,
};
});
setChartData({ labels, datasets });
});
- }
return () => {
socket.off("lineOutput");
socket.emit("stop_stream"); // Stop streaming when component unmounts
+ socket.disconnect();
};
- }, [measurements, duration]);
+ }, [measurements, duration, iotApiUrl]);
- // useEffect(() => {
- // if (!canvasRef.current) return;
- // const ctx = canvasRef.current.getContext("2d");
- // if (!ctx) return;
-
- // const chart = new Chart(ctx, {
- // type,
- // data: chartData,
- // options: options,
- // });
-
- // return () => chart.destroy();
- // }, [chartData, type, title]);
-
- return ;
+ return 0 ? chartData : defaultData} options={options} />;
};
-export default LineGraphComponent;
\ No newline at end of file
+export default LineGraphComponent;
diff --git a/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx
index 0066ec3..ca6b728 100644
--- a/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx
+++ b/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx
@@ -1,5 +1,195 @@
-import { useMemo } from "react";
+// import React, { useEffect, useRef, useMemo, useState } from "react";
+// import { Chart } from "chart.js/auto";
+// import { useThemeStore } from "../../../../store/useThemeStore";
+// import io from "socket.io-client";
+// import { Pie } from 'react-chartjs-2';
+// import useChartStore from "../../../../store/useChartStore";
+
+// // WebSocket Connection
+// // const socket = io("http://localhost:5000"); // Adjust to your backend URL
+
+// interface ChartComponentProps {
+// type: any;
+// title: string;
+// fontFamily?: string;
+// fontSize?: string;
+// fontWeight?: "Light" | "Regular" | "Bold";
+// data: any;
+// }
+
+// const PieChartComponent = ({
+// type,
+// title,
+// fontFamily,
+// fontSize,
+// fontWeight = "Regular",
+// data,
+// }: ChartComponentProps) => {
+// const canvasRef = useRef(null);
+// const { themeColor } = useThemeStore();
+// const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
+// labels: [],
+// datasets: [],
+// });
+
+// const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
+
+// const defaultData = {
+// labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
+// datasets: [
+// {
+// label: "Dataset",
+// data: [12, 19, 3, 5, 2, 3],
+// backgroundColor: ["#6f42c1"],
+// borderColor: "#ffffff",
+// borderWidth: 2,
+// },
+// ],
+// };
+
+// // Memoize Theme Colors to Prevent Unnecessary Recalculations
+// const buttonActionColor = useMemo(
+// () => themeColor[0] || "#6f42c1",
+// [themeColor]
+// );
+// const buttonAbortColor = useMemo(
+// () => themeColor[1] || "#ffffff",
+// [themeColor]
+// );
+
+// // Memoize Font Weight Mapping
+// const chartFontWeightMap = useMemo(
+// () => ({
+// Light: "lighter" as const,
+// Regular: "normal" as const,
+// Bold: "bold" as const,
+// }),
+// []
+// );
+
+// // Parse and Memoize Font Size
+// const fontSizeValue = useMemo(
+// () => (fontSize ? parseInt(fontSize) : 12),
+// [fontSize]
+// );
+
+// // Determine and Memoize Font Weight
+// const fontWeightValue = useMemo(
+// () => chartFontWeightMap[fontWeight],
+// [fontWeight, chartFontWeightMap]
+// );
+
+// // Memoize Chart Font Style
+// const chartFontStyle = useMemo(
+// () => ({
+// family: fontFamily || "Arial",
+// size: fontSizeValue,
+// weight: fontWeightValue,
+// }),
+// [fontFamily, fontSizeValue, fontWeightValue]
+// );
+
+// // Memoize Chart Data
+// // const data = useMemo(() => propsData, [propsData]);
+
+// // Memoize Chart Options
+// const options = useMemo(
+// () => ({
+// responsive: true,
+// maintainAspectRatio: false,
+// plugins: {
+// title: {
+// display: true,
+// text: title,
+// font: chartFontStyle,
+// },
+// legend: {
+// display: false,
+// },
+// },
+// scales: {
+// // x: {
+// // ticks: {
+// // display: true, // This hides the x-axis labels
+// // },
+// // },
+// },
+// }),
+// [title, chartFontStyle]
+// );
+
+// const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
+
+// useEffect(() => {
+
+// const socket = io(`http://${iotApiUrl}`);
+
+// if ( measurements.length > 0 ) {
+// var inputes = {
+// measurements: measurements,
+// duration: duration,
+// interval: 1000,
+// }
+
+// // Start stream
+// const startStream = () => {
+// socket.emit("lineInput", inputes);
+// }
+
+// socket.on('connect', startStream);
+
+// socket.on("lineOutput", (response) => {
+// const responceData = response.data;
+// console.log("Received data:", responceData);
+
+// // Extract timestamps and values
+// const labels = responceData.time;
+// const datasets = measurements.map((measurement: any) => {
+// const key = `${measurement.name}.${measurement.fields}`;
+// return {
+// label: key,
+// data: responceData[key]?.values ?? [], // Ensure it exists
+// backgroundColor: "#6f42c1",
+// borderColor: "#ffffff",
+// };
+// });
+
+// setChartData({ labels, datasets });
+// });
+// }
+
+// return () => {
+// socket.off("lineOutput");
+// socket.emit("stop_stream"); // Stop streaming when component unmounts
+// };
+// }, [measurements, duration]);
+
+// // useEffect(() => {
+// // if (!canvasRef.current) return;
+// // const ctx = canvasRef.current.getContext("2d");
+// // if (!ctx) return;
+
+// // const chart = new Chart(ctx, {
+// // type,
+// // data: chartData,
+// // options: options,
+// // });
+
+// // return () => chart.destroy();
+// // }, [chartData, type, title]);
+
+// return 0 ? chartData : defaultData} options={options} />;
+// };
+
+// export default PieChartComponent;
+
+
+
+import React, { useEffect, useMemo, useState } from "react";
import { Pie } from "react-chartjs-2";
+import io from "socket.io-client";
+import { useThemeStore } from "../../../../store/useThemeStore";
+import useChartStore from "../../../../store/useChartStore";
interface ChartComponentProps {
type: any;
@@ -7,16 +197,42 @@ interface ChartComponentProps {
fontFamily?: string;
fontSize?: string;
fontWeight?: "Light" | "Regular" | "Bold";
- data: any;
}
const PieChartComponent = ({
+ type,
title,
fontFamily,
fontSize,
fontWeight = "Regular",
}: ChartComponentProps) => {
- // Memoize Font Weight Mapping
+ const { themeColor } = useThemeStore();
+ const { measurements, duration } = useChartStore(); // Zustand Store
+ const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
+ labels: [],
+ datasets: [],
+ });
+
+ const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
+
+ const defaultData = {
+ labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
+ datasets: [
+ {
+ label: "Dataset",
+ data: [12, 19, 3, 5, 2, 3],
+ backgroundColor: ["#6f42c1"],
+ borderColor: "#b392f0",
+ borderWidth: 1,
+ },
+ ],
+ };
+
+ // Memoize Theme Colors
+ const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]);
+ const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]);
+
+ // Memoize Font Styling
const chartFontWeightMap = useMemo(
() => ({
Light: "lighter" as const,
@@ -26,19 +242,9 @@ const PieChartComponent = ({
[]
);
- // Parse and Memoize Font Size
- const fontSizeValue = useMemo(
- () => (fontSize ? parseInt(fontSize) : 12),
- [fontSize]
- );
+ const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]);
+ const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]);
- // Determine and Memoize Font Weight
- const fontWeightValue = useMemo(
- () => chartFontWeightMap[fontWeight],
- [fontWeight, chartFontWeightMap]
- );
-
- // Memoize Chart Font Style
const chartFontStyle = useMemo(
() => ({
family: fontFamily || "Arial",
@@ -48,12 +254,7 @@ const PieChartComponent = ({
[fontFamily, fontSizeValue, fontWeightValue]
);
- // Access the CSS variable for the primary accent color
- const accentColor = getComputedStyle(document.documentElement)
- .getPropertyValue("--accent-color")
- .trim();
-
- console.log("accentColor: ", accentColor);
+ // Memoized Chart Options
const options = useMemo(
() => ({
responsive: true,
@@ -68,24 +269,64 @@ const PieChartComponent = ({
display: false,
},
},
+ scales: {
+ // x: {
+ // ticks: {
+ // display: true,
+ // },
+ // },
+ },
}),
[title, chartFontStyle]
);
- const chartData = {
- labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
- datasets: [
- {
- label: "Dataset",
- data: [12, 19, 3, 5, 2, 3],
- backgroundColor: ["#6f42c1"],
- borderColor: "#ffffff",
- borderWidth: 2,
- },
- ],
- };
+ useEffect(() => {
+ if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
- return ;
+ const socket = io(`http://${iotApiUrl}`);
+
+ const inputData = {
+ measurements,
+ duration,
+ interval: 1000,
+ };
+
+ const startStream = () => {
+ socket.emit("lineInput", inputData);
+ };
+
+ socket.on("connect", startStream);
+
+ socket.on("lineOutput", (response) => {
+ const responseData = response.data;
+ console.log("Received data:", responseData);
+
+ // Extract timestamps and values
+ const labels = responseData.time;
+ const datasets = Object.keys(measurements).map((key) => {
+ const measurement = measurements[key];
+ const datasetKey = `${measurement.name}.${measurement.fields}`;
+ return {
+ label: datasetKey,
+ data: responseData[datasetKey]?.values ?? [],
+ backgroundColor: "#6f42c1",
+ borderColor: "#b392f0",
+ borderWidth: 1,
+ };
+ });
+
+ setChartData({ labels, datasets });
+ });
+
+ return () => {
+ socket.off("lineOutput");
+ socket.emit("stop_stream"); // Stop streaming when component unmounts
+ socket.disconnect();
+ };
+ }, [measurements, duration, iotApiUrl]);
+
+ return 0 ? chartData : defaultData} options={options} />;
};
export default PieChartComponent;
+
diff --git a/app/src/components/ui/realTimeVis/charts/ProgressCard.tsx b/app/src/components/ui/realTimeVis/charts/ProgressCard.tsx
index cb35ea3..52daf42 100644
--- a/app/src/components/ui/realTimeVis/charts/ProgressCard.tsx
+++ b/app/src/components/ui/realTimeVis/charts/ProgressCard.tsx
@@ -9,7 +9,7 @@ const ProgressCard = ({
}) => (
{title}
- {data?.stocks.map((stock, index) => (
+ {data?.stocks?.map((stock, index) => (
diff --git a/app/src/modules/builder/agv/navMeshDetails.tsx b/app/src/modules/builder/agv/navMeshDetails.tsx
index c941011..571be5a 100644
--- a/app/src/modules/builder/agv/navMeshDetails.tsx
+++ b/app/src/modules/builder/agv/navMeshDetails.tsx
@@ -34,15 +34,11 @@ export default function NavMeshDetails({
const [positions, indices] = getPositionsAndIndices(meshes);
- const cs = 0.5;
+ const cs = 0.25;
const ch = 0.5;
- const walkableRadius = 0.89;
+ const walkableRadius = 0.5;
- const { success, navMesh } = generateSoloNavMesh(positions, indices, {
- cs,
- ch,
- walkableRadius: Math.round(walkableRadius / ch),
- });
+ const { success, navMesh } = generateSoloNavMesh(positions, indices, { cs, ch, walkableRadius: Math.round(walkableRadius / ch), });
if (!success || !navMesh) {
return;
@@ -53,7 +49,7 @@ export default function NavMeshDetails({
const debugDrawer = new DebugDrawer();
debugDrawer.drawNavMesh(navMesh);
// scene.add(debugDrawer);
- } catch (error) {}
+ } catch (error) { }
};
initializeNavigation();
diff --git a/app/src/modules/builder/agv/pathNavigator.tsx b/app/src/modules/builder/agv/pathNavigator.tsx
index 4193fb7..25d3af0 100644
--- a/app/src/modules/builder/agv/pathNavigator.tsx
+++ b/app/src/modules/builder/agv/pathNavigator.tsx
@@ -86,7 +86,7 @@ export default function PathNavigator({
return (
<>
- {path.length > 0 && }
+ {/* {path.length > 0 && } */}
{path.length > 0 && (
0 ? path[0] : [0, 0.1, 0]}>
diff --git a/app/src/modules/builder/agv/polygonGenerator.tsx b/app/src/modules/builder/agv/polygonGenerator.tsx
index 1eca588..8682371 100644
--- a/app/src/modules/builder/agv/polygonGenerator.tsx
+++ b/app/src/modules/builder/agv/polygonGenerator.tsx
@@ -43,66 +43,46 @@ export default function PolygonGenerator({
const lineFeatures = result?.map((line: any) =>
turf.lineString(line.map((p: any) => p?.position))
- );
+ );
const polygons = turf.polygonize(turf.featureCollection(lineFeatures));
renderWallGeometry(wallPoints);
- let union: any = [];
+ if (polygons.features.length > 1) {
+ polygons.features.forEach((feature) => {
+ if (feature.geometry.type === "Polygon") {
- polygons.features.forEach((feature) => {
- union.push(feature);
- });
+ const shape = new THREE.Shape();
+ const coords = feature.geometry.coordinates[0];
- if (union.length > 1) {
- const unionResult = turf.union(turf.featureCollection(union));
+ shape.moveTo(coords[0][0], coords[0][1]);
- if (unionResult?.geometry.type === "MultiPolygon") {
- unionResult.geometry.coordinates.forEach((poly) => {
- const coordinates = poly[0].map(([x, z]) => {
- return new THREE.Vector3(x, 0, z);
- });
- renderBoxGeometry(coordinates);
- });
- } else if (unionResult?.geometry.type === "Polygon") {
- const coordinates = unionResult.geometry.coordinates[0].map(
- ([x, z]) => {
- return new THREE.Vector3(x, 0, z);
+ for (let i = 1; i < coords.length; i++) {
+ shape.lineTo(coords[i][0], coords[i][1]);
}
- );
- renderBoxGeometry(coordinates);
- }
- } else if (union.length === 1) {
- const coordinates = union[0].geometry.coordinates[0].map(
- ([x, z]: [number, number]) => {
- return new THREE.Vector3(x, 0, z);
+ shape.lineTo(coords[0][0], coords[0][1]);
+
+ const extrudeSettings = {
+ depth: 5,
+ bevelEnabled: false,
+ };
+
+ const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
+
+ const material = new THREE.MeshBasicMaterial({ color: "blue", transparent: true, opacity: 0.5 });
+ const mesh = new THREE.Mesh(geometry, material);
+ mesh.rotateX(Math.PI / 2);
+ mesh.name = "agv-collider";
+ mesh.position.y = 5;
+
+ mesh.receiveShadow = true;
+ groupRef.current?.add(mesh);
}
- );
- // setRooms((prevRooms) => [...prevRooms, coordinates]);
+ });
+
}
}, [lines.current]);
- const renderBoxGeometry = (coordinates: THREE.Vector3[]) => {
- const minX = Math.min(...coordinates.map((p) => p.x));
- const maxX = Math.max(...coordinates.map((p) => p.x));
- const minZ = Math.min(...coordinates.map((p) => p.z));
- const maxZ = Math.max(...coordinates.map((p) => p.z));
-
- const width = maxX - minX;
- const depth = maxZ - minZ;
- const height = 3;
-
- const geometry = new THREE.BoxGeometry(width, height, depth);
- const material = new THREE.MeshBasicMaterial({
- color: "#ff66cc",
- visible: false,
- });
-
- const mesh = new THREE.Mesh(geometry, material);
- mesh.position.set((minX + maxX) / 2, height / 2, (minZ + maxZ) / 2);
- groupRef.current?.add(mesh);
- };
-
const renderWallGeometry = (walls: THREE.Vector3[][]) => {
walls.forEach((wall) => {
if (wall.length < 2) return;
diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx
index 134e10d..8ddcdc9 100644
--- a/app/src/modules/builder/groups/floorItemsGroup.tsx
+++ b/app/src/modules/builder/groups/floorItemsGroup.tsx
@@ -1,5 +1,5 @@
import { useFrame, useThree } from "@react-three/fiber";
-import { useActiveTool, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useLoadingProgress, useRenderDistance, useselectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode } from "../../../store/store";
+import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useLoadingProgress, useRenderDistance, useselectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode } from "../../../store/store";
import assetVisibility from "../geomentries/assets/assetVisibility";
import { useEffect } from "react";
import * as THREE from "three";
@@ -33,7 +33,6 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
const { setLoadingProgress } = useLoadingProgress();
const { activeModule } = useModuleStore();
const { socket } = useSocketStore();
-
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
@@ -306,6 +305,8 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
};
}, [deleteModels, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool, activeModule]);
+
+
useFrame(() => {
if (controls)
assetVisibility(itemsGroup, state.camera.position, renderDistance);
diff --git a/app/src/modules/builder/groups/wallItemsGroup.tsx b/app/src/modules/builder/groups/wallItemsGroup.tsx
index 00d7834..c79adde 100644
--- a/app/src/modules/builder/groups/wallItemsGroup.tsx
+++ b/app/src/modules/builder/groups/wallItemsGroup.tsx
@@ -224,6 +224,7 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable
const onDrop = (event: any) => {
if (!event.dataTransfer?.files[0]) return
+
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
diff --git a/app/src/modules/collaboration/collabCams.tsx b/app/src/modules/collaboration/collabCams.tsx
index 16e0e29..af135a7 100644
--- a/app/src/modules/collaboration/collabCams.tsx
+++ b/app/src/modules/collaboration/collabCams.tsx
@@ -112,7 +112,7 @@ const CamModelsGroup = () => {
socket.off("userDisConnectRespones");
socket.off("cameraUpdateResponse");
};
- }, [socket]);
+ }, [socket, activeUsers]);
useFrame(() => {
if (!groupRef.current) return;
diff --git a/app/src/modules/market/AssetPreview.tsx b/app/src/modules/market/AssetPreview.tsx
index be474a2..9a65990 100644
--- a/app/src/modules/market/AssetPreview.tsx
+++ b/app/src/modules/market/AssetPreview.tsx
@@ -1,6 +1,10 @@
-import React from "react";
+import React, { Suspense, useEffect } from "react";
import assetImage from "../../assets/image/image.png";
import { FiileedStarsIconSmall } from "../../components/icons/marketPlaceIcons";
+import { Canvas, useThree } from "@react-three/fiber";
+import { ContactShadows, OrbitControls, Text } from "@react-three/drei";
+import GltfLoader from "./GltfLoader";
+import * as THREE from "three";
// Define the shape of the selected card
interface SelectedCard {
@@ -17,6 +21,14 @@ interface AssetPreviewProps {
setSelectedCard: React.Dispatch>; // Type for setter function
}
+function Ui() {
+ return (
+
+ Loading your model...
+
+ );
+}
+
const AssetPreview: React.FC = ({
selectedCard,
setSelectedCard,
@@ -27,8 +39,6 @@ const AssetPreview: React.FC = ({
Math.min(5, isNaN(selectedCard.rating) ? 0 : selectedCard.rating)
);
- console.log("selectedCard: ", selectedCard);
-
// Ensure that the rating is a valid positive integer for array length
const starsArray = Array.from({ length: rating }, (_, index) => index);
@@ -36,8 +46,38 @@ const AssetPreview: React.FC = ({
-

+ {/*

*/}
{/* Add canvas here */}
+
+
+
diff --git a/app/src/modules/market/Card.tsx b/app/src/modules/market/Card.tsx
index 91729e3..e723f4f 100644
--- a/app/src/modules/market/Card.tsx
+++ b/app/src/modules/market/Card.tsx
@@ -8,6 +8,7 @@ import {
} from "../../components/icons/marketPlaceIcons";
import assetImage from "../../assets/image/image.png";
+import { getAssetDownload } from "../../services/marketplace/getAssetDownload";
interface CardProps {
assetName: string;
@@ -40,9 +41,9 @@ const Card: React.FC
= ({
return (
-
+ */}
diff --git a/app/src/modules/market/CardsContainer.tsx b/app/src/modules/market/CardsContainer.tsx
index 2704311..423fd16 100644
--- a/app/src/modules/market/CardsContainer.tsx
+++ b/app/src/modules/market/CardsContainer.tsx
@@ -16,109 +16,11 @@ interface ModelData {
uploadDate: number;
_id: string;
}
+interface ModelsProps {
+ models: ModelData[];
+}
-const CardsContainer: React.FC = () => {
- const [models, setModels] = useState
([]);
-
- const array = [
- {
- id: 1,
- name: "Asset 1",
- uploadedOn: "12 Jan 23",
- price: 36500,
- rating: 4.5,
- views: 500,
- },
- {
- id: 2,
- name: "Asset 2",
- uploadedOn: "14 Jan 23",
- price: 45000,
- rating: 4.0,
- views: 500,
- },
- {
- id: 3,
- name: "Asset 3",
- uploadedOn: "15 Jan 23",
- price: 52000,
- rating: 4.8,
- views: 500,
- },
- {
- id: 4,
- name: "Asset 4",
- uploadedOn: "18 Jan 23",
- price: 37000,
- rating: 3.9,
- views: 500,
- },
- {
- id: 5,
- name: "Asset 5",
- uploadedOn: "20 Jan 23",
- price: 60000,
- rating: 5.0,
- views: 500,
- },
- {
- id: 6,
- name: "Asset 6",
- uploadedOn: "22 Jan 23",
- price: 46000,
- rating: 4.2,
- views: 500,
- },
- {
- id: 7,
- name: "Asset 7",
- uploadedOn: "25 Jan 23",
- price: 38000,
- rating: 4.3,
- views: 500,
- },
- {
- id: 8,
- name: "Asset 8",
- uploadedOn: "27 Jan 23",
- price: 41000,
- rating: 4.1,
- views: 500,
- },
- {
- id: 9,
- name: "Asset 9",
- uploadedOn: "30 Jan 23",
- price: 55000,
- rating: 4.6,
- views: 500,
- },
- {
- id: 10,
- name: "Asset 10",
- uploadedOn: "2 Feb 23",
- price: 49000,
- rating: 4.4,
- views: 500,
- },
- {
- id: 11,
- name: "Asset 11",
- uploadedOn: "5 Feb 23",
- price: 62000,
- rating: 5.0,
- views: 500,
- },
- {
- id: 12,
- name: "Asset 12",
- uploadedOn: "7 Feb 23",
- price: 53000,
- rating: 4.7,
- views: 500,
- },
- ];
-
+const CardsContainer: React.FC = ({ models }) => {
const [selectedCard, setSelectedCard] = useState<{
assetName: string;
uploadedOn: string;
@@ -136,33 +38,11 @@ const CardsContainer: React.FC = () => {
}) => {
setSelectedCard(cardData);
};
- const getAllAssets = async () => {
- try {
- const assetsData = await fetchAssets();
- const reversedData = [...assetsData]?.reverse().slice(0, 8);
- setModels(reversedData);
- } catch (error) {
- } finally {
- }
- };
- useEffect(() => {
- getAllAssets();
- }, []);
+
return (
Products You May Like
- {/* {array.map((asset) => (
-
- ))} */}
{models.length > 0 &&
models.map((assetDetail) => (
{
uploadedOn={assetDetail.uploadDate.toString()}
price={36500}
rating={4.5}
- views={500}
+ views={800}
onSelectCard={handleCardSelect}
image={assetDetail.thumbnail}
/>
diff --git a/app/src/modules/market/FilterSearch.tsx b/app/src/modules/market/FilterSearch.tsx
index 11a2cbf..08103ba 100644
--- a/app/src/modules/market/FilterSearch.tsx
+++ b/app/src/modules/market/FilterSearch.tsx
@@ -1,19 +1,69 @@
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
// import RegularDropDown from "./ui/inputs/RegularDropDown";
import Search from "../../components/ui/inputs/Search";
import { StarsIcon } from "../../components/icons/marketPlaceIcons";
import RegularDropDown from "../../components/ui/inputs/RegularDropDown";
-
-const FilterSearch: React.FC = () => {
+import { getSortedAssets } from "../../services/marketplace/getSortedAssets";
+interface ModelData {
+ CreatedBy: string;
+ animated: string | null;
+ category: string;
+ description: string;
+ filename: string;
+ isArchieve: boolean;
+ modelfileID: string;
+ tags: string;
+ thumbnail: string;
+ uploadDate: number;
+ _id: string;
+}
+interface ModelsProps {
+ models: ModelData[];
+ setModels: React.Dispatch>;
+ filteredModels: ModelData[];
+}
+const FilterSearch: React.FC = ({
+ models,
+ setModels,
+ filteredModels,
+}) => {
const [activeOption, setActiveOption] = useState("Sort by"); // State for active option
+ console.log("filteredModels: ", filteredModels);
const handleSelect = (option: string) => {
setActiveOption(option);
+ console.log("option: ", option);
+ // Alphabet ascending
+ // Alphabet descending
+ // All
};
+ useEffect(() => {
+ if (activeOption == "Alphabet ascending") {
+ let ascending = models
+ ?.slice()
+ .sort((a, b) => a.filename.localeCompare(b.filename))
+ .map((val) => val);
+ setModels(ascending);
+ } else if (activeOption == "Alphabet descending") {
+ let descending = models
+ ?.slice()
+ .sort((a, b) => b.filename.localeCompare(a.filename))
+ .map((val) => val);
+ setModels(descending);
+ }
+ }, [activeOption]);
+ const handleSearch = (val: string) => {
+ const filteredModel = filteredModels?.filter((model) =>
+ model.filename.toLowerCase().includes(val.toLowerCase())
+ );
+
+ setModels(filteredModel);
+ };
+
return (
-
{}} />
+
void;
+ selectedAnimation?: string;
+ setSelectedAnimation?: (animation: string) => void;
+}
+
+// const getGLTFUrl = (url: string) => url; // Placeholder for your actual function
+
+const GltfLoader: React.FC = ({
+ glbdata,
+ fromServer,
+ setAnimations,
+ selectedAnimation,
+}) => {
+ const modelUrl: any = fromServer ? fetchGltfUrl(fromServer) : glbdata;
+ const { scene, animations } = useGLTF(modelUrl ?? "") as {
+ scene: Object3D;
+ animations: THREE.AnimationClip[];
+ };
+
+ const mixer = useRef(
+ scene ? new AnimationMixer(scene) : null
+ );
+ const actions = useRef>({});
+
+ useEffect(() => {
+ if (animations.length > 0 && mixer.current && setAnimations) {
+ const animationNames = animations.map((animation) => animation.name);
+ setAnimations(animationNames);
+
+ animations.forEach((animation) => {
+ const action = mixer.current!.clipAction(animation);
+ actions.current[animation.name] = action;
+ });
+ } else {
+ setAnimations && setAnimations([]);
+ }
+ }, [animations, setAnimations]);
+
+ useEffect(() => {
+ if (actions.current && selectedAnimation) {
+ const action = actions.current[selectedAnimation];
+ if (action) {
+ action.reset().fadeIn(0.5).play();
+ return () => {
+ action.fadeOut(0.5);
+ };
+ }
+ }
+ }, [selectedAnimation]);
+
+ useFrame((_, delta) => {
+ if (mixer.current) {
+ mixer.current.update(delta);
+ }
+ });
+
+ return (
+
+
+
+ );
+};
+
+export default GltfLoader;
diff --git a/app/src/modules/market/MarketPlace.tsx b/app/src/modules/market/MarketPlace.tsx
index 71dc0a5..d830576 100644
--- a/app/src/modules/market/MarketPlace.tsx
+++ b/app/src/modules/market/MarketPlace.tsx
@@ -1,14 +1,46 @@
-import React from "react";
+import React, { useEffect, useState } from "react";
import FilterSearch from "./FilterSearch";
import CardsContainer from "./CardsContainer";
-
+import { fetchAssets } from "../../services/marketplace/fetchAssets";
+import { getAssetImages } from "../../services/factoryBuilder/assest/assets/getAssetImages";
+interface ModelData {
+ CreatedBy: string;
+ animated: string | null;
+ category: string;
+ description: string;
+ filename: string;
+ isArchieve: boolean;
+ modelfileID: string;
+ tags: string;
+ thumbnail: string;
+ uploadDate: number;
+ _id: string;
+}
const MarketPlace = () => {
+ const [models, setModels] = useState([]);
+ const [filteredModels, setFilteredModels] = useState([]);
+
+ useEffect(() => {
+ const filteredAssets = async () => {
+ try {
+ const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6");
+ setModels(filt.items);
+ setFilteredModels(filt.items);
+ } catch {}
+ };
+ filteredAssets();
+ }, []);
+
return (
diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx
index 8ceeb2e..ac74240 100644
--- a/app/src/modules/scene/scene.tsx
+++ b/app/src/modules/scene/scene.tsx
@@ -19,6 +19,8 @@ import DroppedObjects from "../../components/ui/componets/DroppedFloatingWidgets
// import Simulation from "./simulationtemp/simulation";
import ZoneCentreTarget from "../../components/ui/componets/zoneCameraTarget";
+import ProductionCapacity from "../../components/layout/3D-cards/cards/ProductionCapacity";
+import Dropped3dWidgets from "../../components/ui/componets/Dropped3dWidget";
export default function Scene() {
@@ -43,13 +45,13 @@ export default function Scene() {
}}
>
+
- {/* */}
@@ -58,9 +60,6 @@ export default function Scene() {
-
-
-
);
}
diff --git a/app/src/modules/simulation/behaviour/behaviour.tsx b/app/src/modules/simulation/behaviour/behaviour.tsx
index d7a08af..2854172 100644
--- a/app/src/modules/simulation/behaviour/behaviour.tsx
+++ b/app/src/modules/simulation/behaviour/behaviour.tsx
@@ -1,43 +1,29 @@
-import { useFloorItems } from '../../../store/store';
+import { useFloorItems, useSimulationPaths } from '../../../store/store';
import * as THREE from 'three';
import * as Types from '../../../types/world/worldTypes';
import { useEffect } from 'react';
-interface Path {
- modeluuid: string;
- modelName: string;
- points: {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
- triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | [];
- connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
- }[];
- pathPosition: [number, number, number];
- pathRotation: [number, number, number];
- speed: number;
-}
-
-function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) {
+function Behaviour() {
+ const { setSimulationPaths } = useSimulationPaths();
const { floorItems } = useFloorItems();
useEffect(() => {
- const newPaths: Path[] = [];
+ const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[] = [];
floorItems.forEach((item: Types.FloorItemType) => {
- if (item.modelfileID === "6633215057b31fe671145959") {
- const point1Position = new THREE.Vector3(0, 1.25, 3.3);
- const middlePointPosition = new THREE.Vector3(0, 1.25, 0);
- const point2Position = new THREE.Vector3(0, 1.25, -3.3);
+ if (item.modelfileID === "672a090f80d91ac979f4d0bd") {
+ 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: Path = {
+ const newPath: Types.ConveyorEventsSchema = {
modeluuid: item.modeluuid,
modelName: item.modelname,
+ type: 'Conveyor',
points: [
{
uuid: point1UUID,
@@ -64,12 +50,32 @@ function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) {
connections: { source: { pathUUID: item.modeluuid, pointUUID: point2UUID }, targets: [] },
},
],
- pathPosition: [...item.position],
- pathRotation: [item.rotation.x, item.rotation.y, item.rotation.z],
+ assetPosition: [...item.position],
+ assetRotation: [item.rotation.x, item.rotation.y, item.rotation.z],
speed: 1,
};
newPaths.push(newPath);
+ } else if (item.modelfileID === "67e3da19c2e8f37134526e6a") {
+ const pointUUID = THREE.MathUtils.generateUUID();
+ const pointPosition = new THREE.Vector3(0, 1.3, 0);
+
+ const newVehiclePath: Types.VehicleEventsSchema = {
+ modeluuid: item.modeluuid,
+ modelName: item.modelname,
+ type: 'Vehicle',
+ point: {
+ uuid: pointUUID,
+ position: [pointPosition.x, pointPosition.y, pointPosition.z],
+ actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: THREE.MathUtils.generateUUID(), hitCount: 1, end: THREE.MathUtils.generateUUID(), buffer: 0, isUsed: false }],
+ triggers: [],
+ connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
+ },
+ assetPosition: [...item.position],
+ speed: 2,
+ };
+
+ newPaths.push(newVehiclePath);
}
});
diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx
index 93172b7..8df718c 100644
--- a/app/src/modules/simulation/path/pathConnector.tsx
+++ b/app/src/modules/simulation/path/pathConnector.tsx
@@ -1,6 +1,7 @@
import { useFrame, useThree } from '@react-three/fiber';
import React, { useEffect, useState } from 'react';
import * as THREE from 'three';
+import * as Types from '../../../types/world/worldTypes';
import { QuadraticBezierLine } from '@react-three/drei';
import { useIsConnecting, useSimulationPaths } from '../../../store/store';
import useModuleStore from '../../../store/useModuleStore';
@@ -27,61 +28,113 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
toPointUUID: string
) => {
const updatedPaths = simulationPaths.map(path => {
- if (path.modeluuid === fromPathUUID) {
- return {
- ...path,
- points: path.points.map(point => {
- if (point.uuid === fromPointUUID) {
- const newTarget = {
- pathUUID: toPathUUID,
- pointUUID: toPointUUID
- };
- const existingTargets = point.connections.targets || [];
-
- if (!existingTargets.some(target =>
- target.pathUUID === newTarget.pathUUID &&
- target.pointUUID === newTarget.pointUUID
- )) {
- return {
- ...point,
- connections: {
- ...point.connections,
- targets: [...existingTargets, newTarget]
- }
+ if (path.type === 'Conveyor') {
+ if (path.modeluuid === fromPathUUID) {
+ return {
+ ...path,
+ points: path.points.map(point => {
+ if (point.uuid === fromPointUUID) {
+ const newTarget = {
+ pathUUID: toPathUUID,
+ pointUUID: toPointUUID
};
+ const existingTargets = point.connections.targets || [];
+
+ if (!existingTargets.some(target =>
+ target.pathUUID === newTarget.pathUUID &&
+ target.pointUUID === newTarget.pointUUID
+ )) {
+ return {
+ ...point,
+ connections: {
+ ...point.connections,
+ targets: [...existingTargets, newTarget]
+ }
+ };
+ }
}
- }
- return point;
- })
- };
+ return point;
+ })
+ };
+ }
+ else if (path.modeluuid === toPathUUID) {
+ return {
+ ...path,
+ points: path.points.map(point => {
+ if (point.uuid === toPointUUID) {
+ const reverseTarget = {
+ pathUUID: fromPathUUID,
+ pointUUID: fromPointUUID
+ };
+ const existingTargets = point.connections.targets || [];
+
+ if (!existingTargets.some(target =>
+ target.pathUUID === reverseTarget.pathUUID &&
+ target.pointUUID === reverseTarget.pointUUID
+ )) {
+ return {
+ ...point,
+ connections: {
+ ...point.connections,
+ targets: [...existingTargets, reverseTarget]
+ }
+ };
+ }
+ }
+ return point;
+ })
+ };
+ }
}
- else if (path.modeluuid === toPathUUID) {
- return {
- ...path,
- points: path.points.map(point => {
- if (point.uuid === toPointUUID) {
- const reverseTarget = {
- pathUUID: fromPathUUID,
- pointUUID: fromPointUUID
- };
- const existingTargets = point.connections.targets || [];
+ else if (path.type === 'Vehicle') {
+ // Handle outgoing connections from Vehicle
+ if (path.modeluuid === fromPathUUID && path.point.uuid === fromPointUUID) {
+ const newTarget = {
+ pathUUID: toPathUUID,
+ pointUUID: toPointUUID
+ };
+ const existingTargets = path.point.connections.targets || [];
- if (!existingTargets.some(target =>
- target.pathUUID === reverseTarget.pathUUID &&
- target.pointUUID === reverseTarget.pointUUID
- )) {
- return {
- ...point,
- connections: {
- ...point.connections,
- targets: [...existingTargets, reverseTarget]
- }
- };
+ if (!existingTargets.some(target =>
+ target.pathUUID === newTarget.pathUUID &&
+ target.pointUUID === newTarget.pointUUID
+ )) {
+ return {
+ ...path,
+ point: {
+ ...path.point,
+ connections: {
+ ...path.point.connections,
+ targets: [...existingTargets, newTarget]
+ }
}
- }
- return point;
- })
- };
+ };
+ }
+ }
+ // Handle incoming connections to Vehicle
+ else if (path.modeluuid === toPathUUID && path.point.uuid === toPointUUID) {
+ const reverseTarget = {
+ pathUUID: fromPathUUID,
+ pointUUID: fromPointUUID
+ };
+ const existingTargets = path.point.connections.targets || [];
+
+ if (!existingTargets.some(target =>
+ target.pathUUID === reverseTarget.pathUUID &&
+ target.pointUUID === reverseTarget.pointUUID
+ )) {
+ return {
+ ...path,
+ point: {
+ ...path.point,
+ connections: {
+ ...path.point.connections,
+ targets: [...existingTargets, reverseTarget]
+ }
+ }
+ };
+ }
+ }
}
return path;
});
@@ -126,25 +179,43 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
if (intersects.length > 0) {
const intersected = intersects[0].object;
- if (intersected.name.includes("action-sphere")) {
+ if (intersected.name.includes("events-sphere")) {
const pathUUID = intersected.userData.path.modeluuid;
const sphereUUID = intersected.uuid;
const worldPosition = new THREE.Vector3();
intersected.getWorldPosition(worldPosition);
- const isStartOrEnd = intersected.userData.path.points.length > 0 && (
- sphereUUID === intersected.userData.path.points[0].uuid ||
- sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid
- );
+ let isStartOrEnd = false;
+
+ if (intersected.userData.path.points) {
+ isStartOrEnd = intersected.userData.path.points.length > 0 && (
+ sphereUUID === intersected.userData.path.points[0].uuid ||
+ sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid
+ );
+ } else if (intersected.userData.path.point) {
+ isStartOrEnd = sphereUUID === intersected.userData.path.point.uuid;
+ }
if (pathUUID) {
- // Check if sphere is already connected
- const isAlreadyConnected = simulationPaths.some(path =>
- path.points.some(point =>
- point.uuid === sphereUUID &&
- point.connections.targets.length > 0
- )
- );
+ const firstPath = simulationPaths.find(p => p.modeluuid === firstSelected?.pathUUID);
+ const secondPath = simulationPaths.find(p => p.modeluuid === pathUUID);
+
+ if (firstPath && secondPath && firstPath.type === 'Vehicle' && secondPath.type === 'Vehicle') {
+ console.log("Cannot connect two vehicle paths together");
+ return;
+ }
+ const isAlreadyConnected = simulationPaths.some(path => {
+ if (path.type === 'Conveyor') {
+ return path.points.some(point =>
+ point.uuid === sphereUUID &&
+ point.connections.targets.length > 0
+ );
+ } else if (path.type === 'Vehicle') {
+ return path.point.uuid === sphereUUID &&
+ path.point.connections.targets.length > 0;
+ }
+ return false;
+ });
if (isAlreadyConnected) {
console.log("Sphere is already connected. Ignoring.");
@@ -211,6 +282,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(scene.children, true).filter((intersect) =>
!intersect.object.name.includes("Roof") &&
+ !intersect.object.name.includes("agv-collider") &&
!intersect.object.name.includes("MeasurementReference") &&
!intersect.object.userData.isPathObject &&
!(intersect.object.type === "GridHelper")
@@ -229,7 +301,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
}
const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) =>
- obj.object.name.includes("action-sphere")
+ obj.object.name.includes("events-sphere")
);
if (sphereIntersects.length > 0) {
@@ -237,27 +309,45 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
const sphereUUID = sphere.uuid;
const spherePosition = new THREE.Vector3();
sphere.getWorldPosition(spherePosition);
- const pathUUID = sphere.userData.path.modeluuid;
+ const pathData = sphere.userData.path;
+ const pathUUID = pathData.modeluuid;
- const isStartOrEnd = sphere.userData.path.points.length > 0 && (
- sphereUUID === sphere.userData.path.points[0].uuid ||
- sphereUUID === sphere.userData.path.points[sphere.userData.path.points.length - 1].uuid
- );
+ const firstPath = simulationPaths.find(p => p.modeluuid === firstSelected.pathUUID);
+ const secondPath = simulationPaths.find(p => p.modeluuid === pathUUID);
+ const isVehicleToVehicle = firstPath?.type === 'Vehicle' && secondPath?.type === 'Vehicle';
- const isAlreadyConnected = simulationPaths.some(path =>
- path.points.some(point =>
- point.uuid === sphereUUID &&
- point.connections.targets.length > 0
- )
- );
+ const isConnectable = (pathData.type === 'Vehicle' ||
+ (pathData.points.length > 0 && (
+ sphereUUID === pathData.points[0].uuid ||
+ sphereUUID === pathData.points[pathData.points.length - 1].uuid
+ ))) && !isVehicleToVehicle;
+
+ const isAlreadyConnected = simulationPaths.some(path => {
+ if (path.type === 'Conveyor') {
+ return path.points.some(point =>
+ point.uuid === sphereUUID &&
+ point.connections.targets.length > 0
+ );
+ } else if (path.type === 'Vehicle') {
+ return path.point.uuid === sphereUUID &&
+ path.point.connections.targets.length > 0;
+ }
+ return false;
+ });
if (
!isAlreadyConnected &&
+ !isVehicleToVehicle &&
firstSelected.sphereUUID !== sphereUUID &&
firstSelected.pathUUID !== pathUUID &&
- (firstSelected.isCorner || isStartOrEnd)
+ (firstSelected.isCorner || isConnectable)
) {
- snappedSphere = { sphereUUID, position: spherePosition, pathUUID, isCorner: isStartOrEnd };
+ snappedSphere = {
+ sphereUUID,
+ position: spherePosition,
+ pathUUID,
+ isCorner: isConnectable
+ };
} else {
isInvalidConnection = true;
}
@@ -281,8 +371,13 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
end: point,
mid: midPoint,
});
+ console.log({
+ start: firstSelected.position,
+ end: point,
+ mid: midPoint,
+ });
- setIsConnecting(true);
+ // setIsConnecting(true);
if (sphereIntersects.length > 0) {
setHelperLineColor(isInvalidConnection ? 'red' : '#6cf542');
@@ -299,13 +394,53 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
}
});
- // Render connections from simulationPaths
return (
<>
- {simulationPaths.flatMap(path =>
- path.points.flatMap(point =>
- point.connections.targets.map((target, index) => {
- const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid);
+ {simulationPaths.flatMap(path => {
+ if (path.type === 'Conveyor') {
+ return path.points.flatMap(point =>
+ point.connections.targets.map((target, index) => {
+ const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID);
+ if (targetPath?.type === 'Vehicle') return null;
+
+ const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid);
+ const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
+
+ if (fromSphere && toSphere) {
+ const fromWorldPosition = new THREE.Vector3();
+ const toWorldPosition = new THREE.Vector3();
+ fromSphere.getWorldPosition(fromWorldPosition);
+ toSphere.getWorldPosition(toWorldPosition);
+
+ const distance = fromWorldPosition.distanceTo(toWorldPosition);
+ const heightFactor = Math.max(0.5, distance * 0.2);
+
+ const midPoint = new THREE.Vector3(
+ (fromWorldPosition.x + toWorldPosition.x) / 2,
+ Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor,
+ (fromWorldPosition.z + toWorldPosition.z) / 2
+ );
+
+ return (
+
+ );
+ }
+ return null;
+ })
+ );
+ } else if (path.type === 'Vehicle') {
+ return path.point.connections.targets.map((target, index) => {
+ const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.point.uuid);
const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
if (fromSphere && toSphere) {
@@ -325,22 +460,23 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
return (
);
}
return null;
- })
- )
- )}
+ });
+ }
+ return [];
+ })}
{currentLine && (
{
if (!selectedActionSphere) return;
- const updatedPaths: Path[] = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? {
- ...point,
- position: [
- selectedActionSphere.point.position.x,
- selectedActionSphere.point.position.y,
- selectedActionSphere.point.position.z,
- ],
- rotation: [
- selectedActionSphere.point.rotation.x,
- selectedActionSphere.point.rotation.y,
- selectedActionSphere.point.rotation.z,
- ]
- }
- : point
- ),
- }));
+ const updatedPaths = simulationPaths.map((path) => {
+ if (path.type === "Conveyor") {
+ return {
+ ...path,
+ points: path.points.map((point) =>
+ point.uuid === selectedActionSphere.point.uuid
+ ? {
+ ...point,
+ position: [
+ selectedActionSphere.point.position.x,
+ selectedActionSphere.point.position.y,
+ selectedActionSphere.point.position.z,
+ ],
+ rotation: [
+ selectedActionSphere.point.rotation.x,
+ selectedActionSphere.point.rotation.y,
+ selectedActionSphere.point.rotation.z,
+ ]
+ }
+ : point
+ ),
+ };
+ }
+ return path;
+ }) as ConveyorEventsSchema[];
setSimulationPaths(updatedPaths);
};
return (
-
+
{simulationPaths.map((path) => {
- const points = path.points.map(point => new THREE.Vector3(...point.position));
+ if (path.type === 'Conveyor') {
+ const points = path.points.map(point => new THREE.Vector3(...point.position));
- return (
- (groupRefs.current[path.modeluuid] = el!)}
- position={path.pathPosition}
- rotation={path.pathRotation}
- onClick={(e) => {
- if (isConnecting) return;
- e.stopPropagation();
- setSelectedPath({ path, group: groupRefs.current[path.modeluuid] });
- setSelectedActionSphere(null);
- setTransformMode(null);
- setSubModule('mechanics');
- }}
- onPointerMissed={() => {
- setSelectedPath(null);
- setSubModule('properties');
- }}
- >
- {path.points.map((point, index) => (
+ return (
+ (groupRefs.current[path.modeluuid] = el!)}
+ position={path.assetPosition}
+ rotation={path.assetRotation}
+ onClick={(e) => {
+ if (isConnecting) return;
+ e.stopPropagation();
+ setSelectedPath({ path, group: groupRefs.current[path.modeluuid] });
+ setSelectedActionSphere(null);
+ setTransformMode(null);
+ setSubModule('mechanics');
+ }}
+ onPointerMissed={() => {
+ setSelectedPath(null);
+ setSubModule('properties');
+ }}
+ >
+ {path.points.map((point, index) => (
+ (sphereRefs.current[point.uuid] = el!)}
+ onClick={(e) => {
+ if (isConnecting) return;
+ e.stopPropagation();
+ setSelectedActionSphere({
+ path,
+ point: sphereRefs.current[point.uuid]
+ });
+ setSubModule('mechanics');
+ setSelectedPath(null);
+ }}
+ userData={{ point, path }}
+ onPointerMissed={() => {
+ setSubModule('properties');
+ setSelectedActionSphere(null);
+ }}
+ >
+
+
+ ))}
+
+ {points.slice(0, -1).map((point, index) => {
+ const nextPoint = points[index + 1];
+ const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]);
+ const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false);
+
+ return (
+
+
+
+ );
+ })}
+
+ );
+ } else if (path.type === 'Vehicle') {
+ return (
+ (groupRefs.current[path.modeluuid] = el!)}
+ position={path.assetPosition}
+ onClick={(e) => {
+ if (isConnecting) return;
+ e.stopPropagation();
+ setSelectedPath({ path, group: groupRefs.current[path.modeluuid] });
+ setSelectedActionSphere(null);
+ setTransformMode(null);
+ setSubModule('mechanics');
+ }}
+ onPointerMissed={() => {
+ setSelectedPath(null);
+ setSubModule('properties');
+ }}
+ >
(sphereRefs.current[point.uuid] = el!)}
+ name='events-sphere'
+ ref={el => (sphereRefs.current[path.point.uuid] = el!)}
onClick={(e) => {
if (isConnecting) return;
e.stopPropagation();
setSelectedActionSphere({
path,
- point: sphereRefs.current[point.uuid]
+ point: sphereRefs.current[path.point.uuid]
});
setSubModule('mechanics');
setSelectedPath(null);
}}
- userData={{ point, path }}
+ userData={{ point: path.point, path }}
onPointerMissed={() => {
setSubModule('properties');
- setSelectedActionSphere(null)
+ setSelectedActionSphere(null);
}}
>
-
+
- ))}
-
- {points.slice(0, -1).map((point, index) => {
- const nextPoint = points[index + 1];
- const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]);
- const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false);
-
- return (
-
-
-
- );
- })}
-
- );
+
+ );
+ }
+ return null;
})}
{selectedActionSphere && transformMode && (
@@ -163,7 +220,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
ref={transformRef}
object={selectedActionSphere.point}
mode={transformMode}
- onObjectChange={updateSimulationPaths}
+ onMouseUp={updateSimulationPaths}
/>
)}
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index fab1042..73ef27f 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -14,7 +14,7 @@ function Simulation() {
const [processes, setProcesses] = useState([]);
useEffect(() => {
- console.log('simulationPaths: ', simulationPaths);
+
}, [simulationPaths]);
// useEffect(() => {
@@ -31,7 +31,7 @@ function Simulation() {
return (
<>
-
+
{activeModule === 'simulation' && (
<>
diff --git a/app/src/modules/simulation/simulationUI.tsx b/app/src/modules/simulation/simulationUI.tsx
index 3a84134..0ce9fc2 100644
--- a/app/src/modules/simulation/simulationUI.tsx
+++ b/app/src/modules/simulation/simulationUI.tsx
@@ -1,409 +1,409 @@
-import { useMemo, useState } from 'react';
-import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation, useDrawMaterialPath } from '../../store/store';
-import * as THREE from 'three';
-import useModuleStore from '../../store/useModuleStore';
+// import { useMemo, useState } from 'react';
+// import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation, useDrawMaterialPath } from '../../store/store';
+// import * as THREE from 'three';
+// import useModuleStore from '../../store/useModuleStore';
-function SimulationUI() {
- const { ToggleView } = useToggleView();
- const { activeModule } = useModuleStore();
- const { startSimulation, setStartSimulation } = useStartSimulation();
- const { selectedActionSphere } = useSelectedActionSphere();
- const { selectedPath, setSelectedPath } = useSelectedPath();
- const { simulationPaths, setSimulationPaths } = useSimulationPaths();
- const { drawMaterialPath, setDrawMaterialPath } = useDrawMaterialPath();
- const [activeButton, setActiveButton] = useState(null);
+// function SimulationUI() {
+// const { ToggleView } = useToggleView();
+// const { activeModule } = useModuleStore();
+// const { startSimulation, setStartSimulation } = useStartSimulation();
+// const { selectedActionSphere } = useSelectedActionSphere();
+// const { selectedPath, setSelectedPath } = useSelectedPath();
+// const { simulationPaths, setSimulationPaths } = useSimulationPaths();
+// const { drawMaterialPath, setDrawMaterialPath } = useDrawMaterialPath();
+// const [activeButton, setActiveButton] = useState(null);
- const handleAddAction = () => {
- if (!selectedActionSphere) return;
+// const handleAddAction = () => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) => {
- if (point.uuid === selectedActionSphere.point.uuid) {
- const actionIndex = point.actions.length;
- const newAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: `Action ${actionIndex + 1}`, // Assign action name based on index
- type: 'Inherit',
- material: 'Inherit',
- delay: 'Inherit',
- spawnInterval: 'Inherit',
- isUsed: false
- };
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) => {
+// if (point.uuid === selectedActionSphere.point.uuid) {
+// const actionIndex = point.actions.length;
+// const newAction = {
+// uuid: THREE.MathUtils.generateUUID(),
+// name: `Action ${actionIndex + 1}`, // Assign action name based on index
+// type: 'Inherit',
+// material: 'Inherit',
+// delay: 'Inherit',
+// spawnInterval: 'Inherit',
+// isUsed: false
+// };
- return { ...point, actions: [...point.actions, newAction] };
- }
- return point;
- }),
- }));
+// return { ...point, actions: [...point.actions, newAction] };
+// }
+// return point;
+// }),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleDeleteAction = (uuid: string) => {
- if (!selectedActionSphere) return;
+// const handleDeleteAction = (uuid: string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleActionSelect = (uuid: string, actionType: string) => {
- if (!selectedActionSphere) return;
+// const handleActionSelect = (uuid: string, actionType: string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? {
- ...point,
- actions: point.actions.map((action) =>
- action.uuid === uuid ? { ...action, type: actionType } : action
- ),
- }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? {
+// ...point,
+// actions: point.actions.map((action) =>
+// action.uuid === uuid ? { ...action, type: actionType } : action
+// ),
+// }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleMaterialSelect = (uuid: string, material: string) => {
- if (!selectedActionSphere) return;
+// const handleMaterialSelect = (uuid: string, material: string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? {
- ...point,
- actions: point.actions.map((action) =>
- action.uuid === uuid ? { ...action, material } : action
- ),
- }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? {
+// ...point,
+// actions: point.actions.map((action) =>
+// action.uuid === uuid ? { ...action, material } : action
+// ),
+// }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleDelayChange = (uuid: string, delay: number | string) => {
- if (!selectedActionSphere) return;
+// const handleDelayChange = (uuid: string, delay: number | string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? {
- ...point,
- actions: point.actions.map((action) =>
- action.uuid === uuid ? { ...action, delay } : action
- ),
- }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? {
+// ...point,
+// actions: point.actions.map((action) =>
+// action.uuid === uuid ? { ...action, delay } : action
+// ),
+// }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => {
- if (!selectedActionSphere) return;
+// const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? {
- ...point,
- actions: point.actions.map((action) =>
- action.uuid === uuid ? { ...action, spawnInterval } : action
- ),
- }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? {
+// ...point,
+// actions: point.actions.map((action) =>
+// action.uuid === uuid ? { ...action, spawnInterval } : action
+// ),
+// }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleSpeedChange = (speed: number) => {
- if (!selectedPath) return;
+// const handleSpeedChange = (speed: number) => {
+// if (!selectedPath) return;
- const updatedPaths = simulationPaths.map((path) =>
- path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
- );
+// const updatedPaths = simulationPaths.map((path) =>
+// path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
+// );
- setSimulationPaths(updatedPaths);
- setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
- };
+// setSimulationPaths(updatedPaths);
+// setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
+// };
- const handleAddTrigger = () => {
- if (!selectedActionSphere) return;
+// const handleAddTrigger = () => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) => {
- if (point.uuid === selectedActionSphere.point.uuid) {
- const triggerIndex = point.triggers.length;
- const newTrigger = {
- uuid: THREE.MathUtils.generateUUID(),
- name: `Trigger ${triggerIndex + 1}`, // Assign name based on index
- type: '',
- isUsed: false
- };
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) => {
+// if (point.uuid === selectedActionSphere.point.uuid) {
+// const triggerIndex = point.triggers.length;
+// const newTrigger = {
+// uuid: THREE.MathUtils.generateUUID(),
+// name: `Trigger ${triggerIndex + 1}`, // Assign name based on index
+// type: '',
+// isUsed: false
+// };
- return { ...point, triggers: [...point.triggers, newTrigger] };
- }
- return point;
- }),
- }));
+// return { ...point, triggers: [...point.triggers, newTrigger] };
+// }
+// return point;
+// }),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleDeleteTrigger = (uuid: string) => {
- if (!selectedActionSphere) return;
+// const handleDeleteTrigger = (uuid: string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleTriggerSelect = (uuid: string, triggerType: string) => {
- if (!selectedActionSphere) return;
+// const handleTriggerSelect = (uuid: string, triggerType: string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? {
- ...point,
- triggers: point.triggers.map((trigger) =>
- trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger
- ),
- }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? {
+// ...point,
+// triggers: point.triggers.map((trigger) =>
+// trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger
+// ),
+// }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleResetPath = () => {
- if (!selectedPath) return;
+// const handleResetPath = () => {
+// if (!selectedPath) return;
- };
+// };
- const handleActionToggle = (uuid: string) => {
- if (!selectedActionSphere) return;
+// const handleActionToggle = (uuid: string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? {
- ...point,
- actions: point.actions.map((action) => ({
- ...action,
- isUsed: action.uuid === uuid ? !action.isUsed : false,
- })),
- }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? {
+// ...point,
+// actions: point.actions.map((action) => ({
+// ...action,
+// isUsed: action.uuid === uuid ? !action.isUsed : false,
+// })),
+// }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const handleTriggerToggle = (uuid: string) => {
- if (!selectedActionSphere) return;
+// const handleTriggerToggle = (uuid: string) => {
+// if (!selectedActionSphere) return;
- const updatedPaths = simulationPaths.map((path) => ({
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.point.uuid
- ? {
- ...point,
- triggers: point.triggers.map((trigger) => ({
- ...trigger,
- isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
- })),
- }
- : point
- ),
- }));
+// const updatedPaths = simulationPaths.map((path) => ({
+// ...path,
+// points: path.points.map((point) =>
+// point.uuid === selectedActionSphere.point.uuid
+// ? {
+// ...point,
+// triggers: point.triggers.map((trigger) => ({
+// ...trigger,
+// isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
+// })),
+// }
+// : point
+// ),
+// }));
- setSimulationPaths(updatedPaths);
- };
+// setSimulationPaths(updatedPaths);
+// };
- const selectedPoint = useMemo(() => {
- if (!selectedActionSphere) return null;
- return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid);
- }, [selectedActionSphere, simulationPaths]);
+// const selectedPoint = useMemo(() => {
+// if (!selectedActionSphere) return null;
+// return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid);
+// }, [selectedActionSphere, simulationPaths]);
- const createPath = () => {
- setActiveButton(activeButton !== 'addMaterialPath' ? 'addMaterialPath' : null);
- setDrawMaterialPath(!drawMaterialPath);
- }
+// const createPath = () => {
+// setActiveButton(activeButton !== 'addMaterialPath' ? 'addMaterialPath' : null);
+// setDrawMaterialPath(!drawMaterialPath);
+// }
- return (
- <>
- {activeModule === "simulation" && (
-
- {!ToggleView && (
- <>
-
+// return (
+// <>
+// {activeModule === "simulation" && (
+//
+// {!ToggleView && (
+// <>
+//
-
- {!ToggleView && }
-
+//
+// {!ToggleView && }
+//
- {selectedPath && (
-
-
- handleSpeedChange(parseFloat(e.target.value))}
- />
-
- )}
+// {selectedPath && (
+//
+//
+// handleSpeedChange(parseFloat(e.target.value))}
+// />
+//
+// )}
- {selectedActionSphere && (
-
-
-
+// {selectedActionSphere && (
+//
+//
+//
- {selectedPoint?.actions.map((action) => (
-
-
-
-
+// {selectedPoint?.actions.map((action) => (
+//
+//
+//
+//
- {(action.type === 'Spawn' || action.type === 'Swap') && (
-
-
-
- )}
+// {(action.type === 'Spawn' || action.type === 'Swap') && (
+//
+//
+//
+// )}
- {action.type === 'Delay' && (
-
+// )}
- {action.type === 'Spawn' && (
-
-
-
handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')}
- />
+// {action.type === 'Spawn' && (
+//
+//
+// handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')}
+// />
-
- )}
-
-
- ))}
+//
+// )}
+//
+//
+// ))}
-
+//
- {selectedPoint?.triggers.map((trigger) => (
-
-
-
-
-
-
- ))}
+// {selectedPoint?.triggers.map((trigger) => (
+//
+//
+//
+//
+//
+//
+// ))}
-
- )}
+//
+// )}
- {selectedPath && (
-
-
-
- )}
- >
- )}
-
- )}
- >
- );
-}
+// {selectedPath && (
+//
+//
+//
+// )}
+// >
+// )}
+//
+// )}
+// >
+// );
+// }
-export default SimulationUI;
\ No newline at end of file
+// export default SimulationUI;
\ No newline at end of file
diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx
index 1046ea2..a7800e1 100644
--- a/app/src/pages/Project.tsx
+++ b/app/src/pages/Project.tsx
@@ -64,7 +64,6 @@ const Project: React.FC = () => {
{activeModule === "market" && }
{activeModule !== "market" && }
- {/* */}
{isPlaying && activeModule === "simulation" && }
);
diff --git a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts
index cd79484..41175ca 100644
--- a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts
+++ b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts
@@ -6,10 +6,7 @@ const MqttEvents = () => {
const { setTouch, setTemperature, setHumidity } = useDrieUIValue();
useEffect(() => {
- const client = mqtt.connect("ws://192.168.0.192:1884", {
- username: "gabby",
- password: "gabby"
- });
+ const client = mqtt.connect(`ws://${process.env.REACT_APP_SERVER_MQTT_URL}`);
client.subscribe("touch");
client.subscribe("temperature");
diff --git a/app/src/services/marketplace/fetchAssetDetails.ts b/app/src/services/marketplace/fetchAssetDetails.ts
new file mode 100644
index 0000000..b14fd3f
--- /dev/null
+++ b/app/src/services/marketplace/fetchAssetDetails.ts
@@ -0,0 +1,22 @@
+let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+export const getAssetDetails = async (filename: string) => {
+ try {
+ const response = await fetch(`${BackEnd_url}/api/v1/assetDetails`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ filename }),
+ });
+
+ if (!response.ok) {
+ throw new Error("Failed to fetch asset details");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error: any) {
+ // console.error("Error fetching category:", error.message);
+ throw new Error(error.message);
+ }
+};
diff --git a/app/src/services/marketplace/fetchAssets.ts b/app/src/services/marketplace/fetchAssets.ts
index 3408252..e434a2b 100644
--- a/app/src/services/marketplace/fetchAssets.ts
+++ b/app/src/services/marketplace/fetchAssets.ts
@@ -6,6 +6,8 @@ export const fetchAssets = async () => {
throw new Error("Network response was not ok");
}
const result = await response.json();
+ const last10Assets = result.slice(-10);
+ console.log('last10Assets: ', last10Assets);
return result;
} catch (error) {
console.log("error: ", error);
diff --git a/app/src/services/marketplace/fetchGltfUrl.ts b/app/src/services/marketplace/fetchGltfUrl.ts
new file mode 100644
index 0000000..3916c9e
--- /dev/null
+++ b/app/src/services/marketplace/fetchGltfUrl.ts
@@ -0,0 +1,7 @@
+let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+export const fetchGltfUrl = (filename: string) => {
+ if (filename) {
+ return `${BackEnd_url}/api/v1/getAssetFile/${filename}`;
+ }
+ return null; // or handle the case when filename is not provided
+};
diff --git a/app/src/services/marketplace/getAssetDownload.ts b/app/src/services/marketplace/getAssetDownload.ts
new file mode 100644
index 0000000..dea6d14
--- /dev/null
+++ b/app/src/services/marketplace/getAssetDownload.ts
@@ -0,0 +1,4 @@
+let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+export const getAssetDownload = (filename: any) => {
+ return `${BackEnd_url}/api/v1/getAssetFile/${filename}.gltf`;
+};
diff --git a/app/src/services/marketplace/getSortedAssets.ts b/app/src/services/marketplace/getSortedAssets.ts
new file mode 100644
index 0000000..3bbbfbe
--- /dev/null
+++ b/app/src/services/marketplace/getSortedAssets.ts
@@ -0,0 +1,25 @@
+let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+export const getSortedAssets = async (category: any, orders: any) => {
+ try {
+ const response = await fetch(
+ `${BackEnd_url}/api/v1/categoryWise/${category}?sortBy=${orders}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error(`Error: ${response.statusText}`);
+ }
+
+ const result = await response.json();
+
+ return result; // Return the result to be used later
+ } catch (error: any) {
+ console.error("Error fetching category:", error.message);
+ throw new Error(error.message);
+ }
+};
diff --git a/app/src/services/realTimeVisulization/zoneData/addWidgets.ts b/app/src/services/realTimeVisulization/zoneData/addWidgets.ts
new file mode 100644
index 0000000..683943e
--- /dev/null
+++ b/app/src/services/realTimeVisulization/zoneData/addWidgets.ts
@@ -0,0 +1,30 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const addingWidgets = async (
+ zoneId: string,
+ organization: string,
+ widget: {}
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/v2/widget/save`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ organization, zoneId, widget }),
+ });
+
+ if (!response.ok) {
+ throw new Error("Failed to add widget in the zone");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ if (error instanceof Error) {
+ throw new Error(error.message);
+ } else {
+ throw new Error("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/realTimeVisulization/zoneData/getSelect2dZoneData.ts b/app/src/services/realTimeVisulization/zoneData/getSelect2dZoneData.ts
new file mode 100644
index 0000000..71d9c2f
--- /dev/null
+++ b/app/src/services/realTimeVisulization/zoneData/getSelect2dZoneData.ts
@@ -0,0 +1,27 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+console.log("url_Backend_dwinzo: ", url_Backend_dwinzo);
+
+export const getSelect2dZoneData = async (
+ ZoneId?: string,
+ organization?: string
+) => {
+ try {
+ const response = await fetch(
+ `${url_Backend_dwinzo}/api/v2/ZoneVisualization/${ZoneId}?organization=${organization}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error("Failed to fetch zoneDatas");
+ }
+
+ return await response.json();
+ } catch (error: any) {
+ throw new Error(error.message);
+ }
+};
diff --git a/app/src/services/realTimeVisulization/zoneData/getZoneData.ts b/app/src/services/realTimeVisulization/zoneData/getZoneData.ts
new file mode 100644
index 0000000..d2df867
--- /dev/null
+++ b/app/src/services/realTimeVisulization/zoneData/getZoneData.ts
@@ -0,0 +1,23 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const getZone2dData = async (organization?: string) => {
+ try {
+ const response = await fetch(
+ `${url_Backend_dwinzo}/api/v2/pageZodeData?organization=${organization}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error("Failed to fetch zoneDatas");
+ }
+
+ return await response.json();
+ } catch (error: any) {
+ throw new Error(error.message);
+ }
+};
diff --git a/app/src/services/realTimeVisulization/zoneData/panel.ts b/app/src/services/realTimeVisulization/zoneData/panel.ts
index b70889a..7f89eed 100644
--- a/app/src/services/realTimeVisulization/zoneData/panel.ts
+++ b/app/src/services/realTimeVisulization/zoneData/panel.ts
@@ -1,22 +1,19 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_BACKEND_URL}`;
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
type Side = "top" | "bottom" | "left" | "right";
export const panelData = async (
organization: string,
- zoneID: string,
+ zoneId: string,
panelOrder: Side[]
) => {
- console.log("panelOrder: ", panelOrder);
- console.log("zoneID: ", zoneID);
- console.log("organization: ", organization);
try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/panel/save`, {
+ const response = await fetch(`${url_Backend_dwinzo}/api/v2/panel/save`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
- body: JSON.stringify({ organization, zoneID, panelOrder }),
+ body: JSON.stringify({ organization, zoneId, panelOrder }),
});
if (!response.ok) {
@@ -33,16 +30,3 @@ export const panelData = async (
}
}
};
-// {objects.map((obj, index) => (
-//
-//
-//
-//
{obj.header}
-//
-//
{obj.value}
-//
{obj.per}
-//
-//
-//
-//
-// ))}
diff --git a/app/src/store/store.ts b/app/src/store/store.ts
index 8b8e544..8bbcba1 100644
--- a/app/src/store/store.ts
+++ b/app/src/store/store.ts
@@ -2,7 +2,6 @@ import * as THREE from "three";
import * as Types from "../types/world/worldTypes";
import { create } from "zustand";
import { io } from "socket.io-client";
-import { ComponentType, SVGProps } from "react";
export const useSocketStore = create((set: any, get: any) => ({
socket: null,
@@ -31,8 +30,8 @@ export const useSocketStore = create((set: any, get: any) => ({
}));
export const useLoadingProgress = create<{ loadingProgress: number; setLoadingProgress: (x: number) => void }>((set) => ({
- loadingProgress: 1,
- setLoadingProgress: (x: number) => set({ loadingProgress: x }),
+ loadingProgress: 1,
+ setLoadingProgress: (x: number) => set({ loadingProgress: x }),
}));
export const useOrganization = create((set: any) => ({
@@ -311,30 +310,14 @@ export const useSelectedPath = create((set: any) => ({
setSelectedPath: (x: any) => set({ selectedPath: x }),
}));
-interface Path {
- modeluuid: string;
- modelName: string;
- points: {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
- triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | [];
- connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
- }[];
- pathPosition: [number, number, number];
- pathRotation: [number, number, number];
- speed: number;
-}
-
interface SimulationPathsStore {
- simulationPaths: Path[];
- setSimulationPaths: (paths: Path[]) => void;
+ simulationPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[];
+ setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void;
}
export const useSimulationPaths = create((set) => ({
- simulationPaths: [],
- setSimulationPaths: (paths: Path[]) => set({ simulationPaths: paths }),
+ simulationPaths: [],
+ setSimulationPaths: (paths) => set({ simulationPaths: paths }),
}));
export const useIsConnecting = create((set: any) => ({
@@ -365,4 +348,7 @@ export const useEditPosition = create((set) => ({
setEdit: (value) => set({ Edit: value }), // Properly updating the state
}));
-
+export const useAsset3dWidget = create((set: any) => ({
+ widgetSelect: "",
+ setWidgetSelect: (x: any) => set({ widgetSelect: x }),
+}));
diff --git a/app/src/store/useChartStore.ts b/app/src/store/useChartStore.ts
index 88d0c9c..4d61952 100644
--- a/app/src/store/useChartStore.ts
+++ b/app/src/store/useChartStore.ts
@@ -6,15 +6,15 @@ interface Measurement {
}
interface MeasurementStore {
- measurements: Measurement[];
+ measurements: Record; // Change array to Record
interval: number;
duration: string;
- setMeasurements: (newMeasurements: Measurement[]) => void;
+ setMeasurements: (newMeasurements: Record) => void;
updateDuration: (newDuration: string) => void;
}
const useChartStore = create((set) => ({
- measurements: [],
+ measurements: {}, // Initialize as an empty object
interval: 1000,
duration: "1h",
@@ -26,3 +26,4 @@ const useChartStore = create((set) => ({
}));
export default useChartStore;
+
diff --git a/app/src/store/useZoneStore.ts b/app/src/store/useZoneStore.ts
index 007a1c6..77dd0d1 100644
--- a/app/src/store/useZoneStore.ts
+++ b/app/src/store/useZoneStore.ts
@@ -14,6 +14,7 @@ interface SelectedZoneState {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
+
lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
diff --git a/app/src/styles/components/marketPlace/marketPlace.scss b/app/src/styles/components/marketPlace/marketPlace.scss
index 8df0896..71f5897 100644
--- a/app/src/styles/components/marketPlace/marketPlace.scss
+++ b/app/src/styles/components/marketPlace/marketPlace.scss
@@ -126,6 +126,8 @@
display: flex;
max-height: 180px;
justify-content: center;
+ border-radius: #{$border-radius-medium};
+ overflow: hidden;
img{
height: inherit;
width: 100%;
@@ -211,7 +213,7 @@
background-color: var(--background-color);
display: flex;
gap: 12px;
- z-index: 100;
+ overflow: hidden;
border-radius: 20px;
}
diff --git a/app/src/styles/components/visualization/floating/common.scss b/app/src/styles/components/visualization/floating/common.scss
index 2994187..00c88a5 100644
--- a/app/src/styles/components/visualization/floating/common.scss
+++ b/app/src/styles/components/visualization/floating/common.scss
@@ -109,7 +109,7 @@
.productionCapacity-wrapper {
- background: var(--background-color);
+ background-color: var(--background-color);
display: flex;
flex-direction: column;
gap: 6px;
@@ -170,6 +170,9 @@
}
}
}
+ .bar-chart{
+ padding:14px 0;
+ }
}
diff --git a/app/src/types/world/worldTypes.d.ts b/app/src/types/world/worldTypes.d.ts
index c1e7128..2fcbd4f 100644
--- a/app/src/types/world/worldTypes.d.ts
+++ b/app/src/types/world/worldTypes.d.ts
@@ -284,4 +284,36 @@ interface ConnectionStore {
setConnections: (connections: PathConnection[]) => void;
addConnection: (newConnection: PathConnection) => void;
removeConnection: (fromUUID: string, toUUID: string) => void;
+}
+
+interface ConveyorEventsSchema {
+ modeluuid: string;
+ modelName: string;
+ type: 'Conveyor';
+ points: {
+ uuid: string;
+ position: [number, number, number];
+ rotation: [number, number, number];
+ actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
+ triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | [];
+ connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
+ }[];
+ assetPosition: [number, number, number];
+ assetRotation: [number, number, number];
+ speed: number;
+}
+
+interface VehicleEventsSchema {
+ modeluuid: string;
+ modelName: string;
+ type: 'Vehicle';
+ point: {
+ uuid: string;
+ position: [number, number, number];
+ actions: { uuid: string; name: string; type: string; start: string, hitCount: number, end: string, buffer: number; isUsed: boolean }[] | [];
+ triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | [];
+ connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
+ };
+ assetPosition: [number, number, number];
+ speed: number;
}
\ No newline at end of file