@jgengine/editor 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -629,6 +629,7 @@
629
629
  ## @jgengine/editor/handlers/navmesh
630
630
 
631
631
  - `navMeshHandlers` (const): const navMeshHandlers: Pick<HandlerTable, "bakeNavMesh"> — Bake caller-provided indexed geometry into a named document navigation mesh.
632
+ - `warmNavBake` (function): function warmNavBake(): void — Start loading the recast module so the first bake request does not have to wait.
632
633
 
633
634
  ## @jgengine/editor/handlers/runtime
634
635
 
@@ -708,6 +709,7 @@
708
709
 
709
710
  ## @jgengine/editor/modelAnimationAuthoring
710
711
 
712
+ - `AnimGraphSource` (type): type AnimGraphSource = "authored" | "locomotion" | "auto" — Where the graph a placement plays comes from.
711
713
  - `AnimationMode` (type): type AnimationMode = "default" | "auto" | "none" | "custom" — Which authoring mode a stored setting represents. `default` = no override key.
712
714
  - `AnimationSetting` (type): type AnimationSetting = AuthoredAnimationConfig | "auto" | "none" — The value stored at `meta.animation`.
713
715
  - `AuthoredAnimationConfig` (interface): interface AuthoredAnimationConfig — Structurally compatible with `ModelAnimationConfig`, but every field optional for authoring.
@@ -719,12 +721,16 @@
719
721
  - `OneShotEvent` (type): type OneShotEvent = (typeof ONE_SHOT_EVENTS)[number] — One-shot animation event a placement can bind a clip to (attack/hit/death/...).
720
722
  - `animationMetaPatch` (function): function animationMetaPatch(setting: AnimationSetting | undefined): { animation: AnimationSetting | undefined } — The meta patch that persists a setting (or clears the override when undefined). Shallow-merges onto `marker.meta` via `setMarker`; an undefined value drops out of the saved JSON document.
721
723
  - `animationMode` (function): function animationMode(setting: AnimationSetting | undefined): AnimationMode — The authoring mode a stored setting maps to.
724
+ - `clearAnimGraph` (function): function clearAnimGraph(setting: AnimationSetting | undefined): AnimationSetting | undefined — Removes a stored graph so `states`/`oneShots` (or clip roles) drive the placement again.
722
725
  - `defaultCustomConfig` (function): function defaultCustomConfig(clips: readonly string[]): AuthoredAnimationConfig — A concrete custom config derived from a rigged asset's clip roles — the `custom` mode seed.
726
+ - `effectiveAnimGraph` (function): function effectiveAnimGraph(setting: AnimationSetting | undefined, clips: readonly string[]): { graph: AnimGraph; source: AnimGraphSource } | null — The graph a placement plays at run time: its stored `graph`, else the locomotion graph of its custom `states`/`oneShots`, else the one clip roles derive for `"auto"` and no-override placements. `null` for `"none"`, a single-clip config, or a rig whose clips have no idle.
723
727
  - `readAnimationSetting` (function): function readAnimationSetting(meta: Record<string, unknown> | undefined): AnimationSetting | undefined — Reads and shape-validates the animation override from a marker's meta; undefined when absent/invalid.
724
728
  - `setAnimationMode` (function): function setAnimationMode(setting: AnimationSetting | undefined, mode: AnimationMode, clips: readonly string[] = []): AnimationSetting | undefined — Switches authoring mode. `custom` seeds from the asset's clip-role defaults (so the user starts from a working config, then overrides) when there is no existing object config; the other modes are the bare string/undefined values.
725
729
  - `setLocomotionClip` (function): function setLocomotionClip(setting: AnimationSetting | undefined, role: LocomotionRole, clipName: string | null): AuthoredAnimationConfig — Sets or clears (null) a locomotion state clip; forces the setting into `custom`.
726
730
  - `setLocomotionNumber` (function): function setLocomotionNumber(setting: AnimationSetting | undefined, key: LocomotionNumber, value: number | null): AuthoredAnimationConfig — Sets or clears (null) a numeric locomotion tuning.
727
731
  - `setOneShotClip` (function): function setOneShotClip(setting: AnimationSetting | undefined, event: string, clipName: string | null): AuthoredAnimationConfig — Binds or clears (null) a one-shot event to a clip.
732
+ - `setTransitionDuration` (function): function setTransitionDuration(setting: AnimationSetting | undefined, graph: AnimGraph, layerId: string, index: number, duration: number): AuthoredAnimationConfig — Sets one transition's crossfade seconds in `graph` and stores the result, so editing a derived graph turns it into an authored one.
733
+ - `storeAnimGraph` (function): function storeAnimGraph(setting: AnimationSetting | undefined, graph: AnimGraph): AuthoredAnimationConfig — Stores `graph` on the placement, keeping its other fields; the stored graph wins at play time.
728
734
 
729
735
  ## @jgengine/editor/networkSnapshot
730
736
 
@@ -820,6 +826,18 @@
820
826
  - `WORKSPACES` (const): const WORKSPACES: readonly RailEntry[] — Rail order and support map. Unsupported modes are visible but disabled — never fake panels.
821
827
  - `WorkspaceRail` (function): function WorkspaceRail({ active, onSelect, }: { active: EditorWorkspace; onSelect: (workspace: EditorWorkspace) => void; }): React.JSX.Element — Narrow left workspace rail. Supported modes activate their home panels; planned modes are disabled with an explanatory tooltip so nothing pretends to work.
822
828
 
829
+ ## @jgengine/editor/shell/animGraphPreview
830
+
831
+ - `GraphParamControl` (interface): interface GraphParamControl — A parameter the preview needs a control for: blend inputs and condition operands.
832
+ - `GraphPreviewFrame` (interface): interface GraphPreviewFrame — What the rig shows at the scrub time.
833
+ - `GraphPreviewInput` (interface): interface GraphPreviewInput — Inputs for {@link simulateGraphPreview}.
834
+ - `MAX_PREVIEW_SECONDS` (const): const MAX_PREVIEW_SECONDS: 20 — Longest preview timeline the scrubber offers, in seconds.
835
+ - `graphClipNames` (function): function graphClipNames(graph: AnimGraph): string[] — Every clip name a graph plays.
836
+ - `graphParamControls` (function): function graphParamControls(graph: AnimGraph): GraphParamControl[] — Parameters a graph reads, with a range covering its blend points and condition values.
837
+ - `graphTriggers` (function): function graphTriggers(graph: AnimGraph): string[] — Every trigger name a graph's transitions listen for, in first-seen order.
838
+ - `recordTrigger` (function): function recordTrigger(triggers: readonly GraphPreviewTrigger[], name: string, at: number): GraphPreviewTrigger[] — Adds a trigger press at `at`, keeping the log in time order.
839
+ - `simulateGraphPreview` (function): function simulateGraphPreview(input: GraphPreviewInput): GraphPreviewFrame — Replays `graph` from its entry states to `time` and reports the pose there.
840
+
823
841
  ## @jgengine/editor/shell/cameraTelemetry
824
842
 
825
843
  - `CameraTelemetry` (interface): interface CameraTelemetry — Per-frame camera orientation channel between the in-canvas probe and the DOM orientation widget. Deliberately a mutable record, not React state: the probe writes every frame and the widget reads on its own rAF loop, applying styles directly — zero shell rerenders.
@@ -73,7 +73,7 @@ bun packages/editor/src/mcp/cli.ts --game <id> \
73
73
  ```
74
74
 
75
75
  - **Required:** `id`, `kind`, and `x`/`z` (`y` optional, defaults to `0`). A game reads its own custom kinds off the document (`editorLayers.markers.filter(m => m.kind === "stash")`), so no engine change is needed to introduce one.
76
- - **Optional:** `color`, `label`, `rotationY`, `meta` — `meta` is validated against the kind's registered schema when one exists (custom kinds skip validation), same as `set_marker`.
76
+ - **Optional:** `color`, `label`, `rotationY`, `catalogId`, `meta` — `catalogId` is the entity kind a `mob`/`boss` marker spawns (without it the marker spawns nothing); `set_marker` patches it too. `meta` is validated against the kind's registered schema when one exists (custom kinds skip validation), same as `set_marker`.
77
77
  - **Id collisions re-id** exactly as `add_path`; the response's `result` carries the id the marker landed under. Use `place_asset` instead when the marker should carry a mesh (it stamps `catalogId`/`meta.assetId`); `add_marker` is for logical, mesh-free markers.
78
78
 
79
79
  ### Click-to-place custom kinds in the GUI
@@ -93,6 +93,17 @@ export const STASH_KIND = definePlaceableMarkerKind({
93
93
  - **Load path:** register from a module the editor loads. Importing your `editorKinds.ts` (side effect) from `editorLayers.ts` covers it — `loadGameLayers` imports `editorLayers.ts` for every editor session, and the game runtime imports it too, so one registration serves both.
94
94
  - `fields` also gives `add_marker`/`set_marker`/`set_meta` a schema to validate that kind's `meta` against; omit `fields` for a bare placeable marker.
95
95
 
96
+ ## Placement animation
97
+
98
+ A placed rigged asset's animation override lives at `marker.meta.animation` and reaches the game through `markerAnimation` → `ModelConfig.animation`. It is `"auto"`, `"none"` or a config with `states`, `oneShots` and an optional stored `graph` (an `AnimGraph`, validated with `parseAnimGraph` on read).
99
+
100
+ - **Inspector → Animation** picks the mode and binds idle/walk/run and one-shot clips.
101
+ - **Animation workspace → Graph** (rail button, or the bottom dock's Animation tab) shows the graph the selected placement plays: layers, states and transitions, with the source (stored, built from states, or derived from clip roles).
102
+ - The scrub slider replays the graph runtime from its entry states. Parameter sliders come from the graph's blend points and conditions.
103
+ - Trigger buttons record a press at the playhead, so scrubbing back and forth replays it. The rig at the camera focus is posed from the runtime's output through the shell's `createGraphPose`.
104
+ - Editing a crossfade, or **Store graph**, writes the graph to `meta.animation.graph` as one undoable edit. **Use derived graph** drops it.
105
+ - Scripted: `set_meta` with `{ "animation": { "graph": { ... } } }` on the marker; see the `jgengine-world` recipe `character-animation.md` for the graph shape.
106
+
96
107
  ## Pure API (`@jgengine/editor`)
97
108
 
98
109
  ```ts
@@ -213,8 +224,7 @@ undoable `setMinimapBake` command. Runtime feeds the stored `background`/`bounds
213
224
  mounted). It is **not** a headless CLI/MCP verb: with no viewport the sampler is null and
214
225
  `bake_minimap` returns `{ ok:false, error:"bake_minimap needs the live editor viewport" }`. To bake
215
226
  a committed scene offline, run a deterministic node script that rebuilds the base field with
216
- `groundFieldFor(world)` and calls `bakeMinimapFromDocument` (see
217
- `scripts/bake-claudecraft-minimap.ts`).
227
+ `groundFieldFor(world)` and calls `bakeMinimapFromDocument`.
218
228
  - GUI: the Terrain panel's **Bake minimap** button calls `bake_minimap` and surfaces any `ok:false`
219
229
  error inline.
220
230
  - RPC/CLI verb: `bake_minimap` (optional `padding`, `resolution`, `waterLevel`). The bake path uses
@@ -11,7 +11,7 @@ Own the spatial realization of game design: player metrics, topology, routes, la
11
11
 
12
12
  All authorable world content belongs in `editor.scene.json`, changed through the editor GUI or RPC/CLI. Never hand-edit the document or keep geometry, paths, spawns, zones, objectives, terrain, foliage, encounters, or coordinate arrays in code. File an editor `[FEATURE]` issue before any fallback.
13
13
 
14
- For a greenfield build, read [references/application-playbook.md](references/application-playbook.md) and produce its greenfield contract (promise, pillars, anti-pillars, core decision, and falsifier) before writing code. Audits may read only the playbook's audit sections. Read [references/live-editor-loop.md](references/live-editor-loop.md) whenever live captures, an editor-agent handoff, or iterative scene improvement is involved. Read [references/field-guide.md](references/field-guide.md) for metric families, topology, pacing, genre lenses, accessibility, and research.
14
+ For a greenfield build, read [references/application-playbook.md](references/application-playbook.md) §1 and produce its metric sheet, topology graph, beat sheet, and encounter cards before art; §3–5 hold the templates. Audits may read only the playbook's audit sections. Read [references/live-editor-loop.md](references/live-editor-loop.md) when a separate editor agent or live editor session applies the changes, or when repairing an existing scene from captures. Read [references/field-guide.md](references/field-guide.md) for metric families, topology, pacing, genre lenses, accessibility, and research.
15
15
 
16
16
  ## Choose the mode
17
17