# Item Editor Fields for AI Agents

> Item editor field ids for AI agents: the model, prefab, die, texture, audio and file tabs in the DiceyTable editor, plus the miniPaint image editor.

- Question: Which item editor fields can an agent set?
- Source: https://diceytable.com/docs/ai-agents/reference/fields/item-editors
- Last verified: 2026-10-09

These are the fields of the item editor tabs for models, prefabs, dice, textures, audio and other files, and of the miniPaint image editor. Decks and layouts have [their own page](https://diceytable.com/docs/ai-agents/reference/fields/deck-and-layout-editors). Each id takes the item it belongs to, such as `@asset:textures/felt.png`.

## Panels in this group

22 panels, with the id prefixes `item`, `minipaint`. The [field catalogue](https://diceytable.com/docs/ai-agents/reference/fields) lists every group.

| Panel | Label | Tab | Fields | Actions |
|---|---|---|---|---|
| [`item.model`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemmodel) | Model tab | `editor` | 31 | 23 |
| [`item.model.collision`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemmodelcollision) | Model collision | `editor` | 13 | 9 |
| [`item.model.trigger`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemmodeltrigger) | Model trigger | `editor` | 6 | 4 |
| [`item.model.interior`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemmodelinterior) | Container interior | `editor` | 5 | 2 |
| [`item.texture`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemtexture) | Texture tab | `editor` | 0 | 3 |
| [`item.texture.sampling`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemtexturesampling) | Texture sampling | `editor` | 7 | 0 |
| [`item.texture.compression`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemtexturecompression) | Texture compression | `editor` | 1 | 1 |
| [`item.texture.webp`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemtexturewebp) | WebP encoding | `editor` | 1 | 1 |
| [`item.texture.resize`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemtextureresize) | Texture resize | `editor` | 3 | 2 |
| [`minipaint`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#minipaint) | Deep image editor | `editor` | 0 | 5 |
| [`item.script`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemscript) | Script editor | `editor` | 0 | 2 |
| [`item.file`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemfile) | File editor | `editor` | 0 | 4 |
| [`item.assembly`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemassembly) | Assembly tab | `editor` | 8 | 6 |
| [`item.prefab`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemprefab) | Prefab tab | `editor` | 28 | 17 |
| [`item.die`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemdie) | Die tab | `editor` | 58 | 18 |
| [`item.pack`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itempack) | Pack tab | `editor` | 0 | 0 |
| [`item.audio`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemaudio) | Audio tab | `editor` | 1 | 5 |
| [`item.audio.trim`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemaudiotrim) | Audio trim | `editor` | 2 | 0 |
| [`item.audio.fades`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemaudiofades) | Audio fades | `editor` | 2 | 0 |
| [`item.audio.level`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemaudiolevel) | Audio level | `editor` | 2 | 0 |
| [`item.audio.loop`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemaudioloop) | Audio loop | `editor` | 1 | 0 |
| [`item.audio.output`](https://diceytable.com/docs/ai-agents/reference/fields/item-editors#itemaudiooutput) | Audio output | `editor` | 2 | 0 |

## `item.model`

**Model tab** · surface `editor` · target `asset`

How it opens: Open the model asset from the explorer (Model tab).

**Fields** (31)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.model.spawn.kind` | Type | `select` | — | `asset` | W | `card`, `deck`, `die`, `token`, `board`, `bag`, `custom`, `card-holder`, `button`, `table`, `coin` | The entity kind every piece placed from this model spawns as (drives its actions and sounds). Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.surface` | Surface | `select` | — | `asset` | W | `wood`, `cardboard`, `metal`, `plastic`, `card`, `tile`, `felt`, `cloth`, `glass`, `stone`, `generic`, `silent` | The physical surface pieces placed from this model have: impact sounds and the mass/friction/bounce baseline. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.flippable` | Flippable | `select` | — | `asset` | W | `auto`, `yes`, `no` | Whether token pieces placed from this model offer Flip; "auto" removes the key so the shape decides. Shown only when Type is token. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.color` | Color | `color` | — | `asset` | W | — | Default tint of pieces placed from this model. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.scale` | Scale | `vec3` | — | `asset` | W | ≥ 0.001, ≤ 100 | Default per-axis scale multiplier of pieces placed from this model (unitless). Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.rotation` | Rotation | `vec3` | `degrees` | `asset` | W | — | Default Euler rotation (degrees, XYZ) of pieces placed from this model. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.spawn-height` | Spawn height | `length` | `length` | `asset` | W | ≥ 0, ≤ 10 | Height above the table a placed piece is dropped from, in feet. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.face-down` | Face down | `boolean` | — | `asset` | W | — | Place pieces from this model face down. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.locked` | Locked | `boolean` | — | `asset` | W | — | Place pieces from this model locked (players cannot move them). Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.cast-shadows` | Cast shadows | `boolean` | — | `asset` | W | — | Per-asset default: pieces from this model cast shadows (a per-entity setting overrides it). Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.receive-shadows` | Receive shadows | `boolean` | — | `asset` | W | — | Per-asset default: pieces from this model receive shadows. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.static-scenery` | Static scenery | `boolean` | — | `asset` | W | — | Opt this model into baked lightmaps (permanently static scenery only; needs lightmap UVs). Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.stack-count` | Stack count | `integer` | — | `asset` | W | ≥ 1, ≤ 1000, step 1 | How many pieces one placement stacks, 1..1000. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.container-mode` | Container mode | `select` | — | `asset` | W | ``, `random`, `stack`, `queue` | How a container placed from this model hands out its contents; "" keeps the default. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.container-form` | Container form | `select` | — | `asset` | W | ``, `holder`, `bag` | For a bag-kind model: "bag" is a closed container whose contents are hidden and drawn at random; "holder" is an open bowl/tray that keeps pieces as loose bodies in its interior. "" keeps the default (bag). Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.container-infinite` | Infinite source | `boolean` | — | `asset` | W | — | A bag-kind model that never depletes (one authored source piece). Needs a container form. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.capacity-limit` | Capacity limit | `integer` | — | `asset` | W | ≥ 1, ≤ 1000, step 1 | Most pieces a container placed from this model holds, 1..1000. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.spawn.tags` | Tags (comma-separated) | `text` | — | `asset` | W | — | Comma-separated tags every piece placed from this model carries. Each is lower-cased and stripped to [a-z0-9_-], at most 32 characters and 100 tags. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.physics.body-type` | Body type | `select` | — | `asset` | W | ``, `static`, `dynamic`, `kinematic` | Default body simulation mode; "" keeps the per-kind default. Inside the collapsed Physics defaults section (`item.model.section.toggle` on `#section:physics`). Project models only; unsaved until Save (the tab's save bar). |
| `item.model.physics.mass` | Mass (kg) | `number` | — | `asset` | W | ≥ 0.001, ≤ 1000, step 0.05 | Default mass in kilograms, 0.001..1000. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.physics.friction` | Friction | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.05 | Default friction, 0..1. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.physics.restitution` | Restitution | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.05 | Default bounciness, 0..1. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.physics.linear-damping` | Linear damping | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.05 | Default linear damping, 0..1. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.physics.angular-damping` | Angular damping | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.05 | Default angular damping, 0..1. Project models only; unsaved until Save (the tab's save bar). |
| `item.model.origin.target` | Move origin to | `length-vec3` | `length` | `asset` | W | — | A point ON the model (its current space, feet) that `item.model.origin.move` makes the new origin. Staging only; nothing changes until Move origin, then Apply. |
| `item.model.optimize.simplify-ratio` | Simplify ratio | `number` | — | `asset` | W | ≥ 0.05, ≤ 1, step 0.05 | Target triangle fraction for `item.model.optimize.simplify`, 0.05..1. A setting for the next run; changes no file. |
| `item.model.optimize.simplify-quality` | Simplify quality | `select` | — | `asset` | W | `preserve`, `balanced`, `aggressive` | Error budget for `item.model.optimize.simplify`: preserve stops early rather than distort; aggressive hits the target. |
| `item.model.optimize.remove-part` | Remove part | `boolean` | — | `asset` | W | — | Check one listed part for `item.model.optimize.remove-parts`. The target is `<asset id>#part:<index>`; the rows exist only after `item.model.optimize.list-parts`. Selection only; changes no file. |
| `item.model.optimize.texture-max-size` | Texture max size | `select` | — | `asset` | W | `0`, `2048`, `1024`, `512` | Longest-edge cap (px) for `item.model.optimize.reencode-textures`; 0 keeps each texture's size. |
| `item.model.optimize.lightmap-resolution` | Lightmap resolution | `select` | — | `asset` | W | `512`, `1024`, `2048`, `0` | Lightmap size the UV unwrap pads its charts for (`item.model.optimize.lightmap-uvs`); 0 = Auto. |
| `item.model.material-slot.material` | Bound to | `select` | — | `asset` | W | — | The project material bound to one GLB material slot (what the mesh renders with); "" clears the binding. The target is `<asset id>#material:<index>`; select that Materials row first with `item.model.tree.select`. Options are the project's material ids. Unsaved until Save. |

**Actions** (23)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.model.duplicate-to-project` | Duplicate to project | W | `asset` | Copy this built-in preset model into the project as an editable model (shown only on read-only presets). |
| `item.model.tree.select` | Select row | R | `asset` | Select one Model tree row, which swaps the right rail to that row's panel (a Materials row shows its slot binding and material; a collider/trigger row selects that entry). The target is `<asset id>#<row id>`: `model:root`, `mesh:<node>`, `material:<index>`, `collider:<entry id>`, `trigger:<id>`, `component:<type>`. View state only. |
| `item.model.tree.toggle` | Expand / collapse | R | `asset` | Expand or collapse one Model tree row that has children. The target is `<asset id>#<row id>` (`model:root`, `folder:meshes`, `folder:materials`, `folder:collision`, `folder:triggers`, `folder:components`). Collapsed rows are not mounted. View state only. |
| `item.model.section.toggle` | Expand / collapse section | R | `asset` | Expand or collapse one Model tab section; collapsed sections do not mount their fields. The target is `<asset id>#section:<key>` with key spawn, physics, collision, trigger or interior. View state only. |
| `item.model.inspect` | Re-inspect | R | `asset` | Re-run the model inspection (errors, warnings and stats in Errors & stats). Changes nothing. |
| `item.model.save` | Save | W | `asset` | Write the tab's sidecar (<model>.meta.json: spawn/physics defaults, collider, triggers, interior, slot bindings) to the project draft. Publishing is separate. |
| `item.model.revert` | Revert | D | `asset` | Discard every unsaved edit in the tab and return to the last saved sidecar. |
| `item.model.spawn.clear` | Clear defaults | D | `asset` | Empty the whole sidecar draft (every default, the collider, triggers and interior). Unsaved until Save; Revert restores it. |
| `item.model.origin.recenter` | Recenter origin | W | `asset` | Stage moving the model's origin to its bottom centre (rewrites the geometry once applied). Nothing changes until `item.model.optimize.apply`. |
| `item.model.origin.centre` | Origin to centre | W | `asset` | Stage moving the model's origin to its bounds centre. Nothing changes until `item.model.optimize.apply`. |
| `item.model.origin.move` | Move origin | W | `asset` | Stage making the point in `item.model.origin.target` the new origin. Nothing changes until `item.model.optimize.apply`. |
| `item.model.optimize.clean-up` | Clean up | W | `asset` | Stage a weld + dedup + prune pass (same as model import) and show before/after stats to Apply or Discard. |
| `item.model.optimize.simplify` | Simplify | W | `asset` | Stage a decimation at the Simplify ratio and quality, and show before/after stats to Apply or Discard. |
| `item.model.optimize.list-parts` | List parts | R | `asset` | Parse the model and list its parts as `item.model.optimize.remove-part` checkboxes. Changes nothing. |
| `item.model.optimize.remove-parts` | Remove checked parts | W | `asset` | Stage deleting the checked parts (and the meshes, materials and textures only they used) to Apply or Discard. |
| `item.model.optimize.reencode-textures` | Re-encode textures (WebP) | W | `asset` | Stage re-encoding the embedded textures as WebP at the Texture max size, to Apply or Discard. |
| `item.model.optimize.recompute-normals` | Recompute normals (faceted) | W | `asset` | Stage recomputed (faceted) normals, to Apply or Discard. |
| `item.model.optimize.generate-tangents` | Generate tangents | W | `asset` | Stage generated tangents, to Apply or Discard. |
| `item.model.optimize.lightmap-uvs` | Generate lightmap UVs | W | `asset` | Stage a second UV set (TEXCOORD_1) for baked lightmaps at the Lightmap resolution, to Apply or Discard. Slow on large models. |
| `item.model.optimize.apply` | Apply | D | `asset` | Replace the model file's bytes with the staged result. Recoverable: the untouched import is preserved under originals/ before the first Apply, and `item.model.optimize.revert-original` restores it. |
| `item.model.optimize.discard` | Discard | D | `asset` | Throw away the staged result without touching the model file. |
| `item.model.optimize.revert-original` | Revert to original | D | `asset` | Replace the model file with its preserved original, discarding every applied optimisation. |
| `item.model.optimize.delete-original` | Delete original | H | `asset` | Requires the user's confirmation in the DiceyTable tab. Deletes the preserved originals/ copy of this model — the only copy of the pre-optimisation bytes — so Revert to original stops working until the next Apply. |

## `item.model.collision`

**Model collision** · surface `editor` · target `asset`

How it opens: Model tab ▸ Collision panel.

**Fields** (13)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.model.collision.shape` | Shape | `select` | — | `asset` | W | `auto`, `box`, `sphere`, `capsule`, `cylinder`, `convexHull`, `mesh` | The collider shape: "auto" drops every authored entry back to the per-kind default; any other value authors the SELECTED entry as that shape (the first entry when none is selected). Unsaved until Save. |
| `item.model.collision.name` | Name (optional) | `text` | — | `asset` | W | — | Display name of a collider entry; "" clears it. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.size` | Size | `length-vec3` | `length` | `asset` | W | ≥ 0.001 | FULL box dimensions (object-local feet) of a box collider entry. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.radius` | Radius | `length` | `length` | `asset` | W | ≥ 0.001 | Radius (object-local feet) of a sphere, capsule or cylinder collider entry. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.height` | Height | `length` | `length` | `asset` | W | ≥ 0 | Height (object-local feet) of a capsule (cylindrical section only, caps excluded) or cylinder collider entry. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.axis` | Axis | `select` | — | `asset` | W | `0`, `1`, `2` | Long axis of a capsule or cylinder collider entry (0 = X, 1 = Y, 2 = Z). The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.model` | Collider model | `asset-ref` | — | `asset` | W | — | The project .glb a convex-hull / triangle-mesh entry takes its geometry from (a repo path from the live options); null goes back to the live render mesh. Clearing leaves the file in the project. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.simplify` | Simplify (% of source) | `slider` | `percent` | `asset` | W | ≥ 5, ≤ 100, step 5 | Target triangle percentage the next `item.model.collision.bake` keeps (mesh-derived entries). The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.decimation` | Decimation | `select` | — | `asset` | W | `quality`, `aggressive` | The meshopt mode the next collider bake uses. A bake setting of this tab, not saved in the sidecar. |
| `item.model.collision.max-error` | Max error (mesh-extent fraction) | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.005 | meshopt error budget for a mesh-derived entry's bake, as a fraction of the mesh extent, 0..1. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.offset` | Offset — centre | `length-vec3` | `length` | `asset` | W | — | Centre of a collider entry relative to the model origin (object-local feet). The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.rotation` | Rotation (°) | `vec3` | `degrees` | `asset` | W | — | Euler rotation (degrees, XYZ) of a collider entry. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.scale` | Scale | `vec3` | — | `asset` | W | — | Per-axis multiplier on a primitive collider entry's dimensions (disabled for mesh-derived entries, which the engine cannot scale). The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |

**Actions** (9)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.model.collision.select-entry` | Select collider | R | `asset` | Select one collider entry so its fields mount. The target is `<asset id>#collider:<entry id>`. View state only. |
| `item.model.collision.fit-to-bounds` | Fit to bounds | W | `asset` | Size and centre a primitive collider entry to the model's measured bounds. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.bake` | Bake collider | W | `asset` | Decimate the mesh-derived entry's source with its Simplify / Max error / Decimation settings, write (or overwrite) <model>.collider.glb in the project and point the entry at it. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.add` | + Add collider | W | `asset` | Append a collider entry fitted to the bounds and select it (at most 8). Unsaved until Save. |
| `item.model.collision.duplicate` | Duplicate | W | `asset` | Copy a collider entry. The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.delete` | Delete | D | `asset` | Remove a collider entry from the draft (deleting the last falls back to Auto). The target is `<asset id>#collider:<entry id>` (the model tree's Collision rows); only the SELECTED entry's fields are mounted, so select it first with `item.model.collision.select-entry`. Unsaved until Save. |
| `item.model.collision.generate-container` | Generate container collider | D | `asset` | Build a closed container shell from the AUTHORED interior, write it as <model>.collider.glb and REPLACE the whole collider list with one static mesh entry. Unsaved until Save; Revert restores the old list. |
| `item.model.collision.simplify-to-fit` | Simplify to fit | W | `asset` | Over the collider triangle budget: decimate the primary mesh-derived entry to fit, then bake it (as `item.model.collision.bake`). |
| `item.model.collision.reapply` | Re-apply | W | `asset` | Host only: push this tab's CURRENT draft collider, triggers and (project models) tags/metadata onto every live entity of this model on the table. Held entities are skipped and reported. |

## `item.model.trigger`

**Model trigger** · surface `editor` · target `asset`

How it opens: Model tab ▸ Trigger panel.

**Fields** (6)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.model.trigger.name` | Name | `text` | — | `asset` | W | — | Name of a trigger volume (1-64 characters). The target is `<asset id>#trigger:<trigger id>` (the model tree's Triggers rows); only the SELECTED volume's fields are mounted, so select it first with `item.model.trigger.select`. Unsaved until Save. |
| `item.model.trigger.shape` | Shape | `select` | — | `asset` | W | `box`, `sphere`, `capsule`, `cylinder` | Shape of a trigger volume. The target is `<asset id>#trigger:<trigger id>` (the model tree's Triggers rows); only the SELECTED volume's fields are mounted, so select it first with `item.model.trigger.select`. Unsaved until Save. |
| `item.model.trigger.position` | Position | `length-vec3` | `length` | `asset` | W | — | Centre of a trigger volume (object-local feet). The target is `<asset id>#trigger:<trigger id>` (the model tree's Triggers rows); only the SELECTED volume's fields are mounted, so select it first with `item.model.trigger.select`. Unsaved until Save. |
| `item.model.trigger.rotation` | Rotation (°) | `vec3` | `degrees` | `asset` | W | — | Euler rotation (degrees, XYZ) of a trigger volume. The target is `<asset id>#trigger:<trigger id>` (the model tree's Triggers rows); only the SELECTED volume's fields are mounted, so select it first with `item.model.trigger.select`. Unsaved until Save. |
| `item.model.trigger.size` | Size | `length-vec3` | `length` | `asset` | W | ≥ 0.001 | FULL dimensions of a trigger volume (object-local feet). The target is `<asset id>#trigger:<trigger id>` (the model tree's Triggers rows); only the SELECTED volume's fields are mounted, so select it first with `item.model.trigger.select`. Unsaved until Save. |
| `item.model.trigger.tag` | Tag | `text` | — | `asset` | W | — | The tag scripts and mods match this trigger volume's enter/leave events on; "" clears it. The target is `<asset id>#trigger:<trigger id>` (the model tree's Triggers rows); only the SELECTED volume's fields are mounted, so select it first with `item.model.trigger.select`. Unsaved until Save. |

**Actions** (4)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.model.trigger.select` | Select trigger volume | R | `asset` | Select one trigger volume so its fields mount. The target is `<asset id>#trigger:<trigger id>`. View state only. |
| `item.model.trigger.add` | + Add trigger volume | W | `asset` | Append a trigger volume and select it. Unsaved until Save. |
| `item.model.trigger.duplicate` | Duplicate | W | `asset` | Copy a trigger volume. The target is `<asset id>#trigger:<trigger id>` (the model tree's Triggers rows); only the SELECTED volume's fields are mounted, so select it first with `item.model.trigger.select`. Unsaved until Save. |
| `item.model.trigger.delete` | Delete | D | `asset` | Remove a trigger volume from the draft. The target is `<asset id>#trigger:<trigger id>` (the model tree's Triggers rows); only the SELECTED volume's fields are mounted, so select it first with `item.model.trigger.select`. Unsaved until Save. |

## `item.model.interior`

**Container interior** · surface `editor` · target `asset`

How it opens: Model tab ▸ Container interior panel.

**Fields** (5)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.model.interior.shape` | Shape | `select` | — | `asset` | W | `box`, `cylinder`, `sphere` | Shape of the container cavity (a sphere is a bowl). Editing any interior field authors all of them. Unsaved until Save. |
| `item.model.interior.position` | Position | `length-vec3` | `length` | `asset` | W | — | Centre of the container cavity (object-local feet). Unsaved until Save. |
| `item.model.interior.rotation` | Rotation (°) | `vec3` | `degrees` | `asset` | W | — | Euler rotation (degrees, XYZ) of the container cavity. Unsaved until Save. |
| `item.model.interior.size` | Size | `length-vec3` | `length` | `asset` | W | ≥ 0.001 | FULL dimensions of the container cavity (object-local feet), not half-extents. Unsaved until Save. |
| `item.model.interior.fill-level` | Fill level | `slider` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | How high a fill goes, as a fraction (0..1) of the cavity height above its floor. Unsaved until Save. |

**Actions** (2)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.model.interior.fit-to-collider` | Fit to collider | W | `asset` | Author the interior derived from the collider's bounds (overwrites the authored one). Unsaved until Save. |
| `item.model.interior.clear` | Clear | D | `asset` | Remove the authored interior so the derived fallback applies again. Unsaved until Save. |

## `item.texture`

**Texture tab** · surface `editor` · target `asset`

How it opens: Open the texture asset from the explorer (Texture tab).

**Actions** (3)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.texture.duplicate-to-project` | Duplicate to project | W | `asset` | Copy this built-in preset texture into the project as an editable file (shown only on read-only presets). |
| `item.texture.edit.open-quick` | Open image editor | R | `asset` | Open the quick image editor (Filerobot) over this texture. Its own controls are third-party; drive it with the image_quick_edit tool. |
| `item.texture.edit.open-advanced` | Open advanced editor | R | `asset` | Open the advanced image editor (miniPaint: layers, brushes, filters) over this texture; its dialogs publish their params as minipaint.dialog.* fields. |

## `item.texture.sampling`

**Texture sampling** · surface `editor` · target `asset`

How it opens: Texture tab ▸ Sampling.

**Fields** (7)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.texture.sampling.srgb` | sRGB | `boolean` | — | `asset` | W | — | Treat the image as sRGB colour data. Turn off for data textures (normal, roughness, masks). |
| `item.texture.sampling.rgbm` | RGBM | `boolean` | — | `asset` | W | — | Decode the image as RGBM-encoded HDR. |
| `item.texture.sampling.mipmaps` | Mipmaps | `boolean` | — | `asset` | W | — | Generate mipmaps (smoother at a distance, +33% memory). |
| `item.texture.sampling.filtering` | Filtering | `select` | — | `asset` | W | `nearest`, `linear` | Texel filtering: nearest (crisp pixel art) or linear. |
| `item.texture.sampling.anisotropy` | Anisotropy | `integer` | — | `asset` | W | ≥ 1, ≤ 16, step 1 | Anisotropic filtering level, 1..16 (sharper at grazing angles). |
| `item.texture.sampling.address-u` | Address U | `select` | — | `asset` | W | `repeat`, `clamp`, `mirror` | Horizontal wrap mode. |
| `item.texture.sampling.address-v` | Address V | `select` | — | `asset` | W | `repeat`, `clamp`, `mirror` | Vertical wrap mode. |

## `item.texture.compression`

**Texture compression** · surface `editor` · target `asset`

How it opens: Texture tab ▸ Compression.

**Fields** (1)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.texture.compression.mode` | Mode | `select` | — | `asset` | W | `etc1s`, `uastc` | Basis codec for the next "Compress to Basis": ETC1S (smaller; colour/albedo) or UASTC (higher quality; normals/detail). Stages the action only. |

**Actions** (1)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.texture.compression.compress` | Compress to Basis | W | `asset` | Encode a Basis-compressed .ktx2 NEXT TO this texture with the staged Mode. The original is kept; nothing is overwritten. |

## `item.texture.webp`

**WebP encoding** · surface `editor` · target `asset`

How it opens: Texture tab ▸ WebP.

**Fields** (1)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.texture.webp.quality` | Quality | `slider` | — | `asset` | W | ≥ 1, ≤ 100, step 1 | WebP quality 1..100 for the next "Re-encode from original" (whole numbers). Stages the action only. |

**Actions** (1)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.texture.webp.reencode` | Re-encode from original | D | `asset` | Re-encode this .webp from its preserved originals/ source at the staged Quality and REPLACE its bytes in place. Recoverable: the original is kept, so a re-encode at another quality restores it. |

## `item.texture.resize`

**Texture resize** · surface `editor` · target `asset`

How it opens: Texture tab ▸ Resize.

**Fields** (3)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.texture.resize.width` | Width | `integer` | — | `asset` | W | ≥ 1, ≤ 8192, step 1 | Target width in pixels for "Apply resize" (1..8192). With Lock aspect on, the height follows. Stages the action only. |
| `item.texture.resize.height` | Height | `integer` | — | `asset` | W | ≥ 1, ≤ 8192, step 1 | Target height in pixels for "Apply resize" (1..8192). With Lock aspect on, the width follows. Stages the action only. |
| `item.texture.resize.lock-aspect` | Lock aspect | `boolean` | — | `asset` | W | — | Keep the image's aspect ratio while editing Width or Height. |

**Actions** (2)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.texture.resize.preset` | Power of two | W | `asset` | Stage a power-of-two size for "Apply resize". The target is `<asset id>#<width>x<height>` (e.g. `textures/felt.webp#1024x1024`); fields_list shows the offered sizes. Writes nothing. |
| `item.texture.resize.apply` | Apply resize | D | `asset` | Resample this texture to the staged Width × Height and REPLACE its bytes in place. Recoverable: the preserved original under originals/ is kept untouched. |

## `minipaint`

**Deep image editor** · surface `editor` · target `asset`

How it opens: Texture tab ▸ Deep edit (miniPaint); its dialogs publish their params as fields.

**Per-instance field families**

| Id pattern | Materialised from |
|---|---|
| `minipaint.dialog.<dialog>.<param>` | One field per parameter of the miniPaint dialog that is open. |

**Actions** (5)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `minipaint.save` | Save to texture | W | `asset` | The editor header's Save to texture: merged export → the texture tab's save (re-encoded to the stored-size policy). |
| `minipaint.close` | Close | R | `asset` | Close the image editor (the texture tab asks about unsaved changes). |
| `minipaint.retry` | Retry | R | `asset` | Reload the image editor after it failed to boot. |
| `minipaint.dialog.ok` | Ok | W | `asset` | Apply the open miniPaint dialog (its OK button) with its current `minipaint.dialog.*` parameters. Undoable in the editor's own history. |
| `minipaint.dialog.cancel` | Cancel | R | `asset` | Close the open miniPaint dialog without applying it. |

**Per-instance action families**

| Id pattern | Registered from |
|---|---|
| `minipaint.menu.<command>` | One action per miniPaint menu command. |

## `item.script`

**Script editor** · surface `editor` · target `script`

How it opens: Open the script from the explorer (Script tab).

**Actions** (2)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.script.save` | Save | W | `script` | Save and compile the Script editor's buffer (the same path as Ctrl+S; the publish scanner runs too). `script_write` is the way to change the text. |
| `item.script.close` | Close | D | `script` | Close the Script editor tab; unsaved edits are discarded after its prompt. |

## `item.file`

**File editor** · surface `editor` · target `asset`

How it opens: Open a text file from the explorer (File tab).

**Actions** (4)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.file.pretty` | Pretty | W | `asset` | Reformat a JSON file as indented JSON in the File editor's buffer (not saved until Save). |
| `item.file.minify` | Minify | W | `asset` | Reformat a JSON file as single-line JSON in the File editor's buffer (not saved until Save). |
| `item.file.save` | Save | W | `asset` | Save the File editor's buffer into the project draft. |
| `item.file.close` | Close | D | `asset` | Close the File editor tab; unsaved edits are discarded after its prompt. |

## `item.assembly`

**Assembly tab** · surface `editor` · target `asset`

How it opens: Open the .assembly.json from the explorer.

**Fields** (8)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.assembly.part.name` | Name | `text` | — | `asset` | W | — | One part's name (1-80 characters). Target `<asset id>#part:<part id>`. |
| `item.assembly.part.model` | Model | `select` | — | `asset` | W | — | Replace one part's model with another project .glb/.gltf (repo-relative path; assemblies cannot nest). The live option list (fields_get) names every choice. Target `<asset id>#part:<part id>`. |
| `item.assembly.part.position` | Position | `length-vec3` | `length` | `asset` | W | step 0.01 | One part's base-centre position in assembly space [x, y, z] (world feet). Target `<asset id>#part:<part id>`. |
| `item.assembly.part.rotation` | Rotation (°) | `vec3` | `degrees` | `asset` | W | step 1 | One part's Euler rotation [x, y, z] in degrees, about its base centre. Target `<asset id>#part:<part id>`. |
| `item.assembly.part.scale` | Scale | `vec3` | — | `asset` | W | step 0.01 | One part's per-axis scale factors [x, y, z] (unitless, each > 0), about its base centre. Mounted only while `item.assembly.part.uniform-scale` is off. Target `<asset id>#part:<part id>`. |
| `item.assembly.part.scale-uniform` | Scale | `number` | — | `asset` | W | ≥ 0.0001, step 0.01 | One part's uniform scale factor (unitless, > 0), written to all three axes. Mounted only while `item.assembly.part.uniform-scale` is on. Target `<asset id>#part:<part id>`. |
| `item.assembly.part.uniform-scale` | Uniform scale | `boolean` | — | `asset` | W | — | Edit one part's scale as a single factor (true; turning it on sets all three axes to X) or per axis (false). Switches which scale field is mounted. Target `<asset id>#part:<part id>`. |
| `item.assembly.add.model` | Add part | `select` | — | `asset` | W | — | The project .glb/.gltf (repo-relative path; "" = none chosen) the next `Add at origin` adds as a part. Changes nothing until the action runs. |

**Actions** (6)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.assembly.save` | Save | W | `asset` | Validate the draft and write the .assembly.json to the project draft (refused while any problem is shown). Placed copies reload with the change; publishing is separate. |
| `item.assembly.revert` | Revert | D | `asset` | Discard every unsaved edit in the tab and return to the last saved document. |
| `item.assembly.close-tab` | Close tab | R | `asset` | Close an Assembly tab whose file is missing or unreadable (the only state that shows this button). |
| `item.assembly.part.reset` | Reset | D | `asset` | Discard one part's unsaved edits, putting it back to its saved values (disabled for a part added since the last save). Target `<asset id>#part:<part id>`. |
| `item.assembly.part.remove` | Remove | D | `asset` | Remove one part from the draft (its model file is kept). Unsaved until Save. Target `<asset id>#part:<part id>`. |
| `item.assembly.part.add` | Add at origin | W | `asset` | Add the model chosen in `item.assembly.add.model` as a new part at the assembly origin. Disabled until a model is chosen. Unsaved until Save. |

## `item.prefab`

**Prefab tab** · surface `editor` · target `asset`

How it opens: Open the .prefab.json from the explorer.

**Fields** (28)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.prefab.prefab.name` | Name | `text` | — | `asset` | W | — | The prefab's name (1-80 characters); becomes the placed root object's label. |
| `item.prefab.body.source` | Body | `select` | — | `asset` | W | — | The prefab's root model. Value is `model:<repo path>` for a project .glb/.gltf/.assembly.json, or `preset:<preset id>` for a built-in piece; the live option list (fields_get) names every choice. Wrap an assembly to build a body from several models. |
| `item.prefab.body.scale` | Body scale | `vec3` | — | `asset` | W | — | Scale factors [x, y, z] (unitless, each > 0) applied to the body model. |
| `item.prefab.body.body-type` | Body type | `select` | — | `asset` | W | `static`, `kinematic`, `dynamic` | Physics body type of the placed root. Unlike a part, the body KEEPS this type when a joint names it: a static body is the anchor a hinged part swings from. |
| `item.prefab.body.weld` | Weld parts | `boolean` | — | `asset` | W | — | Weld every RIGID part (one no joint names) into the body as one physics body with a compound shape (`physics.weldChildren` on the placed root). Off = rigid parts ride along as kinematic children. Jointed parts are never welded. |
| `item.prefab.snap-point.name` | Name | `text` | — | `asset` | W | — | One snap point's name (up to 80 characters). Target `<asset id>#snap:<snap point id>`. |
| `item.prefab.snap-point.position` | Position | `length-vec3` | `length` | `asset` | W | — | One snap point's position in prefab space [x, y, z] (world feet, body origin at 0,0,0). Target `<asset id>#snap:<snap point id>`. |
| `item.prefab.snap-point.rotation-y` | Rotation (°) | `angle` | `degrees` | `asset` | W | step 5 | Facing, in degrees relative to the prefab's yaw, that a piece snapped here is turned to. Target `<asset id>#snap:<snap point id>`. |
| `item.prefab.snap-point.snap-radius` | Snap radius | `length` | `length` | `asset` | W | ≥ 0.01, ≤ 2, step 0.01 | How close (world feet, 0.01-2) a dropped piece has to land to snap here; scales with the placed prefab. Target `<asset id>#snap:<snap point id>`. |
| `item.prefab.attachment.name` | Name | `text` | — | `asset` | W | — | One attachment's name (1-80 characters); becomes its placed object's label. Target `<asset id>#attachment:<attachment id>`. |
| `item.prefab.attachment.source` | Model | `select` | — | `asset` | W | — | The model bolted on as one attachment. Value is `model:<repo path>` for a project .glb/.gltf/.assembly.json, or `preset:<preset id>` for a built-in piece; the live option list (fields_get) names every choice. Target `<asset id>#attachment:<attachment id>`. |
| `item.prefab.attachment.position` | Position | `length-vec3` | `length` | `asset` | W | — | One attachment's position in prefab space [x, y, z] (world feet). Target `<asset id>#attachment:<attachment id>`. |
| `item.prefab.attachment.rotation` | Rotation (°) | `vec3` | `degrees` | `asset` | W | — | One attachment's Euler rotation [x, y, z] in degrees, in prefab space. Target `<asset id>#attachment:<attachment id>`. |
| `item.prefab.attachment.scale` | Scale | `vec3` | — | `asset` | W | — | One attachment's scale factors [x, y, z] (unitless, each > 0). Target `<asset id>#attachment:<attachment id>`. |
| `item.prefab.attachment.body-type` | Body type | `select` | — | `asset` | W | `static`, `kinematic`, `dynamic` | Physics body type of one attachment's placed object; an attachment a joint names is placed dynamic (and unparented) regardless. Target `<asset id>#attachment:<attachment id>`. |
| `item.prefab.attachment.add-source` | Add a part… | `select` | — | `asset` | W | — | The model the next `Add attachment` will bolt on ("" = none chosen). Value is `model:<repo path>` for a project .glb/.gltf/.assembly.json, or `preset:<preset id>` for a built-in piece; the live option list (fields_get) names every choice. Changes nothing until the action runs. |
| `item.prefab.joint.name` | Name | `text` | — | `asset` | W | — | One joint's name (up to 80 characters; empty shows its id). Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.type` | Type | `select` | — | `asset` | W | `hinge`, `fixed`, `spring` | One joint's constraint type: hinge (turns about its axis), fixed (welds two separate bodies), spring (elastic). Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.a` | Connects | `select` | — | `asset` | W | — | One joint's FIRST end: `body` (the prefab's root) or an attachment id. Must differ from the second end. The pivot and axis are stored relative to this end when placed. Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.b` | Connects | `select` | — | `asset` | W | — | One joint's SECOND end: `body` (the prefab's root) or an attachment id. Must differ from the first end. Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.enable-collision` | Parts collide | `boolean` | — | `asset` | W | — | Let the two jointed parts collide with each other. Off for the usual hinge (a lid colliding with its own box jams). Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.pivot` | Pivot | `length-vec3` | `length` | `asset` | W | — | Where one joint sits, in prefab space [x, y, z] (world feet). A hinge turns about this point. A joint saved without one shows end A's origin. Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.axis` | Axis | `vec3` | — | `asset` | W | — | The direction one joint turns about, in prefab space [x, y, z] (any non-zero length; normalised when placed). A joint saved without one shows +Y. Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.limited` | Limit swing | `boolean` | — | `asset` | W | — | HINGE joints only: stop the swing at a range (turning it on starts at 0..110 degrees). Off = turns freely. Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.limit-min` | Range (°) | `angle` | `degrees` | `asset` | W | ≥ -180, ≤ 0, step 5 | Lowest hinge angle (-180..0 degrees) from the placed pose; present only while Limit swing is on. Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.limit-max` | Range (°) | `angle` | `degrees` | `asset` | W | ≥ 0, ≤ 180, step 5 | Highest hinge angle (0..180 degrees) from the placed pose; present only while Limit swing is on. Target `<asset id>#joint:<joint id>`. |
| `item.prefab.joint.add-type` | Joint type | `select` | — | `asset` | W | `hinge`, `fixed`, `spring` | The type the next `Add joint` creates. Changes nothing until the action runs. |
| `item.prefab.viewport.snap` | Snap | `select` | — | `asset` | W | — | Grid snap for gizmo moves in the 3D view: `off` or a step in world feet; any step also snaps gizmo turns to 15 degrees. A view setting — never written to the document. |

**Actions** (17)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.prefab.save` | Save | W | `asset` | Validate the draft against the prefab schema and write the .prefab.json to the project draft (refused while any problem is listed). Placed copies reload with the change; publishing is separate. |
| `item.prefab.close-tab` | Close tab | R | `asset` | Close a Prefab tab whose file is missing or unreadable (the only state that shows this button). |
| `item.prefab.snap-point.add` | Add snap point | W | `asset` | Add a snap point to the draft (id `slot-<n>`) and select it: at the prefab origin, or one catchment-width beside the last one with the same facing and radius, so a row builds up. Unsaved until Save. |
| `item.prefab.snap-point.remove` | Remove snap point | D | `asset` | Remove one snap point from the draft. Target `<asset id>#snap:<snap point id>`. Unsaved until Save. |
| `item.prefab.attachment.add` | Add part | W | `asset` | Bolt the model chosen in `item.prefab.attachment.add-source` onto the draft at the origin (static, unit scale, id `part-<n>`) and select it. Disabled until a model is chosen. Unsaved until Save. |
| `item.prefab.attachment.remove` | Remove part | D | `asset` | Remove one attachment from the draft AND every joint naming it. Target `<asset id>#attachment:<attachment id>`. Unsaved until Save. |
| `item.prefab.joint.add` | Add joint | W | `asset` | Add a joint of the type in `item.prefab.joint.add-type` between the body and the SELECTED part (else the first part), pivot at that part's origin, axis +Y, and select it. Needs at least one part. Unsaved until Save. |
| `item.prefab.joint.remove` | Remove joint | D | `asset` | Remove one joint from the draft. Target `<asset id>#joint:<joint id>`. Unsaved until Save. |
| `item.prefab.joint.axis-x` | X axis | W | `asset` | Set one joint's axis to the prefab's X axis. Target `<asset id>#joint:<joint id>`. Unsaved until Save. |
| `item.prefab.joint.axis-y` | Y axis | W | `asset` | Set one joint's axis to the prefab's Y axis (up). Target `<asset id>#joint:<joint id>`. Unsaved until Save. |
| `item.prefab.joint.axis-z` | Z axis | W | `asset` | Set one joint's axis to the prefab's Z axis. Target `<asset id>#joint:<joint id>`. Unsaved until Save. |
| `item.prefab.undo` | Undo | W | `asset` | Undo the last change to this tab's prefab draft (a gizmo drag is one step). Nothing is written until Save. |
| `item.prefab.redo` | Redo | W | `asset` | Redo the last undone change to this tab's prefab draft. |
| `item.prefab.outline.select` | Select | R | `asset` | Select a row — open its card (or close it if already open) and put the 3D view's gizmo on it. Target `<asset id>#body`, `#attachment:<id>`, `#snap:<id>` or `#joint:<id>`. Changes no document. |
| `item.prefab.viewport.move` | Move | R | `asset` | Show the move gizmo (axis arrows and a ground-plane square) on the selection in the 3D view. |
| `item.prefab.viewport.rotate` | Rotate | R | `asset` | Show the rotate gizmo (rings) on the selection in the 3D view; on a joint it turns the axis. |
| `item.prefab.viewport.frame` | Frame | R | `asset` | Fit the 3D view's camera to every part, snap point and joint. |

## `item.die`

**Die tab** · surface `editor` · target `asset`

How it opens: Open the .die.json from the explorer (models/dice), or New ▸ Die.

**Fields** (58)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.die.name` | Name | `text` | — | `asset` | W | — | The die's name (1-60 characters), at the top of the tab; becomes the baked model's node and material names. While the slug still matches the name, renaming also changes the slug (and so the baked file names). |
| `item.die.slug` | Slug (file name) | `text` | — | `asset` | W | — | The file name Save bakes, beside the design: `<slug>.glb`, `<slug>.collider.glb`, `<slug>.meta.json`. Lower-case letters, digits and single hyphens. A file already at that name that is not this die's last bake blocks Save. Changing it bakes NEW files on the next save; the previous ones are left in place for anything still using them. |
| `item.die.rounding` | Edge rounding | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | How rounded the edges and corners are, 0 (sharp) .. 1 (very round). The flat faces stay on the built-in die's planes (same size and face reading); the mesh and collider are rebuilt together. |
| `item.die.body-color` | Body colour | `color` | — | `asset` | W | — | Colour of the die itself, [r, g, b] in 0..1. |
| `item.die.ink-color` | Ink colour | `color` | — | `asset` | W | — | Colour of numbers, text, pips and mask-mode images, [r, g, b] in 0..1. Colour-mode images keep their own colours. |
| `item.die.ink-material` | Ink material | `select` | — | `asset` | W | — | What numbers, text, pips and mask images are made of: `""` = flat ink colour, or a die material preset id (the same ids as item.die.material.set — `metal-gold`, `marble`, `wood`…). The material brings its colour, pattern, wear, roughness and metalness; one without a colour of its own uses item.die.ink-color. Ink is always solid. A scanned material records its CC0 credit on Save. |
| `item.die.ink-ignore-body-effects` | Keep body effects off the lettering | `boolean` | — | `asset` | W | — | When true, the body's wear (cracks, scratches, dents, rust pitting, kintsugi seams) does not deform numbers, pips or images: their relief stays smooth where the body around them is damaged. |
| `item.die.depth` | Engrave depth | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | How deep numbers, pips and mask images are cut, 0 (printed flat) .. 1 (deep). Shading only: the collider never changes. |
| `item.die.opacity` | Opacity | `number` | — | `asset` | W | ≥ 0.05, ≤ 1, step 0.01 | How see-through the body is, 0.05..1 (1 = solid). Below 1 the die is clear like resin or glass and a model inside shows through; ink always stays solid. |
| `item.die.pattern` | Pattern | `select` | — | `asset` | W | — | The body's pattern: `none`, a scanned CC0 texture (`texture:granite`, `texture:marble`, `texture:onyx`, `texture:oak` — saving records its credit in the project), or a generated `speckle`/`swirl`/`veins`/`grain`. |
| `item.die.pattern-color` | Pattern colour | `color` | — | `asset` | W | — | Colour of a generated pattern's speckles, swirls, veins or grain lines, [r, g, b] in 0..1. Shown only for generated patterns. |
| `item.die.pattern-scale` | Pattern size | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | Feature size of the pattern, 0 (fine) .. 1 (coarse); for a scanned texture, how large it is tiled on the die. |
| `item.die.pattern-amount` | Strength | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | Generated patterns: how strong, 0..1. Scanned textures (labelled Recolour): how far the scan is tinted towards the body colour, 0 = its own colours. |
| `item.die.inclusion.model` | Model | `select` | — | `asset` | W | — | A project .glb sealed inside the die ("" = none); the live options list every eligible model. It is welded into the baked die and can never extend outside it. |
| `item.die.inclusion.size` | Size | `number` | — | `asset` | W | ≥ 0.05, ≤ 1, step 0.01 | The sealed-in model's size as a fraction of the largest that fits at its current position and rotation (1 = as large as possible while every vertex stays inside the die). |
| `item.die.inclusion.rotation-x` | Turn X | `angle` | `degrees` | `asset` | W | ≥ -180, ≤ 180, step 1 | The sealed-in model's rotation about X, degrees. |
| `item.die.inclusion.rotation-y` | Turn Y | `angle` | `degrees` | `asset` | W | ≥ -180, ≤ 180, step 1 | The sealed-in model's rotation about Y, degrees. |
| `item.die.inclusion.rotation-z` | Turn Z | `angle` | `degrees` | `asset` | W | ≥ -180, ≤ 180, step 1 | The sealed-in model's rotation about Z, degrees. |
| `item.die.inclusion.offset-x` | Move X | `number` | — | `asset` | W | ≥ -1, ≤ 1, step 0.01 | The sealed-in model's position on X as a fraction of the die's inner radius (0 = centred). Pulled back in if it would leave the die; size shrinks to keep it inside. |
| `item.die.inclusion.offset-y` | Move Y | `number` | — | `asset` | W | ≥ -1, ≤ 1, step 0.01 | The sealed-in model's position on Y as a fraction of the die's inner radius (0 = centred). Pulled back in if it would leave the die; size shrinks to keep it inside. |
| `item.die.inclusion.offset-z` | Move Z | `number` | — | `asset` | W | ≥ -1, ≤ 1, step 0.01 | The sealed-in model's position on Z as a fraction of the die's inner radius (0 = centred). Pulled back in if it would leave the die; size shrinks to keep it inside. |
| `item.die.inclusion.tint` | One colour | `boolean` | — | `asset` | W | — | Give the sealed-in model one solid colour (item.die.inclusion.color) instead of its own materials. |
| `item.die.inclusion.color` | Colour | `color` | — | `asset` | W | — | The sealed-in model's colour, [r, g, b] in 0..1. Shown only while One colour is on. |
| `item.die.surface` | Made of | `select` | — | `asset` | W | — | What the die is physically made of on the table: its impact sound, grip and bounce (plastic, resin, glass, metal, stone, wood). Choosing one resets Weight to that material's density. |
| `item.die.density` | Weight | `number` | — | `asset` | W | ≥ 0.3, ≤ 12, step 0.1 | Density in g/cm³ (plastic 1.2, glass 2.5, stone 2.7, zinc-alloy metal 6.8, iron 7.8, oak 0.7). The placed die's mass is scaled from it; throws travel the same distance whatever the weight. |
| `item.die.overlay.scratches` | Scratches | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | Fine bright grooves, rougher than the surface around them. 0 = none, 1 = heavy. |
| `item.die.overlay.bumps` | Bumps / hammered | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | Round dents, like hammered metal or sea glass. 0 = none, 1 = heavy. |
| `item.die.overlay.rust` | Rust | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | Matte, non-metallic orange-brown patches with pitting. 0 = none, 1 = heavy. |
| `item.die.overlay.tarnish` | Tarnish / patina | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | Darkening with a green patina; reduces shine and metalness. 0 = none, 1 = heavy. |
| `item.die.overlay.cracks` | Cracks | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | A crackle network with a fainter echo deeper in — best on glass or resin. 0 = none, 1 = heavy. |
| `item.die.overlay.kintsugi` | Gold repair (kintsugi) | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | Kintsugi: the die looks broken and mended, every seam filled with solid, polished metal (item.die.overlay.seam-color). Higher = more, smaller pieces. 0 = none. |
| `item.die.overlay.seam-color` | Seam metal | `color` | — | `asset` | W | — | The metal filling kintsugi seams, [r, g, b] in 0..1 — gold by default; silver, copper and platinum are offered. Shown while Gold repair is above 0. |
| `item.die.faces.preset` | Preset | `select` | — | `asset` | W | — | Apply a whole-die face preset — what every face prints AND counts as: numbers, pips, blank, FATE (d6), average 2-3-3-4-4-5 (d6), percentile 00-90 (d10), zero-based 0-9 (d10). Applies on selection; the live options list those for this shape. |
| `item.die.faces.image` | Same image on every face | `select` | — | `asset` | W | — | Put one project image on every face (applies on selection; faces keep what they count as). |
| `item.die.faces.labels` | Printed text, face 1 first | `text` | — | `asset` | W | — | A list of what each face prints, face 1 first, comma- or line-separated; an empty entry skips a face. Applied by item.die.faces.labels.apply. |
| `item.die.faces.labels-count` | Faces also count as their text | `boolean` | — | `asset` | W | — | When applying the printed-text list, also make each face COUNT as its text (a number when it reads as one). |
| `item.die.faces.values` | Values, face 1 first | `text` | — | `asset` | W | — | A list of what each face counts as, face 1 first: numbers are added to totals, anything else is counted as text. Applied by item.die.faces.values.apply. |
| `item.die.faces.names` | Names, face 1 first | `text` | — | `asset` | W | — | A list of face names, face 1 first, shown beside each result in summaries and chat. Applied by item.die.faces.names.apply. |
| `item.die.roughness` | Roughness | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | Surface finish, 0 (glossy) .. 1 (matte). |
| `item.die.metalness` | Metalness | `number` | — | `asset` | W | ≥ 0, ≤ 1, step 0.01 | 0 for plastic, resin or wood; 1 for a metal die. |
| `item.die.font-family` | Font | `text` | — | `asset` | W | — | CSS font family for numbers and text (e.g. `Georgia`). Any font installed on this computer works: it is baked into the texture at save, so players do not need it. |
| `item.die.font-weight` | Weight | `select` | — | `asset` | W | `normal`, `bold` | Font weight for numbers and text. |
| `item.die.font-italic` | Italic | `boolean` | — | `asset` | W | — | Italic numbers and text. |
| `item.die.glyph-scale` | Glyph size | `number` | — | `asset` | W | ≥ 0.3, ≤ 1.2, step 0.01 | Size of numbers, text and images as a fraction of the face (0.3-1.2). |
| `item.die.pip-scale` | Pip size | `number` | — | `asset` | W | ≥ 0.5, ≤ 1.5, step 0.01 | Pip diameter multiplier (0.5-1.5). |
| `item.die.six-nine` | 6 / 9 marker | `select` | — | `asset` | W | `underline`, `dot`, `none` | How a number that reads as another upside down (6/9, 16/91…) is marked. |
| `item.die.texture-size` | Texture size | `select` | — | `asset` | W | `512`, `1024`, `2048` | Pixel size of the baked texture atlas. Bigger is sharper and heavier to download. |
| `item.die.face.content` | Shows | `select` | — | `asset` | W | `number`, `text`, `pips`, `image`, `blank` | What one face prints: its number, any short text, pips, an image, or nothing. The face still REPORTS its number when rolled. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.text` | Text | `text` | — | `asset` | W | — | Text one face prints when it shows text (up to 6 characters; emoji work). Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.image` | Image | `select` | — | `asset` | W | — | Project image one face prints when it shows an image ("" = none); the live options name every project image. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.image-mode` | Image style | `select` | — | `asset` | W | `mask`, `color` | mask: the image's shape is engraved in the ink colour (its alpha, or its darkness when opaque); color: printed flat in its own colours. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.scale` | Size | `number` | — | `asset` | W | ≥ 0.2, ≤ 1.6, step 0.01 | Multiplier on the design's glyph size for one face (0.2-1.6). Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.rotation` | Rotation (°) | `angle` | `degrees` | `asset` | W | ≥ -180, ≤ 180, step 1 | Clockwise turn of one face's content, in degrees. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.font` | Face font | `text` | — | `asset` | W | — | Font family for one face only ("" = the design's font). Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.name` | Name | `text` | — | `asset` | W | — | Optional name of one face ("" = none), shown beside its value in roll summaries and chat. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.result-type` | Counts as | `select` | — | `asset` | W | `number`, `text` | Whether one face counts as a NUMBER (added to a roll's total) or a TEXT value (tallied, e.g. Hit). Switching to text seeds the value from the face's printed text, name or number. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.result-number` | Value | `number` | — | `asset` | W | ≥ -9999, ≤ 9999 | The number one face counts as when "Counts as" is number (defaults to the face number; decimals and negatives allowed). Shown only for number faces. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.face.result-text` | Value | `text` | — | `asset` | W | — | The text one face counts as when "Counts as" is text (1-24 characters, e.g. Hit). Shown only for text faces. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |

**Actions** (18)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.die.save` | Save | W | `asset` | Write the design (.die.json) and bake the die beside it: <stem>.glb (the stock mesh with the painted textures), <stem>.collider.glb (the stock hull) and <stem>.meta.json (kind die, collider, face layout). Placed copies reload. |
| `item.die.close-tab` | Close tab | R | `asset` | Close a Die tab whose file is missing or unreadable (the only state that shows this button). |
| `item.die.shape.set` | Shape | W | `asset` | Switch the die's shape. Target `<asset id>#shape:<preset id>` (die-d4, die-d6, die-d8, die-d10, die-d12, die-d20). Style and surviving faces are kept. Unsaved until Save. |
| `item.die.face.select` | Select face | R | `asset` | Select one face for editing and turn the 3D preview to show it. Target `<asset id>#face:<value>` (the number that face reports, 1..sides). |
| `item.die.faces.numbers` | All numbers | W | `asset` | Set every face to print its number AND count as its own number (clears custom values and names). Unsaved until Save. |
| `item.die.faces.pips` | All pips | W | `asset` | Set every face to print pips (its number as dots) AND count as its own number (clears custom values and names). Unsaved until Save. |
| `item.die.material.set` | Material | W | `asset` | Start the body from a material preset. Target `<asset id>#material:<id>` (plastic, resin, glass, metal, granite, marble, onyx, wood, stone). Sets finish, metalness, opacity and pattern (and the colour for materials that are one); every setting stays editable. Unsaved until Save. |
| `item.die.inclusion.center` | Centre | W | `asset` | Put the sealed-in model back in the middle of the die, unrotated. Unsaved until Save. |
| `item.die.material.category` | Material type | R | `asset` | Show one material category's presets. Target `<asset id>#category:<plastic\|resin\|glass\|metal\|stone\|wood>`. View state only. |
| `item.die.faces.text` | Text | W | `asset` | Make every face print text (its current text, or its number until changed). Unsaved until Save. |
| `item.die.faces.blank` | Blank | W | `asset` | Make every face blank; faces still count as their numbers. Unsaved until Save. |
| `item.die.faces.reset-style` | Reset sizes & turns | W | `asset` | Clear every face's own size, rotation and font. Unsaved until Save. |
| `item.die.faces.labels.apply` | Apply | W | `asset` | Apply the printed-text list (item.die.faces.labels) to the faces in order. Unsaved until Save. |
| `item.die.faces.values.apply` | Apply | W | `asset` | Apply the values list (item.die.faces.values) to the faces in order. Unsaved until Save. |
| `item.die.faces.names.apply` | Apply | W | `asset` | Apply the names list (item.die.faces.names) to the faces in order. Unsaved until Save. |
| `item.die.view.turntable` | Spin | R | `asset` | Start or stop the 3D preview's slow turntable spin. View state only. |
| `item.die.view.environment` | Lighting | R | `asset` | Light the 3D preview with the table and room Edit Mode has loaded (target `<asset id>#environment:table`, a fresh capture from just above the table) or a neutral studio (`#environment:studio`). Preview only; nothing is saved. |
| `item.die.view.reset` | Reset view | R | `asset` | Turn the 3D preview back to its default three-quarter view. View state only. |

## `item.pack`

**Pack tab** · surface `editor` · singleton (no target)

How it opens: Open the pack reference from the explorer (Pack tab).

_No field or action is registered on this panel yet. `panel_open` can still open it, and `describe_panel` / `screenshot_panel` can read it._

## `item.audio`

**Audio tab** · surface `editor` · target `asset`

How it opens: Open the audio file from the explorer (Sounds folder).

**Fields** (1)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.audio.preview.loop` | Loop preview | `boolean` | — | `asset` | W | — | Loop the preview playback, to listen for the seam. View state only; nothing is saved. |

**Actions** (5)

| Action id | Label | Class | Target | Description |
|---|---|---|---|---|
| `item.audio.play` | Play | R | `asset` | Play the EDITED sound in the tab (a preview; nothing is saved). |
| `item.audio.stop` | Stop | R | `asset` | Stop the preview. |
| `item.audio.save` | Save & optimize | D | `asset` | Render the staged edits from the preserved original and REPLACE this file's bytes with the optimised MP3. Recoverable: the lossless original under originals/ is kept, and the settings are stored in the file, so a later save can undo them. |
| `item.audio.revert` | Discard changes | W | `asset` | Throw away the staged edits and go back to the file's saved settings. |
| `item.audio.reset` | Reset all | W | `asset` | Stage every setting back to its default (untrimmed, no fades, no gain). Save to apply. |

## `item.audio.trim`

**Audio trim** · surface `editor` · target `asset`

How it opens: Audio tab ▸ Trim.

**Fields** (2)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.audio.trim.start` | Start | `number` | — | `asset` | W | ≥ 0, step 0.01 | Seconds of the source to skip at the start. |
| `item.audio.trim.end` | End | `number` | — | `asset` | W | ≥ 0, step 0.01 | Where the sound ends, in seconds of the source (the full length = untrimmed). |

## `item.audio.fades`

**Audio fades** · surface `editor` · target `asset`

How it opens: Audio tab ▸ Fades.

**Fields** (2)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.audio.fade.in` | Fade in | `number` | — | `asset` | W | ≥ 0, step 0.05 | Seconds to fade in from silence. |
| `item.audio.fade.out` | Fade out | `number` | — | `asset` | W | ≥ 0, step 0.05 | Seconds to fade out to silence. |

## `item.audio.level`

**Audio level** · surface `editor` · target `asset`

How it opens: Audio tab ▸ Level.

**Fields** (2)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.audio.level.gain` | Gain (dB) | `number` | — | `asset` | W | ≥ -40, ≤ 24, step 0.5 | Level change in decibels, -40..24, applied after Normalize. Peaks past full scale are clipped. |
| `item.audio.level.normalize` | Normalize | `boolean` | — | `asset` | W | — | Scale the sound so its loudest peak sits at -1 dBFS. |

## `item.audio.loop`

**Audio loop** · surface `editor` · target `asset`

How it opens: Audio tab ▸ Loop.

**Fields** (1)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.audio.loop.crossfade` | Loop crossfade | `number` | — | `asset` | W | ≥ 0, ≤ 30, step 0.05 | Seconds of the end blended into the start so the file loops without a seam (0 = off). Shortens the sound by that much. |

## `item.audio.output`

**Audio output** · surface `editor` · target `asset`

How it opens: Audio tab ▸ Output.

**Fields** (2)

| Field id | Label | Kind | Unit | Target | Class | Range / options | Description |
|---|---|---|---|---|---|---|---|
| `item.audio.output.mono` | Mono | `boolean` | — | `asset` | W | — | Mix to one channel: about half the size, and positional emitters are heard as mono anyway. |
| `item.audio.output.quality` | Quality | `select` | — | `asset` | W | `small`, `balanced`, `high` | MP3 preset: small (32 kHz mono, ≈64 kbps), balanced (44.1 kHz, ≈96–130 kbps), high (44.1 kHz, ≈170–190 kbps). |
