# Sequencer Timeline Playback

This document records the `TODOS.phase-72.72.15.1.2` cinematic sequencer
timeline playback contract. The playback layer is a stateless runtime engine on
top of `FV2SequencerSequenceSpec`: callers pass playback settings, a current
cursor, and a delta or command, then receive a new evaluated cursor.

## Runtime Ownership

- Runtime module: `V2Cinematics`
- Settings struct: `FV2SequencerPlaybackSettings`
- Cursor struct: `FV2SequencerPlaybackCursor`
- Evaluation struct: `FV2SequencerPlaybackEvaluation`
- Issue struct: `FV2SequencerPlaybackIssue`
- Status enum: `EV2SequencerPlaybackStatus`
- Direction enum: `EV2SequencerPlaybackDirection`
- Issue enum: `EV2SequencerPlaybackIssueType`
- Automation: `V2.Cinematics.Sequencer.TimelinePlayback`
- CI checker: `V2/ue/Tools/check-v2-sequencer-timeline-playback.py`

## Playback Controls

The required playback controls are exposed as pure Blueprint helpers:

- `BuildSequencerPlaybackSettings` configures loop, reverse, playback rate,
  start frame, end frame, and scrub-clamping behavior.
- `BuildSequencerPlaybackCursor` creates the initial timeline cursor at either
  the resolved start frame or resolved end frame.
- `PlaySequencerTimeline` resumes playback in forward or reverse direction.
- `PauseSequencerTimeline` freezes the cursor without advancing on later ticks.
- `ScrubSequencerTimeline` moves the cursor to a target frame and can clamp or
  reject out-of-range requests.
- `SetSequencerTimelinePlaybackRate` updates variable speed without rebuilding
  the sequence model.
- `EvaluateSequencerTimelinePlayback` advances a playing cursor by
  `DeltaSeconds * TickResolutionFps * PlaybackRate`.

## Engine Behavior

`FV2SequencerPlaybackSettings` resolves `EndFrame == 0` to the sequence
duration, allowing the default data model to play the full
`Seq.DataModel.CouncilIntro` fixture without repeated boilerplate. Playback rate
must be greater than zero, and playback ranges must resolve to `StartFrame`
before `EndFrame` inside the sequence duration.

Core tick behavior:

- Forward playback advances frames until the end of the resolved range.
- Reverse playback subtracts frames until the start of the resolved range.
- When `bLoop` is true, overshoot wraps around and marks `bLoopedThisTick`.
- When `bLoop` is false, overshoot clamps to the boundary and marks `bCompleted`
  with `EV2SequencerPlaybackStatus::Completed`.

Paused and scrubbing cursors do not advance during tick evaluation. Scrubbed
cursors use `EV2SequencerPlaybackStatus::Scrubbing`, which lets editor UI and
runtime preview flows distinguish timeline dragging from paused playback.

## Validation

`ValidateSequencerDataModel` remains the first gate for playback. Playback
evaluation also reports `InvalidSequence`, `InvalidFrameRange`,
`InvalidPlaybackRate`, `InvalidDeltaSeconds`, and `ScrubFrameOutOfRange` issues
through `FV2SequencerPlaybackEvaluation::Issues`.

## Verification

Run:

```bash
python3 V2/ue/Tools/check-v2-sequencer-timeline-playback.py
```

Adjacent verification should include
`python3 V2/ue/Tools/check-v2-sequencer-data-model.py` and
`python3 V2/ue/Tools/check-v2-cinematics-module.py` so playback remains bound to
the sequencer data model and module inventory.
