# Procedural Demo Set and Guided Tour Runtime
Milestone 4 ships a representative procedural machine set for the animation system. The demo set is intentionally data-driven: each machine module owns its geometry, part metadata, engineering facts, animation lifecycle, and guided tour content, while `proceduralDemoManifest.ts` provides a stable catalogue/runtime adapter for loading them without hard-coding viewer logic.
## Included procedural machines
| Machine | Category | Motion demonstrated | Primary highlighted parts |
| --- | --- | --- | --- |
| Four Stroke Petrol Engine | Engines | 720° Otto cycle with valve timing, piston travel, crankshaft/camshaft relationship | Piston, crankshaft, camshaft, intake valve, exhaust valve |
| Planetary Gearbox | Gearboxes & Drives | Sun/planet/ring epicyclic mesh and carrier rotation | Sun gear, planet gears, ring gear, carrier |
| Differential Gear | Gearboxes & Drives | Equal torque split with wheel speed difference while cornering | Ring gear, spider gears, side gears |
| Centrifugal Pump | Pumps & Fluid Systems | Impeller acceleration, volute pressure recovery, cavitation cueing | Impeller, volute, inlet, outlet, shaft |
| Geneva Drive | Mechanisms | Continuous crank rotation to intermittent indexed output | Driver, pin, Geneva wheel, locking disk |
| Ball Bearing | Structural / Other | Rolling contact, cage precession, load distribution | Inner race, outer race, balls, cage, load vector |
| Disc Brake Caliper | Structural / Other | Hydraulic clamp/release cycle, rotor drag, friction heat cueing | Rotor, caliper body, pads, pistons, hydraulic line |
| Wankel Rotary Engine | Engines | Eccentric rotor orbit, chamber volume change, port timing | Rotor, housing, eccentric shaft, intake port, exhaust port |
## Runtime loading
Use the manifest adapter for catalogue or viewer integrations:
```ts
import {
loadProceduralDemoMachine,
proceduralDemoMachineManifest,
} from '../src/modules/machines/procedural/demoRuntime';
const entry = proceduralDemoMachineManifest[0];
const machine = await loadProceduralDemoMachine(entry.id);
console.log(machine.title, machine.parts, machine.guidedTour);
```
For React views, use the hook:
```tsx
import { useProceduralDemoMachine } from '../src/modules/machines/procedural/demoRuntime';
export function DemoMachinePanel({ machineId }: { machineId: string }) {
const { status, machine, error, reload } = useProceduralDemoMachine(machineId);
if (status === 'loading') return
Loading machine…
;
if (status === 'error') return ;
if (!machine) return null;
return (
{machine.title}
{machine.description}
{machine.parts.length} modeled parts
);
}
```
The normalizer accepts several common machine-module shapes (`default`, `machine`, `definition`, `Scene`, `animationModule`, `parts`, `engineeringFacts`, `guidedTour`) so the core catalogue remains resilient as future machines are added.
## Guided tours
`GuidedTourPlayer` is a GSAP-ticker-backed tour controller that advances steps using requestAnimationFrame timing through `gsap.ticker`. It supports:
- play, pause, resume, restart, stop
- manual next/previous step navigation
- looped or one-shot tours
- time scale adjustment
- reduced-motion mode with shortened step durations and instant camera moves
- lifecycle hooks: `onEnter`, `onFrame`, `onExit`
- host callbacks for camera poses, part highlighting, part isolation, annotations, explode factor, machine playback, and RPM
A viewer supplies a host object:
```ts
import {
GuidedTourPlayer,
createThreeCameraTourHost,
} from '../src/animations/tourRuntime';
const host = createThreeCameraTourHost(camera, {
controls: orbitControls,
highlightParts: (partIds) => setHighlightedParts(partIds),
selectPart: (partId) => setSelectedPart(partId),
setExplodeFactor: (explodeFactor) => setExplode(explodeFactor ?? 0),
setMachinePlayback: (playback) => {
if (playback === 'pause') animation.pause();
else animation.play();
},
setRpm: (rpm) => animation.setRpm(rpm),
});
const player = new GuidedTourPlayer(machine.guidedTour, host, {
defaultStepDurationSeconds: 5,
loop: false,
});
```
React integrations should prefer `useGuidedTourPlayer`, which subscribes to snapshots and cleans up the GSAP ticker on unmount.
## UI controls
The new animation UI components are intentionally presentation-only:
- `AnimationTransport` renders playback, restart, step-through, RPM, time-scale, and loop controls.
- `GuidedTourOverlay` renders tour captions, step progress, keyboard controls, and direct step navigation.
They accept plain snapshots and callback objects, so they can be connected to the existing `MachineAnimationPlayer`, Zustand stores, or a page-level adapter without coupling the controls to machine-specific animation code.
## Authoring requirements for new machines
A new procedural machine should export at least:
1. A React scene component.
2. A standard animation module compatible with the milestone animation player.
3. Part metadata with stable IDs.
4. Engineering facts.
5. Guided tour steps using the `GuidedTourStepDefinition` shape.
6. A manifest entry with category, difficulty, keywords, RPM range, and featured part IDs.
Stable part IDs are important because they are used by:
- URL view-state sharing
- part visibility and opacity controls
- selected-part detail drawers
- guided-tour highlights
- annotations and labels
- accessibility announcements
## Reduced-motion behavior
Reduced-motion preference is detected with `prefers-reduced-motion: reduce` in `usePrefersReducedMotion`. When enabled:
- tour auto-start is suppressed unless explicitly allowed
- tour camera transitions are immediate
- default step durations are capped by `reducedMotionStepDurationSeconds`
- controls remain keyboard-accessible and fully functional
Machine animations should still honor their own reduced-motion policy, typically by starting paused and requiring explicit user playback.
## Quality checklist
Before marking a new machine production-ready:
- The loop has no visible discontinuity at the cycle seam.
- RPM scaling changes speed without changing kinematic relationships.
- Step-through advances to meaningful mechanical phases.
- Every selectable part has a human-readable name and useful description.
- Guided tour step highlights reference real part IDs.
- Camera poses avoid clipping through the model at desktop, tablet, and mobile aspect ratios.
- The scene is legible in solid, transparent, and wireframe display modes.
- Motion remains understandable at `0.1×` and does not become visually noisy at `3×`.
- Reduced-motion mode does not auto-animate camera or machine movement.
- All host subscriptions/tickers/tweens are disposed when leaving the viewer.