# Viewer Animation and Guided Tour Integration
Milestone 4 now includes a runtime bridge between the standardized machine animation modules, guided tours, and viewer UI state.
## Runtime bridge
The integration layer is intentionally small and page-friendly:
- `src/animations/playerAdapter.ts` normalizes `MachineAnimationPlayer` snapshots and exposes a stable control surface: play, pause, resume, restart, stop, RPM, time scale, loop, seek, and step forward/back.
- `src/animations/guidedTourAdapter.ts` normalizes guided tour player snapshots and exposes start, pause, resume, restart, previous/next, and go-to-step controls.
- `src/components/animation/AnimationRuntimeBridge.tsx` owns a player instance, subscribes to snapshots, handles reduced-motion preferences, and feeds the existing `AnimationTransport` component through compatibility props.
- `src/components/animation/GuidedTourRuntimeBridge.tsx` owns a guided tour instance, subscribes to active-step/highlight/camera data, and feeds the existing `GuidedTourOverlay` component through compatibility props.
The bridge passes both the current snapshot and control callbacks to UI components. This completes the missing connection where `MachineAnimationPlayer` data reaches transport controls and where transport callbacks call the active player instance.
## Procedural demo experience
`src/modules/machines/procedural/ProceduralDemoExperience.tsx` is a complete, self-contained viewer composition for the eight procedural machines:
- four-stroke petrol engine
- planetary gearbox
- differential gear
- centrifugal pump
- Geneva drive
- ball bearing
- disc brake caliper
- Wankel rotary engine
It wires:
- procedural machine scene rendering inside React Three Fiber
- animation snapshots into scene props
- guided-tour highlighted part IDs into scene props
- per-part visibility and opacity
- selected/hovered/highlighted part state
- exploded view amount
- wireframe and label toggles
- camera presets
- detail drawer
- shareable URL state
The page adapter `src/pages/ProceduralDemoPage.tsx` can be mounted by the existing router at a route such as `/procedural/:machineId`, `/machines/:machineId/demo`, or as a fallback machine viewer route.
## Manifest validation
`src/modules/machines/procedural/proceduralDemoCatalog.ts` imports each machine module as a namespace and resolves the exact exported machine definition at runtime. This avoids fragile named-export drift while still validating that every required module resolves to a machine definition with a scene component, animation module, guided tour, and part metadata.
Use this during development or tests:
```ts
import { assertProceduralDemoCatalog } from './src/modules/machines/procedural/proceduralDemoManifest';
assertProceduralDemoCatalog();
```
The validation report is also exported as `proceduralDemoCatalogValidationReport`.
## URL state
The procedural viewer encodes the important share state into query parameters:
- `machine`
- `part`
- `explode`
- `wireframe`
- `labels`
- `camera`
- `hidden`
- `opacity`
The `Share` button writes the current URL to the clipboard.
## Router integration
To expose the demo page, import the page into the existing app router:
```tsx
import ProceduralDemoPage from './pages/ProceduralDemoPage';
// Example route element:
// } />
```
If the app uses a custom page switch instead of React Router, render `` from the existing machine-view branch. The page reads `?machine=` first, then the last path segment, so both `/procedural?machine=wankel-rotary-engine` and `/procedural/wankel-rotary-engine` work.
## Maintainer verification notes
Because this pass cannot run the compiler here, verify the following APIs against the resolved dependency versions after install:
- `@react-three/drei`: `Environment`, `OrbitControls`, `ContactShadows`, and `Html` props.
- `@react-three/fiber`: `Canvas`, `useThree`, and the `makeDefault` controls registration behavior.
- Existing local components: exported names from `AnimationTransport`, `GuidedTourOverlay`, `MachineAnimationPlayer`, and `GuidedTourPlayer`.
The integration uses compatibility adapters for these local exports, but a local build should still confirm there are no project-specific lint restrictions around dynamic compatibility props.