Refactor Simulations, RenameTooltip, EditWidgetOption, and RoboticArmAnimator components: streamline imports, enhance UI elements, and improve event handling logic.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
AddIcon,
|
AddIcon,
|
||||||
ArrowIcon,
|
ArrowIcon,
|
||||||
@@ -39,19 +39,30 @@ const List: React.FC<ListProps> = ({ val }) => {
|
|||||||
|
|
||||||
const Simulations: React.FC = () => {
|
const Simulations: React.FC = () => {
|
||||||
const productsContainerRef = useRef<HTMLDivElement>(null);
|
const productsContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const { products, addProduct, removeProduct, renameProduct, addEvent, removeEvent, } = useProductStore();
|
const {
|
||||||
|
products,
|
||||||
|
addProduct,
|
||||||
|
removeProduct,
|
||||||
|
renameProduct,
|
||||||
|
addEvent,
|
||||||
|
removeEvent,
|
||||||
|
} = useProductStore();
|
||||||
const { selectedProduct, setSelectedProduct } = useSelectedProduct();
|
const { selectedProduct, setSelectedProduct } = useSelectedProduct();
|
||||||
const { getEventByModelUuid } = useEventsStore();
|
const { getEventByModelUuid } = useEventsStore();
|
||||||
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
|
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
|
||||||
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 [openObjects, setOpenObjects] = useState(true);
|
const [openObjects, setOpenObjects] = useState(true);
|
||||||
|
|
||||||
const handleAddProduct = () => {
|
const handleAddProduct = () => {
|
||||||
const id = generateUUID();
|
const id = generateUUID();
|
||||||
const name = `Product ${products.length + 1}`;
|
const name = `Product ${products.length + 1}`;
|
||||||
addProduct(name, id);
|
addProduct(name, id);
|
||||||
upsertProductOrEventApi({ productName: name, productId: id, organization: organization });
|
upsertProductOrEventApi({
|
||||||
|
productName: name,
|
||||||
|
productId: id,
|
||||||
|
organization: organization,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveProduct = (productId: string) => {
|
const handleRemoveProduct = (productId: string) => {
|
||||||
@@ -88,12 +99,12 @@ const Simulations: React.FC = () => {
|
|||||||
|
|
||||||
const handleRemoveEventFromProduct = () => {
|
const handleRemoveEventFromProduct = () => {
|
||||||
if (selectedAsset) {
|
if (selectedAsset) {
|
||||||
const email = localStorage.getItem('email')
|
const email = localStorage.getItem("email");
|
||||||
const organization = (email!.split("@")[1]).split(".")[0];
|
const organization = email!.split("@")[1].split(".")[0];
|
||||||
deleteEventDataApi({
|
deleteEventDataApi({
|
||||||
productId: selectedProduct.productId,
|
productId: selectedProduct.productId,
|
||||||
modelUuid: selectedAsset.modelUuid,
|
modelUuid: selectedAsset.modelUuid,
|
||||||
organization: organization
|
organization: organization,
|
||||||
});
|
});
|
||||||
removeEvent(selectedProduct.productId, selectedAsset.modelUuid);
|
removeEvent(selectedProduct.productId, selectedAsset.modelUuid);
|
||||||
clearSelectedAsset();
|
clearSelectedAsset();
|
||||||
@@ -104,7 +115,8 @@ const Simulations: React.FC = () => {
|
|||||||
(product) => product.productId === selectedProduct.productId
|
(product) => product.productId === selectedProduct.productId
|
||||||
);
|
);
|
||||||
|
|
||||||
const events: Event[] = selectedProductData?.eventDatas.map((event) => ({
|
const events: Event[] =
|
||||||
|
selectedProductData?.eventDatas.map((event) => ({
|
||||||
pathName: event.modelName,
|
pathName: event.modelName,
|
||||||
})) || [];
|
})) || [];
|
||||||
|
|
||||||
@@ -115,9 +127,9 @@ const Simulations: React.FC = () => {
|
|||||||
<div className="actions section">
|
<div className="actions section">
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<div className="header-value">Products</div>
|
<div className="header-value">Products</div>
|
||||||
<div className="add-button" onClick={handleAddProduct}>
|
<button className="add-button" onClick={handleAddProduct}>
|
||||||
<AddIcon /> Add
|
<AddIcon /> Add
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="lists-main-container"
|
className="lists-main-container"
|
||||||
@@ -128,11 +140,13 @@ const Simulations: React.FC = () => {
|
|||||||
{products.map((product, index) => (
|
{products.map((product, index) => (
|
||||||
<div
|
<div
|
||||||
key={product.productId}
|
key={product.productId}
|
||||||
className={`list-item ${selectedProduct.productId === product.productId
|
className={`list-item ${
|
||||||
|
selectedProduct.productId === product.productId
|
||||||
? "active"
|
? "active"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
{/* eslint-disable-next-line */}
|
||||||
<div
|
<div
|
||||||
className="value"
|
className="value"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -153,23 +167,23 @@ const Simulations: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{products.length > 1 && (
|
{products.length > 1 && (
|
||||||
<div
|
<button
|
||||||
className="remove-button"
|
className="remove-button"
|
||||||
onClick={() => handleRemoveProduct(product.productId)}
|
onClick={() => handleRemoveProduct(product.productId)}
|
||||||
>
|
>
|
||||||
<RemoveIcon />
|
<RemoveIcon />
|
||||||
</div>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<button
|
||||||
className="resize-icon"
|
className="resize-icon"
|
||||||
id="action-resize"
|
id="action-resize"
|
||||||
onMouseDown={(e) => handleResize(e, productsContainerRef)}
|
onMouseDown={(e: any) => handleResize(e, productsContainerRef)}
|
||||||
>
|
>
|
||||||
<ResizeHeightIcon />
|
<ResizeHeightIcon />
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -184,7 +198,9 @@ const Simulations: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
{openObjects &&
|
{openObjects &&
|
||||||
events.map((event, index) => <List key={index} val={event} />)}
|
events.map((event, index) => (
|
||||||
|
<List key={`${index}-${event.pathName}`} val={event} />
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="compare-simulations-container">
|
<div className="compare-simulations-container">
|
||||||
@@ -192,7 +208,7 @@ const Simulations: React.FC = () => {
|
|||||||
Need to Compare Layout?
|
Need to Compare Layout?
|
||||||
</div>
|
</div>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
Click <span>'Compare'</span> to review and analyze the layout
|
Click '<span>Compare</span>' to review and analyze the layout
|
||||||
differences between them.
|
differences between them.
|
||||||
</div>
|
</div>
|
||||||
<div className="input">
|
<div className="input">
|
||||||
@@ -211,7 +227,7 @@ const Simulations: React.FC = () => {
|
|||||||
event: getEventByModelUuid(selectedAsset.modelUuid),
|
event: getEventByModelUuid(selectedAsset.modelUuid),
|
||||||
addEvent,
|
addEvent,
|
||||||
selectedProduct,
|
selectedProduct,
|
||||||
clearSelectedAsset
|
clearSelectedAsset,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
handleRemoveEventFromProduct();
|
handleRemoveEventFromProduct();
|
||||||
@@ -221,7 +237,7 @@ const Simulations: React.FC = () => {
|
|||||||
</RenderOverlay>
|
</RenderOverlay>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Simulations;
|
export default Simulations;
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ const RenameTooltip: React.FC<RenameTooltipProps> = ({ name, onSubmit }) => {
|
|||||||
<div
|
<div
|
||||||
className="rename-tool-tip"
|
className="rename-tool-tip"
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
|
||||||
top: `${top}px`,
|
top: `${top}px`,
|
||||||
left: `${left}px`,
|
left: `${left}px`,
|
||||||
zIndex: 100,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="header">
|
<div className="header">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
useLeftData,
|
useLeftData,
|
||||||
useTopData,
|
useTopData,
|
||||||
@@ -28,13 +28,13 @@ const EditWidgetOption: React.FC<EditWidgetOptionProps> = ({
|
|||||||
>
|
>
|
||||||
<div className="context-menu-options">
|
<div className="context-menu-options">
|
||||||
{options.map((option, index) => (
|
{options.map((option, index) => (
|
||||||
<div
|
<button
|
||||||
className="option"
|
className="option"
|
||||||
key={index}
|
key={`${index}-${option}`}
|
||||||
onClick={() => onClick(option)}
|
onClick={() => onClick(option)}
|
||||||
>
|
>
|
||||||
{option}
|
{option}
|
||||||
</div>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -64,8 +64,6 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
|
|
||||||
const handleMouseDown = () => {
|
const handleMouseDown = () => {
|
||||||
isDragging.current = true;
|
isDragging.current = true;
|
||||||
document.addEventListener("mousemove", handleMouseMove);
|
|
||||||
document.addEventListener("mouseup", handleMouseUp);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseMove = (e: MouseEvent) => {
|
const handleMouseMove = (e: MouseEvent) => {
|
||||||
@@ -80,11 +78,11 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
isDragging.current = false;
|
isDragging.current = false;
|
||||||
document.removeEventListener("mousemove", handleMouseMove);
|
|
||||||
document.removeEventListener("mouseup", handleMouseUp);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
document.addEventListener("mousemove", handleMouseMove);
|
||||||
|
document.addEventListener("mouseup", handleMouseUp);
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener("mousemove", handleMouseMove);
|
document.removeEventListener("mousemove", handleMouseMove);
|
||||||
document.removeEventListener("mouseup", handleMouseUp);
|
document.removeEventListener("mouseup", handleMouseUp);
|
||||||
@@ -109,24 +107,6 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
{ name: "process 9", completed: 90 }, // 90% completed
|
{ name: "process 9", completed: 90 }, // 90% completed
|
||||||
{ name: "process 10", completed: 30 }, // 30% completed
|
{ name: "process 10", completed: 30 }, // 30% completed
|
||||||
];
|
];
|
||||||
// Move getRandomColor out of render
|
|
||||||
const getRandomColor = () => {
|
|
||||||
const letters = "0123456789ABCDEF";
|
|
||||||
let color = "#";
|
|
||||||
for (let i = 0; i < 6; i++) {
|
|
||||||
color += letters[Math.floor(Math.random() * 16)];
|
|
||||||
}
|
|
||||||
return color;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Store colors for each process item
|
|
||||||
const [_, setProcessColors] = useState<string[]>([]);
|
|
||||||
|
|
||||||
// Generate colors on mount or when process changes
|
|
||||||
useEffect(() => {
|
|
||||||
const generatedColors = process.map(() => getRandomColor());
|
|
||||||
setProcessColors(generatedColors);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const intervals = [10, 20, 30, 40, 50, 60]; // in minutes
|
const intervals = [10, 20, 30, 40, 50, 60]; // in minutes
|
||||||
const totalSegments = intervals.length;
|
const totalSegments = intervals.length;
|
||||||
@@ -218,7 +198,7 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{subModule === "simulations" && (
|
{subModule !== "analysis" && (
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<InfoIcon />
|
<InfoIcon />
|
||||||
{playSimulation
|
{playSimulation
|
||||||
@@ -281,7 +261,7 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
const segmentProgress = (index / totalSegments) * 100;
|
const segmentProgress = (index / totalSegments) * 100;
|
||||||
const isFilled = progress >= segmentProgress;
|
const isFilled = progress >= segmentProgress;
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={index}>
|
<React.Fragment key={`${index}-${label}`}>
|
||||||
<div className="label-dot-wrapper">
|
<div className="label-dot-wrapper">
|
||||||
<div className="label">{label} mins</div>
|
<div className="label">{label} mins</div>
|
||||||
<div
|
<div
|
||||||
@@ -360,6 +340,7 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
className="process-wrapper"
|
className="process-wrapper"
|
||||||
style={{ padding: expand ? "0px" : "5px 35px" }}
|
style={{ padding: expand ? "0px" : "5px 35px" }}
|
||||||
>
|
>
|
||||||
|
{/* eslint-disable-next-line */}
|
||||||
<div
|
<div
|
||||||
className="process-container"
|
className="process-container"
|
||||||
ref={processWrapperRef}
|
ref={processWrapperRef}
|
||||||
@@ -367,7 +348,7 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{process.map((item, index) => (
|
{process.map((item, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={`${index}-${item.name}`}
|
||||||
className="process"
|
className="process"
|
||||||
style={{
|
style={{
|
||||||
width: `${item.completed}%`,
|
width: `${item.completed}%`,
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { useFrame } from '@react-three/fiber';
|
import { useFrame } from "@react-three/fiber";
|
||||||
import * as THREE from 'three';
|
import * as THREE from "three";
|
||||||
import { Line } from '@react-three/drei';
|
import { Line } from "@react-three/drei";
|
||||||
import {
|
import {
|
||||||
useAnimationPlaySpeed,
|
useAnimationPlaySpeed,
|
||||||
usePauseButtonStore,
|
usePauseButtonStore,
|
||||||
usePlayButtonStore,
|
usePlayButtonStore,
|
||||||
useResetButtonStore
|
useResetButtonStore,
|
||||||
} from '../../../../../store/usePlayButtonStore';
|
} from "../../../../../store/usePlayButtonStore";
|
||||||
|
|
||||||
function RoboticArmAnimator({
|
function RoboticArmAnimator({
|
||||||
HandleCallback,
|
HandleCallback,
|
||||||
@@ -16,13 +16,19 @@ function RoboticArmAnimator({
|
|||||||
targetBone,
|
targetBone,
|
||||||
armBot,
|
armBot,
|
||||||
logStatus,
|
logStatus,
|
||||||
path
|
path,
|
||||||
}: any) {
|
}: any) {
|
||||||
const progressRef = useRef(0);
|
const progressRef = useRef(0);
|
||||||
const curveRef = useRef<THREE.Vector3[] | null>(null);
|
const curveRef = useRef<THREE.Vector3[] | null>(null);
|
||||||
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
|
const [currentPath, setCurrentPath] = useState<[number, number, number][]>(
|
||||||
const [circlePoints, setCirclePoints] = useState<[number, number, number][]>([]);
|
[]
|
||||||
const [customCurvePoints, setCustomCurvePoints] = useState<THREE.Vector3[] | null>(null);
|
);
|
||||||
|
const [circlePoints, setCirclePoints] = useState<[number, number, number][]>(
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
const [customCurvePoints, setCustomCurvePoints] = useState<
|
||||||
|
THREE.Vector3[] | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
// Zustand stores
|
// Zustand stores
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
@@ -45,11 +51,10 @@ function RoboticArmAnimator({
|
|||||||
|
|
||||||
// Handle circle points based on armBot position
|
// Handle circle points based on armBot position
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const points = generateRingPoints(1.6, 64)
|
const points = generateRingPoints(1.6, 64);
|
||||||
setCirclePoints(points);
|
setCirclePoints(points);
|
||||||
}, [armBot.position]);
|
}, [armBot.position]);
|
||||||
|
|
||||||
|
|
||||||
function generateRingPoints(radius: any, segments: any) {
|
function generateRingPoints(radius: any, segments: any) {
|
||||||
const points: [number, number, number][] = [];
|
const points: [number, number, number][] = [];
|
||||||
for (let i = 0; i < segments; i++) {
|
for (let i = 0; i < segments; i++) {
|
||||||
@@ -63,7 +68,11 @@ function RoboticArmAnimator({
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
const findNearestIndex = (nearestPoint: [number, number, number], points: [number, number, number][], epsilon = 1e-6) => {
|
const findNearestIndex = (
|
||||||
|
nearestPoint: [number, number, number],
|
||||||
|
points: [number, number, number][],
|
||||||
|
epsilon = 1e-6
|
||||||
|
) => {
|
||||||
for (let i = 0; i < points.length; i++) {
|
for (let i = 0; i < points.length; i++) {
|
||||||
const [x, y, z] = points[i];
|
const [x, y, z] = points[i];
|
||||||
if (
|
if (
|
||||||
@@ -77,15 +86,22 @@ function RoboticArmAnimator({
|
|||||||
return -1; // Not found
|
return -1; // Not found
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Handle nearest points and final path (including arc points)
|
// Handle nearest points and final path (including arc points)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (circlePoints.length > 0 && currentPath.length > 0) {
|
if (circlePoints.length > 0 && currentPath.length > 0) {
|
||||||
const start = currentPath[0];
|
const start = currentPath[0];
|
||||||
const end = currentPath[currentPath.length - 1];
|
const end = currentPath[currentPath.length - 1];
|
||||||
|
|
||||||
const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number];
|
const raisedStart = [start[0], start[1] + 0.5, start[2]] as [
|
||||||
const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number];
|
number,
|
||||||
|
number,
|
||||||
|
number
|
||||||
|
];
|
||||||
|
const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [
|
||||||
|
number,
|
||||||
|
number,
|
||||||
|
number
|
||||||
|
];
|
||||||
|
|
||||||
const findNearest = (target: [number, number, number]) => {
|
const findNearest = (target: [number, number, number]) => {
|
||||||
return circlePoints.reduce((nearest, point) => {
|
return circlePoints.reduce((nearest, point) => {
|
||||||
@@ -107,14 +123,19 @@ function RoboticArmAnimator({
|
|||||||
|
|
||||||
const nearestToEnd = findNearest(raisedEnd);
|
const nearestToEnd = findNearest(raisedEnd);
|
||||||
|
|
||||||
const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints);
|
const indexOfNearestStart = findNearestIndex(
|
||||||
|
nearestToStart,
|
||||||
|
circlePoints
|
||||||
|
);
|
||||||
|
|
||||||
const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints);
|
const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints);
|
||||||
|
|
||||||
// Find clockwise and counter-clockwise distances
|
// Find clockwise and counter-clockwise distances
|
||||||
const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + 64) % 64;
|
const clockwiseDistance =
|
||||||
|
(indexOfNearestEnd - indexOfNearestStart + 64) % 64;
|
||||||
|
|
||||||
const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + 64) % 64;
|
const counterClockwiseDistance =
|
||||||
|
(indexOfNearestStart - indexOfNearestEnd + 64) % 64;
|
||||||
|
|
||||||
const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance;
|
const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance;
|
||||||
|
|
||||||
@@ -123,24 +144,25 @@ function RoboticArmAnimator({
|
|||||||
|
|
||||||
if (clockwiseIsShorter) {
|
if (clockwiseIsShorter) {
|
||||||
if (indexOfNearestStart <= indexOfNearestEnd) {
|
if (indexOfNearestStart <= indexOfNearestEnd) {
|
||||||
arcPoints = circlePoints.slice(indexOfNearestStart, indexOfNearestEnd + 1);
|
arcPoints = circlePoints.slice(
|
||||||
|
indexOfNearestStart,
|
||||||
|
indexOfNearestEnd + 1
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Wrap around
|
// Wrap around
|
||||||
arcPoints = [
|
arcPoints = [
|
||||||
...circlePoints.slice(indexOfNearestStart, 64),
|
...circlePoints.slice(indexOfNearestStart, 64),
|
||||||
...circlePoints.slice(0, indexOfNearestEnd + 1)
|
...circlePoints.slice(0, indexOfNearestEnd + 1),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} else {
|
} else if (indexOfNearestStart >= indexOfNearestEnd) {
|
||||||
if (indexOfNearestStart >= indexOfNearestEnd) {
|
for (
|
||||||
for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) {
|
let i = indexOfNearestStart;
|
||||||
|
i !== (indexOfNearestEnd - 1 + 64) % 64;
|
||||||
|
i = (i - 1 + 64) % 64
|
||||||
|
) {
|
||||||
arcPoints.push(circlePoints[i]);
|
arcPoints.push(circlePoints[i]);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) {
|
|
||||||
arcPoints.push(circlePoints[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue your custom path logic
|
// Continue your custom path logic
|
||||||
@@ -148,13 +170,20 @@ function RoboticArmAnimator({
|
|||||||
new THREE.Vector3(start[0], start[1], start[2]), // start
|
new THREE.Vector3(start[0], start[1], start[2]), // start
|
||||||
new THREE.Vector3(raisedStart[0], raisedStart[1], raisedStart[2]), // lift up
|
new THREE.Vector3(raisedStart[0], raisedStart[1], raisedStart[2]), // lift up
|
||||||
new THREE.Vector3(nearestToStart[0], raisedStart[1], nearestToStart[2]), // move to arc start
|
new THREE.Vector3(nearestToStart[0], raisedStart[1], nearestToStart[2]), // move to arc start
|
||||||
...arcPoints.map(point => new THREE.Vector3(point[0], raisedStart[1], point[2])),
|
...arcPoints.map(
|
||||||
|
(point) => new THREE.Vector3(point[0], raisedStart[1], point[2])
|
||||||
|
),
|
||||||
new THREE.Vector3(nearestToEnd[0], raisedEnd[1], nearestToEnd[2]), // move from arc end
|
new THREE.Vector3(nearestToEnd[0], raisedEnd[1], nearestToEnd[2]), // move from arc end
|
||||||
new THREE.Vector3(raisedEnd[0], raisedEnd[1], raisedEnd[2]), // lowered end
|
new THREE.Vector3(raisedEnd[0], raisedEnd[1], raisedEnd[2]), // lowered end
|
||||||
new THREE.Vector3(end[0], end[1], end[2]) // end
|
new THREE.Vector3(end[0], end[1], end[2]), // end
|
||||||
];
|
];
|
||||||
|
|
||||||
const customCurve = new THREE.CatmullRomCurve3(pathVectors, false, 'centripetal', 1);
|
const customCurve = new THREE.CatmullRomCurve3(
|
||||||
|
pathVectors,
|
||||||
|
false,
|
||||||
|
"centripetal",
|
||||||
|
1
|
||||||
|
);
|
||||||
const generatedPoints = customCurve.getPoints(100);
|
const generatedPoints = customCurve.getPoints(100);
|
||||||
setCustomCurvePoints(generatedPoints);
|
setCustomCurvePoints(generatedPoints);
|
||||||
}
|
}
|
||||||
@@ -164,13 +193,16 @@ function RoboticArmAnimator({
|
|||||||
useFrame((_, delta) => {
|
useFrame((_, delta) => {
|
||||||
if (!ikSolver) return;
|
if (!ikSolver) return;
|
||||||
|
|
||||||
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
|
const bone = ikSolver.mesh.skeleton.bones.find(
|
||||||
|
(b: any) => b.name === targetBone
|
||||||
|
);
|
||||||
if (!bone) return;
|
if (!bone) return;
|
||||||
|
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
if (!isPaused && customCurvePoints && currentPath.length > 0) {
|
if (!isPaused && customCurvePoints && currentPath.length > 0) {
|
||||||
const curvePoints = customCurvePoints;
|
const curvePoints = customCurvePoints;
|
||||||
const speedAdjustedProgress = progressRef.current + (speed * armBot.speed);
|
const speedAdjustedProgress =
|
||||||
|
progressRef.current + speed * armBot.speed;
|
||||||
const index = Math.floor(speedAdjustedProgress);
|
const index = Math.floor(speedAdjustedProgress);
|
||||||
|
|
||||||
if (index >= curvePoints.length) {
|
if (index >= curvePoints.length) {
|
||||||
@@ -185,7 +217,7 @@ function RoboticArmAnimator({
|
|||||||
progressRef.current = speedAdjustedProgress;
|
progressRef.current = speedAdjustedProgress;
|
||||||
}
|
}
|
||||||
} else if (isPaused) {
|
} else if (isPaused) {
|
||||||
logStatus(armBot.modelUuid, 'Simulation Paused');
|
logStatus(armBot.modelUuid, "Simulation Paused");
|
||||||
}
|
}
|
||||||
|
|
||||||
ikSolver.update();
|
ikSolver.update();
|
||||||
@@ -196,20 +228,29 @@ function RoboticArmAnimator({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{customCurvePoints && currentPath && isPlaying && (
|
{customCurvePoints && currentPath && isPlaying && (
|
||||||
<mesh rotation={armBot.rotation} position={armBot.position}>
|
<mesh rotation={armBot.rotation} position={armBot.position}>
|
||||||
<Line
|
<Line
|
||||||
points={customCurvePoints.map((p) => [p.x, p.y, p.z] as [number, number, number])}
|
points={customCurvePoints.map(
|
||||||
|
(p) => [p.x, p.y, p.z] as [number, number, number]
|
||||||
|
)}
|
||||||
color="green"
|
color="green"
|
||||||
lineWidth={5}
|
lineWidth={5}
|
||||||
dashed={false}
|
dashed={false}
|
||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
)}
|
)}
|
||||||
<mesh position={[armBot.position[0], armBot.position[1] + 1.5, armBot.position[2]]} rotation={[-Math.PI / 2, 0, 0]}>
|
<mesh
|
||||||
|
position={[
|
||||||
|
armBot.position[0],
|
||||||
|
armBot.position[1] + 1.5,
|
||||||
|
armBot.position[2],
|
||||||
|
]}
|
||||||
|
rotation={[-Math.PI / 2, 0, 0]}
|
||||||
|
visible={false}
|
||||||
|
>
|
||||||
<ringGeometry args={[1.59, 1.61, 64]} />
|
<ringGeometry args={[1.59, 1.61, 64]} />
|
||||||
<meshBasicMaterial color="green" side={THREE.DoubleSide} />
|
<meshBasicMaterial color="green" side={THREE.DoubleSide} />
|
||||||
</mesh>
|
</mesh>
|
||||||
|
|||||||
Reference in New Issue
Block a user