docs: reorganize docs into bgm and status folders

Group the bgm spec cluster under docs/bgm and move dev logs and plans under docs/status, add an overview index, and update cross-references in the docs, README, and source comments.
This commit is contained in:
2026-08-16 11:57:19 +08:00
parent cf8ca07850
commit 345832e389
19 changed files with 79 additions and 43 deletions
+3 -2
View File
@@ -14,8 +14,9 @@ analyze their contents. A lightweight, client-only pnpm monorepo.
| `packages/mesh` | 2D shapes + extrusion into 3D mesh geometry | Isomorphic | | `packages/mesh` | 2D shapes + extrusion into 3D mesh geometry | Isomorphic |
| `packages/shared` | Shared types + zod schemas | Isomorphic | | `packages/shared` | Shared types + zod schemas | Isomorphic |
See [`docs/architecture.md`](docs/architecture.md) for the architecture and See [`docs/overview.md`](docs/overview.md) for the docs index,
[`docs/implementation-plan.md`](docs/implementation-plan.md) for the plan. [`docs/architecture.md`](docs/architecture.md) for the architecture, and
[`docs/status/implementation-plan.md`](docs/status/implementation-plan.md) for the plan.
## Setup ## Setup
@@ -30,7 +30,7 @@ export function tintedColor(base: THREE.Color, tint: THREE.Color): THREE.Color {
* the same image. * the same image.
* *
* These caches live for the session (like drei's global texture cache) and are * These caches live for the session (like drei's global texture cache) and are
* not disposed on unmount; see `docs/full-setup-view.md`. * not disposed on unmount; see `docs/status/full-setup-view.md`.
*/ */
const geometryCache = new Map<string, THREE.BufferGeometry>(); const geometryCache = new Map<string, THREE.BufferGeometry>();
+2 -2
View File
@@ -2,8 +2,8 @@
> **Scope:** The system's architecture and dependency graph. For implementation > **Scope:** The system's architecture and dependency graph. For implementation
> details (files, endpoints, build order), see > details (files, endpoints, build order), see
> [`implementation-plan.md`](./implementation-plan.md). For the rationale behind > [`status/implementation-plan.md`](./status/implementation-plan.md). For the
> key decisions, see [`decisions.md`](./decisions.md). > rationale behind key decisions, see [`decisions.md`](./decisions.md).
## Overview ## Overview
@@ -1,14 +1,14 @@
# bgm-commands # bgm-commands
Command execution for [bgm](./bgm-format.md) board games, built into Command execution for [bgm](./format.md) board games, built into
[`@tts/tabletop`](./bgm-tabletop.md). A command is a unit of scripted [`@tts/tabletop`](./tabletop.md). A command is a unit of scripted
interaction — focus the camera, wait for a tap, move a part, show a caption — interaction — focus the camera, wait for a tap, move a part, show a caption —
that runs against the tabletop state store and render layer. that runs against the tabletop state store and render layer.
This doc covers **command execution**: the async lifecycle, run contexts, and This doc covers **command execution**: the async lifecycle, run contexts, and
tap interaction. The message layer above this — how commands are *declared* tap interaction. The message layer above this — how commands are *declared*
and *fired* (triggers, orchestrators, the message queue) — is specified in and *fired* (triggers, orchestrators, the message queue) — is specified in
[`bgm-engine.md`](./bgm-engine.md). Commands are async functions registered [`engine.md`](./engine.md). Commands are async functions registered
with the engine's handler registry; `@tts/tabletop` provides the concrete with the engine's handler registry; `@tts/tabletop` provides the concrete
commands that mutate the tabletop store and render layer. commands that mutate the tabletop store and render layer.
@@ -16,7 +16,7 @@ commands that mutate the tabletop store and render layer.
A command is an async function that returns a result. Every command ends in A command is an async function that returns a result. Every command ends in
one of three states, emitted as a message discriminated on the type suffix one of three states, emitted as a message discriminated on the type suffix
(see `bgm-engine.md` §3): (see `engine.md` §3):
- `:done` — completed normally. - `:done` — completed normally.
- `:cancel` — interrupted (a newer command superseded it, the user skipped, - `:cancel` — interrupted (a newer command superseded it, the user skipped,
@@ -124,7 +124,7 @@ cancel, so a cancelled `wait: tap` never leaks a handler.
## 5. run context ## 5. run context
The context a command receives is the handle to everything it can affect. The The context a command receives is the handle to everything it can affect. The
engine defines the base `RunContext` (see `bgm-engine.md` §5): `signal` engine defines the base `RunContext` (see `engine.md` §5): `signal`
(cancellation), `emit`, `wait`, and `enableTrigger`/`disableTrigger`. Tabletop (cancellation), `emit`, `wait`, and `enableTrigger`/`disableTrigger`. Tabletop
extends it with the handles commands need to mutate the board: extends it with the handles commands need to mutate the board:
@@ -142,12 +142,12 @@ interface TabletopRunContext extends RunContext {
The tap detector reads trigger points from a runtime map keyed by part id; it The tap detector reads trigger points from a runtime map keyed by part id; it
does not care where they are declared. Declaration (on the part definition, in does not care where they are declared. Declaration (on the part definition, in
a setup, or in a script) is the deferred "how to declare" half and lives in a setup, or in a script) is the deferred "how to declare" half and lives in
`bgm-format.md`. `format.md`.
## Open decisions ## Open decisions
- **Where commands are declared** — the `script` role and its schema - **Where commands are declared** — the `script` role and its schema
(`bgm-format.md`), deferred. (`format.md`), deferred.
- **Animation** — a general "ease toward target placement" layer (preferred) - **Animation** — a general "ease toward target placement" layer (preferred)
vs explicit per-move tweens. vs explicit per-move tweens.
- **Camera**`CameraControls` (drei) vs hand-rolled. - **Camera**`CameraControls` (drei) vs hand-rolled.
+5 -5
View File
@@ -1,7 +1,7 @@
# bgm-engine # bgm-engine
The message layer that drives [bgm](./bgm-format.md) board games, built into The message layer that drives [bgm](./format.md) board games, built into
[`@tts/engine`](./architecture.md). It unifies the two halves of scripted [`@tts/engine`](../architecture.md). It unifies the two halves of scripted
interaction — *declaring* what should happen and *executing* it — into a single interaction — *declaring* what should happen and *executing* it — into a single
reactive loop: **messages** flow through a **queue**, and **handlers** react to reactive loop: **messages** flow through a **queue**, and **handlers** react to
them. them.
@@ -9,7 +9,7 @@ them.
This doc covers the message model (what flows), the queue and its tick (how it This doc covers the message model (what flows), the queue and its tick (how it
flows), and the handlers (who reacts). Command *execution* — the async flows), and the handlers (who reacts). Command *execution* — the async
lifecycle, run contexts, and tap interaction — is specified in lifecycle, run contexts, and tap interaction — is specified in
[`bgm-commands.md`](./bgm-commands.md); this doc is the layer above it. [`commands.md`](./commands.md); this doc is the layer above it.
## package split ## package split
@@ -19,7 +19,7 @@ is node-testable in isolation (mirroring `@tts/extract`'s isomorphic, zero-dep
style). It defines the contract — `Message`, the handler registry, `Trigger`, style). It defines the contract — `Message`, the handler registry, `Trigger`,
`Orchestrator`, and `RunContext`. `Orchestrator`, and `RunContext`.
[`@tts/tabletop`](./bgm-tabletop.md) is one consumer of that contract: it [`@tts/tabletop`](./tabletop.md) is one consumer of that contract: it
registers the built-in commands (`move`, `focus`, `caption`, `enableSurface`, registers the built-in commands (`move`, `focus`, `caption`, `enableSurface`,
...) that mutate the tabletop store and drive the render layer. The engine ...) that mutate the tabletop store and drive the render layer. The engine
never imports tabletop; tabletop depends on the engine for the message types never imports tabletop; tabletop depends on the engine for the message types
@@ -94,7 +94,7 @@ it cannot re-enter itself.
### interaction messages ### interaction messages
Interaction is the player's input, reported to the engine as messages. Only Interaction is the player's input, reported to the engine as messages. Only
tap interaction is supported (see `bgm-commands.md` §4). tap interaction is supported (see `commands.md` §4).
```ts ```ts
interface TapMessage { interface TapMessage {
@@ -1,6 +1,6 @@
# bgm-tabletop # bgm-tabletop
a r3f based interactive component library to work with [bgm](./bgm-format.md) board games. will be used somewhere in the `web` app's bgm inspector routes. a r3f based interactive component library to work with [bgm](./format.md) board games. will be used somewhere in the `web` app's bgm inspector routes.
## 1. stack ## 1. stack
@@ -47,14 +47,14 @@ the render map is per enabled surface: a piece may appear on more than one enabl
## 4. stacking ## 4. stacking
the format's stacking strategy (`curve` / `limit` / `align` / `steps` / `tilt` / `zStart` / `zEnd`, see `bgm-format.md` §4) is implemented as a hook, e.g. `useStacking(route.stacking, index, stackSize)`, returning the offset/rotation to apply to a piece: `{ x, y, rotation, z, tilt }`. `x`/`y`/`rotation` come from the `curve`; `z` is the surface-normal height ramped from `zStart` to `zEnd`; `tilt` is the rotation about the card's local Y (long) axis, applied to every part. `PartPlacement` consumes it. the format's stacking strategy (`curve` / `limit` / `align` / `steps` / `tilt` / `zStart` / `zEnd`, see `format.md` §4) is implemented as a hook, e.g. `useStacking(route.stacking, index, stackSize)`, returning the offset/rotation to apply to a piece: `{ x, y, rotation, z, tilt }`. `x`/`y`/`rotation` come from the `curve`; `z` is the surface-normal height ramped from `zStart` to `zEnd`; `tilt` is the rotation about the card's local Y (long) axis, applied to every part. `PartPlacement` consumes it.
## 5. commands ## 5. commands
Scripted interaction — focus, tap-to-advance, move, caption — is built on an Scripted interaction — focus, tap-to-advance, move, caption — is built on an
async command layer. See [`bgm-commands.md`](./bgm-commands.md) for command async command layer. See [`commands.md`](./commands.md) for command
execution (lifecycle, run contexts, tap interaction), and execution (lifecycle, run contexts, tap interaction), and
[`bgm-engine.md`](./bgm-engine.md) for the message layer above it (the queue, [`engine.md`](./engine.md) for the message layer above it (the queue,
triggers, and orchestrators that declare and fire commands). triggers, and orchestrators that declare and fire commands).
## 6. usage ## 6. usage
+2 -2
View File
@@ -2,7 +2,7 @@
> **Scope:** The rationale behind key design decisions. For the system's > **Scope:** The rationale behind key design decisions. For the system's
> architecture, see [`architecture.md`](./architecture.md). For the concrete > architecture, see [`architecture.md`](./architecture.md). For the concrete
> build plan, see [`implementation-plan.md`](./implementation-plan.md). > build plan, see [`status/implementation-plan.md`](./status/implementation-plan.md).
> >
> Each entry records the decision, the context, and the alternatives considered. > Each entry records the decision, the context, and the alternatives considered.
> New entries are appended; existing entries are updated only to correct facts, > New entries are appended; existing entries are updated only to correct facts,
@@ -275,7 +275,7 @@ group starts (e.g. a `camera` group so a second focus cancels the first).
**Context:** The user wants to script interaction sequences — focus, caption, **Context:** The user wants to script interaction sequences — focus, caption,
title, highlight, tap-to-advance, move, camera away. The state store and title, highlight, tap-to-advance, move, camera away. The state store and
render layer already exist; what's missing is a way to drive them over time render layer already exist; what's missing is a way to drive them over time
and react to input. Design: [`bgm-commands.md`](./bgm-commands.md). and react to input. Design: [`bgm/commands.md`](./bgm/commands.md).
**Alternatives considered:** A single monolithic script interpreter. Rejected **Alternatives considered:** A single monolithic script interpreter. Rejected
— commands as self-contained async units are testable in isolation and let — commands as self-contained async units are testable in isolation and let
+25
View File
@@ -0,0 +1,25 @@
# Docs
The documentation is split into the living specs, which describe how the
system works today, and the status/plans, which track development iterations
and go stale as work lands.
## Specs — how the system works
| Doc | Covers |
| --- | --- |
| [`architecture.md`](./architecture.md) | System architecture and the package dependency graph |
| [`decisions.md`](./decisions.md) | Key design decisions and the rationale behind them |
| [`bgm/format.md`](./bgm/format.md) | The board game manifest (bgm) format spec |
| [`bgm/engine.md`](./bgm/engine.md) | The bgm message layer: queue, triggers, orchestrators |
| [`bgm/commands.md`](./bgm/commands.md) | bgm command execution: lifecycle, run contexts, tap interaction |
| [`bgm/tabletop.md`](./bgm/tabletop.md) | The r3f tabletop component library |
## Status & plans (dev logs)
| Doc | Covers |
| --- | --- |
| [`status/implementation-plan.md`](./status/implementation-plan.md) | Original build plan |
| [`status/bgm-loader.md`](./status/bgm-loader.md) | bgm loader — what's built, works, missing |
| [`status/bgm-tabletop.md`](./status/bgm-tabletop.md) | bgm tabletop — implementation plan / status |
| [`status/full-setup-view.md`](./status/full-setup-view.md) | Full-setup view plan |
@@ -1,7 +1,7 @@
# bgm Loader — Status # bgm Loader — Status
> WIP. What's built, what works, what's missing, and the known issues. > WIP. What's built, what works, what's missing, and the known issues.
> Spec: [`bgm-format.md`](./bgm-format.md). > Spec: [`../bgm/format.md`](../bgm/format.md).
## What's built ## What's built
@@ -30,7 +30,7 @@ A real 52-card deck: a single `card` part expanded by `$variants` into 52 cards,
### `packages/tabletop` — rendering library (new) ### `packages/tabletop` — rendering library (new)
A standalone r3f library that renders bgm parts. `PartView`/`PartMesh` build a mesh from a `Part` definition via `@tts/mesh` (size/fillet, face/back sprite UVs, traced `shape` or rect fallback). Proxy calls (`/asset`, `/trace`) default to `@tts/http` handlers and are overridable via `TabletopProvider`. Plan: [`bgm-tabletop-plan.md`](./bgm-tabletop-plan.md). A standalone r3f library that renders bgm parts. `PartView`/`PartMesh` build a mesh from a `Part` definition via `@tts/mesh` (size/fillet, face/back sprite UVs, traced `shape` or rect fallback). Proxy calls (`/asset`, `/trace`) default to `@tts/http` handlers and are overridable via `TabletopProvider`. Plan: [`bgm-tabletop.md`](./bgm-tabletop.md).
### `packages/http` — shared proxy HTTP (new) ### `packages/http` — shared proxy HTTP (new)
@@ -71,5 +71,5 @@ The vite plugin itself lives in `packages/bgm/src/vite.ts` (exported from `@tts/
- **`$variants` URL paths** — spec mentions file/URL; URLs deferred. - **`$variants` URL paths** — spec mentions file/URL; URLs deferred.
- **zod `SerializedPackage` shape for the emitted JSON** — the plugin emits `SerializedPackage` objects; a zod schema for the emitted module would give runtime validation beyond the ambient `declare module`. - **zod `SerializedPackage` shape for the emitted JSON** — the plugin emits `SerializedPackage` objects; a zod schema for the emitted module would give runtime validation beyond the ambient `declare module`.
- **`setup` value expansion** — `type` without `id` → all parts of that type is documented but not implemented in the loader (it's a game-state init concern; noted as future). - **`setup` value expansion** — `type` without `id` → all parts of that type is documented but not implemented in the loader (it's a game-state init concern; noted as future).
- **Surface mounting is validated but not resolved**`mount`/`children`/`surfaces` are parsed and validated, but the loader doesn't resolve child→parent relationships or enforce that a setup's `surfaces`/a surface's `children` reference existing surfaces. That's a game-state/rendering concern (see `docs/bgm-tabletop.md`). - **Surface mounting is validated but not resolved**`mount`/`children`/`surfaces` are parsed and validated, but the loader doesn't resolve child→parent relationships or enforce that a setup's `surfaces`/a surface's `children` reference existing surfaces. That's a game-state/rendering concern (see `../bgm/tabletop.md`).
- Docs for the loader itself (this file is the start). - Docs for the loader itself (this file is the start).
@@ -1,8 +1,9 @@
# bgm-tabletop — Implementation Plan / Status # bgm-tabletop — Implementation Plan / Status
> **Scope:** A standalone r3f component library that renders [bgm](./bgm-format.md) > **Scope:** A standalone r3f component library that renders
> board games: a state store, surface mounting, part placement with stacking, > [bgm](../bgm/format.md) board games: a state store, surface mounting, part
> and per-part meshes. Design: [`bgm-tabletop.md`](./bgm-tabletop.md). > placement with stacking, and per-part meshes. Design:
> [`../bgm/tabletop.md`](../bgm/tabletop.md).
> **Status:** items 18 implemented and the full tabletop scene is wired into > **Status:** items 18 implemented and the full tabletop scene is wired into
> the web app's setup detail route (`/bgm/:id/setups/:type/:setup`). The > the web app's setup detail route (`/bgm/:id/setups/:type/:setup`). The
> part-inspection route renders `PartView` from the library. > part-inspection route renders `PartView` from the library.
@@ -75,7 +76,7 @@ useful slice and unblocks the web app's part inspection route immediately.
### 3. State store (`state.ts`) ✅ ### 3. State store (`state.ts`) ✅
Source-of-truth game state per `bgm-tabletop.md` §2: Source-of-truth game state per `../bgm/tabletop.md` §2:
```ts ```ts
interface GameState { interface GameState {
@@ -96,7 +97,7 @@ interface PartState {
Computed with a selector/memo so the render list is stable. A path's ordered Computed with a selector/memo so the render list is stable. A path's ordered
children (for stacking) are derived from the parts map by sorting on `index`. children (for stacking) are derived from the parts map by sorting on `index`.
- **Assumption**: each piece id is unique on the board (documented in - **Assumption**: each piece id is unique on the board (documented in
`bgm-tabletop.md`); the render map is keyed by piece id. `../bgm/tabletop.md`); the render map is keyed by piece id.
### 4. Setup seeding (`setup.ts`) ✅ ### 4. Setup seeding (`setup.ts`) ✅
@@ -104,7 +105,7 @@ interface PartState {
`Setup` — enables its `surfaces` (or all when omitted) and applies its `Setup` — enables its `surfaces` (or all when omitted) and applies its
ordered `setup` placements (each moves its `parts` to a `path`). ordered `setup` placements (each moves its `parts` to a `path`).
- `setup` value expansion: a bare `type` (no id) expands to all parts of that - `setup` value expansion: a bare `type` (no id) expands to all parts of that
type (documented in `bgm-format.md` §3; the loader doesn't do this — it's a type (documented in `../bgm/format.md` §3; the loader doesn't do this — it's a
game-state init concern, so it lives here). game-state init concern, so it lives here).
### 5. Surface mounting (`mount.ts`) ✅ ### 5. Surface mounting (`mount.ts`) ✅
@@ -126,7 +127,7 @@ interface PartState {
### 7. Stacking (`stacking.ts`) ✅ ### 7. Stacking (`stacking.ts`) ✅
- `useStacking(route.stacking, index, stackSize)``{ x, y, rotation, z, tilt }`. - `useStacking(route.stacking, index, stackSize)``{ x, y, rotation, z, tilt }`.
- Implements the format's positioning process (`bgm-format.md` §4): step - Implements the format's positioning process (`../bgm/format.md` §4): step
length from curve length / `max(steps, count-1)`, alignment (`start`/`end`/ length from curve length / `max(steps, count-1)`, alignment (`start`/`end`/
`center`), and `limit` (`0` all, `n` first n, `-n` last n). `center`), and `limit` (`0` all, `n` first n, `-n` last n).
- `z` ramps linearly from `zStart` to `zEnd` across the curve's span; `tilt` - `z` ramps linearly from `zStart` to `zEnd` across the curve's span; `tilt`
@@ -174,7 +175,7 @@ consumers share them (see Open decisions).
## Commands (not yet implemented) ## Commands (not yet implemented)
Scripted interaction is designed in [`bgm-commands.md`](./bgm-commands.md): Scripted interaction is designed in [`../bgm/commands.md`](../bgm/commands.md):
async commands with `ok`/`cancel`/`error` results, per-invocation run async commands with `ok`/`cancel`/`error` results, per-invocation run
contexts, fire-and-forget vs self-managed waiting, and tap interaction with contexts, fire-and-forget vs self-managed waiting, and tap interaction with
part-local trigger points. Implementation order: types + run-context manager, part-local trigger points. Implementation order: types + run-context manager,
@@ -2,8 +2,8 @@
> **Scope:** The concrete build plan — files, endpoints, dependencies, build > **Scope:** The concrete build plan — files, endpoints, dependencies, build
> order. For the system's architecture and dependency graph, see > order. For the system's architecture and dependency graph, see
> [`architecture.md`](./architecture.md). For the rationale behind key decisions, > [`../architecture.md`](../architecture.md). For the rationale behind key decisions,
> see [`decisions.md`](./decisions.md). > see [`../decisions.md`](../decisions.md).
A lightweight, client-only pnpm monorepo for searching the Tabletop Simulator A lightweight, client-only pnpm monorepo for searching the Tabletop Simulator
Steam Workshop, fetching full TTS save files, and analyzing their contents. Steam Workshop, fetching full TTS save files, and analyzing their contents.
@@ -55,7 +55,16 @@ tts-workshop/
├── .npmrc ├── .npmrc
├── .env.example # STEAM_API_KEY, PORT ├── .env.example # STEAM_API_KEY, PORT
├── docs/ ├── docs/
── implementation-plan.md # this file ── overview.md
│ ├── architecture.md
│ ├── decisions.md
│ ├── bgm/
│ │ ├── format.md
│ │ ├── engine.md
│ │ ├── commands.md
│ │ └── tabletop.md
│ └── status/
│ └── implementation-plan.md # this file
├── apps/ ├── apps/
│ ├── proxy/ │ ├── proxy/
│ │ ├── package.json │ │ ├── package.json
+1 -1
View File
@@ -11,7 +11,7 @@
* their `include` patterns, and assembles the package's parts, surfaces, * their `include` patterns, and assembles the package's parts, surfaces,
* and setups. * and setups.
* *
* See docs/bgm-format.md for the format's concrete behavior. * See docs/bgm/format.md for the format's concrete behavior.
*/ */
import * as path from 'node:path'; import * as path from 'node:path';
import picomatch from 'picomatch'; import picomatch from 'picomatch';
+1 -1
View File
@@ -2,7 +2,7 @@
* Parse raw definition files (yaml/json/toml text) into JSON objects. * Parse raw definition files (yaml/json/toml text) into JSON objects.
* *
* A def file's document can be either a single JSON object (the root) or a * A def file's document can be either a single JSON object (the root) or a
* list of objects; both are handled per docs/bgm-format.md §3. In list mode, * list of objects; both are handled per docs/bgm/format.md §3. In list mode,
* each object is a separate definition. * each object is a separate definition.
*/ */
import * as fs from 'node:fs'; import * as fs from 'node:fs';
+1 -1
View File
@@ -3,7 +3,7 @@
* *
* These validate the raw definition objects (after `$variants` expansion) * These validate the raw definition objects (after `$variants` expansion)
* and produce the typed `Part` / `Surface` / `Setup` / `PackageDef` values. * and produce the typed `Part` / `Surface` / `Setup` / `PackageDef` values.
* See docs/bgm-format.md for the format's concrete behavior. * See docs/bgm/format.md for the format's concrete behavior.
*/ */
import { z } from 'zod'; import { z } from 'zod';
import type { PackageDef, Part, Setup, Surface } from './types.js'; import type { PackageDef, Part, Setup, Surface } from './types.js';
+1 -1
View File
@@ -5,7 +5,7 @@
* discovered as JSON objects from yaml/json/toml files and from markdown * discovered as JSON objects from yaml/json/toml files and from markdown
* code blocks, then assembled into a `Package` (see `collect.ts` / `emit.ts`). * code blocks, then assembled into a `Package` (see `collect.ts` / `emit.ts`).
* *
* The concrete behavior of the format is described in `docs/bgm-format.md`. * The concrete behavior of the format is described in `docs/bgm/format.md`.
*/ */
/** Part value types. */ /** Part value types. */
+1 -1
View File
@@ -2,7 +2,7 @@
* The `$variants` directive: parse a CSV into a typed object array and * The `$variants` directive: parse a CSV into a typed object array and
* extend the original object with each row. * extend the original object with each row.
* *
* Per docs/bgm-format.md §1: * Per docs/bgm/format.md §1:
* - The CSV's first row is the header, the second row is the type declaration * - The CSV's first row is the header, the second row is the type declaration
* (`string`, `number`, `string[]`, `[number;number;number;number]`, ...), * (`string`, `number`, `string[]`, `[number;number;number;number]`, ...),
* the remaining rows are data. * the remaining rows are data.
+1 -1
View File
@@ -1,5 +1,5 @@
/** /**
* Stacking the format's positioning process (`bgm-format.md` §4). * Stacking the format's positioning process (`docs/bgm/format.md` §4).
* *
* Given a route's `stacking` strategy and a piece's position in its path's * Given a route's `stacking` strategy and a piece's position in its path's
* stack, compute the offset/rotation to apply. Parts are spread along an SVG * stack, compute the offset/rotation to apply. Parts are spread along an SVG