> ## Documentation Index
> Fetch the complete documentation index at: https://docs.teriyakigaming.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ink Page Reader

> Snap a page into view for reading and float it back exactly where it lay — with fit-to-view framing, a flip to the back of the sheet, movement and camera locks, and physics capture.

**Ink Page Reader** (`UInkPageReaderComponent`) is the component that lets a player pick
up and read a page. Add it to your player — pawn, character or player controller — and
call **Begin Reading**: the page floats up in front of the camera, held at a distance
where it fills a comfortable slice of the screen. Call **End Reading** and it floats back
to exactly where it was lying. **Flip Page** turns the sheet over to show its back.

The reader is the **presentation engine**: it contains no interaction logic and almost no
input handling. It is driven by whatever runs interaction in your project — your own
interaction component, a Blueprint trigger, or the bundled
[Ink Page Interactor](/plugins/inkwell/components/interactor). Every function is Blueprint-callable.

<Note>
  **This is a production component.** Unlike the bundled interaction pieces — the
  [Ink Page Interactor](/plugins/inkwell/components/interactor), the showroom's demo character, game mode
  and prompt widget, which are reference implementations — the reader is what your own
  interaction system is meant to call. The one demo-flavored thing on it is the optional
  flip-key binding (**Bind Flip Key**, on by default so the back of a sheet is reachable
  out of the box); turn it off when you bind your own flip input.
</Note>

The reader moves the **actor** that owns the page — the owner of the
[Ink Page Display](/plugins/inkwell/components/page-display) component you hand to Begin Reading — so
anything attached to that actor rides along. The level still owns the actor; the reader
holds only weak references to it.

## Adding it

Add **Ink Page Reader** from the **Add Component** menu (category **Inkwell**) to your
player pawn, character or player controller. It is Blueprint-spawnable and Blueprintable,
so you can subclass it if you want your own defaults.

Where you put it decides which controller the input locks reach: on a **pawn**, the
reader resolves the pawn's possessing controller; on a **controller**, that controller is
used directly. Either works. (The flip-key binding is the exception: it binds on the
owning **pawn's** input component, so a reader living on a controller never binds it.)

If you use the [Ink Page Interactor](/plugins/inkwell/components/interactor) for prototyping, you do not
need to add a reader yourself — the interactor reuses one on its owner if there is one,
and creates one if there is not.

## Wiring it to your interaction system

<Steps>
  <Step title="Add the component">
    Open your character Blueprint, click **Add Component**, and add **Ink Page Reader**.
    Leave the defaults for now.
  </Step>

  <Step title="Find something to read">
    Your interaction code needs the page. If it already line-traces, take the **Hit Actor**;
    if it uses an interface or an overlap, take that actor. Any actor carrying an
    [Ink Page Display](/plugins/inkwell/components/page-display) — including a placed
    [Ink Page](/plugins/inkwell/components/page-actor) and an [Ink Page Stack](/plugins/inkwell/components/page-stack) — is
    readable.
  </Step>

  <Step title="Start the read">
    On your interact input: **Branch** on **Is Reading**. False → **Begin Reading Actor**
    with the hit actor. True → **End Reading**. That single toggle is the whole open/close
    loop.
  </Step>

  <Step title="Turn pages">
    Bind your page-turn input to **Next Page** and **Previous Page** on the reader. They do
    nothing unless a page is up, so they are safe to leave bound all the time. On a sheet
    with an authored back they follow [book order](#book-order) — front, back, then the next
    page.
  </Step>

  <Step title="React in the HUD">
    On **Event Begin Play**, bind **On Reading Started** and **On Reading Ended**. Hide the
    crosshair and show a "put back" prompt on the first; restore the HUD on the second. Bind
    **On Reading Side Changed** if your HUD shows a Front/Back label.
  </Step>

  <Step title="Play it">
    Walk up to a page and press your interact key. The sheet should float to your eyes over
    about a third of a second, your movement should stop, and the view should freeze. Press
    **F** to turn it over. Press your interact key again and it settles back exactly where it
    was.
  </Step>
</Steps>

<Warning>
  If **Begin Reading Actor** returns false, either the actor has no Ink Page Display
  component on it, or a page is already up — the reader refuses a second read while one is
  being held. Call **End Reading** first, or use the **Is Reading** toggle above.
</Warning>

## Properties

All properties live under **Inkwell → Reading**, are editable per instance, and are
readable and writable from Blueprint at runtime.

| Property                                                      | Type      | Default                        | What it does                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------------------------------------- | --------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Fit Page To View** (`bFitPageToView`)                       | Boolean   | `true`                         | Work out the hold distance from the page's real size and the camera's field of view, so a 60×90 cm playbill and a 7.6 cm sticky note each fill the same comfortable slice of the screen. Off: the flat **View Distance** below is used verbatim, exactly what earlier versions of Inkwell did.                                                                           |
| **View Fill Fraction** (`ViewFillFraction`)                   | Float     | `0.75`                         | How much of the screen the page should cover with the fit on, as a fraction of the viewport's height (and of its width — whichever runs out first wins, so a landscape page fits sideways too). Clamped 0.05–1.0.                                                                                                                                                        |
| **Min View Distance** (`MinViewDistance`)                     | Float     | `18.0`                         | Closest the fitted distance may come, in centimeters, so a postage-stamp prop is not pulled through the near clip plane. The reader also enforces its own floor of the near plane plus half the page's width — room for the page to [flip](#turning-the-sheet-over) without crossing the eye — and the larger floor wins. Clamped to at least 1; the slider covers 5–60. |
| **Max View Distance** (`MaxViewDistance`)                     | Float     | `90.0`                         | Furthest the fitted distance may go, in centimeters — the cap that keeps a big page from being pushed into the furniture behind it. A page too tall to fit on screen at the cap shows its readable middle. Yields to the floor above rather than fighting it. Clamped to at least 1; the slider covers 50–1000.                                                          |
| **View Distance** (`ViewDistance`)                            | Float     | `45.0`                         | How far in front of the camera the page floats, in centimeters, used verbatim when **Fit Page To View** is off. With the fit on it is only the reference distance **View Offset** is measured against. Clamped to at least 1; the slider covers 10–200.                                                                                                                  |
| **View Offset** (`ViewOffset`)                                | Vector 2D | `(0.0, -2.0)`                  | Nudges the page on screen, in centimeters: **X** moves it right, **Y** moves it up. The default drops it 2 cm below center. With the fit on, the nudge scales with the fitted distance so it looks like the same drop at every distance.                                                                                                                                 |
| **Reading Rotation Offset** (`ReadingRotationOffset`)         | Rotator   | Pitch `0`, Yaw `90`, Roll `90` | Extra rotation composed onto the camera rotation so the sheet's printed face points at the viewer with the text upright. Tuned for the Inkwell page sheet. See [Customizing the reading pose](#customizing-the-reading-pose).                                                                                                                                            |
| **Blend Time** (`BlendTime`)                                  | Float     | `0.3`                          | Seconds the page takes to float up and back. `0` snaps instantly, both ways. The slider covers 0–2.                                                                                                                                                                                                                                                                      |
| **Flip Duration** (`FlipDuration`)                            | Float     | `0.35`                         | Seconds a flip takes to turn the sheet over. `0` snaps, the same contract as Blend Time. The slider covers 0–2.                                                                                                                                                                                                                                                          |
| **Bind Flip Key** (`bBindFlipKey`)                            | Boolean   | `true`                         | Bind **Flip Key** on the owning pawn so a page can be turned over out of the box. Separate from the interactor's **Enable Default Input** on purpose: flipping is a reader operation with no other way to reach it. The binding does not consume input.                                                                                                                  |
| **Flip Key** (`FlipKey`)                                      | Key       | `F`                            | The key **Bind Flip Key** binds. Only meaningful while that is on.                                                                                                                                                                                                                                                                                                       |
| **Keep Clear Of Obstructions** (`bKeepClearOfObstructions`)   | Boolean   | `true`                         | Trace along the view and pull the held page in front of whatever the player is facing, so reading something off a podium while looking down does not sink the page into the podium. See [Staying out of the furniture](#staying-out-of-the-furniture).                                                                                                                   |
| **Return To Front On Page Turn** (`bReturnToFrontOnPageTurn`) | Boolean   | `true`                         | Turn a flipped page back to its front when the reader moves to another page — a new page has a new back the player never chose to look at.                                                                                                                                                                                                                               |
| **Follow Camera** (`bFollowCamera`)                           | Boolean   | `true`                         | Keep the page glued to the view, so it stays centered as the player looks around. Off: the page floats to where the camera was pointing when the read began, and stays there.                                                                                                                                                                                            |
| **Lock Movement While Reading** (`bLockMovementWhileReading`) | Boolean   | `true`                         | Stop the reading pawn from moving while a page is up — including jumping. See [The locks](#the-locks).                                                                                                                                                                                                                                                                   |
| **Lock Look While Reading** (`bLockLookWhileReading`)         | Boolean   | `true`                         | Freeze the camera while a page is up, so the view cannot rotate while the page is being inspected. See [The locks](#the-locks).                                                                                                                                                                                                                                          |

## How a read plays out

The reader moves through four phases:

1. **Idle** — nothing held. The component does not tick at all.
2. **Blend in** — the page floats from where it lay to the reading pose over **Blend
   Time** seconds, on a smoothstep curve so the pick-up eases in and out.
3. **Reading** — held at the eyes. With **Follow Camera** on, the pose is recomputed every
   frame; with it off, the component stops ticking here (unless a flip is still turning),
   because nothing is left to move.
4. **Blend out** — the same smoothstep in reverse, back onto the exact transform the actor
   had when the read began. Collision and physics are restored when it lands.

**Is Reading** is true through blend-in and reading — including while the page is still on
its way up — and false during blend-out. **Get Current Page** returns the page being read,
or None.

The put-back descends from wherever the page actually was: the reading target is frozen
at the moment **End Reading** is called, before **On Reading Ended** fires. So a listener
that restores reader properties on that event — a per-prop tuning component putting
**View Fill Fraction** back, for example — cannot yank the descending page to a different
distance. Overrides applied while reading release cleanly. A page put back while turned
over unwinds its flip on the way down, landing front-up on the exact pose it was picked
up from.

### Where the page goes

The pose is derived from the player's view point:

* A **possessed pawn** reads through its controller's view point, so camera managers, view
  targets and control rotation are all respected.
* Anything else — an unpossessed pawn, a non-pawn owner — falls back to the actor's eyes
  view point.

From there the page is placed straight ahead at the [hold distance](#how-the-hold-distance-is-chosen),
nudged by **View Offset** along the camera's right and up axes, and rotated by the camera
rotation composed with **Reading Rotation Offset**. Scale is never part of the pose: the
page keeps the physical size its document, **Page Scale** and actor scale give it.

With **Follow Camera** off, the target is captured once, at the moment the blend starts.

### How the hold distance is chosen

With **Fit Page To View** on (the default), the reader computes the distance at which the
page covers **View Fill Fraction** of the screen — against the viewport's real field of
view and aspect ratio, height and width both, whichever runs out first. The page size used
is the **document's** printed size times **Page Scale** times the actor's scale, not the
mesh bounds — on the showroom's poster board it is the 60×90 cm page being framed, not
the plywood around it.

The result is clamped between a floor and **Max View Distance**:

* The floor is the larger of **Min View Distance** and the near clip plane plus half the
  page's width. The second term is what guarantees a flip can swing the sheet's edge
  toward the camera without any part of it crossing the near plane — applied whether or
  not a flip is running, so starting one never makes the page lurch backwards.
* **Max View Distance** yields to the floor rather than fighting it.

With the fit off, **View Distance** is used verbatim — to the centimeter, so a project
that tuned it keeps its framing. On that manual path a flip that needs more room than the
tuned distance allows eases the page away from the eye for the duration of the turn and
brings it straight back.

**Get Reading Distance** returns the distance in use — the fitted value, or View Distance
when the fit is off, before the obstruction clamp — and `0` when nothing is being read.

### Staying out of the furniture

The hold distance is measured along the view with no knowledge of the world, so with
**Keep Clear Of Obstructions** on (the default) the reader traces the view ray on the
**Visibility** channel — ignoring the page actor and the reader's own pawn — and pulls
the page in front of the first blocking hit, with a margin for the edge that swings out
mid-flip. Pressed right up against a wall, the distance is floored at the near-plane term
so the page stays visible rather than comfortable.

## Book order

On a multipage document whose sheets have authored backs (see
[two-sided pages](/plugins/inkwell/authoring/documents)), **Next Page** and **Previous Page** read the
document the way a book is read:

* **Next Page** on a front face whose sheet has an authored back **turns the sheet over**
  instead of skipping what is written on the other side. On a front with no back, it
  turns to the next page as usual.
* **Previous Page** on a back face returns to the **front of the same sheet** before it
  retreats a page.
* With **Return To Front On Page Turn** on (the default), an actual page turn also turns
  the new sheet front-up.

This is also what makes a two-sided single-page note readable with the same two inputs as
everything else: forward is the flip, and there is no third thing to press. A sheet with
no authored back never flips on a page turn — an unauthored back costs nothing and shows
nothing.

## Turning the sheet over

**Flip Page** turns the held page over, animated over **Flip Duration** seconds. It is a
toggle against the side the page is currently turning *towards*, not the side on screen —
so tapping it twice in quick succession reverses the turn and settles back where it
started rather than finishing the rotation anyway. It never changes which page is shown:
"Page 2 of 3" does not move, and **On Page Changed** does not fire.

The turn is about whichever of the page's own axes **Reading Rotation Offset** puts
vertically on screen, so a custom prop with its own offset still turns the way a sheet of
paper turns. It rotates about the page **actor's** origin: a mesh whose page face is
off-center will swing rather than spin.

| Node                      | Returns       | What it does                                                                                                                                                             |
| ------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Flip Page**             | Boolean       | Toggle the held page over. False when no page is held up.                                                                                                                |
| **Set Reading Side**      | Boolean       | Turn the held page to a specific **Side** (Front / Back). **Animate** off snaps — what you want when restoring saved state rather than reacting to a keypress.           |
| **Set Showing Back**      | Boolean       | Convenience over Set Reading Side for a plain boolean toggle.                                                                                                            |
| **Get Reading Side**      | Ink Page Side | The face turned towards the viewer right now. Swaps at the halfway point of a flip, so it always agrees with what the player sees. Front whenever nothing is being read. |
| **Is Showing Back**       | Boolean       | True while the back of the sheet is the face on screen.                                                                                                                  |
| **Get Reading Side Text** | Text          | "Front" or "Back", ready to drop into a HUD label.                                                                                                                       |
| **Is Flipping**           | Boolean       | True while a flip is still in motion.                                                                                                                                    |
| **Can Flip Page**         | Boolean       | True when there is a page held up that Flip Page would turn — use it to gray out a prompt.                                                                               |

With **Bind Flip Key** on, the reader binds **Flip Key** (default **F**) on the owning
pawn once the pawn has an input component, retrying on a timer until it does. The binding
does not consume input, so it sits alongside your Enhanced Input mappings rather than
swallowing the key, and it quietly does nothing while no page is held. Turn **Bind Flip
Key** off when you route your own input to **Flip Page**.

## Customizing the reading pose

The pose properties are all live: change them from Blueprint mid-read and the next frame
uses the new values (with **Follow Camera** on). That makes tuning quick — set them on
the component's Details panel, press Play, read a page, and adjust. The showroom's
demo-only Inkwell Exhibit component is a worked example of exactly this: it writes the
reader's public properties when a read starts and restores them when it ends.

**Making the page bigger or smaller on screen.** With **Fit Page To View** on, raise
**View Fill Fraction** to fill more of the screen. With it off, apparent size is a
function of distance: lower **View Distance**. If a page needs to be physically larger
everywhere — in the world as well as in the hand — change
[**Page Scale**](/plugins/inkwell/components/page-display#sizing) on the display component instead.

**Framing.** **View Offset** is in centimeters at the page, not in screen percent. The
default `(0, -2)` drops the sheet slightly below eye line, which reads as "held in the
hands" rather than "pinned to the face". Positive **X** shifts it right — useful if your
HUD occupies one side. With the fit on, the nudge is scaled with the fitted distance so
its apparent size stays constant; with the fit off it is untouched, to the centimeter.

**Orientation.** `ReadingRotationOffset` is composed onto the camera rotation, so it
describes the sheet's orientation *relative to the view*, not to the world. The default —
Pitch 0, Yaw 90, Roll 90 — is tuned for the Inkwell page sheet, a flat plane whose printed
face points up: it turns the sheet to face the camera and then spins it in its own plane
so the writing reads upright.

If you read from your own mesh, tune it like this:

<Steps>
  <Step title="Start from zero">
    Set **Reading Rotation Offset** to `(0, 0, 0)` and read the page once. The sheet is now
    aligned with the camera's own axes, which tells you where its printed face is pointing.
  </Step>

  <Step title="Point the face at the viewer">
    Adjust **Pitch** and **Yaw** in 90-degree steps until you can see the printed side. Both
    turn the sheet's face; which one you need depends on which axis your mesh's face lies on.
  </Step>

  <Step title="Stand the writing upright">
    Adjust **Roll** in 90-degree steps. Roll spins the sheet within its own plane, so it only
    changes which edge is up.
  </Step>

  <Step title="Fix mirrored text">
    Text that reads backwards means you are looking at the back of the sheet. Add 180 degrees
    to whichever of Pitch or Yaw you used in step 2.
  </Step>

  <Step title="Save it">
    Put the final rotator on the reader's defaults. If different props need different offsets,
    set **Reading Rotation Offset** from Blueprint just before calling **Begin Reading**.
    The flip axis follows the offset automatically, so a prop with its own offset still flips
    correctly.
  </Step>
</Steps>

<Tip>
  For a "pinned in place" feel — the page stays where the player lifted it and they can look
  around it — turn **Follow Camera** off and **Lock Look While Reading** off together. With
  the look lock on (the default) the camera cannot rotate anyway, so Follow Camera makes
  little visible difference.
</Tip>

## The locks

The reader has **two independent input locks**, both on by default. They engage the moment
**Begin Reading** succeeds and release the moment **End Reading** is called — *not* when
the page finishes floating down — so control comes back instantly when the player lets go.

### Lock Movement While Reading

* Move input on the controller is ignored (`SetIgnoreMoveInput`).
* The pawn's current motion is stopped immediately — **unless it is falling**. An airborne
  pawn is left alone, because zeroing velocity mid-jump would freeze it in the air.
* **Jumping is covered too.** Ignoring move input does not stop a character from jumping,
  so for an `ACharacter` the reader also calls **Stop Jumping** and clears the character
  movement component's own jump permission (`NavAgentProps.bCanJump`), restoring the saved
  value on unlock. This is the part most hand-rolled "freeze the player" code misses.

### Lock Look While Reading

* Look input on the controller is ignored (`SetIgnoreLookInput`), so the view cannot rotate
  while the page is being inspected. Combined with **Follow Camera**, the page stays
  perfectly still in front of the reader.

### How the locks behave around the engine

The engine's ignore-input counters stack, so the reader is careful with them:

* Each lock is taken **at most once per read**, and the reader remembers exactly which
  controller it locked, so exactly that one is released.
* If possession arrives or resets mid-read — a client restart zeroes a controller's ignore
  counters — the reader re-asserts both locks from its tick while a page is up. Best
  effort: with **Follow Camera** off the tick sleeps during the reading phase, so
  re-assertion cannot run there.
* On release, a pawn-mounted reader whose controller has meanwhile possessed a *different*
  pawn does not decrement the counters: the engine already reset them on repossession, and
  decrementing would steal another system's lock. A reader living on a controller always
  releases.
* The character's jump permission is restored only if it is still disabled, so an outside
  system that deliberately re-enabled jumping mid-read keeps its change.

<Note>
  If your project runs its own input-state machine ("in menu", "in cutscene", "reading"),
  turn both locks off and manage input yourself. **On Reading Started** and **On Reading
  Ended** fire at exactly the right moments to drive it.
</Note>

## Physics and collision capture

When a read begins the reader captures everything needed to put the page back exactly as
it was:

* The page actor's **full transform** is saved. That is the blend-back destination.
* Every primitive on the actor that is **simulating physics** — a loose sheet the player
  can knock off a desk — has simulation switched off for the ride, because a simulating
  body ignores actor moves. Each one is re-attached to the actor's root so it follows the
  actor while held.
* The actor's **collision is disabled**, with its previous state saved, so nothing traces
  against or bumps into a page held at the reader's face. (This is also why a page's own
  blocking collision — see [Ink Page actor](/plugins/inkwell/components/page-actor#collision) — is not a
  problem while reading.)

On landing, the reverse: the actor is teleported onto its saved transform, collision is
restored to the saved state, and simulation is switched back on for every primitive that
had it. Re-enabling simulation re-detaches those meshes from the actor root, which is
standard engine behavior and exactly the state they were in before.

## Events

| Event                                                | When it fires                                                                                                                                                                       | Payload                                                                                                                                       |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **On Reading Started** (`OnReadingStarted`)          | A page starts being read (Begin Reading succeeded). Hide the crosshair, show a close prompt, play a paper rustle.                                                                   | **Page** — the Ink Page Display being read.                                                                                                   |
| **On Reading Ended** (`OnReadingEnded`)              | The page is put back down: End Reading was called, the page actor was destroyed mid-read, or the reader itself was torn down. Restore your HUD here.                                | **Page** — the display that was being read. **Can be None** when the page actor was destroyed while it was up, so listeners must tolerate it. |
| **On Reading Side Changed** (`OnReadingSideChanged`) | The face turned towards the viewer changes — at the **halfway point** of a flip, the frame the paper goes edge-on, so a Front/Back HUD label bound to it swaps exactly on the turn. | **Page** — the display being read (can be None if the actor died mid-read). **Side** — the face now towards the camera.                       |

## Blueprint API

| Node                     | Returns          | What it does                                                                                                                                                                                                 |
| ------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Begin Reading**        | Boolean          | Floats the given Ink Page Display's actor up in front of the camera. False when the page is invalid or something is already being read.                                                                      |
| **Begin Reading Actor**  | Boolean          | The same, but finds the Ink Page Display on the given actor for you.                                                                                                                                         |
| **End Reading**          | —                | Puts the page back down; it blends back to exactly where it was. Does nothing when nothing is being read. Both locks release immediately.                                                                    |
| **Is Reading**           | Boolean          | True while a page is held up, including while it is still floating up. False during the float back down.                                                                                                     |
| **Get Current Page**     | Ink Page Display | The page being read, or None.                                                                                                                                                                                |
| **Next Page**            | Boolean          | Turns forward in [book order](#book-order): a front with an authored back flips over first, otherwise the display's **Next Page** runs. False when not reading, or on the last page with **Loop Pages** off. |
| **Previous Page**        | Boolean          | Turns back in book order: a back face returns to its own front first. False when not reading, or on the first page with **Loop Pages** off.                                                                  |
| **Get Reading Distance** | Float            | Centimeters the page is being held in front of the camera — the fitted value, or **View Distance** when the fit is off. `0` when not reading.                                                                |

The flip half of the API — **Flip Page**, **Set Reading Side**, **Set Showing Back**,
**Get Reading Side**, **Is Showing Back**, **Get Reading Side Text**, **Is Flipping**,
**Can Flip Page** — is tabled under
[Turning the sheet over](#turning-the-sheet-over).

<Tip>
  [Ink Page Stack](/plugins/inkwell/components/page-stack) is itself an Ink Page Display, so **Begin Reading
  Actor** on a journal lifts the whole pile — thickness, fan and all — and **Next Page**
  animates its page turns while it is up.
</Tip>

### Starting a read while a page is floating back

Calling **Begin Reading** during a blend-out is handled for you:

* **The same page**, still on its way down: the blend reverses from wherever the page
  currently is. The original resting transform and physics state stay as captured, so it
  still lands home correctly later. A flip still unwinding keeps unwinding smoothly.
* **A different page**, still on its way down: the old one is put home instantly, then the
  new read starts from scratch.

While a page is actively up (blend-in or reading), **Begin Reading** refuses and returns
false. Call **End Reading** first.

## Edge cases the reader handles

<AccordionGroup>
  <Accordion title="The page actor is destroyed mid-read">
    If the held actor disappears — destroyed by gameplay, or its level streamed out — the
    reader lets go on its next tick: locks released, captured state cleared (there is nothing
    left to snap home), and **On Reading Ended** broadcast. The event's **Page** may
    legitimately be None here, so HUD listeners must handle that. A verbose `LogInkwell`
    message records it.
  </Accordion>

  <Accordion title="The reader is torn down mid-read">
    On End Play — the pawn is destroyed, the level changes — the reader never leaves a page
    floating in the air with its physics off. It snaps the page home, restores collision and
    physics, releases the locks and broadcasts **On Reading Ended**. From then until the next
    Begin Play it also **refuses new reads**, so an On Reading Ended listener that reacts by
    starting another read cannot take state that could never be released.
  </Accordion>

  <Accordion title="Blend Time is 0">
    The page snaps straight to the eyes on Begin Reading and straight home on End Reading. No
    blend phases, but the same capture, restore and events. Flip Duration 0 does the same for
    flips.
  </Accordion>

  <Accordion title="The page is put back while turned over">
    End Reading targets the front: the sheet unwinds its flip during the descent and lands
    front-up on the exact pose it was picked up from — never 180 degrees out from how it
    actually lies. The flip state is then cleared silently; On Reading Ended is the only
    signal for the read being over.
  </Accordion>

  <Accordion title="Restoring twice">
    Every teardown path funnels through one restore routine, and unlocking is safe to call
    when nothing is locked. You cannot double-release or leak a lock by hitting several edge
    cases at once.
  </Accordion>
</AccordionGroup>

## Next

<CardGroup cols={2}>
  <Card title="Integration guide" icon="plug" href="/plugins/inkwell/guides/integration">
    Driving the reader from an interaction system you already have.
  </Card>

  <Card title="Ink Page Interactor" icon="hand-pointer" href="/plugins/inkwell/components/interactor">
    The demo focus trace and keys — a worked reference for what your system should call.
  </Card>

  <Card title="Ink Page Stack" icon="layer-group" href="/plugins/inkwell/components/page-stack">
    Reading a whole journal instead of a single sheet.
  </Card>
</CardGroup>
