Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions docs/controls.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ If the guess is still wrong on your hardware, pick it yourself: right-click the

### Edit and Interact

The editor has two click modes. Switch with the **Interact mode** cell at the end of the bottom
bar, or press **I**:
The editor has two click modes. Switch with the **Interact mode** cell on the bottom bar (it sits
between the transform tools and Play — the default order is Move, Rotate, Scale, Interact, Play,
Object list, Node editor, Explorer, Animation), or press **I**:

- **Edit** (the default) — every click selects, so every object, module pieces included, can
be picked and moved.
Expand All @@ -42,6 +43,13 @@ bar, or press **I**:

**Play** is the third mode, entered with the play button as before.

In **Edit inside a running game**, every object can be moved: a body you drop stays where you put
it (it is parked out of the simulation) until you leave Edit.

**FPS and draw calls** — *Settings ▸ Interface ▸ Viewport* shows a small counter in any mode:
frames per second, frame time, draw calls and triangles. Draw calls turn amber above 120 and red
above 150, the budget of a Quest headset; in VR the same counter is a strip in front of you.

### Clicking through glass

A see-through wall no longer steals the click from what is behind it: shells that are nearly
Expand Down
77 changes: 77 additions & 0 deletions docs/lod.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Levels of Detail (LOD)

A **level of detail** is a simpler version of a model that draws instead of the full one when the
model is small on screen. Far-away objects then cost a fraction of their triangles — which is what
keeps a big scene smooth on a phone or a Quest — and up close you still see every detail.

theprototype.app does this two ways:

- **Automatically** — any dense model you load (3000+ triangles) gets simplified levels in the
background, built once and shared by every copy. You can switch this off in **Settings ▸
Simplify distant models** (this device only).
- **A LOD group on an object**, edited in its properties like in a professional 3D package
(Unity's *LOD Group*, Unreal's *LOD settings*). Pack items that ship LOD files come with one
already. A LOD group is part of the scene: it is saved, it undoes, and everyone in the session
sees the same levels.

## The LOD section

Select an object and open its **Properties**; the **LOD** section shows its group.

- **The level bar** runs from 100% of the screen height on the left to 0% on the right. Each
coloured segment is one level — **LOD0** is the object itself, then LOD1, LOD2… — and names its
triangle count. A white tick under the bar shows how big the object is on screen right now, and
a dot marks the level being drawn.
- **Drag an edge** between two segments to choose when the next level takes over. The labels under
the bar read the thresholds (`LOD0 < 30%` means "LOD1 draws once the object is under 30% of the
screen height"). A drag is one undo step.
- **Force LOD** draws one level whatever the distance (*Auto* = by screen size). Use it for a
background prop that never needs full detail, or to check how a level looks.
- **Cull when smaller than the last level's size** stops drawing the object entirely once it is
tinier than the last threshold — good for clutter far away.
- **Show LOD level in the viewport** paints every LOD-managed object in its level's colour
(green LOD0, yellow LOD1, orange LOD2, red LOD3…). Only on your screen.

### Selecting and editing a level

**Click a segment** to select that level. While it is selected the viewport **shows that level**
(on your screen only) so you can see what you are editing; click it again — or select another
object — and the object goes back to *Auto*.

For a selected level you can:

- **Replace with** another object in the scene, or **drop a model from the Explorer** on the bar —
the level then draws that model instead (e.g. a hand-made low-poly version).
- **Move level** puts the transform gizmo on the level: line a replacement model up with the
original. The object itself does not move; the level's offset is saved with the group.
- **Own material for this level** gives the level its own colour, roughness and metalness.
Without it, a level uses the object's own materials — so a colour change on the object shows on
every level.
- **Triangles %** (generated levels): how much of the original the level keeps; **Rebuild** applies it.
- **Remove level**.

**Generate levels** builds three simplified levels (50%, 25% and 10% of the triangles) with
meshoptimizer, off the main thread. **+ Level** adds one more; **Remove group** goes back to the
automatic behaviour.

## Pack items with LODs

Pack items can ship their own LOD files (made offline by the pack tools). Placing one adds its LOD
group to the object; the level files are only downloaded when the object is first small enough to
need one, and once for every copy in the scene. Pieces placed before their pack had LOD files pick
them up automatically. Pack authors: see the `lods` field in the core repo's `PACKS.md`.

## In VR

The VR **Properties** panel has a **LOD** row: it reads the level being drawn (`Auto · LOD1`, or
`LOD2 forced`), and left/right on the stick (or the − / + buttons) cycles **Force LOD** through
Auto, LOD0, LOD1…

## How it works (for the curious)

The scene itself never changes: a level is swapped in only while a frame is being drawn, so
picking, physics, the mesh tools and every save always see the full object. A level made from a
pack file is matched to the object **by node name** and draws with the object's own material,
which is why an animated door keeps animating at every level. Switching back to a finer level
needs the object to grow a little past the threshold first (hysteresis), so an object sitting on
an edge does not flicker between levels while you move.
22 changes: 22 additions & 0 deletions docs/module-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,12 @@ api.game.addSetting?.({
onChange: (v) => setBoard(v)
});
setBoard(api.game.setting?.('board') ?? 'globe'); // the stored choice at load
```

A choice row with `onLevels: true` (1.19) is ALSO drawn as tabs above the Levels page in the
headset — Untangle's Globe / 2D board.

```js
api.game.setSetting?.('board', '2d'); // your in-game button writes the same row
api.game.onSettingsChange?.((values) => console.log(values.board, values.sfx));
```
Expand Down Expand Up @@ -492,6 +498,22 @@ the scene, keyed by uuid, and `recent` is the last 32 hits in order. It is runti
state — a late joiner's log starts empty, so a module that needs history keeps its
own through `registerStateSync`.

## New in 1.19

- **`api.inScene()`** — false once a scene switch LEFT your module behind (the person chose *Keep*
when opening a scene that does not use you). Core already keeps your levels, help, settings rows,
Restart, music and spawn out of the new game; stand your own drawing and listening down while it
reads false (a gun in the hand, a HUD of your own).
- **`api.behavior`** — `list()` (the functional pack items in the scene: doors, lids, levers, with
their type and whether they are open), `state(uuid)` and `trigger(uuid, open?)` (open, close or
toggle one — replicated like a click).
- **`api.claimInput('sticks')`** — claim BOTH VR thumbsticks (move, turn, teleport stand down) to
read `input().axes` yourself; returns true on a core that knows the scope, so feature-detect it.
- **`api.lod(object)`** handles gain `force(n)` (pin a level; `null` back to automatic) and
`levels()`.
- `api.music` is owned by your module: `stop()` stops only your track, and unloading your module
stops it.

## Lifecycle

- Core modules load at boot unless disabled in the manager; user modules load
Expand Down
3 changes: 3 additions & 0 deletions docs/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Open it from **Menu ▸ Modules**.
- **⬇ Download as example** exports a core module as a zip — the best starting point for writing your own.
- Peers exchange module lists when they connect and show a toast if a module is missing or a different version on the other side. The session still works, but that module's behavior may differ — treat *same modules everywhere* as part of the session contract.

When you open another scene, the modules the last scene brought can be unloaded or kept — see
[Opening another scene, and modules](saving.md#opening-another-scene-and-modules).

## What modules can add

- **Flow nodes** — new node groups in the palette, driving per-frame effects through the Object Selector like built-in nodes.
Expand Down
29 changes: 27 additions & 2 deletions docs/packs.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,33 @@ A kit piece in your scene is saved as a **reference to its pack**: a level of 15
server. A piece you edit (a mesh change, a new colour) is saved in full, as before. Placing a kit
piece is undoable like any other object.

Three walkable example levels built from the kits are in **Templates ▸ General**: *Castle
Courtyard*, *Forest Clearing* and *Tavern Interior*. Press Play to walk them.
Walkable example levels built from the kits are in **Templates ▸ General**: *Castle Courtyard*,
*Forest Clearing*, *Tavern Interior*, *Wizard's Tower*, *Market Town Square* and the *Architecture
shell*. Press Play to walk them; their doors open.

## The kits (1.19)

| Pack | What is in it |
|---|---|
| **Interiors: Home, Tavern & Office** | 30 pieces of furniture, kitchen, bar, lights and decor, plus wall trims (skirting, wainscot, cornice) that snap to the architecture kit's walls |
| **Town & Market** | 27 pieces — seamless street tiles (road, curb, corner, crossing, sidewalk), a fountain, market stalls, a well, lamps, a clock tower top and a garden gate that opens |
| **Interactive Kit** | 19 pieces that **move when you use them**: doors with their frames, gates, a portcullis, a trapdoor, shutters, a chest, drawers, a cabinet, a lever, a pressure plate, a wall button, and an ambient torch, banner and ceiling fan |
| **Arcane Study** | seven wizard's-study props — an alchemy table, a potion shelf, a crystal ball, a lectern, a telescope, an armillary sphere, a rune rug |

**Doors, lids and levers.** A piece with a ▶ badge in the Explorer is *functional*. In Edit it
rests (a door stays shut, nothing plays by itself — placing or loading it never starts an
animation). In **Interact** or **Play**, click it (or point the VR laser at it, poke it, or knock
on it) and it opens with a sound; click again and it closes. Everyone in the session sees the same
door, and you can walk through an open one. A sliding door may open as you walk up to it. Only
ambient pieces (a banner, a fan, a torch flame) move on their own, and only in Interact and Play.
The Animation panel can preview a clip in Edit without changing your scene.

**Levels of detail.** Every pack piece comes with lighter versions of itself that are drawn when
it is far away. See [Levels of detail](lod.md) to force a level, edit one or tune the distances.

**Draw calls.** Every copy of the same pack piece is drawn in one go (*Settings ▸ Performance ▸
Draw repeated kit pieces together*, on by default) — a furnished tavern stays inside a headset's
budget.

## For pack authors

Expand Down
19 changes: 18 additions & 1 deletion docs/saving.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ had nothing open will not close the panels *you* have open.

**Menu ▸ Templates** opens a picker of ready-made scenes, in four tabs:

- **General** — starting points, including a **Blank** card that clears the scene (it asks first).
- **General** — starting points and walkable kit levels, including a **Blank** card that clears the scene (it asks first).
- **Examples** — worked showcases to pull apart and learn from.
- **Games** — playable scenes. A game is a scene plus, sometimes, a module: a card wears a *Needs …* badge when it depends on one, and loading it offers to install it — every player needs their own copy. **Towers**, the first one, is co-op crate stacking built from flow nodes, the HUD and the Collectibles module. **Stars Room** is the second: a zero-gravity room of glowing stars you [knock](physics.md#the-knock) about, with an optional round on the <kbd>P</kbd> menu — pure app, nothing to install.
- **Community** — scenes other people published from the app; see [Community](community.md).
Expand All @@ -31,6 +31,23 @@ Templates load through the same path as a `.tpscene` file, so with peers connect

Each card also has a small **save to Library** button in its corner (*Save "Towers" to your Library as a new scene*). It files the starter as a new scene in your [Explorer](explorer.md) without loading it — the scene you have open stays as it is — so you can collect a few and open them later.

## Opening another scene, and modules

A game usually brings a module with it (Waves brings *Waves* and *Health*). When you open another
scene that does not need them, the app **asks**: *Unload* (the default — the modules are switched
off and the new scene starts clean), *Keep* (they stay loaded; their music, menus, levels and spawn
stop counting until you go back to their scene), or *Cancel*. Tick *Remember my choice*, or set it
in **Settings ▸ Scene ▸ When opening another scene** (Ask / Keep modules / Unload modules). Modules
you installed as tools and no scene uses are never asked about. Opening a scene that needs a module
you unloaded offers to turn it back on.

**Clear scene** asks what to clear: *Clear objects* (the default), or tick *Also reset the game
setup and unload its modules* to **Clear everything** — the game's menu, HUD, flow nodes, play and
physics settings, sky and look go too, so no leftover Menu or Play button stays behind.

Big scenes **load without freezing the app**: a progress bar shows what is loading and how far it
has got, pieces stream in, and *Cancel* stops the load and takes back what it had added.

## Scene (`.tpscene`) — recommended

A `.tpscene` file is a zip bundle containing everything a scene needs:
Expand Down
6 changes: 4 additions & 2 deletions docs/vr.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,13 @@ Grid toggle, **World 1:1** (reset a scaled/rotated world grab), **Settings**, **
- **Move** — push the left thumbstick. With **VR flying** on, forward follows where your controller aims; otherwise it stays level. Hold the **left grip** to switch the stick to panning and elevation.
- **Teleport** — push the **right thumbstick up** to arc a beam, release to blink to the landing spot (on the ground or any upward-facing surface). Toggle teleport in Settings.
- **Snap-turn** — flick the right thumbstick left/right to rotate in fixed steps. The **snap angle** is Off / 15° / 30° / 45° (default 45°), shown live in the Scene radial and VR Settings; **Mirror snap turn** flips the direction.
- **World grab** — grip with **both hands in empty air** to grab the whole world: pull your hands apart/together to scale, twist to rotate, move to reposition. **System ▸ World 1:1** snaps it back to normal.
- **World grab** — grip with **both hands in empty air** to grab the whole world: pull your hands apart/together to scale, twist to rotate, move to reposition. **System ▸ World 1:1** snaps it back to normal. Holding the world with **one** grip, push the stick **up/down** to send it away or bring it closer, as with an object.

## Grabbing, scaling and stretching

- **Grip** an object to grab it. The default *rigid* grab treats the controller as a handle — the grabbing hand's thumbstick reels the object nearer/farther and scales it. (Other grab styles are available via **System ▸ Grab mode**.)
- **Two hands** on the same object scales it uniformly by the distance between them.
- **Two hands** on the same object scales it uniformly by the distance between them. Two hands on **two different** objects hold one each (Towers' blocks): letting go of one never freezes the other.
- In **Edit**, walls and floors are scenery and a grip on them moves the world — **select** one first to grip it.
- **VR Stretch** — non-uniform, per-axis scaling. From the Edit menu, grab the **W/H/D slider handles** and drag horizontally to stretch that axis; the result is baked when you confirm.
- **Box Select** (Tools ▸ Box Select) — pull the trigger to anchor one corner, drag out a box, release to select everything inside it.

Expand Down Expand Up @@ -143,6 +144,7 @@ Reachable from **System ▸ Settings** in VR, and mirrored in the desktop **Sett
| Hold to move vertex | on / off |
| Refresh rate | Max / 90 / 120 Hz |
| Peer hand style | Model / Hands / Spheres |
| FPS and draw calls | on / off (a strip in front of you; draw calls red above 150) |
| My hand model | any GLB in your library |
| VR menu on left | on / off |
| Passthrough (AR) | on / off (applies next entry) |
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ nav:
- Building:
- Explorer: explorer.md
- Packs: packs.md
- Levels of Detail: lod.md
- Prefabs: prefabs.md
- Mesh Editing: mesh-editing.md
- Splines: splines.md
Expand Down