# 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.