feat: Add MaterialInstances component for rendering animated materials based on active curves
refactor: Clean up console logs in ProcessAnimator for better readability fix: Update group visibility logic in Agv and PathNavigator components
This commit is contained in:
parent
43d21a522c
commit
a59aa1d61c
|
@ -79,8 +79,9 @@ const Agv: React.FC<ProcessContainerProps> = ({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{pathPoints.map((pair, i) => (
|
{pathPoints.map((pair, i) => (
|
||||||
<group key={i} visible={!isPlaying}>
|
<group key={i}>
|
||||||
<PathNavigator
|
<PathNavigator
|
||||||
|
key={i}
|
||||||
navMesh={navMesh}
|
navMesh={navMesh}
|
||||||
pathPoints={pair.points}
|
pathPoints={pair.points}
|
||||||
id={pair.modelUuid}
|
id={pair.modelUuid}
|
||||||
|
|
|
@ -185,7 +185,7 @@ export default function PathNavigator({
|
||||||
function logAgvStatus(id: string, status: string) {
|
function logAgvStatus(id: string, status: string) {
|
||||||
// console.log(
|
// console.log(
|
||||||
// `AGV ${id}: ${status}`
|
// `AGV ${id}: ${status}`
|
||||||
|
|
||||||
// );
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ export default function PathNavigator({
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group name="path-navigator-lines" visible={!isPlaying}>
|
<group name="path-navigator-lines">
|
||||||
{toPickupPath.length > 0 && (
|
{toPickupPath.length > 0 && (
|
||||||
<Line
|
<Line
|
||||||
points={toPickupPath}
|
points={toPickupPath}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { useFrame } from "@react-three/fiber";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||||
import { useSimulationStates } from "../../../store/store";
|
import { useSimulationStates } from "../../../store/store";
|
||||||
|
import MaterialInstances from "./MaterialInstances";
|
||||||
|
|
||||||
|
|
||||||
interface StaticMachineState {
|
interface StaticMachineState {
|
||||||
|
@ -257,6 +258,10 @@ const IKAnimationController = ({
|
||||||
});
|
});
|
||||||
}, [process, groupRef, isPlaying]);
|
}, [process, groupRef, isPlaying]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('processedCurves: ', processedCurves);
|
||||||
|
}, [processedCurves])
|
||||||
|
|
||||||
const activeCurve = useMemo(() => {
|
const activeCurve = useMemo(() => {
|
||||||
if (isPlaying && processedCurves)
|
if (isPlaying && processedCurves)
|
||||||
return processedCurves.find((c) => c?.trigger === selectedTrigger);
|
return processedCurves.find((c) => c?.trigger === selectedTrigger);
|
||||||
|
@ -337,7 +342,19 @@ const IKAnimationController = ({
|
||||||
ikSolver.update();
|
ikSolver.update();
|
||||||
});
|
});
|
||||||
|
|
||||||
return null;
|
return (
|
||||||
|
<>
|
||||||
|
{armBot.status === 'moving' && activeCurve &&
|
||||||
|
<MaterialInstances
|
||||||
|
groupRef={groupRef}
|
||||||
|
activeCurve={activeCurve}
|
||||||
|
progress={progress}
|
||||||
|
ikSolver={ikSolver}
|
||||||
|
targetBoneName={targetBoneName}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default IKAnimationController;
|
export default IKAnimationController;
|
|
@ -0,0 +1,42 @@
|
||||||
|
import React from 'react';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import { Box } from '@react-three/drei';
|
||||||
|
|
||||||
|
type MaterialInstancesProps = {
|
||||||
|
groupRef: React.RefObject<THREE.Group>;
|
||||||
|
activeCurve: any;
|
||||||
|
progress: number;
|
||||||
|
ikSolver: any;
|
||||||
|
targetBoneName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function MaterialInstances({
|
||||||
|
groupRef,
|
||||||
|
activeCurve,
|
||||||
|
progress,
|
||||||
|
ikSolver,
|
||||||
|
targetBoneName
|
||||||
|
}: MaterialInstancesProps) {
|
||||||
|
const { endToRestRange, startToEndRange } = activeCurve;
|
||||||
|
|
||||||
|
// Show the box from when we reach the start point until we leave the end point
|
||||||
|
const shouldShow = (progress >= startToEndRange[0] && progress < startToEndRange[1] && progress >= endToRestRange[0]);
|
||||||
|
|
||||||
|
if (!shouldShow || !ikSolver) return null;
|
||||||
|
|
||||||
|
const targetBone = ikSolver.mesh.skeleton.bones.find(
|
||||||
|
(b: any) => b.name === targetBoneName
|
||||||
|
);
|
||||||
|
if (!targetBone) return null;
|
||||||
|
|
||||||
|
const worldPos = new THREE.Vector3();
|
||||||
|
targetBone.getWorldPosition(worldPos);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box args={[0.5, 0.5, 0.5]} position={worldPos}>
|
||||||
|
<meshStandardMaterial color="orange" />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MaterialInstances;
|
|
@ -169,9 +169,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
|
|
||||||
const spawnPoint = findSpawnPoint(process);
|
const spawnPoint = findSpawnPoint(process);
|
||||||
if (!spawnPoint || !spawnPoint.actions) {
|
if (!spawnPoint || !spawnPoint.actions) {
|
||||||
console.log(
|
|
||||||
`Process ${process.id} has no valid spawn point or actions`
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,10 +252,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
|
|
||||||
// Check connection status with debugging
|
// Check connection status with debugging
|
||||||
const isConnected = isConnectedToActiveArmBot(process.id);
|
const isConnected = isConnectedToActiveArmBot(process.id);
|
||||||
console.log(
|
|
||||||
`Process ${process.id} animation - connected:`,
|
|
||||||
isConnected
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isConnected) {
|
if (isConnected) {
|
||||||
// Stop all animations when connected to active arm bot
|
// Stop all animations when connected to active arm bot
|
||||||
|
@ -293,9 +286,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
currentTime - processState.processDelayStartTime >=
|
currentTime - processState.processDelayStartTime >=
|
||||||
effectiveDelayTime
|
effectiveDelayTime
|
||||||
) {
|
) {
|
||||||
console.log(
|
|
||||||
`Process ${process.id} delay completed, resuming animation`
|
|
||||||
);
|
|
||||||
newStates[process.id] = {
|
newStates[process.id] = {
|
||||||
...processState,
|
...processState,
|
||||||
isProcessDelaying: false,
|
isProcessDelaying: false,
|
||||||
|
@ -331,9 +321,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
[];
|
[];
|
||||||
|
|
||||||
if (path.length < 2) {
|
if (path.length < 2) {
|
||||||
console.log(
|
|
||||||
`Process ${process.id} has insufficient path points: ${path.length}`
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,9 +335,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
|
|
||||||
const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current;
|
const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current;
|
||||||
if (!currentRef) {
|
if (!currentRef) {
|
||||||
console.log(
|
|
||||||
`No reference for object ${objectId}, skipping animation`
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,9 +362,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
stateRef.currentDelayDuration / speedRef.current;
|
stateRef.currentDelayDuration / speedRef.current;
|
||||||
|
|
||||||
if (currentTime - stateRef.delayStartTime >= effectiveDelayTime) {
|
if (currentTime - stateRef.delayStartTime >= effectiveDelayTime) {
|
||||||
console.log(
|
|
||||||
`Delay complete for object ${objectId}, resuming animation`
|
|
||||||
);
|
|
||||||
stateRef.isDelaying = false;
|
stateRef.isDelaying = false;
|
||||||
stateRef.delayComplete = true;
|
stateRef.delayComplete = true;
|
||||||
stateRef.isAnimating = true;
|
stateRef.isAnimating = true;
|
||||||
|
@ -408,9 +389,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
|
|
||||||
// Skip non-animating objects
|
// Skip non-animating objects
|
||||||
if (!stateRef.isAnimating) {
|
if (!stateRef.isAnimating) {
|
||||||
console.log(
|
|
||||||
`Object ${objectId} not animating, skipping animation updates`
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,9 +432,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
|
|
||||||
if (shouldHide) {
|
if (shouldHide) {
|
||||||
if (isAgvPicking) {
|
if (isAgvPicking) {
|
||||||
console.log(
|
|
||||||
`AGV picking at last point for object ${objectId}, hiding object`
|
|
||||||
);
|
|
||||||
updatedObjects[objectId] = {
|
updatedObjects[objectId] = {
|
||||||
...obj,
|
...obj,
|
||||||
visible: false,
|
visible: false,
|
||||||
|
@ -517,14 +492,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
if (stateRef.delayComplete && stateRef.progress < 0.01) {
|
if (stateRef.delayComplete && stateRef.progress < 0.01) {
|
||||||
stateRef.progress = 0.05;
|
stateRef.progress = 0.05;
|
||||||
stateRef.delayComplete = false;
|
stateRef.delayComplete = false;
|
||||||
console.log(
|
|
||||||
`Boosting progress for object ${objectId} after delay`
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
stateRef.progress += movement / distance;
|
stateRef.progress += movement / distance;
|
||||||
console.log(
|
|
||||||
`Object ${objectId} progress: ${stateRef.progress.toFixed(3)}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle point transition
|
// Handle point transition
|
||||||
|
@ -564,9 +533,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||||
|
|
||||||
// Log if no animation is occurring when it should
|
// Log if no animation is occurring when it should
|
||||||
if (!animationOccurring && !isConnected) {
|
if (!animationOccurring && !isConnected) {
|
||||||
console.log(
|
// console.log(
|
||||||
`Warning: No animation occurring for process ${process.id} despite not being connected`
|
// `Warning: No animation occurring for process ${process.id} despite not being connected`
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
newStates[process.id] = {
|
newStates[process.id] = {
|
||||||
|
|
|
@ -510,6 +510,14 @@ export const useProcessAnimation = (
|
||||||
|
|
||||||
if (activeVehicles.length === 0) {
|
if (activeVehicles.length === 0) {
|
||||||
onHitTriggers.forEach((trigger: Trigger) => {
|
onHitTriggers.forEach((trigger: Trigger) => {
|
||||||
|
const triggerKey = `${point.uuid}-${trigger.uuid}`;
|
||||||
|
|
||||||
|
newTriggerCounts[triggerKey] = (newTriggerCounts[triggerKey] || 0) + 1;
|
||||||
|
|
||||||
|
shouldLog = true;
|
||||||
|
|
||||||
|
newTriggerLogs.push({ timestamp: currentTime, pointId: point.uuid, objectId, triggerId: trigger.uuid, });
|
||||||
|
|
||||||
const connections = point.connections?.targets || [];
|
const connections = point.connections?.targets || [];
|
||||||
|
|
||||||
connections.forEach((connection) => {
|
connections.forEach((connection) => {
|
||||||
|
@ -529,7 +537,7 @@ export const useProcessAnimation = (
|
||||||
|
|
||||||
let processTotalHits = Object.values(newTriggerCounts).reduce((a, b) => a + b, 0);
|
let processTotalHits = Object.values(newTriggerCounts).reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
// Handle logic for vehicles and ArmBots when a trigger is hit
|
// Handle logic for vehicles when a trigger is hit
|
||||||
if (shouldLog) {
|
if (shouldLog) {
|
||||||
vehiclePaths.forEach((vehiclePath) => {
|
vehiclePaths.forEach((vehiclePath) => {
|
||||||
if (vehiclePath.points?.length > 0) {
|
if (vehiclePath.points?.length > 0) {
|
||||||
|
|
Loading…
Reference in New Issue