@origingame/engine 0.3.0 → 0.5.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.
Files changed (92) hide show
  1. package/dist/web/origin-engine.d.ts +44 -5
  2. package/dist/web/origin-engine.js +279 -19
  3. package/dist/web/origin-engine_bg.wasm +0 -0
  4. package/dist/web/origin-engine_bg.wasm.d.ts +18 -5
  5. package/dist/web-publish/origin-engine-lanes.js +289 -48
  6. package/dist/web-publish/origin-engine-lanes_bg.wasm +0 -0
  7. package/dist/web-publish/origin-engine.d.ts +44 -5
  8. package/dist/web-publish/origin-engine.js +279 -38
  9. package/dist/web-publish/origin-engine_bg.wasm +0 -0
  10. package/dist/web-publish/origin-engine_bg.wasm.d.ts +18 -5
  11. package/dist/web-publish-2d/origin-engine-lanes.js +289 -48
  12. package/dist/web-publish-2d/origin-engine-lanes_bg.wasm +0 -0
  13. package/dist/web-publish-2d/origin-engine.d.ts +44 -5
  14. package/dist/web-publish-2d/origin-engine.js +279 -38
  15. package/dist/web-publish-2d/origin-engine_bg.wasm +0 -0
  16. package/dist/web-publish-2d/origin-engine_bg.wasm.d.ts +18 -5
  17. package/knowledge/README.md +2 -1
  18. package/knowledge/guides/three-to-og.md +393 -0
  19. package/knowledge/knowledge.json +2 -1
  20. package/knowledge/looks/catalogue.json +123 -2
  21. package/knowledge/package.json +3 -2
  22. package/knowledge/scaffold/origin-engine.json +2 -2
  23. package/knowledge/scaffold/template/package.json +1 -1
  24. package/knowledge/scaffold/template/project.ogt +1 -1
  25. package/knowledge/scripts/validate.ts +209 -27
  26. package/knowledge/skills/og-audio/SKILL.md +33 -7
  27. package/knowledge/skills/og-build/SKILL.md +66 -7
  28. package/knowledge/skills/og-core/SKILL.md +24 -8
  29. package/knowledge/skills/og-feel/SKILL.md +11 -3
  30. package/knowledge/skills/og-game/SKILL.md +680 -51
  31. package/knowledge/skills/og-i18n/SKILL.md +7 -7
  32. package/knowledge/skills/og-model/SKILL.md +374 -0
  33. package/knowledge/skills/og-platform-sdk/SKILL.md +7 -1
  34. package/knowledge/skills/og-taste/SKILL.md +7 -0
  35. package/knowledge/skills/og-ui/SKILL.md +39 -8
  36. package/knowledge/wiki/ai.md +20 -20
  37. package/knowledge/wiki/anim.md +537 -63
  38. package/knowledge/wiki/atmosphere.md +13 -13
  39. package/knowledge/wiki/audio.md +160 -20
  40. package/knowledge/wiki/camera.md +13 -13
  41. package/knowledge/wiki/commands.md +11 -11
  42. package/knowledge/wiki/debug.md +13 -13
  43. package/knowledge/wiki/game.md +8 -8
  44. package/knowledge/wiki/i18n.md +7 -7
  45. package/knowledge/wiki/index.md +81 -3
  46. package/knowledge/wiki/input.md +47 -47
  47. package/knowledge/wiki/load.md +83 -57
  48. package/knowledge/wiki/math.md +102 -102
  49. package/knowledge/wiki/nav.md +34 -34
  50. package/knowledge/wiki/net.md +10 -10
  51. package/knowledge/wiki/path.md +14 -14
  52. package/knowledge/wiki/physics.md +111 -100
  53. package/knowledge/wiki/platform.md +44 -44
  54. package/knowledge/wiki/probe.md +86 -86
  55. package/knowledge/wiki/reflect.md +30 -18
  56. package/knowledge/wiki/render.md +1243 -176
  57. package/knowledge/wiki/rng.md +14 -14
  58. package/knowledge/wiki/shapes.md +727 -0
  59. package/knowledge/wiki/stream.md +15 -15
  60. package/knowledge/wiki/system.md +8 -8
  61. package/knowledge/wiki/systems.md +2 -2
  62. package/knowledge/wiki/terrain.md +24 -20
  63. package/knowledge/wiki/tilemap.md +13 -13
  64. package/knowledge/wiki/time.md +4 -4
  65. package/knowledge/wiki/timeline.md +14 -14
  66. package/knowledge/wiki/transform.md +8 -8
  67. package/knowledge/wiki/tween.md +17 -17
  68. package/knowledge/wiki/ui.md +245 -269
  69. package/knowledge/wiki/video.md +5 -5
  70. package/knowledge/wiki/world.md +36 -36
  71. package/package.json +4 -4
  72. package/schema/api.schema.json +2238 -81
  73. package/shell/page.ts +4 -0
  74. package/shell/platform.ts +5 -0
  75. package/shell/player.ts +8 -2
  76. package/shell/transport.ts +6 -0
  77. package/src/generated/abi.ts +40 -1
  78. package/src/geom.ts +260 -0
  79. package/src/index.ts +19 -1
  80. package/src/node/device.ts +5 -2
  81. package/src/node/playtest-run.ts +1 -0
  82. package/src/node/polish.ts +34 -15
  83. package/src/node/run.ts +23 -6
  84. package/src/platform-local.ts +2 -0
  85. package/src/playtest.ts +8 -0
  86. package/src/runtime.ts +88 -6
  87. package/src/ui-kit/settings.ts +9 -0
  88. package/src/web/gl-state.ts +907 -0
  89. package/src/web/shell.ts +1 -1
  90. package/src/web/worker.ts +8 -2
  91. package/types/bindings.json +1222 -453
  92. package/types/index.d.ts +1868 -315
package/types/index.d.ts CHANGED
@@ -31,12 +31,32 @@ export interface FieldSpec<K extends ColumnKind = ColumnKind> {
31
31
  readonly capacity?: number;
32
32
  }
33
33
 
34
+ /** The column kinds a list holds: one number (`f32`, `f64`, `u32`, `i32`) or a handle. */
35
+ export type ListKind = {
36
+ [K in ColumnKind]: ColumnKinds[K]["value"] extends number ? K : never;
37
+ }[ColumnKind];
38
+
39
+ /**
40
+ * A list field, made by `list(of, capacity)`: at most `list` values of the
41
+ * element's kind, starting empty. Its value is a frozen array: read it as a
42
+ * copy, write it whole (`post.custom = [...post.custom, h]`).
43
+ */
44
+ export interface ListSpec<K extends ListKind = ListKind> {
45
+ readonly kind: K;
46
+ readonly default: readonly ColumnKinds[K]["value"][];
47
+ readonly options: FieldOptions;
48
+ /** The capacity in elements, 1 to 1024. */
49
+ readonly list: number;
50
+ }
51
+
34
52
  /** A reflected layout: field names to field specs. */
35
- export type Fields = { readonly [field: string]: FieldSpec };
53
+ export type Fields = { readonly [field: string]: FieldSpec | ListSpec };
36
54
 
37
- /** The value of a layout: each field as its column's value type. */
55
+ /** The value of a layout: each field as its column's value type, a list as a read-only array of it. */
38
56
  export type FieldValues<F extends Fields> = {
39
- -readonly [K in keyof F]: ColumnKinds[F[K]["kind"]]["value"];
57
+ -readonly [K in keyof F]: F[K] extends { readonly list: number }
58
+ ? readonly ColumnKinds[F[K]["kind"]]["value"][]
59
+ : ColumnKinds[F[K]["kind"]]["value"];
40
60
  };
41
61
 
42
62
  /** The typed views of a layout: each field as its column's typed array. */
@@ -117,6 +137,8 @@ export interface ColumnKinds {
117
137
  Material: { readonly array: Uint32Array; readonly stride: 2; readonly value: Material };
118
138
  /** A ToneMapping field: the variant's index. */
119
139
  ToneMapping: { readonly array: Uint32Array; readonly stride: 1; readonly value: ToneMapping };
140
+ /** A QualityPreset field: the variant's index. */
141
+ QualityPreset: { readonly array: Uint32Array; readonly stride: 1; readonly value: QualityPreset };
120
142
  /** A Texture handle field (0 is none). */
121
143
  Texture: { readonly array: Uint32Array; readonly stride: 2; readonly value: Texture };
122
144
  /** A Lut handle field (0 is none). */
@@ -131,16 +153,26 @@ export interface ColumnKinds {
131
153
  DofQuality: { readonly array: Uint32Array; readonly stride: 1; readonly value: DofQuality };
132
154
  /** A SpriteBlend field: the variant's index. */
133
155
  SpriteBlend: { readonly array: Uint32Array; readonly stride: 1; readonly value: SpriteBlend };
156
+ /** A SpriteFacing field: the variant's index. */
157
+ SpriteFacing: { readonly array: Uint32Array; readonly stride: 1; readonly value: SpriteFacing };
134
158
  /** A StripBlend field: the variant's index. */
135
159
  StripBlend: { readonly array: Uint32Array; readonly stride: 1; readonly value: StripBlend };
136
160
  /** A Palette handle field (0 is none). */
137
161
  Palette: { readonly array: Uint32Array; readonly stride: 2; readonly value: Palette };
162
+ /**
163
+ * A Look handle field (0 is none): a look og.load.look answered, kept for og.render.applyLook.
164
+ */
165
+ Look: { readonly array: Uint32Array; readonly stride: 2; readonly value: Look };
138
166
  /** A DitherPattern field: the variant's index. */
139
167
  DitherPattern: { readonly array: Uint32Array; readonly stride: 1; readonly value: DitherPattern };
140
168
  /** A StyliseSpace field: the variant's index. */
141
169
  StyliseSpace: { readonly array: Uint32Array; readonly stride: 1; readonly value: StyliseSpace };
142
170
  /** A ReflectionProbeMode field: the variant's index. */
143
171
  ReflectionProbeMode: { readonly array: Uint32Array; readonly stride: 1; readonly value: ReflectionProbeMode };
172
+ /**
173
+ * A Shader handle field (0 is none): a material shader og.load.shader answered, kept for og.render.shaderMaterial.
174
+ */
175
+ Shader: { readonly array: Uint32Array; readonly stride: 2; readonly value: Shader };
144
176
  /** A LineMode field: the variant's index. */
145
177
  LineMode: { readonly array: Uint32Array; readonly stride: 1; readonly value: LineMode };
146
178
  /** A RenderTargetFormat field: the variant's index. */
@@ -155,6 +187,14 @@ export interface ColumnKinds {
155
187
  Asset: { readonly array: Uint32Array; readonly stride: 2; readonly value: Asset };
156
188
  /** A Sound handle field. */
157
189
  Sound: { readonly array: Uint32Array; readonly stride: 2; readonly value: Sound };
190
+ /**
191
+ * A Font handle field (0 is none): a font og.load.font answered, kept for og.render.text or og.ui.configure.
192
+ */
193
+ Font: { readonly array: Uint32Array; readonly stride: 2; readonly value: Font };
194
+ /**
195
+ * A Style handle field (0 is none): a UI style og.load.style answered, kept for og.ui.configure.
196
+ */
197
+ Style: { readonly array: Uint32Array; readonly stride: 2; readonly value: Style };
158
198
  /** A SkeletonAsset handle field. */
159
199
  SkeletonAsset: { readonly array: Uint32Array; readonly stride: 2; readonly value: SkeletonAsset };
160
200
  /** A ClipAsset handle field. */
@@ -169,6 +209,12 @@ export interface ColumnKinds {
169
209
  IkSolver: { readonly array: Uint32Array; readonly stride: 1; readonly value: IkSolver };
170
210
  /** An IkSpace field: the variant's index. */
171
211
  IkSpace: { readonly array: Uint32Array; readonly stride: 1; readonly value: IkSpace };
212
+ /** A SpringSpace field: the variant's index. */
213
+ SpringSpace: { readonly array: Uint32Array; readonly stride: 1; readonly value: SpringSpace };
214
+ /** A SpringColliderShape field: the variant's index. */
215
+ SpringColliderShape: { readonly array: Uint32Array; readonly stride: 1; readonly value: SpringColliderShape };
216
+ /** A Rig handle field (0 is none): a humanoid map og.load.rig answered. */
217
+ Rig: { readonly array: Uint32Array; readonly stride: 2; readonly value: Rig };
172
218
  /** A FlipbookSheet handle field. */
173
219
  FlipbookSheet: { readonly array: Uint32Array; readonly stride: 2; readonly value: FlipbookSheet };
174
220
  /** A Rig2D handle field. */
@@ -179,6 +225,10 @@ export interface ColumnKinds {
179
225
  TilemapAsset: { readonly array: Uint32Array; readonly stride: 2; readonly value: TilemapAsset };
180
226
  /** An AudioBus field: the variant's index. */
181
227
  AudioBus: { readonly array: Uint32Array; readonly stride: 1; readonly value: AudioBus };
228
+ /** An AudioResampler field: the variant's index. */
229
+ AudioResampler: { readonly array: Uint32Array; readonly stride: 1; readonly value: AudioResampler };
230
+ /** A PanningModel field: the variant's index. */
231
+ PanningModel: { readonly array: Uint32Array; readonly stride: 1; readonly value: PanningModel };
182
232
  /** A Navigation handle field. */
183
233
  Navigation: { readonly array: Uint32Array; readonly stride: 2; readonly value: Navigation };
184
234
  /** A Behaviour handle field. */
@@ -901,8 +951,8 @@ export declare const color: ColorMath;
901
951
  // ── reflect ─────────────────────────────────────────────────────
902
952
  // Reflection: components and resources are declared once with their field layout and metadata, and registered by name.
903
953
  // The inspector, Tune, the probe, scene text and the wiki read this one schema. Each column factory below makes one field.
904
- // A field holds one value: there is no array or list column. A few values are numbered fields (`p0` to `p7`, as og.CameraRail does); a list of things is an entity each, with its own component, looped over by a query (a ring of skid marks, the laps of a race); a long record (a lap's taped inputs) is text in `str` fields of at most 4,096 bytes each, chunked over entities. Keep none of it in module variables: they are not world state, so a snapshot, a replay and a hot reload lose them.
905
- // A handle (an og.load answer, a texture, a sound, a geometry, a material, an entity) is a 64-bit number: keep it in a field of its own kind (`Asset()`, `Texture()`, `Sound()`, `Geometry()`, `Material()`, `Entity()`, the factories of the API's handle types), in a component or a resource. A `u32` field refuses one (handles pass 2^32: `4294967298 is not a u32`); an `f64` holds the number but loses its type.
954
+ // A field holds one value, or a list of at most a fixed number of one number type or handle: `list(u32(), 8)`, `list(Asset(), 4)` (the list factory below). A list is read as a frozen copy (`push` throws) and written whole (`chain.passes = [...chain.passes, h]`); one over its capacity is refused, never truncated. A few vectors are numbered fields (`p0` to `p7`, as og.CameraRail does); a list of things with fields of their own is an entity each, with its own component, looped over by a query (a ring of skid marks, the laps of a race); a long record (a lap's taped inputs) is text in `str` fields of at most 4,096 bytes each, chunked over entities. Keep none of it in module variables: they are not world state, so a snapshot, a replay and a hot reload lose them.
955
+ // A handle (an og.load answer, a texture, a sound, a geometry, a material, an entity) is a 64-bit number: keep it in a field of its own kind (`Asset()`, `Texture()`, `Sound()`, `Font()`, `Style()`, `Geometry()`, `Material()`, `Entity()`: every handle type of the API has its factory, named as the type), never cast to another kind, in a component or a resource. A `u32` field refuses one (handles pass 2^32: `4294967298 is not a u32`); an `f64` holds the number but loses its type.
906
956
 
907
957
  /**
908
958
  * Metadata of one field. Ranges and units are what Tune and the probe's bounds show. Nothing clamps writes: game code's writes (world.set, a resource field, a column) are stored as given, and writes from outside the game (the probe's `set`, `patch` and sweeps, Tune, a look's fields at cook) are refused outside min..max with the range named.
@@ -1055,6 +1105,17 @@ export declare function Color(value?: Color, options?: FieldOptions): FieldSpec<
1055
1105
  */
1056
1106
  export declare function str(capacity: number, value?: string, options?: FieldOptions): FieldSpec<"str">;
1057
1107
 
1108
+ /**
1109
+ * A list of at most `capacity` values of one number column (`f32`, `f64`, `u32`, `i32`) or handle column (`Asset`, `Entity`, `Post`, ...), stored inline: a count, then the elements, zeros past the count, so `[]` and `[0]` differ and the list is world state like a number. The capacity is 1 to 1,024 elements; it starts empty and is never tunable.
1110
+ * Reading it answers a frozen array, a copy: `push`, `splice` and index writes throw, so change it by writing a whole array (`v.passes = [...v.passes, h]`, `v.passes = []`). A list over the capacity is refused with the fix named (an error value from world.insert/world.set, a throw from a resource's setter), never truncated. Scene text and looks give it on one line, its elements in order (`passes 3 5`), the key alone for the empty list. Its view is the element's typed array with a stride of (capacity + 1) elements, the count first.
1111
+ *
1112
+ * A list field: stored in the element's typed array, (capacity + 1) of its lanes per entity, the count first.
1113
+ * @param of The element's column factory, called for its kind: `u32()`, `Asset()`, `Post()` (its default and options are not used).
1114
+ * @param capacity The most elements it holds, 1 to 1024.
1115
+ * @param options Label and docs (a list has no range and is not tunable).
1116
+ */
1117
+ export declare function list<K extends ListKind>(of: FieldSpec<K>, capacity: number, options?: FieldOptions): ListSpec<K>;
1118
+
1058
1119
  /**
1059
1120
  * Declare a component: plain data stored per entity in engine memory, one column per field.
1060
1121
  * Registration is by name, so a hot reload re-registers the same component and migrates its fields by name.
@@ -4030,7 +4091,33 @@ export type ToneMapping = "aces" | "agx" | "none";
4030
4091
  export declare function ToneMapping(value?: ToneMapping, options?: FieldOptions): FieldSpec<"ToneMapping">;
4031
4092
 
4032
4093
  /**
4033
- * The frame's look after lighting: environment light, sky, bloom, exposure metering and tone mapping. Read after each tick; it never feeds back into the simulation. Camera.exposure is the manual exposure.
4094
+ * A graphics preset: a row of RenderSettings' quality fields that og.render.applyQuality writes (its doc has the table). The settings screen (og.ui.settingsScreen) offers the three.
4095
+ * - `"medium"`: The full frame: every quality field at its default.
4096
+ * - `"low"`: The cheapest frame: no rect-light shadows, two shadowed lights, half-size shadow maps, plain fog, hard particles, no screen-space reflections or ambient occlusion, FXAA for MSAA.
4097
+ * - `"high"`: The full frame with the shadow maps at twice their side.
4098
+ */
4099
+ export type GraphicsQuality = "medium" | "low" | "high";
4100
+
4101
+ /**
4102
+ * The preset RenderSettings' quality fields were last written with (RenderSettings.quality).
4103
+ * - `"none"`: No preset applied: the fields are their defaults or the game's own.
4104
+ * - `"low"`: og.render.applyQuality(world, "low").
4105
+ * - `"medium"`: og.render.applyQuality(world, "medium").
4106
+ * - `"high"`: og.render.applyQuality(world, "high").
4107
+ */
4108
+ export type QualityPreset = "none" | "low" | "medium" | "high";
4109
+
4110
+ /**
4111
+ * A QualityPreset field: the variant's index.
4112
+ *
4113
+ * A `QualityPreset` field: stored in a `Uint32Array` with stride 1.
4114
+ * @param value The field's default; omitted, the column's zero value.
4115
+ * @param options Range, unit, label, docs and the tunable flag.
4116
+ */
4117
+ export declare function QualityPreset(value?: QualityPreset, options?: FieldOptions): FieldSpec<"QualityPreset">;
4118
+
4119
+ /**
4120
+ * The frame's look after lighting: environment light, sky, bloom, exposure metering and tone mapping, and what the frame may cost: the quality fields (rectShadows to msaaSamples) that og.render.applyQuality sets from a graphics preset. Read after each tick; it never feeds back into the simulation. Camera.exposure is the manual exposure.
4034
4121
  *
4035
4122
  * The `RenderSettings` resource (token `og.RenderSettings`).
4036
4123
  */
@@ -4115,7 +4202,7 @@ export interface RenderSettings {
4115
4202
  */
4116
4203
  decalAtlas: Texture;
4117
4204
  /**
4118
- * A multiplier on every model's projected size when its level of detail is picked (og.Model.lodBias multiplies it again): 1 is the engine's choice, 2 keeps full meshes twice as far, 0.5 simplifies sooner; 0 draws every model at its full mesh.
4205
+ * A multiplier on every model's projected level-of-detail error when its level is picked (og.Model.lodBias multiplies it again): a level is drawn while its error, measured by the cook against the full mesh, covers less than a pixel on the screen. 1 is the engine's choice, 2 keeps full meshes twice as far, 0.5 simplifies sooner; 0 draws every model at its full mesh.
4119
4206
  *
4120
4207
  * @default 1
4121
4208
  * @range 0..16
@@ -4128,6 +4215,61 @@ export interface RenderSettings {
4128
4215
  * @default true
4129
4216
  */
4130
4217
  bakedLighting: boolean;
4218
+ /**
4219
+ * The graphics preset og.render.applyQuality last wrote into the quality fields below (rectShadows to msaaSamples), or none. A record for the settings screen and the probe: the renderer reads the fields, never this, so a field the game sets after the preset is drawn as set.
4220
+ */
4221
+ quality: QualityPreset;
4222
+ /**
4223
+ * Rect lights whose castShadow is on cast their soft shadows; false draws every rect light unshadowed, each keeping its castShadow for when this is on again. The low preset turns it off: a rect light's shadow is the costliest light in the frame.
4224
+ *
4225
+ * @default true
4226
+ */
4227
+ rectShadows: boolean;
4228
+ /**
4229
+ * At most this many point, spot and rect lights cast shadows in a frame, the brightest at the camera kept (RenderCapabilities.shadowedLights caps it); 0 casts none. The directional light's cascades are not counted.
4230
+ *
4231
+ * @default 8
4232
+ * @range 0..8
4233
+ */
4234
+ shadowedLights: number;
4235
+ /**
4236
+ * The shadow maps at this fraction of their full side: the directional light's cascades (2048 texels by default) and the local lights' layers (512), each kept within 64 texels and the device's limit (4096 for the cascades). Changing it makes the maps again at the next frame; RenderCapabilities.shadowMapSize is the cascades' side drawn.
4237
+ *
4238
+ * @default 1
4239
+ * @range 0.125..4
4240
+ */
4241
+ shadowMapScale: number;
4242
+ /**
4243
+ * An og.VolumetricFog is drawn lit, with its light shafts; false draws the same medium as plain distance and height fog.
4244
+ *
4245
+ * @default true
4246
+ */
4247
+ volumetricFog: boolean;
4248
+ /**
4249
+ * Particles with a softDistance fade against the scene behind them; false draws them hard-edged and asks no depth prepass for them.
4250
+ *
4251
+ * @default true
4252
+ */
4253
+ softParticles: boolean;
4254
+ /**
4255
+ * PostEffects.ssr draws (on the full tier); false leaves smooth surfaces the reflection probes' and the environment's reflection. PostEffects keeps its settings either way.
4256
+ *
4257
+ * @default true
4258
+ */
4259
+ screenSpaceReflections: boolean;
4260
+ /**
4261
+ * PostEffects.ao darkens creases; false draws none. PostEffects keeps its settings either way.
4262
+ *
4263
+ * @default true
4264
+ */
4265
+ ambientOcclusion: boolean;
4266
+ /**
4267
+ * Samples per pixel where the antialiasing multisamples (msaa, the WebGL2 tier's choice; RenderCapabilities.antialias): 4, or 1, which draws FXAA instead. TAA, FXAA and no antialiasing take one sample whatever it says. Changing it makes the multisampled targets and pipelines again at the next frame.
4268
+ *
4269
+ * @default 4
4270
+ * @range 1..4
4271
+ */
4272
+ msaaSamples: number;
4131
4273
  }
4132
4274
 
4133
4275
  /**
@@ -4273,6 +4415,23 @@ export type SpriteBlend = "alpha" | "additive";
4273
4415
  */
4274
4416
  export declare function SpriteBlend(value?: SpriteBlend, options?: FieldOptions): FieldSpec<"SpriteBlend">;
4275
4417
 
4418
+ /**
4419
+ * How a world sprite turns towards the camera that draws it: a billboard (three.js Sprite). Decided as a mode of og.Sprite and SpriteDesc rather than a component of its own: a billboard is the same quad, texture, region, flash, glow, blend, layer, drop shadow and texture array layer as any sprite, drawn by the same sprite batch and shader, which only stands its corners differently. The turn is computed on the GPU from each camera's own axes (the main camera, every og.CameraView and og.Mirror, every face of a reflection probe), so it never feeds back into the simulation and a snapshot holds only the mode. The sprite turns about its anchor (a nine-slice turns as one panel), `rotation` still turns it within its own plane, and its drop shadow is cast by the quad stood upright facing the sun, so it shows the whole shape from every camera. Within its layer a faced sprite without sortY draws back to front from the camera's eye (by view depth; a probe's six faces by distance from the probe), after the layer's drop shadows and before its unfaced sprites; and it is culled by its bounds (a sphere round the anchor through the farthest corner) against the camera's view. Sprites draw over the 3D scene after its transparent meshes and particles, depth tested and not depth writing, so a billboard behind a transparent mesh still draws over it.
4420
+ * - `"none"`: In the world's xy plane facing +z, as every sprite before billboards.
4421
+ * - `"camera"`: In the camera's view plane: its x along the camera's right, its y along its up, as particle billboards (smoke, glints, impostors seen from any side).
4422
+ * - `"cameraY"`: Upright, turned about the world's y axis towards the camera: its y stays +y, its x the camera's right laid level. Trees, characters and props that must stand while the camera looks down on them.
4423
+ */
4424
+ export type SpriteFacing = "none" | "camera" | "cameraY";
4425
+
4426
+ /**
4427
+ * A SpriteFacing field: the variant's index.
4428
+ *
4429
+ * A `SpriteFacing` field: stored in a `Uint32Array` with stride 1.
4430
+ * @param value The field's default; omitted, the column's zero value.
4431
+ * @param options Range, unit, label, docs and the tunable flag.
4432
+ */
4433
+ export declare function SpriteFacing(value?: SpriteFacing, options?: FieldOptions): FieldSpec<"SpriteFacing">;
4434
+
4276
4435
  /**
4277
4436
  * How a trail, ribbon or beam is blended.
4278
4437
  * - `"additive"`: Added: glowing streaks, lasers, magic.
@@ -4617,23 +4776,11 @@ export interface PostEffects {
4617
4776
  */
4618
4777
  ssrIntensity: number;
4619
4778
  /**
4620
- * The first custom post pass (og.load.post, a `type post` asset; 0 is none). PostEffects.custom1 to custom8 are an ordered list, as many as og-render runs (RenderCapabilities.maxCustomPosts): each runs over the one before it (the lit image for the first), after depth of field and motion blur and before exposure, bloom and the tone curve, and reads the lit image, depth and normals too (it turns the prepass on). Its parameters are set with og.render.setPostParam. A pass the device fails to compile is reported (og.render.postErrors) and skipped.
4779
+ * The custom post passes, in order (og.load.post, `type post` assets): at most RenderCapabilities.maxCustomPosts (8, og-render's MAX_CUSTOM_POSTS). Each runs over the one before it (the lit image for the first), after depth of field and motion blur and before exposure, bloom and the tone curve, and reads the lit image, depth and normals too (any pass turns the prepass on). Write the whole list: `post.custom = [grade, crt]`, `post.custom = []`; a look gives it on one line (`custom "post/tint.ogt" "post/crt.ogt"`). A 0 in it is skipped. Its parameters are set with og.render.setPostParam. A pass the device fails to compile is reported (og.render.postErrors) and skipped.
4780
+ *
4781
+ * @capacity 8 elements (List.Post.8): reading answers a frozen copy (push throws); write a whole array, refused over the capacity, never truncated
4621
4782
  */
4622
- custom1: Post;
4623
- /** The second custom post pass, over the first's output (0 skips the slot). */
4624
- custom2: Post;
4625
- /** The third custom post pass. */
4626
- custom3: Post;
4627
- /** The fourth custom post pass. */
4628
- custom4: Post;
4629
- /** The fifth custom post pass. */
4630
- custom5: Post;
4631
- /** The sixth custom post pass. */
4632
- custom6: Post;
4633
- /** The seventh custom post pass. */
4634
- custom7: Post;
4635
- /** The eighth and last custom post pass, over every one before it. */
4636
- custom8: Post;
4783
+ custom: readonly Post[];
4637
4784
  }
4638
4785
 
4639
4786
  /**
@@ -4659,6 +4806,15 @@ export type Look = number & { readonly [handleType]: "Look" };
4659
4806
  */
4660
4807
  export declare function Palette(value?: Palette, options?: FieldOptions): FieldSpec<"Palette">;
4661
4808
 
4809
+ /**
4810
+ * A Look handle field (0 is none): a look og.load.look answered, kept for og.render.applyLook.
4811
+ *
4812
+ * A `Look` field: stored in a `Uint32Array` with stride 2.
4813
+ * @param value The field's default; omitted, the column's zero value.
4814
+ * @param options Range, unit, label, docs and the tunable flag.
4815
+ */
4816
+ export declare function Look(value?: Look, options?: FieldOptions): FieldSpec<"Look">;
4817
+
4662
4818
  /**
4663
4819
  * The threshold pattern Stylise.dither spreads the steps of posterize and palette with.
4664
4820
  * - `"none"`: No dither: every pixel rounds to its nearest step or colour, in flat bands.
@@ -5656,7 +5812,7 @@ export interface TextMetrics {
5656
5812
  }
5657
5813
 
5658
5814
  /**
5659
- * A textured or solid quad in the world's xy plane facing +z, drawn this frame only (immediate mode, as og.render.text): submit it every tick it should show. Sprites and text are sorted by layer and drawn over the 3D scene.
5815
+ * A textured or solid quad in the world's xy plane facing +z (or turned to the camera, `facing`), drawn this frame only (immediate mode, as og.render.text): submit it every tick it should show. Sprites and text are sorted by layer and drawn over the 3D scene.
5660
5816
  *
5661
5817
  * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
5662
5818
  */
@@ -5792,6 +5948,12 @@ export interface SpriteDesc {
5792
5948
  * @default true
5793
5949
  */
5794
5950
  readonly toneMapped?: boolean;
5951
+ /**
5952
+ * A billboard: none keeps the quad in the world's xy plane; camera turns it into the view plane of each camera that draws it; cameraY stands it upright turned about y towards the camera (trees, characters). World sprites only (a screen sprite ignores it); see SpriteFacing for sorting, culling and its drop shadow.
5953
+ *
5954
+ * @default "none"
5955
+ */
5956
+ readonly facing?: SpriteFacing;
5795
5957
  /**
5796
5958
  * Mirror the region left to right.
5797
5959
  *
@@ -5839,7 +6001,7 @@ export interface SpriteDesc {
5839
6001
 
5840
6002
 
5841
6003
  /**
5842
- * A sprite drawn every frame at the entity's MatrixWorld (its xy and z, its rotation about z; its scale multiplies width and height, so squash and stretch is a tween of og.Transform.scale). With an og.Flipbook on the entity, the texture (or an `array true` sheet's texture array layer), region and anchor come from the flipbook's current frame.
6004
+ * A sprite drawn every frame at the entity's MatrixWorld (its xy and z, its rotation about z, in the xy plane or turned to the camera by `facing`; its scale multiplies width and height, so squash and stretch is a tween of og.Transform.scale). With an og.Flipbook on the entity, the texture (or an `array true` sheet's texture array layer), region and anchor come from the flipbook's current frame.
5843
6005
  * Sorted with the immediate sprites and text by layer, then (sortY) by y, then texture: one draw per run of one texture. Tile layers draw before the sprites of their layer.
5844
6006
  *
5845
6007
  * The value of the `Sprite` component (token `og.Sprite`).
@@ -5907,6 +6069,10 @@ export interface Sprite {
5907
6069
  * Within its layer, lower y draws in front: top-down characters, props and trees overlap by their feet.
5908
6070
  */
5909
6071
  sortY: boolean;
6072
+ /**
6073
+ * A billboard (SpriteDesc.facing): none keeps the quad in the world's xy plane; camera turns it into each camera's view plane; cameraY stands it upright turned about y towards the camera, for trees and characters in a 3D set. Its afterimages face as it does; its blob shadow stays flat.
6074
+ */
6075
+ facing: SpriteFacing;
5910
6076
  /** Mirror left to right (a character facing left). */
5911
6077
  flipX: boolean;
5912
6078
  /** Mirror top to bottom. */
@@ -6323,7 +6489,7 @@ export interface RenderCapabilities {
6323
6489
  /** The largest side of a render target (the device's largest 2D texture). */
6324
6490
  readonly maxRenderTargetSize: number;
6325
6491
  /**
6326
- * The most custom post passes a frame runs: 8 on every tier, PostEffects.custom1 to custom8 (numbered fields, as a reflected record has no list field).
6492
+ * The most custom post passes a frame runs: 8 on every tier, PostEffects.custom's capacity.
6327
6493
  */
6328
6494
  readonly maxCustomPosts: number;
6329
6495
  /**
@@ -6339,9 +6505,17 @@ export interface RenderCapabilities {
6339
6505
  */
6340
6506
  readonly maxLightCookies: number;
6341
6507
  /**
6342
- * Whether the device times each render pass on the GPU (timestamp queries: Vulkan, Metal and D3D12 adapters that have them, WebGPU with `timestamp-query`; never WebGL2): ProbeTimings.gpuPasses and the trace's gpu thread are filled only where it is true.
6508
+ * Whether the device times each render pass on the GPU (timestamp queries: Vulkan, Metal and D3D12 adapters that have them, WebGPU with `timestamp-query`; never WebGL2, and never in a publish build, which leaves the queries out): ProbeTimings.gpuPasses and the trace's gpu thread are filled only where it is true.
6343
6509
  */
6344
6510
  readonly gpuTimestamps: boolean;
6511
+ /**
6512
+ * The anisotropic filtering of sprites and og.ui's images (text is not filtered anisotropically: its distance field would lose its edge): 16 where the device filters anisotropically (WebGPU, Vulkan, Metal, WebGL2 with EXT_texture_filter_anisotropic), 1 where it has none and on a software rasterizer (the vulkan-cpu tier: lavapipe's anisotropic filter softens even an image drawn 1:1), 0 without a renderer. Above 1, an image squeezed along one axis keeps the other axis's detail: a style's nine-slice middle squeezed into a short button keeps its outline as crisp as the corners. At 1 the squeezed piece reads a smaller mip level and blurs; og.ui bounds a middle's squeeze at twice its art, so the outline there is one mip level softer than the corners.
6513
+ */
6514
+ readonly spriteAnisotropy: number;
6515
+ /**
6516
+ * Whether the renderer draws the 3D world subsystems: terrain, planar water (og.Water), the 3D fluids, scattered copies and volumetric fog. False in the 2D profile's publish and lanes modules, which leave them out (a scene's are not drawn, og.terrain's calls and a SHAPE_HEIGHTFIELD collider answer a refusal naming this field, and `og build --publish` refuses a 2D project whose scenes hold og.Terrain, og.TerrainScatter, og.Water, og.WaterSurface or og.Fluid3D, by scene file and line); true in the 3D modules, the dev module and the native host.
6517
+ */
6518
+ readonly world3d: boolean;
6345
6519
  }
6346
6520
 
6347
6521
  /**
@@ -6429,6 +6603,16 @@ export interface ReflectionProbe {
6429
6603
  */
6430
6604
  export type Shader = number & { readonly [handleType]: "Shader" };
6431
6605
 
6606
+ /**
6607
+ * A Shader handle field (0 is none): a material shader og.load.shader answered, kept for og.render.shaderMaterial.
6608
+ *
6609
+ * A `Shader` field: stored in a `Uint32Array` with stride 2.
6610
+ * @param value The field's default; omitted, the column's zero value.
6611
+ * @param options Range, unit, label, docs and the tunable flag.
6612
+ */
6613
+ export declare function Shader(value?: Shader, options?: FieldOptions): FieldSpec<"Shader">;
6614
+
6615
+
6432
6616
 
6433
6617
 
6434
6618
 
@@ -6860,177 +7044,696 @@ export interface TubeGeometryDesc {
6860
7044
 
6861
7045
 
6862
7046
  /**
6863
- * How a line set's points join, as three.js's three line objects.
6864
- * - `"strip"`: One polyline through every point, as three.js Line.
6865
- * - `"segments"`: Pairs of points, each its own segment, as three.js LineSegments.
6866
- * - `"loop"`: A polyline closed back to its first point, as three.js LineLoop.
7047
+ * A shape as points, what og.Shape.extractPoints returns and what shapeGeometry, extrudeGeometry and sweepGeometry read: the outline, then each hole. A repeated closing point is dropped, as three.js drops it.
6867
7048
  */
6868
- export type LineMode = "strip" | "segments" | "loop";
7049
+ export interface ShapePoints {
7050
+ /** The outline's points, in order. */
7051
+ readonly shape: readonly Vector2[];
7052
+ /** Each hole's points, in order. */
7053
+ readonly holes: readonly (readonly Vector2[])[];
7054
+ }
6869
7055
 
6870
7056
  /**
6871
- * A LineMode field: the variant's index.
7057
+ * A flat shape with holes in the xy plane facing +Z, as three.js ShapeGeometry(shapes, curveSegments): triangulated by earcut (three.js's own port), the outline made clockwise and the holes counter-clockwise first, so its vertices and triangles are three.js's for the same shape. uvs are world x and y (v flipped to run down the image).
6872
7058
  *
6873
- * A `LineMode` field: stored in a `Uint32Array` with stride 1.
6874
- * @param value The field's default; omitted, the column's zero value.
6875
- * @param options Range, unit, label, docs and the tunable flag.
7059
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
6876
7060
  */
6877
- export declare function LineMode(value?: LineMode, options?: FieldOptions): FieldSpec<"LineMode">;
7061
+ export interface ShapeGeometryDesc {
7062
+ /**
7063
+ * One og.Shape (an og.Path2 is a shape without holes), a list of them, or the outline's points. Without it, three.js's default triangle (0, 0.5), (-0.5, -0.5), (0.5, -0.5).
7064
+ *
7065
+ * @default null
7066
+ */
7067
+ readonly shapes?: Path2 | readonly Path2[] | readonly Vector2[] | null;
7068
+ /**
7069
+ * Points per curve when an og.Shape's curves are flattened (three.js extractPoints(curveSegments); an ellipse takes twice as many, a spline as many per point).
7070
+ *
7071
+ * @default 12
7072
+ * @range 1..
7073
+ */
7074
+ readonly curveSegments?: number;
7075
+ /**
7076
+ * How many times a texture repeats across it, along u and v: its UVs scaled by uvRepeat (three.js texture.repeat, here on the geometry; material textures sample with repeat wrapping).
7077
+ *
7078
+ * @default { x: 1, y: 1 }
7079
+ */
7080
+ readonly uvRepeat?: Vector2;
7081
+ /**
7082
+ * Register it as a physics mesh too (BufferGeometryDesc.physics).
7083
+ *
7084
+ * @default true
7085
+ */
7086
+ readonly physics?: boolean;
7087
+ /**
7088
+ * Whether og.render.updateGeometry may rewrite it later (BufferGeometryDesc.dynamic).
7089
+ *
7090
+ * @default false
7091
+ */
7092
+ readonly dynamic?: boolean;
7093
+ }
6878
7094
 
6879
7095
  /**
6880
- * Lines through points, drawn this frame only (immediate mode, as og.render.sprite): submit them every tick they should show. three.js Line, LineSegments and LineLoop with a LineBasicMaterial or LineDashedMaterial, but any width on every tier (each segment is a quad in screen space with a feathered edge, so WebGL2's one-pixel lines do not apply).
6881
- * World lines are drawn in the scene after the transparent meshes and particles, exposed, bloomed and tone mapped with it; screen lines over the finished frame, after every post effect and under the UI.
7096
+ * Shapes pushed along +Z, or along a path, as three.js ExtrudeGeometry(shapes, options) with its option names and defaults: a closed solid, its lids from earcut and its walls ring by ring, rounded by a bevel of bevelSegments rings at each face. Unindexed as three.js's (every triangle its own vertices, flat normals), three.js's vertex order and counts; uvs from three.js's WorldUVGenerator (v flipped to run down the image).
6882
7097
  *
6883
7098
  * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
6884
7099
  */
6885
- export interface LinesDesc {
7100
+ export interface ExtrudeGeometryDesc {
6886
7101
  /**
6887
- * The points, in order: world positions, or with screen CSS pixels from the top left of the play surface with y down (z ignored).
7102
+ * One og.Shape, a list of them, or the outline's points. Without it, three.js's default square of side 1.
6888
7103
  *
6889
- * @default []
7104
+ * @default null
7105
+ */
7106
+ readonly shapes?: Path2 | readonly Path2[] | readonly Vector2[] | null;
7107
+ /**
7108
+ * How far the shape is pushed along +Z (without extrudePath).
7109
+ *
7110
+ * @default 1
7111
+ * @range 0..
6890
7112
  * @unit m (metres)
6891
7113
  */
6892
- readonly points?: readonly Vector3[];
7114
+ readonly depth?: number;
6893
7115
  /**
6894
- * Per point linear colours, blended along each segment (three.js vertexColors); empty is `color` for all.
7116
+ * Rings along the depth or the path.
6895
7117
  *
6896
- * @default []
7118
+ * @default 1
7119
+ * @range 1..
6897
7120
  */
6898
- readonly colors?: readonly Color[];
7121
+ readonly steps?: number;
6899
7122
  /**
6900
- * The linear colour.
7123
+ * Round the edges of both faces.
6901
7124
  *
6902
- * @default { r: 1, g: 1, b: 1 }
7125
+ * @default true
6903
7126
  */
6904
- readonly color?: Color;
7127
+ readonly bevelEnabled?: boolean;
6905
7128
  /**
6906
- * The alpha.
7129
+ * How far the bevel reaches beyond each face, along z.
6907
7130
  *
6908
- * @default 1
6909
- * @range 0..1
7131
+ * @default 0.2
7132
+ * @range 0..
7133
+ * @unit m (metres)
6910
7134
  */
6911
- readonly opacity?: number;
7135
+ readonly bevelThickness?: number;
6912
7136
  /**
6913
- * How the points join.
7137
+ * How far the bevel reaches out from the outline. Null or unset, bevelThickness - 0.1, as three.js derives it (0.1 at the default thickness, 0 at a thickness of 0.1).
6914
7138
  *
6915
- * @default "strip"
7139
+ * @default null
7140
+ * @unit m (metres)
6916
7141
  */
6917
- readonly mode?: LineMode;
7142
+ readonly bevelSize?: number | null;
6918
7143
  /**
6919
- * The width: CSS pixels, or world units with worldUnits.
7144
+ * How far the bevel starts out from the outline.
6920
7145
  *
6921
- * @default 1
6922
- * @range 0..
7146
+ * @default 0
7147
+ * @unit m (metres)
6923
7148
  */
6924
- readonly width?: number;
7149
+ readonly bevelOffset?: number;
6925
7150
  /**
6926
- * Measure width in world units (a line that thins with distance) instead of CSS pixels (as wide at any distance).
7151
+ * Rings in each bevel.
6927
7152
  *
6928
- * @default false
7153
+ * @default 3
7154
+ * @range 1..
6929
7155
  */
6930
- readonly worldUnits?: boolean;
7156
+ readonly bevelSegments?: number;
6931
7157
  /**
6932
- * Hidden behind nearer geometry, as three.js Material.depthTest; false draws it over the scene. Screen lines are never depth tested.
7158
+ * Points per curve when an og.Shape's curves are flattened.
6933
7159
  *
6934
- * @default true
7160
+ * @default 12
7161
+ * @range 1..
6935
7162
  */
6936
- readonly depthTest?: boolean;
7163
+ readonly curveSegments?: number;
6937
7164
  /**
6938
- * Draw in screen space over the finished frame: points in CSS pixels, width in CSS pixels.
7165
+ * A path (og.path.create or og.path.find) to extrude along instead of +Z: the shape's x along the path's normal and y along its binormal (three.js's Frenet frames), steps rings evenly spaced along it. A path turns the bevel off, as three.js. 0 extrudes along +Z.
6939
7166
  *
6940
- * @default false
7167
+ * @default 0
6941
7168
  */
6942
- readonly screen?: boolean;
7169
+ readonly extrudePath?: Path;
6943
7170
  /**
6944
- * Dashes, as three.js LineDashedMaterial: dashSize on, gapSize off, along the line from its first point.
7171
+ * How many times a texture repeats across it, along u and v: its UVs scaled by uvRepeat (three.js texture.repeat, here on the geometry; material textures sample with repeat wrapping).
6945
7172
  *
6946
- * @default false
7173
+ * @default { x: 1, y: 1 }
6947
7174
  */
6948
- readonly dashed?: boolean;
7175
+ readonly uvRepeat?: Vector2;
6949
7176
  /**
6950
- * A dash's length: world units (CSS pixels for screen lines).
7177
+ * Register it as a physics mesh too.
6951
7178
  *
6952
- * @default 3
6953
- * @range 0..
7179
+ * @default true
6954
7180
  */
6955
- readonly dashSize?: number;
7181
+ readonly physics?: boolean;
6956
7182
  /**
6957
- * A gap's length.
7183
+ * Whether og.render.updateGeometry may rewrite it later.
6958
7184
  *
6959
- * @default 1
6960
- * @range 0..
7185
+ * @default false
6961
7186
  */
6962
- readonly gapSize?: number;
7187
+ readonly dynamic?: boolean;
6963
7188
  }
6964
7189
 
6965
-
6966
7190
  /**
6967
- * A point cloud drawn this frame only (immediate mode), as three.js Points with a PointsMaterial: a square per point facing the camera. Submit it every tick it should show (og.Points keeps a static set).
7191
+ * A profile turned round +Y, as three.js LatheGeometry(points, segments, phiStart, phiLength): vases, bottles, columns, wheels. three.js's vertices, indices and smooth normals; u round the axis, v along the profile (flipped to run down the image). A whole turn's seam meets exactly.
6968
7192
  *
6969
7193
  * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
6970
7194
  */
6971
- export interface PointsDesc {
7195
+ export interface LatheGeometryDesc {
6972
7196
  /**
6973
- * The positions: world, or with screen CSS pixels from the top left, y down.
7197
+ * The profile, x the distance from the axis and y the height, in order (at least two). Without it, three.js's default (0, -0.5), (0.5, 0), (0, 0.5).
6974
7198
  *
6975
7199
  * @default []
6976
7200
  * @unit m (metres)
6977
7201
  */
6978
- readonly points?: readonly Vector3[];
6979
- /**
6980
- * Per point linear colours; empty is `color` for all.
6981
- *
6982
- * @default []
6983
- */
6984
- readonly colors?: readonly Color[];
7202
+ readonly points?: readonly Vector2[];
6985
7203
  /**
6986
- * The linear colour.
7204
+ * Segments round the axis.
6987
7205
  *
6988
- * @default { r: 1, g: 1, b: 1 }
7206
+ * @default 12
7207
+ * @range 1..
6989
7208
  */
6990
- readonly color?: Color;
7209
+ readonly segments?: number;
6991
7210
  /**
6992
- * The alpha.
7211
+ * Where the turn starts, from +Z towards +X.
6993
7212
  *
6994
- * @default 1
6995
- * @range 0..1
7213
+ * @default 0
7214
+ * @unit rad (radians)
6996
7215
  */
6997
- readonly opacity?: number;
7216
+ readonly phiStart?: number;
6998
7217
  /**
6999
- * The side of each square: world units with sizeAttenuation, else CSS pixels.
7218
+ * How far it turns; 2 pi is whole (clamped to it).
7000
7219
  *
7001
- * @default 1
7002
- * @range 0..
7220
+ * @default 6.283185307179586
7221
+ * @unit rad (radians)
7003
7222
  */
7004
- readonly size?: number;
7223
+ readonly phiLength?: number;
7005
7224
  /**
7006
- * Size in world units, smaller with distance, as three.js PointsMaterial.sizeAttenuation; false keeps every point `size` CSS pixels.
7225
+ * How many times a texture repeats across it, along u and v: its UVs scaled by uvRepeat (three.js texture.repeat, here on the geometry; material textures sample with repeat wrapping).
7007
7226
  *
7008
- * @default true
7227
+ * @default { x: 1, y: 1 }
7009
7228
  */
7010
- readonly sizeAttenuation?: boolean;
7229
+ readonly uvRepeat?: Vector2;
7011
7230
  /**
7012
- * Hidden behind nearer geometry; false draws them over the scene.
7231
+ * Register it as a physics mesh too.
7013
7232
  *
7014
7233
  * @default true
7015
7234
  */
7016
- readonly depthTest?: boolean;
7235
+ readonly physics?: boolean;
7017
7236
  /**
7018
- * Draw in screen space over the finished frame, positions and size in CSS pixels.
7237
+ * Whether og.render.updateGeometry may rewrite it later.
7019
7238
  *
7020
7239
  * @default false
7021
7240
  */
7022
- readonly screen?: boolean;
7241
+ readonly dynamic?: boolean;
7023
7242
  }
7024
7243
 
7025
-
7026
7244
  /**
7027
- * Draws a geometry's vertices as lines at the entity's MatrixWorld, every frame (three.js Line, LineSegments or LineLoop over a BufferGeometry): a static set of lines kept as data, a level's outline, a track, a constellation. The vertices are taken in order (the geometry's indices are not read), with its vertex colours times color.
7245
+ * A polyhedron from vertices and faces, every face subdivided `detail` times and every vertex pushed onto the sphere of `radius`, as three.js PolyhedronGeometry(vertices, indices, radius, detail): unindexed, flat normals at detail 0 and the sphere's above, three.js's spherical uvs.
7028
7246
  *
7029
- * The value of the `Lines` component (token `og.Lines`).
7247
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
7030
7248
  */
7031
- export interface Lines {
7032
- /** The vertices (og.render.bufferGeometry: an unindexed one of any count). */
7033
- geometry: Geometry;
7249
+ export interface PolyhedronGeometryDesc {
7250
+ /**
7251
+ * The corners, x y z each (three.js's flat array).
7252
+ *
7253
+ * @default []
7254
+ */
7255
+ readonly vertices?: readonly number[];
7256
+ /**
7257
+ * The faces, three corner indices each, counter-clockwise seen from outside.
7258
+ *
7259
+ * @default []
7260
+ */
7261
+ readonly indices?: readonly number[];
7262
+ /**
7263
+ * The sphere the vertices are pushed onto.
7264
+ *
7265
+ * @default 1
7266
+ * @range 0..
7267
+ * @unit m (metres)
7268
+ */
7269
+ readonly radius?: number;
7270
+ /**
7271
+ * Subdivisions of each face: (detail + 1)² triangles a face.
7272
+ *
7273
+ * @default 0
7274
+ * @range ..64
7275
+ */
7276
+ readonly detail?: number;
7277
+ /**
7278
+ * How many times a texture repeats across it, along u and v: its UVs scaled by uvRepeat (three.js texture.repeat, here on the geometry; material textures sample with repeat wrapping).
7279
+ *
7280
+ * @default { x: 1, y: 1 }
7281
+ */
7282
+ readonly uvRepeat?: Vector2;
7283
+ /**
7284
+ * Register it as a physics mesh too.
7285
+ *
7286
+ * @default true
7287
+ */
7288
+ readonly physics?: boolean;
7289
+ /**
7290
+ * Whether og.render.updateGeometry may rewrite it later.
7291
+ *
7292
+ * @default false
7293
+ */
7294
+ readonly dynamic?: boolean;
7295
+ }
7296
+
7297
+ /**
7298
+ * A regular solid, as three.js IcosahedronGeometry, DodecahedronGeometry, OctahedronGeometry and TetrahedronGeometry(radius, detail): PolyhedronGeometryDesc with the solid's own vertices and faces. An icosahedron at detail 2 or more is a sphere with even triangles.
7299
+ *
7300
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
7301
+ */
7302
+ export interface SolidGeometryDesc {
7303
+ /**
7304
+ * The radius.
7305
+ *
7306
+ * @default 1
7307
+ * @range 0..
7308
+ * @unit m (metres)
7309
+ */
7310
+ readonly radius?: number;
7311
+ /**
7312
+ * Subdivisions of each face.
7313
+ *
7314
+ * @default 0
7315
+ * @range ..64
7316
+ */
7317
+ readonly detail?: number;
7318
+ /**
7319
+ * How many times a texture repeats across it, along u and v: its UVs scaled by uvRepeat (three.js texture.repeat, here on the geometry; material textures sample with repeat wrapping).
7320
+ *
7321
+ * @default { x: 1, y: 1 }
7322
+ */
7323
+ readonly uvRepeat?: Vector2;
7324
+ /**
7325
+ * Register it as a physics mesh too.
7326
+ *
7327
+ * @default true
7328
+ */
7329
+ readonly physics?: boolean;
7330
+ /**
7331
+ * Whether og.render.updateGeometry may rewrite it later.
7332
+ *
7333
+ * @default false
7334
+ */
7335
+ readonly dynamic?: boolean;
7336
+ }
7337
+
7338
+ /**
7339
+ * A value at a fraction of a sweep's path: linear between keys, held before the first and past the last.
7340
+ */
7341
+ export interface SweepKey {
7342
+ /**
7343
+ * The fraction of the path's length, 0 to 1.
7344
+ *
7345
+ * @unit ratio (a fraction between 0 and 1)
7346
+ */
7347
+ readonly t: number;
7348
+ /** The value there. */
7349
+ readonly value: number;
7350
+ }
7351
+
7352
+ /**
7353
+ * A section swept along a path, scaled and twisted over it: horns, tusks, handles, blades, tapered pipes, twisted columns (img2threejs's tapered sweep; three.js has no class for it). The section's x lies along the path's normal and y along its binormal (three.js's Frenet frames), rings evenly spaced along the path's length; u runs along the path, v round the section (flipped to run down the image), the sides smooth. An open path's ends are capped.
7354
+ *
7355
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
7356
+ */
7357
+ export interface SweepGeometryDesc {
7358
+ /**
7359
+ * The section's outline: an og.Shape or og.Path2 (flattened by curveSegments; holes are not swept) or its points, at least three, either winding.
7360
+ *
7361
+ * @default null
7362
+ */
7363
+ readonly section?: Path2 | readonly Vector2[] | null;
7364
+ /**
7365
+ * The path (og.path.create or og.path.find).
7366
+ *
7367
+ * @default 0
7368
+ */
7369
+ readonly path?: Path;
7370
+ /**
7371
+ * Rings along the path, less one.
7372
+ *
7373
+ * @default 64
7374
+ * @range 1..
7375
+ */
7376
+ readonly steps?: number;
7377
+ /**
7378
+ * The section's scale over the path (none: 1 throughout). A horn: [{ t: 0, value: 1 }, { t: 1, value: 0.05 }].
7379
+ *
7380
+ * @default []
7381
+ */
7382
+ readonly scale?: readonly SweepKey[];
7383
+ /**
7384
+ * The section's turn round the path over its length, in radians (none: 0).
7385
+ *
7386
+ * @default []
7387
+ */
7388
+ readonly twist?: readonly SweepKey[];
7389
+ /**
7390
+ * Close the ends of an open path.
7391
+ *
7392
+ * @default true
7393
+ */
7394
+ readonly caps?: boolean;
7395
+ /**
7396
+ * Points per curve when an og.Shape section is flattened.
7397
+ *
7398
+ * @default 12
7399
+ * @range 1..
7400
+ */
7401
+ readonly curveSegments?: number;
7402
+ /**
7403
+ * How many times a texture repeats across it, along u and v: its UVs scaled by uvRepeat (three.js texture.repeat, here on the geometry; material textures sample with repeat wrapping).
7404
+ *
7405
+ * @default { x: 1, y: 1 }
7406
+ */
7407
+ readonly uvRepeat?: Vector2;
7408
+ /**
7409
+ * Register it as a physics mesh too.
7410
+ *
7411
+ * @default true
7412
+ */
7413
+ readonly physics?: boolean;
7414
+ /**
7415
+ * Whether og.render.updateGeometry may rewrite it later.
7416
+ *
7417
+ * @default false
7418
+ */
7419
+ readonly dynamic?: boolean;
7420
+ }
7421
+
7422
+ /**
7423
+ * The world axis a part is mirrored along, after its placement.
7424
+ * - `"none"`: Not mirrored.
7425
+ * - `"x"`: x negated: the mirror image across the yz plane.
7426
+ * - `"y"`: y negated: across the xz plane.
7427
+ * - `"z"`: z negated: across the xy plane.
7428
+ */
7429
+ export type MirrorAxis = "none" | "x" | "y" | "z";
7430
+
7431
+ /**
7432
+ * A geometry placed as an Object3D is (scale, then rotate, then move), then mirrored: one part of og.render.mergeGeometries or an operand of og.render.csgGeometry.
7433
+ *
7434
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
7435
+ */
7436
+ export interface GeometryPart {
7437
+ /**
7438
+ * Any geometry: made, a primitive or a loaded glTF's.
7439
+ *
7440
+ * @default 0
7441
+ */
7442
+ readonly geometry?: Geometry;
7443
+ /**
7444
+ * Where it goes.
7445
+ *
7446
+ * @default { x: 0, y: 0, z: 0 }
7447
+ * @unit m (metres)
7448
+ */
7449
+ readonly position?: Vector3;
7450
+ /**
7451
+ * How it turns.
7452
+ *
7453
+ * @default { x: 0, y: 0, z: 0, w: 1 }
7454
+ */
7455
+ readonly quaternion?: Quaternion;
7456
+ /**
7457
+ * Its scale (a negative component mirrors it as `mirror` does).
7458
+ *
7459
+ * @default { x: 1, y: 1, z: 1 }
7460
+ */
7461
+ readonly scale?: Vector3;
7462
+ /**
7463
+ * Mirror it along a world axis after placing it: a symmetric prop is one half twice, the second mirrored.
7464
+ *
7465
+ * @default "none"
7466
+ */
7467
+ readonly mirror?: MirrorAxis;
7468
+ }
7469
+
7470
+ /**
7471
+ * A boolean operation on two solids.
7472
+ * - `"union"`: Everything in either: a + b.
7473
+ * - `"subtract"`: What of a is not in b: a - b (holes, notches, a dice's pips).
7474
+ * - `"intersect"`: What is in both.
7475
+ */
7476
+ export type CsgOp = "union" | "subtract" | "intersect";
7477
+
7478
+ /**
7479
+ * Two closed geometries combined by a boolean operation, each placed first: a box with a hole bored through it, a dice, a window cut in a wall. The result is closed when both are (every edge shared by two triangles, wound opposite), every piece keeps its source's normals, uvs and colours (b's turned inside out where it is subtracted). Where a plane side or an edge crossing is decided, the decision is exact (Shewchuk's predicates), so every host makes the same cuts; faces that coincide keep one copy or none, as the operation says.
7480
+ *
7481
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
7482
+ */
7483
+ export interface CsgGeometryDesc {
7484
+ /**
7485
+ * The operation.
7486
+ *
7487
+ * @default "union"
7488
+ */
7489
+ readonly op?: CsgOp;
7490
+ /**
7491
+ * The first operand.
7492
+ *
7493
+ * @default {}
7494
+ */
7495
+ readonly a?: GeometryPart;
7496
+ /**
7497
+ * The second operand.
7498
+ *
7499
+ * @default {}
7500
+ */
7501
+ readonly b?: GeometryPart;
7502
+ /**
7503
+ * How many times a texture repeats across it, along u and v: its UVs scaled by uvRepeat (three.js texture.repeat, here on the geometry; material textures sample with repeat wrapping).
7504
+ *
7505
+ * @default { x: 1, y: 1 }
7506
+ */
7507
+ readonly uvRepeat?: Vector2;
7508
+ /**
7509
+ * Register it as a physics mesh too.
7510
+ *
7511
+ * @default true
7512
+ */
7513
+ readonly physics?: boolean;
7514
+ /**
7515
+ * Whether og.render.updateGeometry may rewrite it later.
7516
+ *
7517
+ * @default false
7518
+ */
7519
+ readonly dynamic?: boolean;
7520
+ }
7521
+
7522
+ /**
7523
+ * Geometries placed and merged into one, as three.js BufferGeometryUtils.mergeGeometries after applying each part's matrix: a prop of parts drawn in one draw, a mirrored half, an array (the same part at several placements). Normals follow each placement; a mirrored part turns its triangles so they still face out. Vertex colours are kept when any part has them.
7524
+ *
7525
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
7526
+ */
7527
+ export interface MergeGeometriesDesc {
7528
+ /**
7529
+ * The parts, in order (at least one).
7530
+ *
7531
+ * @default []
7532
+ */
7533
+ readonly parts?: readonly GeometryPart[];
7534
+ /**
7535
+ * How many times a texture repeats across it, along u and v: its UVs scaled by uvRepeat (three.js texture.repeat, here on the geometry; material textures sample with repeat wrapping).
7536
+ *
7537
+ * @default { x: 1, y: 1 }
7538
+ */
7539
+ readonly uvRepeat?: Vector2;
7540
+ /**
7541
+ * Register it as a physics mesh too.
7542
+ *
7543
+ * @default true
7544
+ */
7545
+ readonly physics?: boolean;
7546
+ /**
7547
+ * Whether og.render.updateGeometry may rewrite it later.
7548
+ *
7549
+ * @default false
7550
+ */
7551
+ readonly dynamic?: boolean;
7552
+ }
7553
+
7554
+
7555
+
7556
+
7557
+
7558
+
7559
+
7560
+
7561
+
7562
+
7563
+
7564
+
7565
+ /**
7566
+ * How a line set's points join, as three.js's three line objects.
7567
+ * - `"strip"`: One polyline through every point, as three.js Line.
7568
+ * - `"segments"`: Pairs of points, each its own segment, as three.js LineSegments.
7569
+ * - `"loop"`: A polyline closed back to its first point, as three.js LineLoop.
7570
+ */
7571
+ export type LineMode = "strip" | "segments" | "loop";
7572
+
7573
+ /**
7574
+ * A LineMode field: the variant's index.
7575
+ *
7576
+ * A `LineMode` field: stored in a `Uint32Array` with stride 1.
7577
+ * @param value The field's default; omitted, the column's zero value.
7578
+ * @param options Range, unit, label, docs and the tunable flag.
7579
+ */
7580
+ export declare function LineMode(value?: LineMode, options?: FieldOptions): FieldSpec<"LineMode">;
7581
+
7582
+ /**
7583
+ * Lines through points, drawn this frame only (immediate mode, as og.render.sprite): submit them every tick they should show. three.js Line, LineSegments and LineLoop with a LineBasicMaterial or LineDashedMaterial, but any width on every tier (each segment is a quad in screen space with a feathered edge, so WebGL2's one-pixel lines do not apply).
7584
+ * World lines are drawn in the scene after the transparent meshes and particles, exposed, bloomed and tone mapped with it; screen lines over the finished frame, after every post effect and under the UI.
7585
+ *
7586
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
7587
+ */
7588
+ export interface LinesDesc {
7589
+ /**
7590
+ * The points, in order: world positions, or with screen CSS pixels from the top left of the play surface with y down (z ignored).
7591
+ *
7592
+ * @default []
7593
+ * @unit m (metres)
7594
+ */
7595
+ readonly points?: readonly Vector3[];
7596
+ /**
7597
+ * Per point linear colours, blended along each segment (three.js vertexColors); empty is `color` for all.
7598
+ *
7599
+ * @default []
7600
+ */
7601
+ readonly colors?: readonly Color[];
7602
+ /**
7603
+ * The linear colour.
7604
+ *
7605
+ * @default { r: 1, g: 1, b: 1 }
7606
+ */
7607
+ readonly color?: Color;
7608
+ /**
7609
+ * The alpha.
7610
+ *
7611
+ * @default 1
7612
+ * @range 0..1
7613
+ */
7614
+ readonly opacity?: number;
7615
+ /**
7616
+ * How the points join.
7617
+ *
7618
+ * @default "strip"
7619
+ */
7620
+ readonly mode?: LineMode;
7621
+ /**
7622
+ * The width: CSS pixels, or world units with worldUnits.
7623
+ *
7624
+ * @default 1
7625
+ * @range 0..
7626
+ */
7627
+ readonly width?: number;
7628
+ /**
7629
+ * Measure width in world units (a line that thins with distance) instead of CSS pixels (as wide at any distance).
7630
+ *
7631
+ * @default false
7632
+ */
7633
+ readonly worldUnits?: boolean;
7634
+ /**
7635
+ * Hidden behind nearer geometry, as three.js Material.depthTest; false draws it over the scene. Screen lines are never depth tested.
7636
+ *
7637
+ * @default true
7638
+ */
7639
+ readonly depthTest?: boolean;
7640
+ /**
7641
+ * Draw in screen space over the finished frame: points in CSS pixels, width in CSS pixels.
7642
+ *
7643
+ * @default false
7644
+ */
7645
+ readonly screen?: boolean;
7646
+ /**
7647
+ * Dashes, as three.js LineDashedMaterial: dashSize on, gapSize off, along the line from its first point.
7648
+ *
7649
+ * @default false
7650
+ */
7651
+ readonly dashed?: boolean;
7652
+ /**
7653
+ * A dash's length: world units (CSS pixels for screen lines).
7654
+ *
7655
+ * @default 3
7656
+ * @range 0..
7657
+ */
7658
+ readonly dashSize?: number;
7659
+ /**
7660
+ * A gap's length.
7661
+ *
7662
+ * @default 1
7663
+ * @range 0..
7664
+ */
7665
+ readonly gapSize?: number;
7666
+ }
7667
+
7668
+
7669
+ /**
7670
+ * A point cloud drawn this frame only (immediate mode), as three.js Points with a PointsMaterial: a square per point facing the camera. Submit it every tick it should show (og.Points keeps a static set).
7671
+ *
7672
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
7673
+ */
7674
+ export interface PointsDesc {
7675
+ /**
7676
+ * The positions: world, or with screen CSS pixels from the top left, y down.
7677
+ *
7678
+ * @default []
7679
+ * @unit m (metres)
7680
+ */
7681
+ readonly points?: readonly Vector3[];
7682
+ /**
7683
+ * Per point linear colours; empty is `color` for all.
7684
+ *
7685
+ * @default []
7686
+ */
7687
+ readonly colors?: readonly Color[];
7688
+ /**
7689
+ * The linear colour.
7690
+ *
7691
+ * @default { r: 1, g: 1, b: 1 }
7692
+ */
7693
+ readonly color?: Color;
7694
+ /**
7695
+ * The alpha.
7696
+ *
7697
+ * @default 1
7698
+ * @range 0..1
7699
+ */
7700
+ readonly opacity?: number;
7701
+ /**
7702
+ * The side of each square: world units with sizeAttenuation, else CSS pixels.
7703
+ *
7704
+ * @default 1
7705
+ * @range 0..
7706
+ */
7707
+ readonly size?: number;
7708
+ /**
7709
+ * Size in world units, smaller with distance, as three.js PointsMaterial.sizeAttenuation; false keeps every point `size` CSS pixels.
7710
+ *
7711
+ * @default true
7712
+ */
7713
+ readonly sizeAttenuation?: boolean;
7714
+ /**
7715
+ * Hidden behind nearer geometry; false draws them over the scene.
7716
+ *
7717
+ * @default true
7718
+ */
7719
+ readonly depthTest?: boolean;
7720
+ /**
7721
+ * Draw in screen space over the finished frame, positions and size in CSS pixels.
7722
+ *
7723
+ * @default false
7724
+ */
7725
+ readonly screen?: boolean;
7726
+ }
7727
+
7728
+
7729
+ /**
7730
+ * Draws a geometry's vertices as lines at the entity's MatrixWorld, every frame (three.js Line, LineSegments or LineLoop over a BufferGeometry): a static set of lines kept as data, a level's outline, a track, a constellation. The vertices are taken in order (the geometry's indices are not read), with its vertex colours times color.
7731
+ *
7732
+ * The value of the `Lines` component (token `og.Lines`).
7733
+ */
7734
+ export interface Lines {
7735
+ /** The vertices (og.render.bufferGeometry: an unindexed one of any count). */
7736
+ geometry: Geometry;
7034
7737
  /** How the vertices join. */
7035
7738
  mode: LineMode;
7036
7739
  /**
@@ -7578,6 +8281,165 @@ export interface BakedScene {
7578
8281
  }
7579
8282
 
7580
8283
 
8284
+ // ── shapes ──────────────────────────────────────────────────────
8285
+ // Two-dimensional outlines in three.js's words: og.Shape and og.Path2 are three.js's Shape and Path, built by the same calls (moveTo, lineTo, quadraticCurveTo, bezierCurveTo, splineThru, arc, absarc, ellipse, absellipse, closePath) and flattened to points by getPoints, so a three.js outline is a paste. og.render.shapeGeometry, extrudeGeometry and sweepGeometry take them; only their points cross to the engine.
8286
+ // They are TypeScript values, not world state: make them in start or a command and let the geometry made from them be what the world keeps. Points come from basic arithmetic (no Math.sin), so they are the same on every host.
8287
+ // A prop of these parts belongs in an asset: an `.ogt` of `type model` names each part's geometry by its og.render call (`extrudeGeometry { shape { absarc 0 0 1 0 6.283185307179586 false } depth 0.2 }`), its shapes as og.Shape's calls one a line with `hole { }` blocks, places parts as mergeGeometries does (`position`, `quaternion`, `scale`, `mirror`, or several `at { }` blocks: one mesh drawn instanced), gives each a `material` and hangs it from a named `pivot` (a node). og cook builds it into the model blob a glTF cooks to (levels of detail, raycast BVH, nodes), refuses it past project.ogt's triangle and vertex budgets, and og dev re-cooks it on an edit; og.load.gltf and a scene's `model` line take it as any model. The og-game skill §18 has a whole example.
8288
+
8289
+ /** A shape's holes, as three.js Shape.holes: an array; push a path to add a hole. */
8290
+ export interface PathList {
8291
+ /** How many holes. */
8292
+ readonly length: number;
8293
+ /**
8294
+ * Add a hole (Array.push).
8295
+ *
8296
+ * @param path The hole's outline, either winding.
8297
+ */
8298
+ push(path: Path2): number;
8299
+ }
8300
+
8301
+ /**
8302
+ * An outline of curves, as three.js Path: each call adds a curve from the current point (moveTo only moves it). Every method but getPoints returns the path, so calls chain.
8303
+ */
8304
+ export interface Path2 {
8305
+ /**
8306
+ * Move the current point without drawing, as three.js Path.moveTo.
8307
+ *
8308
+ * @param x x.
8309
+ * @param y y.
8310
+ */
8311
+ moveTo(x: number, y: number): this;
8312
+ /**
8313
+ * A straight line to (x, y), as three.js Path.lineTo.
8314
+ *
8315
+ * @param x x.
8316
+ * @param y y.
8317
+ */
8318
+ lineTo(x: number, y: number): this;
8319
+ /**
8320
+ * A quadratic Bézier curve through one control point to (x, y), as three.js Path.quadraticCurveTo.
8321
+ *
8322
+ * @param cpX The control point's x.
8323
+ * @param cpY The control point's y.
8324
+ * @param x The end's x.
8325
+ * @param y The end's y.
8326
+ */
8327
+ quadraticCurveTo(cpX: number, cpY: number, x: number, y: number): this;
8328
+ /**
8329
+ * A cubic Bézier curve through two control points to (x, y), as three.js Path.bezierCurveTo.
8330
+ *
8331
+ * @param cp1X The first control point's x.
8332
+ * @param cp1Y The first control point's y.
8333
+ * @param cp2X The second control point's x.
8334
+ * @param cp2Y The second control point's y.
8335
+ * @param x The end's x.
8336
+ * @param y The end's y.
8337
+ */
8338
+ bezierCurveTo(cp1X: number, cp1Y: number, cp2X: number, cp2Y: number, x: number, y: number): this;
8339
+ /**
8340
+ * A Catmull-Rom spline from the current point through the points, as three.js Path.splineThru (a SplineCurve).
8341
+ *
8342
+ * @param points The points it passes through, in order.
8343
+ */
8344
+ splineThru(points: readonly Vector2[]): this;
8345
+ /**
8346
+ * A circular arc centred at (x, y) from the current point, as three.js Path.arc.
8347
+ *
8348
+ * @param x The centre's x, from the current point.
8349
+ * @param y The centre's y, from the current point.
8350
+ * @param radius The radius.
8351
+ * @param startAngle Where it starts, from +x towards +y.
8352
+ * @param endAngle Where it ends.
8353
+ * @param clockwise Go clockwise. Default `false`.
8354
+ */
8355
+ arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, clockwise?: boolean): this;
8356
+ /**
8357
+ * A circular arc centred at (x, y), as three.js Path.absarc: a line joins it to the current point when they differ.
8358
+ *
8359
+ * @param x The centre's x.
8360
+ * @param y The centre's y.
8361
+ * @param radius The radius.
8362
+ * @param startAngle Where it starts, from +x towards +y.
8363
+ * @param endAngle Where it ends.
8364
+ * @param clockwise Go clockwise. Default `false`.
8365
+ */
8366
+ absarc(x: number, y: number, radius: number, startAngle: number, endAngle: number, clockwise?: boolean): this;
8367
+ /**
8368
+ * An elliptic arc centred at (x, y) from the current point, as three.js Path.ellipse.
8369
+ *
8370
+ * @param x The centre's x, from the current point.
8371
+ * @param y The centre's y, from the current point.
8372
+ * @param xRadius The radius along x.
8373
+ * @param yRadius The radius along y.
8374
+ * @param startAngle Where it starts.
8375
+ * @param endAngle Where it ends.
8376
+ * @param clockwise Go clockwise. Default `false`.
8377
+ * @param rotation The ellipse's turn round its centre. Default `0`.
8378
+ */
8379
+ ellipse(x: number, y: number, xRadius: number, yRadius: number, startAngle: number, endAngle: number, clockwise?: boolean, rotation?: number): this;
8380
+ /**
8381
+ * An elliptic arc centred at (x, y), as three.js Path.absellipse.
8382
+ *
8383
+ * @param x The centre's x.
8384
+ * @param y The centre's y.
8385
+ * @param xRadius The radius along x.
8386
+ * @param yRadius The radius along y.
8387
+ * @param startAngle Where it starts.
8388
+ * @param endAngle Where it ends.
8389
+ * @param clockwise Go clockwise. Default `false`.
8390
+ * @param rotation The ellipse's turn round its centre. Default `0`.
8391
+ */
8392
+ absellipse(x: number, y: number, xRadius: number, yRadius: number, startAngle: number, endAngle: number, clockwise?: boolean, rotation?: number): this;
8393
+ /**
8394
+ * Start at the first point and draw lines through the rest, as three.js Path.setFromPoints.
8395
+ *
8396
+ * @param points The points.
8397
+ */
8398
+ setFromPoints(points: readonly Vector2[]): this;
8399
+ /**
8400
+ * A line back to the first point when the outline does not end there, as three.js CurvePath.closePath.
8401
+ */
8402
+ closePath(): this;
8403
+ /**
8404
+ * The outline as points, as three.js CurvePath.getPoints: each curve divided into `divisions` (an ellipse twice as many, a spline as many per point, a line one), repeated points dropped.
8405
+ *
8406
+ * @param divisions Divisions per curve. Default `12`.
8407
+ */
8408
+ getPoints(divisions?: number): readonly Vector2[];
8409
+ }
8410
+
8411
+ /** An outline with holes, as three.js Shape. */
8412
+ export interface Shape extends Path2 {
8413
+ /** The holes: `shape.holes.push(hole)`. */
8414
+ readonly holes: PathList;
8415
+ /**
8416
+ * The outline's and the holes' points, as three.js Shape.extractPoints.
8417
+ *
8418
+ * @param divisions Divisions per curve. Default `12`.
8419
+ */
8420
+ extractPoints(divisions?: number): ShapePoints;
8421
+ }
8422
+
8423
+ /** og.Path2: `new og.Path2(points?)`. */
8424
+ export interface Path2Class {
8425
+ /**
8426
+ * A path, through the points when given (setFromPoints).
8427
+ *
8428
+ * @param points Points to start from.
8429
+ */
8430
+ new(points?: readonly Vector2[] | null): Path2;
8431
+ }
8432
+
8433
+ /** og.Shape: `new og.Shape(points?)`. */
8434
+ export interface ShapeClass {
8435
+ /**
8436
+ * A shape, through the points when given (setFromPoints).
8437
+ *
8438
+ * @param points Points to start from.
8439
+ */
8440
+ new(points?: readonly Vector2[] | null): Shape;
8441
+ }
8442
+
7581
8443
  // ── load ────────────────────────────────────────────────────────
7582
8444
  // Asset loading from cooked output: `og cook` turns assets/ into cooked/ (.ogb blobs and the manifest cooked/.cook.ogt), and the runtime reads only cooked/.
7583
8445
  // Paths are asset ids: the path under assets/ (`models/ship.glb`, `scenes/main.ogt`); an `assets/` prefix is accepted. Every blob is checked against the manifest's type, schema version and cook stamp.
@@ -7645,6 +8507,24 @@ export declare function Asset(value?: Asset, options?: FieldOptions): FieldSpec<
7645
8507
  */
7646
8508
  export declare function Sound(value?: Sound, options?: FieldOptions): FieldSpec<"Sound">;
7647
8509
 
8510
+ /**
8511
+ * A Font handle field (0 is none): a font og.load.font answered, kept for og.render.text or og.ui.configure.
8512
+ *
8513
+ * A `Font` field: stored in a `Uint32Array` with stride 2.
8514
+ * @param value The field's default; omitted, the column's zero value.
8515
+ * @param options Range, unit, label, docs and the tunable flag.
8516
+ */
8517
+ export declare function Font(value?: Font, options?: FieldOptions): FieldSpec<"Font">;
8518
+
8519
+ /**
8520
+ * A Style handle field (0 is none): a UI style og.load.style answered, kept for og.ui.configure.
8521
+ *
8522
+ * A `Style` field: stored in a `Uint32Array` with stride 2.
8523
+ * @param value The field's default; omitted, the column's zero value.
8524
+ * @param options Range, unit, label, docs and the tunable flag.
8525
+ */
8526
+ export declare function Style(value?: Style, options?: FieldOptions): FieldSpec<"Style">;
8527
+
7648
8528
  /**
7649
8529
  * Where a load is.
7650
8530
  * - `"pending"`: Still loading.
@@ -7818,7 +8698,7 @@ export interface Model {
7818
8698
  */
7819
8699
  visible: boolean;
7820
8700
  /**
7821
- * This instance's level of detail bias, multiplied with RenderSettings.lodBias: the cook simplifies every mesh into levels (a model's import settings, `model { lods 1 0.5 0.25 }` by default, the triangle fraction of each level; a glTF with MSFT_lod keeps its own levels), and the renderer draws the level its projected size calls for, with hysteresis so it does not flicker at the boundary. Above 1 keeps detail farther (a hero), below 1 drops it sooner (a crowd); 0 always draws the full mesh. dump_entity shows the level drawn.
8701
+ * This instance's level of detail bias, multiplied with RenderSettings.lodBias: the cook simplifies every mesh into levels (a model's import settings, `model { lods 1 0.5 0.25 }` by default, the triangle fraction of each level; a glTF with MSFT_lod keeps its own levels) and measures each level's error against the full mesh, and the renderer draws the coarsest level whose error covers less than a pixel at the model's distance, with hysteresis so it does not flicker at the boundary. Above 1 keeps detail farther (a hero), below 1 drops it sooner (a crowd); 0 always draws the full mesh. dump_entity shows the level drawn.
7822
8702
  *
7823
8703
  * @default 1
7824
8704
  * @range 0..16
@@ -8198,7 +9078,7 @@ export interface Physics {
8198
9078
  }
8199
9079
 
8200
9080
  /**
8201
- * Two solid colliders started touching during the tick.
9081
+ * Two solid colliders started touching during the tick. Read in the tick after, when og.Velocity already holds the solver's answer (the bodies parting): how hard they met is `impulse` and `relativeVelocity`, taken in the step itself.
8202
9082
  *
8203
9083
  * The payload of the `CollisionStarted` event (token `og.CollisionStarted`).
8204
9084
  */
@@ -8207,10 +9087,27 @@ export interface CollisionStarted {
8207
9087
  readonly a: Entity;
8208
9088
  /** The entity with the higher id. */
8209
9089
  readonly b: Entity;
8210
- /** The deepest contact point in world space (z is 0 in 2D). */
9090
+ /**
9091
+ * The deepest contact point in world space (z is 0 in 2D).
9092
+ *
9093
+ * @unit m (metres)
9094
+ */
8211
9095
  readonly point: Vector3;
8212
9096
  /** The contact normal, from a towards b. */
8213
9097
  readonly normal: Vector3;
9098
+ /**
9099
+ * The normal impulse the solver gave the pair in the step that made the contact (every substep, every contact point), in newton-seconds: b took `impulse` along `normal`, a the same against it. Its momentum answer to the hit, at least 0; heavier and faster hits give more.
9100
+ *
9101
+ * @range 0..
9102
+ * @unit newtonSecond (newton-seconds: an impulse, the momentum that changes a kilogram's velocity by one metre per second)
9103
+ */
9104
+ readonly impulse: number;
9105
+ /**
9106
+ * a's velocity relative to b at `point` as that step began, before the solver answered: each body's linear velocity plus its angular velocity crossed with the point's offset from its centre of mass (a static collider is still; z is 0 in 2D). Along `normal` it is the closing speed, positive while they approach: max(0, relativeVelocity · normal) is how hard they hit, in m/s.
9107
+ *
9108
+ * @unit mps (metres per second)
9109
+ */
9110
+ readonly relativeVelocity: Vector3;
8214
9111
  }
8215
9112
 
8216
9113
  /**
@@ -11039,334 +11936,692 @@ export type IkSpace = "world" | "model";
11039
11936
  export declare function IkSpace(value?: IkSpace, options?: FieldOptions): FieldSpec<"IkSpace">;
11040
11937
 
11041
11938
  /**
11042
- * A posed skeleton: the entity is drawn skinned by the joint palette og.anim writes each tick. The pose itself (every node's local transform) is world state kept by the `og.anim` state block.
11939
+ * A posed skeleton: the entity is drawn skinned by the joint palette og.anim writes each tick. The pose itself (every node's local transform) is world state kept by the `og.anim` state block.
11940
+ *
11941
+ * The value of the `Skeleton` component (token `og.Skeleton`).
11942
+ */
11943
+ export interface Skeleton {
11944
+ /** The skeleton asset (og.load.animation's `skeleton`); 0 is none. */
11945
+ asset: SkeletonAsset;
11946
+ /**
11947
+ * Which of the asset's skins the joint palette is for (glTF skin index).
11948
+ *
11949
+ * @range 0..
11950
+ */
11951
+ skin: number;
11952
+ /**
11953
+ * Root motion extraction: off (animate in place), planar (xz travel and yaw move og.Transform) or full.
11954
+ */
11955
+ rootMotion: RootMotion;
11956
+ /**
11957
+ * The joint whose motion is extracted (an index into the skin's joints; 0 is its first joint, usually the hips).
11958
+ *
11959
+ * @range 0..
11960
+ */
11961
+ rootJoint: number;
11962
+ /**
11963
+ * Written: the number of joints in the palette (0 until the first tick).
11964
+ *
11965
+ * @readonly written by the engine
11966
+ */
11967
+ readonly jointCount: number;
11968
+ }
11969
+
11970
+ /**
11971
+ * Plays one clip on a skeleton. Alone it poses the skeleton from its rest pose; with an og.AnimationGraph it plays over the graph's result with `weight`. Changing `clip` cross-fades from the previous one over `fade`; a clip change starts the new clip at 0 (or at `time` if the game wrote it in the same tick).
11972
+ *
11973
+ * The value of the `AnimationPlayer` component (token `og.AnimationPlayer`).
11974
+ */
11975
+ export interface AnimationPlayer {
11976
+ /** The clip asset; 0 plays nothing. */
11977
+ clip: ClipAsset;
11978
+ /**
11979
+ * The playback position; written every tick, set it to seek (no markers fire across a seek).
11980
+ *
11981
+ * @range 0..
11982
+ * @unit s (seconds of simulation time)
11983
+ */
11984
+ time: number;
11985
+ /**
11986
+ * Playback rate (1 = as authored, negative plays backwards).
11987
+ *
11988
+ * @default 1
11989
+ * @range -10..10
11990
+ * @tunable
11991
+ */
11992
+ speed: number;
11993
+ /**
11994
+ * Wrap at the end of the clip; otherwise hold the last frame and set `finished`.
11995
+ *
11996
+ * @default true
11997
+ */
11998
+ loop: boolean;
11999
+ /**
12000
+ * How much of the pose this player decides (0 = none, 1 = all).
12001
+ *
12002
+ * @default 1
12003
+ * @range 0..1
12004
+ * @tunable
12005
+ */
12006
+ weight: number;
12007
+ /**
12008
+ * Cross-fade duration when `clip` changes.
12009
+ *
12010
+ * @default 0.2
12011
+ * @range 0..10
12012
+ * @unit s (seconds of simulation time)
12013
+ * @tunable
12014
+ */
12015
+ fade: number;
12016
+ /**
12017
+ * Stepped playback: each pose is held for 1/stepFps seconds, the clip sampled at its time floored to that step (12 is stop motion "on twos", 8 on threes), the same on every tick rate; 0 samples every tick. `time`, markers and root motion stay continuous; a one-shot still ends on its last frame.
12018
+ *
12019
+ * @range 0..60
12020
+ * @tunable
12021
+ */
12022
+ stepFps: number;
12023
+ /**
12024
+ * Written: a non-looping clip reached its end.
12025
+ *
12026
+ * @readonly written by the engine
12027
+ */
12028
+ readonly finished: boolean;
12029
+ }
12030
+
12031
+ /**
12032
+ * Runs a blend-tree graph (og.anim.graph) on a skeleton: its layers' state machines pick motions by the parameters p0...p7, which the graph names in `param` order (`param speed` is p0, the next `param` is p1, ...).
12033
+ *
12034
+ * The value of the `AnimationGraph` component (token `og.AnimationGraph`).
12035
+ */
12036
+ export interface AnimationGraph {
12037
+ /** The graph asset; 0 is none. */
12038
+ asset: GraphAsset;
12039
+ /**
12040
+ * How much of the pose the graph decides over the rest pose.
12041
+ *
12042
+ * @default 1
12043
+ * @range 0..1
12044
+ * @tunable
12045
+ */
12046
+ weight: number;
12047
+ /**
12048
+ * A playback-rate multiplier for every layer.
12049
+ *
12050
+ * @default 1
12051
+ * @range 0..10
12052
+ * @tunable
12053
+ */
12054
+ speed: number;
12055
+ /**
12056
+ * Parameter 0 (the graph's first `param`).
12057
+ *
12058
+ * @tunable
12059
+ */
12060
+ p0: number;
12061
+ /**
12062
+ * Parameter 1.
12063
+ *
12064
+ * @tunable
12065
+ */
12066
+ p1: number;
12067
+ /**
12068
+ * Parameter 2.
12069
+ *
12070
+ * @tunable
12071
+ */
12072
+ p2: number;
12073
+ /**
12074
+ * Parameter 3.
12075
+ *
12076
+ * @tunable
12077
+ */
12078
+ p3: number;
12079
+ /**
12080
+ * Parameter 4.
12081
+ *
12082
+ * @tunable
12083
+ */
12084
+ p4: number;
12085
+ /**
12086
+ * Parameter 5.
12087
+ *
12088
+ * @tunable
12089
+ */
12090
+ p5: number;
12091
+ /**
12092
+ * Parameter 6.
12093
+ *
12094
+ * @tunable
12095
+ */
12096
+ p6: number;
12097
+ /**
12098
+ * Parameter 7.
12099
+ *
12100
+ * @tunable
12101
+ */
12102
+ p7: number;
12103
+ /**
12104
+ * Written: the base layer's current state (its index in the graph file).
12105
+ *
12106
+ * @readonly written by the engine
12107
+ */
12108
+ readonly state: number;
12109
+ /**
12110
+ * Written: seconds since the base layer entered `state`.
12111
+ *
12112
+ * @unit s (seconds of simulation time)
12113
+ * @readonly written by the engine
12114
+ */
12115
+ readonly stateTime: number;
12116
+ }
12117
+
12118
+ /**
12119
+ * Morph-target weights of the skeleton entity's mesh, in the order of the glTF mesh's targets. With `source` clips the playing clips' weight channels write them; with `component` game code does.
12120
+ *
12121
+ * The value of the `Blendshapes` component (token `og.Blendshapes`).
12122
+ */
12123
+ export interface Blendshapes {
12124
+ /**
12125
+ * Who decides the weights: component (game code writes w0...w7) or clips (the animation writes them).
12126
+ */
12127
+ source: BlendshapeSource;
12128
+ /**
12129
+ * The glTF mesh index whose targets the weights drive (0 is the first mesh).
12130
+ *
12131
+ * @range 0..
12132
+ */
12133
+ mesh: number;
12134
+ /**
12135
+ * Weight of target 0.
12136
+ *
12137
+ * @range -1..2
12138
+ * @tunable
12139
+ */
12140
+ w0: number;
12141
+ /**
12142
+ * Weight of target 1.
12143
+ *
12144
+ * @range -1..2
12145
+ * @tunable
12146
+ */
12147
+ w1: number;
12148
+ /**
12149
+ * Weight of target 2.
12150
+ *
12151
+ * @range -1..2
12152
+ * @tunable
12153
+ */
12154
+ w2: number;
12155
+ /**
12156
+ * Weight of target 3.
12157
+ *
12158
+ * @range -1..2
12159
+ * @tunable
12160
+ */
12161
+ w3: number;
12162
+ /**
12163
+ * Weight of target 4.
12164
+ *
12165
+ * @range -1..2
12166
+ * @tunable
12167
+ */
12168
+ w4: number;
12169
+ /**
12170
+ * Weight of target 5.
12171
+ *
12172
+ * @range -1..2
12173
+ * @tunable
12174
+ */
12175
+ w5: number;
12176
+ /**
12177
+ * Weight of target 6.
12178
+ *
12179
+ * @range -1..2
12180
+ * @tunable
12181
+ */
12182
+ w6: number;
12183
+ /**
12184
+ * Weight of target 7.
12185
+ *
12186
+ * @range -1..2
12187
+ * @tunable
12188
+ */
12189
+ w7: number;
12190
+ }
12191
+
12192
+ /**
12193
+ * An inverse-kinematics constraint on a skeleton, applied after its clips and graph: the chain of `bones` bones ending at joint `tip` turns so the tip reaches `target`. Put it on its own entity (a skeleton can have many chains); chains apply in query order.
11043
12194
  *
11044
- * The value of the `Skeleton` component (token `og.Skeleton`).
12195
+ * The value of the `IkChain` component (token `og.IkChain`).
11045
12196
  */
11046
- export interface Skeleton {
11047
- /** The skeleton asset (og.load.animation's `skeleton`); 0 is none. */
11048
- asset: SkeletonAsset;
12197
+ export interface IkChain {
12198
+ /** The entity with the og.Skeleton this chain bends. */
12199
+ skeleton: Entity;
11049
12200
  /**
11050
- * Which of the asset's skins the joint palette is for (glTF skin index).
12201
+ * The end joint (an index into the skin's joints): the foot or the hand.
11051
12202
  *
11052
12203
  * @range 0..
11053
12204
  */
11054
- skin: number;
12205
+ tip: number;
11055
12206
  /**
11056
- * Root motion extraction: off (animate in place), planar (xz travel and yaw move og.Transform) or full.
12207
+ * How many bones above the tip turn (two-bone always uses 2).
12208
+ *
12209
+ * @default 2
12210
+ * @range 1..32
11057
12211
  */
11058
- rootMotion: RootMotion;
12212
+ bones: number;
12213
+ /** twoBone (analytic, with a pole) or fabrik (iterative, any length). */
12214
+ solver: IkSolver;
11059
12215
  /**
11060
- * The joint whose motion is extracted (an index into the skin's joints; 0 is its first joint, usually the hips).
12216
+ * Where the tip should be, in `space`: for `world`, the frame of the skeleton entity's og.Transform (its parent's frame when it has a parent, not true world).
12217
+ *
12218
+ * @unit m (metres)
12219
+ */
12220
+ target: Vector3;
12221
+ /**
12222
+ * A point the middle joint bends towards (two-bone); the zero vector keeps the animated bend.
12223
+ *
12224
+ * @unit m (metres)
12225
+ */
12226
+ pole: Vector3;
12227
+ /**
12228
+ * What `target` and `pole` are relative to: world (the frame the skeleton entity's og.Transform is in, so its parent's frame for a child entity, not true world) or model.
12229
+ */
12230
+ space: IkSpace;
12231
+ /**
12232
+ * How much of the solved rotation is applied (0 = the animated pose, 1 = fully solved).
12233
+ *
12234
+ * @default 1
12235
+ * @range 0..1
12236
+ * @tunable
12237
+ */
12238
+ weight: number;
12239
+ /**
12240
+ * FABRIK iterations at most.
12241
+ *
12242
+ * @default 10
12243
+ * @range 1..64
12244
+ */
12245
+ iterations: number;
12246
+ /**
12247
+ * The tip distance (model units) at which the target counts as reached.
11061
12248
  *
12249
+ * @default 0.001
11062
12250
  * @range 0..
12251
+ * @unit m (metres)
11063
12252
  */
11064
- rootJoint: number;
12253
+ tolerance: number;
11065
12254
  /**
11066
- * Written: the number of joints in the palette (0 until the first tick).
12255
+ * Written: the tip is within `tolerance` of the target after solving.
11067
12256
  *
11068
12257
  * @readonly written by the engine
11069
12258
  */
11070
- readonly jointCount: number;
12259
+ readonly reached: boolean;
12260
+ /**
12261
+ * Written: the tip's distance from the target after solving, in model units.
12262
+ *
12263
+ * @unit m (metres)
12264
+ * @readonly written by the engine
12265
+ */
12266
+ readonly error: number;
11071
12267
  }
11072
12268
 
11073
12269
  /**
11074
- * Plays one clip on a skeleton. Alone it poses the skeleton from its rest pose; with an og.AnimationGraph it plays over the graph's result with `weight`. Changing `clip` cross-fades from the previous one over `fade`; a clip change starts the new clip at 0 (or at `time` if the game wrote it in the same tick).
12270
+ * An aim constraint on a skeleton, applied after its clips, graph and IK chains: `joint` turns so its `axis` points at `target` and its `upAxis` leans towards `up` (three.js Object3D.lookAt: +Z at the target, +Y up). The direction is held within maxYaw and maxPitch of the animated forward; with `bones` above 1 the joint's parents share the turn. Put it on its own entity (a head, the eyes, a turret's barrel); constraints apply in query order, and og.JointLimit clamps the joints it turns.
11075
12271
  *
11076
- * The value of the `AnimationPlayer` component (token `og.AnimationPlayer`).
12272
+ * The value of the `LookAt` component (token `og.LookAt`).
11077
12273
  */
11078
- export interface AnimationPlayer {
11079
- /** The clip asset; 0 plays nothing. */
11080
- clip: ClipAsset;
12274
+ export interface LookAt {
12275
+ /** The entity with the og.Skeleton this constraint turns. */
12276
+ skeleton: Entity;
11081
12277
  /**
11082
- * The playback position; written every tick, set it to seek (no markers fire across a seek).
12278
+ * The joint that aims (an index into the skin's joints): the head, an eye.
11083
12279
  *
11084
12280
  * @range 0..
11085
- * @unit s (seconds of simulation time)
11086
12281
  */
11087
- time: number;
12282
+ joint: number;
11088
12283
  /**
11089
- * Playback rate (1 = as authored, negative plays backwards).
12284
+ * How many joints share the turn: `joint` and its parents (3 spreads a look over neck, chest and spine), each parent taking an even share and `joint` the rest.
11090
12285
  *
11091
12286
  * @default 1
11092
- * @range -10..10
11093
- * @tunable
12287
+ * @range 1..8
11094
12288
  */
11095
- speed: number;
12289
+ bones: number;
11096
12290
  /**
11097
- * Wrap at the end of the clip; otherwise hold the last frame and set `finished`.
12291
+ * The point to look at, in `space`.
11098
12292
  *
11099
- * @default true
12293
+ * @unit m (metres)
11100
12294
  */
11101
- loop: boolean;
12295
+ target: Vector3;
11102
12296
  /**
11103
- * How much of the pose this player decides (0 = none, 1 = all).
12297
+ * What `target` and `up` are relative to: world (the frame the skeleton entity's og.Transform is in) or model.
12298
+ */
12299
+ space: IkSpace;
12300
+ /**
12301
+ * The joint's forward, in its own frame: the axis turned onto the target.
11104
12302
  *
11105
- * @default 1
11106
- * @range 0..1
12303
+ * @default { x: 0, y: 0, z: 1 }
12304
+ */
12305
+ axis: Vector3;
12306
+ /**
12307
+ * The joint's up, in its own frame: yaw turns about it, pitch towards it, and it rolls towards `up`.
12308
+ *
12309
+ * @default { x: 0, y: 1, z: 0 }
12310
+ */
12311
+ upAxis: Vector3;
12312
+ /**
12313
+ * The up hint, a direction in `space` the joint's `upAxis` leans to (three.js Object3D.up); the zero vector keeps the animated roll.
12314
+ *
12315
+ * @default { x: 0, y: 1, z: 0 }
12316
+ */
12317
+ up: Vector3;
12318
+ /**
12319
+ * The largest turn about `upAxis`, left or right of the animated forward.
12320
+ *
12321
+ * @default 3.1416
12322
+ * @range 0..3.1416
12323
+ * @unit rad (radians)
11107
12324
  * @tunable
11108
12325
  */
11109
- weight: number;
12326
+ maxYaw: number;
11110
12327
  /**
11111
- * Cross-fade duration when `clip` changes.
12328
+ * The largest turn towards or away from `upAxis`, from the animated forward.
11112
12329
  *
11113
- * @default 0.2
11114
- * @range 0..10
11115
- * @unit s (seconds of simulation time)
12330
+ * @default 1.5708
12331
+ * @range 0..1.5708
12332
+ * @unit rad (radians)
11116
12333
  * @tunable
11117
12334
  */
11118
- fade: number;
12335
+ maxPitch: number;
11119
12336
  /**
11120
- * Stepped playback: each pose is held for 1/stepFps seconds, the clip sampled at its time floored to that step (12 is stop motion "on twos", 8 on threes), the same on every tick rate; 0 samples every tick. `time`, markers and root motion stay continuous; a one-shot still ends on its last frame.
12337
+ * How much of the turn is applied (0 = the animated pose, 1 = aimed).
11121
12338
  *
11122
- * @range 0..60
12339
+ * @default 1
12340
+ * @range 0..1
11123
12341
  * @tunable
11124
12342
  */
11125
- stepFps: number;
12343
+ weight: number;
11126
12344
  /**
11127
- * Written: a non-looping clip reached its end.
12345
+ * Written: the target lay outside maxYaw or maxPitch, so the joint aims at the nearest direction inside them.
11128
12346
  *
11129
12347
  * @readonly written by the engine
11130
12348
  */
11131
- readonly finished: boolean;
12349
+ readonly clamped: boolean;
11132
12350
  }
11133
12351
 
11134
12352
  /**
11135
- * Runs a blend-tree graph (og.anim.graph) on a skeleton: its layers' state machines pick motions by the parameters p0...p7, which the graph names in `param` order (`param speed` is p0, the next `param` is p1, ...).
12353
+ * How far a joint may turn from its rest rotation when og.anim's solvers (og.IkChain, og.LookAt, og.FootLock) turn it: a swing of `axis` within a cone and a twist about it within a range. A hinge (a knee, an elbow) is `axis` along the hinge, `swing` 0 (or a little play) and the bend range as twistMin...twistMax. Put it on its own entity, one per joint; the animated pose itself is never clamped.
11136
12354
  *
11137
- * The value of the `AnimationGraph` component (token `og.AnimationGraph`).
12355
+ * The value of the `JointLimit` component (token `og.JointLimit`).
11138
12356
  */
11139
- export interface AnimationGraph {
11140
- /** The graph asset; 0 is none. */
11141
- asset: GraphAsset;
11142
- /**
11143
- * How much of the pose the graph decides over the rest pose.
11144
- *
11145
- * @default 1
11146
- * @range 0..1
11147
- * @tunable
11148
- */
11149
- weight: number;
12357
+ export interface JointLimit {
12358
+ /** The entity with the og.Skeleton whose joint this limits. */
12359
+ skeleton: Entity;
11150
12360
  /**
11151
- * A playback-rate multiplier for every layer.
12361
+ * The limited joint (an index into the skin's joints).
11152
12362
  *
11153
- * @default 1
11154
- * @range 0..10
11155
- * @tunable
12363
+ * @range 0..
11156
12364
  */
11157
- speed: number;
12365
+ joint: number;
11158
12366
  /**
11159
- * Parameter 0 (the graph's first `param`).
12367
+ * The twist axis in the joint's rest frame: along the bone for a ball joint, along the hinge for a hinge.
11160
12368
  *
11161
- * @tunable
12369
+ * @default { x: 0, y: 1, z: 0 }
11162
12370
  */
11163
- p0: number;
12371
+ axis: Vector3;
11164
12372
  /**
11165
- * Parameter 1.
12373
+ * The cone half-angle the axis may swing away from its rest direction (0 locks it: a hinge; pi is free).
11166
12374
  *
12375
+ * @default 3.1416
12376
+ * @range 0..3.1416
12377
+ * @unit rad (radians)
11167
12378
  * @tunable
11168
12379
  */
11169
- p1: number;
12380
+ swing: number;
11170
12381
  /**
11171
- * Parameter 2.
12382
+ * The least twist about `axis` from rest (a hinge's bend one way).
11172
12383
  *
12384
+ * @default -3.1416
12385
+ * @range -3.1416..3.1416
12386
+ * @unit rad (radians)
11173
12387
  * @tunable
11174
12388
  */
11175
- p2: number;
12389
+ twistMin: number;
11176
12390
  /**
11177
- * Parameter 3.
12391
+ * The most twist about `axis` from rest (a hinge's bend the other way).
11178
12392
  *
12393
+ * @default 3.1416
12394
+ * @range -3.1416..3.1416
12395
+ * @unit rad (radians)
11179
12396
  * @tunable
11180
12397
  */
11181
- p3: number;
12398
+ twistMax: number;
12399
+ }
12400
+
12401
+ /**
12402
+ * Foot locking: while the playing clips plant `foot` (within 5 mm of its lowest in each clip, the notion retargeting uses, weighed across blends and cross-fades: planted when the planting clips hold at least half the pose), the foot stays where it touched the ground, through clip blends and root motion, its leg bent by two-bone IK and the foot keeping its animated orientation; when the clips lift it, the foot rejoins its animation over `release`. Put it on its own entity, one per foot; locks apply after root motion and before og.IkChain, in query order, and og.JointLimit clamps the leg. The lock is world state (the `og.anim` state block).
12403
+ *
12404
+ * The value of the `FootLock` component (token `og.FootLock`).
12405
+ */
12406
+ export interface FootLock {
12407
+ /** The entity with the og.Skeleton whose foot this holds. */
12408
+ skeleton: Entity;
11182
12409
  /**
11183
- * Parameter 4.
12410
+ * The foot joint (an index into the skin's joints); the two bones above it are the leg that bends.
11184
12411
  *
11185
- * @tunable
12412
+ * @range 0..
11186
12413
  */
11187
- p4: number;
12414
+ foot: number;
11188
12415
  /**
11189
- * Parameter 5.
12416
+ * How much of the lock is applied (0 = the animated foot, 1 = held).
11190
12417
  *
12418
+ * @default 1
12419
+ * @range 0..1
11191
12420
  * @tunable
11192
12421
  */
11193
- p5: number;
12422
+ weight: number;
11194
12423
  /**
11195
- * Parameter 6.
12424
+ * Seconds the foot takes to rejoin its animation once lifted (0: at once).
11196
12425
  *
12426
+ * @default 0.15
12427
+ * @range 0..2
12428
+ * @unit s (seconds of simulation time)
11197
12429
  * @tunable
11198
12430
  */
11199
- p6: number;
12431
+ release: number;
11200
12432
  /**
11201
- * Parameter 7.
12433
+ * Farther than this from where the animation puts the foot, the lock lets go (a leg cannot stretch).
11202
12434
  *
12435
+ * @default 0.5
12436
+ * @range 0..
12437
+ * @unit m (metres)
11203
12438
  * @tunable
11204
12439
  */
11205
- p7: number;
12440
+ maxDistance: number;
11206
12441
  /**
11207
- * Written: the base layer's current state (its index in the graph file).
12442
+ * Written: the playing clips plant the foot this tick.
11208
12443
  *
11209
12444
  * @readonly written by the engine
11210
12445
  */
11211
- readonly state: number;
12446
+ readonly planted: boolean;
11212
12447
  /**
11213
- * Written: seconds since the base layer entered `state`.
12448
+ * Written: the foot is held at its lock this tick.
11214
12449
  *
11215
- * @unit s (seconds of simulation time)
11216
12450
  * @readonly written by the engine
11217
12451
  */
11218
- readonly stateTime: number;
12452
+ readonly locked: boolean;
11219
12453
  }
11220
12454
 
11221
12455
  /**
11222
- * Morph-target weights of the skeleton entity's mesh, in the order of the glTF mesh's targets. With `source` clips the playing clips' weight channels write them; with `component` game code does.
12456
+ * Where a spring bone's tails move.
12457
+ * - `"world"`: The frame the skeleton entity's og.Transform is written in: the chain lags behind the entity's motion (walking, root motion, a jump).
12458
+ * - `"model"`: The skeleton's model space: only the animation moves the chain (a teleport or a vehicle carrying the entity does not).
12459
+ */
12460
+ export type SpringSpace = "world" | "model";
12461
+
12462
+ /**
12463
+ * A SpringSpace field: the variant's index.
11223
12464
  *
11224
- * The value of the `Blendshapes` component (token `og.Blendshapes`).
12465
+ * A `SpringSpace` field: stored in a `Uint32Array` with stride 1.
12466
+ * @param value The field's default; omitted, the column's zero value.
12467
+ * @param options Range, unit, label, docs and the tunable flag.
11225
12468
  */
11226
- export interface Blendshapes {
12469
+ export declare function SpringSpace(value?: SpringSpace, options?: FieldOptions): FieldSpec<"SpringSpace">;
12470
+
12471
+ /**
12472
+ * A spring (jiggle) bone chain, three-vrm's VRMSpringBone: `joint` and its `bones` - 1 parents swing after their parents' motion. Each joint's tail (the next joint of the chain; for the last joint its first child, or its parent bone continued at the same length) is a point pulled towards where the animated pose puts it by a damped spring (`frequency`, `damping`), under `gravity`, held at the bone's length, and the joint turns to point at it. Applied after og.IkChain and og.LookAt, top joint first; put it on its own entity (a tail, an ear, a strand of hair, a single jiggling node), one per chain. Deterministic under the fixed tick; the tails' positions and velocities are world state (the `og.anim` state block), so a restore continues a swing exactly. A changed chain (another skeleton, length or space) restarts at the animated pose.
12473
+ *
12474
+ * The value of the `SpringBone` component (token `og.SpringBone`).
12475
+ */
12476
+ export interface SpringBone {
12477
+ /** The entity with the og.Skeleton whose joints this swings. */
12478
+ skeleton: Entity;
11227
12479
  /**
11228
- * Who decides the weights: component (game code writes w0...w7) or clips (the animation writes them).
12480
+ * The chain's last joint (an index into the skin's joints): the tip of a tail, an ear.
12481
+ *
12482
+ * @range 0..
11229
12483
  */
11230
- source: BlendshapeSource;
12484
+ joint: number;
11231
12485
  /**
11232
- * The glTF mesh index whose targets the weights drive (0 is the first mesh).
12486
+ * How many joints swing: `joint` and its parents (1 is the joint alone).
11233
12487
  *
11234
- * @range 0..
12488
+ * @default 1
12489
+ * @range 1..16
11235
12490
  */
11236
- mesh: number;
12491
+ bones: number;
11237
12492
  /**
11238
- * Weight of target 0.
12493
+ * How fast a tail springs back to its animated place: the spring's natural frequency (0: no spring, it only hangs and swings).
11239
12494
  *
11240
- * @range -1..2
12495
+ * @default 3
12496
+ * @range 0..30
12497
+ * @unit hz (ticks or cycles per second)
11241
12498
  * @tunable
11242
12499
  */
11243
- w0: number;
12500
+ frequency: number;
11244
12501
  /**
11245
- * Weight of target 1.
12502
+ * The damping ratio: 0 swings on, 1 settles without overshooting (critical damping).
11246
12503
  *
11247
- * @range -1..2
12504
+ * @default 0.3
12505
+ * @range 0..2
11248
12506
  * @tunable
11249
12507
  */
11250
- w1: number;
12508
+ damping: number;
11251
12509
  /**
11252
- * Weight of target 2.
12510
+ * The last joint's frequency as a multiple of `frequency`, the joints between in proportion along the chain (1: every joint alike; 0.25: the tip springs back four times slower than the top, a soft strand on a stiff root).
11253
12511
  *
11254
- * @range -1..2
12512
+ * @default 1
12513
+ * @range 0..4
11255
12514
  * @tunable
11256
12515
  */
11257
- w2: number;
12516
+ tipFrequency: number;
11258
12517
  /**
11259
- * Weight of target 3.
12518
+ * The last joint's damping ratio as a multiple of `damping`, the joints between in proportion along the chain (1: every joint alike).
11260
12519
  *
11261
- * @range -1..2
12520
+ * @default 1
12521
+ * @range 0..4
11262
12522
  * @tunable
11263
12523
  */
11264
- w3: number;
12524
+ tipDamping: number;
11265
12525
  /**
11266
- * Weight of target 4.
12526
+ * An acceleration on every tail, in `space` (three-vrm's gravityDir times gravityPower): (0, -9.8, 0) makes a chain droop.
11267
12527
  *
11268
- * @range -1..2
12528
+ * @unit mps2 (metres per second squared)
12529
+ */
12530
+ gravity: Vector3;
12531
+ /**
12532
+ * Where the tails move: world (the frame the skeleton entity's og.Transform is in, so the chain lags behind the entity's motion) or model (only the animation moves it).
12533
+ */
12534
+ space: SpringSpace;
12535
+ /**
12536
+ * How much of the swing is applied (0 = the animated pose, 1 = the spring's).
12537
+ *
12538
+ * @default 1
12539
+ * @range 0..1
11269
12540
  * @tunable
11270
12541
  */
11271
- w4: number;
12542
+ weight: number;
11272
12543
  /**
11273
- * Weight of target 5.
12544
+ * The tails' radius against og.SpringCollider (three-vrm's hitRadius): a tail stays this far outside every collider it meets (0: a point).
11274
12545
  *
11275
- * @range -1..2
12546
+ * @range 0..
12547
+ * @unit m (metres)
11276
12548
  * @tunable
11277
12549
  */
11278
- w5: number;
12550
+ radius: number;
11279
12551
  /**
11280
- * Weight of target 6.
12552
+ * The og.SpringCollider layers the tails are pushed out of, as bits: a collider on the same skeleton counts when its `layers` meet these.
11281
12553
  *
11282
- * @range -1..2
11283
- * @tunable
12554
+ * @default 4294967295
11284
12555
  */
11285
- w6: number;
12556
+ colliders: number;
11286
12557
  /**
11287
- * Weight of target 7.
12558
+ * Written: the farthest a tail is from its animated place this tick.
11288
12559
  *
11289
- * @range -1..2
11290
- * @tunable
12560
+ * @unit m (metres)
12561
+ * @readonly written by the engine
11291
12562
  */
11292
- w7: number;
12563
+ readonly lag: number;
11293
12564
  }
11294
12565
 
11295
12566
  /**
11296
- * An inverse-kinematics constraint on a skeleton, applied after its clips and graph: the chain of `bones` bones ending at joint `tip` turns so the tip reaches `target`. Put it on its own entity (a skeleton can have many chains); chains apply in query order.
12567
+ * The shape of a spring collider.
12568
+ * - `"sphere"`: A ball of `radius` about `offset`.
12569
+ * - `"capsule"`: A capsule of `radius` about the segment from `offset` to `tail`.
12570
+ */
12571
+ export type SpringColliderShape = "sphere" | "capsule";
12572
+
12573
+ /**
12574
+ * A SpringColliderShape field: the variant's index.
11297
12575
  *
11298
- * The value of the `IkChain` component (token `og.IkChain`).
12576
+ * A `SpringColliderShape` field: stored in a `Uint32Array` with stride 1.
12577
+ * @param value The field's default; omitted, the column's zero value.
12578
+ * @param options Range, unit, label, docs and the tunable flag.
11299
12579
  */
11300
- export interface IkChain {
11301
- /** The entity with the og.Skeleton this chain bends. */
12580
+ export declare function SpringColliderShape(value?: SpringColliderShape, options?: FieldOptions): FieldSpec<"SpringColliderShape">;
12581
+
12582
+ /**
12583
+ * A collider spring bones are kept out of, three-vrm's VRMSpringBoneCollider: a sphere or a capsule riding on a joint of a skeleton (a head, a chest, an upper arm), so hair, ears and tails do not swing through the body. Each tick, after a tail of an og.SpringBone of the same skeleton has stepped and before its joint turns, the tail is pushed out of every collider whose `layers` meet the spring's `colliders` (in query order) to `radius` plus the spring's `radius`, keeping its bone's length. Put it on its own entity, one per shape; colliders follow the pose as it is when a chain is swung, so one on a joint an earlier chain swung follows that swing.
12584
+ *
12585
+ * The value of the `SpringCollider` component (token `og.SpringCollider`).
12586
+ */
12587
+ export interface SpringCollider {
12588
+ /** The entity with the og.Skeleton whose spring bones this keeps out. */
11302
12589
  skeleton: Entity;
11303
12590
  /**
11304
- * The end joint (an index into the skin's joints): the foot or the hand.
12591
+ * The joint the collider rides on (an index into the skin's joints).
11305
12592
  *
11306
12593
  * @range 0..
11307
12594
  */
11308
- tip: number;
11309
- /**
11310
- * How many bones above the tip turn (two-bone always uses 2).
11311
- *
11312
- * @default 2
11313
- * @range 1..32
11314
- */
11315
- bones: number;
11316
- /** twoBone (analytic, with a pole) or fabrik (iterative, any length). */
11317
- solver: IkSolver;
12595
+ joint: number;
12596
+ /** A sphere about `offset`, or a capsule from `offset` to `tail`. */
12597
+ shape: SpringColliderShape;
11318
12598
  /**
11319
- * Where the tip should be, in `space`: for `world`, the frame of the skeleton entity's og.Transform (its parent's frame when it has a parent, not true world).
12599
+ * The sphere's centre, or the capsule's first end, in the joint's frame.
11320
12600
  *
11321
12601
  * @unit m (metres)
11322
12602
  */
11323
- target: Vector3;
12603
+ offset: Vector3;
11324
12604
  /**
11325
- * A point the middle joint bends towards (two-bone); the zero vector keeps the animated bend.
12605
+ * The capsule's other end, in the joint's frame (a sphere ignores it).
11326
12606
  *
11327
12607
  * @unit m (metres)
11328
12608
  */
11329
- pole: Vector3;
11330
- /**
11331
- * What `target` and `pole` are relative to: world (the frame the skeleton entity's og.Transform is in, so its parent's frame for a child entity, not true world) or model.
11332
- */
11333
- space: IkSpace;
11334
- /**
11335
- * How much of the solved rotation is applied (0 = the animated pose, 1 = fully solved).
11336
- *
11337
- * @default 1
11338
- * @range 0..1
11339
- * @tunable
11340
- */
11341
- weight: number;
11342
- /**
11343
- * FABRIK iterations at most.
11344
- *
11345
- * @default 10
11346
- * @range 1..64
11347
- */
11348
- iterations: number;
12609
+ tail: Vector3;
11349
12610
  /**
11350
- * The tip distance (model units) at which the target counts as reached.
12611
+ * The radius, in metres of the skeleton's model space (the joint's own scale does not apply).
11351
12612
  *
11352
- * @default 0.001
12613
+ * @default 0.1
11353
12614
  * @range 0..
11354
12615
  * @unit m (metres)
12616
+ * @tunable
11355
12617
  */
11356
- tolerance: number;
11357
- /**
11358
- * Written: the tip is within `tolerance` of the target after solving.
11359
- *
11360
- * @readonly written by the engine
11361
- */
11362
- readonly reached: boolean;
12618
+ radius: number;
11363
12619
  /**
11364
- * Written: the tip's distance from the target after solving, in model units.
12620
+ * The layers this collider is on, as bits (a spring bone's `colliders` picks them).
11365
12621
  *
11366
- * @unit m (metres)
11367
- * @readonly written by the engine
12622
+ * @default 1
11368
12623
  */
11369
- readonly error: number;
12624
+ layers: number;
11370
12625
  }
11371
12626
 
11372
12627
  /**
@@ -11443,16 +12698,25 @@ export interface GraphDesc {
11443
12698
 
11444
12699
 
11445
12700
  /**
11446
- * A humanoid map from og.load.rig (a cooked `.ogt` of `type rig`): the naming scheme a skeleton's node names follow and the standard bones it names outright.
12701
+ * A humanoid map from og.load.rig (a cooked `.ogt` of `type rig`): the naming scheme a skeleton's node names follow, the standard bones it names outright and, with `footHeight`, how high its ankles stand above the ground.
11447
12702
  *
11448
12703
  * A generational handle: a number the engine hands out. A dead handle is an error value, never a crash.
11449
12704
  */
11450
12705
  export type Rig = number & { readonly [handleType]: "Rig" };
11451
12706
 
12707
+ /**
12708
+ * A Rig handle field (0 is none): a humanoid map og.load.rig answered.
12709
+ *
12710
+ * A `Rig` field: stored in a `Uint32Array` with stride 2.
12711
+ * @param value The field's default; omitted, the column's zero value.
12712
+ * @param options Range, unit, label, docs and the tunable flag.
12713
+ */
12714
+ export declare function Rig(value?: Rig, options?: FieldOptions): FieldSpec<"Rig">;
12715
+
11452
12716
  /** One standard humanoid bone of a skeleton. */
11453
12717
  export interface HumanBone {
11454
12718
  /**
11455
- * The standard bone: hips, spine, chest, upperChest, neck, head, then leftShoulder, leftUpperArm, leftLowerArm, leftHand, the right arm, leftUpperLeg, leftLowerLeg, leftFoot, leftToes and the right leg.
12719
+ * The standard bone: hips, spine, chest, upperChest, neck, head, then leftShoulder, leftUpperArm, leftLowerArm, leftHand, the right arm, leftUpperLeg, leftLowerLeg, leftFoot, leftToes and the right leg, then each hand's fingers (VRM 1.0 names): leftThumbMetacarpal, leftThumbProximal, leftThumbDistal, leftIndexProximal, leftIndexIntermediate, leftIndexDistal, the same for Middle, Ring and Little, and the right hand's.
11456
12720
  */
11457
12721
  readonly bone: string;
11458
12722
  /** The skeleton node that is that bone. */
@@ -11535,6 +12799,27 @@ export interface RetargetDesc {
11535
12799
  }
11536
12800
 
11537
12801
 
12802
+ /**
12803
+ * A clip to play on the other side of the skeleton it was made for.
12804
+ *
12805
+ * A desc: every field may be omitted and then takes its documented default; `{}` is valid.
12806
+ */
12807
+ export interface MirrorDesc {
12808
+ /**
12809
+ * The clip, made for `skeleton`.
12810
+ *
12811
+ * @default 0
12812
+ */
12813
+ readonly clip?: ClipAsset;
12814
+ /**
12815
+ * The skeleton the clip was made for (og.load.animation's `skeleton`); its left and right nodes are paired by name, the side tokens every rig naming scheme writes swapped (LeftArm and RightArm, thigh.L and thigh.R, J_Bip_L_ and J_Bip_R_, calf_l and calf_r).
12816
+ *
12817
+ * @default 0
12818
+ */
12819
+ readonly skeleton?: SkeletonAsset;
12820
+ }
12821
+
12822
+
11538
12823
  /**
11539
12824
  * A sprite sheet's frames and clips (a cooked `.ogt` of `type flipbook`), from og.load.flipbook.
11540
12825
  *
@@ -11734,6 +13019,12 @@ export interface Skeleton2D {
11734
13019
  * The sprite layer it draws in, sorted with the sprites there (after them when they share the layer).
11735
13020
  */
11736
13021
  layer: number;
13022
+ /**
13023
+ * The skin it wears: an index into Rig2DInfo.skins (0 is the rig's default; `rig.skins.indexOf("armor")` finds one by name). A skin shows its own attachment wherever the setup pose or a clip shows the default's; a slot the skin leaves alone shows the default's. Change it any tick: the pose is drawn from it.
13024
+ *
13025
+ * @range 0..
13026
+ */
13027
+ skin: number;
11737
13028
  /**
11738
13029
  * Written: a clip that does not loop reached its end (or its start, played backwards).
11739
13030
  *
@@ -11743,7 +13034,7 @@ export interface Skeleton2D {
11743
13034
  }
11744
13035
 
11745
13036
  /**
11746
- * A 2D skeleton's clip passed one of its events (`event 0.2 "step"` in the rig) in the last tick: footsteps, the frame a swing lands. Read in the tick after, like every event; a clip started at 0 fires its events at 0, a looping clip fires each once per pass.
13037
+ * A 2D skeleton's clip, or the clip a child armature in one of its slots plays, passed one of its events (`event 0.2 "step"` in the rig) in the last tick: footsteps, the frame a swing lands. Read in the tick after, like every event; a clip started at 0 fires its events at 0, a looping clip fires each once per pass.
11747
13038
  *
11748
13039
  * The payload of the `Skeleton2DEvent` event (token `og.Skeleton2DEvent`).
11749
13040
  */
@@ -11760,6 +13051,10 @@ export interface Skeleton2DEvent {
11760
13051
  * @unit s (seconds of simulation time)
11761
13052
  */
11762
13053
  readonly time: number;
13054
+ /**
13055
+ * Empty for the skeleton's own clip; for an event of a child armature shown in one of its slots, that armature's name (`clip` and `time` are then the child's clip and its time): a flame's crackle apart from the keeper's footsteps (at most 63 bytes).
13056
+ */
13057
+ readonly armature: string;
11763
13058
  }
11764
13059
 
11765
13060
  /**
@@ -11847,6 +13142,10 @@ export interface Rig2DInfo {
11847
13142
  readonly slots: readonly string[];
11848
13143
  /** The IK constraints' names: an index here is IkTarget2D.constraint. */
11849
13144
  readonly constraints: readonly string[];
13145
+ /**
13146
+ * Its skins' names, `default` (the rig's own attachments) first: an index here is Skeleton2D.skin.
13147
+ */
13148
+ readonly skins: readonly string[];
11850
13149
  /** Its clips, in file order. */
11851
13150
  readonly clips: readonly Rig2DClipInfo[];
11852
13151
  }
@@ -12359,6 +13658,7 @@ export interface TileCell {
12359
13658
  // Sound: inside the tick, the engine's og.audio system (after the game's systems and physics) turns AudioSource changes into a deterministic, time-stamped command stream; outside the tick the host's mixer renders it (an AudioWorklet on the web, the output device, a capture or a null sink natively).
12360
13659
  // The stream, not the PCM, is world state: snapshots, restore and the world hash cover it, and nothing a sink does reaches the world. Load sounds with og.load.sound; inserting a source plays it, setting `playing` false stops it, and a one-shot sets `playing` back to false when it ends.
12361
13660
  // Spatial gain and pan are computed in the tick from the source's world transform relative to the first AudioListener's (three.js convention: the listener looks down -Z, +X is right; with none, the origin looking down -Z). A source, listener or zone on a child entity is placed at its og.Transform composed down og.Parent, as og.MatrixWorld is: a sound on a child is heard where its parent carries it, a listener under a camera rig hears from the rig.
13661
+ // Propagation, all in the tick and so in the stream: a spatial source or listener that moves shifts the pitch (Doppler, from their tick velocities: AudioSource.dopplerFactor, AudioListener.dopplerFactor, Audio.speedOfSound), a source with a cone is turned down away from its +Z (coneInnerAngle, coneOuterAngle, coneOuterGain, as three.js's setDirectionalCone), and a listener whose panningModel is hrtf places sources for headphones (interaural delay and head shadow) instead of the stereo panner.
12362
13662
 
12363
13663
  /** SoundEnded.reason: a one-shot played to its end. */
12364
13664
  export declare const SOUND_FINISHED: 0;
@@ -12377,6 +13677,11 @@ export declare const SOUND_REPLACED: 3;
12377
13677
  */
12378
13678
  export declare const SOUND_CULLED: 4;
12379
13679
 
13680
+ /**
13681
+ * SoundEnded.reason: AudioSource.retrigger started the sound again from the top; a new voice plays it.
13682
+ */
13683
+ export declare const SOUND_RETRIGGERED: 5;
13684
+
12380
13685
  /**
12381
13686
  * The bus a source plays on; every bus passes through master.
12382
13687
  * - `"master"`: The master bus: what every bus passes through.
@@ -12395,6 +13700,38 @@ export type AudioBus = "master" | "music" | "sfx" | "ui";
12395
13700
  */
12396
13701
  export declare function AudioBus(value?: AudioBus, options?: FieldOptions): FieldSpec<"AudioBus">;
12397
13702
 
13703
+ /**
13704
+ * How an AudioListener places spatial sources between the ears, as Web Audio's PannerNode.panningModel.
13705
+ * - `"equalpower"`: The stereo panner (Web Audio's equal-power law): for speakers.
13706
+ * - `"hrtf"`: For headphones: a spherical-head model (Brown and Duda, 1998) that delays the far ear by the interaural time difference (up to 0.66 ms) and shadows its highs (up to -20 dB), so a source moves between the ears; front and back, up and down are not told apart (no pinna).
13707
+ */
13708
+ export type PanningModel = "equalpower" | "hrtf";
13709
+
13710
+ /**
13711
+ * How the mixer resamples a voice whose pitch or sound rate differs from the output's.
13712
+ * - `"linear"`: Linear interpolation: the engine's mix before round 4, cheaper, with duller highs (-3.4 dB at 15 kHz from 44.1 kHz) and images (-11.5 dB there).
13713
+ * - `"sinc"`: A Kaiser-windowed sinc (beta 7, 16 taps, 2048 phases; widened up to 64 taps for a voice pitched up to 4x): flat to the highs, images below -70 dB.
13714
+ */
13715
+ export type AudioResampler = "linear" | "sinc";
13716
+
13717
+ /**
13718
+ * An AudioResampler field: the variant's index.
13719
+ *
13720
+ * A `AudioResampler` field: stored in a `Uint32Array` with stride 1.
13721
+ * @param value The field's default; omitted, the column's zero value.
13722
+ * @param options Range, unit, label, docs and the tunable flag.
13723
+ */
13724
+ export declare function AudioResampler(value?: AudioResampler, options?: FieldOptions): FieldSpec<"AudioResampler">;
13725
+
13726
+ /**
13727
+ * A PanningModel field: the variant's index.
13728
+ *
13729
+ * A `PanningModel` field: stored in a `Uint32Array` with stride 1.
13730
+ * @param value The field's default; omitted, the column's zero value.
13731
+ * @param options Range, unit, label, docs and the tunable flag.
13732
+ */
13733
+ export declare function PanningModel(value?: PanningModel, options?: FieldOptions): FieldSpec<"PanningModel">;
13734
+
12398
13735
  /**
12399
13736
  * A sound an entity plays. Level-triggered: while `playing` is true it plays (inserting a source plays it), setting it false stops it, and a one-shot that reaches its end sets it back to false and sends og.SoundEnded.
12400
13737
  * A one-shot of F frames at rate R and pitch p started in tick S ends in tick S + ceil(F * tickRate / (R * p)) - 1. A despawned entity's voice is silenced without an event.
@@ -12536,6 +13873,47 @@ export interface AudioSource {
12536
13873
  * @tunable
12537
13874
  */
12538
13875
  fade: number;
13876
+ /**
13877
+ * Doppler: how much a spatial source's and the listener's motion along the line between them shifts its pitch, from their tick velocities (world positions down og.Parent): pitch times (c - DF * vListener) / (c - DF * vSource), c being Audio.speedOfSound and DF this times AudioListener.dopplerFactor (OpenAL's model). 1 is physical, 0 is off. A jump at or past the speed of sound in a tick is a teleport and shifts nothing; DF * v is held within c/2, so the shift stays within a factor of 3.
13878
+ *
13879
+ * @default 1
13880
+ * @range 0..10
13881
+ * @tunable
13882
+ */
13883
+ dopplerFactor: number;
13884
+ /**
13885
+ * Directivity, as three.js PositionalAudio.setDirectionalCone and Web Audio's PannerNode: a spatial source plays at full volume while the listener is within this full angle about the source's +Z (its world transform's, three.js's PositionalAudio orientation); 360 with coneOuterAngle 360 is omnidirectional.
13886
+ *
13887
+ * @default 360
13888
+ * @range 0..360
13889
+ * @unit deg (degrees)
13890
+ * @tunable
13891
+ */
13892
+ coneInnerAngle: number;
13893
+ /**
13894
+ * Past this full angle about the source's +Z it plays at coneOuterGain; between coneInnerAngle and this the gain falls linearly with the angle.
13895
+ *
13896
+ * @default 360
13897
+ * @range 0..360
13898
+ * @unit deg (degrees)
13899
+ * @tunable
13900
+ */
13901
+ coneOuterAngle: number;
13902
+ /**
13903
+ * The gain outside coneOuterAngle.
13904
+ *
13905
+ * @range 0..1
13906
+ * @tunable
13907
+ */
13908
+ coneOuterGain: number;
13909
+ /**
13910
+ * Past Audio.maxVoices it goes virtual instead of being culled: silent, its playhead running on (a one-shot still ends on its tick), and heard again from where it would be, fading in, once it stands within the cap. Without it the source is culled (SOUND_CULLED, playing false).
13911
+ */
13912
+ virtualize: boolean;
13913
+ /**
13914
+ * Set true to start the sound again from the top (its startOffset, its startAt) this tick, playing or not, without a level change on `playing`: the voice playing ends (SOUND_RETRIGGERED) and a new one starts in the same tick. The engine sets it back to false and `playing` true.
13915
+ */
13916
+ retrigger: boolean;
12539
13917
  }
12540
13918
 
12541
13919
  /**
@@ -12552,6 +13930,20 @@ export interface AudioListener {
12552
13930
  * @tunable
12553
13931
  */
12554
13932
  volume: number;
13933
+ /**
13934
+ * Scales every spatial source's Doppler shift (AudioSource.dopplerFactor); 0 turns Doppler off for this listener.
13935
+ *
13936
+ * @default 1
13937
+ * @range 0..10
13938
+ * @tunable
13939
+ */
13940
+ dopplerFactor: number;
13941
+ /**
13942
+ * How spatial sources are placed between the ears: equalpower (speakers) or hrtf (headphones). Non-spatial sources keep their pan either way; the stereo path is unchanged while it is equalpower.
13943
+ *
13944
+ * @default "equalpower"
13945
+ */
13946
+ panningModel: PanningModel;
12555
13947
  }
12556
13948
 
12557
13949
  /**
@@ -12640,6 +14032,21 @@ export interface Audio {
12640
14032
  * @readonly written by the engine
12641
14033
  */
12642
14034
  readonly outputLatency: number;
14035
+ /**
14036
+ * The speed of sound Doppler shifts are computed against (AudioSource.dopplerFactor).
14037
+ *
14038
+ * @default 343.3
14039
+ * @range 1..10000
14040
+ * @unit mps (metres per second)
14041
+ * @tunable
14042
+ */
14043
+ speedOfSound: number;
14044
+ /**
14045
+ * How voices are resampled: sinc (the default) or linear, the mix before round 4, for a game that relies on its exact output. A sound at the output's rate played at pitch 1 is its own samples either way.
14046
+ *
14047
+ * @default "sinc"
14048
+ */
14049
+ resampler: AudioResampler;
12643
14050
  }
12644
14051
 
12645
14052
  /**
@@ -12936,7 +14343,7 @@ export interface SoundEnded {
12936
14343
  /** The voice id in the command stream. */
12937
14344
  readonly voice: number;
12938
14345
  /**
12939
- * Why: SOUND_FINISHED (0), SOUND_STOPPED (1), SOUND_REMOVED (2), SOUND_REPLACED (3) or SOUND_CULLED (4).
14346
+ * Why: SOUND_FINISHED (0), SOUND_STOPPED (1), SOUND_REMOVED (2), SOUND_REPLACED (3), SOUND_CULLED (4) or SOUND_RETRIGGERED (5).
12940
14347
  */
12941
14348
  readonly reason: number;
12942
14349
  }
@@ -16908,14 +18315,6 @@ export interface ScreenTransitionResult {
16908
18315
 
16909
18316
 
16910
18317
 
16911
- /**
16912
- * A graphics quality preset.
16913
- * - `"medium"`: Medium.
16914
- * - `"low"`: Low: the fewest effects.
16915
- * - `"high"`: High: every effect.
16916
- */
16917
- export type GraphicsQuality = "medium" | "low" | "high";
16918
-
16919
18318
  /**
16920
18319
  * A template's action, by its id (a menu item, `buy:<item>`, `share`).
16921
18320
  *
@@ -17219,6 +18618,12 @@ export interface SettingsDesc {
17219
18618
  * @default null
17220
18619
  */
17221
18620
  readonly onSave?: SettingsChanged | null;
18621
+ /**
18622
+ * The world the graphics preset is drawn in: when the player picks another preset the screen calls og.render.applyQuality(world, preset) before onChange. Null leaves applying it to the game. Inside a system, the system declares RenderSettings among its writes.
18623
+ *
18624
+ * @default null
18625
+ */
18626
+ readonly world?: World | null;
17222
18627
  /**
17223
18628
  * The dialog's title. Every word of the screen is a field with its English default: a localised game passes its string table's (og.i18n.t).
17224
18629
  *
@@ -20012,7 +21417,7 @@ export interface EngineProbe extends RuntimeProbe {
20012
21417
 
20013
21418
  // ── terrain ─────────────────────────────────────────────────────
20014
21419
  // Terrain (phase 2): a height field over a rectangle, cooked by `og cook` from a `type terrain` .ogt (a 16-bit grey PNG or an EXR heightmap, an optional control map, up to four layered materials with slope and altitude rules, their maps separate textures or layers of two texture arrays: `layers` and `layerNormals` with each layer's `albedoLayer` and `normalLayer`, two sampled textures instead of up to eight) into tiles; drawn as a geometry clipmap around the camera (nested levels by distance, no cracks) that casts and receives shadows under the fog; collided with as a height field; baked into navmeshes by a navmesh file's `terrain` entry.
20015
- // Load it with og.terrain.load, then place it: an og.Terrain on an entity draws it placed by the entity's world transform (centred on its position, turned and scaled with it), and an og.Collider of shape SHAPE_HEIGHTFIELD naming the TerrainInfo's geometry makes it solid. og.TerrainScatter grows grass, flowers or stones over a layer near the camera. og.terrain.sample answers the surface's height and normal anywhere (pass it the entity's position, quaternion and scale); og.terrain.edit raises, lowers, flattens, smooths or paints it at runtime, and og.terrain.setLayer retunes a layer. Edits are world state: a snapshot keeps them, the world hash covers them, and a restore brings the ground back as it was (rebuilt from the cook with the restored edits replayed, for the renderer, physics and sample alike).
21420
+ // Load it with og.terrain.load, then place it: an og.Terrain on an entity draws it placed by the entity's world transform (centred on its position, turned and scaled with it), and an og.Collider of shape SHAPE_HEIGHTFIELD naming the TerrainInfo's geometry makes it solid. og.TerrainScatter grows grass, flowers or stones over a layer near the camera. og.terrain.sample answers the surface's height and normal anywhere (pass it the entity's position, quaternion and scale); og.terrain.edit raises, lowers, flattens, smooths or paints it at runtime, and og.terrain.setLayer retunes a layer. Terrain is 3D: the 2D profile's publish and lanes modules leave it out (RenderCapabilities.world3d is false), where every call here answers a refusal naming that field. Edits are world state: a snapshot keeps them, the world hash covers them, and a restore brings the ground back as it was (rebuilt from the cook with the restored edits replayed, for the renderer, physics and sample alike).
20016
21421
  // Its tiles stream (phase 3): the cook stores the field as a pyramid of tiles, each compressed on its own, and every frame the renderer keeps on the GPU only the tiles the camera's clipmap wants, within each terrain's tile budget (16 MiB by default), decoded off the frame (a worker thread natively, the browser's DecompressionStream on the Web) a few at a time, the most needed first; until a tile arrives its area draws from the coarser level that holds it, then fades in. Nothing a tick reads depends on which tiles are resident (collision and og.terrain.sample read the whole field), so a run's world hash is the same streamed or not. The probe's `terrain_stream:resident` decodes every wanted tile before each frame instead (`terrain_stream:stream[:<MiB>]` streams again, within that budget), and `dump_stream`'s `terrain` gives the tiles resident, waiting, decoding and cached.
20017
21422
 
20018
21423
  /**
@@ -20183,6 +21588,12 @@ export interface TerrainInfo {
20183
21588
  readonly collision: boolean;
20184
21589
  /** Its terrain file's `castShadows`. */
20185
21590
  readonly castShadows: boolean;
21591
+ /**
21592
+ * A generated terrain's sea level (`generate { sea <m> }`) above its entity: place an og.Water there, the terrain's size; null without a sea.
21593
+ *
21594
+ * @unit m (metres)
21595
+ */
21596
+ readonly seaLevel: number | null;
20186
21597
  }
20187
21598
 
20188
21599
  /**
@@ -21413,9 +22824,9 @@ export declare namespace og {
21413
22824
  /** A cone of light along the entity's local -Z, as three.js SpotLight. */
21414
22825
  const SpotLight: ComponentType<{ readonly color: FieldSpec<"Color">; readonly intensity: FieldSpec<"f32">; readonly distance: FieldSpec<"f32">; readonly angle: FieldSpec<"f32">; readonly penumbra: FieldSpec<"f32">; readonly castShadow: FieldSpec<"bool">; readonly cookie: FieldSpec<"Texture"> }, SpotLight>;
21415
22826
  /**
21416
- * The frame's look after lighting: environment light, sky, bloom, exposure metering and tone mapping. Read after each tick; it never feeds back into the simulation. Camera.exposure is the manual exposure.
22827
+ * The frame's look after lighting: environment light, sky, bloom, exposure metering and tone mapping, and what the frame may cost: the quality fields (rectShadows to msaaSamples) that og.render.applyQuality sets from a graphics preset. Read after each tick; it never feeds back into the simulation. Camera.exposure is the manual exposure.
21417
22828
  */
21418
- const RenderSettings: ResourceType<{ readonly environmentIntensity: FieldSpec<"f32">; readonly sky: FieldSpec<"bool">; readonly bloom: FieldSpec<"bool">; readonly bloomThreshold: FieldSpec<"f32">; readonly bloomKnee: FieldSpec<"f32">; readonly bloomIntensity: FieldSpec<"f32">; readonly autoExposure: FieldSpec<"bool">; readonly adaptSpeedUp: FieldSpec<"f32">; readonly adaptSpeedDown: FieldSpec<"f32">; readonly toneMapped: FieldSpec<"bool">; readonly toneMapping: FieldSpec<"ToneMapping">; readonly exposure: FieldSpec<"f32">; readonly decalAtlas: FieldSpec<"Texture">; readonly lodBias: FieldSpec<"f32">; readonly bakedLighting: FieldSpec<"bool"> }, RenderSettings>;
22829
+ const RenderSettings: ResourceType<{ readonly environmentIntensity: FieldSpec<"f32">; readonly sky: FieldSpec<"bool">; readonly bloom: FieldSpec<"bool">; readonly bloomThreshold: FieldSpec<"f32">; readonly bloomKnee: FieldSpec<"f32">; readonly bloomIntensity: FieldSpec<"f32">; readonly autoExposure: FieldSpec<"bool">; readonly adaptSpeedUp: FieldSpec<"f32">; readonly adaptSpeedDown: FieldSpec<"f32">; readonly toneMapped: FieldSpec<"bool">; readonly toneMapping: FieldSpec<"ToneMapping">; readonly exposure: FieldSpec<"f32">; readonly decalAtlas: FieldSpec<"Texture">; readonly lodBias: FieldSpec<"f32">; readonly bakedLighting: FieldSpec<"bool">; readonly quality: FieldSpec<"QualityPreset">; readonly rectShadows: FieldSpec<"bool">; readonly shadowedLights: FieldSpec<"u32">; readonly shadowMapScale: FieldSpec<"f32">; readonly volumetricFog: FieldSpec<"bool">; readonly softParticles: FieldSpec<"bool">; readonly screenSpaceReflections: FieldSpec<"bool">; readonly ambientOcclusion: FieldSpec<"bool">; readonly msaaSamples: FieldSpec<"u32"> }, RenderSettings>;
21419
22830
  /**
21420
22831
  * Image-based light from a cooked HDR environment map instead of the sky, as three.js scene.environment, and the map behind the scene, as scene.background = the environment. Load the map with og.load.environment: the cook has already prefiltered it (GGX levels for reflections from mirror to rough, harmonics for the diffuse light), so setting it costs a few copy passes on any tier, WebGL2 included. Without a map the sky lights the scene as before (og.Sky, a DayNight, or the built-in one). Read after each tick; it never feeds back into the simulation.
21421
22832
  */
@@ -21424,7 +22835,7 @@ export declare namespace og {
21424
22835
  * The post stack beyond RenderSettings' bloom, exposure and tone mapping, and camera shake. Every effect is off by default (its switch false or its amount 0) and then costs nothing: no pass is recorded. Read after each tick; it never feeds back into the simulation.
21425
22836
  * Screen-space ambient occlusion, outlines, depth of field, motion blur and god rays run a depth-normal prepass, turned on with them. Grading, vignette, aberration, grain and the flash apply to the display colour after tone mapping; the UI and screen-space sprites (the overlay) come after all of it.
21426
22837
  */
21427
- const PostEffects: ResourceType<{ readonly ao: FieldSpec<"bool">; readonly aoRadius: FieldSpec<"f32">; readonly aoIntensity: FieldSpec<"f32">; readonly aoMethod: FieldSpec<"AoMethod">; readonly outline: FieldSpec<"bool">; readonly outlineColor: FieldSpec<"Color">; readonly outlineWidth: FieldSpec<"f32">; readonly outlineDepthThreshold: FieldSpec<"f32">; readonly outlineNormalThreshold: FieldSpec<"f32">; readonly depthOfField: FieldSpec<"bool">; readonly dofFocusDistance: FieldSpec<"f32">; readonly dofFocusRange: FieldSpec<"f32">; readonly dofMaxBlur: FieldSpec<"f32">; readonly dofFalloff: FieldSpec<"f32">; readonly dofQuality: FieldSpec<"DofQuality">; readonly motionBlur: FieldSpec<"bool">; readonly motionBlurShutter: FieldSpec<"f32">; readonly motionBlurSamples: FieldSpec<"u32">; readonly motionBlurMaxPixels: FieldSpec<"f32">; readonly godRays: FieldSpec<"bool">; readonly godRaysIntensity: FieldSpec<"f32">; readonly godRaysDecay: FieldSpec<"f32">; readonly godRaysDensity: FieldSpec<"f32">; readonly godRaysTint: FieldSpec<"Color">; readonly godRaysSamples: FieldSpec<"u32">; readonly godRaysThreshold: FieldSpec<"f32">; readonly glow: FieldSpec<"bool">; readonly glowIntensity: FieldSpec<"f32">; readonly lut: FieldSpec<"Lut">; readonly lutIntensity: FieldSpec<"f32">; readonly vignette: FieldSpec<"bool">; readonly vignetteIntensity: FieldSpec<"f32">; readonly vignetteRadius: FieldSpec<"f32">; readonly vignetteSmoothness: FieldSpec<"f32">; readonly vignetteColor: FieldSpec<"Color">; readonly chromaticAberration: FieldSpec<"f32">; readonly filmGrain: FieldSpec<"f32">; readonly filmGrainSize: FieldSpec<"f32">; readonly flash: FieldSpec<"f32">; readonly flashColor: FieldSpec<"Color">; readonly shakeTrauma: FieldSpec<"f32">; readonly shakeMaxOffset: FieldSpec<"f32">; readonly shakeMaxRoll: FieldSpec<"f32">; readonly shakeFrequency: FieldSpec<"f32">; readonly shakeSeed: FieldSpec<"u32">; readonly ssr: FieldSpec<"bool">; readonly ssrMaxDistance: FieldSpec<"f32">; readonly ssrThickness: FieldSpec<"f32">; readonly ssrSteps: FieldSpec<"u32">; readonly ssrFade: FieldSpec<"f32">; readonly ssrIntensity: FieldSpec<"f32">; readonly custom1: FieldSpec<"Post">; readonly custom2: FieldSpec<"Post">; readonly custom3: FieldSpec<"Post">; readonly custom4: FieldSpec<"Post">; readonly custom5: FieldSpec<"Post">; readonly custom6: FieldSpec<"Post">; readonly custom7: FieldSpec<"Post">; readonly custom8: FieldSpec<"Post"> }, PostEffects>;
22838
+ const PostEffects: ResourceType<{ readonly ao: FieldSpec<"bool">; readonly aoRadius: FieldSpec<"f32">; readonly aoIntensity: FieldSpec<"f32">; readonly aoMethod: FieldSpec<"AoMethod">; readonly outline: FieldSpec<"bool">; readonly outlineColor: FieldSpec<"Color">; readonly outlineWidth: FieldSpec<"f32">; readonly outlineDepthThreshold: FieldSpec<"f32">; readonly outlineNormalThreshold: FieldSpec<"f32">; readonly depthOfField: FieldSpec<"bool">; readonly dofFocusDistance: FieldSpec<"f32">; readonly dofFocusRange: FieldSpec<"f32">; readonly dofMaxBlur: FieldSpec<"f32">; readonly dofFalloff: FieldSpec<"f32">; readonly dofQuality: FieldSpec<"DofQuality">; readonly motionBlur: FieldSpec<"bool">; readonly motionBlurShutter: FieldSpec<"f32">; readonly motionBlurSamples: FieldSpec<"u32">; readonly motionBlurMaxPixels: FieldSpec<"f32">; readonly godRays: FieldSpec<"bool">; readonly godRaysIntensity: FieldSpec<"f32">; readonly godRaysDecay: FieldSpec<"f32">; readonly godRaysDensity: FieldSpec<"f32">; readonly godRaysTint: FieldSpec<"Color">; readonly godRaysSamples: FieldSpec<"u32">; readonly godRaysThreshold: FieldSpec<"f32">; readonly glow: FieldSpec<"bool">; readonly glowIntensity: FieldSpec<"f32">; readonly lut: FieldSpec<"Lut">; readonly lutIntensity: FieldSpec<"f32">; readonly vignette: FieldSpec<"bool">; readonly vignetteIntensity: FieldSpec<"f32">; readonly vignetteRadius: FieldSpec<"f32">; readonly vignetteSmoothness: FieldSpec<"f32">; readonly vignetteColor: FieldSpec<"Color">; readonly chromaticAberration: FieldSpec<"f32">; readonly filmGrain: FieldSpec<"f32">; readonly filmGrainSize: FieldSpec<"f32">; readonly flash: FieldSpec<"f32">; readonly flashColor: FieldSpec<"Color">; readonly shakeTrauma: FieldSpec<"f32">; readonly shakeMaxOffset: FieldSpec<"f32">; readonly shakeMaxRoll: FieldSpec<"f32">; readonly shakeFrequency: FieldSpec<"f32">; readonly shakeSeed: FieldSpec<"u32">; readonly ssr: FieldSpec<"bool">; readonly ssrMaxDistance: FieldSpec<"f32">; readonly ssrThickness: FieldSpec<"f32">; readonly ssrSteps: FieldSpec<"u32">; readonly ssrFade: FieldSpec<"f32">; readonly ssrIntensity: FieldSpec<"f32">; readonly custom: ListSpec<"Post"> }, PostEffects>;
21428
22839
  /**
21429
22840
  * Stylisation primitives that move the frame away from the photographic: a low-resolution pixel grid scaled up by whole numbers, fewer tones or a fixed palette through an ordered or blue-noise dither, halftone dots, cross-hatching, painterly smoothing over a canvas, ink lines on tonal edges, flat colour bands by depth, and the vertex snapping, affine textures and coarse depth of early 3D hardware. They compose: a look (og.load.look) sets this with PostEffects and RenderSettings, and the game's art direction is in that data, not in the engine. Every primitive is off at its zero value (0, false, none) and then costs nothing: no pass is recorded and no pipeline is built. RenderCapabilities.stylise names the primitives this renderer draws; a field it does not name is carried and read back but not drawn. Read after each tick; it never feeds back into the simulation.
21430
22841
  * Order in the frame: depth bands colour the lit scene with the fog, before tone mapping; after tone mapping and PostEffects' grading come paint, hatching, halftone and ink, then posterize and palette quantise through the dither, all at the logical resolution, and the pixel grid is scaled up last. The UI and screen-space sprites are drawn over the scaled frame at the output's resolution, unstylised.
@@ -21463,10 +22874,10 @@ export declare namespace og {
21463
22874
  */
21464
22875
  const Beam: ComponentType<{ readonly end: FieldSpec<"Vector3">; readonly width: FieldSpec<"f32">; readonly color: FieldSpec<"Color">; readonly opacity: FieldSpec<"f32">; readonly texture: FieldSpec<"Texture">; readonly tile: FieldSpec<"f32">; readonly scroll: FieldSpec<"f32">; readonly segments: FieldSpec<"u32">; readonly jitter: FieldSpec<"f32">; readonly seed: FieldSpec<"u32">; readonly blend: FieldSpec<"StripBlend"> }, Beam>;
21465
22876
  /**
21466
- * A sprite drawn every frame at the entity's MatrixWorld (its xy and z, its rotation about z; its scale multiplies width and height, so squash and stretch is a tween of og.Transform.scale). With an og.Flipbook on the entity, the texture (or an `array true` sheet's texture array layer), region and anchor come from the flipbook's current frame.
22877
+ * A sprite drawn every frame at the entity's MatrixWorld (its xy and z, its rotation about z, in the xy plane or turned to the camera by `facing`; its scale multiplies width and height, so squash and stretch is a tween of og.Transform.scale). With an og.Flipbook on the entity, the texture (or an `array true` sheet's texture array layer), region and anchor come from the flipbook's current frame.
21467
22878
  * Sorted with the immediate sprites and text by layer, then (sortY) by y, then texture: one draw per run of one texture. Tile layers draw before the sprites of their layer.
21468
22879
  */
21469
- const Sprite: ComponentType<{ readonly texture: FieldSpec<"Texture">; readonly array: FieldSpec<"TextureArray">; readonly arrayLayer: FieldSpec<"u32">; readonly width: FieldSpec<"f32">; readonly height: FieldSpec<"f32">; readonly anchor: FieldSpec<"Vector2">; readonly color: FieldSpec<"Color">; readonly opacity: FieldSpec<"f32">; readonly uvMin: FieldSpec<"Vector2">; readonly uvMax: FieldSpec<"Vector2">; readonly layer: FieldSpec<"i32">; readonly sortY: FieldSpec<"bool">; readonly flipX: FieldSpec<"bool">; readonly flipY: FieldSpec<"bool">; readonly flash: FieldSpec<"f32">; readonly flashColor: FieldSpec<"Color">; readonly glow: FieldSpec<"f32">; readonly blend: FieldSpec<"SpriteBlend">; readonly castShadow: FieldSpec<"bool">; readonly sliceX: FieldSpec<"Vector2">; readonly sliceY: FieldSpec<"Vector2">; readonly sliceScale: FieldSpec<"f32">; readonly shadow: FieldSpec<"f32">; readonly shadowSize: FieldSpec<"Vector2">; readonly shadowOffset: FieldSpec<"Vector2">; readonly dropShadow: FieldSpec<"f32">; readonly dropShadowHeight: FieldSpec<"f32">; readonly toneMapped: FieldSpec<"bool">; readonly visible: FieldSpec<"bool">; readonly layers: FieldSpec<"u32"> }, Sprite>;
22880
+ const Sprite: ComponentType<{ readonly texture: FieldSpec<"Texture">; readonly array: FieldSpec<"TextureArray">; readonly arrayLayer: FieldSpec<"u32">; readonly width: FieldSpec<"f32">; readonly height: FieldSpec<"f32">; readonly anchor: FieldSpec<"Vector2">; readonly color: FieldSpec<"Color">; readonly opacity: FieldSpec<"f32">; readonly uvMin: FieldSpec<"Vector2">; readonly uvMax: FieldSpec<"Vector2">; readonly layer: FieldSpec<"i32">; readonly sortY: FieldSpec<"bool">; readonly facing: FieldSpec<"SpriteFacing">; readonly flipX: FieldSpec<"bool">; readonly flipY: FieldSpec<"bool">; readonly flash: FieldSpec<"f32">; readonly flashColor: FieldSpec<"Color">; readonly glow: FieldSpec<"f32">; readonly blend: FieldSpec<"SpriteBlend">; readonly castShadow: FieldSpec<"bool">; readonly sliceX: FieldSpec<"Vector2">; readonly sliceY: FieldSpec<"Vector2">; readonly sliceScale: FieldSpec<"f32">; readonly shadow: FieldSpec<"f32">; readonly shadowSize: FieldSpec<"Vector2">; readonly shadowOffset: FieldSpec<"Vector2">; readonly dropShadow: FieldSpec<"f32">; readonly dropShadowHeight: FieldSpec<"f32">; readonly toneMapped: FieldSpec<"bool">; readonly visible: FieldSpec<"bool">; readonly layers: FieldSpec<"u32"> }, Sprite>;
21470
22881
  /**
21471
22882
  * Ghosts of the entity's og.Sprite: every `interval` ticks its pose (position, rotation, scale, frame, flips) is kept, and the last `count` are drawn behind it, fading from `opacity` to 0, tinted by color. A dash, a speed-up, a teleport. The history is world state (the og.sprite state block).
21472
22883
  */
@@ -21611,6 +23022,25 @@ export declare namespace og {
21611
23022
  * @returns Refused for a look not loaded in this world, one in a streaming group that is not resident (the reason names it), or a resource the system did not declare.
21612
23023
  */
21613
23024
  function applyLook(world: World, look: Look): Result<void>;
23025
+ /**
23026
+ * Apply a graphics preset: write its row of RenderSettings' quality fields (the rest of RenderSettings keeps its values) and record it in RenderSettings.quality. The renderer reads those fields and nothing else, so what the probe and dump_world show of RenderSettings is what the next frame draws. The settings screen calls it when the player picks a preset (SettingsDesc.world); a game applies a saved preset itself at start. Inside a system, the system must declare RenderSettings among its writes. The rows:
23027
+ * | Field | low | medium | high |
23028
+ * |---|---|---|---|
23029
+ * | rectShadows | false | true | true |
23030
+ * | shadowedLights | 2 | 8 | 8 |
23031
+ * | shadowMapScale | 0.5 | 1 | 2 |
23032
+ * | volumetricFog | false | true | true |
23033
+ * | softParticles | false | true | true |
23034
+ * | screenSpaceReflections | false | true | true |
23035
+ * | ambientOcclusion | false | true | true |
23036
+ * | msaaSamples | 1 | 4 | 4 |
23037
+ * Medium is every field's default, the frame drawn before any preset.
23038
+ *
23039
+ * @param world The world whose RenderSettings change.
23040
+ * @param preset The preset.
23041
+ * @returns Refused for a world that is not alive, or inside a system that did not declare RenderSettings among its writes.
23042
+ */
23043
+ function applyQuality(world: World, preset: GraphicsQuality): Result<void>;
21614
23044
  /**
21615
23045
  * The look last applied (by og.render.applyLook or GameDesc.look), as og.load.lookInfo describes it; null before any.
21616
23046
  *
@@ -21706,6 +23136,90 @@ export declare namespace og {
21706
23136
  * @returns Refused for fewer than two points or a point that is not finite (without a path), or a path that is not alive.
21707
23137
  */
21708
23138
  function tubeGeometry(world: World, desc?: TubeGeometryDesc): Result<Geometry>;
23139
+ /**
23140
+ * Make a flat shape for og.Mesh (one-sided, as circleGeometry): an og.Shape with holes, or a points array. Physics can use it as a triangle-mesh Collider.mesh.
23141
+ *
23142
+ * @param world The world whose renderer owns the geometry.
23143
+ * @param desc The shapes and their tessellation.
23144
+ * @returns Refused for a shape whose points are not finite or that triangulates to nothing.
23145
+ */
23146
+ function shapeGeometry(world: World, desc?: ShapeGeometryDesc): Result<Geometry>;
23147
+ /**
23148
+ * Make an extruded solid for og.Mesh: a three.js extrusion is a paste (`og.render.extrudeGeometry(world, { shapes: shape, depth: 0.2, bevelEnabled: true })`). Gears, signs, keys, logos, cookie cutters; along a path, a rail or a moulding.
23149
+ *
23150
+ * @param world The world whose renderer owns the geometry.
23151
+ * @param desc The shapes, depth, bevel and path.
23152
+ * @returns Refused for a shape whose points are not finite or that triangulates to nothing, or an extrudePath that is not alive.
23153
+ */
23154
+ function extrudeGeometry(world: World, desc?: ExtrudeGeometryDesc): Result<Geometry>;
23155
+ /**
23156
+ * Make a solid of revolution for og.Mesh: a profile turned round +Y.
23157
+ *
23158
+ * @param world The world whose renderer owns the geometry.
23159
+ * @param desc The profile and the turn.
23160
+ * @returns Refused for fewer than two points or one that is not finite.
23161
+ */
23162
+ function latheGeometry(world: World, desc?: LatheGeometryDesc): Result<Geometry>;
23163
+ /**
23164
+ * Make a polyhedron from vertices and faces for og.Mesh, subdivided onto a sphere.
23165
+ *
23166
+ * @param world The world whose renderer owns the geometry.
23167
+ * @param desc The vertices, faces, radius and detail.
23168
+ * @returns Refused for no faces, an index past the vertices, or a count that is not a multiple of three.
23169
+ */
23170
+ function polyhedronGeometry(world: World, desc?: PolyhedronGeometryDesc): Result<Geometry>;
23171
+ /**
23172
+ * Make an icosahedron (twenty faces) for og.Mesh; with detail, a geodesic sphere.
23173
+ *
23174
+ * @param world The world whose renderer owns the geometry.
23175
+ * @param desc Its radius and detail.
23176
+ */
23177
+ function icosahedronGeometry(world: World, desc?: SolidGeometryDesc): Result<Geometry>;
23178
+ /**
23179
+ * Make a dodecahedron (twelve pentagons, thirty-six triangles) for og.Mesh.
23180
+ *
23181
+ * @param world The world whose renderer owns the geometry.
23182
+ * @param desc Its radius and detail.
23183
+ */
23184
+ function dodecahedronGeometry(world: World, desc?: SolidGeometryDesc): Result<Geometry>;
23185
+ /**
23186
+ * Make an octahedron (eight faces) for og.Mesh.
23187
+ *
23188
+ * @param world The world whose renderer owns the geometry.
23189
+ * @param desc Its radius and detail.
23190
+ */
23191
+ function octahedronGeometry(world: World, desc?: SolidGeometryDesc): Result<Geometry>;
23192
+ /**
23193
+ * Make a tetrahedron (four faces) for og.Mesh.
23194
+ *
23195
+ * @param world The world whose renderer owns the geometry.
23196
+ * @param desc Its radius and detail.
23197
+ */
23198
+ function tetrahedronGeometry(world: World, desc?: SolidGeometryDesc): Result<Geometry>;
23199
+ /**
23200
+ * Make a section swept along a path for og.Mesh, tapered and twisted by keys.
23201
+ *
23202
+ * @param world The world whose renderer owns the geometry.
23203
+ * @param desc The section, path, keys and caps.
23204
+ * @returns Refused for a path that is not alive, a section of fewer than three points or of no area, or a value that is not finite.
23205
+ */
23206
+ function sweepGeometry(world: World, desc?: SweepGeometryDesc): Result<Geometry>;
23207
+ /**
23208
+ * Make the union, difference or intersection of two placed geometries for og.Mesh. Chain calls for more operands (a cube minus six spheres is six calls); each result is a geometry like any other.
23209
+ *
23210
+ * @param world The world whose renderer owns the geometry.
23211
+ * @param desc The operation and its operands.
23212
+ * @returns Refused for a dead geometry, a placement with a zero scale, or a position that is not finite.
23213
+ */
23214
+ function csgGeometry(world: World, desc?: CsgGeometryDesc): Result<Geometry>;
23215
+ /**
23216
+ * Make one geometry of several placed ones for og.Mesh: one draw instead of many, mirrored halves, arrays.
23217
+ *
23218
+ * @param world The world whose renderer owns the geometry.
23219
+ * @param desc The parts and their placements.
23220
+ * @returns Refused for no parts, a dead geometry, or a placement with a zero scale.
23221
+ */
23222
+ function mergeGeometries(world: World, desc?: MergeGeometriesDesc): Result<Geometry>;
21709
23223
  /**
21710
23224
  * Draw lines this frame. Systems and commands may call it; the list is cleared at every tick, so submit them every tick they should show (og.Lines keeps a static set).
21711
23225
  *
@@ -21750,7 +23264,7 @@ export declare namespace og {
21750
23264
  */
21751
23265
  function setPostParam(world: World, post: Post, name: string, value: readonly number[]): Result<void>;
21752
23266
  /**
21753
- * The custom post passes PostEffects.custom1 to custom8 name that failed to compile on this device, each skipped (the frame draws as without it). The cook validates every pass for each back end, so this is a device's own refusal.
23267
+ * The custom post passes PostEffects.custom names that failed to compile on this device, each skipped (the frame draws as without it). The cook validates every pass for each back end, so this is a device's own refusal.
21754
23268
  *
21755
23269
  * @param world The world asked.
21756
23270
  */
@@ -21762,6 +23276,14 @@ export declare namespace og {
21762
23276
  */
21763
23277
  function bakedLighting(world: World): readonly BakedScene[];
21764
23278
  }
23279
+ /**
23280
+ * three.js's Path (named Path2 beside og.path's 3D paths): `new og.Path2().moveTo(0, 0).lineTo(1, 0)`.
23281
+ */
23282
+ const Path2: Path2Class;
23283
+ /**
23284
+ * three.js's Shape: `const s = new og.Shape(); s.moveTo(0, 0).lineTo(1, 0).lineTo(0, 1); s.holes.push(hole)`.
23285
+ */
23286
+ const Shape: ShapeClass;
21765
23287
  /**
21766
23288
  * Draws a loaded glTF's default scene at the entity's world transform: every mesh node with its glTF material. Scene entities with a `model` line get one; world.instantiate of a glTF asset spawns one.
21767
23289
  * The glTF's materials are shared by every instance of it; `tint` and `flash` are this instance's own, carried with its transform to the lit shaders (one draw for every instance, whatever each shows), so one of a crowd can flash when struck.
@@ -21802,7 +23324,7 @@ export declare namespace og {
21802
23324
  function defaultBundle(world: World): Result<Asset>;
21803
23325
  /**
21804
23326
  * Load a cooked glTF (.gltf or .glb), as three.js GLTFLoader.load: its meshes, materials and textures join the renderer once.
21805
- * A MagicaVoxel `.vox` cooks to a glTF and loads here too: greedy-meshed, flat-shaded, its palette as vertex colours, z-up turned y-up, each model about its centre (MagicaVoxel's pivot, with a scene graph or without). Its import settings (`models/hut.vox.ogt`, `type import`) size and place it: `model { voxScale 0.1 voxOrigin bottom }` is 0.1 m a voxel (default 1) and the lowest voxel on y = 0 (default `center`, the editor's origin). A `.vox` with frames (MagicaVoxel's animation) cooks to clips that swap the frames' models, played by og.AnimationPlayer as any skinned clip: `voxFps 8` (default 10) and `voxClip walk 0 3` (frames 0 to 3; default one clip `frames` of every frame).
23327
+ * A MagicaVoxel `.vox` cooks to a glTF and loads here too: greedy-meshed, flat-shaded, its palette as vertex colours, z-up turned y-up, each model about its centre (MagicaVoxel's pivot, with a scene graph or without). Its import settings (`models/hut.vox.ogt`, `type import`) size and place it: `model { voxScale 0.1 voxOrigin bottom }` is 0.1 m a voxel (default 1) and the lowest voxel on y = 0 (default `center`, the editor's origin). A `.vox` with frames (MagicaVoxel's animation) cooks to clips that swap the frames' models, played by og.AnimationPlayer as any skinned clip: `voxFps 8` (default 10) and `voxClip walk 0 3` (frames 0 to 3; default one clip `frames` of the file's playback range, else of every frame); a node's `_loop` repeats its keys as the editor plays them.
21806
23328
  *
21807
23329
  * @param world The world that owns the asset.
21808
23330
  * @param path The asset id, such as `models/ship.glb`.
@@ -21873,7 +23395,7 @@ export declare namespace og {
21873
23395
  */
21874
23396
  function shader(world: World, path: string): Result<Shader>;
21875
23397
  /**
21876
- * A custom post pass for PostEffects.custom1 to custom8, from a cooked `.ogt` of `type post`: `code` or `source` (a `.wgsl` beside it) defining `fn post(f: PostInput, p: Params) -> vec4<f32>` and `param <name> float|vec2|vec3|vec4|color <default...>` lines (at most eight). The function reads previous(uv), scene_color(uv), depth(uv), normal(uv) and f.uv, f.pixel, f.size, f.time, and returns linear HDR colour (the og-game skill's Custom post passes section has the contract). The cook compiles it for every back end. Loaded once per path.
23398
+ * A custom post pass for PostEffects.custom, from a cooked `.ogt` of `type post`: `code` or `source` (a `.wgsl` beside it) defining `fn post(f: PostInput, p: Params) -> vec4<f32>` and `param <name> float|vec2|vec3|vec4|color <default...>` lines (at most eight). The function reads previous(uv), scene_color(uv), depth(uv), normal(uv) and f.uv, f.pixel, f.size, f.time, and returns linear HDR colour (the og-game skill's Custom post passes section has the contract). The cook compiles it for every back end. Loaded once per path.
21877
23399
  *
21878
23400
  * @param world The world whose renderer owns it.
21879
23401
  * @param path The asset id, such as `post/crt.ogt`.
@@ -22043,7 +23565,9 @@ export declare namespace og {
22043
23565
  * The physics settings of the world. The profile is the project's; the same components serve both profiles.
22044
23566
  */
22045
23567
  const Physics: ResourceType<{ readonly profile: FieldSpec<"u32">; readonly gravity: FieldSpec<"Vector3">; readonly substeps: FieldSpec<"u32">; readonly solverIterations: FieldSpec<"u32">; readonly restSpeed: FieldSpec<"f32"> }, Physics>;
22046
- /** Two solid colliders started touching during the tick. */
23568
+ /**
23569
+ * Two solid colliders started touching during the tick. Read in the tick after, when og.Velocity already holds the solver's answer (the bodies parting): how hard they met is `impulse` and `relativeVelocity`, taken in the step itself.
23570
+ */
22047
23571
  const CollisionStarted: EventType<CollisionStarted>;
22048
23572
  /** Two solid colliders stopped touching, or one of them went away. */
22049
23573
  const CollisionEnded: EventType<CollisionEnded>;
@@ -22324,6 +23848,26 @@ export declare namespace og {
22324
23848
  * An inverse-kinematics constraint on a skeleton, applied after its clips and graph: the chain of `bones` bones ending at joint `tip` turns so the tip reaches `target`. Put it on its own entity (a skeleton can have many chains); chains apply in query order.
22325
23849
  */
22326
23850
  const IkChain: ComponentType<{ readonly skeleton: FieldSpec<"Entity">; readonly tip: FieldSpec<"u32">; readonly bones: FieldSpec<"u32">; readonly solver: FieldSpec<"IkSolver">; readonly target: FieldSpec<"Vector3">; readonly pole: FieldSpec<"Vector3">; readonly space: FieldSpec<"IkSpace">; readonly weight: FieldSpec<"f32">; readonly iterations: FieldSpec<"u32">; readonly tolerance: FieldSpec<"f32">; readonly reached: FieldSpec<"bool">; readonly error: FieldSpec<"f32"> }, IkChain>;
23851
+ /**
23852
+ * An aim constraint on a skeleton, applied after its clips, graph and IK chains: `joint` turns so its `axis` points at `target` and its `upAxis` leans towards `up` (three.js Object3D.lookAt: +Z at the target, +Y up). The direction is held within maxYaw and maxPitch of the animated forward; with `bones` above 1 the joint's parents share the turn. Put it on its own entity (a head, the eyes, a turret's barrel); constraints apply in query order, and og.JointLimit clamps the joints it turns.
23853
+ */
23854
+ const LookAt: ComponentType<{ readonly skeleton: FieldSpec<"Entity">; readonly joint: FieldSpec<"u32">; readonly bones: FieldSpec<"u32">; readonly target: FieldSpec<"Vector3">; readonly space: FieldSpec<"IkSpace">; readonly axis: FieldSpec<"Vector3">; readonly upAxis: FieldSpec<"Vector3">; readonly up: FieldSpec<"Vector3">; readonly maxYaw: FieldSpec<"f32">; readonly maxPitch: FieldSpec<"f32">; readonly weight: FieldSpec<"f32">; readonly clamped: FieldSpec<"bool"> }, LookAt>;
23855
+ /**
23856
+ * How far a joint may turn from its rest rotation when og.anim's solvers (og.IkChain, og.LookAt, og.FootLock) turn it: a swing of `axis` within a cone and a twist about it within a range. A hinge (a knee, an elbow) is `axis` along the hinge, `swing` 0 (or a little play) and the bend range as twistMin...twistMax. Put it on its own entity, one per joint; the animated pose itself is never clamped.
23857
+ */
23858
+ const JointLimit: ComponentType<{ readonly skeleton: FieldSpec<"Entity">; readonly joint: FieldSpec<"u32">; readonly axis: FieldSpec<"Vector3">; readonly swing: FieldSpec<"f32">; readonly twistMin: FieldSpec<"f32">; readonly twistMax: FieldSpec<"f32"> }, JointLimit>;
23859
+ /**
23860
+ * Foot locking: while the playing clips plant `foot` (within 5 mm of its lowest in each clip, the notion retargeting uses, weighed across blends and cross-fades: planted when the planting clips hold at least half the pose), the foot stays where it touched the ground, through clip blends and root motion, its leg bent by two-bone IK and the foot keeping its animated orientation; when the clips lift it, the foot rejoins its animation over `release`. Put it on its own entity, one per foot; locks apply after root motion and before og.IkChain, in query order, and og.JointLimit clamps the leg. The lock is world state (the `og.anim` state block).
23861
+ */
23862
+ const FootLock: ComponentType<{ readonly skeleton: FieldSpec<"Entity">; readonly foot: FieldSpec<"u32">; readonly weight: FieldSpec<"f32">; readonly release: FieldSpec<"f32">; readonly maxDistance: FieldSpec<"f32">; readonly planted: FieldSpec<"bool">; readonly locked: FieldSpec<"bool"> }, FootLock>;
23863
+ /**
23864
+ * A spring (jiggle) bone chain, three-vrm's VRMSpringBone: `joint` and its `bones` - 1 parents swing after their parents' motion. Each joint's tail (the next joint of the chain; for the last joint its first child, or its parent bone continued at the same length) is a point pulled towards where the animated pose puts it by a damped spring (`frequency`, `damping`), under `gravity`, held at the bone's length, and the joint turns to point at it. Applied after og.IkChain and og.LookAt, top joint first; put it on its own entity (a tail, an ear, a strand of hair, a single jiggling node), one per chain. Deterministic under the fixed tick; the tails' positions and velocities are world state (the `og.anim` state block), so a restore continues a swing exactly. A changed chain (another skeleton, length or space) restarts at the animated pose.
23865
+ */
23866
+ const SpringBone: ComponentType<{ readonly skeleton: FieldSpec<"Entity">; readonly joint: FieldSpec<"u32">; readonly bones: FieldSpec<"u32">; readonly frequency: FieldSpec<"f32">; readonly damping: FieldSpec<"f32">; readonly tipFrequency: FieldSpec<"f32">; readonly tipDamping: FieldSpec<"f32">; readonly gravity: FieldSpec<"Vector3">; readonly space: FieldSpec<"SpringSpace">; readonly weight: FieldSpec<"f32">; readonly radius: FieldSpec<"f32">; readonly colliders: FieldSpec<"u32">; readonly lag: FieldSpec<"f32"> }, SpringBone>;
23867
+ /**
23868
+ * A collider spring bones are kept out of, three-vrm's VRMSpringBoneCollider: a sphere or a capsule riding on a joint of a skeleton (a head, a chest, an upper arm), so hair, ears and tails do not swing through the body. Each tick, after a tail of an og.SpringBone of the same skeleton has stepped and before its joint turns, the tail is pushed out of every collider whose `layers` meet the spring's `colliders` (in query order) to `radius` plus the spring's `radius`, keeping its bone's length. Put it on its own entity, one per shape; colliders follow the pose as it is when a chain is swung, so one on a joint an earlier chain swung follows that swing.
23869
+ */
23870
+ const SpringCollider: ComponentType<{ readonly skeleton: FieldSpec<"Entity">; readonly joint: FieldSpec<"u32">; readonly shape: FieldSpec<"SpringColliderShape">; readonly offset: FieldSpec<"Vector3">; readonly tail: FieldSpec<"Vector3">; readonly radius: FieldSpec<"f32">; readonly layers: FieldSpec<"u32"> }, SpringCollider>;
22327
23871
  /**
22328
23872
  * A named marker of a clip that playback passed in the last tick (read in the tick after it fired, like every event). Cross-fades and blends fire every contributing clip's markers.
22329
23873
  */
@@ -22341,9 +23885,9 @@ export declare namespace og {
22341
23885
  * Plays a clip of a 2D rig at the entity: the og.skeleton2d system advances it by scaled time (Time.scaledDt) after the game's systems and fires its events as og.Skeleton2DEvent; extraction draws its slots, in their order, as textured triangles of the sprite batch at `layer` (region attachments as quads, mesh attachments weighted to bones and deformed by the clip), lit by og.Lighting2D when the layer is in its range, as a sprite there is. The rig's pixels are `unit` to a world unit and +y is up; the entity's og.Transform places, turns (about z) and scales it.
22342
23886
  * Changing `clip` restarts at 0 (or at `time`, written in the same tick); writing a different time is a seek and fires no events. The pose is a function of these fields, the Transform and the og.IkTarget2D on it; the playback position is world state (the og.skeleton2d state block).
22343
23887
  */
22344
- const Skeleton2D: ComponentType<{ readonly rig: FieldSpec<"Rig2D">; readonly clip: FieldSpec<"u32">; readonly time: FieldSpec<"f32">; readonly speed: FieldSpec<"f32">; readonly loop: FieldSpec<"bool">; readonly flipX: FieldSpec<"bool">; readonly layer: FieldSpec<"i32">; readonly finished: FieldSpec<"bool"> }, Skeleton2D>;
23888
+ const Skeleton2D: ComponentType<{ readonly rig: FieldSpec<"Rig2D">; readonly clip: FieldSpec<"u32">; readonly time: FieldSpec<"f32">; readonly speed: FieldSpec<"f32">; readonly loop: FieldSpec<"bool">; readonly flipX: FieldSpec<"bool">; readonly layer: FieldSpec<"i32">; readonly skin: FieldSpec<"u32">; readonly finished: FieldSpec<"bool"> }, Skeleton2D>;
22345
23889
  /**
22346
- * A 2D skeleton's clip passed one of its events (`event 0.2 "step"` in the rig) in the last tick: footsteps, the frame a swing lands. Read in the tick after, like every event; a clip started at 0 fires its events at 0, a looping clip fires each once per pass.
23890
+ * A 2D skeleton's clip, or the clip a child armature in one of its slots plays, passed one of its events (`event 0.2 "step"` in the rig) in the last tick: footsteps, the frame a swing lands. Read in the tick after, like every event; a clip started at 0 fires its events at 0, a looping clip fires each once per pass.
22347
23891
  */
22348
23892
  const Skeleton2DEvent: EventType<Skeleton2DEvent>;
22349
23893
  /**
@@ -22373,13 +23917,21 @@ export declare namespace og {
22373
23917
  */
22374
23918
  function humanoid(world: World, desc?: HumanoidDesc): Result<Humanoid>;
22375
23919
  /**
22376
- * A new clip for `target` from a clip of `source`: each animated humanoid bone turns as the source's does from its rest pose (after a rest correction, so a T-pose drives an A-pose and other bone frames agree), the target keeps its bone lengths, the hips travel the source's distance scaled by the leg ratio (root motion kept, hip height scaled), and with footIk the feet land where the source's do, scaled. Same name, duration and markers. The cook does the same for a model's `animation { library }` import setting; this is for clips chosen at run time.
23920
+ * A new clip for `target` from a clip of `source`: each animated humanoid bone turns as the source's does from its rest pose (after a rest correction, so a T-pose drives an A-pose and other bone frames agree; fingers turn from their hand, so a hand pose holds whatever the arm does), the target keeps its bone lengths, the hips travel the source's distance scaled by the leg ratio (root motion kept, hip height scaled), and with footIk the feet land where the source's do, scaled, on the ground each rig's `footHeight` names (else its rest pose's foot heights). The target's twist bones (unmapped nodes named `twist`, or Rigify's `DEF-….001`, on an upper or lower arm or leg) take a share of their segment's twist by how far along it they sit. Same name, duration and markers. The cook does the same for a model's `animation { library }` import setting; this is for clips chosen at run time.
22377
23921
  *
22378
23922
  * @param world The world whose animation owns the skeletons and the clip.
22379
23923
  * @param desc The clip, the two skeletons and their rigs.
22380
23924
  * @returns The new clip (what AnimationPlayer.clip takes). Refused for an unregistered clip, skeleton or rig, a skeleton without recognisable hips (name them in a `type rig` file), or a rig naming a missing node.
22381
23925
  */
22382
23926
  function retarget(world: World, desc?: RetargetDesc): Result<ClipInfo>;
23927
+ /**
23928
+ * A new clip that plays `clip` on the other side: every frame reflected in the skeleton's x = 0 plane, each node taking its counterpart's motion (a left swing becomes the right's), rotations moved in model space so left and right bone frames need not mirror each other, root motion's sideways travel and turns flipped. Assumes a symmetric rest pose; a sided node without a counterpart keeps its rest pose. Same name, duration and markers (markers keep their names). Mirroring twice gives the clip back. A clip known ahead needs no call: a graph's `clip` line with `mirror true` plays it mirrored, and the cook's `animation { mirror "<clip>" }` writes the mirrored clip into the model.
23929
+ *
23930
+ * @param world The world whose animation owns the skeleton and the clip.
23931
+ * @param desc The clip and its skeleton.
23932
+ * @returns The new clip (what AnimationPlayer.clip takes). Refused for an unregistered clip or skeleton.
23933
+ */
23934
+ function mirror(world: World, desc?: MirrorDesc): Result<ClipInfo>;
22383
23935
  /**
22384
23936
  * The index of a flipbook clip by name, for Flipbook.clip: `og.anim.clip(hero, "walk_down")`. -1 when the sheet has no such clip.
22385
23937
  *
@@ -22541,13 +24093,13 @@ export declare namespace og {
22541
24093
  * A sound an entity plays. Level-triggered: while `playing` is true it plays (inserting a source plays it), setting it false stops it, and a one-shot that reaches its end sets it back to false and sends og.SoundEnded.
22542
24094
  * A one-shot of F frames at rate R and pitch p started in tick S ends in tick S + ceil(F * tickRate / (R * p)) - 1. A despawned entity's voice is silenced without an event.
22543
24095
  */
22544
- const AudioSource: ComponentType<{ readonly sound: FieldSpec<"Sound">; readonly bus: FieldSpec<"AudioBus">; readonly volume: FieldSpec<"f32">; readonly pitch: FieldSpec<"f32">; readonly pan: FieldSpec<"f32">; readonly loop: FieldSpec<"bool">; readonly loopStart: FieldSpec<"f32">; readonly loopEnd: FieldSpec<"f32">; readonly spatial: FieldSpec<"bool">; readonly refDistance: FieldSpec<"f32">; readonly maxDistance: FieldSpec<"f32">; readonly rolloffFactor: FieldSpec<"f32">; readonly playing: FieldSpec<"bool">; readonly priority: FieldSpec<"u32">; readonly lowpass: FieldSpec<"f32">; readonly occlude: FieldSpec<"bool">; readonly distanceCutoff: FieldSpec<"f32">; readonly startAt: FieldSpec<"f64">; readonly startOffset: FieldSpec<"f64">; readonly fade: FieldSpec<"f32"> }, AudioSource>;
24096
+ const AudioSource: ComponentType<{ readonly sound: FieldSpec<"Sound">; readonly bus: FieldSpec<"AudioBus">; readonly volume: FieldSpec<"f32">; readonly pitch: FieldSpec<"f32">; readonly pan: FieldSpec<"f32">; readonly loop: FieldSpec<"bool">; readonly loopStart: FieldSpec<"f32">; readonly loopEnd: FieldSpec<"f32">; readonly spatial: FieldSpec<"bool">; readonly refDistance: FieldSpec<"f32">; readonly maxDistance: FieldSpec<"f32">; readonly rolloffFactor: FieldSpec<"f32">; readonly playing: FieldSpec<"bool">; readonly priority: FieldSpec<"u32">; readonly lowpass: FieldSpec<"f32">; readonly occlude: FieldSpec<"bool">; readonly distanceCutoff: FieldSpec<"f32">; readonly startAt: FieldSpec<"f64">; readonly startOffset: FieldSpec<"f64">; readonly fade: FieldSpec<"f32">; readonly dopplerFactor: FieldSpec<"f32">; readonly coneInnerAngle: FieldSpec<"f32">; readonly coneOuterAngle: FieldSpec<"f32">; readonly coneOuterGain: FieldSpec<"f32">; readonly virtualize: FieldSpec<"bool">; readonly retrigger: FieldSpec<"bool"> }, AudioSource>;
22545
24097
  /**
22546
24098
  * Where spatial sources are heard from: the entity's world transform (its og.Transform down og.Parent, so a listener under a camera rig hears from the rig), looking down its -Z with +X to the right. The first listener in query order is used.
22547
24099
  */
22548
- const AudioListener: ComponentType<{ readonly volume: FieldSpec<"f32"> }, AudioListener>;
24100
+ const AudioListener: ComponentType<{ readonly volume: FieldSpec<"f32">; readonly dopplerFactor: FieldSpec<"f32">; readonly panningModel: FieldSpec<"PanningModel"> }, AudioListener>;
22549
24101
  /** Bus volumes; master scales every bus. A change ramps over 256 frames in the mixer. */
22550
- const Audio: ResourceType<{ readonly master: FieldSpec<"f32">; readonly music: FieldSpec<"f32">; readonly sfx: FieldSpec<"f32">; readonly ui: FieldSpec<"f32">; readonly maxVoices: FieldSpec<"u32">; readonly occlusionGain: FieldSpec<"f32">; readonly occlusionCutoff: FieldSpec<"f32">; readonly reverbRoom: FieldSpec<"f32">; readonly reverbDamping: FieldSpec<"f32">; readonly outputLatency: FieldSpec<"f64"> }, Audio>;
24102
+ const Audio: ResourceType<{ readonly master: FieldSpec<"f32">; readonly music: FieldSpec<"f32">; readonly sfx: FieldSpec<"f32">; readonly ui: FieldSpec<"f32">; readonly maxVoices: FieldSpec<"u32">; readonly occlusionGain: FieldSpec<"f32">; readonly occlusionCutoff: FieldSpec<"f32">; readonly reverbRoom: FieldSpec<"f32">; readonly reverbDamping: FieldSpec<"f32">; readonly outputLatency: FieldSpec<"f64">; readonly speedOfSound: FieldSpec<"f32">; readonly resampler: FieldSpec<"AudioResampler"> }, Audio>;
22551
24103
  /**
22552
24104
  * A bus's insert effects: a high- and low-pass (12 dB/octave), a compressor, side-chain ducking by another bus, and a send to the shared reverb, whose return joins master. One entity per bus (the first in query order counts); without one a bus passes straight through.
22553
24105
  * Changes reach the mixer through the command stream, so they are deterministic and in the world hash; the PCM is the mixer's.
@@ -22574,6 +24126,7 @@ export declare namespace og {
22574
24126
  * Sound: inside the tick, the engine's og.audio system (after the game's systems and physics) turns AudioSource changes into a deterministic, time-stamped command stream; outside the tick the host's mixer renders it (an AudioWorklet on the web, the output device, a capture or a null sink natively).
22575
24127
  * The stream, not the PCM, is world state: snapshots, restore and the world hash cover it, and nothing a sink does reaches the world. Load sounds with og.load.sound; inserting a source plays it, setting `playing` false stops it, and a one-shot sets `playing` back to false when it ends.
22576
24128
  * Spatial gain and pan are computed in the tick from the source's world transform relative to the first AudioListener's (three.js convention: the listener looks down -Z, +X is right; with none, the origin looking down -Z). A source, listener or zone on a child entity is placed at its og.Transform composed down og.Parent, as og.MatrixWorld is: a sound on a child is heard where its parent carries it, a listener under a camera rig hears from the rig.
24129
+ * Propagation, all in the tick and so in the stream: a spatial source or listener that moves shifts the pitch (Doppler, from their tick velocities: AudioSource.dopplerFactor, AudioListener.dopplerFactor, Audio.speedOfSound), a source with a cone is turned down away from its +Z (coneInnerAngle, coneOuterAngle, coneOuterGain, as three.js's setDirectionalCone), and a listener whose panningModel is hrtf places sources for headphones (interaural delay and head shadow) instead of the stereo panner.
22577
24130
  */
22578
24131
  namespace audio {
22579
24132
  /**
@@ -23800,7 +25353,7 @@ export declare namespace og {
23800
25353
  const TerrainScatter: ComponentType<{ readonly data: FieldSpec<"TerrainData">; readonly geometry: FieldSpec<"Geometry">; readonly material: FieldSpec<"Material">; readonly layer: FieldSpec<"u32">; readonly density: FieldSpec<"f32">; readonly distance: FieldSpec<"f32">; readonly fade: FieldSpec<"f32">; readonly minScale: FieldSpec<"f32">; readonly maxScale: FieldSpec<"f32">; readonly align: FieldSpec<"f32">; readonly seed: FieldSpec<"u32"> }, TerrainScatter>;
23801
25354
  /**
23802
25355
  * Terrain (phase 2): a height field over a rectangle, cooked by `og cook` from a `type terrain` .ogt (a 16-bit grey PNG or an EXR heightmap, an optional control map, up to four layered materials with slope and altitude rules, their maps separate textures or layers of two texture arrays: `layers` and `layerNormals` with each layer's `albedoLayer` and `normalLayer`, two sampled textures instead of up to eight) into tiles; drawn as a geometry clipmap around the camera (nested levels by distance, no cracks) that casts and receives shadows under the fog; collided with as a height field; baked into navmeshes by a navmesh file's `terrain` entry.
23803
- * Load it with og.terrain.load, then place it: an og.Terrain on an entity draws it placed by the entity's world transform (centred on its position, turned and scaled with it), and an og.Collider of shape SHAPE_HEIGHTFIELD naming the TerrainInfo's geometry makes it solid. og.TerrainScatter grows grass, flowers or stones over a layer near the camera. og.terrain.sample answers the surface's height and normal anywhere (pass it the entity's position, quaternion and scale); og.terrain.edit raises, lowers, flattens, smooths or paints it at runtime, and og.terrain.setLayer retunes a layer. Edits are world state: a snapshot keeps them, the world hash covers them, and a restore brings the ground back as it was (rebuilt from the cook with the restored edits replayed, for the renderer, physics and sample alike).
25356
+ * Load it with og.terrain.load, then place it: an og.Terrain on an entity draws it placed by the entity's world transform (centred on its position, turned and scaled with it), and an og.Collider of shape SHAPE_HEIGHTFIELD naming the TerrainInfo's geometry makes it solid. og.TerrainScatter grows grass, flowers or stones over a layer near the camera. og.terrain.sample answers the surface's height and normal anywhere (pass it the entity's position, quaternion and scale); og.terrain.edit raises, lowers, flattens, smooths or paints it at runtime, and og.terrain.setLayer retunes a layer. Terrain is 3D: the 2D profile's publish and lanes modules leave it out (RenderCapabilities.world3d is false), where every call here answers a refusal naming that field. Edits are world state: a snapshot keeps them, the world hash covers them, and a restore brings the ground back as it was (rebuilt from the cook with the restored edits replayed, for the renderer, physics and sample alike).
23804
25357
  * Its tiles stream (phase 3): the cook stores the field as a pyramid of tiles, each compressed on its own, and every frame the renderer keeps on the GPU only the tiles the camera's clipmap wants, within each terrain's tile budget (16 MiB by default), decoded off the frame (a worker thread natively, the browser's DecompressionStream on the Web) a few at a time, the most needed first; until a tile arrives its area draws from the coarser level that holds it, then fades in. Nothing a tick reads depends on which tiles are resident (collision and og.terrain.sample read the whole field), so a run's world hash is the same streamed or not. The probe's `terrain_stream:resident` decodes every wanted tile before each frame instead (`terrain_stream:stream[:<MiB>]` streams again, within that budget), and `dump_stream`'s `terrain` gives the tiles resident, waiting, decoding and cached.
23805
25358
  */
23806
25359
  namespace terrain {