Hidden panel zone based template Sc shot
This commit is contained in:
commit
ceecff851a
app/src
components
layout
3D-cards/cards
sidebarLeft
sidebarRight
ui
modules
builder
csg
geomentries/assets
groups
scene
simulation/path
visualization
store
styles
types/world
|
@ -35,19 +35,32 @@ interface ProductionCapacityProps {
|
||||||
// onPointerDown:any
|
// onPointerDown:any
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductionCapacity: React.FC<ProductionCapacityProps> = ({ id, type, position, rotation, onContextMenu }) => {
|
const ProductionCapacity: React.FC<ProductionCapacityProps> = ({
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
position,
|
||||||
|
rotation,
|
||||||
|
onContextMenu,
|
||||||
|
}) => {
|
||||||
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
||||||
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
|
const {
|
||||||
|
measurements: chartMeasurements,
|
||||||
|
duration: chartDuration,
|
||||||
|
name: widgetName,
|
||||||
|
} = useChartStore();
|
||||||
const [measurements, setmeasurements] = useState<any>({});
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
const [duration, setDuration] = useState("1h")
|
const [duration, setDuration] = useState("1h");
|
||||||
const [name, setName] = useState("Widget")
|
const [name, setName] = useState("Widget");
|
||||||
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
const [chartData, setChartData] = useState<{
|
||||||
|
labels: string[];
|
||||||
|
datasets: any[];
|
||||||
|
}>({
|
||||||
labels: [],
|
labels: [],
|
||||||
datasets: [],
|
datasets: [],
|
||||||
});
|
});
|
||||||
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
const organization = email?.split("@")[1]?.split(".")[0]
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
// Chart data for a week
|
// Chart data for a week
|
||||||
const defaultChartData = {
|
const defaultChartData = {
|
||||||
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week
|
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week
|
||||||
|
@ -101,7 +114,8 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({ id, type, posit
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
const socket = io(`http://${iotApiUrl}`);
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
@ -111,7 +125,6 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({ id, type, posit
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const startStream = () => {
|
const startStream = () => {
|
||||||
socket.emit("lineInput", inputData);
|
socket.emit("lineInput", inputData);
|
||||||
};
|
};
|
||||||
|
@ -148,22 +161,20 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({ id, type, posit
|
||||||
}, [measurements, duration, iotApiUrl]);
|
}, [measurements, duration, iotApiUrl]);
|
||||||
|
|
||||||
const fetchSavedInputes = async () => {
|
const fetchSavedInputes = async () => {
|
||||||
|
|
||||||
if (id !== "") {
|
if (id !== "") {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`);
|
const response = await axios.get(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`
|
||||||
|
);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setmeasurements(response.data.Data.measurements)
|
setmeasurements(response.data.Data.measurements);
|
||||||
setDuration(response.data.Data.duration)
|
setDuration(response.data.Data.duration);
|
||||||
setName(response.data.widgetName)
|
setName(response.data.widgetName);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) { }
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
|
@ -173,13 +184,9 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({ id, type, posit
|
||||||
if (selectedChartId?.id === id) {
|
if (selectedChartId?.id === id) {
|
||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
}
|
}
|
||||||
}
|
}, [chartMeasurements, chartDuration, widgetName]);
|
||||||
, [chartMeasurements, chartDuration, widgetName])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => { }, [rotation]);
|
||||||
|
|
||||||
|
|
||||||
}, [rotation])
|
|
||||||
const rotationDegrees = {
|
const rotationDegrees = {
|
||||||
x: (rotation[0] * 180) / Math.PI,
|
x: (rotation[0] * 180) / Math.PI,
|
||||||
y: (rotation[1] * 180) / Math.PI,
|
y: (rotation[1] * 180) / Math.PI,
|
||||||
|
@ -187,30 +194,44 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({ id, type, posit
|
||||||
};
|
};
|
||||||
|
|
||||||
const transformStyle = {
|
const transformStyle = {
|
||||||
transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg)`,
|
transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg) translate(-50%, -50%)`,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={position}
|
|
||||||
|
<Html
|
||||||
|
position={position}
|
||||||
scale={[0.5, 0.5, 0.5]}
|
scale={[0.5, 0.5, 0.5]}
|
||||||
transform
|
transform
|
||||||
sprite
|
sprite
|
||||||
zIndexRange={[1,0]}
|
zIndexRange={[1, 0]}
|
||||||
// center
|
|
||||||
// distanceFactor={10} // Adjusted for visual balance
|
|
||||||
style={{
|
style={{
|
||||||
transform: transformStyle.transform,
|
transform: transformStyle.transform,
|
||||||
transformStyle: 'preserve-3d',
|
transformStyle: "preserve-3d",
|
||||||
transition: 'transform 0.1s ease-out'
|
transition: "transform 0.1s ease-out",
|
||||||
}}>
|
}}
|
||||||
<div className="productionCapacity-wrapper card"
|
onDragOver={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
onDrop={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
// e.stopPropagation();
|
||||||
|
}}
|
||||||
|
wrapperClass="pointer-none"
|
||||||
|
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`productionCapacity-wrapper card ${selectedChartId?.id === id ? "activeChart" : ""}`}
|
||||||
onClick={() => setSelectedChartId({ id: id, type: type })}
|
onClick={() => setSelectedChartId({ id: id, type: type })}
|
||||||
onContextMenu={onContextMenu}
|
onContextMenu={onContextMenu}
|
||||||
|
|
||||||
style={{
|
style={{
|
||||||
width: '300px', // Original width
|
width: "300px", // Original width
|
||||||
height: '300px', // Original height
|
height: "300px", // Original height
|
||||||
transform: transformStyle.transform,
|
transform: transformStyle.transform,
|
||||||
transformStyle: 'preserve-3d'
|
transformStyle: "preserve-3d",
|
||||||
|
position: "absolute",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="headeproductionCapacityr-wrapper">
|
<div className="headeproductionCapacityr-wrapper">
|
||||||
|
@ -233,10 +254,18 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({ id, type, posit
|
||||||
</div>{" "}
|
</div>{" "}
|
||||||
<div className="bar-chart charts">
|
<div className="bar-chart charts">
|
||||||
{/* Bar Chart */}
|
{/* Bar Chart */}
|
||||||
<Bar data={Object.keys(measurements).length > 0 ? chartData : defaultChartData} options={chartOptions} />
|
<Bar
|
||||||
|
data={
|
||||||
|
Object.keys(measurements).length > 0
|
||||||
|
? chartData
|
||||||
|
: defaultChartData
|
||||||
|
}
|
||||||
|
options={chartOptions}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Html>
|
</Html>
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,20 +46,32 @@ interface ReturnOfInvestmentProps {
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
onContextMenu?: (event: React.MouseEvent) => void;
|
onContextMenu?: (event: React.MouseEvent) => void;
|
||||||
}
|
}
|
||||||
const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, position, rotation, onContextMenu }) => {
|
const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
position,
|
||||||
|
rotation,
|
||||||
|
onContextMenu,
|
||||||
|
}) => {
|
||||||
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
||||||
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
|
const {
|
||||||
|
measurements: chartMeasurements,
|
||||||
|
duration: chartDuration,
|
||||||
|
name: widgetName,
|
||||||
|
} = useChartStore();
|
||||||
const [measurements, setmeasurements] = useState<any>({});
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
const [duration, setDuration] = useState("1h")
|
const [duration, setDuration] = useState("1h");
|
||||||
const [name, setName] = useState("Widget")
|
const [name, setName] = useState("Widget");
|
||||||
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
const [chartData, setChartData] = useState<{
|
||||||
|
labels: string[];
|
||||||
|
datasets: any[];
|
||||||
|
}>({
|
||||||
labels: [],
|
labels: [],
|
||||||
datasets: [],
|
datasets: [],
|
||||||
});
|
});
|
||||||
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
const organization = email?.split("@")[1]?.split(".")[0]
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
// Improved sample data for the smooth curve graph (single day)
|
// Improved sample data for the smooth curve graph (single day)
|
||||||
const graphData: ChartData<"line"> = {
|
const graphData: ChartData<"line"> = {
|
||||||
labels: [
|
labels: [
|
||||||
|
@ -129,7 +141,8 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
const socket = io(`http://${iotApiUrl}`);
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
@ -139,7 +152,6 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const startStream = () => {
|
const startStream = () => {
|
||||||
socket.emit("lineInput", inputData);
|
socket.emit("lineInput", inputData);
|
||||||
};
|
};
|
||||||
|
@ -157,8 +169,10 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
|
||||||
return {
|
return {
|
||||||
label: datasetKey,
|
label: datasetKey,
|
||||||
data: responseData[datasetKey]?.values ?? [],
|
data: responseData[datasetKey]?.values ?? [],
|
||||||
borderColor: index === 0 ? "rgba(75, 192, 192, 1)" : "rgba(255, 99, 132, 1)", // Light blue color
|
borderColor:
|
||||||
backgroundColor: index === 0 ? "rgba(75, 192, 192, 0.2)" : "rgba(255, 99, 132, 0.2)",
|
index === 0 ? "rgba(75, 192, 192, 1)" : "rgba(255, 99, 132, 1)", // Light blue color
|
||||||
|
backgroundColor:
|
||||||
|
index === 0 ? "rgba(75, 192, 192, 0.2)" : "rgba(255, 99, 132, 0.2)",
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.4, // Smooth curve effect
|
tension: 0.4, // Smooth curve effect
|
||||||
pointRadius: 0, // Hide dots
|
pointRadius: 0, // Hide dots
|
||||||
|
@ -177,14 +191,15 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
|
||||||
}, [measurements, duration, iotApiUrl]);
|
}, [measurements, duration, iotApiUrl]);
|
||||||
|
|
||||||
const fetchSavedInputes = async () => {
|
const fetchSavedInputes = async () => {
|
||||||
|
|
||||||
if (id !== "") {
|
if (id !== "") {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`);
|
const response = await axios.get(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`
|
||||||
|
);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setmeasurements(response.data.Data.measurements)
|
setmeasurements(response.data.Data.measurements);
|
||||||
setDuration(response.data.Data.duration)
|
setDuration(response.data.Data.duration);
|
||||||
setName(response.data.widgetName)
|
setName(response.data.widgetName);
|
||||||
} else {
|
} else {
|
||||||
console.log("Unexpected response:", response);
|
console.log("Unexpected response:", response);
|
||||||
}
|
}
|
||||||
|
@ -192,7 +207,7 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
|
||||||
console.error("There was an error!", error);
|
console.error("There was an error!", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
|
@ -202,8 +217,7 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
|
||||||
if (selectedChartId?.id === id) {
|
if (selectedChartId?.id === id) {
|
||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
}
|
}
|
||||||
}
|
}, [chartMeasurements, chartDuration, widgetName]);
|
||||||
, [chartMeasurements, chartDuration, widgetName])
|
|
||||||
const rotationDegrees = {
|
const rotationDegrees = {
|
||||||
x: (rotation[0] * 180) / Math.PI,
|
x: (rotation[0] * 180) / Math.PI,
|
||||||
y: (rotation[1] * 180) / Math.PI,
|
y: (rotation[1] * 180) / Math.PI,
|
||||||
|
@ -215,26 +229,32 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({ id, type, posit
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[position[0], position[1], position[2]]}
|
<Html
|
||||||
|
position={[position[0], position[1], position[2]]}
|
||||||
scale={[0.5, 0.5, 0.5]}
|
scale={[0.5, 0.5, 0.5]}
|
||||||
transform
|
transform
|
||||||
zIndexRange={[1, 0]}
|
zIndexRange={[1, 0]}
|
||||||
sprite
|
sprite
|
||||||
style={{
|
style={{
|
||||||
transform: transformStyle.transform,
|
transform: transformStyle.transform,
|
||||||
transformStyle: 'preserve-3d',
|
transformStyle: "preserve-3d",
|
||||||
transition: 'transform 0.1s ease-out'
|
transition: "transform 0.1s ease-out",
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="returnOfInvestment card"
|
<div
|
||||||
|
className={`returnOfInvestment card ${
|
||||||
|
selectedChartId?.id === id ? "activeChart" : ""
|
||||||
|
}`}
|
||||||
onClick={() => setSelectedChartId({ id: id, type: type })}
|
onClick={() => setSelectedChartId({ id: id, type: type })}
|
||||||
onContextMenu={onContextMenu}
|
onContextMenu={onContextMenu}
|
||||||
>
|
>
|
||||||
<div className="header">Return of Investment</div>
|
<div className="header">Return of Investment</div>
|
||||||
<div className="lineGraph charts">
|
<div className="lineGraph charts">
|
||||||
{/* Smooth curve graph with two datasets */}
|
{/* Smooth curve graph with two datasets */}
|
||||||
<SmoothLineGraphComponent data={Object.keys(measurements).length > 0 ? chartData : graphData} options={graphOptions} />
|
<SmoothLineGraphComponent
|
||||||
|
data={Object.keys(measurements).length > 0 ? chartData : graphData}
|
||||||
|
options={graphOptions}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="returns-wrapper">
|
<div className="returns-wrapper">
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
|
|
|
@ -13,16 +13,26 @@ interface StateWorkingProps {
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
onContextMenu?: (event: React.MouseEvent) => void;
|
onContextMenu?: (event: React.MouseEvent) => void;
|
||||||
}
|
}
|
||||||
const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotation, onContextMenu }) => {
|
const StateWorking: React.FC<StateWorkingProps> = ({
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
position,
|
||||||
|
rotation,
|
||||||
|
onContextMenu,
|
||||||
|
}) => {
|
||||||
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
||||||
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
|
const {
|
||||||
|
measurements: chartMeasurements,
|
||||||
|
duration: chartDuration,
|
||||||
|
name: widgetName,
|
||||||
|
} = useChartStore();
|
||||||
const [measurements, setmeasurements] = useState<any>({});
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
const [duration, setDuration] = useState("1h")
|
const [duration, setDuration] = useState("1h");
|
||||||
const [name, setName] = useState("Widget")
|
const [name, setName] = useState("Widget");
|
||||||
const [datas, setDatas] = useState<any>({});
|
const [datas, setDatas] = useState<any>({});
|
||||||
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
const organization = email?.split("@")[1]?.split(".")[0]
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
// const datas = [
|
// const datas = [
|
||||||
// { key: "Oil Tank:", value: "24/341" },
|
// { key: "Oil Tank:", value: "24/341" },
|
||||||
// { key: "Oil Refin:", value: 36.023 },
|
// { key: "Oil Refin:", value: 36.023 },
|
||||||
|
@ -33,7 +43,8 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
// ];
|
// ];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0)
|
||||||
|
return;
|
||||||
const socket = io(`http://${iotApiUrl}`);
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
const inputData = {
|
const inputData = {
|
||||||
measurements,
|
measurements,
|
||||||
|
@ -46,7 +57,6 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
socket.on("connect", startStream);
|
socket.on("connect", startStream);
|
||||||
socket.on("lastOutput", (response) => {
|
socket.on("lastOutput", (response) => {
|
||||||
const responseData = response;
|
const responseData = response;
|
||||||
|
|
||||||
|
|
||||||
setDatas(responseData);
|
setDatas(responseData);
|
||||||
});
|
});
|
||||||
|
@ -59,14 +69,15 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
}, [measurements, duration, iotApiUrl]);
|
}, [measurements, duration, iotApiUrl]);
|
||||||
|
|
||||||
const fetchSavedInputes = async () => {
|
const fetchSavedInputes = async () => {
|
||||||
|
|
||||||
if (id !== "") {
|
if (id !== "") {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`);
|
const response = await axios.get(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`
|
||||||
|
);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setmeasurements(response.data.Data.measurements)
|
setmeasurements(response.data.Data.measurements);
|
||||||
setDuration(response.data.Data.duration)
|
setDuration(response.data.Data.duration);
|
||||||
setName(response.data.widgetName)
|
setName(response.data.widgetName);
|
||||||
} else {
|
} else {
|
||||||
console.log("Unexpected response:", response);
|
console.log("Unexpected response:", response);
|
||||||
}
|
}
|
||||||
|
@ -74,10 +85,7 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
console.error("There was an error!", error);
|
console.error("There was an error!", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
|
@ -87,8 +95,7 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
if (selectedChartId?.id === id) {
|
if (selectedChartId?.id === id) {
|
||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
}
|
}
|
||||||
}
|
}, [chartMeasurements, chartDuration, widgetName]);
|
||||||
, [chartMeasurements, chartDuration, widgetName])
|
|
||||||
|
|
||||||
const rotationDegrees = {
|
const rotationDegrees = {
|
||||||
x: (rotation[0] * 180) / Math.PI,
|
x: (rotation[0] * 180) / Math.PI,
|
||||||
|
@ -100,19 +107,22 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg)`,
|
transform: `rotateX(${rotationDegrees.x}deg) rotateY(${rotationDegrees.y}deg) rotateZ(${rotationDegrees.z}deg)`,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Html position={[position[0], position[1], position[2]]}
|
<Html
|
||||||
|
position={[position[0], position[1], position[2]]}
|
||||||
scale={[0.5, 0.5, 0.5]}
|
scale={[0.5, 0.5, 0.5]}
|
||||||
transform
|
transform
|
||||||
zIndexRange={[1, 0]}
|
zIndexRange={[1, 0]}
|
||||||
sprite
|
sprite
|
||||||
style={{
|
style={{
|
||||||
transform: transformStyle.transform,
|
transform: transformStyle.transform,
|
||||||
transformStyle: 'preserve-3d',
|
transformStyle: "preserve-3d",
|
||||||
transition: 'transform 0.1s ease-out'
|
transition: "transform 0.1s ease-out",
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="stateWorking-wrapper card"
|
<div
|
||||||
|
className={`stateWorking-wrapper card ${
|
||||||
|
selectedChartId?.id === id ? "activeChart" : ""
|
||||||
|
}`}
|
||||||
onClick={() => setSelectedChartId({ id: id, type: type })}
|
onClick={() => setSelectedChartId({ id: id, type: type })}
|
||||||
onContextMenu={onContextMenu}
|
onContextMenu={onContextMenu}
|
||||||
>
|
>
|
||||||
|
@ -120,12 +130,10 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<span>State</span>
|
<span>State</span>
|
||||||
<span>
|
<span>
|
||||||
{datas?.input1 ? datas.input1 : 'input1'} <span>.</span>
|
{datas?.input1 ? datas.input1 : "input1"} <span>.</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="img">
|
<div className="img">{/* <img src={image} alt="" /> */}</div>
|
||||||
{/* <img src={image} alt="" /> */}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/* Data */}
|
{/* Data */}
|
||||||
<div className="data-wrapper">
|
<div className="data-wrapper">
|
||||||
|
@ -136,28 +144,52 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
</div>
|
</div>
|
||||||
))} */}
|
))} */}
|
||||||
<div className="data-table">
|
<div className="data-table">
|
||||||
<div className="data">{measurements?.input2?.fields ? measurements.input2.fields : 'input2'}</div>
|
<div className="data">
|
||||||
<div className="key">{datas?.input2 ? datas.input2 : 'data'}</div>
|
{measurements?.input2?.fields
|
||||||
|
? measurements.input2.fields
|
||||||
|
: "input2"}
|
||||||
|
</div>
|
||||||
|
<div className="key">{datas?.input2 ? datas.input2 : "data"}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="data-table">
|
<div className="data-table">
|
||||||
<div className="data">{measurements?.input3?.fields ? measurements.input3.fields : 'input3'}</div>
|
<div className="data">
|
||||||
<div className="key">{datas?.input3 ? datas.input3 : 'data'}</div>
|
{measurements?.input3?.fields
|
||||||
|
? measurements.input3.fields
|
||||||
|
: "input3"}
|
||||||
|
</div>
|
||||||
|
<div className="key">{datas?.input3 ? datas.input3 : "data"}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="data-table">
|
<div className="data-table">
|
||||||
<div className="data">{measurements?.input4?.fields ? measurements.input4.fields : 'input4'}</div>
|
<div className="data">
|
||||||
<div className="key">{datas?.input4 ? datas.input4 : 'data'}</div>
|
{measurements?.input4?.fields
|
||||||
|
? measurements.input4.fields
|
||||||
|
: "input4"}
|
||||||
|
</div>
|
||||||
|
<div className="key">{datas?.input4 ? datas.input4 : "data"}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="data-table">
|
<div className="data-table">
|
||||||
<div className="data">{measurements?.input5?.fields ? measurements.input5.fields : 'input5'}</div>
|
<div className="data">
|
||||||
<div className="key">{datas?.input5 ? datas.input5 : 'data'}</div>
|
{measurements?.input5?.fields
|
||||||
|
? measurements.input5.fields
|
||||||
|
: "input5"}
|
||||||
|
</div>
|
||||||
|
<div className="key">{datas?.input5 ? datas.input5 : "data"}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="data-table">
|
<div className="data-table">
|
||||||
<div className="data">{measurements?.input6?.fields ? measurements.input6.fields : 'input6'}</div>
|
<div className="data">
|
||||||
<div className="key">{datas?.input6 ? datas.input6 : 'data'}</div>
|
{measurements?.input6?.fields
|
||||||
|
? measurements.input6.fields
|
||||||
|
: "input6"}
|
||||||
|
</div>
|
||||||
|
<div className="key">{datas?.input6 ? datas.input6 : "data"}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="data-table">
|
<div className="data-table">
|
||||||
<div className="data">{measurements?.input7?.fields ? measurements.input7.fields : 'input7'}</div>
|
<div className="data">
|
||||||
<div className="key">{datas?.input7 ? datas.input7 : 'data'}</div>
|
{measurements?.input7?.fields
|
||||||
|
? measurements.input7.fields
|
||||||
|
: "input7"}
|
||||||
|
</div>
|
||||||
|
<div className="key">{datas?.input7 ? datas.input7 : "data"}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -166,5 +198,3 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||||
};
|
};
|
||||||
|
|
||||||
export default StateWorking;
|
export default StateWorking;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,20 +49,32 @@ interface ThroughputProps {
|
||||||
onContextMenu?: (event: React.MouseEvent) => void;
|
onContextMenu?: (event: React.MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, onContextMenu }) => {
|
const Throughput: React.FC<ThroughputProps> = ({
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
position,
|
||||||
|
rotation,
|
||||||
|
onContextMenu,
|
||||||
|
}) => {
|
||||||
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
const { selectedChartId, setSelectedChartId } = useWidgetStore();
|
||||||
const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore();
|
const {
|
||||||
|
measurements: chartMeasurements,
|
||||||
|
duration: chartDuration,
|
||||||
|
name: widgetName,
|
||||||
|
} = useChartStore();
|
||||||
const [measurements, setmeasurements] = useState<any>({});
|
const [measurements, setmeasurements] = useState<any>({});
|
||||||
const [duration, setDuration] = useState("1h")
|
const [duration, setDuration] = useState("1h");
|
||||||
const [name, setName] = useState("Widget")
|
const [name, setName] = useState("Widget");
|
||||||
const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({
|
const [chartData, setChartData] = useState<{
|
||||||
|
labels: string[];
|
||||||
|
datasets: any[];
|
||||||
|
}>({
|
||||||
labels: [],
|
labels: [],
|
||||||
datasets: [],
|
datasets: [],
|
||||||
});
|
});
|
||||||
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
const organization = email?.split("@")[1]?.split(".")[0]
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
|
|
||||||
// Sample data for the line graph
|
// Sample data for the line graph
|
||||||
const graphData: ChartData<"line"> = {
|
const graphData: ChartData<"line"> = {
|
||||||
|
@ -112,7 +124,8 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return;
|
if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
const socket = io(`http://${iotApiUrl}`);
|
const socket = io(`http://${iotApiUrl}`);
|
||||||
|
|
||||||
|
@ -122,7 +135,6 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
|
||||||
interval: 1000,
|
interval: 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const startStream = () => {
|
const startStream = () => {
|
||||||
socket.emit("lineInput", inputData);
|
socket.emit("lineInput", inputData);
|
||||||
};
|
};
|
||||||
|
@ -157,14 +169,15 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
|
||||||
}, [measurements, duration, iotApiUrl]);
|
}, [measurements, duration, iotApiUrl]);
|
||||||
|
|
||||||
const fetchSavedInputes = async () => {
|
const fetchSavedInputes = async () => {
|
||||||
|
|
||||||
if (id !== "") {
|
if (id !== "") {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`);
|
const response = await axios.get(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`
|
||||||
|
);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setmeasurements(response.data.Data.measurements)
|
setmeasurements(response.data.Data.measurements);
|
||||||
setDuration(response.data.Data.duration)
|
setDuration(response.data.Data.duration);
|
||||||
setName(response.data.widgetName)
|
setName(response.data.widgetName);
|
||||||
} else {
|
} else {
|
||||||
console.log("Unexpected response:", response);
|
console.log("Unexpected response:", response);
|
||||||
}
|
}
|
||||||
|
@ -172,7 +185,7 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
|
||||||
console.error("There was an error!", error);
|
console.error("There was an error!", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
|
@ -182,8 +195,7 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
|
||||||
if (selectedChartId?.id === id) {
|
if (selectedChartId?.id === id) {
|
||||||
fetchSavedInputes();
|
fetchSavedInputes();
|
||||||
}
|
}
|
||||||
}
|
}, [chartMeasurements, chartDuration, widgetName]);
|
||||||
, [chartMeasurements, chartDuration, widgetName])
|
|
||||||
const rotationDegrees = {
|
const rotationDegrees = {
|
||||||
x: (rotation[0] * 180) / Math.PI,
|
x: (rotation[0] * 180) / Math.PI,
|
||||||
y: (rotation[1] * 180) / Math.PI,
|
y: (rotation[1] * 180) / Math.PI,
|
||||||
|
@ -195,19 +207,22 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Html position={[position[0], position[1], position[2]]}
|
<Html
|
||||||
|
position={[position[0], position[1], position[2]]}
|
||||||
scale={[0.5, 0.5, 0.5]}
|
scale={[0.5, 0.5, 0.5]}
|
||||||
transform
|
transform
|
||||||
zIndexRange={[1, 0]}
|
zIndexRange={[1, 0]}
|
||||||
sprite
|
sprite
|
||||||
style={{
|
style={{
|
||||||
transform: transformStyle.transform,
|
transform: transformStyle.transform,
|
||||||
transformStyle: 'preserve-3d',
|
transformStyle: "preserve-3d",
|
||||||
transition: 'transform 0.1s ease-out'
|
transition: "transform 0.1s ease-out",
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="throughput-wrapper"
|
<div
|
||||||
|
className={`throughput-wrapper card ${
|
||||||
|
selectedChartId?.id === id ? "activeChart" : ""
|
||||||
|
}`}
|
||||||
onClick={() => setSelectedChartId({ id: id, type: type })}
|
onClick={() => setSelectedChartId({ id: id, type: type })}
|
||||||
onContextMenu={onContextMenu}
|
onContextMenu={onContextMenu}
|
||||||
>
|
>
|
||||||
|
@ -234,7 +249,10 @@ const Throughput: React.FC<ThroughputProps> = ({ id, type, position, rotation, o
|
||||||
</div>
|
</div>
|
||||||
<div className="line-graph">
|
<div className="line-graph">
|
||||||
{/* Line graph using react-chartjs-2 */}
|
{/* Line graph using react-chartjs-2 */}
|
||||||
<LineGraphComponent data={Object.keys(measurements).length > 0 ? chartData : graphData} options={graphOptions} />
|
<LineGraphComponent
|
||||||
|
data={Object.keys(measurements).length > 0 ? chartData : graphData}
|
||||||
|
options={graphOptions}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="footer">
|
<div className="footer">
|
||||||
You made an extra <span className="value">$1256.13</span> this month
|
You made an extra <span className="value">$1256.13</span> this month
|
||||||
|
|
|
@ -147,7 +147,7 @@ const Assets: React.FC = () => {
|
||||||
<div className="assets-container">
|
<div className="assets-container">
|
||||||
{categoryAssets &&
|
{categoryAssets &&
|
||||||
categoryAssets?.map((asset: any, index: number) => (
|
categoryAssets?.map((asset: any, index: number) => (
|
||||||
<div key={index} className="assets">
|
<div key={index} className="assets" id={asset.filename}>
|
||||||
<img
|
<img
|
||||||
src={asset?.thumbnail}
|
src={asset?.thumbnail}
|
||||||
alt={asset.filename}
|
alt={asset.filename}
|
||||||
|
@ -171,6 +171,7 @@ const Assets: React.FC = () => {
|
||||||
<div className="assets-wrapper">
|
<div className="assets-wrapper">
|
||||||
<div
|
<div
|
||||||
className="back-button"
|
className="back-button"
|
||||||
|
id="asset-backButtom"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedCategory(null);
|
setSelectedCategory(null);
|
||||||
setCategoryAssets([]);
|
setCategoryAssets([]);
|
||||||
|
@ -182,7 +183,7 @@ const Assets: React.FC = () => {
|
||||||
<div className="assets-container">
|
<div className="assets-container">
|
||||||
{categoryAssets &&
|
{categoryAssets &&
|
||||||
categoryAssets?.map((asset: any, index: number) => (
|
categoryAssets?.map((asset: any, index: number) => (
|
||||||
<div key={index} className="assets">
|
<div key={index} className="assets" id={asset.filename}>
|
||||||
<img
|
<img
|
||||||
src={asset?.thumbnail}
|
src={asset?.thumbnail}
|
||||||
alt={asset.filename}
|
alt={asset.filename}
|
||||||
|
@ -222,6 +223,7 @@ const Assets: React.FC = () => {
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className="category"
|
className="category"
|
||||||
|
id={category}
|
||||||
onClick={() => fetchCategoryAssets(category)}
|
onClick={() => fetchCategoryAssets(category)}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -4,6 +4,7 @@ import useTemplateStore from "../../../../store/useTemplateStore";
|
||||||
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
|
||||||
import { getTemplateData } from "../../../../services/realTimeVisulization/zoneData/getTemplate";
|
import { getTemplateData } from "../../../../services/realTimeVisulization/zoneData/getTemplate";
|
||||||
import { useSocketStore } from "../../../../store/store";
|
import { useSocketStore } from "../../../../store/store";
|
||||||
|
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||||
|
|
||||||
const Templates = () => {
|
const Templates = () => {
|
||||||
const { templates, removeTemplate, setTemplates } = useTemplateStore();
|
const { templates, removeTemplate, setTemplates } = useTemplateStore();
|
||||||
|
@ -34,7 +35,10 @@ const Templates = () => {
|
||||||
templateID: id,
|
templateID: id,
|
||||||
};
|
};
|
||||||
if (visualizationSocket) {
|
if (visualizationSocket) {
|
||||||
visualizationSocket.emit("v2:viz-template:deleteTemplate", deleteTemplate);
|
visualizationSocket.emit(
|
||||||
|
"v2:viz-template:deleteTemplate",
|
||||||
|
deleteTemplate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
removeTemplate(id);
|
removeTemplate(id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -65,11 +69,15 @@ const Templates = () => {
|
||||||
widgets: template.widgets,
|
widgets: template.widgets,
|
||||||
});
|
});
|
||||||
|
|
||||||
useDroppedObjectsStore.getState().setZone(selectedZone.zoneName, selectedZone.zoneId);
|
useDroppedObjectsStore
|
||||||
|
.getState()
|
||||||
|
.setZone(selectedZone.zoneName, selectedZone.zoneId);
|
||||||
|
|
||||||
if (Array.isArray(template.floatingWidget)) {
|
if (Array.isArray(template.floatingWidget)) {
|
||||||
template.floatingWidget.forEach((val: any) => {
|
template.floatingWidget.forEach((val: any) => {
|
||||||
useDroppedObjectsStore.getState().addObject(selectedZone.zoneName, val);
|
useDroppedObjectsStore
|
||||||
|
.getState()
|
||||||
|
.addObject(selectedZone.zoneName, val);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -79,7 +87,7 @@ const Templates = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="template-list">
|
<div className="template-list">
|
||||||
{templates.map((template) => (
|
{templates.map((template, index) => (
|
||||||
<div key={template.id} className="template-item">
|
<div key={template.id} className="template-item">
|
||||||
{template?.snapshot && (
|
{template?.snapshot && (
|
||||||
<div className="template-image-container">
|
<div className="template-image-container">
|
||||||
|
@ -96,7 +104,8 @@ const Templates = () => {
|
||||||
onClick={() => handleLoadTemplate(template)}
|
onClick={() => handleLoadTemplate(template)}
|
||||||
className="template-name"
|
className="template-name"
|
||||||
>
|
>
|
||||||
{template.name}
|
{/* {`Template ${index + 1}`} */}
|
||||||
|
<RenameInput value={`Template ${index + 1}`} />
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDeleteTemplate(template.id)}
|
onClick={() => handleDeleteTemplate(template.id)}
|
||||||
|
|
|
@ -21,11 +21,13 @@ const Widgets3D = () => {
|
||||||
className="widget-item"
|
className="widget-item"
|
||||||
draggable
|
draggable
|
||||||
onDragStart={(e) => {
|
onDragStart={(e) => {
|
||||||
|
let name = widget.name
|
||||||
let crt = e.target
|
let crt = e.target
|
||||||
if (crt instanceof HTMLElement) {
|
if (crt instanceof HTMLElement) {
|
||||||
const widget = crt.cloneNode(true) as HTMLElement;
|
const widget = crt.cloneNode(true) as HTMLElement;
|
||||||
e.dataTransfer.setDragImage(widget, 0, 0)
|
e.dataTransfer.setDragImage(widget, 0, 0)
|
||||||
e.dataTransfer.effectAllowed = "move"
|
e.dataTransfer.effectAllowed = "move"
|
||||||
|
e.dataTransfer.setData("text/plain", "ui-" + name)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onPointerDown={() => {
|
onPointerDown={() => {
|
||||||
|
@ -40,7 +42,7 @@ const Widgets3D = () => {
|
||||||
className="widget-image"
|
className="widget-image"
|
||||||
src={widget.img}
|
src={widget.img}
|
||||||
alt={widget.name}
|
alt={widget.name}
|
||||||
// draggable={false}
|
draggable={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import Analysis from "./analysis/Analysis";
|
||||||
import Simulations from "./simulation/Simulations";
|
import Simulations from "./simulation/Simulations";
|
||||||
import {
|
import {
|
||||||
useSelectedActionSphere,
|
useSelectedActionSphere,
|
||||||
useselectedFloorItem,
|
useSelectedFloorItem,
|
||||||
} from "../../../store/store";
|
} from "../../../store/store";
|
||||||
import GlobalProperties from "./properties/GlobalProperties";
|
import GlobalProperties from "./properties/GlobalProperties";
|
||||||
import AsstePropertiies from "./properties/AssetProperties";
|
import AsstePropertiies from "./properties/AssetProperties";
|
||||||
|
@ -30,7 +30,7 @@ const SideBarRight: React.FC = () => {
|
||||||
const { toggleUI } = useToggleStore();
|
const { toggleUI } = useToggleStore();
|
||||||
const { selectedActionSphere } = useSelectedActionSphere();
|
const { selectedActionSphere } = useSelectedActionSphere();
|
||||||
const { subModule, setSubModule } = useSubModuleStore();
|
const { subModule, setSubModule } = useSubModuleStore();
|
||||||
const { selectedFloorItem } = useselectedFloorItem();
|
const { selectedFloorItem } = useSelectedFloorItem();
|
||||||
// Reset activeList whenever activeModule changes
|
// Reset activeList whenever activeModule changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeModule !== "simulation") setSubModule("properties");
|
if (activeModule !== "simulation") setSubModule("properties");
|
||||||
|
@ -101,7 +101,7 @@ const SideBarRight: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
{toggleUI &&
|
{toggleUI &&
|
||||||
subModule === "zoneProperties" &&
|
subModule === "zoneProperties" &&
|
||||||
activeModule === "builder" && (
|
(activeModule === "builder" || activeModule === "simulation") && (
|
||||||
<div className="sidebar-right-container">
|
<div className="sidebar-right-container">
|
||||||
<div className="sidebar-right-content-container">
|
<div className="sidebar-right-content-container">
|
||||||
<ZoneProperties />
|
<ZoneProperties />
|
||||||
|
@ -135,7 +135,7 @@ const SideBarRight: React.FC = () => {
|
||||||
selectedActionSphere.path.type === "StaticMachine" && (
|
selectedActionSphere.path.type === "StaticMachine" && (
|
||||||
<div className="sidebar-right-container">
|
<div className="sidebar-right-container">
|
||||||
<div className="sidebar-right-content-container">
|
<div className="sidebar-right-content-container">
|
||||||
<StaticMachineMechanics />
|
<StaticMachineMechanics />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -144,7 +144,7 @@ const SideBarRight: React.FC = () => {
|
||||||
selectedActionSphere.path.type === "ArmBot" && (
|
selectedActionSphere.path.type === "ArmBot" && (
|
||||||
<div className="sidebar-right-container">
|
<div className="sidebar-right-container">
|
||||||
<div className="sidebar-right-content-container">
|
<div className="sidebar-right-content-container">
|
||||||
<ArmBotMechanics />
|
<ArmBotMechanics />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,65 +1,121 @@
|
||||||
import React, { useRef, useMemo } from "react";
|
import React, { useRef, useMemo, useCallback, useState } from "react";
|
||||||
import { InfoIcon } from "../../../icons/ExportCommonIcons";
|
import { InfoIcon } from "../../../icons/ExportCommonIcons";
|
||||||
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
||||||
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
import {
|
||||||
|
useSelectedActionSphere,
|
||||||
|
useSimulationStates,
|
||||||
|
useSocketStore
|
||||||
|
} from "../../../../store/store";
|
||||||
import * as Types from '../../../../types/world/worldTypes';
|
import * as Types from '../../../../types/world/worldTypes';
|
||||||
import PositionInput from "../customInput/PositionInputs";
|
import LabeledButton from "../../../ui/inputs/LabledButton";
|
||||||
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
|
||||||
|
|
||||||
const ArmBotMechanics: React.FC = () => {
|
const ArmBotMechanics: React.FC = () => {
|
||||||
const { selectedActionSphere } = useSelectedActionSphere();
|
const { selectedActionSphere } = useSelectedActionSphere();
|
||||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
|
const [selectedTrigger, setSelectedTrigger] = useState<string | null>(null);
|
||||||
|
|
||||||
const propertiesContainerRef = useRef<HTMLDivElement>(null);
|
const propertiesContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const { selectedPoint, connectedPointUuids } = useMemo(() => {
|
// Get connected models for dropdowns
|
||||||
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
|
const connectedModels = useMemo(() => {
|
||||||
|
if (!selectedActionSphere?.points?.uuid) return [];
|
||||||
|
|
||||||
const vehiclePaths = simulationStates.filter(
|
}, [selectedActionSphere, simulationStates]);
|
||||||
|
|
||||||
|
// Get triggers only from connected models
|
||||||
|
const connectedTriggers = useMemo(() => {
|
||||||
|
}, [connectedModels, simulationStates]);
|
||||||
|
|
||||||
|
const { selectedPoint } = useMemo(() => {
|
||||||
|
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null };
|
||||||
|
|
||||||
|
const armBotPaths = simulationStates.filter(
|
||||||
(path): path is Types.ArmBotEventsSchema => path.type === "ArmBot"
|
(path): path is Types.ArmBotEventsSchema => path.type === "ArmBot"
|
||||||
);
|
);
|
||||||
|
|
||||||
const points = vehiclePaths.find(
|
const points = armBotPaths.find(
|
||||||
(path) => path.points.uuid === selectedActionSphere.points.uuid
|
(path) => path.points.uuid === selectedActionSphere.points.uuid
|
||||||
)?.points;
|
)?.points;
|
||||||
|
|
||||||
if (!points) return { selectedPoint: null, connectedPointUuids: [] };
|
|
||||||
|
|
||||||
const connectedUuids: string[] = [];
|
|
||||||
if (points.connections?.targets) {
|
|
||||||
points.connections.targets.forEach(target => {
|
|
||||||
connectedUuids.push(target.pointUUID);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedPoint: points,
|
selectedPoint: points || null
|
||||||
connectedPointUuids: connectedUuids
|
|
||||||
};
|
};
|
||||||
}, [selectedActionSphere, simulationStates]);
|
}, [selectedActionSphere, simulationStates]);
|
||||||
|
|
||||||
const updateBackend = async (updatedPath: Types.ArmBotEventsSchema | undefined) => {
|
const updateBackend = async (updatedPath: Types.ArmBotEventsSchema | undefined) => {
|
||||||
if (!updatedPath) return;
|
// if (!updatedPath) return;
|
||||||
const email = localStorage.getItem("email");
|
// const email = localStorage.getItem("email");
|
||||||
const organization = email ? email.split("@")[1].split(".")[0] : "";
|
// const organization = email ? email.split("@")[1].split(".")[0] : "";
|
||||||
|
|
||||||
// await setEventApi(
|
// const data = {
|
||||||
// organization,
|
// organization: organization,
|
||||||
// updatedPath.modeluuid,
|
// modeluuid: updatedPath.modeluuid,
|
||||||
// { type: "ArmBot", points: updatedPath.points }
|
// eventData: { type: "ArmBot", points: updatedPath.points }
|
||||||
// );
|
// }
|
||||||
|
|
||||||
const data = {
|
|
||||||
organization: organization,
|
|
||||||
modeluuid: updatedPath.modeluuid,
|
|
||||||
eventData: { type: "ArmBot", points: updatedPath.points }
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.emit('v2:model-asset:updateEventData', data);
|
|
||||||
|
|
||||||
|
// socket.emit('v2:model-asset:updateEventData', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const handleActionUpdate = useCallback((updatedAction: Partial<Types.ArmBotEventsSchema['points']['actions']>) => {
|
||||||
|
// if (!selectedActionSphere?.points?.uuid) return;
|
||||||
|
|
||||||
|
// const updatedPaths = simulationStates.map((path) => {
|
||||||
|
// return path;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const updatedPath = updatedPaths.find(
|
||||||
|
// (path): path is Types.ArmBotEventsSchema =>
|
||||||
|
// path.type === "ArmBot" &&
|
||||||
|
// path.points.uuid === selectedActionSphere.points.uuid
|
||||||
|
// );
|
||||||
|
// updateBackend(updatedPath);
|
||||||
|
|
||||||
|
// setSimulationStates(updatedPaths);
|
||||||
|
// }, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
|
||||||
|
|
||||||
|
// const handleSpeedChange = useCallback((speed: number) => {
|
||||||
|
// handleActionUpdate({ speed });
|
||||||
|
// }, [handleActionUpdate]);
|
||||||
|
|
||||||
|
// const handleProcessChange = useCallback((processes: Types.ArmBotEventsSchema['points']['actions']['processes']) => {
|
||||||
|
// handleActionUpdate({ processes });
|
||||||
|
// }, [handleActionUpdate]);
|
||||||
|
|
||||||
|
// const handleTriggerSelect = useCallback((displayName: string) => {
|
||||||
|
// const selected = connectedTriggers.find(t => t.displayName === displayName);
|
||||||
|
// setSelectedTrigger(selected?.uuid || null);
|
||||||
|
// }, [connectedTriggers]);
|
||||||
|
|
||||||
|
// const handleStartPointSelect = useCallback((pointUUID: string) => {
|
||||||
|
// if (!selectedTrigger || !selectedPoint) return;
|
||||||
|
|
||||||
|
// const updatedProcesses = selectedPoint.actions.processes?.map(process =>
|
||||||
|
// process.triggerId === selectedTrigger
|
||||||
|
// ? { ...process, startPoint: pointUUID }
|
||||||
|
// : process
|
||||||
|
// ) || [];
|
||||||
|
|
||||||
|
// handleProcessChange(updatedProcesses);
|
||||||
|
// }, [selectedTrigger, selectedPoint, handleProcessChange]);
|
||||||
|
|
||||||
|
// const handleEndPointSelect = useCallback((pointUUID: string) => {
|
||||||
|
// if (!selectedTrigger || !selectedPoint) return;
|
||||||
|
|
||||||
|
// const updatedProcesses = selectedPoint.actions.processes?.map(process =>
|
||||||
|
// process.triggerId === selectedTrigger
|
||||||
|
// ? { ...process, endPoint: pointUUID }
|
||||||
|
// : process
|
||||||
|
// ) || [];
|
||||||
|
|
||||||
|
// handleProcessChange(updatedProcesses);
|
||||||
|
// }, [selectedTrigger, selectedPoint, handleProcessChange]);
|
||||||
|
|
||||||
|
// const getCurrentProcess = useCallback(() => {
|
||||||
|
// if (!selectedTrigger || !selectedPoint) return null;
|
||||||
|
// return selectedPoint.actions.processes?.find(p => p.triggerId === selectedTrigger);
|
||||||
|
// }, [selectedTrigger, selectedPoint]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="machine-mechanics-container" key={selectedPoint?.uuid}>
|
<div className="machine-mechanics-container" key={selectedPoint?.uuid}>
|
||||||
|
@ -71,16 +127,50 @@ const ArmBotMechanics: React.FC = () => {
|
||||||
<div className="selected-properties-container" ref={propertiesContainerRef}>
|
<div className="selected-properties-container" ref={propertiesContainerRef}>
|
||||||
<div className="properties-header">ArmBot Properties</div>
|
<div className="properties-header">ArmBot Properties</div>
|
||||||
|
|
||||||
{selectedPoint && (
|
{/* {selectedPoint && (
|
||||||
<>
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
key={`speed-${selectedPoint.uuid}`}
|
||||||
|
label="ArmBot Speed"
|
||||||
|
value={selectedPoint.actions.speed.toString()}
|
||||||
|
onChange={(value) => handleSpeedChange(parseInt(value))}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LabledDropdown
|
||||||
|
key={`trigger-select-${selectedPoint.uuid}`}
|
||||||
|
label="Select Trigger"
|
||||||
|
defaultOption={connectedTriggers.find(t => t.uuid === selectedTrigger)?.displayName || ''}
|
||||||
|
onSelect={handleTriggerSelect}
|
||||||
|
options={connectedTriggers.map(trigger => trigger.displayName)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{selectedTrigger && (
|
||||||
|
<>
|
||||||
|
<LabledDropdown
|
||||||
|
key={`start-point-${selectedTrigger}`}
|
||||||
|
label="Start Point"
|
||||||
|
defaultOption={getCurrentProcess()?.startPoint || ''}
|
||||||
|
onSelect={handleStartPointSelect}
|
||||||
|
options={connectedModels.map((model, index) => `${model.modelName} [${index}]`)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LabledDropdown
|
||||||
|
key={`end-point-${selectedTrigger}`}
|
||||||
|
label="End Point"
|
||||||
|
defaultOption={getCurrentProcess()?.endPoint || ''}
|
||||||
|
onSelect={handleEndPointSelect}
|
||||||
|
options={connectedModels.map((model, index) => `${model.modelName} [${index}]`)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="footer">
|
<div className="footer">
|
||||||
<InfoIcon />
|
<InfoIcon />
|
||||||
Configure armbot properties.
|
Configure ArmBot properties and trigger-based processes.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React, { useRef, useMemo } from "react";
|
import React, { useRef, useMemo, useCallback } from "react";
|
||||||
import { InfoIcon } from "../../../icons/ExportCommonIcons";
|
import { InfoIcon } from "../../../icons/ExportCommonIcons";
|
||||||
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
||||||
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
import { useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
||||||
import * as Types from '../../../../types/world/worldTypes';
|
import * as Types from '../../../../types/world/worldTypes';
|
||||||
import PositionInput from "../customInput/PositionInputs";
|
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
|
||||||
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||||
|
|
||||||
const StaticMachineMechanics: React.FC = () => {
|
const StaticMachineMechanics: React.FC = () => {
|
||||||
|
@ -16,11 +16,11 @@ const StaticMachineMechanics: React.FC = () => {
|
||||||
const { selectedPoint, connectedPointUuids } = useMemo(() => {
|
const { selectedPoint, connectedPointUuids } = useMemo(() => {
|
||||||
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
|
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
|
||||||
|
|
||||||
const vehiclePaths = simulationStates.filter(
|
const staticMachinePaths = simulationStates.filter(
|
||||||
(path): path is Types.StaticMachineEventsSchema => path.type === "StaticMachine"
|
(path): path is Types.StaticMachineEventsSchema => path.type === "StaticMachine"
|
||||||
);
|
);
|
||||||
|
|
||||||
const points = vehiclePaths.find(
|
const points = staticMachinePaths.find(
|
||||||
(path) => path.points.uuid === selectedActionSphere.points.uuid
|
(path) => path.points.uuid === selectedActionSphere.points.uuid
|
||||||
)?.points;
|
)?.points;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ const StaticMachineMechanics: React.FC = () => {
|
||||||
// await setEventApi(
|
// await setEventApi(
|
||||||
// organization,
|
// organization,
|
||||||
// updatedPath.modeluuid,
|
// updatedPath.modeluuid,
|
||||||
// { type: "StaticMachine", points: updatedPath.points }
|
// { type: "Vehicle", points: updatedPath.points }
|
||||||
// );
|
// );
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
@ -57,9 +57,77 @@ const StaticMachineMechanics: React.FC = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.emit('v2:model-asset:updateEventData', data);
|
socket.emit('v2:model-asset:updateEventData', data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleActionUpdate = useCallback((updatedAction: Partial<Types.StaticMachineEventsSchema['points']['actions']>) => {
|
||||||
|
if (!selectedActionSphere?.points?.uuid) return;
|
||||||
|
|
||||||
|
const updatedPaths = simulationStates.map((path) => {
|
||||||
|
if (path.type === "StaticMachine" && path.points.uuid === selectedActionSphere.points.uuid) {
|
||||||
|
return {
|
||||||
|
...path,
|
||||||
|
points: {
|
||||||
|
...path.points,
|
||||||
|
actions: {
|
||||||
|
...path.points.actions,
|
||||||
|
...updatedAction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedPath = updatedPaths.find(
|
||||||
|
(path): path is Types.StaticMachineEventsSchema =>
|
||||||
|
path.type === "StaticMachine" &&
|
||||||
|
path.points.uuid === selectedActionSphere.points.uuid
|
||||||
|
);
|
||||||
|
updateBackend(updatedPath);
|
||||||
|
|
||||||
|
setSimulationStates(updatedPaths);
|
||||||
|
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
|
||||||
|
|
||||||
|
const handleBufferChange = useCallback((buffer: number) => {
|
||||||
|
handleActionUpdate({ buffer });
|
||||||
|
}, [handleActionUpdate]);
|
||||||
|
|
||||||
|
const handleMaterialChange = useCallback((material: string) => {
|
||||||
|
handleActionUpdate({ material });
|
||||||
|
}, [handleActionUpdate]);
|
||||||
|
|
||||||
|
const handleTriggerChange = useCallback((updatedTrigger: Partial<Types.StaticMachineEventsSchema['points']['triggers']>) => {
|
||||||
|
if (!selectedActionSphere?.points?.uuid) return;
|
||||||
|
|
||||||
|
const updatedPaths = simulationStates.map((path) => {
|
||||||
|
if (path.type === "StaticMachine" && path.points.uuid === selectedActionSphere.points.uuid) {
|
||||||
|
return {
|
||||||
|
...path,
|
||||||
|
points: {
|
||||||
|
...path.points,
|
||||||
|
triggers: {
|
||||||
|
...path.points.triggers,
|
||||||
|
...updatedTrigger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedPath = updatedPaths.find(
|
||||||
|
(path): path is Types.StaticMachineEventsSchema =>
|
||||||
|
path.type === "StaticMachine" &&
|
||||||
|
path.points.uuid === selectedActionSphere.points.uuid
|
||||||
|
);
|
||||||
|
updateBackend(updatedPath);
|
||||||
|
|
||||||
|
setSimulationStates(updatedPaths);
|
||||||
|
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
|
||||||
|
|
||||||
|
const handleTriggerTypeChange = useCallback((type: string) => {
|
||||||
|
handleTriggerChange({ type });
|
||||||
|
}, [handleTriggerChange]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="machine-mechanics-container" key={selectedPoint?.uuid}>
|
<div className="machine-mechanics-container" key={selectedPoint?.uuid}>
|
||||||
|
@ -67,20 +135,50 @@ const StaticMachineMechanics: React.FC = () => {
|
||||||
{selectedActionSphere?.path?.modelName || "Machine point not found"}
|
{selectedActionSphere?.path?.modelName || "Machine point not found"}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div className="machine-mechanics-content-container">
|
<div className="machine-mechanics-content-container">
|
||||||
<div className="selected-properties-container" ref={propertiesContainerRef}>
|
<div className="selected-properties-container" ref={propertiesContainerRef}>
|
||||||
<div className="properties-header">Machine Properties</div>
|
<div className="properties-header">Machine Properties</div>
|
||||||
|
|
||||||
{selectedPoint && (
|
{selectedPoint && (
|
||||||
<>
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
key={`buffer-${selectedPoint.uuid}`}
|
||||||
|
label="Buffer Time"
|
||||||
|
value={selectedPoint.actions.buffer.toString()}
|
||||||
|
onChange={(value) => handleBufferChange(parseInt(value))}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LabledDropdown
|
||||||
|
key={`material-${selectedPoint.uuid}`}
|
||||||
|
label="Material"
|
||||||
|
defaultOption={selectedPoint.actions.material}
|
||||||
|
onSelect={(value) => handleMaterialChange(value)}
|
||||||
|
options={["Inherit", "Crate", "Box"]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LabledDropdown
|
||||||
|
key={`trigger-type-${selectedPoint.uuid}`}
|
||||||
|
label="Trigger Type"
|
||||||
|
defaultOption={selectedPoint.triggers.type}
|
||||||
|
onSelect={(value) => handleTriggerTypeChange(value)}
|
||||||
|
options={["OnComplete", "OnStart"]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <LabeledButton
|
||||||
|
label="Reset"
|
||||||
|
value="Reset Settings"
|
||||||
|
onClick={() => {
|
||||||
|
// Implement reset functionality if needed
|
||||||
|
}}
|
||||||
|
/> */}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="footer">
|
<div className="footer">
|
||||||
<InfoIcon />
|
<InfoIcon />
|
||||||
Configure machine properties.
|
Configure machine interaction properties and triggers.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionS
|
||||||
import * as Types from '../../../../types/world/worldTypes';
|
import * as Types from '../../../../types/world/worldTypes';
|
||||||
import PositionInput from "../customInput/PositionInputs";
|
import PositionInput from "../customInput/PositionInputs";
|
||||||
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||||
|
import LabeledButton from "../../../ui/inputs/LabledButton";
|
||||||
|
|
||||||
const VehicleMechanics: React.FC = () => {
|
const VehicleMechanics: React.FC = () => {
|
||||||
const { selectedActionSphere } = useSelectedActionSphere();
|
const { selectedActionSphere } = useSelectedActionSphere();
|
||||||
|
@ -126,6 +127,33 @@ const VehicleMechanics: React.FC = () => {
|
||||||
setSimulationStates(updatedPaths);
|
setSimulationStates(updatedPaths);
|
||||||
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
|
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
|
||||||
|
|
||||||
|
|
||||||
|
const ResetVehicleState = React.useCallback(() => {
|
||||||
|
if (!selectedActionSphere?.points?.uuid) return;
|
||||||
|
|
||||||
|
const updatedPaths = simulationStates.map((state) => {
|
||||||
|
if (state.type === "Vehicle" && state.points.uuid === selectedActionSphere.points.uuid) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
points: {
|
||||||
|
...state.points,
|
||||||
|
actions: { ...state.points.actions, start: {}, end: {} }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedPath = updatedPaths.find(
|
||||||
|
(path): path is Types.VehicleEventsSchema =>
|
||||||
|
path.type === "Vehicle" &&
|
||||||
|
path.points.uuid === selectedActionSphere.points.uuid
|
||||||
|
);
|
||||||
|
updateBackend(updatedPath);
|
||||||
|
|
||||||
|
setSimulationStates(updatedPaths);
|
||||||
|
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
|
||||||
|
|
||||||
const handleStartEyeDropClick = () => {
|
const handleStartEyeDropClick = () => {
|
||||||
setEditingPoint('start');
|
setEditingPoint('start');
|
||||||
setEyeDropMode(true);
|
setEyeDropMode(true);
|
||||||
|
@ -193,6 +221,14 @@ const VehicleMechanics: React.FC = () => {
|
||||||
handleEyeDropClick={handleEndEyeDropClick}
|
handleEyeDropClick={handleEndEyeDropClick}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<LabeledButton
|
||||||
|
label="Reset"
|
||||||
|
value="Clear Points"
|
||||||
|
onClick={() => {
|
||||||
|
ResetVehicleState();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<InputWithDropDown
|
<InputWithDropDown
|
||||||
key={`hitcount-${selectedPoint.uuid}`}
|
key={`hitcount-${selectedPoint.uuid}`}
|
||||||
label="Hit Count"
|
label="Hit Count"
|
||||||
|
|
|
@ -4,7 +4,7 @@ import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
||||||
import { RemoveIcon } from "../../../icons/ExportCommonIcons";
|
import { RemoveIcon } from "../../../icons/ExportCommonIcons";
|
||||||
import PositionInput from "../customInput/PositionInputs";
|
import PositionInput from "../customInput/PositionInputs";
|
||||||
import RotationInput from "../customInput/RotationInput";
|
import RotationInput from "../customInput/RotationInput";
|
||||||
import { useselectedFloorItem } from "../../../../store/store";
|
import { useSelectedFloorItem } from "../../../../store/store";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
|
||||||
interface UserData {
|
interface UserData {
|
||||||
|
@ -16,7 +16,7 @@ interface UserData {
|
||||||
const AssetProperties: React.FC = () => {
|
const AssetProperties: React.FC = () => {
|
||||||
const [userData, setUserData] = useState<UserData[]>([]); // State to track user data
|
const [userData, setUserData] = useState<UserData[]>([]); // State to track user data
|
||||||
const [nextId, setNextId] = useState(1); // Unique ID for new entries
|
const [nextId, setNextId] = useState(1); // Unique ID for new entries
|
||||||
const { selectedFloorItem } = useselectedFloorItem();
|
const { selectedFloorItem } = useSelectedFloorItem();
|
||||||
// Function to handle adding new user data
|
// Function to handle adding new user data
|
||||||
const handleAddUserData = () => {
|
const handleAddUserData = () => {
|
||||||
const newUserData: UserData = {
|
const newUserData: UserData = {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { useSelectedZoneStore } from "../../store/useZoneStore";
|
||||||
import {
|
import {
|
||||||
useActiveTool,
|
useActiveTool,
|
||||||
useAddAction,
|
useAddAction,
|
||||||
useDeleteModels,
|
useDeleteTool,
|
||||||
useDeletePointOrLine,
|
useDeletePointOrLine,
|
||||||
useMovePoint,
|
useMovePoint,
|
||||||
useRefTextUpdate,
|
useRefTextUpdate,
|
||||||
|
@ -61,7 +61,7 @@ const Tools: React.FC = () => {
|
||||||
|
|
||||||
// wall options
|
// wall options
|
||||||
const { toggleView, setToggleView } = useToggleView();
|
const { toggleView, setToggleView } = useToggleView();
|
||||||
const { setDeleteModels } = useDeleteModels();
|
const { setDeleteTool } = useDeleteTool();
|
||||||
const { setAddAction } = useAddAction();
|
const { setAddAction } = useAddAction();
|
||||||
const { setSelectedWallItem } = useSelectedWallItem();
|
const { setSelectedWallItem } = useSelectedWallItem();
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ const Tools: React.FC = () => {
|
||||||
const toggleSwitch = () => {
|
const toggleSwitch = () => {
|
||||||
if (toggleThreeD) {
|
if (toggleThreeD) {
|
||||||
setSelectedWallItem(null);
|
setSelectedWallItem(null);
|
||||||
setDeleteModels(false);
|
setDeleteTool(false);
|
||||||
setAddAction(null);
|
setAddAction(null);
|
||||||
setToggleView(true);
|
setToggleView(true);
|
||||||
// localStorage.setItem("navBarUi", JSON.stringify(!toggleThreeD));
|
// localStorage.setItem("navBarUi", JSON.stringify(!toggleThreeD));
|
||||||
|
@ -136,7 +136,7 @@ const Tools: React.FC = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setToolMode(null);
|
setToolMode(null);
|
||||||
setDeleteModels(false);
|
setDeleteTool(false);
|
||||||
setAddAction(null);
|
setAddAction(null);
|
||||||
setTransformMode(null);
|
setTransformMode(null);
|
||||||
setMovePoint(false);
|
setMovePoint(false);
|
||||||
|
@ -202,7 +202,7 @@ const Tools: React.FC = () => {
|
||||||
if (toggleView) {
|
if (toggleView) {
|
||||||
setDeletePointOrLine(true);
|
setDeletePointOrLine(true);
|
||||||
} else {
|
} else {
|
||||||
setDeleteModels(true);
|
setDeleteTool(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
CleanPannel,
|
CleanPannel,
|
||||||
EyeIcon,
|
EyeIcon,
|
||||||
LockIcon,
|
LockIcon,
|
||||||
} from "../../icons/RealTimeVisulationIcons";
|
} from "../../icons/RealTimeVisulationIcons";
|
||||||
import { panelData } from "../../../services/realTimeVisulization/zoneData/panel";
|
|
||||||
import { AddIcon } from "../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../icons/ExportCommonIcons";
|
||||||
import { deletePanelApi } from "../../../services/realTimeVisulization/zoneData/deletePanel";
|
|
||||||
import { useSocketStore } from "../../../store/store";
|
import { useSocketStore } from "../../../store/store";
|
||||||
|
|
||||||
// Define the type for `Side`
|
// Define the type for `Side`
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
|
||||||
|
// Define the type for HiddenPanels, where keys are zone IDs and values are arrays of hidden sides
|
||||||
|
interface HiddenPanels {
|
||||||
|
[zoneId: string]: Side[];
|
||||||
|
}
|
||||||
|
|
||||||
// Define the type for the props passed to the Buttons component
|
// Define the type for the props passed to the Buttons component
|
||||||
interface ButtonsProps {
|
interface ButtonsProps {
|
||||||
selectedZone: {
|
selectedZone: {
|
||||||
|
@ -35,7 +38,6 @@ interface ButtonsProps {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
|
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
|
@ -49,8 +51,8 @@ interface ButtonsProps {
|
||||||
}[];
|
}[];
|
||||||
}>
|
}>
|
||||||
>;
|
>;
|
||||||
hiddenPanels: Side[]; // Add this prop for hidden panels
|
hiddenPanels: HiddenPanels; // Updated prop type
|
||||||
setHiddenPanels: React.Dispatch<React.SetStateAction<Side[]>>; // Add this prop for updating hidden panels
|
setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type
|
||||||
}
|
}
|
||||||
|
|
||||||
const AddButtons: React.FC<ButtonsProps> = ({
|
const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
|
@ -61,11 +63,33 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const { visualizationSocket } = useSocketStore();
|
const { visualizationSocket } = useSocketStore();
|
||||||
|
|
||||||
// Local state to track hidden panels
|
// Function to toggle visibility of a panel
|
||||||
|
const toggleVisibility = (side: Side) => {
|
||||||
|
const isHidden = hiddenPanels[selectedZone.zoneId]?.includes(side) ?? false;
|
||||||
|
|
||||||
|
if (isHidden) {
|
||||||
|
// If the panel is already hidden, remove it from the hiddenPanels array for this zone
|
||||||
|
setHiddenPanels((prevHiddenPanels) => ({
|
||||||
|
...prevHiddenPanels,
|
||||||
|
[selectedZone.zoneId]: prevHiddenPanels[selectedZone.zoneId].filter(
|
||||||
|
(panel) => panel !== side
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
// If the panel is visible, add it to the hiddenPanels array for this zone
|
||||||
|
setHiddenPanels((prevHiddenPanels) => ({
|
||||||
|
...prevHiddenPanels,
|
||||||
|
[selectedZone.zoneId]: [
|
||||||
|
...(prevHiddenPanels[selectedZone.zoneId] || []),
|
||||||
|
side,
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Function to toggle lock/unlock a panel
|
// Function to toggle lock/unlock a panel
|
||||||
const toggleLockPanel = (side: Side) => {
|
const toggleLockPanel = (side: Side) => {
|
||||||
console.log('side: ', side);
|
console.log("side: ", side);
|
||||||
//add api
|
//add api
|
||||||
const newLockedPanels = selectedZone.lockedPanels.includes(side)
|
const newLockedPanels = selectedZone.lockedPanels.includes(side)
|
||||||
? selectedZone.lockedPanels.filter((panel) => panel !== side)
|
? selectedZone.lockedPanels.filter((panel) => panel !== side)
|
||||||
|
@ -80,22 +104,10 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
setSelectedZone(updatedZone);
|
setSelectedZone(updatedZone);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to toggle visibility of a panel
|
|
||||||
const toggleVisibility = (side: Side) => {
|
|
||||||
const isHidden = hiddenPanels.includes(side);
|
|
||||||
if (isHidden) {
|
|
||||||
// If the panel is already hidden, remove it from the hiddenPanels array
|
|
||||||
setHiddenPanels(hiddenPanels.filter((panel) => panel !== side));
|
|
||||||
} else {
|
|
||||||
// If the panel is visible, add it to the hiddenPanels array
|
|
||||||
setHiddenPanels([...hiddenPanels, side]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to clean all widgets from a panel
|
// Function to clean all widgets from a panel
|
||||||
const cleanPanel = (side: Side) => {
|
const cleanPanel = (side: Side) => {
|
||||||
//add api
|
//add api
|
||||||
console.log('side: ', side);
|
console.log("side: ", side);
|
||||||
const cleanedWidgets = selectedZone.widgets.filter(
|
const cleanedWidgets = selectedZone.widgets.filter(
|
||||||
(widget) => widget.panel !== side
|
(widget) => widget.panel !== side
|
||||||
);
|
);
|
||||||
|
@ -150,8 +162,6 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
} else {
|
} else {
|
||||||
setHiddenPanels(hiddenPanels.filter((panel) => panel !== side));
|
|
||||||
|
|
||||||
// Panel does not exist: Create panel
|
// Panel does not exist: Create panel
|
||||||
try {
|
try {
|
||||||
// Get email and organization safely with a default fallback
|
// Get email and organization safely with a default fallback
|
||||||
|
@ -188,7 +198,6 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
|
@ -217,16 +226,20 @@ const AddButtons: React.FC<ButtonsProps> = ({
|
||||||
{/* Hide Panel */}
|
{/* Hide Panel */}
|
||||||
<div
|
<div
|
||||||
className={`icon ${
|
className={`icon ${
|
||||||
hiddenPanels.includes(side) ? "active" : ""
|
hiddenPanels[selectedZone.zoneId]?.includes(side)
|
||||||
|
? "active"
|
||||||
|
: ""
|
||||||
}`}
|
}`}
|
||||||
title={
|
title={
|
||||||
hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel"
|
hiddenPanels[selectedZone.zoneId]?.includes(side)
|
||||||
|
? "Show Panel"
|
||||||
|
: "Hide Panel"
|
||||||
}
|
}
|
||||||
onClick={() => toggleVisibility(side)}
|
onClick={() => toggleVisibility(side)}
|
||||||
>
|
>
|
||||||
<EyeIcon
|
<EyeIcon
|
||||||
fill={
|
fill={
|
||||||
hiddenPanels.includes(side)
|
hiddenPanels[selectedZone.zoneId]?.includes(side)
|
||||||
? "var(--primary-color)"
|
? "var(--primary-color)"
|
||||||
: "var(--text-color)"
|
: "var(--text-color)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,12 +88,15 @@ export const DraggableWidget = ({
|
||||||
|
|
||||||
const chartWidget = useRef<HTMLDivElement>(null);
|
const chartWidget = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const isPanelHidden = hiddenPanels.includes(widget.panel);
|
OuterClick({
|
||||||
|
contextClassName: [
|
||||||
// OuterClick({
|
"chart-container",
|
||||||
// contextClassName: ["chart-container", "floating", "sidebar-right-wrapper"],
|
"floating",
|
||||||
// setMenuVisible: () => setSelectedChartId(null),
|
"sidebar-right-wrapper",
|
||||||
// });
|
"card",
|
||||||
|
],
|
||||||
|
setMenuVisible: () => setSelectedChartId(null),
|
||||||
|
});
|
||||||
|
|
||||||
const deleteSelectedChart = async () => {
|
const deleteSelectedChart = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -397,7 +400,4 @@ export const DraggableWidget = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// by using canvasDimensions.height canvasDimensions.width dynamically div value insted of static 6 and 4 calculate according to canvasDimensions.width canvasDimensions.height
|
||||||
|
|
||||||
|
|
||||||
// by using canvasDimensions.height canvasDimensions.width dynamically div value insted of static 6 and 4 calculate according to canvasDimensions.width canvasDimensions.height
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import { useThree } from "@react-three/fiber";
|
import { useThree } from "@react-three/fiber";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../../store/store";
|
import {
|
||||||
|
useAsset3dWidget,
|
||||||
|
useSocketStore,
|
||||||
|
useWidgetSubOption,
|
||||||
|
} from "../../../store/store";
|
||||||
import useModuleStore from "../../../store/useModuleStore";
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
import { ThreeState } from "../../../types/world/worldTypes";
|
import { ThreeState } from "../../../types/world/worldTypes";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
@ -13,11 +17,19 @@ import { generateUniqueId } from "../../../functions/generateUniqueId";
|
||||||
import { adding3dWidgets } from "../../../services/realTimeVisulization/zoneData/add3dWidget";
|
import { adding3dWidgets } from "../../../services/realTimeVisulization/zoneData/add3dWidget";
|
||||||
import { get3dWidgetZoneData } from "../../../services/realTimeVisulization/zoneData/get3dWidgetData";
|
import { get3dWidgetZoneData } from "../../../services/realTimeVisulization/zoneData/get3dWidgetData";
|
||||||
import { use3DWidget } from "../../../store/useDroppedObjectsStore";
|
import { use3DWidget } from "../../../store/useDroppedObjectsStore";
|
||||||
import { useEditWidgetOptionsStore, useLeftData, useRightClickSelected, useRightSelected, useTopData, useZoneWidgetStore } from "../../../store/useZone3DWidgetStore";
|
import {
|
||||||
import { useWidgetStore } from "../../../store/useWidgetStore";
|
useEditWidgetOptionsStore,
|
||||||
import EditWidgetOption from "../menu/EditWidgetOption";
|
useLeftData,
|
||||||
|
useRightClickSelected,
|
||||||
|
useRightSelected,
|
||||||
|
useTopData,
|
||||||
|
useZoneWidgetStore,
|
||||||
|
} from "../../../store/useZone3DWidgetStore";
|
||||||
import { delete3dWidgetApi } from "../../../services/realTimeVisulization/zoneData/delete3dWidget";
|
import { delete3dWidgetApi } from "../../../services/realTimeVisulization/zoneData/delete3dWidget";
|
||||||
import { update3dWidget, update3dWidgetRotation } from "../../../services/realTimeVisulization/zoneData/update3dWidget";
|
import {
|
||||||
|
update3dWidget,
|
||||||
|
update3dWidgetRotation,
|
||||||
|
} from "../../../services/realTimeVisulization/zoneData/update3dWidget";
|
||||||
type WidgetData = {
|
type WidgetData = {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -26,7 +38,6 @@ type WidgetData = {
|
||||||
tempPosition?: [number, number, number];
|
tempPosition?: [number, number, number];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default function Dropped3dWidgets() {
|
export default function Dropped3dWidgets() {
|
||||||
const { widgetSelect } = useAsset3dWidget();
|
const { widgetSelect } = useAsset3dWidget();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
@ -36,19 +47,18 @@ export default function Dropped3dWidgets() {
|
||||||
const { top, setTop } = useTopData();
|
const { top, setTop } = useTopData();
|
||||||
const { left, setLeft } = useLeftData();
|
const { left, setLeft } = useLeftData();
|
||||||
const { rightSelect, setRightSelect } = useRightSelected();
|
const { rightSelect, setRightSelect } = useRightSelected();
|
||||||
const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore()
|
const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore();
|
||||||
const { zoneWidgetData, setZoneWidgetData, addWidget, updateWidgetPosition, updateWidgetRotation } = useZoneWidgetStore();
|
const { zoneWidgetData, setZoneWidgetData, addWidget, updateWidgetPosition, updateWidgetRotation, tempWidget, tempWidgetPosition } = useZoneWidgetStore();
|
||||||
const { setWidgets3D } = use3DWidget();
|
const { setWidgets3D } = use3DWidget();
|
||||||
const { visualizationSocket } = useSocketStore();
|
const { visualizationSocket } = useSocketStore();
|
||||||
const { rightClickSelected, setRightClickSelected } = useRightClickSelected();
|
const { rightClickSelected, setRightClickSelected } = useRightClickSelected();
|
||||||
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Floor plane for horizontal move
|
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Floor plane for horizontal move
|
||||||
const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0)); // Vertical plane for vertical move
|
const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0)); // Vertical plane for vertical move
|
||||||
const planeIntersect = useRef(new THREE.Vector3());
|
const planeIntersect = useRef(new THREE.Vector3());
|
||||||
|
|
||||||
const rotationStartRef = useRef<[number, number, number]>([0, 0, 0]);
|
const rotationStartRef = useRef<[number, number, number]>([0, 0, 0]);
|
||||||
const mouseStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
|
const mouseStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
|
||||||
|
|
||||||
|
const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || [];
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeModule !== "visualization") return;
|
if (activeModule !== "visualization") return;
|
||||||
if (!selectedZone.zoneId) return;
|
if (!selectedZone.zoneId) return;
|
||||||
|
@ -57,7 +67,10 @@ export default function Dropped3dWidgets() {
|
||||||
const organization = email?.split("@")[1]?.split(".")[0];
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
|
|
||||||
async function get3dWidgetData() {
|
async function get3dWidgetData() {
|
||||||
const result = await get3dWidgetZoneData(selectedZone.zoneId, organization);
|
const result = await get3dWidgetZoneData(
|
||||||
|
selectedZone.zoneId,
|
||||||
|
organization
|
||||||
|
);
|
||||||
|
|
||||||
setWidgets3D(result);
|
setWidgets3D(result);
|
||||||
|
|
||||||
|
@ -68,66 +81,50 @@ export default function Dropped3dWidgets() {
|
||||||
rotation: widget.rotation || [0, 0, 0],
|
rotation: widget.rotation || [0, 0, 0],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
setZoneWidgetData(selectedZone.zoneId, formattedWidgets);
|
setZoneWidgetData(selectedZone.zoneId, formattedWidgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
get3dWidgetData();
|
get3dWidgetData();
|
||||||
}, [selectedZone.zoneId, activeModule]);
|
}, [selectedZone.zoneId, activeModule]);
|
||||||
|
|
||||||
|
const createdWidgetRef = useRef<WidgetData | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeModule !== "visualization") return;
|
if (activeModule !== "visualization") return;
|
||||||
if (widgetSubOption === "Floating" || widgetSubOption === "2D") return;
|
if (widgetSubOption === "Floating" || widgetSubOption === "2D") return;
|
||||||
if (selectedZone.zoneName === "") return;
|
if (selectedZone.zoneName === "") return;
|
||||||
|
|
||||||
const canvasElement = gl.domElement;
|
const canvasElement = document.getElementById("real-time-vis-canvas");
|
||||||
|
|
||||||
|
if (!canvasElement) return;
|
||||||
|
|
||||||
|
const hasEntered = { current: false };
|
||||||
|
|
||||||
const handleDragEnter = (event: DragEvent) => {
|
const handleDragEnter = (event: DragEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
console.log("Drag enter");
|
|
||||||
|
|
||||||
};
|
if (hasEntered.current || !widgetSelect.startsWith("ui")) return;
|
||||||
|
hasEntered.current = true;
|
||||||
|
|
||||||
const handleDragOver = (event: DragEvent) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDragLeave = (event: DragEvent) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
console.log("Drag leave");
|
|
||||||
// Remove visual feedback
|
|
||||||
canvasElement.style.cursor = "";
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDrop = async (event: DragEvent) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
canvasElement.style.cursor = ""; // Reset cursor
|
|
||||||
|
|
||||||
const email = localStorage.getItem("email") || "";
|
|
||||||
const organization = email?.split("@")[1]?.split(".")[0];
|
|
||||||
if (!widgetSelect.startsWith("ui")) return;
|
|
||||||
const group1 = scene.getObjectByName("itemsGroup");
|
const group1 = scene.getObjectByName("itemsGroup");
|
||||||
if (!group1) return;
|
if (!group1) return;
|
||||||
|
|
||||||
// Update raycaster with current mouse position
|
|
||||||
const rect = canvasElement.getBoundingClientRect();
|
const rect = canvasElement.getBoundingClientRect();
|
||||||
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||||
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||||
raycaster.setFromCamera(mouse, camera);
|
raycaster.setFromCamera(mouse, camera);
|
||||||
|
|
||||||
const intersects = raycaster.intersectObjects(scene.children, true).filter(
|
const intersects = raycaster
|
||||||
(intersect) =>
|
.intersectObjects(scene.children, true)
|
||||||
!intersect.object.name.includes("Roof") &&
|
.filter(
|
||||||
!intersect.object.name.includes("agv-collider") &&
|
(intersect) =>
|
||||||
!intersect.object.name.includes("MeasurementReference") &&
|
!intersect.object.name.includes("Roof") &&
|
||||||
!intersect.object.userData.isPathObject &&
|
!intersect.object.name.includes("agv-collider") &&
|
||||||
!(intersect.object.type === "GridHelper")
|
!intersect.object.name.includes("MeasurementReference") &&
|
||||||
);
|
!intersect.object.userData.isPathObject &&
|
||||||
|
!(intersect.object.type === "GridHelper")
|
||||||
|
);
|
||||||
|
|
||||||
if (intersects.length > 0) {
|
if (intersects.length > 0) {
|
||||||
const { x, y, z } = intersects[0].point;
|
const { x, y, z } = intersects[0].point;
|
||||||
|
@ -138,36 +135,100 @@ export default function Dropped3dWidgets() {
|
||||||
rotation: [0, 0, 0],
|
rotation: [0, 0, 0],
|
||||||
};
|
};
|
||||||
|
|
||||||
const add3dWidget = {
|
createdWidgetRef.current = newWidget;
|
||||||
organization: organization,
|
tempWidget(selectedZone.zoneId, newWidget); // temp add in UI
|
||||||
widget: newWidget,
|
|
||||||
zoneId: selectedZone.zoneId
|
|
||||||
};
|
|
||||||
|
|
||||||
if (visualizationSocket) {
|
|
||||||
visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
addWidget(selectedZone.zoneId, newWidget);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add all event listeners
|
const handleDragOver = (event: DragEvent) => {
|
||||||
// canvasElement.addEventListener("dragenter", handleDragEnter);
|
event.preventDefault();
|
||||||
// canvasElement.addEventListener("dragover", handleDragOver);
|
event.stopPropagation();
|
||||||
// canvasElement.addEventListener("dragleave", handleDragLeave);
|
event.dataTransfer!.dropEffect = "move"; // ✅ Add this line
|
||||||
|
const widget = createdWidgetRef.current;
|
||||||
|
if (!widget) return;
|
||||||
|
|
||||||
|
const rect = canvasElement.getBoundingClientRect();
|
||||||
|
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||||
|
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||||
|
raycaster.setFromCamera(mouse, 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")
|
||||||
|
);
|
||||||
|
// Update widget's position in memory
|
||||||
|
if (intersects.length > 0) {
|
||||||
|
const { x, y, z } = intersects[0].point;
|
||||||
|
tempWidgetPosition(selectedZone.zoneId, widget.id, [x, y, z]);
|
||||||
|
widget.position = [x, y, z];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDrop = (event: any) => {
|
||||||
|
console.log("onDrop called. hasEntered: ", hasEntered.current);
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
hasEntered.current = false;
|
||||||
|
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
|
|
||||||
|
const newWidget = createdWidgetRef.current;
|
||||||
|
if (!newWidget || !widgetSelect.startsWith("ui")) return;
|
||||||
|
|
||||||
|
// ✅ Manual removal of the temp widget (same ID)
|
||||||
|
const prevWidgets = useZoneWidgetStore.getState().zoneWidgetData[selectedZone.zoneId] || [];
|
||||||
|
const cleanedWidgets = prevWidgets.filter(w => w.id !== newWidget.id);
|
||||||
|
useZoneWidgetStore.setState((state) => ({
|
||||||
|
zoneWidgetData: {
|
||||||
|
...state.zoneWidgetData,
|
||||||
|
[selectedZone.zoneId]: cleanedWidgets,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
// ✅ Now re-add it as final
|
||||||
|
addWidget(selectedZone.zoneId, newWidget);
|
||||||
|
|
||||||
|
const add3dWidget = {
|
||||||
|
organization,
|
||||||
|
widget: newWidget,
|
||||||
|
zoneId: selectedZone.zoneId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (visualizationSocket) {
|
||||||
|
visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
let pointerDivs = document.getElementsByClassName("pointer-none");
|
||||||
|
Array.from(pointerDivs).forEach((el) => {
|
||||||
|
el.classList.remove("pointer-none");
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
createdWidgetRef.current = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
canvasElement.addEventListener("dragenter", handleDragEnter);
|
||||||
|
canvasElement.addEventListener("dragover", handleDragOver);
|
||||||
canvasElement.addEventListener("drop", onDrop);
|
canvasElement.addEventListener("drop", onDrop);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
// // Clean up all event listeners
|
canvasElement.removeEventListener("dragenter", handleDragEnter);
|
||||||
// canvasElement.removeEventListener("dragenter", handleDragEnter);
|
canvasElement.removeEventListener("dragover", handleDragOver);
|
||||||
// canvasElement.removeEventListener("dragover", handleDragOver);
|
|
||||||
// canvasElement.removeEventListener("dragleave", handleDragLeave);
|
|
||||||
canvasElement.removeEventListener("drop", onDrop);
|
canvasElement.removeEventListener("drop", onDrop);
|
||||||
canvasElement.style.cursor = ""; // Ensure cursor is reset
|
|
||||||
};
|
};
|
||||||
}, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption, gl.domElement, scene, raycaster, camera]);
|
}, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption, camera,]);
|
||||||
const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || [];
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!rightClickSelected) return;
|
if (!rightClickSelected) return;
|
||||||
|
@ -176,7 +237,9 @@ export default function Dropped3dWidgets() {
|
||||||
|
|
||||||
if (rightSelect === "Duplicate") {
|
if (rightSelect === "Duplicate") {
|
||||||
async function duplicateWidget() {
|
async function duplicateWidget() {
|
||||||
const widgetToDuplicate = activeZoneWidgets.find((w: WidgetData) => w.id === rightClickSelected);
|
const widgetToDuplicate = activeZoneWidgets.find(
|
||||||
|
(w: WidgetData) => w.id === rightClickSelected
|
||||||
|
);
|
||||||
if (!widgetToDuplicate) return;
|
if (!widgetToDuplicate) return;
|
||||||
const newWidget: WidgetData = {
|
const newWidget: WidgetData = {
|
||||||
id: generateUniqueId(),
|
id: generateUniqueId(),
|
||||||
|
@ -191,19 +254,19 @@ export default function Dropped3dWidgets() {
|
||||||
const adding3dWidget = {
|
const adding3dWidget = {
|
||||||
organization: organization,
|
organization: organization,
|
||||||
widget: newWidget,
|
widget: newWidget,
|
||||||
zoneId: selectedZone.zoneId
|
zoneId: selectedZone.zoneId,
|
||||||
};
|
};
|
||||||
if (visualizationSocket) {
|
if (visualizationSocket) {
|
||||||
visualizationSocket.emit("v2:viz-3D-widget:add", adding3dWidget);
|
visualizationSocket.emit("v2:viz-3D-widget:add", adding3dWidget);
|
||||||
}
|
}
|
||||||
// let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget)
|
// let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget)
|
||||||
//
|
//
|
||||||
|
|
||||||
addWidget(selectedZone.zoneId, newWidget);
|
addWidget(selectedZone.zoneId, newWidget);
|
||||||
setRightSelect(null);
|
setRightSelect(null);
|
||||||
setRightClickSelected(null);
|
setRightClickSelected(null);
|
||||||
}
|
}
|
||||||
duplicateWidget()
|
duplicateWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rightSelect === "Delete") {
|
if (rightSelect === "Delete") {
|
||||||
|
@ -215,7 +278,6 @@ export default function Dropped3dWidgets() {
|
||||||
zoneId: selectedZone.zoneId,
|
zoneId: selectedZone.zoneId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (visualizationSocket) {
|
if (visualizationSocket) {
|
||||||
visualizationSocket.emit("v2:viz-3D-widget:delete", deleteWidget);
|
visualizationSocket.emit("v2:viz-3D-widget:delete", deleteWidget);
|
||||||
}
|
}
|
||||||
|
@ -223,10 +285,11 @@ export default function Dropped3dWidgets() {
|
||||||
// const response = await delete3dWidgetApi(selectedZone.zoneId, organization, rightClickSelected);
|
// const response = await delete3dWidgetApi(selectedZone.zoneId, organization, rightClickSelected);
|
||||||
setZoneWidgetData(
|
setZoneWidgetData(
|
||||||
selectedZone.zoneId,
|
selectedZone.zoneId,
|
||||||
activeZoneWidgets.filter((w: WidgetData) => w.id !== rightClickSelected)
|
activeZoneWidgets.filter(
|
||||||
|
(w: WidgetData) => w.id !== rightClickSelected
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
setRightClickSelected(null);
|
setRightClickSelected(null);
|
||||||
setRightSelect(null);
|
setRightSelect(null);
|
||||||
|
@ -238,7 +301,6 @@ export default function Dropped3dWidgets() {
|
||||||
}, [rightSelect, rightClickSelected]);
|
}, [rightSelect, rightClickSelected]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
const organization = email?.split("@")[1]?.split(".")[0];
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
const handleMouseDown = (event: MouseEvent) => {
|
const handleMouseDown = (event: MouseEvent) => {
|
||||||
|
@ -247,13 +309,18 @@ export default function Dropped3dWidgets() {
|
||||||
if (rightSelect === "RotateX" || rightSelect === "RotateY") {
|
if (rightSelect === "RotateX" || rightSelect === "RotateY") {
|
||||||
mouseStartRef.current = { x: event.clientX, y: event.clientY };
|
mouseStartRef.current = { x: event.clientX, y: event.clientY };
|
||||||
|
|
||||||
const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) =>
|
const selectedZone = Object.keys(zoneWidgetData).find(
|
||||||
zoneWidgetData[zoneId].some((widget: WidgetData) => widget.id === rightClickSelected)
|
(zoneId: string) =>
|
||||||
|
zoneWidgetData[zoneId].some(
|
||||||
|
(widget: WidgetData) => widget.id === rightClickSelected
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!selectedZone) return;
|
if (!selectedZone) return;
|
||||||
|
|
||||||
const selectedWidget = zoneWidgetData[selectedZone].find((widget: WidgetData) => widget.id === rightClickSelected);
|
const selectedWidget = zoneWidgetData[selectedZone].find(
|
||||||
|
(widget: WidgetData) => widget.id === rightClickSelected
|
||||||
|
);
|
||||||
if (selectedWidget) {
|
if (selectedWidget) {
|
||||||
rotationStartRef.current = selectedWidget.rotation || [0, 0, 0];
|
rotationStartRef.current = selectedWidget.rotation || [0, 0, 0];
|
||||||
}
|
}
|
||||||
|
@ -263,11 +330,15 @@ export default function Dropped3dWidgets() {
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
const handleMouseMove = (event: MouseEvent) => {
|
||||||
if (!rightClickSelected || !rightSelect) return;
|
if (!rightClickSelected || !rightSelect) return;
|
||||||
const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) =>
|
const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) =>
|
||||||
zoneWidgetData[zoneId].some((widget: WidgetData) => widget.id === rightClickSelected)
|
zoneWidgetData[zoneId].some(
|
||||||
|
(widget: WidgetData) => widget.id === rightClickSelected
|
||||||
|
)
|
||||||
);
|
);
|
||||||
if (!selectedZone) return;
|
if (!selectedZone) return;
|
||||||
|
|
||||||
const selectedWidget = zoneWidgetData[selectedZone].find((widget: WidgetData) => widget.id === rightClickSelected);
|
const selectedWidget = zoneWidgetData[selectedZone].find(
|
||||||
|
(widget: WidgetData) => widget.id === rightClickSelected
|
||||||
|
);
|
||||||
if (!selectedWidget) return;
|
if (!selectedWidget) return;
|
||||||
|
|
||||||
const rect = gl.domElement.getBoundingClientRect();
|
const rect = gl.domElement.getBoundingClientRect();
|
||||||
|
@ -276,22 +347,29 @@ export default function Dropped3dWidgets() {
|
||||||
|
|
||||||
raycaster.setFromCamera(mouse, camera);
|
raycaster.setFromCamera(mouse, camera);
|
||||||
|
|
||||||
if (rightSelect === "Horizontal Move" && raycaster.ray.intersectPlane(plane.current, planeIntersect.current)) {
|
if (
|
||||||
|
rightSelect === "Horizontal Move" &&
|
||||||
|
raycaster.ray.intersectPlane(plane.current, planeIntersect.current)
|
||||||
|
) {
|
||||||
const newPosition: [number, number, number] = [
|
const newPosition: [number, number, number] = [
|
||||||
planeIntersect.current.x,
|
planeIntersect.current.x,
|
||||||
selectedWidget.position[1],
|
selectedWidget.position[1],
|
||||||
planeIntersect.current.z
|
planeIntersect.current.z,
|
||||||
];
|
];
|
||||||
updateWidgetPosition(selectedZone, rightClickSelected, newPosition);
|
updateWidgetPosition(selectedZone, rightClickSelected, newPosition);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rightSelect === "Vertical Move") {
|
if (rightSelect === "Vertical Move") {
|
||||||
if (raycaster.ray.intersectPlane(verticalPlane.current, planeIntersect.current)) {
|
if (
|
||||||
|
raycaster.ray.intersectPlane(
|
||||||
|
verticalPlane.current,
|
||||||
|
planeIntersect.current
|
||||||
|
)
|
||||||
|
) {
|
||||||
updateWidgetPosition(selectedZone, rightClickSelected, [
|
updateWidgetPosition(selectedZone, rightClickSelected, [
|
||||||
selectedWidget.position[0],
|
selectedWidget.position[0],
|
||||||
planeIntersect.current.y,
|
planeIntersect.current.y,
|
||||||
selectedWidget.position[2]
|
selectedWidget.position[2],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,7 +380,7 @@ export default function Dropped3dWidgets() {
|
||||||
const newRotation: [number, number, number] = [
|
const newRotation: [number, number, number] = [
|
||||||
rotationStartRef.current[0] + deltaX * rotationSpeed,
|
rotationStartRef.current[0] + deltaX * rotationSpeed,
|
||||||
rotationStartRef.current[1],
|
rotationStartRef.current[1],
|
||||||
rotationStartRef.current[2]
|
rotationStartRef.current[2],
|
||||||
];
|
];
|
||||||
updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
|
updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
|
||||||
}
|
}
|
||||||
|
@ -313,7 +391,7 @@ export default function Dropped3dWidgets() {
|
||||||
const newRotation: [number, number, number] = [
|
const newRotation: [number, number, number] = [
|
||||||
rotationStartRef.current[0],
|
rotationStartRef.current[0],
|
||||||
rotationStartRef.current[1] + deltaY * rotationSpeed,
|
rotationStartRef.current[1] + deltaY * rotationSpeed,
|
||||||
rotationStartRef.current[2]
|
rotationStartRef.current[2],
|
||||||
];
|
];
|
||||||
updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
|
updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
|
||||||
}
|
}
|
||||||
|
@ -324,31 +402,42 @@ export default function Dropped3dWidgets() {
|
||||||
const newRotation: [number, number, number] = [
|
const newRotation: [number, number, number] = [
|
||||||
currentRotation[0],
|
currentRotation[0],
|
||||||
currentRotation[1],
|
currentRotation[1],
|
||||||
currentRotation[2] + deltaX * rotationSpeed
|
currentRotation[2] + deltaX * rotationSpeed,
|
||||||
];
|
];
|
||||||
updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
|
updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
if (!rightClickSelected || !rightSelect) return;
|
if (!rightClickSelected || !rightSelect) return;
|
||||||
const selectedZone = Object.keys(zoneWidgetData).find(zoneId =>
|
const selectedZone = Object.keys(zoneWidgetData).find((zoneId) =>
|
||||||
zoneWidgetData[zoneId].some(widget => widget.id === rightClickSelected)
|
zoneWidgetData[zoneId].some(
|
||||||
|
(widget) => widget.id === rightClickSelected
|
||||||
|
)
|
||||||
);
|
);
|
||||||
if (!selectedZone) return;
|
if (!selectedZone) return;
|
||||||
|
|
||||||
const selectedWidget = zoneWidgetData[selectedZone].find(widget => widget.id === rightClickSelected);
|
const selectedWidget = zoneWidgetData[selectedZone].find(
|
||||||
|
(widget) => widget.id === rightClickSelected
|
||||||
|
);
|
||||||
if (!selectedWidget) return;
|
if (!selectedWidget) return;
|
||||||
// Format values to 2 decimal places
|
// Format values to 2 decimal places
|
||||||
const formatValues = (vals: number[]) => vals.map(val => parseFloat(val.toFixed(2)));
|
const formatValues = (vals: number[]) =>
|
||||||
if (rightSelect === "Horizontal Move" || rightSelect === "Vertical Move") {
|
vals.map((val) => parseFloat(val.toFixed(2)));
|
||||||
let lastPosition = formatValues(selectedWidget.position) as [number, number, number];
|
if (
|
||||||
|
rightSelect === "Horizontal Move" ||
|
||||||
|
rightSelect === "Vertical Move"
|
||||||
|
) {
|
||||||
|
let lastPosition = formatValues(selectedWidget.position) as [
|
||||||
|
number,
|
||||||
|
number,
|
||||||
|
number
|
||||||
|
];
|
||||||
// (async () => {
|
// (async () => {
|
||||||
// let response = await update3dWidget(selectedZone, organization, rightClickSelected, lastPosition);
|
// let response = await update3dWidget(selectedZone, organization, rightClickSelected, lastPosition);
|
||||||
//
|
//
|
||||||
// if (response) {
|
// if (response) {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
// })();
|
// })();
|
||||||
let updatingPosition = {
|
let updatingPosition = {
|
||||||
|
@ -356,21 +445,22 @@ export default function Dropped3dWidgets() {
|
||||||
zoneId: selectedZone,
|
zoneId: selectedZone,
|
||||||
id: rightClickSelected,
|
id: rightClickSelected,
|
||||||
position: lastPosition,
|
position: lastPosition,
|
||||||
}
|
};
|
||||||
if (visualizationSocket) {
|
if (visualizationSocket) {
|
||||||
visualizationSocket.emit("v2:viz-3D-widget:modifyPositionRotation", updatingPosition);
|
visualizationSocket.emit(
|
||||||
|
"v2:viz-3D-widget:modifyPositionRotation",
|
||||||
|
updatingPosition
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
} else if (rightSelect.includes("Rotate")) {
|
||||||
}
|
|
||||||
else if (rightSelect.includes("Rotate")) {
|
|
||||||
const rotation = selectedWidget.rotation || [0, 0, 0];
|
const rotation = selectedWidget.rotation || [0, 0, 0];
|
||||||
|
|
||||||
let lastRotation = formatValues(rotation) as [number, number, number];
|
let lastRotation = formatValues(rotation) as [number, number, number];
|
||||||
// (async () => {
|
// (async () => {
|
||||||
// let response = await update3dWidgetRotation(selectedZone, organization, rightClickSelected, lastRotation);
|
// let response = await update3dWidgetRotation(selectedZone, organization, rightClickSelected, lastRotation);
|
||||||
//
|
//
|
||||||
// if (response) {
|
// if (response) {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
// })();
|
// })();
|
||||||
let updatingRotation = {
|
let updatingRotation = {
|
||||||
|
@ -378,9 +468,12 @@ export default function Dropped3dWidgets() {
|
||||||
zoneId: selectedZone,
|
zoneId: selectedZone,
|
||||||
id: rightClickSelected,
|
id: rightClickSelected,
|
||||||
rotation: lastRotation,
|
rotation: lastRotation,
|
||||||
}
|
};
|
||||||
if (visualizationSocket) {
|
if (visualizationSocket) {
|
||||||
visualizationSocket.emit("v2:viz-3D-widget:modifyPositionRotation", updatingRotation);
|
visualizationSocket.emit(
|
||||||
|
"v2:viz-3D-widget:modifyPositionRotation",
|
||||||
|
updatingRotation
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,33 +496,73 @@ export default function Dropped3dWidgets() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{activeZoneWidgets.map(({ id, type, position, rotation = [0, 0, 0] }: WidgetData) => {
|
{activeZoneWidgets.map(
|
||||||
const handleRightClick = (event: React.MouseEvent, id: string) => {
|
({ id, type, position, rotation = [0, 0, 0] }: WidgetData) => {
|
||||||
event.preventDefault();
|
const handleRightClick = (event: React.MouseEvent, id: string) => {
|
||||||
const canvasElement = document.getElementById("real-time-vis-canvas");
|
event.preventDefault();
|
||||||
if (!canvasElement) throw new Error("Canvas element not found");
|
const canvasElement = document.getElementById(
|
||||||
const canvasRect = canvasElement.getBoundingClientRect();
|
"real-time-vis-canvas"
|
||||||
const relativeX = event.clientX - canvasRect.left;
|
);
|
||||||
const relativeY = event.clientY - canvasRect.top;
|
if (!canvasElement) throw new Error("Canvas element not found");
|
||||||
setEditWidgetOptions(true);
|
const canvasRect = canvasElement.getBoundingClientRect();
|
||||||
setRightClickSelected(id);
|
const relativeX = event.clientX - canvasRect.left;
|
||||||
setTop(relativeY);
|
const relativeY = event.clientY - canvasRect.top;
|
||||||
setLeft(relativeX);
|
setEditWidgetOptions(true);
|
||||||
};
|
setRightClickSelected(id);
|
||||||
|
setTop(relativeY);
|
||||||
|
setLeft(relativeX);
|
||||||
|
};
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "ui-Widget 1":
|
case "ui-Widget 1":
|
||||||
return (<ProductionCapacity key={id} id={id} type={type} position={position} rotation={rotation} onContextMenu={(e) => handleRightClick(e, id)} />);
|
return (
|
||||||
case "ui-Widget 2":
|
<ProductionCapacity
|
||||||
return (<ReturnOfInvestment key={id} id={id} type={type} position={position} rotation={rotation} onContextMenu={(e) => handleRightClick(e, id)} />);
|
key={id}
|
||||||
case "ui-Widget 3":
|
id={id}
|
||||||
return (<StateWorking key={id} id={id} type={type} position={position} rotation={rotation} onContextMenu={(e) => handleRightClick(e, id)} />);
|
type={type}
|
||||||
case "ui-Widget 4":
|
position={position}
|
||||||
return (<Throughput key={id} id={id} type={type} position={position} rotation={rotation} onContextMenu={(e) => handleRightClick(e, id)} />);
|
rotation={rotation}
|
||||||
default:
|
onContextMenu={(e) => handleRightClick(e, id)}
|
||||||
return null;
|
/>
|
||||||
|
);
|
||||||
|
case "ui-Widget 2":
|
||||||
|
return (
|
||||||
|
<ReturnOfInvestment
|
||||||
|
key={id}
|
||||||
|
id={id}
|
||||||
|
type={type}
|
||||||
|
position={position}
|
||||||
|
rotation={rotation}
|
||||||
|
onContextMenu={(e) => handleRightClick(e, id)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case "ui-Widget 3":
|
||||||
|
return (
|
||||||
|
<StateWorking
|
||||||
|
key={id}
|
||||||
|
id={id}
|
||||||
|
type={type}
|
||||||
|
position={position}
|
||||||
|
rotation={rotation}
|
||||||
|
onContextMenu={(e) => handleRightClick(e, id)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case "ui-Widget 4":
|
||||||
|
return (
|
||||||
|
<Throughput
|
||||||
|
key={id}
|
||||||
|
id={id}
|
||||||
|
type={type}
|
||||||
|
position={position}
|
||||||
|
rotation={rotation}
|
||||||
|
onContextMenu={(e) => handleRightClick(e, id)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ interface PanelProps {
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
}>
|
}>
|
||||||
>;
|
>;
|
||||||
hiddenPanels: string[];
|
hiddenPanels: any;
|
||||||
setZonesData: React.Dispatch<React.SetStateAction<any>>;
|
setZonesData: React.Dispatch<React.SetStateAction<any>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,12 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
const handleDrop = (e: React.DragEvent, panel: Side) => {
|
const handleDrop = (e: React.DragEvent, panel: Side) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const { draggedAsset } = useWidgetStore.getState();
|
const { draggedAsset } = useWidgetStore.getState();
|
||||||
if (!draggedAsset || isPanelLocked(panel)) return;
|
if (
|
||||||
|
!draggedAsset ||
|
||||||
|
isPanelLocked(panel) ||
|
||||||
|
hiddenPanels[selectedZone.zoneId]?.includes(panel)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
const currentWidgetsCount = getCurrentWidgetCount(panel);
|
const currentWidgetsCount = getCurrentWidgetCount(panel);
|
||||||
const maxCapacity = calculatePanelCapacity(panel);
|
const maxCapacity = calculatePanelCapacity(panel);
|
||||||
|
@ -255,8 +260,6 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
const leftCapacity = calculatePanelCapacity("left");
|
const leftCapacity = calculatePanelCapacity("left");
|
||||||
const rightCapacity = calculatePanelCapacity("right");
|
const rightCapacity = calculatePanelCapacity("right");
|
||||||
|
|
||||||
console.log('topCapacity: ', topCapacity);
|
|
||||||
console.log('bottomWidth: ', bottomWidth);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<style>
|
<style>
|
||||||
|
@ -280,7 +283,7 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
key={side}
|
key={side}
|
||||||
id="panel-wrapper"
|
id="panel-wrapper"
|
||||||
className={`panel ${side}-panel absolute ${
|
className={`panel ${side}-panel absolute ${
|
||||||
hiddenPanels.includes(side) ? "hidePanel" : ""
|
hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : ""
|
||||||
}`}
|
}`}
|
||||||
style={getPanelStyle(side)}
|
style={getPanelStyle(side)}
|
||||||
onDrop={(e) => handleDrop(e, side)}
|
onDrop={(e) => handleDrop(e, side)}
|
||||||
|
@ -296,9 +299,11 @@ const Panel: React.FC<PanelProps> = ({
|
||||||
<div
|
<div
|
||||||
className={`panel-content ${isPlaying && "fullScreen"}`}
|
className={`panel-content ${isPlaying && "fullScreen"}`}
|
||||||
style={{
|
style={{
|
||||||
pointerEvents: selectedZone.lockedPanels.includes(side)
|
pointerEvents:
|
||||||
? "none"
|
selectedZone.lockedPanels.includes(side) ||
|
||||||
: "auto",
|
hiddenPanels[selectedZone.zoneId]?.includes(side)
|
||||||
|
? "none"
|
||||||
|
: "auto",
|
||||||
opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
|
opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {
|
||||||
useRightClickSelected,
|
useRightClickSelected,
|
||||||
useRightSelected,
|
useRightSelected,
|
||||||
} from "../../../store/useZone3DWidgetStore";
|
} from "../../../store/useZone3DWidgetStore";
|
||||||
|
import Dropped3dWidgets from "./Dropped3dWidget";
|
||||||
|
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
|
||||||
|
@ -52,8 +53,13 @@ type Widget = {
|
||||||
data: any;
|
data: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Define the type for HiddenPanels, where keys are zone IDs and values are arrays of hidden sides
|
||||||
|
interface HiddenPanels {
|
||||||
|
[zoneId: string]: Side[];
|
||||||
|
}
|
||||||
|
|
||||||
const RealTimeVisulization: React.FC = () => {
|
const RealTimeVisulization: React.FC = () => {
|
||||||
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
|
const [hiddenPanels, setHiddenPanels] = React.useState<HiddenPanels>({});
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
@ -67,12 +73,13 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
const { rightClickSelected, setRightClickSelected } = useRightClickSelected();
|
const { rightClickSelected, setRightClickSelected } = useRightClickSelected();
|
||||||
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false);
|
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false);
|
||||||
|
|
||||||
const [floatingWidgets, setFloatingWidgets] = useState<Record<string, { zoneName: string; zoneId: string; objects: any[] }>>({});
|
const [floatingWidgets, setFloatingWidgets] = useState<
|
||||||
|
Record<string, { zoneName: string; zoneId: string; objects: any[] }>
|
||||||
|
>({});
|
||||||
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
|
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
|
||||||
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
|
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
|
||||||
const { visualizationSocket } = useSocketStore();
|
const { visualizationSocket } = useSocketStore();
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function GetZoneData() {
|
async function GetZoneData() {
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
|
@ -99,7 +106,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
setZonesData(formattedData);
|
setZonesData(formattedData);
|
||||||
} catch (error) { }
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetZoneData();
|
GetZoneData();
|
||||||
|
@ -127,6 +134,8 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
// useEffect(() => {}, [floatingWidgets]);
|
// useEffect(() => {}, [floatingWidgets]);
|
||||||
|
|
||||||
const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
|
const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
|
@ -172,7 +181,6 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
if (visualizationSocket) {
|
if (visualizationSocket) {
|
||||||
visualizationSocket.emit("v2:viz-float:add", addFloatingWidget);
|
visualizationSocket.emit("v2:viz-float:add", addFloatingWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let response = await addingFloatingWidgets(
|
// let response = await addingFloatingWidgets(
|
||||||
// selectedZone.zoneId,
|
// selectedZone.zoneId,
|
||||||
// organization,
|
// organization,
|
||||||
|
@ -197,29 +205,9 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
} catch (error) { }
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
|
||||||
const editWidgetOptions = document.querySelector(
|
|
||||||
".editWidgetOptions-wrapper"
|
|
||||||
);
|
|
||||||
if (
|
|
||||||
editWidgetOptions &&
|
|
||||||
!editWidgetOptions.contains(event.target as Node)
|
|
||||||
) {
|
|
||||||
setRightClickSelected(null);
|
|
||||||
setRightSelect(null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("mousedown", handleClickOutside);
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("mousedown", handleClickOutside);
|
|
||||||
};
|
|
||||||
}, [setRightClickSelected]);
|
|
||||||
|
|
||||||
// Add this useEffect hook to your component
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
const editWidgetOptions = document.querySelector(
|
const editWidgetOptions = document.querySelector(
|
||||||
|
@ -242,8 +230,6 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
id="real-time-vis-canvas"
|
id="real-time-vis-canvas"
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
import { useSelectedFloorItem, useZoneAssetId } from '../../../store/store';
|
||||||
|
import * as THREE from "three";
|
||||||
|
import { useThree } from '@react-three/fiber';
|
||||||
|
import * as Types from "../../../types/world/worldTypes";
|
||||||
|
export default function ZoneAssets() {
|
||||||
|
const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
|
||||||
|
const { setSelectedFloorItem } = useSelectedFloorItem();
|
||||||
|
const { raycaster, controls, scene }: any = useThree();
|
||||||
|
useEffect(() => {
|
||||||
|
// console.log('zoneAssetId: ', zoneAssetId);
|
||||||
|
if (!zoneAssetId) return
|
||||||
|
console.log('zoneAssetId: ', zoneAssetId);
|
||||||
|
let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id);
|
||||||
|
if (!AssetMesh) return;
|
||||||
|
|
||||||
|
const bbox = new THREE.Box3().setFromObject(AssetMesh);
|
||||||
|
const size = bbox.getSize(new THREE.Vector3());
|
||||||
|
const center = bbox.getCenter(new THREE.Vector3());
|
||||||
|
|
||||||
|
const front = new THREE.Vector3(0, 0, 1);
|
||||||
|
AssetMesh.localToWorld(front);
|
||||||
|
front.sub(AssetMesh.position).normalize();
|
||||||
|
|
||||||
|
const distance = Math.max(size.x, size.y, size.z) * 2;
|
||||||
|
const newPosition = center.clone().addScaledVector(front, distance);
|
||||||
|
|
||||||
|
controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true);
|
||||||
|
controls.setTarget(center.x, center.y, center.z, true);
|
||||||
|
controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
|
||||||
|
|
||||||
|
setSelectedFloorItem(AssetMesh);
|
||||||
|
|
||||||
|
}, [zoneAssetId, scene, controls])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
|
||||||
import List from "./List";
|
import List from "./List";
|
||||||
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
||||||
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
||||||
import { useZones } from "../../../store/store";
|
import { useFloorItems, useZones } from "../../../store/store";
|
||||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
||||||
|
|
||||||
interface DropDownListProps {
|
interface DropDownListProps {
|
||||||
|
@ -38,92 +38,66 @@ const DropDownList: React.FC<DropDownListProps> = ({
|
||||||
const handleToggle = () => {
|
const handleToggle = () => {
|
||||||
setIsOpen((prev) => !prev); // Toggle the state
|
setIsOpen((prev) => !prev); // Toggle the state
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Asset {
|
interface Asset {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
position: [number, number, number]; // x, y, z
|
||||||
}
|
}
|
||||||
|
|
||||||
const [zoneDataList, setZoneDataList] = useState<
|
interface Zone {
|
||||||
{ id: string; name: string; assets: Asset[] }[]
|
zoneId: string;
|
||||||
>([]);
|
zoneName: string;
|
||||||
const [zonePoints3D, setZonePoints3D] = useState<[]>([]);
|
points: [number, number, number][]; // polygon vertices
|
||||||
|
}
|
||||||
|
interface ZoneData {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
assets: { id: string; name: string; position?: [] ;rotation?:{}}[];
|
||||||
|
}
|
||||||
|
const [zoneDataList, setZoneDataList] = useState<ZoneData[]>([]);
|
||||||
|
const { floorItems, setFloorItems } = useFloorItems();
|
||||||
|
|
||||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
const isPointInsidePolygon = (point: [number, number], polygon: [number, number][]) => {
|
||||||
|
let inside = false;
|
||||||
|
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||||
|
const xi = polygon[i][0], zi = polygon[i][1];
|
||||||
|
const xj = polygon[j][0], zj = polygon[j][1];
|
||||||
|
|
||||||
useEffect(() => {
|
const intersect = ((zi > point[1]) !== (zj > point[1])) &&
|
||||||
// const value = (zones || []).map(
|
(point[0] < (xj - xi) * (point[1] - zi) / (zj - zi + 0.000001) + xi);
|
||||||
// (val: { zoneId: string; zoneName: string }) => ({
|
|
||||||
// id: val.zoneId,
|
|
||||||
// name: val.zoneName,
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
// console.log('zones: ', zones);
|
|
||||||
const value = (zones || []).map((val: { zoneId: string; zoneName: string }) => ({
|
|
||||||
id: val.zoneId,
|
|
||||||
name: val.zoneName
|
|
||||||
}));
|
|
||||||
setZoneDataList(prev => (JSON.stringify(prev) !== JSON.stringify(value) ? value : prev));
|
|
||||||
const allPoints = zones.flatMap((zone: any) => zone.points);
|
|
||||||
setZonePoints3D(allPoints);
|
|
||||||
// setZoneDataList([
|
|
||||||
// {
|
|
||||||
// id: "zone1",
|
|
||||||
// name: "Zone 1",
|
|
||||||
// assets: [
|
|
||||||
// {
|
|
||||||
// id: "asset1",
|
|
||||||
// name: "Asset 1",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "asset2",
|
|
||||||
// name: "Asset 2",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "asset3",
|
|
||||||
// name: "Asset 3",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "zone2",
|
|
||||||
// name: "Zone 2",
|
|
||||||
// assets: [
|
|
||||||
// {
|
|
||||||
// id: "asset4",
|
|
||||||
// name: "Asset 4",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "asset5",
|
|
||||||
// name: "Asset 5",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "asset6",
|
|
||||||
// name: "Asset 6",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "zone3",
|
|
||||||
// name: "Zone 3",
|
|
||||||
// assets: [
|
|
||||||
// {
|
|
||||||
// id: "asset7",
|
|
||||||
// name: "Asset 7",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "asset8",
|
|
||||||
// name: "Asset 8",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
}, [zones]);
|
if (intersect) inside = !inside;
|
||||||
|
}
|
||||||
|
return inside;
|
||||||
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
// console.log('zonePoints3D: ', zonePoints3D);
|
const updatedZoneList: ZoneData[] = zones.map((zone: Zone) => {
|
||||||
}, [zonePoints3D])
|
const polygon2D = zone.points.map((p: [number, number, number]) => [p[0], p[2]]) as [number, number][];
|
||||||
|
|
||||||
|
const assetsInZone = floorItems
|
||||||
|
.filter((item: any) => {
|
||||||
|
const [x, , z] = item.position;
|
||||||
|
return isPointInsidePolygon([x, z], polygon2D);
|
||||||
|
})
|
||||||
|
.map((item: any) => ({
|
||||||
|
id: item.modeluuid,
|
||||||
|
name: item.modelname,
|
||||||
|
position: item.position,
|
||||||
|
rotation:item.rotation
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: zone.zoneId,
|
||||||
|
name: zone.zoneName,
|
||||||
|
assets: assetsInZone,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
setZoneDataList(updatedZoneList);
|
||||||
|
}, [zones, floorItems]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dropdown-list-container">
|
<div className="dropdown-list-container">
|
||||||
|
|
|
@ -12,10 +12,14 @@ import {
|
||||||
LockIcon,
|
LockIcon,
|
||||||
RmoveIcon,
|
RmoveIcon,
|
||||||
} from "../../icons/ExportCommonIcons";
|
} from "../../icons/ExportCommonIcons";
|
||||||
|
import { useThree } from "@react-three/fiber";
|
||||||
|
import { useZoneAssetId } from "../../../store/store";
|
||||||
|
|
||||||
interface Asset {
|
interface Asset {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
position?: [number, number, number]; // Proper 3D vector
|
||||||
|
rotation?: { x: number; y: number; z: number }; // Proper rotation format
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ZoneItem {
|
interface ZoneItem {
|
||||||
|
@ -33,11 +37,13 @@ interface ListProps {
|
||||||
const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
||||||
const { activeModule, setActiveModule } = useModuleStore();
|
const { activeModule, setActiveModule } = useModuleStore();
|
||||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||||
|
const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
|
||||||
const { setSubModule } = useSubModuleStore();
|
const { setSubModule } = useSubModuleStore();
|
||||||
const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>(
|
const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>(
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
useSelectedZoneStore.getState().setSelectedZone({
|
useSelectedZoneStore.getState().setSelectedZone({
|
||||||
zoneName: "",
|
zoneName: "",
|
||||||
|
@ -88,7 +94,9 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
||||||
console.error("Error selecting zone:", error);
|
console.error("Error selecting zone:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function handleAssetClick(asset: Asset) {
|
||||||
|
setZoneAssetId(asset)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{items.length > 0 ? (
|
{items.length > 0 ? (
|
||||||
|
@ -139,7 +147,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
||||||
className="list-container asset-item"
|
className="list-container asset-item"
|
||||||
>
|
>
|
||||||
<div className="list-item">
|
<div className="list-item">
|
||||||
<div className="value">
|
<div className="value" onClick={() => handleAssetClick(asset)}>
|
||||||
<RenameInput value={asset.name} />
|
<RenameInput value={asset.name} />
|
||||||
</div>
|
</div>
|
||||||
<div className="options-container">
|
<div className="options-container">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { Geometry, Base, Subtraction } from "@react-three/csg";
|
import { Geometry, Base, Subtraction } from "@react-three/csg";
|
||||||
import { useDeleteModels } from "../../../store/store";
|
import { useDeleteTool } from "../../../store/store";
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
|
|
||||||
export interface CsgProps {
|
export interface CsgProps {
|
||||||
|
@ -11,19 +11,19 @@ export interface CsgProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Csg: React.FC<CsgProps> = (props) => {
|
export const Csg: React.FC<CsgProps> = (props) => {
|
||||||
const { deleteModels } = useDeleteModels();
|
const { deleteTool } = useDeleteTool();
|
||||||
const modelRef = useRef<THREE.Object3D>();
|
const modelRef = useRef<THREE.Object3D>();
|
||||||
const originalMaterials = useRef<Map<THREE.Mesh, THREE.Material>>(new Map());
|
const originalMaterials = useRef<Map<THREE.Mesh, THREE.Material>>(new Map());
|
||||||
|
|
||||||
const handleHover = (hovered: boolean, object: THREE.Mesh | null) => {
|
const handleHover = (hovered: boolean, object: THREE.Mesh | null) => {
|
||||||
if (modelRef.current && deleteModels) {
|
if (modelRef.current && deleteTool) {
|
||||||
modelRef.current.traverse((child) => {
|
modelRef.current.traverse((child) => {
|
||||||
if (child instanceof THREE.Mesh) {
|
if (child instanceof THREE.Mesh) {
|
||||||
if (!originalMaterials.current.has(child)) {
|
if (!originalMaterials.current.has(child)) {
|
||||||
originalMaterials.current.set(child, child.material);
|
originalMaterials.current.set(child, child.material);
|
||||||
}
|
}
|
||||||
child.material = child.material.clone();
|
child.material = child.material.clone();
|
||||||
child.material.color.set(hovered && deleteModels ? 0xff0000 : (originalMaterials.current.get(child) as any).color);
|
child.material.color.set(hovered && deleteTool ? 0xff0000 : (originalMaterials.current.get(child) as any).color);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,7 +219,7 @@ async function handleModelLoad(
|
||||||
eventData.position = newFloorItem.position;
|
eventData.position = newFloorItem.position;
|
||||||
eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
|
eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
|
||||||
|
|
||||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
eventData as Types.ConveyorEventsSchema
|
eventData as Types.ConveyorEventsSchema
|
||||||
]);
|
]);
|
||||||
|
@ -281,13 +281,139 @@ async function handleModelLoad(
|
||||||
return updatedItems;
|
return updatedItems;
|
||||||
});
|
});
|
||||||
|
|
||||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
eventData as Types.VehicleEventsSchema
|
eventData as Types.VehicleEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (res.type === "StaticMachine") {
|
||||||
|
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
|
||||||
|
const backendEventData: Extract<Types.EventData['eventData'], { type: 'StaticMachine' }> = {
|
||||||
|
type: "StaticMachine",
|
||||||
|
points: {
|
||||||
|
uuid: pointUUID,
|
||||||
|
position: res.points.position as [number, number, number],
|
||||||
|
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', buffer: 0, material: 'Inherit' },
|
||||||
|
triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
|
||||||
|
connections: { source: { modelUUID: model.uuid, pointUUID: pointUUID }, targets: [] },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// await setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// newFloorItem.modeluuid,
|
||||||
|
// newFloorItem.modelname,
|
||||||
|
// newFloorItem.modelfileID,
|
||||||
|
// newFloorItem.position,
|
||||||
|
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
|
socketId: socket.id
|
||||||
|
};
|
||||||
|
|
||||||
|
const eventData: any = backendEventData;
|
||||||
|
eventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
eventData.modelName = newFloorItem.modelname;
|
||||||
|
eventData.position = newFloorItem.position;
|
||||||
|
eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
|
||||||
|
|
||||||
|
setFloorItems((prevItems) => {
|
||||||
|
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||||
|
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||||
|
return updatedItems;
|
||||||
|
});
|
||||||
|
|
||||||
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
eventData as Types.StaticMachineEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (res.type === "ArmBot") {
|
||||||
|
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
|
||||||
|
const backendEventData: Extract<Types.EventData['eventData'], { type: 'ArmBot' }> = {
|
||||||
|
type: "ArmBot",
|
||||||
|
points: {
|
||||||
|
uuid: pointUUID,
|
||||||
|
position: res.points.position as [number, number, number],
|
||||||
|
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', speed: 1, processes: [] },
|
||||||
|
triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
|
||||||
|
connections: { source: { modelUUID: model.uuid, pointUUID: pointUUID }, targets: [] },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// await setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// newFloorItem.modeluuid,
|
||||||
|
// newFloorItem.modelname,
|
||||||
|
// newFloorItem.modelfileID,
|
||||||
|
// newFloorItem.position,
|
||||||
|
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
|
socketId: socket.id
|
||||||
|
};
|
||||||
|
|
||||||
|
const eventData: any = backendEventData;
|
||||||
|
eventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
eventData.modelName = newFloorItem.modelname;
|
||||||
|
eventData.position = newFloorItem.position;
|
||||||
|
eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
|
||||||
|
|
||||||
|
setFloorItems((prevItems) => {
|
||||||
|
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||||
|
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||||
|
return updatedItems;
|
||||||
|
});
|
||||||
|
|
||||||
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
eventData as Types.ArmBotEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// API
|
// API
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { useAddAction, useDeleteModels, useRoofVisibility, useToggleView, useWallVisibility, useUpdateScene } from "../../../store/store";
|
import { useAddAction, useDeleteTool, useRoofVisibility, useToggleView, useWallVisibility, useUpdateScene } from "../../../store/store";
|
||||||
import hideRoof from "../geomentries/roofs/hideRoof";
|
import hideRoof from "../geomentries/roofs/hideRoof";
|
||||||
import hideWalls from "../geomentries/walls/hideWalls";
|
import hideWalls from "../geomentries/walls/hideWalls";
|
||||||
import addAndUpdateReferencePillar from "../geomentries/pillars/addAndUpdateReferencePillar";
|
import addAndUpdateReferencePillar from "../geomentries/pillars/addAndUpdateReferencePillar";
|
||||||
|
@ -16,7 +16,7 @@ const FloorGroup = ({ floorGroup, lines, referencePole, hoveredDeletablePillar }
|
||||||
const { toggleView, setToggleView } = useToggleView();
|
const { toggleView, setToggleView } = useToggleView();
|
||||||
const { scene, camera, pointer, raycaster, gl } = useThree();
|
const { scene, camera, pointer, raycaster, gl } = useThree();
|
||||||
const { addAction, setAddAction } = useAddAction();
|
const { addAction, setAddAction } = useAddAction();
|
||||||
const { deleteModels, setDeleteModels } = useDeleteModels();
|
const { deleteTool, setDeleteTool } = useDeleteTool();
|
||||||
const { updateScene, setUpdateScene } = useUpdateScene();
|
const { updateScene, setUpdateScene } = useUpdateScene();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -56,7 +56,7 @@ const FloorGroup = ({ floorGroup, lines, referencePole, hoveredDeletablePillar }
|
||||||
if (addAction === "pillar") {
|
if (addAction === "pillar") {
|
||||||
addPillar(referencePole, floorGroup);
|
addPillar(referencePole, floorGroup);
|
||||||
}
|
}
|
||||||
if (deleteModels) {
|
if (deleteTool) {
|
||||||
DeletePillar(hoveredDeletablePillar, floorGroup);
|
DeletePillar(hoveredDeletablePillar, floorGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ const FloorGroup = ({ floorGroup, lines, referencePole, hoveredDeletablePillar }
|
||||||
canvasElement.removeEventListener("mouseup", onMouseUp);
|
canvasElement.removeEventListener("mouseup", onMouseUp);
|
||||||
canvasElement.removeEventListener("mousemove", onMouseMove);
|
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||||
};
|
};
|
||||||
}, [deleteModels, addAction])
|
}, [deleteTool, addAction])
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
hideRoof(roofVisibility, floorGroup, camera);
|
hideRoof(roofVisibility, floorGroup, camera);
|
||||||
|
@ -87,7 +87,7 @@ const FloorGroup = ({ floorGroup, lines, referencePole, hoveredDeletablePillar }
|
||||||
if (addAction === "pillar") {
|
if (addAction === "pillar") {
|
||||||
addAndUpdateReferencePillar(raycaster, floorGroup, referencePole);
|
addAndUpdateReferencePillar(raycaster, floorGroup, referencePole);
|
||||||
}
|
}
|
||||||
if (deleteModels) {
|
if (deleteTool) {
|
||||||
DeletableHoveredPillar(state, floorGroup, hoveredDeletablePillar);
|
DeletableHoveredPillar(state, floorGroup, hoveredDeletablePillar);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useLoadingProgress, useRenderDistance, useselectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, } from "../../../store/store";
|
import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, } from "../../../store/store";
|
||||||
import assetVisibility from "../geomentries/assets/assetVisibility";
|
import assetVisibility from "../geomentries/assets/assetVisibility";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
@ -26,10 +26,10 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
const { toggleView } = useToggleView();
|
const { toggleView } = useToggleView();
|
||||||
const { floorItems, setFloorItems } = useFloorItems();
|
const { floorItems, setFloorItems } = useFloorItems();
|
||||||
const { camMode } = useCamMode();
|
const { camMode } = useCamMode();
|
||||||
const { deleteModels } = useDeleteModels();
|
const { deleteTool } = useDeleteTool();
|
||||||
const { setDeletableFloorItem } = useDeletableFloorItem();
|
const { setDeletableFloorItem } = useDeletableFloorItem();
|
||||||
const { transformMode } = useTransformMode();
|
const { transformMode } = useTransformMode();
|
||||||
const { setselectedFloorItem } = useselectedFloorItem();
|
const { setSelectedFloorItem } = useSelectedFloorItem();
|
||||||
const { activeTool } = useActiveTool();
|
const { activeTool } = useActiveTool();
|
||||||
const { selectedItem, setSelectedItem } = useSelectedItem();
|
const { selectedItem, setSelectedItem } = useSelectedItem();
|
||||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||||
|
@ -191,8 +191,10 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
isLeftMouseDown = false;
|
isLeftMouseDown = false;
|
||||||
if (drag) return;
|
if (drag) return;
|
||||||
|
|
||||||
if (deleteModels) {
|
if (deleteTool) {
|
||||||
DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, setSimulationStates, socket);
|
DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, setSimulationStates, socket);
|
||||||
|
|
||||||
|
// Remove EventData if there are any in the asset.
|
||||||
}
|
}
|
||||||
const Mode = transformMode;
|
const Mode = transformMode;
|
||||||
|
|
||||||
|
@ -212,12 +214,12 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
// }
|
// }
|
||||||
// if (currentObject) {
|
// if (currentObject) {
|
||||||
// AttachedObject.current = currentObject as any;
|
// AttachedObject.current = currentObject as any;
|
||||||
// setselectedFloorItem(AttachedObject.current!);
|
// setSelectedFloorItem(AttachedObject.current!);
|
||||||
// }
|
// }
|
||||||
} else {
|
} else {
|
||||||
const target = controls.getTarget(new THREE.Vector3());
|
const target = controls.getTarget(new THREE.Vector3());
|
||||||
await controls.setTarget(target.x, 0, target.z, true);
|
await controls.setTarget(target.x, 0, target.z, true);
|
||||||
setselectedFloorItem(null);
|
setSelectedFloorItem(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,12 +263,12 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
controls.setTarget(center.x, center.y, center.z, true);
|
controls.setTarget(center.x, center.y, center.z, true);
|
||||||
controls.fitToBox(AttachedObject.current!, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
|
controls.fitToBox(AttachedObject.current!, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
|
||||||
|
|
||||||
setselectedFloorItem(AttachedObject.current!);
|
setSelectedFloorItem(AttachedObject.current!);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const target = controls.getTarget(new THREE.Vector3());
|
const target = controls.getTarget(new THREE.Vector3());
|
||||||
await controls.setTarget(target.x, 0, target.z, true);
|
await controls.setTarget(target.x, 0, target.z, true);
|
||||||
setselectedFloorItem(null);
|
setSelectedFloorItem(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +297,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
if (controls) {
|
if (controls) {
|
||||||
const target = controls.getTarget(new THREE.Vector3());
|
const target = controls.getTarget(new THREE.Vector3());
|
||||||
controls.setTarget(target.x, 0, target.z, true);
|
controls.setTarget(target.x, 0, target.z, true);
|
||||||
setselectedFloorItem(null);
|
setSelectedFloorItem(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,14 +309,14 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
canvasElement.removeEventListener("drop", onDrop);
|
canvasElement.removeEventListener("drop", onDrop);
|
||||||
canvasElement.removeEventListener("dragover", onDragOver);
|
canvasElement.removeEventListener("dragover", onDragOver);
|
||||||
};
|
};
|
||||||
}, [deleteModels, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool, activeModule,]);
|
}, [deleteTool, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool, activeModule,]);
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
if (controls)
|
if (controls)
|
||||||
assetVisibility(itemsGroup, state.camera.position, renderDistance);
|
assetVisibility(itemsGroup, state.camera.position, renderDistance);
|
||||||
if (deleteModels && activeModule === "builder") {
|
if (deleteTool && activeModule === "builder") {
|
||||||
DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem);
|
DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem);
|
||||||
} else if (!deleteModels) {
|
} else if (!deleteTool) {
|
||||||
if (hoveredDeletableFloorItem.current) {
|
if (hoveredDeletableFloorItem.current) {
|
||||||
hoveredDeletableFloorItem.current = undefined;
|
hoveredDeletableFloorItem.current = undefined;
|
||||||
setDeletableFloorItem(null);
|
setDeletableFloorItem(null);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useDeleteModels, useDeletePointOrLine, useObjectPosition, useObjectRotation, useObjectScale, useSelectedWallItem, useSocketStore, useWallItems } from "../../../store/store";
|
import { useDeleteTool, useDeletePointOrLine, useObjectPosition, useObjectRotation, useObjectScale, useSelectedWallItem, useSocketStore, useWallItems } from "../../../store/store";
|
||||||
import { Csg } from "../csg/csg";
|
import { Csg } from "../csg/csg";
|
||||||
import * as Types from "../../../types/world/worldTypes";
|
import * as Types from "../../../types/world/worldTypes";
|
||||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||||
|
@ -16,7 +16,7 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable
|
||||||
const state = useThree();
|
const state = useThree();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { pointer, camera, raycaster } = state;
|
const { pointer, camera, raycaster } = state;
|
||||||
const { deleteModels, setDeleteModels } = useDeleteModels();
|
const { deleteTool, setDeleteTool } = useDeleteTool();
|
||||||
const { wallItems, setWallItems } = useWallItems();
|
const { wallItems, setWallItems } = useWallItems();
|
||||||
const { objectPosition, setObjectPosition } = useObjectPosition();
|
const { objectPosition, setObjectPosition } = useObjectPosition();
|
||||||
const { objectScale, setObjectScale } = useObjectScale();
|
const { objectScale, setObjectScale } = useObjectScale();
|
||||||
|
@ -210,7 +210,7 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable
|
||||||
const onMouseUp = (evt: any) => {
|
const onMouseUp = (evt: any) => {
|
||||||
if (evt.button === 0) {
|
if (evt.button === 0) {
|
||||||
isLeftMouseDown = false;
|
isLeftMouseDown = false;
|
||||||
if (!drag && deleteModels && activeModule === "builder") {
|
if (!drag && deleteTool && activeModule === "builder") {
|
||||||
DeleteWallItems(hoveredDeletableWallItem, setWallItems, wallItems, socket);
|
DeleteWallItems(hoveredDeletableWallItem, setWallItems, wallItems, socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,15 +257,15 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable
|
||||||
canvasElement.removeEventListener("drop", onDrop);
|
canvasElement.removeEventListener("drop", onDrop);
|
||||||
canvasElement.removeEventListener("dragover", onDragOver);
|
canvasElement.removeEventListener("dragover", onDragOver);
|
||||||
};
|
};
|
||||||
}, [deleteModels, wallItems])
|
}, [deleteTool, wallItems])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (deleteModels && activeModule === "builder") {
|
if (deleteTool && activeModule === "builder") {
|
||||||
handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex);
|
handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex);
|
||||||
setSelectedWallItem(null);
|
setSelectedWallItem(null);
|
||||||
setSelectedItemsIndex(null);
|
setSelectedItemsIndex(null);
|
||||||
}
|
}
|
||||||
}, [deleteModels])
|
}, [deleteTool])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Geometry } from "@react-three/csg";
|
import { Geometry } from "@react-three/csg";
|
||||||
import { useDeleteModels, useSelectedWallItem, useToggleView, useTransformMode, useWallItems, useWalls } from "../../../store/store";
|
import { useDeleteTool, useSelectedWallItem, useToggleView, useTransformMode, useWallItems, useWalls } from "../../../store/store";
|
||||||
import handleMeshDown from "../eventFunctions/handleMeshDown";
|
import handleMeshDown from "../eventFunctions/handleMeshDown";
|
||||||
import handleMeshMissed from "../eventFunctions/handleMeshMissed";
|
import handleMeshMissed from "../eventFunctions/handleMeshMissed";
|
||||||
import WallsMesh from "./wallsMesh";
|
import WallsMesh from "./wallsMesh";
|
||||||
|
@ -11,13 +11,13 @@ const WallsAndWallItems = ({ CSGGroup, AssetConfigurations, setSelectedItemsInde
|
||||||
const { walls, setWalls } = useWalls();
|
const { walls, setWalls } = useWalls();
|
||||||
const { wallItems, setWallItems } = useWallItems();
|
const { wallItems, setWallItems } = useWallItems();
|
||||||
const { toggleView, setToggleView } = useToggleView();
|
const { toggleView, setToggleView } = useToggleView();
|
||||||
const { deleteModels, setDeleteModels } = useDeleteModels();
|
const { deleteTool, setDeleteTool } = useDeleteTool();
|
||||||
const { transformMode, setTransformMode } = useTransformMode();
|
const { transformMode, setTransformMode } = useTransformMode();
|
||||||
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
|
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (transformMode === null) {
|
if (transformMode === null) {
|
||||||
if (!deleteModels) {
|
if (!deleteTool) {
|
||||||
handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex);
|
handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex);
|
||||||
setSelectedWallItem(null);
|
setSelectedWallItem(null);
|
||||||
setSelectedItemsIndex(null);
|
setSelectedItemsIndex(null);
|
||||||
|
@ -33,12 +33,12 @@ const WallsAndWallItems = ({ CSGGroup, AssetConfigurations, setSelectedItemsInde
|
||||||
receiveShadow
|
receiveShadow
|
||||||
visible={!toggleView}
|
visible={!toggleView}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (!deleteModels && transformMode !== null) {
|
if (!deleteTool && transformMode !== null) {
|
||||||
handleMeshDown(event, currentWallItem, setSelectedWallItem, setSelectedItemsIndex, wallItems, toggleView);
|
handleMeshDown(event, currentWallItem, setSelectedWallItem, setSelectedItemsIndex, wallItems, toggleView);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
onPointerMissed={() => {
|
||||||
if (!deleteModels) {
|
if (!deleteTool) {
|
||||||
handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex);
|
handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex);
|
||||||
setSelectedWallItem(null);
|
setSelectedWallItem(null);
|
||||||
setSelectedItemsIndex(null);
|
setSelectedItemsIndex(null);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@ import { useEffect } from "react";
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import * as Types from '../../../types/world/worldTypes';
|
import * as Types from '../../../types/world/worldTypes';
|
||||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||||
import { useActiveLayer, useSocketStore, useDeleteModels, useDeletePointOrLine, useMovePoint, useToggleView, useUpdateScene, useNewLines, useToolMode } from "../../../store/store";
|
import { useActiveLayer, useSocketStore, useDeleteTool, useDeletePointOrLine, useMovePoint, useToggleView, useUpdateScene, useNewLines, useToolMode } from "../../../store/store";
|
||||||
import { useThree } from "@react-three/fiber";
|
import { useThree } from "@react-three/fiber";
|
||||||
import arrayLineToObject from "../geomentries/lines/lineConvertions/arrayLineToObject";
|
import arrayLineToObject from "../geomentries/lines/lineConvertions/arrayLineToObject";
|
||||||
import addPointToScene from "../geomentries/points/addPointToScene";
|
import addPointToScene from "../geomentries/points/addPointToScene";
|
||||||
|
@ -14,7 +14,7 @@ import loadZones from "../geomentries/zones/loadZones";
|
||||||
|
|
||||||
const ZoneGroup = ({ zoneGroup, plane, floorPlanGroupLine, floorPlanGroupPoint, line, lines, currentLayerPoint, dragPointControls, floorPlanGroup, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => {
|
const ZoneGroup = ({ zoneGroup, plane, floorPlanGroupLine, floorPlanGroupPoint, line, lines, currentLayerPoint, dragPointControls, floorPlanGroup, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => {
|
||||||
const { toggleView, setToggleView } = useToggleView();
|
const { toggleView, setToggleView } = useToggleView();
|
||||||
const { deleteModels, setDeleteModels } = useDeleteModels();
|
const { deleteTool, setDeleteTool } = useDeleteTool();
|
||||||
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
|
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
|
||||||
const { toolMode, setToolMode } = useToolMode();
|
const { toolMode, setToolMode } = useToolMode();
|
||||||
const { movePoint, setMovePoint } = useMovePoint();
|
const { movePoint, setMovePoint } = useMovePoint();
|
||||||
|
@ -35,7 +35,7 @@ const ZoneGroup = ({ zoneGroup, plane, floorPlanGroupLine, floorPlanGroupPoint,
|
||||||
if (toolMode === "Zone") {
|
if (toolMode === "Zone") {
|
||||||
setDeletePointOrLine(false);
|
setDeletePointOrLine(false);
|
||||||
setMovePoint(false);
|
setMovePoint(false);
|
||||||
setDeleteModels(false);
|
setDeleteTool(false);
|
||||||
} else {
|
} else {
|
||||||
removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint);
|
removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint);
|
||||||
removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
|
removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
|
||||||
|
|
|
@ -192,7 +192,7 @@ function processLoadedModel(
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (item.eventData || item.modelfileID === '67e3db5ac2e8f37134526f40' || item.modelfileID === '67eb7904c2e8f37134527eae') {
|
if (item.eventData || item.modelfileID === '67e3db5ac2e8f37134526f40') {
|
||||||
processEventData(item, setSimulationStates);
|
processEventData(item, setSimulationStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ function processEventData(item: Types.EventData, setSimulationStates: any) {
|
||||||
data.position = item.position;
|
data.position = item.position;
|
||||||
data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
|
data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
|
||||||
|
|
||||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
data as Types.ConveyorEventsSchema
|
data as Types.ConveyorEventsSchema
|
||||||
]);
|
]);
|
||||||
|
@ -222,58 +222,35 @@ function processEventData(item: Types.EventData, setSimulationStates: any) {
|
||||||
data.modelName = item.modelname;
|
data.modelName = item.modelname;
|
||||||
data.position = item.position;
|
data.position = item.position;
|
||||||
|
|
||||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
data as Types.VehicleEventsSchema
|
data as Types.VehicleEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} else if (item.modelfileID === '67e3db5ac2e8f37134526f40') {
|
} else if (item.eventData?.type === 'StaticMachine') {
|
||||||
|
|
||||||
const pointUUID = THREE.MathUtils.generateUUID();
|
const data: any = item.eventData;
|
||||||
const pointPosition = new THREE.Vector3(0, 1.5, -0.5);
|
data.modeluuid = item.modeluuid;
|
||||||
|
data.modelName = item.modelname;
|
||||||
|
data.position = item.position;
|
||||||
|
data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
|
||||||
|
|
||||||
const staticMachine: Types.StaticMachineEventsSchema = {
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
modeluuid: item.modeluuid,
|
|
||||||
modelName: item.modelname,
|
|
||||||
type: "StaticMachine",
|
|
||||||
points: {
|
|
||||||
uuid: pointUUID,
|
|
||||||
position: [pointPosition.x, pointPosition.y, pointPosition.z],
|
|
||||||
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', buffer: 'Inherit', material: 'Inherit', isUsed: false },
|
|
||||||
triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
|
|
||||||
connections: { source: { modelUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
|
|
||||||
},
|
|
||||||
position: item.position,
|
|
||||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
|
||||||
};
|
|
||||||
|
|
||||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
staticMachine as Types.StaticMachineEventsSchema
|
data as Types.StaticMachineEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} else if (item.modelfileID === '67eb7904c2e8f37134527eae') {
|
} else if (item.eventData?.type === 'ArmBot') {
|
||||||
const pointUUID = THREE.MathUtils.generateUUID();
|
|
||||||
const pointPosition = new THREE.Vector3(0, 2.75, -0.5);
|
|
||||||
|
|
||||||
const armBot: Types.ArmBotEventsSchema = {
|
const data: any = item.eventData;
|
||||||
modeluuid: item.modeluuid,
|
data.modeluuid = item.modeluuid;
|
||||||
modelName: item.modelname,
|
data.modelName = item.modelname;
|
||||||
type: "ArmBot",
|
data.position = item.position;
|
||||||
points: {
|
data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
|
||||||
uuid: pointUUID,
|
|
||||||
position: [pointPosition.x, pointPosition.y, pointPosition.z],
|
|
||||||
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', speed: 1, processes: [] },
|
|
||||||
triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
|
|
||||||
connections: { source: { modelUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
|
|
||||||
},
|
|
||||||
position: item.position,
|
|
||||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
|
||||||
}
|
|
||||||
|
|
||||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
armBot as Types.ArmBotEventsSchema
|
data as Types.ArmBotEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,10 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
||||||
uuid: THREE.MathUtils.generateUUID()
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
}))
|
}))
|
||||||
: [defaultAction],
|
: [defaultAction],
|
||||||
triggers: (eventData as Types.ConveyorEventsSchema)?.points[index].triggers,
|
triggers: (eventData as Types.ConveyorEventsSchema)?.points[index].triggers.map(trigger => ({
|
||||||
|
...trigger,
|
||||||
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
|
})),
|
||||||
connections: {
|
connections: {
|
||||||
source: { modelUUID: obj.uuid, pointUUID },
|
source: { modelUUID: obj.uuid, pointUUID },
|
||||||
targets: []
|
targets: []
|
||||||
|
@ -320,6 +323,163 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
||||||
|
|
||||||
socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (eventData.type === 'StaticMachine' && eventData) {
|
||||||
|
const createStaticMachinePoint = () => {
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
const vehiclePoint = (eventData as Types.StaticMachineEventsSchema)?.points;
|
||||||
|
const hasActions = vehiclePoint?.actions !== undefined;
|
||||||
|
|
||||||
|
const defaultAction = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
name: 'Action 1',
|
||||||
|
buffer: 0,
|
||||||
|
material: 'Inherit',
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: pointUUID,
|
||||||
|
position: vehiclePoint?.position,
|
||||||
|
actions: hasActions
|
||||||
|
? {
|
||||||
|
...vehiclePoint.actions,
|
||||||
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
|
}
|
||||||
|
: defaultAction,
|
||||||
|
connections: {
|
||||||
|
source: { modelUUID: obj.uuid, pointUUID },
|
||||||
|
targets: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const backendEventData = {
|
||||||
|
type: 'StaticMachine',
|
||||||
|
points: createStaticMachinePoint()
|
||||||
|
};
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// obj.uuid,
|
||||||
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
|
socketId: socket.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
|
||||||
|
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
newEventData.modelName = newFloorItem.modelname;
|
||||||
|
newEventData.position = newFloorItem.position;
|
||||||
|
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||||
|
|
||||||
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
newEventData as Types.StaticMachineEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (eventData.type === 'ArmBot' && eventData) {
|
||||||
|
const createArmBotPoint = () => {
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
const vehiclePoint = (eventData as Types.ArmBotEventsSchema)?.points;
|
||||||
|
const hasActions = vehiclePoint?.actions !== undefined;
|
||||||
|
|
||||||
|
const defaultAction = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
name: 'Action 1',
|
||||||
|
buffer: 0,
|
||||||
|
material: 'Inherit',
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: pointUUID,
|
||||||
|
position: vehiclePoint?.position,
|
||||||
|
actions: hasActions
|
||||||
|
? {
|
||||||
|
...vehiclePoint.actions,
|
||||||
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
|
}
|
||||||
|
: defaultAction,
|
||||||
|
triggers: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
name: vehiclePoint.triggers.name,
|
||||||
|
type: vehiclePoint.triggers.type,
|
||||||
|
},
|
||||||
|
connections: {
|
||||||
|
source: { modelUUID: obj.uuid, pointUUID },
|
||||||
|
targets: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const backendEventData = {
|
||||||
|
type: 'ArmBot',
|
||||||
|
points: createArmBotPoint()
|
||||||
|
};
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// obj.uuid,
|
||||||
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
|
socketId: socket.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
|
||||||
|
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
newEventData.modelName = newFloorItem.modelname;
|
||||||
|
newEventData.position = newFloorItem.position;
|
||||||
|
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||||
|
|
||||||
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
newEventData as Types.ArmBotEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//REST
|
//REST
|
||||||
|
|
|
@ -163,7 +163,10 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
||||||
uuid: THREE.MathUtils.generateUUID()
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
}))
|
}))
|
||||||
: [defaultAction],
|
: [defaultAction],
|
||||||
triggers: (eventData as Types.ConveyorEventsSchema)?.points[index].triggers,
|
triggers: (eventData as Types.ConveyorEventsSchema)?.points[index].triggers.map(trigger => ({
|
||||||
|
...trigger,
|
||||||
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
|
})),
|
||||||
connections: {
|
connections: {
|
||||||
source: { modelUUID: newFloorItem.modeluuid, pointUUID },
|
source: { modelUUID: newFloorItem.modeluuid, pointUUID },
|
||||||
targets: []
|
targets: []
|
||||||
|
@ -174,9 +177,9 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
||||||
const backendEventData = {
|
const backendEventData = {
|
||||||
type: 'Conveyor',
|
type: 'Conveyor',
|
||||||
points: [
|
points: [
|
||||||
createConveyorPoint(0), // point1
|
createConveyorPoint(0),
|
||||||
createConveyorPoint(1), // middlePoint
|
createConveyorPoint(1),
|
||||||
createConveyorPoint(2) // point2
|
createConveyorPoint(2)
|
||||||
],
|
],
|
||||||
speed: (eventData as Types.ConveyorEventsSchema)?.speed
|
speed: (eventData as Types.ConveyorEventsSchema)?.speed
|
||||||
};
|
};
|
||||||
|
@ -302,6 +305,163 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
||||||
|
|
||||||
socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (eventData.type === 'StaticMachine' && eventData) {
|
||||||
|
const createStaticMachinePoint = () => {
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
const vehiclePoint = (eventData as Types.StaticMachineEventsSchema)?.points;
|
||||||
|
const hasActions = vehiclePoint?.actions !== undefined;
|
||||||
|
|
||||||
|
const defaultAction = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
name: 'Action 1',
|
||||||
|
buffer: 0,
|
||||||
|
material: 'Inherit',
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: pointUUID,
|
||||||
|
position: vehiclePoint?.position,
|
||||||
|
actions: hasActions
|
||||||
|
? {
|
||||||
|
...vehiclePoint.actions,
|
||||||
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
|
}
|
||||||
|
: defaultAction,
|
||||||
|
connections: {
|
||||||
|
source: { modelUUID: obj.uuid, pointUUID },
|
||||||
|
targets: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const backendEventData = {
|
||||||
|
type: 'StaticMachine',
|
||||||
|
points: createStaticMachinePoint()
|
||||||
|
};
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// obj.uuid,
|
||||||
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
|
socketId: socket.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
|
||||||
|
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
newEventData.modelName = newFloorItem.modelname;
|
||||||
|
newEventData.position = newFloorItem.position;
|
||||||
|
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||||
|
|
||||||
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
newEventData as Types.StaticMachineEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (eventData.type === 'ArmBot' && eventData) {
|
||||||
|
const createArmBotPoint = () => {
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
const vehiclePoint = (eventData as Types.ArmBotEventsSchema)?.points;
|
||||||
|
const hasActions = vehiclePoint?.actions !== undefined;
|
||||||
|
|
||||||
|
const defaultAction = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
name: 'Action 1',
|
||||||
|
buffer: 0,
|
||||||
|
material: 'Inherit',
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: pointUUID,
|
||||||
|
position: vehiclePoint?.position,
|
||||||
|
actions: hasActions
|
||||||
|
? {
|
||||||
|
...vehiclePoint.actions,
|
||||||
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
|
}
|
||||||
|
: defaultAction,
|
||||||
|
triggers: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
name: vehiclePoint.triggers.name,
|
||||||
|
type: vehiclePoint.triggers.type,
|
||||||
|
},
|
||||||
|
connections: {
|
||||||
|
source: { modelUUID: obj.uuid, pointUUID },
|
||||||
|
targets: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const backendEventData = {
|
||||||
|
type: 'ArmBot',
|
||||||
|
points: createArmBotPoint()
|
||||||
|
};
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// obj.uuid,
|
||||||
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
|
socketId: socket.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
|
||||||
|
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
newEventData.modelName = newFloorItem.modelname;
|
||||||
|
newEventData.position = newFloorItem.position;
|
||||||
|
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||||
|
|
||||||
|
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
newEventData as Types.ArmBotEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//REST
|
//REST
|
||||||
|
|
|
@ -323,7 +323,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
// eventData: { type: backendEventData.type, points: backendEventData.points },
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
socketId: socket.id,
|
socketId: socket.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
// eventData: { type: backendEventData.type, points: backendEventData.points },
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
socketId: socket.id,
|
socketId: socket.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
// eventData: { type: backendEventData.type, points: backendEventData.points },
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
socketId: socket.id,
|
socketId: socket.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -381,7 +381,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
// eventData: { type: backendEventData.type, points: backendEventData.points },
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
socketId: socket.id,
|
socketId: socket.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { TransformControls } from "@react-three/drei";
|
import { TransformControls } from "@react-three/drei";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useselectedFloorItem, useObjectPosition, useObjectScale, useObjectRotation, useTransformMode, useFloorItems, useSocketStore, useActiveTool } from "../../../store/store";
|
import { useSelectedFloorItem, useObjectPosition, useObjectScale, useObjectRotation, useTransformMode, useFloorItems, useSocketStore, useActiveTool } from "../../../store/store";
|
||||||
import { useThree } from "@react-three/fiber";
|
import { useThree } from "@react-three/fiber";
|
||||||
|
|
||||||
import * as Types from '../../../types/world/worldTypes';
|
import * as Types from '../../../types/world/worldTypes';
|
||||||
|
@ -8,7 +8,7 @@ import { useEffect } from "react";
|
||||||
|
|
||||||
export default function TransformControl() {
|
export default function TransformControl() {
|
||||||
const state = useThree();
|
const state = useThree();
|
||||||
const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem();
|
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
|
||||||
const { objectPosition, setObjectPosition } = useObjectPosition();
|
const { objectPosition, setObjectPosition } = useObjectPosition();
|
||||||
const { objectScale, setObjectScale } = useObjectScale();
|
const { objectScale, setObjectScale } = useObjectScale();
|
||||||
const { objectRotation, setObjectRotation } = useObjectRotation();
|
const { objectRotation, setObjectRotation } = useObjectRotation();
|
||||||
|
@ -96,7 +96,7 @@ export default function TransformControl() {
|
||||||
const target = (state.controls as any).getTarget(new THREE.Vector3());
|
const target = (state.controls as any).getTarget(new THREE.Vector3());
|
||||||
(state.controls as any).setTarget(target.x, 0, target.z, true);
|
(state.controls as any).setTarget(target.x, 0, target.z, true);
|
||||||
}
|
}
|
||||||
setselectedFloorItem(null);
|
setSelectedFloorItem(null);
|
||||||
{
|
{
|
||||||
setObjectPosition({ x: undefined, y: undefined, z: undefined });
|
setObjectPosition({ x: undefined, y: undefined, z: undefined });
|
||||||
setObjectScale({ x: undefined, y: undefined, z: undefined });
|
setObjectScale({ x: undefined, y: undefined, z: undefined });
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
useSelectedActionSphere,
|
useSelectedActionSphere,
|
||||||
useSelectedPath,
|
useSelectedPath,
|
||||||
useSelectedWallItem,
|
useSelectedWallItem,
|
||||||
useselectedFloorItem,
|
useSelectedFloorItem,
|
||||||
} from "../../../store/store";
|
} from "../../../store/store";
|
||||||
import * as Types from "../../../types/world/worldTypes";
|
import * as Types from "../../../types/world/worldTypes";
|
||||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||||
|
@ -15,7 +15,7 @@ import { useEffect } from "react";
|
||||||
export default function PostProcessing() {
|
export default function PostProcessing() {
|
||||||
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
|
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
|
||||||
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
|
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
|
||||||
const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem();
|
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
|
||||||
const { selectedActionSphere } = useSelectedActionSphere();
|
const { selectedActionSphere } = useSelectedActionSphere();
|
||||||
const { selectedPath } = useSelectedPath();
|
const { selectedPath } = useSelectedPath();
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import Simulation from "../simulation/simulation";
|
||||||
// import Simulation from "./simulationtemp/simulation";
|
// import Simulation from "./simulationtemp/simulation";
|
||||||
import ZoneCentreTarget from "../../components/ui/componets/zoneCameraTarget";
|
import ZoneCentreTarget from "../../components/ui/componets/zoneCameraTarget";
|
||||||
import Dropped3dWidgets from "../../components/ui/componets/Dropped3dWidget";
|
import Dropped3dWidgets from "../../components/ui/componets/Dropped3dWidget";
|
||||||
|
import ZoneAssets from "../../components/ui/componets/zoneAssets";
|
||||||
|
|
||||||
export default function Scene() {
|
export default function Scene() {
|
||||||
const map = useMemo(
|
const map = useMemo(
|
||||||
|
@ -48,6 +49,7 @@ export default function Scene() {
|
||||||
<MeasurementTool />
|
<MeasurementTool />
|
||||||
<World />
|
<World />
|
||||||
<ZoneCentreTarget />
|
<ZoneCentreTarget />
|
||||||
|
<ZoneAssets />
|
||||||
<Simulation />
|
<Simulation />
|
||||||
<PostProcessing />
|
<PostProcessing />
|
||||||
{savedTheme !== "dark" ? <Sun /> : <></>}
|
{savedTheme !== "dark" ? <Sun /> : <></>}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React, { useEffect, useRef, useState } from 'react';
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import * as Types from '../../../types/world/worldTypes';
|
import * as Types from '../../../types/world/worldTypes';
|
||||||
import { QuadraticBezierLine } from '@react-three/drei';
|
import { QuadraticBezierLine } from '@react-three/drei';
|
||||||
import { useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore } from '../../../store/store';
|
import { useDeleteTool, useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore } from '../../../store/store';
|
||||||
import useModuleStore from '../../../store/useModuleStore';
|
import useModuleStore from '../../../store/useModuleStore';
|
||||||
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
||||||
import { setEventApi } from '../../../services/factoryBuilder/assest/floorAsset/setEventsApt';
|
import { setEventApi } from '../../../services/factoryBuilder/assest/floorAsset/setEventsApt';
|
||||||
|
@ -11,6 +11,7 @@ import { setEventApi } from '../../../services/factoryBuilder/assest/floorAsset/
|
||||||
function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject<THREE.Group> }) {
|
function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject<THREE.Group> }) {
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||||
|
const { deleteTool } = useDeleteTool();
|
||||||
const { renderDistance } = useRenderDistance();
|
const { renderDistance } = useRenderDistance();
|
||||||
const { setIsConnecting } = useIsConnecting();
|
const { setIsConnecting } = useIsConnecting();
|
||||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||||
|
@ -21,6 +22,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
const [firstSelected, setFirstSelected] = useState<{ modelUUID: string; sphereUUID: string; position: THREE.Vector3; isCorner: boolean; } | null>(null);
|
const [firstSelected, setFirstSelected] = useState<{ modelUUID: string; sphereUUID: string; position: THREE.Vector3; isCorner: boolean; } | null>(null);
|
||||||
const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3, end: THREE.Vector3, mid: THREE.Vector3 } | null>(null);
|
const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3, end: THREE.Vector3, mid: THREE.Vector3 } | null>(null);
|
||||||
const [helperlineColor, setHelperLineColor] = useState<string>('red');
|
const [helperlineColor, setHelperLineColor] = useState<string>('red');
|
||||||
|
const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
|
||||||
|
|
||||||
const updatePathConnections = (fromModelUUID: string, fromPointUUID: string, toModelUUID: string, toPointUUID: string) => {
|
const updatePathConnections = (fromModelUUID: string, fromPointUUID: string, toModelUUID: string, toPointUUID: string) => {
|
||||||
const updatedPaths = simulationStates.map(path => {
|
const updatedPaths = simulationStates.map(path => {
|
||||||
|
@ -334,7 +336,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID
|
path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID
|
||||||
);
|
);
|
||||||
|
|
||||||
// updateBackend(updatedPathDetails);
|
updateBackend(updatedPathDetails);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateBackend = async (updatedPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => {
|
const updateBackend = async (updatedPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => {
|
||||||
|
@ -375,6 +377,38 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
|
|
||||||
socket.emit('v2:model-asset:updateEventData', data);
|
socket.emit('v2:model-asset:updateEventData', data);
|
||||||
|
|
||||||
|
} else if (updatedPath.type === 'StaticMachine') {
|
||||||
|
|
||||||
|
// await setEventApi(
|
||||||
|
// organization,
|
||||||
|
// updatedPath.modeluuid,
|
||||||
|
// { type: "StaticMachine", points: updatedPath.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization: organization,
|
||||||
|
modeluuid: updatedPath.modeluuid,
|
||||||
|
eventData: { type: "StaticMachine", points: updatedPath.points }
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v2:model-asset:updateEventData', data);
|
||||||
|
|
||||||
|
} else if (updatedPath.type === 'ArmBot') {
|
||||||
|
|
||||||
|
// await setEventApi(
|
||||||
|
// organization,
|
||||||
|
// updatedPath.modeluuid,
|
||||||
|
// { type: "ArmBot", points: updatedPath.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization: organization,
|
||||||
|
modeluuid: updatedPath.modeluuid,
|
||||||
|
eventData: { type: "ArmBot", points: updatedPath.points }
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v2:model-asset:updateEventData', data);
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -479,7 +513,6 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
|
|
||||||
// For Vehicles, check if they're already connected to anything
|
// For Vehicles, check if they're already connected to anything
|
||||||
if (intersected.userData.path.type === 'Vehicle') {
|
if (intersected.userData.path.type === 'Vehicle') {
|
||||||
console.log('intersected: ', intersected);
|
|
||||||
const vehicleConnections = intersected.userData.path.points.connections.targets.length;
|
const vehicleConnections = intersected.userData.path.points.connections.targets.length;
|
||||||
if (vehicleConnections >= 1) {
|
if (vehicleConnections >= 1) {
|
||||||
console.log("Vehicle can only have one connection");
|
console.log("Vehicle can only have one connection");
|
||||||
|
@ -589,20 +622,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
}
|
}
|
||||||
|
|
||||||
// All checks passed - make the connection
|
// All checks passed - make the connection
|
||||||
handleAddConnection(
|
handleAddConnection(firstSelected.modelUUID, firstSelected.sphereUUID, modelUUID, sphereUUID);
|
||||||
firstSelected.modelUUID,
|
|
||||||
firstSelected.sphereUUID,
|
|
||||||
modelUUID,
|
|
||||||
sphereUUID
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
// First selection - just store it
|
// First selection - just store it
|
||||||
setFirstSelected({
|
setFirstSelected({ modelUUID, sphereUUID, position: worldPosition, isCorner: isStartOrEnd });
|
||||||
modelUUID,
|
|
||||||
sphereUUID,
|
|
||||||
position: worldPosition,
|
|
||||||
isCorner: isStartOrEnd
|
|
||||||
});
|
|
||||||
setIsConnecting(true);
|
setIsConnecting(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -615,7 +638,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (activeModule === 'simulation') {
|
if (activeModule === 'simulation' && !deleteTool) {
|
||||||
canvasElement.addEventListener("mousedown", onMouseDown);
|
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||||
canvasElement.addEventListener("mouseup", onMouseUp);
|
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||||
canvasElement.addEventListener("mousemove", onMouseMove);
|
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||||
|
@ -632,7 +655,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
canvasElement.removeEventListener("mousemove", onMouseMove);
|
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||||
canvasElement.removeEventListener("contextmenu", onContextMenu);
|
canvasElement.removeEventListener("contextmenu", onContextMenu);
|
||||||
};
|
};
|
||||||
}, [camera, scene, raycaster, firstSelected, simulationStates]);
|
}, [camera, scene, raycaster, firstSelected, simulationStates, deleteTool]);
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
Object.values(groupRefs.current).forEach((group) => {
|
Object.values(groupRefs.current).forEach((group) => {
|
||||||
|
@ -665,9 +688,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) =>
|
const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => obj.object.name.includes("events-sphere"));
|
||||||
obj.object.name.includes("events-sphere")
|
|
||||||
);
|
|
||||||
|
|
||||||
if (sphereIntersects.length > 0) {
|
if (sphereIntersects.length > 0) {
|
||||||
const sphere = sphereIntersects[0].object;
|
const sphere = sphereIntersects[0].object;
|
||||||
|
@ -682,15 +703,21 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
const isVehicleToVehicle = firstPath?.type === 'Vehicle' && secondPath?.type === 'Vehicle';
|
const isVehicleToVehicle = firstPath?.type === 'Vehicle' && secondPath?.type === 'Vehicle';
|
||||||
|
|
||||||
// Inside the useFrame hook, where we check for snapped spheres:
|
// Inside the useFrame hook, where we check for snapped spheres:
|
||||||
const isConnectable = (pathData.type === 'Vehicle' ||
|
const isConnectable = (
|
||||||
|
pathData.type === 'Vehicle' ||
|
||||||
|
pathData.type === 'ArmBot' ||
|
||||||
(pathData.points.length > 0 && (
|
(pathData.points.length > 0 && (
|
||||||
sphereUUID === pathData.points[0].uuid ||
|
sphereUUID === pathData.points[0].uuid ||
|
||||||
sphereUUID === pathData.points[pathData.points.length - 1].uuid
|
sphereUUID === pathData.points[pathData.points.length - 1].uuid ||
|
||||||
))) &&
|
(pathData.type === 'Conveyor' && firstPath?.type === 'ArmBot') // Allow ArmBot to connect to middle points
|
||||||
|
))
|
||||||
|
) &&
|
||||||
!isVehicleToVehicle &&
|
!isVehicleToVehicle &&
|
||||||
!(firstPath?.type === 'Conveyor' &&
|
!(
|
||||||
|
firstPath?.type === 'Conveyor' &&
|
||||||
pathData.type === 'Conveyor' &&
|
pathData.type === 'Conveyor' &&
|
||||||
!firstSelected.isCorner);
|
!firstSelected.isCorner
|
||||||
|
);
|
||||||
|
|
||||||
// Check for duplicate connection (regardless of path type)
|
// Check for duplicate connection (regardless of path type)
|
||||||
const isDuplicateConnection = simulationStates.some(path => {
|
const isDuplicateConnection = simulationStates.some(path => {
|
||||||
|
@ -825,6 +852,127 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const removeConnections = (connection1: { model: string; point: string }, connection2: { model: string; point: string }) => {
|
||||||
|
const updatedStates = simulationStates.map(state => {
|
||||||
|
// Handle Conveyor (which has multiple points)
|
||||||
|
if (state.type === 'Conveyor') {
|
||||||
|
const updatedConveyor: Types.ConveyorEventsSchema = {
|
||||||
|
...state,
|
||||||
|
points: state.points.map(point => {
|
||||||
|
// Check if this point is either connection1 or connection2
|
||||||
|
if ((state.modeluuid === connection1.model && point.uuid === connection1.point) ||
|
||||||
|
(state.modeluuid === connection2.model && point.uuid === connection2.point)) {
|
||||||
|
|
||||||
|
return {
|
||||||
|
...point,
|
||||||
|
connections: {
|
||||||
|
...point.connections,
|
||||||
|
targets: point.connections.targets.filter(target => {
|
||||||
|
// Remove the target that matches the other connection
|
||||||
|
return !(
|
||||||
|
(target.modelUUID === connection1.model && target.pointUUID === connection1.point) ||
|
||||||
|
(target.modelUUID === connection2.model && target.pointUUID === connection2.point)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return point;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
return updatedConveyor;
|
||||||
|
}
|
||||||
|
// Handle Vehicle
|
||||||
|
else if (state.type === 'Vehicle') {
|
||||||
|
if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) ||
|
||||||
|
(state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
|
||||||
|
|
||||||
|
const updatedVehicle: Types.VehicleEventsSchema = {
|
||||||
|
...state,
|
||||||
|
points: {
|
||||||
|
...state.points,
|
||||||
|
connections: {
|
||||||
|
...state.points.connections,
|
||||||
|
targets: state.points.connections.targets.filter(target => {
|
||||||
|
return !(
|
||||||
|
(target.modelUUID === connection1.model && target.pointUUID === connection1.point) ||
|
||||||
|
(target.modelUUID === connection2.model && target.pointUUID === connection2.point)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// Ensure all required Vehicle point properties are included
|
||||||
|
speed: state.points.speed,
|
||||||
|
actions: state.points.actions
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return updatedVehicle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle StaticMachine
|
||||||
|
else if (state.type === 'StaticMachine') {
|
||||||
|
if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) ||
|
||||||
|
(state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
|
||||||
|
|
||||||
|
const updatedStaticMachine: Types.StaticMachineEventsSchema = {
|
||||||
|
...state,
|
||||||
|
points: {
|
||||||
|
...state.points,
|
||||||
|
connections: {
|
||||||
|
...state.points.connections,
|
||||||
|
targets: state.points.connections.targets.filter(target => {
|
||||||
|
return !(
|
||||||
|
(target.modelUUID === connection1.model && target.pointUUID === connection1.point) ||
|
||||||
|
(target.modelUUID === connection2.model && target.pointUUID === connection2.point)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// Ensure all required StaticMachine point properties are included
|
||||||
|
actions: state.points.actions,
|
||||||
|
triggers: state.points.triggers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return updatedStaticMachine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle ArmBot
|
||||||
|
else if (state.type === 'ArmBot') {
|
||||||
|
if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) ||
|
||||||
|
(state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
|
||||||
|
|
||||||
|
const updatedArmBot: Types.ArmBotEventsSchema = {
|
||||||
|
...state,
|
||||||
|
points: {
|
||||||
|
...state.points,
|
||||||
|
connections: {
|
||||||
|
...state.points.connections,
|
||||||
|
targets: state.points.connections.targets.filter(target => {
|
||||||
|
return !(
|
||||||
|
(target.modelUUID === connection1.model && target.pointUUID === connection1.point) ||
|
||||||
|
(target.modelUUID === connection2.model && target.pointUUID === connection2.point)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// Ensure all required ArmBot point properties are included
|
||||||
|
actions: state.points.actions,
|
||||||
|
triggers: state.points.triggers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return updatedArmBot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedPaths = updatedStates.filter(state =>
|
||||||
|
state.modeluuid === connection1.model || state.modeluuid === connection2.model
|
||||||
|
);
|
||||||
|
|
||||||
|
updateBackend(updatedPaths);
|
||||||
|
|
||||||
|
setSimulationStates(updatedStates);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group name='simulationConnectionGroup' visible={!isPlaying}>
|
<group name='simulationConnectionGroup' visible={!isPlaying}>
|
||||||
{simulationStates.flatMap(path => {
|
{simulationStates.flatMap(path => {
|
||||||
|
@ -832,7 +980,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
return path.points.flatMap(point =>
|
return path.points.flatMap(point =>
|
||||||
point.connections.targets.map((target, index) => {
|
point.connections.targets.map((target, index) => {
|
||||||
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
||||||
if (targetPath?.type === 'Vehicle') return null;
|
if (targetPath?.type !== 'Conveyor' && targetPath?.type !== 'ArmBot') return null;
|
||||||
|
|
||||||
const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid);
|
const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid);
|
||||||
const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
|
const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
|
||||||
|
@ -845,11 +993,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
|
|
||||||
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
||||||
const heightFactor = Math.max(0.5, distance * 0.2);
|
const heightFactor = Math.max(0.5, distance * 0.2);
|
||||||
const midPoint = new THREE.Vector3(
|
const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2);
|
||||||
(fromWorldPosition.x + toWorldPosition.x) / 2,
|
|
||||||
Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor,
|
|
||||||
(fromWorldPosition.z + toWorldPosition.z) / 2
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QuadraticBezierLine
|
<QuadraticBezierLine
|
||||||
|
@ -858,11 +1002,30 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
start={fromWorldPosition.toArray()}
|
start={fromWorldPosition.toArray()}
|
||||||
end={toWorldPosition.toArray()}
|
end={toWorldPosition.toArray()}
|
||||||
mid={midPoint.toArray()}
|
mid={midPoint.toArray()}
|
||||||
color="white"
|
color={
|
||||||
|
deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}`
|
||||||
|
? 'red'
|
||||||
|
: targetPath?.type === 'ArmBot'
|
||||||
|
? '#42a5f5'
|
||||||
|
: 'white'
|
||||||
|
}
|
||||||
lineWidth={4}
|
lineWidth={4}
|
||||||
dashed
|
dashed={(deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}`) ? false : true}
|
||||||
dashSize={0.75}
|
dashSize={0.75}
|
||||||
dashScale={20}
|
dashScale={20}
|
||||||
|
onPointerOver={() => setHoveredLineKey(`${point.uuid}-${target.pointUUID}-${index}`)}
|
||||||
|
onPointerOut={() => setHoveredLineKey(null)}
|
||||||
|
onClick={() => {
|
||||||
|
if (deleteTool) {
|
||||||
|
|
||||||
|
const connection1 = { model: path.modeluuid, point: point.uuid }
|
||||||
|
const connection2 = { model: target.modelUUID, point: target.pointUUID }
|
||||||
|
|
||||||
|
removeConnections(connection1, connection2)
|
||||||
|
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
userData={target}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -884,11 +1047,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
|
|
||||||
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
||||||
const heightFactor = Math.max(0.5, distance * 0.2);
|
const heightFactor = Math.max(0.5, distance * 0.2);
|
||||||
const midPoint = new THREE.Vector3(
|
const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2);
|
||||||
(fromWorldPosition.x + toWorldPosition.x) / 2,
|
|
||||||
Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor,
|
|
||||||
(fromWorldPosition.z + toWorldPosition.z) / 2
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QuadraticBezierLine
|
<QuadraticBezierLine
|
||||||
|
@ -897,11 +1056,27 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
start={fromWorldPosition.toArray()}
|
start={fromWorldPosition.toArray()}
|
||||||
end={toWorldPosition.toArray()}
|
end={toWorldPosition.toArray()}
|
||||||
mid={midPoint.toArray()}
|
mid={midPoint.toArray()}
|
||||||
color="orange"
|
color={
|
||||||
|
deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`
|
||||||
|
? 'red'
|
||||||
|
: 'orange'
|
||||||
|
}
|
||||||
lineWidth={4}
|
lineWidth={4}
|
||||||
dashed
|
dashed={(deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`) ? false : true}
|
||||||
dashSize={0.75}
|
dashSize={0.75}
|
||||||
dashScale={20}
|
dashScale={20}
|
||||||
|
onPointerOver={() => setHoveredLineKey(`${path.points.uuid}-${target.pointUUID}-${index}`)}
|
||||||
|
onPointerOut={() => setHoveredLineKey(null)}
|
||||||
|
onClick={() => {
|
||||||
|
if (deleteTool) {
|
||||||
|
|
||||||
|
const connection1 = { model: path.modeluuid, point: path.points.uuid }
|
||||||
|
const connection2 = { model: target.modelUUID, point: target.pointUUID }
|
||||||
|
|
||||||
|
removeConnections(connection1, connection2)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
userData={target}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -925,11 +1100,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
|
|
||||||
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
||||||
const heightFactor = Math.max(0.5, distance * 0.2);
|
const heightFactor = Math.max(0.5, distance * 0.2);
|
||||||
const midPoint = new THREE.Vector3(
|
const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2);
|
||||||
(fromWorldPosition.x + toWorldPosition.x) / 2,
|
|
||||||
Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor,
|
|
||||||
(fromWorldPosition.z + toWorldPosition.z) / 2
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QuadraticBezierLine
|
<QuadraticBezierLine
|
||||||
|
@ -938,11 +1109,28 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||||
start={fromWorldPosition.toArray()}
|
start={fromWorldPosition.toArray()}
|
||||||
end={toWorldPosition.toArray()}
|
end={toWorldPosition.toArray()}
|
||||||
mid={midPoint.toArray()}
|
mid={midPoint.toArray()}
|
||||||
color="#42a5f5"
|
color={
|
||||||
|
deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`
|
||||||
|
? 'red'
|
||||||
|
: '#42a5f5'
|
||||||
|
}
|
||||||
lineWidth={4}
|
lineWidth={4}
|
||||||
dashed
|
dashed={(deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`) ? false : true}
|
||||||
dashSize={0.75}
|
dashSize={0.75}
|
||||||
dashScale={20}
|
dashScale={20}
|
||||||
|
onPointerOver={() => setHoveredLineKey(`${path.points.uuid}-${target.pointUUID}-${index}`)}
|
||||||
|
onPointerOut={() => setHoveredLineKey(null)}
|
||||||
|
onClick={() => {
|
||||||
|
if (deleteTool) {
|
||||||
|
|
||||||
|
const connection1 = { model: path.modeluuid, point: path.points.uuid }
|
||||||
|
const connection2 = { model: target.modelUUID, point: target.pointUUID }
|
||||||
|
|
||||||
|
removeConnections(connection1, connection2)
|
||||||
|
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
userData={target}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +1,20 @@
|
||||||
|
import html2canvas from "html2canvas";
|
||||||
|
|
||||||
export const captureVisualization = async (): Promise<string | null> => {
|
export const captureVisualization = async (): Promise<string | null> => {
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
const container = document.getElementById("real-time-vis-canvas");
|
||||||
if (!container) return null;
|
if (!container) return null;
|
||||||
|
|
||||||
const canvas = document.createElement("canvas");
|
try {
|
||||||
const ctx = canvas.getContext("2d");
|
// Use html2canvas to capture the container
|
||||||
if (!ctx) return null;
|
const canvas = await html2canvas(container, {
|
||||||
|
scale: 1, // Adjust scale for higher/lower resolution
|
||||||
const rect = container.getBoundingClientRect();
|
|
||||||
canvas.width = rect.width;
|
|
||||||
canvas.height = rect.height;
|
|
||||||
|
|
||||||
// Draw background
|
|
||||||
ctx.fillStyle = getComputedStyle(container).backgroundColor;
|
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
||||||
|
|
||||||
// Capture all canvas elements
|
|
||||||
const canvases = container.querySelectorAll("canvas");
|
|
||||||
canvases.forEach((childCanvas) => {
|
|
||||||
const childRect = childCanvas.getBoundingClientRect();
|
|
||||||
const x = childRect.left - rect.left;
|
|
||||||
const y = childRect.top - rect.top;
|
|
||||||
ctx.drawImage(childCanvas, x, y, childRect.width, childRect.height);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Capture SVG elements
|
// Convert the canvas to a data URL (PNG format)
|
||||||
const svgs = container.querySelectorAll("svg");
|
const dataUrl = canvas.toDataURL("image/png");
|
||||||
for (const svg of Array.from(svgs)) {
|
return dataUrl;
|
||||||
const svgString = new XMLSerializer().serializeToString(svg);
|
} catch (error) {
|
||||||
const svgBlob = new Blob([svgString], { type: "image/svg+xml" });
|
console.error("Error capturing visualization:", error);
|
||||||
const url = URL.createObjectURL(svgBlob);
|
return null;
|
||||||
|
}
|
||||||
try {
|
|
||||||
const img = await new Promise<HTMLImageElement>((resolve, reject) => {
|
|
||||||
const image = new Image();
|
|
||||||
image.onload = () => resolve(image);
|
|
||||||
image.onerror = reject;
|
|
||||||
image.src = url;
|
|
||||||
});
|
|
||||||
|
|
||||||
const svgRect = svg.getBoundingClientRect();
|
|
||||||
ctx.drawImage(
|
|
||||||
img,
|
|
||||||
svgRect.left - rect.left,
|
|
||||||
svgRect.top - rect.top,
|
|
||||||
svgRect.width,
|
|
||||||
svgRect.height
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return canvas.toDataURL("image/png");
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,6 @@ export const handleSaveTemplate = async ({
|
||||||
try {
|
try {
|
||||||
// Check if the selected zone has any widgets
|
// Check if the selected zone has any widgets
|
||||||
if (!selectedZone.panelOrder || selectedZone.panelOrder.length === 0) {
|
if (!selectedZone.panelOrder || selectedZone.panelOrder.length === 0) {
|
||||||
console.warn("No widgets found in the selected zone.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +63,7 @@ export const handleSaveTemplate = async ({
|
||||||
floatingWidget,
|
floatingWidget,
|
||||||
widgets3D,
|
widgets3D,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('newTemplate: ', newTemplate);
|
|
||||||
// Extract organization from email
|
// Extract organization from email
|
||||||
const email = localStorage.getItem("email") || "";
|
const email = localStorage.getItem("email") || "";
|
||||||
const organization = email.includes("@")
|
const organization = email.includes("@")
|
||||||
|
@ -73,7 +71,6 @@ export const handleSaveTemplate = async ({
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
if (!organization) {
|
if (!organization) {
|
||||||
console.error("Organization could not be determined from email.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let saveTemplate = {
|
let saveTemplate = {
|
||||||
|
@ -88,13 +85,13 @@ export const handleSaveTemplate = async ({
|
||||||
try {
|
try {
|
||||||
addTemplate(newTemplate);
|
addTemplate(newTemplate);
|
||||||
// const response = await saveTemplateApi(organization, newTemplate);
|
// const response = await saveTemplateApi(organization, newTemplate);
|
||||||
// console.log("Save API Response:", response);
|
//
|
||||||
|
|
||||||
// Add template only if API call succeeds
|
// Add template only if API call succeeds
|
||||||
} catch (apiError) {
|
} catch (apiError) {
|
||||||
// console.error("Error saving template to API:", apiError);
|
//
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.error("Error in handleSaveTemplate:", error);
|
//
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -106,9 +106,9 @@ export const useMenuVisible = create<any>((set: any) => ({
|
||||||
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
|
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useDeleteModels = create<any>((set: any) => ({
|
export const useDeleteTool = create<any>((set: any) => ({
|
||||||
deleteModels: false,
|
deleteTool: false,
|
||||||
setDeleteModels: (x: any) => set(() => ({ deleteModels: x })),
|
setDeleteTool: (x: any) => set(() => ({ deleteTool: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useToolMode = create<any>((set: any) => ({
|
export const useToolMode = create<any>((set: any) => ({
|
||||||
|
@ -164,9 +164,9 @@ export const useSelectedWallItem = create<any>((set: any) => ({
|
||||||
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
|
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useselectedFloorItem = create<any>((set: any) => ({
|
export const useSelectedFloorItem = create<any>((set: any) => ({
|
||||||
selectedFloorItem: null,
|
selectedFloorItem: null,
|
||||||
setselectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
|
setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useDeletableFloorItem = create<any>((set: any) => ({
|
export const useDeletableFloorItem = create<any>((set: any) => ({
|
||||||
|
@ -446,3 +446,23 @@ export const useTileDistance = create<any>((set: any) => ({
|
||||||
planeValue: { ...state.planeValue, ...value },
|
planeValue: { ...state.planeValue, ...value },
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Define the Asset type
|
||||||
|
type Asset = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
position?: [number, number, number]; // Optional: 3D position
|
||||||
|
rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation
|
||||||
|
};
|
||||||
|
|
||||||
|
// Zustand store type
|
||||||
|
type ZoneAssetState = {
|
||||||
|
zoneAssetId: Asset | null;
|
||||||
|
setZoneAssetId: (asset: Asset | null) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Zustand store
|
||||||
|
export const useZoneAssetId = create<ZoneAssetState>((set) => ({
|
||||||
|
zoneAssetId: null,
|
||||||
|
setZoneAssetId: (asset) => set({ zoneAssetId: asset }),
|
||||||
|
}));
|
|
@ -12,7 +12,9 @@ type ZoneWidgetStore = {
|
||||||
zoneWidgetData: Record<string, WidgetData[]>;
|
zoneWidgetData: Record<string, WidgetData[]>;
|
||||||
setZoneWidgetData: (zoneId: string, widgets: WidgetData[]) => void;
|
setZoneWidgetData: (zoneId: string, widgets: WidgetData[]) => void;
|
||||||
addWidget: (zoneId: string, widget: WidgetData) => void;
|
addWidget: (zoneId: string, widget: WidgetData) => void;
|
||||||
|
tempWidget: (zoneId: string, widget: WidgetData) => void;
|
||||||
updateWidgetPosition: (zoneId: string, widgetId: string, newPosition: [number, number, number]) => void;
|
updateWidgetPosition: (zoneId: string, widgetId: string, newPosition: [number, number, number]) => void;
|
||||||
|
tempWidgetPosition: (zoneId: string, widgetId: string, newPosition: [number, number, number]) => void;
|
||||||
updateWidgetRotation: (zoneId: string, widgetId: string, newRotation: [number, number, number]) => void;
|
updateWidgetRotation: (zoneId: string, widgetId: string, newRotation: [number, number, number]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,6 +33,13 @@ export const useZoneWidgetStore = create<ZoneWidgetStore>((set) => ({
|
||||||
[zoneId]: [...(state.zoneWidgetData[zoneId] || []), { ...widget, rotation: widget.rotation || [0, 0, 0] }],
|
[zoneId]: [...(state.zoneWidgetData[zoneId] || []), { ...widget, rotation: widget.rotation || [0, 0, 0] }],
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
|
tempWidget: (zoneId: string, widget: WidgetData) =>
|
||||||
|
set((state: ZoneWidgetStore) => ({
|
||||||
|
zoneWidgetData: {
|
||||||
|
...state.zoneWidgetData,
|
||||||
|
[zoneId]: [...(state.zoneWidgetData[zoneId] || []), { ...widget, rotation: widget.rotation || [0, 0, 0] }],
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
|
||||||
updateWidgetPosition: (zoneId: string, widgetId: string, newPosition: [number, number, number]) =>
|
updateWidgetPosition: (zoneId: string, widgetId: string, newPosition: [number, number, number]) =>
|
||||||
set((state: ZoneWidgetStore) => {
|
set((state: ZoneWidgetStore) => {
|
||||||
|
@ -44,6 +53,18 @@ export const useZoneWidgetStore = create<ZoneWidgetStore>((set) => ({
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
tempWidgetPosition: (zoneId: string, widgetId: string, newPosition: [number, number, number]) =>
|
||||||
|
set((state: ZoneWidgetStore) => {
|
||||||
|
const widgets = state.zoneWidgetData[zoneId] || [];
|
||||||
|
return {
|
||||||
|
zoneWidgetData: {
|
||||||
|
...state.zoneWidgetData,
|
||||||
|
[zoneId]: widgets.map((widget: WidgetData) =>
|
||||||
|
widget.id === widgetId ? { ...widget, position: newPosition } : widget
|
||||||
|
),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
updateWidgetRotation: (zoneId: string, widgetId: string, newRotation: [number, number, number]) =>
|
updateWidgetRotation: (zoneId: string, widgetId: string, newRotation: [number, number, number]) =>
|
||||||
set((state: ZoneWidgetStore) => {
|
set((state: ZoneWidgetStore) => {
|
||||||
|
@ -59,13 +80,6 @@ export const useZoneWidgetStore = create<ZoneWidgetStore>((set) => ({
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// export type WidgetData = {
|
|
||||||
// id: string;
|
|
||||||
// type: string;
|
|
||||||
// position: [number, number, number];
|
|
||||||
// rotation?: [number, number, number];
|
|
||||||
// tempPosition?: [number, number, number];
|
|
||||||
// };
|
|
||||||
|
|
||||||
interface RightClickStore {
|
interface RightClickStore {
|
||||||
rightClickSelected: string | null;
|
rightClickSelected: string | null;
|
||||||
|
|
|
@ -81,9 +81,12 @@
|
||||||
|
|
||||||
.returnOfInvestment {
|
.returnOfInvestment {
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
min-width: 150px;
|
||||||
|
|
||||||
.charts {
|
.charts {
|
||||||
|
width: 100%;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
|
min-width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.returns-wrapper {
|
.returns-wrapper {
|
||||||
|
@ -126,6 +129,12 @@
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
border-radius: 5.2px;
|
border-radius: 5.2px;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
font-size: $small;
|
font-size: $small;
|
||||||
text-align: start;
|
text-align: start;
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
max-width: calc(100% - 500px);
|
max-width: calc(100% - 500px);
|
||||||
|
min-width: 150px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
transform: translate(-50%, -0%);
|
transform: translate(-50%, -0%);
|
||||||
|
|
||||||
|
@ -364,6 +365,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel.hidePanel {
|
.panel.hidePanel {
|
||||||
|
pointer-events: none;
|
||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -750,7 +752,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.activeChart {
|
.activeChart {
|
||||||
outline: 1px solid var(--accent-color);
|
outline: 2px solid var(--accent-color);
|
||||||
z-index: 2 !important;
|
z-index: 2 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,3 +21,7 @@
|
||||||
box-shadow: var(--box-shadow-light);
|
box-shadow: var(--box-shadow-light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pointer-none{
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
|
@ -324,7 +324,7 @@ interface StaticMachineEventsSchema {
|
||||||
points: {
|
points: {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
actions: { uuid: string; name: string; buffer: number | string; material: string; isUsed: boolean };
|
actions: { uuid: string; name: string; buffer: number; material: string; };
|
||||||
triggers: { uuid: string; name: string; type: string };
|
triggers: { uuid: string; name: string; type: string };
|
||||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||||
};
|
};
|
||||||
|
@ -375,5 +375,23 @@ export type EventData = {
|
||||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||||
speed: number;
|
speed: number;
|
||||||
};
|
};
|
||||||
|
} | {
|
||||||
|
type: 'StaticMachine';
|
||||||
|
points: {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
actions: { uuid: string; name: string; buffer: number; material: string; };
|
||||||
|
triggers: { uuid: string; name: string; type: string };
|
||||||
|
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||||
|
};
|
||||||
|
} | {
|
||||||
|
type: 'ArmBot';
|
||||||
|
points: {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[] };
|
||||||
|
triggers: { uuid: string; name: string; type: string };
|
||||||
|
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue