pillar Jig half way completed
This commit is contained in:
15
app/src/modules/simulation/crane/crane.tsx
Normal file
15
app/src/modules/simulation/crane/crane.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react'
|
||||
import CraneInstances from './instances/craneInstances'
|
||||
|
||||
function Crane() {
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<CraneInstances />
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Crane
|
||||
@@ -0,0 +1,133 @@
|
||||
import * as THREE from 'three';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useThree } from '@react-three/fiber';
|
||||
|
||||
function PillarJibAnimator({ crane }: { crane: CraneStatus }) {
|
||||
const { scene } = useThree();
|
||||
|
||||
useEffect(() => {
|
||||
const model = scene.getObjectByProperty('uuid', crane.modelUuid);
|
||||
|
||||
if (model) {
|
||||
const base = model.getObjectByName('base');
|
||||
const trolley = model.getObjectByName('trolley');
|
||||
const hook = model.getObjectByName('hook');
|
||||
|
||||
if (base && trolley && hook) {
|
||||
let trolleyDir = 1;
|
||||
let hookDir = 1;
|
||||
|
||||
const trolleySpeed = 0.01;
|
||||
const hookSpeed = 0.01;
|
||||
const rotationSpeed = 0.005;
|
||||
|
||||
const trolleyMinOffset = -1;
|
||||
const trolleyMaxOffset = 1.75;
|
||||
const hookMinOffset = 0.25;
|
||||
const hookMaxOffset = -1.5;
|
||||
|
||||
const originalTrolleyX = trolley.position.x;
|
||||
const originalHookY = hook.position.y;
|
||||
|
||||
const animate = () => {
|
||||
if (base) {
|
||||
base.rotation.y += rotationSpeed;
|
||||
}
|
||||
|
||||
if (trolley) {
|
||||
trolley.position.x += trolleyDir * trolleySpeed;
|
||||
if (trolley.position.x >= originalTrolleyX + trolleyMaxOffset ||
|
||||
trolley.position.x <= originalTrolleyX + trolleyMinOffset) {
|
||||
trolleyDir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hook) {
|
||||
hook.position.y += hookDir * hookSpeed;
|
||||
if (hook.position.y >= originalHookY + hookMinOffset ||
|
||||
hook.position.y <= originalHookY + hookMaxOffset) {
|
||||
hookDir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
animate();
|
||||
}
|
||||
}
|
||||
}, [crane, scene]);
|
||||
|
||||
return (
|
||||
<PillarJibHelper crane={crane} />
|
||||
);
|
||||
}
|
||||
|
||||
export default PillarJibAnimator;
|
||||
|
||||
function PillarJibHelper({ crane }: { crane: CraneStatus }) {
|
||||
const { scene } = useThree();
|
||||
|
||||
const { geometry, position } = useMemo(() => {
|
||||
const model = scene.getObjectByProperty('uuid', crane.modelUuid);
|
||||
if (!model) return { geometry: null, position: null };
|
||||
|
||||
const base = model.getObjectByName('base');
|
||||
const trolley = model.getObjectByName('trolley');
|
||||
const hook = model.getObjectByName('hook');
|
||||
|
||||
if (!base || !trolley || !hook) return { geometry: null, position: null };
|
||||
|
||||
const baseWorld = new THREE.Vector3();
|
||||
base.getWorldPosition(baseWorld);
|
||||
|
||||
const trolleyWorld = new THREE.Vector3();
|
||||
trolley.getWorldPosition(trolleyWorld);
|
||||
|
||||
const hookWorld = new THREE.Vector3();
|
||||
hook.getWorldPosition(hookWorld);
|
||||
|
||||
const distFromBase = new THREE.Vector2(trolleyWorld.x - baseWorld.x, trolleyWorld.z - baseWorld.z).length();
|
||||
const outerRadius = distFromBase + 1.75;
|
||||
const innerRadius = Math.max(distFromBase - 1, 0.05);
|
||||
const height = (0.25 - (-1.5));
|
||||
const cylinderYPosition = hookWorld.y + (height / 2) + (-1.5 + 0.25) / 2;
|
||||
|
||||
const shape = new THREE.Shape();
|
||||
shape.absarc(0, 0, outerRadius, 0, Math.PI * 2, false);
|
||||
|
||||
const hole = new THREE.Path();
|
||||
hole.absarc(0, 0, innerRadius, 0, Math.PI * 2, true);
|
||||
shape.holes.push(hole);
|
||||
|
||||
const extrudeSettings = {
|
||||
depth: height,
|
||||
bevelEnabled: false,
|
||||
steps: 1
|
||||
};
|
||||
|
||||
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
|
||||
const position: [number, number, number] = [baseWorld.x, cylinderYPosition, baseWorld.z];
|
||||
|
||||
return { geometry, position };
|
||||
}, [scene, crane.modelUuid]);
|
||||
|
||||
if (!geometry || !position) return null;
|
||||
|
||||
return (
|
||||
<mesh
|
||||
geometry={geometry}
|
||||
position={position}
|
||||
rotation={[Math.PI / 2, 0, 0]}
|
||||
>
|
||||
<meshStandardMaterial
|
||||
color={0x888888}
|
||||
metalness={0.5}
|
||||
roughness={0.4}
|
||||
side={THREE.DoubleSide}
|
||||
transparent={true}
|
||||
opacity={0.3}
|
||||
/>
|
||||
</mesh>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from 'react'
|
||||
import PillarJibInstance from './instance/pillarJibInstance';
|
||||
import { useSceneContext } from '../../../scene/sceneContext';
|
||||
|
||||
function CraneInstances() {
|
||||
const { craneStore } = useSceneContext();
|
||||
const { cranes } = craneStore();
|
||||
|
||||
return (
|
||||
<>
|
||||
{cranes.map((crane: CraneStatus) => (
|
||||
<React.Fragment key={crane.modelUuid}>
|
||||
|
||||
{crane.subType === "pillarJib" &&
|
||||
<PillarJibInstance crane={crane} />
|
||||
}
|
||||
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default CraneInstances
|
||||
@@ -0,0 +1,14 @@
|
||||
import PillarJibAnimator from '../animator/pillarJibAnimator'
|
||||
|
||||
function PillarJibInstance({ crane }: { crane: CraneStatus }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<PillarJibAnimator crane={crane} />
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default PillarJibInstance
|
||||
@@ -40,7 +40,7 @@ function PointsCalculator(
|
||||
}
|
||||
|
||||
return {
|
||||
points: [worldTopMiddle]
|
||||
points: [new THREE.Vector3(worldTopMiddle.x, worldTopMiddle.y + 0.1, worldTopMiddle.z)]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ function PointInstances() {
|
||||
machine: "purple",
|
||||
storageUnit: "red",
|
||||
human: "white",
|
||||
crane: "yellow",
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -173,6 +173,22 @@ function TriggerConnector() {
|
||||
});
|
||||
});
|
||||
}
|
||||
// Handle Human point
|
||||
else if (event.type === "crane" && 'point' in event) {
|
||||
const point = event.point;
|
||||
point.actions?.forEach(action => {
|
||||
action.triggers?.forEach(trigger => {
|
||||
if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint) {
|
||||
newConnections.push({
|
||||
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||
startPointUuid: point.uuid,
|
||||
endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||
trigger
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
setConnections(newConnections);
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useParams } from 'react-router-dom';
|
||||
import { useVersionContext } from '../../builder/version/versionContext';
|
||||
|
||||
function Products() {
|
||||
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, layout, productStore } = useSceneContext();
|
||||
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, layout, productStore } = useSceneContext();
|
||||
const { products, getProductById, addProduct, setProducts } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { setMainProduct } = useMainProduct();
|
||||
@@ -20,7 +20,8 @@ function Products() {
|
||||
const { addMachine, clearMachines } = machineStore();
|
||||
const { addConveyor, clearConveyors } = conveyorStore();
|
||||
const { setCurrentMaterials, clearStorageUnits, updateCurrentLoad, addStorageUnit } = storageUnitStore();
|
||||
const { addHuman, addCurrentAction, clearHumans } = humanStore();
|
||||
const { addHuman, addCurrentAction: addCurrentActionHuman, clearHumans } = humanStore();
|
||||
const { addCrane, addCurrentAction: addCurrentActionCrane, clearCranes } = craneStore();
|
||||
const { isReset } = useResetButtonStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { mainProduct } = useMainProduct();
|
||||
@@ -164,7 +165,25 @@ function Products() {
|
||||
addHuman(selectedProduct.productUuid, events);
|
||||
|
||||
if (events.point.actions.length > 0) {
|
||||
addCurrentAction(events.modelUuid, events.point.actions[0].actionUuid);
|
||||
addCurrentActionHuman(events.modelUuid, events.point.actions[0].actionUuid);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [selectedProduct, products, isReset, isPlaying]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedProduct.productUuid) {
|
||||
const product = getProductById(selectedProduct.productUuid);
|
||||
if (product) {
|
||||
clearCranes();
|
||||
product.eventDatas.forEach(events => {
|
||||
if (events.type === 'crane') {
|
||||
addCrane(selectedProduct.productUuid, events);
|
||||
|
||||
if (events.point.actions.length > 0) {
|
||||
addCurrentActionCrane(events.modelUuid, events.point.actions[0].actionUuid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ import Materials from './materials/materials';
|
||||
import Machine from './machine/machine';
|
||||
import StorageUnit from './storageUnit/storageUnit';
|
||||
import Human from './human/human';
|
||||
import Crane from './crane/crane';
|
||||
import Simulator from './simulator/simulator';
|
||||
import Products from './products/products';
|
||||
import Trigger from './triggers/trigger';
|
||||
@@ -55,6 +56,8 @@ function Simulation() {
|
||||
|
||||
<Human />
|
||||
|
||||
<Crane />
|
||||
|
||||
<Simulator />
|
||||
|
||||
<SimulationAnalysis />
|
||||
|
||||
Reference in New Issue
Block a user