---
title: "camera"
description: "The camera namespace — the engine's Luau API reference for camera."
section: "API Reference"
slug: "api-camera"
canonical: "https://origozero.ai/docs/api-camera"
updated: "2026-09-06T10:26:32.381291370+00:00"
tags: ["api", "reference"]
---

# camera

The `camera` namespace — 41 functions.

## globals/camera/active {#globals-camera-active}

```lua
camera.active() -> string?
```

Entity id of the on-screen render camera this frame — whichever camera
wins the viewport by priority (the editor fly-camera in edit mode, the
gameplay camera in play). Render features, billboards, and input bases that
must follow the human's on-screen view read this.

**Returns** `string?` — Entity id of the on-screen camera, or nil if none is active — including the frame after that camera's entity is despawned.

```lua
local camId = camera.active()
```

## globals/camera/cut {#globals-camera-cut}

```lua
camera.cut()
```

Declare that the camera on screen cuts: the next frame it draws stands
somewhere it did not travel to. Motion vectors are the difference between
where a surface projects now and where it projected on the camera's
previous frame, and everything temporal reads that difference — the shutter
reconstructs the frame by walking it, a temporal resolve reprojects its
history along it. Across a cut that difference describes a displacement no
surface made, so the frame is reconstructed from taps a whole screen away
and belongs to neither shot. A declared cut leaves the camera with no
previous frame for exactly one frame, which is the state its very first
frame is already in, so every consumer reads zero motion across the cut.
Declare it in the same step that places the camera at the new station;
declaring it again before that frame draws still costs the one frame.
Handing the viewport from one camera to another is already a cut without
being declared one: the incoming camera stands where it always stood, and
the engine performs the handover, so it is what states it.

```lua
camera.cut(); entity(camId).position = { 40, 6, -12 }
```

## globals/camera/editor {#globals-camera-editor}

```lua
camera.editor() -> string?
```

Entity id of the editor fly-camera (the EditorOnly authoring camera), or
nil if the scene has none. This is the camera the editor viewport renders
through, so it is the one a `capture` of the screen sees. Its pose is its
entity transform: assign `entity(id).position` to move it and aim it with
the camera toolbox's `lookAt`, which makes a screen capture repeatable
instead of whatever pose the instance booted with.

**Returns** `string?` — Entity id of the editor camera, or nil.

```lua
local camId = camera.editor()
local id = camera.editor(); entity(id).position = { 12, 8, 12 }; tools.use("camera", "lookAt", id, { 0, 0, 0 })
```

## globals/camera/editorOverride {#globals-camera-editoroverride}

```lua
camera.editorOverride() -> string?
```

Entity id currently overriding viewport selection, or nil when the
viewport is decided by highest-priority-wins.

**Returns** `string?` — Entity id of the overriding camera, or nil.

```lua
local owner = camera.editorOverride()
```

## globals/camera/get {#globals-camera-get}

```lua
camera.get(target: (string | EntityRef)) -> CameraReport?
```

One camera's report from the observation — the same record
`camera.list` yields, for the camera the caller names. Takes an entity id,
an entity name, or an entity proxy, the same way the camera tools do.

**Parameters**

- `target` `(string | EntityRef)` — Entity id, entity name, or entity proxy of the camera to report on.

**Returns** `CameraReport?` — The report, or nil when nothing resolves or that camera has none.

```lua
local c = camera.get(camera.active()); print(c.frame.far, c.authored.far)
local c = camera.get("minimapCam"); print(c.rendering, c.reason)
```

## globals/camera/list {#globals-camera-list}

```lua
camera.list() -> { CameraReport }
```

Every camera in the world as a compact row each, ordered the way the
renderer resolves the on-screen camera: highest priority first. Reads the
same observation `camera.observe` does, so a row can never disagree with
the full report about whether a camera is `enabled` or which one drew.

**Returns** `{ CameraReport }` — One row per camera entity, or an empty list before the first frame.

```lua
for _, c in ipairs(camera.list()) do print(c.name, c.enabled, c.rendering) end
```

## globals/camera/main {#globals-camera-main}

```lua
camera.main() -> string?
```

Entity id of the main scene camera — the scene camera the viewport is
drawn from, and while the editor fly-camera holds the screen, the scene
camera that would take it. The gameplay/PlayerPrototype camera, an
agent-placed scene camera, or a cutscene camera. Never the editor camera;
nil if the scene has only the editor camera. It comes off the same
selection the frame does, so writing a pose to it moves what is drawn
whenever a scene camera is on screen. The scene camera with the highest
authored `priority` takes it; cameras tied on priority settle on the order
the frame visits them, so a scene that needs a specific camera — a
prototype and the clone play makes of it both stand at 0 — states a
distinct priority rather than resting on that order. For the camera drawn
on screen whichever partition owns it, use `camera.active()`.

**Returns** `string?` — Entity id of the main scene camera, or nil — including the frame after that camera's entity is despawned, before the scene elects another.

```lua
local camId = camera.main(); local cam = camId and entity(camId)
```

## globals/camera/motionTally {#globals-camera-motiontally}

```lua
camera.motionTally() -> { frames: number, withoutHistory: number }
```

Frames the camera on screen has drawn, and how many of them had no
previous frame to difference their motion vectors against — its first
frame, every declared cut, and every frame the viewport changes hands on.
Both counts are monotonic across the session, so two readings either side
of a run say what happened in between.

**Returns** `{ frames: number, withoutHistory: number }` — `{ frames, withoutHistory }`.

```lua
local before = camera.motionTally().withoutHistory
```

## globals/camera/observe {#globals-camera-observe}

```lua
camera.observe() -> CameraObservation?
```

Every camera in the world, for the frame that has just been drawn.
Answers "why is this camera not showing what I expect" in one call:
`rendering` says whether each camera drew and `reason` names the single
cause when it did not — `"disabled"`, `"entityInactive"`, `"targetMissing"`,
`"noLayers"`, `"outranked"`, `"notDrawn"`. Each camera carries both
projections: `authored` is what the Camera component holds and `frame` is
what the renderer actually built, with `mismatch` naming every field the
two disagree on — so a clip range or a lens the frame did not use is one
field read. `frame`, `viewProj`, `frustum` and the `cost` numbers describe
a camera that drew; every cost is for that one frame.
One snapshot is published per drawn frame, from after the frame is drawn,
so a read describes the last frame rather than the world at the instant of
the call — a write and a read in one script step return the frame that ran
before the write. Put a `task.wait()` between them to compare a camera
either side of a change; `frame` counts the frames observed, so a poll can
wait for it to advance.

**Returns** `CameraObservation?` — The observation, or nil before the first frame has been drawn.

```lua
local obs = camera.observe(); for _, c in ipairs(obs.cameras) do print(c.name, c.rendering, c.reason) end
local dark = {}; for _, c in ipairs(camera.observe().cameras) do if not c.rendering then table.insert(dark, c.name .. ": " .. tostring(c.reason)) end end
```

## globals/camera/setEditorOverride {#globals-camera-seteditoroverride}

```lua
camera.setEditorOverride(entityId: string?)
```

Give one camera the viewport outright, or pass nil to clear it. While
set, that camera IS the on-screen camera and priority is never consulted,
so no authored priority can take the viewport from it — which is what makes
an authoring camera safe to fly over a scene holding a camera at any
priority. An override naming a camera that is despawned or disabled falls
back to highest-priority-wins rather than blanking the screen.

**Parameters**

- `entityId` `string` _(optional)_ — Entity id of the camera to route the viewport to, or nil to clear.

```lua
camera.setEditorOverride(camera.editor())
camera.setEditorOverride(nil)
```

## globals/camera/viewData {#globals-camera-viewdata}

```lua
camera.viewData(target: ((string | EntityRef)?)?) -> CameraView?
```

Camera render data. Called with no argument it is the active viewport
camera's data for this frame: world position, which projection it drew and
the field describing that frame, viewport pixel size, the 6 world-space
frustum planes (the same inward-pointing, normalized planes the renderer
culls with), and the view-projection matrix. The camera state a render
feature needs for camera-relative work — LOD selection, frustum culling,
billboards. Render features also get it as `ctx.camera`.
Called with an entity id it is that camera's data, read from the frame's
camera observation, and carries the identity the bare form has no room for:
which camera it describes, which frame it was built for, what it rendered
into, and the render layers it resolved to.

**Parameters**

- `target` `((string | EntityRef)?)` _(optional)_ — Entity id, name, or proxy of the camera to read, or nil for the
viewport camera.

**Returns** `CameraView?` — The camera view data, or nil when that camera drew no frame.

```lua
local c = camera.viewData(); if c then print(c.position.x, c.fovY) end
local minimap = camera.viewData("minimapCam"); print(minimap.output.target, minimap.viewport.w)
```

## modules/camera/README {#modules-camera-readme}

```lua
require("@builtin/modules/api/engine/camera") -- camera (also available as global 'camera')
```

Script-facing camera queries: the main scene camera, the on-screen render camera, the editor fly-camera, per-frame view data, and the camera observation — which cameras drew this frame, with what projection, into what, and at what cost. Public Luau surface over the `__camera` Internal FFI namespace.

Usage: local camera = require("@builtin/modules/api/engine/camera")
Also available as global: camera

## modules/camera/active {#modules-camera-active}

```lua
active(): string?
```

Entity id of the on-screen render camera this frame — whichever camera
wins the viewport by priority (the editor fly-camera in edit mode, the
gameplay camera in play). Render features, billboards, and input bases that
must follow the human's on-screen view read this.

```lua
local camId = camera.active()
```

## modules/camera/cut {#modules-camera-cut}

```lua
cut()
```

Declare that the camera on screen cuts: the next frame it draws stands
somewhere it did not travel to. Motion vectors are the difference between
where a surface projects now and where it projected on the camera's
previous frame, and everything temporal reads that difference — the shutter
reconstructs the frame by walking it, a temporal resolve reprojects its
history along it. Across a cut that difference describes a displacement no
surface made, so the frame is reconstructed from taps a whole screen away
and belongs to neither shot. A declared cut leaves the camera with no
previous frame for exactly one frame, which is the state its very first
frame is already in, so every consumer reads zero motion across the cut.
Declare it in the same step that places the camera at the new station;
declaring it again before that frame draws still costs the one frame.
Handing the viewport from one camera to another is already a cut without
being declared one: the incoming camera stands where it always stood, and
the engine performs the handover, so it is what states it.

```lua
camera.cut(); entity(camId).position = { 40, 6, -12 }
```

## modules/camera/editor {#modules-camera-editor}

```lua
editor(): string?
```

Entity id of the editor fly-camera (the EditorOnly authoring camera), or
nil if the scene has none. This is the camera the editor viewport renders
through, so it is the one a `capture` of the screen sees. Its pose is its
entity transform: assign `entity(id).position` to move it and aim it with
the camera toolbox's `lookAt`, which makes a screen capture repeatable
instead of whatever pose the instance booted with.

```lua
local camId = camera.editor()
local id = camera.editor(); entity(id).position = { 12, 8, 12 }; tools.use("camera", "lookAt", id, { 0, 0, 0 })
```

## modules/camera/editorOverride {#modules-camera-editoroverride}

```lua
editorOverride(): string?
```

Entity id currently overriding viewport selection, or nil when the
viewport is decided by highest-priority-wins.

```lua
local owner = camera.editorOverride()
```

## modules/camera/get {#modules-camera-get}

```lua
get(target: (string | EntityRef)): CameraReport?
```

One camera's report from the observation — the same record
`camera.list` yields, for the camera the caller names. Takes an entity id,
an entity name, or an entity proxy, the same way the camera tools do.

**Parameters**

- `target` `(string | EntityRef)` — Entity id, entity name, or entity proxy of the camera to report on.

```lua
local c = camera.get(camera.active()); print(c.frame.far, c.authored.far)
local c = camera.get("minimapCam"); print(c.rendering, c.reason)
```

## modules/camera/list {#modules-camera-list}

```lua
list(): { CameraReport }
```

Every camera in the world as a compact row each, ordered the way the
renderer resolves the on-screen camera: highest priority first. Reads the
same observation `camera.observe` does, so a row can never disagree with
the full report about whether a camera is `enabled` or which one drew.

```lua
for _, c in ipairs(camera.list()) do print(c.name, c.enabled, c.rendering) end
```

## modules/camera/main {#modules-camera-main}

```lua
main(): string?
```

Entity id of the main scene camera — the scene camera the viewport is
drawn from, and while the editor fly-camera holds the screen, the scene
camera that would take it. The gameplay/PlayerPrototype camera, an
agent-placed scene camera, or a cutscene camera. Never the editor camera;
nil if the scene has only the editor camera. It comes off the same
selection the frame does, so writing a pose to it moves what is drawn
whenever a scene camera is on screen. The scene camera with the highest
authored `priority` takes it; cameras tied on priority settle on the order
the frame visits them, so a scene that needs a specific camera — a
prototype and the clone play makes of it both stand at 0 — states a
distinct priority rather than resting on that order. For the camera drawn
on screen whichever partition owns it, use `camera.active()`.

```lua
local camId = camera.main(); local cam = camId and entity(camId)
```

## modules/camera/motionTally {#modules-camera-motiontally}

```lua
motionTally(): { frames: number, withoutHistory: number }
```

Frames the camera on screen has drawn, and how many of them had no
previous frame to difference their motion vectors against — its first
frame, every declared cut, and every frame the viewport changes hands on.
Both counts are monotonic across the session, so two readings either side
of a run say what happened in between.

```lua
local before = camera.motionTally().withoutHistory
```

## modules/camera/observe {#modules-camera-observe}

```lua
observe(): CameraObservation?
```

Every camera in the world, for the frame that has just been drawn.
Answers "why is this camera not showing what I expect" in one call:
`rendering` says whether each camera drew and `reason` names the single
cause when it did not — `"disabled"`, `"entityInactive"`, `"targetMissing"`,
`"noLayers"`, `"outranked"`, `"notDrawn"`. Each camera carries both
projections: `authored` is what the Camera component holds and `frame` is
what the renderer actually built, with `mismatch` naming every field the
two disagree on — so a clip range or a lens the frame did not use is one
field read. `frame`, `viewProj`, `frustum` and the `cost` numbers describe
a camera that drew; every cost is for that one frame.
One snapshot is published per drawn frame, from after the frame is drawn,
so a read describes the last frame rather than the world at the instant of
the call — a write and a read in one script step return the frame that ran
before the write. Put a `task.wait()` between them to compare a camera
either side of a change; `frame` counts the frames observed, so a poll can
wait for it to advance.

```lua
local obs = camera.observe(); for _, c in ipairs(obs.cameras) do print(c.name, c.rendering, c.reason) end
local dark = {}; for _, c in ipairs(camera.observe().cameras) do if not c.rendering then table.insert(dark, c.name .. ": " .. tostring(c.reason)) end end
```

## modules/camera/setEditorOverride {#modules-camera-seteditoroverride}

```lua
setEditorOverride(entityId: string?)
```

Give one camera the viewport outright, or pass nil to clear it. While
set, that camera IS the on-screen camera and priority is never consulted,
so no authored priority can take the viewport from it — which is what makes
an authoring camera safe to fly over a scene holding a camera at any
priority. An override naming a camera that is despawned or disabled falls
back to highest-priority-wins rather than blanking the screen.

**Parameters**

- `entityId` `string?` _(optional)_ — Entity id of the camera to route the viewport to, or nil to clear.

```lua
camera.setEditorOverride(camera.editor())
camera.setEditorOverride(nil)
```

## modules/camera/viewData {#modules-camera-viewdata}

```lua
viewData(target: ((string | EntityRef)?)): CameraView?
```

Camera render data. Called with no argument it is the active viewport
camera's data for this frame: world position, which projection it drew and
the field describing that frame, viewport pixel size, the 6 world-space
frustum planes (the same inward-pointing, normalized planes the renderer
culls with), and the view-projection matrix. The camera state a render
feature needs for camera-relative work — LOD selection, frustum culling,
billboards. Render features also get it as `ctx.camera`.
Called with an entity id it is that camera's data, read from the frame's
camera observation, and carries the identity the bare form has no room for:
which camera it describes, which frame it was built for, what it rendered
into, and the render layers it resolved to.

**Parameters**

- `target` `((string | EntityRef)?)` _(optional)_ — Entity id, name, or proxy of the camera to read, or nil for the
viewport camera.

```lua
local c = camera.viewData(); if c then print(c.position.x, c.fovY) end
local minimap = camera.viewData("minimapCam"); print(minimap.output.target, minimap.viewport.w)
```

## tools/camera/bindToPlayer {#tools-camera-bindtoplayer}

```lua
camera.bindToPlayer(camera?: (EntityRef | string)) -> BindToPlayerResult
```

Make the joining player use this camera in play — bind it to the active scene's PlayerPrototype. The prototype's `camera` role must be a descendant of its subtree (it is cloned with the player on spawn), so this re-parents the camera into the prototype (keeping its world pose) and sets the prototype's `camera` ref to it. This is how you choose the player's camera: pair it with a static behavior (`camera.set { behavior = "@builtin::controller.menu" }`) for a fixed PS1-style camera the player moves within, or a follow behavior (`orbital_follow`, `third_person_follow`, `first_person`, …) for a tracking one. On spawn the player's body is bound as the camera's follow target; a static behavior ignores that and holds its pose. Errors when the scene has no PlayerPrototype (a player-less scene has no player camera to bind). Returns `{ prototype, camera }`.

**Parameters**

- `camera` `(EntityRef | string)` _(optional)_

**Returns** `BindToPlayerResult`

```lua
"fixedCam"
```

## tools/camera/create {#tools-camera-create}

```lua
camera.create(name: string, position?: (vec3 | number), opts?: CameraCreateOpts) -> shared.CameraInfo
```

Spawn a new camera entity at a position, with any starting parameters. `opts` accepts `fov`, `near`, `far`, `priority`, `renderLayers` (a layer-name spec like `"all !ui"`), `debugChannel`, `follow` (an entity the camera behavior tracks), `behavior` (a `cameraBehavior`-tagged component), `lookAt` (a world position or entity to aim at), and `target` (render-to-texture: `true` or `{ width, height, name }` renders offscreen; omit for the viewport). The scene's primary camera is spawned for you from the PlayerPrototype — use this for ADDITIONAL cameras (a security view, a cutscene angle, a render-texture feed). Returns the new camera's full parameter record.

**Parameters**

- `name` `string`
- `position` `(vec3 | number)` _(optional)_
- `opts` `CameraCreateOpts` _(optional)_

**Returns** `shared.CameraInfo`

```lua
"securityCam", { 0, 6, 12 }, { fov = 50, renderLayers = "all !ui" }
"feedCam", { x = 2, y = 3, z = 2 }, { target = { width = 512, height = 512 }, lookAt = "player" }
```

## tools/camera/frame {#tools-camera-frame}

```lua
camera.frame(camera?: (EntityRef | string), target: EntityRef | string, opts?: CameraFrameOpts) -> shared.CameraInfo
```

Position and aim a camera to frame a target entity in one step: place the camera at `distance` from the target on the `yaw`/`pitch` angle, then look at it. `opts` accepts `distance` (default 10), `yaw` (default 0), and `pitch` (default 20), all degrees. Pass `nil` for the first argument to frame with the active camera. Returns the camera's updated parameter record.

**Parameters**

- `camera` `(EntityRef | string)` _(optional)_
- `target` `EntityRef | string`
- `opts` `CameraFrameOpts` _(optional)_

**Returns** `shared.CameraInfo`

```lua
"securityCam", "player", { distance = 8, yaw = 30, pitch = 15 }
nil, "statue"
```

## tools/camera/get {#tools-camera-get}

```lua
camera.get(camera?: (EntityRef | string)) -> shared.CameraInfo
```

Read the full parameter record for one camera — position, rotation, fov, near, far, priority, render-layer spec, debug channel, render-target guid, behavior, and follow target — beside whether it is `enabled` (the switch that decides whether it renders at all), whether it is `rendering`, the `reason` it is not, the projection the renderer built for it in `frame`, and `mismatch` naming every field where that frame disagrees with the record above. Pass a camera name/id/proxy, or nothing to read the active (on-screen) camera, falling back to the scene's main camera.

**Parameters**

- `camera` `(EntityRef | string)` _(optional)_

**Returns** `shared.CameraInfo`

```lua
"securityCam"
```

## tools/camera/list {#tools-camera-list}

```lua
camera.list() -> { shared.CameraRow }
```

List every camera in the scene, enumerated from the live ECS so a just-spawned, hidden, or runtime camera is never missed, sorted by descending priority (the order the renderer resolves the on-screen camera). Each row marks whether it is the `active` camera (drawn this frame), whether it is `enabled` — the per-camera switch that decides whether it competes for the viewport or renders into a target at all — whether it is `rendering` and the `reason` it is not, whether it is the `player` camera (the one the PlayerPrototype uses — the joining player's view), and its `role` — `"main"` (highest-priority active non-editor), `"editor"` (the editor fly-camera), or `""` — plus its priority, fov, render-layer spec, and render-target guid. For the projection the renderer actually built for each camera, and what each cost, read `camera.observe()`.

**Returns** `{ shared.CameraRow }`

## tools/camera/lookAt {#tools-camera-lookat}

```lua
camera.lookAt(camera?: LookAtRef, target?: LookAtRef) -> shared.CameraInfo
```

Aim a camera at a world position or at another entity. The target is an entity name/id or a position `{ x, y, z }` / `{ x =, y =, z = }`. Pass a single target to aim the active camera, or a camera plus a target to aim a specific one. Returns the camera's updated parameter record.

**Parameters**

- `camera` `LookAtRef` _(optional)_
- `target` `LookAtRef` _(optional)_

**Returns** `shared.CameraInfo`

```lua
"securityCam", "player"
{ 10, 0, 5 }
```

## tools/camera/set {#tools-camera-set}

```lua
camera.set(camera?: (EntityRef | string | CameraSetParams), params?: CameraSetParams) -> shared.CameraInfo
```

Change one or more parameters on a camera in a single call. Accepts `fov`, `near`, `far`, `priority`, `debugPass` (the diagnostic view this camera renders, BY NAME — `"final"` (lit), `"normal"`, `"depth"`, a content view like `"lightmap"`, …; `renderer.debugPass.list()` enumerates them; the live viewport draws the active camera's pass), `renderLayers` (a layer-name spec like `"all !ui"` — a bare name includes a layer, `!name` excludes it), `behavior` (a `cameraBehavior`-tagged component ref), and `follow` (the entity the behavior tracks). `debugChannel` accepts the raw numeric channel for the same effect. Pass no camera (or `nil`) to change the active camera; pass `{ ... }` as the only argument for the same. Returns the camera's updated parameter record.

**Parameters**

- `camera` `(EntityRef | string | CameraSetParams)` _(optional)_
- `params` `CameraSetParams` _(optional)_

**Returns** `shared.CameraInfo`

```lua
"securityCam", { fov = 50, priority = 5 }
{ debugPass = "normal" }
{ debugPass = "final" }   -- back to the lit image
```

## typed/builtin//modules/api/engine/camera/camera/active {#typed-builtin-modules-api-engine-camera-camera-active}

```lua
camera.active() -> string?
```

Entity id of the on-screen render camera this frame — whichever camera
wins the viewport by priority (the editor fly-camera in edit mode, the
gameplay camera in play). Render features, billboards, and input bases that
must follow the human's on-screen view read this.

**Returns** `string?` — Entity id of the on-screen camera, or nil if none is active — including the frame after that camera's entity is despawned.

```lua
local camId = camera.active()
```

## typed/builtin//modules/api/engine/camera/camera/cut {#typed-builtin-modules-api-engine-camera-camera-cut}

```lua
camera.cut()
```

Declare that the camera on screen cuts: the next frame it draws stands
somewhere it did not travel to. Motion vectors are the difference between
where a surface projects now and where it projected on the camera's
previous frame, and everything temporal reads that difference — the shutter
reconstructs the frame by walking it, a temporal resolve reprojects its
history along it. Across a cut that difference describes a displacement no
surface made, so the frame is reconstructed from taps a whole screen away
and belongs to neither shot. A declared cut leaves the camera with no
previous frame for exactly one frame, which is the state its very first
frame is already in, so every consumer reads zero motion across the cut.
Declare it in the same step that places the camera at the new station;
declaring it again before that frame draws still costs the one frame.
Handing the viewport from one camera to another is already a cut without
being declared one: the incoming camera stands where it always stood, and
the engine performs the handover, so it is what states it.

```lua
camera.cut(); entity(camId).position = { 40, 6, -12 }
```

## typed/builtin//modules/api/engine/camera/camera/editor {#typed-builtin-modules-api-engine-camera-camera-editor}

```lua
camera.editor() -> string?
```

Entity id of the editor fly-camera (the EditorOnly authoring camera), or
nil if the scene has none. This is the camera the editor viewport renders
through, so it is the one a `capture` of the screen sees. Its pose is its
entity transform: assign `entity(id).position` to move it and aim it with
the camera toolbox's `lookAt`, which makes a screen capture repeatable
instead of whatever pose the instance booted with.

**Returns** `string?` — Entity id of the editor camera, or nil.

```lua
local camId = camera.editor()
local id = camera.editor(); entity(id).position = { 12, 8, 12 }; tools.use("camera", "lookAt", id, { 0, 0, 0 })
```

## typed/builtin//modules/api/engine/camera/camera/editorOverride {#typed-builtin-modules-api-engine-camera-camera-editoroverride}

```lua
camera.editorOverride() -> string?
```

Entity id currently overriding viewport selection, or nil when the
viewport is decided by highest-priority-wins.

**Returns** `string?` — Entity id of the overriding camera, or nil.

```lua
local owner = camera.editorOverride()
```

## typed/builtin//modules/api/engine/camera/camera/get {#typed-builtin-modules-api-engine-camera-camera-get}

```lua
camera.get(target: (string | EntityRef)) -> CameraReport?
```

One camera's report from the observation — the same record
`camera.list` yields, for the camera the caller names. Takes an entity id,
an entity name, or an entity proxy, the same way the camera tools do.

## typed/builtin//modules/api/engine/camera/camera/list {#typed-builtin-modules-api-engine-camera-camera-list}

```lua
camera.list() -> { CameraReport }
```

Every camera in the world as a compact row each, ordered the way the
renderer resolves the on-screen camera: highest priority first. Reads the
same observation `camera.observe` does, so a row can never disagree with
the full report about whether a camera is `enabled` or which one drew.

**Returns** `{ CameraReport }` — One row per camera entity, or an empty list before the first frame.

```lua
for _, c in ipairs(camera.list()) do print(c.name, c.enabled, c.rendering) end
```

## typed/builtin//modules/api/engine/camera/camera/main {#typed-builtin-modules-api-engine-camera-camera-main}

```lua
camera.main() -> string?
```

Entity id of the main scene camera — the scene camera the viewport is
drawn from, and while the editor fly-camera holds the screen, the scene
camera that would take it. The gameplay/PlayerPrototype camera, an
agent-placed scene camera, or a cutscene camera. Never the editor camera;
nil if the scene has only the editor camera. It comes off the same
selection the frame does, so writing a pose to it moves what is drawn
whenever a scene camera is on screen. The scene camera with the highest
authored `priority` takes it; cameras tied on priority settle on the order
the frame visits them, so a scene that needs a specific camera — a
prototype and the clone play makes of it both stand at 0 — states a
distinct priority rather than resting on that order. For the camera drawn
on screen whichever partition owns it, use `camera.active()`.

**Returns** `string?` — Entity id of the main scene camera, or nil — including the frame after that camera's entity is despawned, before the scene elects another.

```lua
local camId = camera.main(); local cam = camId and entity(camId)
```

## typed/builtin//modules/api/engine/camera/camera/motionTally {#typed-builtin-modules-api-engine-camera-camera-motiontally}

```lua
camera.motionTally() -> { frames: number, withoutHistory: number }
```

Frames the camera on screen has drawn, and how many of them had no
previous frame to difference their motion vectors against — its first
frame, every declared cut, and every frame the viewport changes hands on.
Both counts are monotonic across the session, so two readings either side
of a run say what happened in between.

**Returns** `{ frames: number, withoutHistory: number }` — `{ frames, withoutHistory }`.

```lua
local before = camera.motionTally().withoutHistory
```

## typed/builtin//modules/api/engine/camera/camera/observe {#typed-builtin-modules-api-engine-camera-camera-observe}

```lua
camera.observe() -> CameraObservation?
```

Every camera in the world, for the frame that has just been drawn.
Answers "why is this camera not showing what I expect" in one call:
`rendering` says whether each camera drew and `reason` names the single
cause when it did not — `"disabled"`, `"entityInactive"`, `"targetMissing"`,
`"noLayers"`, `"outranked"`, `"notDrawn"`. Each camera carries both
projections: `authored` is what the Camera component holds and `frame` is
what the renderer actually built, with `mismatch` naming every field the
two disagree on — so a clip range or a lens the frame did not use is one
field read. `frame`, `viewProj`, `frustum` and the `cost` numbers describe
a camera that drew; every cost is for that one frame.
One snapshot is published per drawn frame, from after the frame is drawn,
so a read describes the last frame rather than the world at the instant of
the call — a write and a read in one script step return the frame that ran
before the write. Put a `task.wait()` between them to compare a camera
either side of a change; `frame` counts the frames observed, so a poll can
wait for it to advance.

**Returns** `CameraObservation?` — The observation, or nil before the first frame has been drawn.

```lua
local obs = camera.observe(); for _, c in ipairs(obs.cameras) do print(c.name, c.rendering, c.reason) end
local dark = {}; for _, c in ipairs(camera.observe().cameras) do if not c.rendering then table.insert(dark, c.name .. ": " .. tostring(c.reason)) end end
```

## typed/builtin//modules/api/engine/camera/camera/setEditorOverride {#typed-builtin-modules-api-engine-camera-camera-seteditoroverride}

```lua
camera.setEditorOverride(entityId: string?)
```

Give one camera the viewport outright, or pass nil to clear it. While
set, that camera IS the on-screen camera and priority is never consulted,
so no authored priority can take the viewport from it — which is what makes
an authoring camera safe to fly over a scene holding a camera at any
priority. An override naming a camera that is despawned or disabled falls
back to highest-priority-wins rather than blanking the screen.

**Parameters**

- `entityId` `string` _(optional)_ — Entity id of the camera to route the viewport to, or nil to clear.

```lua
camera.setEditorOverride(camera.editor())
camera.setEditorOverride(nil)
```

## typed/builtin//modules/api/engine/camera/camera/viewData {#typed-builtin-modules-api-engine-camera-camera-viewdata}

```lua
camera.viewData(target: ((string | EntityRef)?)?) -> CameraView?
```

Camera render data. Called with no argument it is the active viewport
camera's data for this frame: world position, which projection it drew and
the field describing that frame, viewport pixel size, the 6 world-space
frustum planes (the same inward-pointing, normalized planes the renderer
culls with), and the view-projection matrix. The camera state a render
feature needs for camera-relative work — LOD selection, frustum culling,
billboards. Render features also get it as `ctx.camera`.
Called with an entity id it is that camera's data, read from the frame's
camera observation, and carries the identity the bare form has no room for:
which camera it describes, which frame it was built for, what it rendered
into, and the render layers it resolved to.

**Parameters**

- `target` `((string | EntityRef)?)` _(optional)_ — Entity id, name, or proxy of the camera to read, or nil for the
viewport camera.

**Returns** `CameraView?` — The camera view data, or nil when that camera drew no frame.

```lua
local c = camera.viewData(); if c then print(c.position.x, c.fovY) end
local minimap = camera.viewData("minimapCam"); print(minimap.output.target, minimap.viewport.w)
```
