/** * The 3D hero view of the line. * * No external assets are loaded anywhere in this scene - no HDRI environment, no * CDN font, no texture. Everything is primitives and analytic lights, because the * demo has to survive a room with no working wifi. */ import { Suspense } from 'react'; import { Canvas } from '@react-three/fiber'; import { OrbitControls, ContactShadows } from '@react-three/drei'; import { useStore } from '../store.js'; import { Station } from './Station.jsx'; import { Belt, QueueBoxes, FlowBoxes } from './Conveyor.jsx'; import { stateMeta } from '../lib/format.js'; /** Station centres, evenly spaced along the line. */ const SPACING = 4.3; const stationX = (i, n) => (i - (n - 1) / 2) * SPACING; function Floor() { return ( <> {/* aisle markings, purely to give the eye a ground plane to read depth from */} {[-3.2, 3.2].map((z) => ( ))} ); } function LineContent() { const frame = useStore((s) => s.frame); const meta = useStore((s) => s.meta); const selected = useStore((s) => s.selected); const select = useStore((s) => s.select); if (!frame || !meta) return null; const n = frame.stations.length; return ( {frame.stations.map((st, i) => ( x.id === st.id)} x={stationX(i, n)} selected={selected === st.id} onSelect={select} /> ))} {frame.buffers.map((level, i) => { const x = (stationX(i, n) + stationX(i + 1, n)) / 2; const width = SPACING - 2.15; const upstream = frame.stations[i]; return ( = frame.bufferCapacity} /> ); })} ); } export function Scene() { const frame = useStore((s) => s.frame); const connected = useStore((s) => s.connected); const worstState = frame ? (frame.stations.find((s) => s.state === 'fault' || s.state === 'down') || frame.stations.find((s) => s.state === 'blocked')) : null; return (
{/* Analytic lights only - an HDRI would be a network fetch. */}
LINE-1 · Assembly & Cure {connected ? 'Live twin' : 'Disconnected'} {worstState ? ` · ${worstState.id} ${stateMeta(worstState.state).label.toLowerCase()}` : ' · all stations nominal'}
{/* Legend pairs every status colour with its word. */}
{['running', 'microstop', 'blocked', 'fault'].map((s) => { const sm = stateMeta(s); return ( {sm.label} ); })}
Drag to orbit · scroll to zoom · click a machine to inspect
); }