resolved bug in finding distance and some changes in marketplace

This commit is contained in:
Poovizhi99 2025-05-13 16:57:55 +05:30
parent 8848d78c3b
commit 890fdc889f
11 changed files with 391 additions and 413 deletions

View File

@ -9,6 +9,7 @@ REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
# Base URL for the server marketplace, used for market place model blob. # Base URL for the server marketplace, used for market place model blob.
REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011 REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
# REACT_APP_SERVER_MARKETPLACE_URL=192.168.0.110:3501
# Base URL for the asset library server, used for asset library images and model blob id. # Base URL for the asset library server, used for asset library images and model blob id.
REACT_APP_SERVER_ASSET_LIBRARY_URL=185.100.212.76:50011 REACT_APP_SERVER_ASSET_LIBRARY_URL=185.100.212.76:50011

View File

@ -14,11 +14,14 @@ interface SelectedCard {
rating: number; rating: number;
views: number; views: number;
description: string; description: string;
AssetID: string
} }
// Define the props type for AssetPreview // Define the props type for AssetPreview
interface AssetPreviewProps { interface AssetPreviewProps {
selectedCard: SelectedCard; selectedCard: SelectedCard;
modelUrl: string;
setSelectedCard: React.Dispatch<React.SetStateAction<SelectedCard | null>>; // Type for setter function setSelectedCard: React.Dispatch<React.SetStateAction<SelectedCard | null>>; // Type for setter function
} }
@ -33,8 +36,10 @@ function Ui() {
const AssetPreview: React.FC<AssetPreviewProps> = ({ const AssetPreview: React.FC<AssetPreviewProps> = ({
selectedCard, selectedCard,
setSelectedCard, setSelectedCard,
modelUrl
}) => { }) => {
// Ensure rating is a valid number between 0 and 5 // Ensure rating is a valid number between 0 and 5
console.log('modelUrl: ', modelUrl);
const rating = Math.max( const rating = Math.max(
0, 0,
Math.min(5, isNaN(selectedCard.rating) ? 0 : selectedCard.rating) Math.min(5, isNaN(selectedCard.rating) ? 0 : selectedCard.rating)
@ -63,8 +68,8 @@ const AssetPreview: React.FC<AssetPreviewProps> = ({
}} }}
> >
<Suspense fallback={<Ui />}> <Suspense fallback={<Ui />}>
{selectedCard.assetName && ( {selectedCard.assetName && modelUrl && (
<GltfLoader fromServer={selectedCard.assetName} /> <GltfLoader fromServer={modelUrl} assetId={selectedCard?.AssetID} />
)} )}
<OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} /> <OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} />
<ContactShadows <ContactShadows

View File

@ -19,6 +19,8 @@ interface CardProps {
views: number; views: number;
image: string; image: string;
description: string; description: string;
AssetID: string
modelUrl: string
onSelectCard: (cardData: { onSelectCard: (cardData: {
assetName: string; assetName: string;
uploadedOn: number; uploadedOn: number;
@ -26,6 +28,8 @@ interface CardProps {
rating: number; rating: number;
views: number; views: number;
description: string; description: string;
AssetID: string;
}) => void; }) => void;
} }
@ -37,10 +41,18 @@ const Card: React.FC<CardProps> = ({
views, views,
image, image,
description, description,
AssetID,
modelUrl,
onSelectCard, onSelectCard,
}) => { }) => {
const handleCardSelect = () => { const handleCardSelect = () => {
onSelectCard({ assetName, uploadedOn, price, rating, views, description }); console.log('assetName: ', assetName);
console.log('AssetID: ', AssetID);
onSelectCard({
assetName, uploadedOn, price, rating, views, description, AssetID
});
}; };
return ( return (

View File

@ -1,6 +1,8 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Card from "./Card"; import Card from "./Card";
import AssetPreview from "./AssetPreview"; import AssetPreview from "./AssetPreview";
import { getAssetDetails } from "../../services/marketplace/fetchAssetDetails";
import { fetchGltfUrl } from "../../services/marketplace/fetchGltfUrl";
interface ModelData { interface ModelData {
CreatedBy: string; CreatedBy: string;
@ -15,6 +17,7 @@ interface ModelData {
uploadDate: number; uploadDate: number;
_id: string; _id: string;
price: number; price: number;
AssetID: string
} }
interface ModelsProps { interface ModelsProps {
models: ModelData[]; models: ModelData[];
@ -28,19 +31,26 @@ const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
rating: number; rating: number;
views: number; views: number;
description: string; description: string;
AssetID: string;
} | null>(null); } | null>(null);
const [modelUrl, setModelUrl] = useState<string>("")
const handleCardSelect = (cardData: { const handleCardSelect = async (cardData: {
assetName: string; assetName: string;
uploadedOn: number; uploadedOn: number;
price: number; price: number;
rating: number; rating: number;
views: number; views: number;
description: string; description: string;
AssetID: string
}) => { }) => {
setSelectedCard(cardData); setSelectedCard(cardData);
const res = await fetchGltfUrl(cardData.assetName, cardData.AssetID);
console.log('res: ', res);
setModelUrl(res.url)
}; };
return ( return (
<div className="cards-container-wrapper"> <div className="cards-container-wrapper">
<div className="cards-container-container"> <div className="cards-container-container">
@ -57,7 +67,9 @@ const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
views={800} views={800}
onSelectCard={handleCardSelect} onSelectCard={handleCardSelect}
image={assetDetail.thumbnail} image={assetDetail.thumbnail}
AssetID={assetDetail?.AssetID}
description={assetDetail.description} description={assetDetail.description}
modelUrl={modelUrl}
/> />
))} ))}
{/* <RenderOverlay> */} {/* <RenderOverlay> */}
@ -65,6 +77,7 @@ const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
<AssetPreview <AssetPreview
selectedCard={selectedCard} selectedCard={selectedCard}
setSelectedCard={setSelectedCard} setSelectedCard={setSelectedCard}
modelUrl={modelUrl}
/> />
)} )}
{/* </RenderOverlay> */} {/* </RenderOverlay> */}

View File

@ -16,6 +16,7 @@ interface ModelData {
uploadDate: number; uploadDate: number;
_id: string; _id: string;
price: number; price: number;
AssetID: string
} }
interface ModelsProps { interface ModelsProps {

View File

@ -11,6 +11,7 @@ interface GltfLoaderProps {
setAnimations?: (animations?: string[]) => void; setAnimations?: (animations?: string[]) => void;
selectedAnimation?: string; selectedAnimation?: string;
setSelectedAnimation?: (animation: string) => void; setSelectedAnimation?: (animation: string) => void;
assetId: string
} }
// const getGLTFUrl = (url: string) => url; // Placeholder for your actual function // const getGLTFUrl = (url: string) => url; // Placeholder for your actual function
@ -20,9 +21,10 @@ const GltfLoader: React.FC<GltfLoaderProps> = ({
fromServer, fromServer,
setAnimations, setAnimations,
selectedAnimation, selectedAnimation,
assetId
}) => { }) => {
const modelUrl: any = fromServer ? fetchGltfUrl(fromServer) : glbdata; // const modelUrl: any = fromServer ? fetchGltfUrl(fromServer, assetId) : glbdata;
const { scene, animations } = useGLTF(modelUrl ?? "") as { const { scene, animations } = useGLTF(fromServer ?? "") as {
scene: Object3D; scene: Object3D;
animations: THREE.AnimationClip[]; animations: THREE.AnimationClip[];
}; };

View File

@ -17,6 +17,7 @@ interface ModelData {
uploadDate: number; uploadDate: number;
_id: string; _id: string;
price: number; price: number;
AssetID: string
} }
const MarketPlace = () => { const MarketPlace = () => {
const [models, setModels] = useState<ModelData[]>([]); const [models, setModels] = useState<ModelData[]>([]);
@ -33,6 +34,7 @@ const MarketPlace = () => {
try { try {
const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6"); const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6");
setModels(filt.items); setModels(filt.items);
console.log('filt.items: ', filt.items);
setFilteredModels(filt.items); setFilteredModels(filt.items);
setisLoading(false); setisLoading(false);
} catch { } catch {

View File

@ -1,270 +1,339 @@
import React, { useRef } from "react"; import React, { useRef, useState } from "react";
import { import {
Vector3, Vector3,
Raycaster, Raycaster,
BufferGeometry, BufferGeometry,
LineBasicMaterial, LineBasicMaterial,
Line, Line,
Mesh, Mesh,
Group, Group,
} from "three"; } from "three";
import { useThree, useFrame } from "@react-three/fiber"; import { useThree, useFrame } from "@react-three/fiber";
import { Html } from "@react-three/drei"; import { Html } from "@react-three/drei";
interface DistanceFindingControlsProps { interface DistanceFindingControlsProps {
boundingBoxRef: React.RefObject<Mesh>; boundingBoxRef: React.RefObject<Mesh>;
object: number; object: number;
} }
const DistanceFindingControls = ({ const DistanceFindingControls = ({
boundingBoxRef, boundingBoxRef,
object, object,
}: DistanceFindingControlsProps) => { }: DistanceFindingControlsProps) => {
const { camera, scene } = useThree(); const { camera, scene } = useThree();
const [labelValues, setLabelValues] = useState<{
textPosX: any;
textNegX: any;
textPosZ: any;
textNegZ: any;
}>({
textPosX: "",
textNegX: "",
textPosZ: "",
textNegZ: "",
});
// Refs for measurement lines // Refs for measurement lines
const line1 = useRef<Line>(null); const line1 = useRef<Line>(null);
const line2 = useRef<Line>(null); const line2 = useRef<Line>(null);
const line3 = useRef<Line>(null); const line3 = useRef<Line>(null);
const line4 = useRef<Line>(null); const line4 = useRef<Line>(null);
const line5 = useRef<Line>(null); const line5 = useRef<Line>(null);
// Refs for measurement text labels // Refs for measurement text labels
const textPosX = useRef<Group>(null); const textPosX = useRef<Group>(null);
const textNegX = useRef<Group>(null); const textNegX = useRef<Group>(null);
const textPosZ = useRef<Group>(null); const textPosZ = useRef<Group>(null);
const textNegZ = useRef<Group>(null); const textNegZ = useRef<Group>(null);
const textPosY = useRef<Group>(null); const textPosY = useRef<Group>(null);
// Store line geometries to avoid recreation // Store line geometries to avoid recreation
const lineGeometries = useRef({ const lineGeometries = useRef({
posX: new BufferGeometry(), posX: new BufferGeometry(),
negX: new BufferGeometry(), negX: new BufferGeometry(),
posZ: new BufferGeometry(), posZ: new BufferGeometry(),
negZ: new BufferGeometry(), negZ: new BufferGeometry(),
posY: new BufferGeometry(), posY: new BufferGeometry(),
}); });
useFrame(() => { useFrame(() => {
if (!boundingBoxRef?.current) return; if (!boundingBoxRef?.current) return;
boundingBoxRef.current.geometry.computeBoundingBox(); boundingBoxRef.current.geometry.computeBoundingBox();
const bbox = boundingBoxRef.current.geometry.boundingBox; const bbox = boundingBoxRef.current.geometry.boundingBox;
if (!bbox) return; if (!bbox) return;
const size = { const size = {
x: bbox.max.x - bbox.min.x, x: bbox.max.x - bbox.min.x,
y: bbox.max.y - bbox.min.y, y: bbox.max.y - bbox.min.y,
z: bbox.max.z - bbox.min.z, z: bbox.max.z - bbox.min.z,
};
const vec = boundingBoxRef.current?.getWorldPosition(new Vector3()).clone();
if (!vec) return;
updateLine({
line: line1.current,
geometry: lineGeometries.current.posX,
direction: new Vector3(1, 0, 0), // Positive X
angle: "pos",
mesh: textPosX,
vec,
size,
});
updateLine({
line: line2.current,
geometry: lineGeometries.current.negX,
direction: new Vector3(-1, 0, 0), // Negative X
angle: "neg",
mesh: textNegX,
vec,
size,
});
updateLine({
line: line3.current,
geometry: lineGeometries.current.posZ,
direction: new Vector3(0, 0, 1), // Positive Z
angle: "pos",
mesh: textPosZ,
vec,
size,
});
updateLine({
line: line4.current,
geometry: lineGeometries.current.negZ,
direction: new Vector3(0, 0, -1), // Negative Z
angle: "neg",
mesh: textNegZ,
vec,
size,
});
updateLine({
line: line5.current,
geometry: lineGeometries.current.posY,
direction: new Vector3(0, -1, 0), // Down (Y)
angle: "posY",
mesh: textPosY,
vec,
size,
});
});
const updateLine = ({
line,
geometry,
direction,
angle,
mesh,
vec,
size,
}: {
line: Line | null;
geometry: BufferGeometry;
direction: Vector3;
angle: string;
mesh: React.RefObject<Group>;
vec: Vector3;
size: { x: number; y: number; z: number };
}) => {
if (!line) return;
const points = [];
if (angle === "pos") {
points[0] = new Vector3(vec.x, vec.y, vec.z).add(
new Vector3((direction.x * size.x) / 2, 0, (direction.z * size.z) / 2)
);
} else if (angle === "neg") {
points[0] = new Vector3(vec.x, vec.y, vec.z).sub(
new Vector3((-direction.x * size.x) / 2, 0, (-direction.z * size.z) / 2)
);
} else if (angle === "posY") {
points[0] = new Vector3(vec.x, vec.y, vec.z).sub(
new Vector3(0, size.y / 2, 0)
);
}
const ray = new Raycaster();
if (camera) ray.camera = camera;
ray.set(new Vector3(vec.x, vec.y, vec.z), direction);
ray.params.Line.threshold = 0.1;
// Find intersection points
const wallsGroup = scene.children.find((val) =>
val?.name.includes("Walls")
);
const intersects = wallsGroup
? ray.intersectObjects([wallsGroup], true)
: [];
// Find intersection point
if (intersects[0]) {
for (const intersect of intersects) {
if (intersect.object.name.includes("Wall")) {
points[1] =
angle !== "posY" ? intersect.point : new Vector3(vec.x, 0, vec.z); // Floor
break;
}
}
}
// Update line geometry
if (points[1]) {
geometry.dispose();
geometry.setFromPoints([points[0], points[1]]);
line.geometry = geometry;
// Update measurement text
if (mesh?.current) {
geometry.computeBoundingSphere();
const center = geometry.boundingSphere?.center;
if (center) {
mesh.current.position.copy(center);
}
const label = document.getElementById(mesh.current.name);
if (label) {
label.innerText = `${points[0].distanceTo(points[1]).toFixed(2)}m`;
}
}
} else {
// No intersection found - clear the line
geometry.dispose();
geometry.setFromPoints([new Vector3(), new Vector3()]);
line.geometry = geometry;
const label = document.getElementById(mesh?.current?.name ?? "");
if (label) label.innerText = "";
}
}; };
const Material = new LineBasicMaterial({ color: "#d2baff" }); const vec = boundingBoxRef.current?.getWorldPosition(new Vector3()).clone();
return ( if (!vec) return;
<> updateLine({
{/* Measurement text labels */} line: line1.current,
{boundingBoxRef.current && object > 0 && ( geometry: lineGeometries.current.posX,
<> direction: new Vector3(1, 0, 0), // Positive X
<group name="textPosX" ref={textPosX}> angle: "pos",
<Html mesh: textPosX,
wrapperClass="distance-text-wrapper" vec,
className="distance-text" size,
zIndexRange={[1, 0]} });
style={{ pointerEvents: "none" }} updateLine({
> line: line2.current,
<div className="distance-label" id="textPosX"></div> geometry: lineGeometries.current.negX,
</Html> direction: new Vector3(-1, 0, 0), // Negative X
</group> angle: "neg",
<group name="textNegX" ref={textNegX}> mesh: textNegX,
<Html vec,
wrapperClass="distance-text-wrapper" size,
className="distance-text" });
zIndexRange={[1, 0]} updateLine({
style={{ pointerEvents: "none" }} line: line3.current,
> geometry: lineGeometries.current.posZ,
<div className="distance-label" id="textNegX"></div> direction: new Vector3(0, 0, 1), // Positive Z
</Html> angle: "pos",
</group> mesh: textPosZ,
<group name="textPosZ" ref={textPosZ}> vec,
<Html size,
wrapperClass="distance-text-wrapper" });
className="distance-text" updateLine({
zIndexRange={[2, 0]} line: line4.current,
style={{ pointerEvents: "none" }} geometry: lineGeometries.current.negZ,
> direction: new Vector3(0, 0, -1), // Negative Z
<div className="distance-label" id="textPosZ"></div> angle: "neg",
</Html> mesh: textNegZ,
</group> vec,
<group name="textNegZ" ref={textNegZ}> size,
<Html });
wrapperClass="distance-text-wrapper" updateLine({
className="distance-text" line: line5.current,
zIndexRange={[1, 0]} geometry: lineGeometries.current.posY,
style={{ pointerEvents: "none" }} direction: new Vector3(0, -1, 0), // Down (Y)
> angle: "posY",
<div className="distance-label" id="textNegZ"></div> mesh: textPosY,
</Html> vec,
</group> size,
});
});
{/* Measurement lines */} const updateLine = ({
<primitive line,
object={new Line(new BufferGeometry(), Material)} geometry,
ref={line1} direction,
/> angle,
<primitive mesh,
object={new Line(new BufferGeometry(), Material)} vec,
ref={line2} size,
/> }: {
<primitive line: Line | null;
object={new Line(new BufferGeometry(), Material)} geometry: BufferGeometry;
ref={line3} direction: Vector3;
/> angle: string;
<primitive mesh: React.RefObject<Group>;
object={new Line(new BufferGeometry(), Material)} vec: Vector3;
ref={line4} size: { x: number; y: number; z: number };
/> }) => {
</> if (!line) return;
)}
</> const points = [];
if (angle === "pos") {
points[0] = new Vector3(vec.x, vec.y, vec.z).add(
new Vector3((direction.x * size.x) / 2, 0, (direction.z * size.z) / 2)
);
} else if (angle === "neg") {
points[0] = new Vector3(vec.x, vec.y, vec.z).sub(
new Vector3((-direction.x * size.x) / 2, 0, (-direction.z * size.z) / 2)
);
} else if (angle === "posY") {
points[0] = new Vector3(vec.x, vec.y, vec.z).sub(
new Vector3(0, size.y / 2, 0)
);
}
const ray = new Raycaster();
if (camera) ray.camera = camera;
ray.set(new Vector3(vec.x, vec.y, vec.z), direction);
ray.params.Line.threshold = 0.1;
// Find intersection points
const wallsGroup = scene.children.find((val) =>
val?.name.includes("Walls")
); );
const intersects = wallsGroup
? ray.intersectObjects([wallsGroup], true)
: [];
// Find intersection point
if (intersects[0]) {
for (const intersect of intersects) {
if (intersect.object.name.includes("Wall")) {
points[1] =
angle !== "posY" ? intersect.point : new Vector3(vec.x, 0, vec.z); // Floor
break;
}
}
}
if (points[1]) {
geometry.dispose();
geometry.setFromPoints([points[0], points[1]]);
line.geometry = geometry;
// Calculate the distance only once
const distance = points[0].distanceTo(points[1]).toFixed(2);
// Update measurement text
if (mesh?.current) {
geometry.computeBoundingSphere();
const center = geometry.boundingSphere?.center;
if (center) {
mesh.current.position.copy(center);
}
const label = document.getElementById(mesh.current.name);
if (label) {
label.innerText = `${distance}m`;
// Update specific label state based on the label ID
switch (label.id) {
case "textPosX":
setLabelValues((prevState) => ({ ...prevState, textPosX: distance }));
break;
case "textNegX":
setLabelValues((prevState) => ({ ...prevState, textNegX: distance }));
break;
case "textPosZ":
setLabelValues((prevState) => ({ ...prevState, textPosZ: distance }));
break;
case "textNegZ":
setLabelValues((prevState) => ({ ...prevState, textNegZ: distance }));
break;
default:
break;
}
}
}
} else {
// No intersection found - clear the line
geometry.dispose();
geometry.setFromPoints([new Vector3(), new Vector3()]);
line.geometry = geometry;
const label = document.getElementById(mesh?.current?.name ?? "");
if (label) {
label.innerText = "";
// Clear the corresponding label value in the state
switch (label.id) {
case "textPosX":
setLabelValues((prevState) => ({ ...prevState, textPosX: "" }));
break;
case "textNegX":
setLabelValues((prevState) => ({ ...prevState, textNegX: "" }));
break;
case "textPosZ":
setLabelValues((prevState) => ({ ...prevState, textPosZ: "" }));
break;
case "textNegZ":
setLabelValues((prevState) => ({ ...prevState, textNegZ: "" }));
break;
default:
break;
}
}
}
};
const Material = new LineBasicMaterial({ color: "#d2baff" });
return (
<>
{/* Measurement text labels */}
{boundingBoxRef.current && object > 0 && (
<>
<group name="textPosX" ref={textPosX}>
<Html
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[1, 0]}
style={{
pointerEvents: "none",
visibility: labelValues.textPosX === "" ? "hidden" : "visible",
}}
>
<div className="distance-label" id="textPosX">{labelValues.textPosX}</div>
</Html>
</group>
<group name="textNegX" ref={textNegX}>
<Html
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[1, 0]}
style={{
pointerEvents: "none",
visibility: labelValues.textNegX === "" ? "hidden" : "visible",
}}
>
<div className="distance-label" id="textNegX">{labelValues.textNegX}</div>
</Html>
</group>
<group name="textPosZ" ref={textPosZ}>
<Html
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[2, 0]}
style={{
pointerEvents: "none",
visibility: labelValues.textPosZ === "" ? "hidden" : "visible",
}}
>
<div className="distance-label" id="textPosZ">{labelValues.textPosZ}</div>
</Html>
</group>
<group name="textNegZ" ref={textNegZ}>
<Html
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[1, 0]}
style={{
pointerEvents: "none",
visibility: labelValues.textNegZ === "" ? "hidden" : "visible",
}}
>
<div className="distance-label" id="textNegZ">{labelValues.textNegZ}</div>
</Html>
</group>
{/* Measurement lines */}
<primitive
object={new Line(new BufferGeometry(), Material)}
ref={line1}
/>
<primitive
object={new Line(new BufferGeometry(), Material)}
ref={line2}
/>
<primitive
object={new Line(new BufferGeometry(), Material)}
ref={line3}
/>
<primitive
object={new Line(new BufferGeometry(), Material)}
ref={line4}
/>
</>
)
}
</>
);
}; };
export default DistanceFindingControls; export default DistanceFindingControls;

View File

@ -11,7 +11,10 @@ import { useProductStore } from '../../../../../store/simulation/useProductStore
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler'; import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import MaterialAnimator from '../animator/materialAnimator'; import MaterialAnimator from '../animator/materialAnimator';
type Timer = {
start: number | null;
active: boolean;
};
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) { function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
const { navMesh } = useNavMesh(); const { navMesh } = useNavMesh();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
@ -20,20 +23,16 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const { triggerPointActions } = useTriggerHandler(); const { triggerPointActions } = useTriggerHandler();
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore(); const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct(); const { selectedProduct } = useSelectedProduct();
const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial, incrementIdleTime, incrementActiveTime } = useVehicleStore(); const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial } = useVehicleStore();
const [currentPhase, setCurrentPhase] = useState<string>('stationed'); const [currentPhase, setCurrentPhase] = useState<string>('stationed');
const [path, setPath] = useState<[number, number, number][]>([]); const [path, setPath] = useState<[number, number, number][]>([]);
const pauseTimeRef = useRef<number | null>(null); const pauseTimeRef = useRef<number | null>(null);
const idleTimeRef = useRef<number>(0);
const activeTimeRef = useRef<number>(0);
const isPausedRef = useRef<boolean>(false); const isPausedRef = useRef<boolean>(false);
let startTime: number; let startTime: number;
let fixedInterval: number; let fixedInterval: number;
const { speed } = useAnimationPlaySpeed(); const { speed } = useAnimationPlaySpeed();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
useEffect(() => { useEffect(() => {
isPausedRef.current = isPaused; isPausedRef.current = isPaused;
}, [isPaused]); }, [isPaused]);
@ -55,7 +54,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
); );
function vehicleStatus(modelId: string, status: string) { function vehicleStatus(modelId: string, status: string) {
// console.log(`${modelId} , ${status}`); //
} }
// Function to reset everything // Function to reset everything
@ -121,157 +120,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [vehicles, currentPhase, path, isPlaying]); }, [vehicles, currentPhase, path, isPlaying]);
const previousTimeRef = useRef<number | null>(null); // Tracks the last frame time
const isActiveRef = useRef(agvDetail.isActive); // Tracks the previous isActive state
const animationFrameIdRef = useRef<number | null>(null); // Tracks the animation frame ID
// // Animate function (moved outside useEffect)
// function animate(currentTime: number) {
// if (previousTimeRef.current === null) {
// // Initialize previousTime on the first frame
// previousTimeRef.current = currentTime;
// }
// const deltaTime = (currentTime - previousTimeRef.current) / 1000; // Time difference in seconds
// previousTimeRef.current = currentTime;
// if (idleTimeRef.current == 0) {
// activeTimeRef.current += deltaTime * speed; // Scale active time by speed
// const roundedActiveTime = Math.round(activeTimeRef.current); // Round to nearest integer
// console.log('Active Time:', roundedActiveTime, 'seconds');
// incrementActiveTime(agvDetail.modelUuid, roundedActiveTime);
// incrementIdleTime(agvDetail.modelUuid, 0);
// } else if (activeTimeRef.current = 0) {
// idleTimeRef.current += deltaTime * speed; // Scale idle time by speed
// const roundedIdleTime = Math.round(idleTimeRef.current); // Round to nearest integer
// console.log('Idle Time:', roundedIdleTime, 'seconds');
// incrementIdleTime(agvDetail.modelUuid, roundedIdleTime);
// incrementActiveTime(agvDetail.modelUuid, 0);
// }
// // Request the next animation frame
// animationFrameIdRef.current = requestAnimationFrame(animate);
// }
// useEffect(() => {
// // Reset timers when transitioning between states
// if (!agvDetail.isActive) {
// activeTimeRef.current = 0;
// } else {
// idleTimeRef.current = 0;
// }
// if (animationFrameIdRef.current === null) {
// animationFrameIdRef.current = requestAnimationFrame(animate);
// }
// console.log("veh", vehicles);
// // Cleanup function to stop the animation loop
// return () => {
// if (animationFrameIdRef.current !== null) {
// cancelAnimationFrame(animationFrameIdRef.current);
// animationFrameIdRef.current = null; // Reset the animation frame ID
// }
// };
// }, [agvDetail.isActive]);
// Animate function (moved outside useEffect)
function animate(currentTime: number) {
if (previousTimeRef.current === null) {
// Initialize previousTime on the first frame
previousTimeRef.current = currentTime;
}
const deltaTime = (currentTime - previousTimeRef.current) / 1000; // Time difference in seconds
previousTimeRef.current = currentTime;
if (agvDetail.isActive) {
// AGV is active: Increment active time
activeTimeRef.current += deltaTime * speed; // Scale active time by speed
const roundedActiveTime = Math.round(activeTimeRef.current); // Round to nearest integer
} else {
idleTimeRef.current += deltaTime * speed; // Scale idle time by speed
const roundedIdleTime = Math.round(idleTimeRef.current); // Round to nearest integer
}
// Request the next animation frame
animationFrameIdRef.current = requestAnimationFrame(animate);
}
useEffect(() => {
// Start or stop the animation based on the isActive state
if (!agvDetail.isActive) {
// Transitioning to idle: Reset idle time
const roundedIdleTime = Math.round(idleTimeRef.current); // Get the final rounded idle time
console.log('Final Idle Time:', roundedIdleTime, 'seconds');
incrementIdleTime(agvDetail.modelUuid, roundedIdleTime);
activeTimeRef.current = 0;
} else {
// Transitioning to active: Finalize idle time and pass it to incrementIdleTime
const roundedActiveTime = Math.round(activeTimeRef.current); // Round to nearest integer
console.log('Active Time:', roundedActiveTime, 'seconds');
incrementActiveTime(agvDetail.modelUuid, roundedActiveTime);
idleTimeRef.current = 0; // Reset idle time
}
// Start the animation loop if not already running
if (animationFrameIdRef.current === null) {
animationFrameIdRef.current = requestAnimationFrame(animate);
}
// Cleanup function to stop the animation loop
return () => {
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null; // Reset the animation frame ID
}
};
}, [agvDetail.isActive]);
// let position = 0;
// let previousTime: number;
// function animate(currentTime: number) {
// previousTime = performance.now();
// const deltaTime = (currentTime - previousTime) / 1000;
// previousTime = currentTime;
// position += speed * deltaTime;
// console.log('deltaTime: ', deltaTime);
// console.log('position: ', position);
// if (idleTimeRef.current === 0) {
// activeTimeRef.current = position;
// console.log('position: active', position);
// console.log(' activeTimeRef.current: ', activeTimeRef.current);
// incrementActiveTime(agvDetail.modelUuid, position)
// incrementIdleTime(agvDetail.modelUuid, idleTimeRef.current)
// }
// else if (activeTimeRef.current === 0) {
// idleTimeRef.current = position;
// console.log('position:idle ', position);
// console.log(' idleTimeRef.current: ', idleTimeRef.current);
// incrementActiveTime(agvDetail.modelUuid, activeTimeRef.current)
// incrementIdleTime(agvDetail.modelUuid, position)
// }
// }
// useEffect(() => {
// if (agvDetail.isActive) {
// idleTimeRef.current = 0;
// activeTimeRef.current = performance.now();
// requestAnimationFrame(animate);
// } else {
// activeTimeRef.current = 0;
// idleTimeRef.current = performance.now();
// requestAnimationFrame(animate);
// }
// console.log('vehicles: ', vehicles);
// }, [agvDetail.isActive]);
function handleCallBack() { function handleCallBack() {
if (currentPhase === 'stationed-pickup') { if (currentPhase === 'stationed-pickup') {
@ -299,6 +147,9 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
} }
} }
function startUnloadingProcess() { function startUnloadingProcess() {
if (agvDetail.point.action.triggers.length > 0) { if (agvDetail.point.action.triggers.length > 0) {
const trigger = getTriggerByUuid(selectedProduct.productId, agvDetail.point.action.triggers[0].triggerUuid); const trigger = getTriggerByUuid(selectedProduct.productId, agvDetail.point.action.triggers[0].triggerUuid);

View File

@ -1,5 +1,6 @@
let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
export const getAssetDetails = async (filename: string) => { export const getAssetDetails = async (filename: string) => {
console.log('filename: ', filename);
try { try {
const response = await fetch(`${BackEnd_url}/api/v1/assetDetails`, { const response = await fetch(`${BackEnd_url}/api/v1/assetDetails`, {
method: "POST", method: "POST",

View File

@ -1,7 +1,28 @@
let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
export const fetchGltfUrl = (filename: string) => {
if (filename) { export const fetchGltfUrl = async (filename: string, AssetID: string) => {
return `${BackEnd_url}/api/v1/getAssetFile/${filename}`; try {
const response = await fetch(
`${BackEnd_url}/api/v2/assetDetails/${filename}/${AssetID}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
// body: JSON.stringify(assetData),
}
);
if (!response.ok) {
throw new Error("Failed to fetch asset details");
}
const result = await response.json();
// console.log("result: preview", result);
return result;
} catch (error: any) {
//
throw new Error(error.message);
} }
return null; // or handle the case when filename is not provided
}; };