--- id: PLN-0019 ticket: render-all-scene-cache-and-camera-integration title: Plan - Scene Binding, Camera, and Scene Status status: accepted created: 2026-04-14 completed: tags: [gfx, runtime, render, scene, camera, frame-composer] --- ## Objective Implement the `FrameComposer` scene-binding contract, minimal camera state, and explicit scene-availability status without yet completing the cache-refresh render path. ## Background `DEC-0014` locks scene activation around `bind_scene(scene_bank_id)` with `SceneBankPoolAccess`, pointer-based access only, and `scene_bank_id + Arc` retained inside `FrameComposer`. The same decision also requires `FrameComposer` to remain tile-size agnostic and to preserve canonical per-layer `tile_size`, including `8x8`. For the scene-layer motion contract, this plan treats `parallax_factor` as the canonical field name for the per-layer camera multiplier. ## Scope ### Included - scene bind/unbind contract - active scene identity and shared reference storage - scene availability status - minimal camera state (`i32`, top-left viewport) ### Excluded - applying cache refreshes - full render-path migration - HUD behavior ## Execution Steps ### Step 1 - Add scene binding state to `FrameComposer` **What:** Implement the canonical bind/unbind surface. **How:** - Add `bind_scene(scene_bank_id)` and `unbind_scene()`. - Resolve scenes from `SceneBankPoolAccess`. - Store both: - `scene_bank_id` - `Arc` - Replace prior scene binding completely on a new bind. **File(s):** - `crates/console/prometeu-drivers/src/frame_composer.rs` - `crates/console/prometeu-drivers/src/memory_banks.rs` ### Step 2 - Add explicit scene status **What:** Expose scene availability through status, not just implicit option checks. **How:** - Define a scene status enum or equivalent status object. - Distinguish at least: - no scene bound - bound and available - bound but not renderable if such intermediate state is needed - Ensure no-scene rendering remains valid. **File(s):** - `crates/console/prometeu-drivers/src/frame_composer.rs` - optional HAL-facing status surface if needed later ### Step 3 - Add camera contract **What:** Implement the V1 camera ownership inside `FrameComposer`. **How:** - Add `set_camera(x, y)`. - Store camera coordinates as `i32`. - Treat them as top-left viewport coordinates in world space. - Keep all advanced camera behavior out of scope. **File(s):** - `crates/console/prometeu-drivers/src/frame_composer.rs` ### Step 4 - Tie cache/resolver lifetime to scene binding **What:** Align cache/resolver lifetime with the active scene contract. **How:** - Cache and resolver remain `None` / absent when no scene is bound. - On bind: - create or reinitialize cache/resolver. - On unbind: - discard cache/resolver and invalidate the world path. - Any initialization must derive layer math from the bound scene tile sizes instead of assuming `16x16`. - Any layer-camera math or related contract references must use `parallax_factor` terminology rather than generic `motion` naming. **File(s):** - `crates/console/prometeu-drivers/src/frame_composer.rs` ## Test Requirements ### Unit Tests - bind stores `scene_bank_id + Arc`. - unbind clears active scene and cache. - scene status reflects no-scene and active-scene states. - camera coordinates are stored as top-left pixel-space values. - bind/unbind remains valid for scenes whose layers use `8x8` tiles. - scene binding and camera-facing contracts preserve `parallax_factor` as the canonical layer field name. ### Integration Tests - `FrameComposer` can resolve a scene from the pool and survive no-scene operation. ### Manual Verification - Confirm scene access remains pointer-based and no scene copies are introduced. ## Acceptance Criteria - [ ] `FrameComposer` binds scenes by bank id through `SceneBankPoolAccess`. - [ ] Active binding stores both scene id and shared scene reference. - [ ] Scene status is explicit. - [ ] Camera contract is implemented as `i32` top-left viewport coordinates. - [ ] Cache/resolver lifetime follows scene bind/unbind. - [ ] Scene bind/cache/resolver setup preserves canonical per-layer tile sizes, including `8x8`. - [ ] Scene-layer camera multiplier naming is aligned on `parallax_factor`. ## Dependencies - Depends on `PLN-0017` - Source decision: `DEC-0014` ## Risks - Weak scene-status semantics can make no-scene behavior ambiguous in later render integration. - If cache/resolver lifetime is not tied cleanly to binding, stale world state can leak across scene transitions.