@zylem/game-lib 0.8.9 → 0.9.1

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 (69) hide show
  1. package/README.md +7 -1
  2. package/dist/api/game-lib.api.json +37952 -19547
  3. package/dist/api/game-lib.api.md +1302 -7
  4. package/dist/api/game-lib.d.ts +1696 -3
  5. package/dist/api/game-lib.typedoc.json +174596 -76562
  6. package/dist/audio.d.ts +193 -1
  7. package/dist/audio.js +1 -1
  8. package/dist/bridge.d.ts +17 -2
  9. package/dist/bridge.js +1 -1
  10. package/dist/catalog.js +1 -1
  11. package/dist/chunk-2PFNNGTV.js +1 -0
  12. package/dist/chunk-2XMG3NJS.js +1 -0
  13. package/dist/chunk-4CZZZCFB.js +9 -0
  14. package/dist/chunk-7CBJKE42.js +1 -0
  15. package/dist/{chunk-CBUQBP2U.js → chunk-BQRMYLYD.js} +1 -1
  16. package/dist/chunk-FZNEWOC5.js +1 -0
  17. package/dist/chunk-GPCSX3M6.js +1 -0
  18. package/dist/chunk-K3NNXZIJ.js +1 -0
  19. package/dist/{chunk-JNFFTNMH.js → chunk-KSEP7AUF.js} +1 -1
  20. package/dist/{chunk-7JSZEEAE.js → chunk-LI43BZQN.js} +1 -1
  21. package/dist/chunk-NVVLLWIM.js +1 -0
  22. package/dist/chunk-QGIYILYI.js +1 -0
  23. package/dist/chunk-SHDHPDOV.js +24 -0
  24. package/dist/chunk-STVEILJJ.js +1 -0
  25. package/dist/chunk-SWDNK4GG.js +1 -0
  26. package/dist/chunk-UUOPT2N4.js +1 -0
  27. package/dist/chunk-VMXSE3EC.js +0 -0
  28. package/dist/{chunk-EYDC2PMO.js → chunk-VSFULLND.js} +1 -1
  29. package/dist/chunk-YNX3Q3CL.js +1 -0
  30. package/dist/chunk-ZZO4CKRU.js +1 -0
  31. package/dist/cinematics.d.ts +279 -0
  32. package/dist/cinematics.js +1 -0
  33. package/dist/core.d.ts +124 -10
  34. package/dist/core.js +1 -1
  35. package/dist/cutscene-definition-C479fkei.d.ts +509 -0
  36. package/dist/debug.d.ts +1 -0
  37. package/dist/debug.js +1 -1
  38. package/dist/{entity-type-map-D6BeAdvg.d.ts → entity-type-map-CrsrKT8c.d.ts} +12 -3
  39. package/dist/entity.d.ts +2 -1
  40. package/dist/entity.js +1 -1
  41. package/dist/game-D8KTP3fD.d.ts +652 -0
  42. package/dist/game-default-JV3Q6JAL.js +1 -0
  43. package/dist/graphics.d.ts +1 -1
  44. package/dist/graphics.js +1 -1
  45. package/dist/public.d.ts +12 -6
  46. package/dist/public.js +1 -1
  47. package/dist/schema/cutscene.schema.json +782 -0
  48. package/dist/schema/song.schema.json +430 -0
  49. package/dist/schema.d.ts +2 -0
  50. package/dist/schema.js +1 -1
  51. package/dist/selection-bounds-BKmSo9aG.d.ts +50 -0
  52. package/dist/song-definition-rEKksP0B.d.ts +263 -0
  53. package/dist/song-player-7QPLFLAS.js +1 -0
  54. package/dist/{game-DyKbOeck.d.ts → stage-CAPlk_cN.d.ts} +146 -647
  55. package/dist/web-components.d.ts +5 -3
  56. package/dist/web-components.js +1 -1
  57. package/dist/{zylem-camera-DZTpPOiD.d.ts → zylem-camera-CYDtrVgi.d.ts} +134 -102
  58. package/package.json +11 -4
  59. package/dist/chunk-34MYRTRP.js +0 -9
  60. package/dist/chunk-AXJTUVGC.js +0 -24
  61. package/dist/chunk-BWOZF5YK.js +0 -1
  62. package/dist/chunk-EVMLNMGU.js +0 -1
  63. package/dist/chunk-G3TBBZUI.js +0 -1
  64. package/dist/chunk-J6KD2G6F.js +0 -1
  65. package/dist/chunk-X7T7QRYP.js +0 -1
  66. package/dist/chunk-YVWDCZNT.js +0 -1
  67. package/dist/chunk-ZRT3ZQVH.js +0 -1
  68. package/dist/game-default-6YXFFZ2Q.js +0 -1
  69. /package/dist/{chunk-MSCVL5OK.js → chunk-ELQN62PQ.js} +0 -0
@@ -22,6 +22,7 @@ import { BoundaryRicochet3DEntity } from '@zylem/behaviors';
22
22
  import { BoundaryRicochetCoordinator } from '@zylem/behaviors';
23
23
  import { BoundaryRicochetEntity } from '@zylem/behaviors';
24
24
  import { BoundaryRicochetUpdate } from '@zylem/behaviors';
25
+ import { Box3 } from 'three';
25
26
  import { BRIDGE_READY_EVENT } from '@zylem/bridge';
26
27
  import { BridgeChannel } from '@zylem/bridge';
27
28
  import { BridgeDebugTool } from '@zylem/bridge';
@@ -35,6 +36,7 @@ import { BridgeVec3 } from '@zylem/bridge';
35
36
  import { BufferGeometry } from 'three';
36
37
  import { BurstParticlePresetOptions } from '@zylem/behaviors';
37
38
  import { Camera } from 'three';
39
+ import { CameraPosePayload } from '@zylem/bridge';
38
40
  import { clamp } from 'three/tsl';
39
41
  import { Color } from 'three';
40
42
  import { ColorRepresentation } from 'three';
@@ -72,6 +74,10 @@ import { createTopDownMovementInputComponent } from '@zylem/behaviors';
72
74
  import { createTopDownMovementStateComponent } from '@zylem/behaviors';
73
75
  import { createTransformComponent } from '@zylem/behaviors';
74
76
  import { createTransformStore } from '@zylem/behaviors/core';
77
+ import { CutsceneLoadPayload } from '@zylem/bridge';
78
+ import { CutscenePlaybackState } from '@zylem/bridge';
79
+ import { CutsceneStatusPayload } from '@zylem/bridge';
80
+ import { CutsceneViewPayload } from '@zylem/bridge';
75
81
  import { defineBehavior } from '@zylem/behaviors';
76
82
  import { DefineBehaviorConfig } from '@zylem/behaviors';
77
83
  import { Destructible3DBehavior } from '@zylem/behaviors';
@@ -360,6 +366,7 @@ import { ThrusterState } from '@zylem/behaviors';
360
366
  import { ThrusterStateComponent } from '@zylem/behaviors';
361
367
  import { tickCooldowns } from '@zylem/behaviors';
362
368
  import { time } from 'three/tsl';
369
+ import * as ToneNs from 'tone';
363
370
  import { TopDownMovementBehavior } from '@zylem/behaviors';
364
371
  import { TopDownMovementBehaviorOptions } from '@zylem/behaviors';
365
372
  import { TopDownMovementComponent } from '@zylem/behaviors';
@@ -431,6 +438,12 @@ export declare interface Action {
431
438
  reset(): void;
432
439
  }
433
440
 
441
+ /**
442
+ * The active shot across every camera track. Tracks are prioritised in
443
+ * order, so a shot on the first camera track overrides one on the second.
444
+ */
445
+ export declare function activeShot(definition: CutsceneDefinition, time: number): CameraShot | undefined;
446
+
434
447
  export declare const ACTOR_TYPE: unique symbol;
435
448
 
436
449
  declare type ActorOptions = BaseNode | ZylemActorOptions;
@@ -545,6 +558,62 @@ export declare type AspectRatioValue = (typeof AspectRatio)[keyof typeof AspectR
545
558
 
546
559
  export { atan }
547
560
 
561
+ /**
562
+ * Tracks that actually make sound: when any track is soloed only the soloed,
563
+ * unmuted ones play; otherwise everything not muted.
564
+ */
565
+ export declare function audibleTrackIds(tracks: readonly SongTrack[]): Set<string>;
566
+
567
+ export declare type AudioClip = Static<typeof AudioClipSchema>;
568
+
569
+ export declare const AudioClipSchema: _sinclair_typebox.TObject<{
570
+ kind: _sinclair_typebox.TLiteral<"audio">;
571
+ id: _sinclair_typebox.TString;
572
+ trackId: _sinclair_typebox.TString;
573
+ name: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
574
+ /** URL of the audio file. */
575
+ url: _sinclair_typebox.TString;
576
+ /** Beats from the song start. */
577
+ start: _sinclair_typebox.TNumber;
578
+ /** Seconds trimmed from the start of the file. */
579
+ offset: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
580
+ /** Beats. */
581
+ length: _sinclair_typebox.TNumber;
582
+ /** Clip gain in dB. */
583
+ gain: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
584
+ }>;
585
+
586
+ export declare type AudioItem = Static<typeof AudioItemSchema>;
587
+
588
+ export declare const AudioItemSchema: _sinclair_typebox.TObject<{
589
+ id: _sinclair_typebox.TString;
590
+ time: _sinclair_typebox.TNumber;
591
+ kind: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"song">, _sinclair_typebox.TLiteral<"sfx">]>;
592
+ /** Song slug for `song`, asset URL for `sfx`. */
593
+ ref: _sinclair_typebox.TString;
594
+ loop: _sinclair_typebox.TBoolean;
595
+ /** Gain in dB. */
596
+ volume: _sinclair_typebox.TNumber;
597
+ }>;
598
+
599
+ export declare type AudioTrack = Static<typeof AudioTrackSchema>;
600
+
601
+ declare const AudioTrackSchema: _sinclair_typebox.TObject<{
602
+ kind: _sinclair_typebox.TLiteral<"audio">;
603
+ id: _sinclair_typebox.TString;
604
+ name: _sinclair_typebox.TString;
605
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
606
+ id: _sinclair_typebox.TString;
607
+ time: _sinclair_typebox.TNumber;
608
+ kind: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"song">, _sinclair_typebox.TLiteral<"sfx">]>;
609
+ /** Song slug for `song`, asset URL for `sfx`. */
610
+ ref: _sinclair_typebox.TString;
611
+ loop: _sinclair_typebox.TBoolean;
612
+ /** Gain in dB. */
613
+ volume: _sinclair_typebox.TNumber;
614
+ }>>;
615
+ }>;
616
+
548
617
  declare interface BaseCollisionOptions {
549
618
  /** Whether the body is static (fixed) or dynamic */
550
619
  static?: boolean;
@@ -674,6 +743,16 @@ declare type BaseNodeOptions<T = any> = BaseNode | Partial<T>;
674
743
 
675
744
  declare type BasicTypes = number | string | boolean;
676
745
 
746
+ /**
747
+ * Pure timing and scheduling math for songs. Everything here runs without
748
+ * an AudioContext so the player, the offline renderer and the editor agree
749
+ * on when things happen.
750
+ */
751
+ /** Quarter-note beats per bar: 4/4 → 4, 6/8 → 3, 3/4 → 3. */
752
+ export declare function beatsPerBar(signature: TimeSignature): number;
753
+
754
+ export declare function beatsToSeconds(beats: number, bpm: number): number;
755
+
677
756
  export { BehaviorDescriptor }
678
757
 
679
758
  export { BehaviorHandle }
@@ -850,6 +929,27 @@ export declare interface CameraFeedOptions {
850
929
  height?: number;
851
930
  }
852
931
 
932
+ export declare type CameraKeyframe = Static<typeof CameraKeyframeSchema>;
933
+
934
+ export declare const CameraKeyframeSchema: _sinclair_typebox.TObject<{
935
+ id: _sinclair_typebox.TString;
936
+ /** Seconds from the cutscene start. */
937
+ time: _sinclair_typebox.TNumber;
938
+ position: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
939
+ x: _sinclair_typebox.TNumber;
940
+ y: _sinclair_typebox.TNumber;
941
+ z: _sinclair_typebox.TNumber;
942
+ }>>;
943
+ lookAt: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
944
+ x: _sinclair_typebox.TNumber;
945
+ y: _sinclair_typebox.TNumber;
946
+ z: _sinclair_typebox.TNumber;
947
+ }>>;
948
+ fov: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
949
+ /** Easing used to arrive at this keyframe from the previous one. */
950
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
951
+ }>;
952
+
853
953
  /**
854
954
  * CameraManager orchestrates multiple cameras per stage.
855
955
  *
@@ -1044,6 +1144,12 @@ export declare interface CameraOptions {
1044
1144
  */
1045
1145
  export declare interface CameraPerspective {
1046
1146
  id: string;
1147
+ /**
1148
+ * Projection the Three.js camera must use. When omitted, the runtime keeps
1149
+ * a perspective camera. Orthographic perspectives set this so a runtime
1150
+ * switch replaces the camera instance.
1151
+ */
1152
+ projection?: CameraProjection;
1047
1153
  /** Compute the raw desired pose for this frame given the current context. */
1048
1154
  getBasePose(ctx: CameraContext): CameraPose;
1049
1155
  /** Optional defaults for smoothing and other pipeline settings. */
@@ -1136,6 +1242,62 @@ export declare interface CameraPose {
1136
1242
  lookAt?: Vector3;
1137
1243
  }
1138
1244
 
1245
+ export declare type CameraPoseDef = Static<typeof CameraPoseDefSchema>;
1246
+
1247
+ declare const CameraPoseDefSchema: _sinclair_typebox.TObject<{
1248
+ position: _sinclair_typebox.TObject<{
1249
+ x: _sinclair_typebox.TNumber;
1250
+ y: _sinclair_typebox.TNumber;
1251
+ z: _sinclair_typebox.TNumber;
1252
+ }>;
1253
+ lookAt: _sinclair_typebox.TObject<{
1254
+ x: _sinclair_typebox.TNumber;
1255
+ y: _sinclair_typebox.TNumber;
1256
+ z: _sinclair_typebox.TNumber;
1257
+ }>;
1258
+ }>;
1259
+
1260
+ export { CameraPosePayload }
1261
+
1262
+ /** Which Three.js camera a perspective commits onto. */
1263
+ export declare type CameraProjection = 'perspective' | 'orthographic';
1264
+
1265
+ export declare type CameraShot = Static<typeof CameraShotSchema>;
1266
+
1267
+ export declare const CameraShotSchema: _sinclair_typebox.TObject<{
1268
+ id: _sinclair_typebox.TString;
1269
+ cameraId: _sinclair_typebox.TString;
1270
+ start: _sinclair_typebox.TNumber;
1271
+ end: _sinclair_typebox.TNumber;
1272
+ blend: _sinclair_typebox.TObject<{
1273
+ /** Seconds spent blending from the previous shot's camera; 0 is a hard cut. */
1274
+ duration: _sinclair_typebox.TNumber;
1275
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
1276
+ }>;
1277
+ }>;
1278
+
1279
+ export declare type CameraTrack = Static<typeof CameraTrackSchema>;
1280
+
1281
+ /** Camera tracks in priority order. */
1282
+ export declare function cameraTracks(definition: CutsceneDefinition): CameraTrack[];
1283
+
1284
+ declare const CameraTrackSchema: _sinclair_typebox.TObject<{
1285
+ kind: _sinclair_typebox.TLiteral<"camera">;
1286
+ id: _sinclair_typebox.TString;
1287
+ name: _sinclair_typebox.TString;
1288
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
1289
+ id: _sinclair_typebox.TString;
1290
+ cameraId: _sinclair_typebox.TString;
1291
+ start: _sinclair_typebox.TNumber;
1292
+ end: _sinclair_typebox.TNumber;
1293
+ blend: _sinclair_typebox.TObject<{
1294
+ /** Seconds spent blending from the previous shot's camera; 0 is a hard cut. */
1295
+ duration: _sinclair_typebox.TNumber;
1296
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
1297
+ }>;
1298
+ }>>;
1299
+ }>;
1300
+
1139
1301
  /**
1140
1302
  * CameraWrapper is the user-facing camera handle returned by createCamera().
1141
1303
  * It provides convenience methods for target management, orbital controls,
@@ -1239,6 +1401,9 @@ declare interface CleanupFunction<T, TGlobals extends GlobalRecord = any> {
1239
1401
  */
1240
1402
  export declare function clearGlobalSubscriptions(): void;
1241
1403
 
1404
+ /** Clips whose window covers `beat` on a track. */
1405
+ export declare function clipsAt(song: SongDefinition, trackId: string, beat: number): Array<NoteClip | AudioClip>;
1406
+
1242
1407
  /**
1243
1408
  * Closest point along an infinite line to a ray, as a distance along the line.
1244
1409
  *
@@ -1495,6 +1660,19 @@ export declare function createCone(...args: Array<ConeOptions>): ZylemCone;
1495
1660
  */
1496
1661
  export declare function createCooldownIcon(...args: Array<CooldownIconOptions>): ZylemCooldownIcon;
1497
1662
 
1663
+ /**
1664
+ * Plays a cutscene against a live stage: drives the camera through a
1665
+ * pipeline behavior, fires event/audio items as the playhead crosses them,
1666
+ * and runs scene transitions through the renderer.
1667
+ *
1668
+ * ```ts
1669
+ * const player = createCutscenePlayer(INTRO_CUTSCENE, { host: createStageCutsceneHost(stage) });
1670
+ * player.on('complete', () => player.dispose());
1671
+ * player.play();
1672
+ * ```
1673
+ */
1674
+ export declare function createCutscenePlayer(initial: CutsceneDefinition, options: CutscenePlayerOptions): CutscenePlayer;
1675
+
1498
1676
  /**
1499
1677
  * Create a cylinder entity.
1500
1678
  * @param args Options or child nodes
@@ -1599,6 +1777,12 @@ declare interface CreateGameEntityOptions<T extends GameEntity<any>, CreateOptio
1599
1777
  */
1600
1778
  export declare function createGlobal<T>(path: string, defaultValue: T): T;
1601
1779
 
1780
+ /**
1781
+ * Builds the synth and effects chain for an instrument definition. The
1782
+ * returned `output` is not connected anywhere; the caller routes it.
1783
+ */
1784
+ export declare function createInstrument(Tone: ToneModule, def: InstrumentDefinition): Instrument;
1785
+
1602
1786
  export { createJumpConfig2D }
1603
1787
 
1604
1788
  export { createJumpConfig3D }
@@ -1669,6 +1853,17 @@ export { createPlatformer3DMovementComponent }
1669
1853
 
1670
1854
  export { createPlatformer3DStateComponent }
1671
1855
 
1856
+ /**
1857
+ * Follow a target with per-axis delay or platform settling.
1858
+ *
1859
+ * Shifts `position` and `lookAt` by the same delta, so the perspective's
1860
+ * offset stays intact and the framed point becomes the filtered focus.
1861
+ *
1862
+ * "On a platform" is inferred from the axis going quiet. Games do not have
1863
+ * to supply a grounded flag.
1864
+ */
1865
+ export declare function createPlatformFollow(options?: PlatformFollowOptions): CameraBehavior;
1866
+
1672
1867
  /**
1673
1868
  * Create a pyramid entity.
1674
1869
  * @param args Options or child nodes
@@ -1681,6 +1876,13 @@ export { createShooter2DStateComponent }
1681
1876
 
1682
1877
  export { createSimulation }
1683
1878
 
1879
+ /**
1880
+ * Plays a song on Tone.js's transport. The transport is shared, so creating
1881
+ * a player disposes the previous one: one song plays at a time. Tone.js is
1882
+ * loaded lazily; the first `play()` must follow a user gesture.
1883
+ */
1884
+ export declare function createSongPlayer(definition: SongDefinition, options?: SongPlayerOptions): SongPlayer;
1885
+
1684
1886
  export declare function createSphere(...args: Array<SphereOptions>): ZylemSphere;
1685
1887
 
1686
1888
  export declare function createSprite(...args: Array<SpriteOptions>): ZylemSprite;
@@ -1690,6 +1892,18 @@ export declare function createSprite(...args: Array<SpriteOptions>): ZylemSprite
1690
1892
  */
1691
1893
  export declare function createStage(...options: StageOptions): Stage;
1692
1894
 
1895
+ export declare function createStageCutsceneHost(stageLike: CutsceneStageLike, options?: StageCutsceneHostOptions): CutsceneHost;
1896
+
1897
+ /**
1898
+ * StarCraft-style pan on the XZ plane.
1899
+ *
1900
+ * The perspective (top-down or isometric) owns the angle. This behavior only
1901
+ * slides the framed point: edge scroll, arrow or stick pan, and an optional
1902
+ * follow target. Screen up maps to world −Z, which matches a top-down camera
1903
+ * whose up vector is −Z.
1904
+ */
1905
+ export declare function createStrategyPan(options?: StrategyPanOptions): StrategyPanBehavior;
1906
+
1693
1907
  export declare function createText(...args: Array<TextOptions>): ZylemText;
1694
1908
 
1695
1909
  export { createThrusterInputComponent }
@@ -1721,6 +1935,509 @@ export declare function createZone(...args: Array<ZoneOptions>): ZylemZone;
1721
1935
  /** Default blend: plain crossfade between the two frames. */
1722
1936
  export declare const crossfadeTransitionShader: ZylemTransitionShader;
1723
1937
 
1938
+ /** Pipeline key the cutscene player registers its behavior under. */
1939
+ export declare const CUTSCENE_BEHAVIOR_KEY = "cutscene";
1940
+
1941
+ export declare type CutsceneCamera = Static<typeof CutsceneCameraSchema>;
1942
+
1943
+ /**
1944
+ * Camera behavior that hands the pipeline a fixed pose each frame while a
1945
+ * cutscene is playing. It runs after the game's own behaviors (high
1946
+ * priority) so shots override follow/look-at logic, and it disables itself
1947
+ * when the player has no pose (no active shot) so gameplay framing resumes.
1948
+ *
1949
+ * `damping` applies optional per-frame smoothing for follow cameras; the
1950
+ * player passes 0 for authored moves so keyframes land exactly.
1951
+ */
1952
+ export declare class CutsceneCameraBehavior implements CameraBehavior {
1953
+ priority: number;
1954
+ enabled: boolean;
1955
+ private target;
1956
+ private smoothed;
1957
+ private damping;
1958
+ /** Sets the pose to show; `null` releases the camera back to gameplay. */
1959
+ setPose(pose: EvaluatedPose | null, damping?: number): void;
1960
+ /** Snap smoothing state so the next frame lands exactly on the pose (seeks, cuts). */
1961
+ snap(): void;
1962
+ onDetach(): void;
1963
+ update(ctx: CameraContext, pose: CameraPose): CameraPose;
1964
+ }
1965
+
1966
+ export declare type CutsceneCameraKind = Static<typeof CutsceneCameraKindSchema>;
1967
+
1968
+ declare const CutsceneCameraKindSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"static">, _sinclair_typebox.TLiteral<"dolly">, _sinclair_typebox.TLiteral<"follow">]>;
1969
+
1970
+ export declare const CutsceneCameraSchema: _sinclair_typebox.TObject<{
1971
+ id: _sinclair_typebox.TString;
1972
+ name: _sinclair_typebox.TString;
1973
+ kind: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"static">, _sinclair_typebox.TLiteral<"dolly">, _sinclair_typebox.TLiteral<"follow">]>;
1974
+ /** Vertical field of view in degrees. */
1975
+ fov: _sinclair_typebox.TNumber;
1976
+ /** Base pose; `static` cameras hold it, keyframes and dollies start from it. */
1977
+ pose: _sinclair_typebox.TObject<{
1978
+ position: _sinclair_typebox.TObject<{
1979
+ x: _sinclair_typebox.TNumber;
1980
+ y: _sinclair_typebox.TNumber;
1981
+ z: _sinclair_typebox.TNumber;
1982
+ }>;
1983
+ lookAt: _sinclair_typebox.TObject<{
1984
+ x: _sinclair_typebox.TNumber;
1985
+ y: _sinclair_typebox.TNumber;
1986
+ z: _sinclair_typebox.TNumber;
1987
+ }>;
1988
+ }>;
1989
+ /** `dolly` cameras ride this path over each shot. */
1990
+ dollyId: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
1991
+ /** Progress curve along the dolly path (0 → 1 over the shot). */
1992
+ dollyEasing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
1993
+ /** Entity name a `follow` camera tracks, and what a dolly looks at when set. */
1994
+ target: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
1995
+ /** Offset from the target for `follow` cameras. */
1996
+ offset: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
1997
+ x: _sinclair_typebox.TNumber;
1998
+ y: _sinclair_typebox.TNumber;
1999
+ z: _sinclair_typebox.TNumber;
2000
+ }>>;
2001
+ /** Smoothing for `follow` cameras, 0 (instant) … 1 (very slow). */
2002
+ damping: _sinclair_typebox.TNumber;
2003
+ keyframes: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2004
+ id: _sinclair_typebox.TString;
2005
+ /** Seconds from the cutscene start. */
2006
+ time: _sinclair_typebox.TNumber;
2007
+ position: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
2008
+ x: _sinclair_typebox.TNumber;
2009
+ y: _sinclair_typebox.TNumber;
2010
+ z: _sinclair_typebox.TNumber;
2011
+ }>>;
2012
+ lookAt: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
2013
+ x: _sinclair_typebox.TNumber;
2014
+ y: _sinclair_typebox.TNumber;
2015
+ z: _sinclair_typebox.TNumber;
2016
+ }>>;
2017
+ fov: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
2018
+ /** Easing used to arrive at this keyframe from the previous one. */
2019
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
2020
+ }>>;
2021
+ }>;
2022
+
2023
+ export declare type CutsceneDefinition = Static<typeof CutsceneDefinitionSchema>;
2024
+
2025
+ export declare const CutsceneDefinitionSchema: _sinclair_typebox.TObject<{
2026
+ id: _sinclair_typebox.TString;
2027
+ name: _sinclair_typebox.TString;
2028
+ /** Seconds. */
2029
+ duration: _sinclair_typebox.TNumber;
2030
+ /** Stage the cutscene was authored against; informational. */
2031
+ stage: _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNull]>;
2032
+ skippable: _sinclair_typebox.TBoolean;
2033
+ scenes: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2034
+ id: _sinclair_typebox.TString;
2035
+ name: _sinclair_typebox.TString;
2036
+ /** Seconds from the cutscene start. */
2037
+ start: _sinclair_typebox.TNumber;
2038
+ end: _sinclair_typebox.TNumber;
2039
+ /** How the picture arrives at this scene's start. */
2040
+ transitionIn: _sinclair_typebox.TObject<{
2041
+ type: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"cut">, _sinclair_typebox.TLiteral<"fade">, _sinclair_typebox.TLiteral<"wipe">, _sinclair_typebox.TLiteral<"radial">, _sinclair_typebox.TLiteral<"noise">, _sinclair_typebox.TLiteral<"cells">]>;
2042
+ /** Seconds; ignored for `cut`. */
2043
+ duration: _sinclair_typebox.TNumber;
2044
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
2045
+ }>;
2046
+ }>>;
2047
+ cameras: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2048
+ id: _sinclair_typebox.TString;
2049
+ name: _sinclair_typebox.TString;
2050
+ kind: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"static">, _sinclair_typebox.TLiteral<"dolly">, _sinclair_typebox.TLiteral<"follow">]>;
2051
+ /** Vertical field of view in degrees. */
2052
+ fov: _sinclair_typebox.TNumber;
2053
+ /** Base pose; `static` cameras hold it, keyframes and dollies start from it. */
2054
+ pose: _sinclair_typebox.TObject<{
2055
+ position: _sinclair_typebox.TObject<{
2056
+ x: _sinclair_typebox.TNumber;
2057
+ y: _sinclair_typebox.TNumber;
2058
+ z: _sinclair_typebox.TNumber;
2059
+ }>;
2060
+ lookAt: _sinclair_typebox.TObject<{
2061
+ x: _sinclair_typebox.TNumber;
2062
+ y: _sinclair_typebox.TNumber;
2063
+ z: _sinclair_typebox.TNumber;
2064
+ }>;
2065
+ }>;
2066
+ /** `dolly` cameras ride this path over each shot. */
2067
+ dollyId: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
2068
+ /** Progress curve along the dolly path (0 → 1 over the shot). */
2069
+ dollyEasing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
2070
+ /** Entity name a `follow` camera tracks, and what a dolly looks at when set. */
2071
+ target: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
2072
+ /** Offset from the target for `follow` cameras. */
2073
+ offset: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
2074
+ x: _sinclair_typebox.TNumber;
2075
+ y: _sinclair_typebox.TNumber;
2076
+ z: _sinclair_typebox.TNumber;
2077
+ }>>;
2078
+ /** Smoothing for `follow` cameras, 0 (instant) … 1 (very slow). */
2079
+ damping: _sinclair_typebox.TNumber;
2080
+ keyframes: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2081
+ id: _sinclair_typebox.TString;
2082
+ /** Seconds from the cutscene start. */
2083
+ time: _sinclair_typebox.TNumber;
2084
+ position: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
2085
+ x: _sinclair_typebox.TNumber;
2086
+ y: _sinclair_typebox.TNumber;
2087
+ z: _sinclair_typebox.TNumber;
2088
+ }>>;
2089
+ lookAt: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
2090
+ x: _sinclair_typebox.TNumber;
2091
+ y: _sinclair_typebox.TNumber;
2092
+ z: _sinclair_typebox.TNumber;
2093
+ }>>;
2094
+ fov: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
2095
+ /** Easing used to arrive at this keyframe from the previous one. */
2096
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
2097
+ }>>;
2098
+ }>>;
2099
+ dollies: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2100
+ id: _sinclair_typebox.TString;
2101
+ name: _sinclair_typebox.TString;
2102
+ points: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2103
+ x: _sinclair_typebox.TNumber;
2104
+ y: _sinclair_typebox.TNumber;
2105
+ z: _sinclair_typebox.TNumber;
2106
+ }>>;
2107
+ closed: _sinclair_typebox.TBoolean;
2108
+ /** Catmull-Rom tension; 0.5 is centripetal. */
2109
+ tension: _sinclair_typebox.TNumber;
2110
+ }>>;
2111
+ tracks: _sinclair_typebox.TArray<_sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
2112
+ kind: _sinclair_typebox.TLiteral<"camera">;
2113
+ id: _sinclair_typebox.TString;
2114
+ name: _sinclair_typebox.TString;
2115
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2116
+ id: _sinclair_typebox.TString;
2117
+ cameraId: _sinclair_typebox.TString;
2118
+ start: _sinclair_typebox.TNumber;
2119
+ end: _sinclair_typebox.TNumber;
2120
+ blend: _sinclair_typebox.TObject<{
2121
+ /** Seconds spent blending from the previous shot's camera; 0 is a hard cut. */
2122
+ duration: _sinclair_typebox.TNumber;
2123
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
2124
+ }>;
2125
+ }>>;
2126
+ }>, _sinclair_typebox.TObject<{
2127
+ kind: _sinclair_typebox.TLiteral<"event">;
2128
+ id: _sinclair_typebox.TString;
2129
+ name: _sinclair_typebox.TString;
2130
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2131
+ id: _sinclair_typebox.TString;
2132
+ time: _sinclair_typebox.TNumber;
2133
+ event: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
2134
+ type: _sinclair_typebox.TLiteral<"emit">;
2135
+ /** Stage event name. */
2136
+ name: _sinclair_typebox.TString;
2137
+ payload: _sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>>;
2138
+ }>, _sinclair_typebox.TObject<{
2139
+ type: _sinclair_typebox.TLiteral<"playAnimation">;
2140
+ /** Entity name. */
2141
+ entity: _sinclair_typebox.TString;
2142
+ /** Animation key as passed to `playAnimation({ key })`. */
2143
+ key: _sinclair_typebox.TString;
2144
+ }>, _sinclair_typebox.TObject<{
2145
+ type: _sinclair_typebox.TLiteral<"playSong">;
2146
+ /** Song slug or URL; resolved by the host. */
2147
+ song: _sinclair_typebox.TString;
2148
+ loop: _sinclair_typebox.TBoolean;
2149
+ }>, _sinclair_typebox.TObject<{
2150
+ type: _sinclair_typebox.TLiteral<"stopSong">;
2151
+ song: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
2152
+ }>, _sinclair_typebox.TObject<{
2153
+ type: _sinclair_typebox.TLiteral<"setVariable">;
2154
+ name: _sinclair_typebox.TString;
2155
+ value: _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>;
2156
+ }>]>;
2157
+ }>>;
2158
+ }>, _sinclair_typebox.TObject<{
2159
+ kind: _sinclair_typebox.TLiteral<"audio">;
2160
+ id: _sinclair_typebox.TString;
2161
+ name: _sinclair_typebox.TString;
2162
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2163
+ id: _sinclair_typebox.TString;
2164
+ time: _sinclair_typebox.TNumber;
2165
+ kind: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"song">, _sinclair_typebox.TLiteral<"sfx">]>;
2166
+ /** Song slug for `song`, asset URL for `sfx`. */
2167
+ ref: _sinclair_typebox.TString;
2168
+ loop: _sinclair_typebox.TBoolean;
2169
+ /** Gain in dB. */
2170
+ volume: _sinclair_typebox.TNumber;
2171
+ }>>;
2172
+ }>]>>;
2173
+ }>;
2174
+
2175
+ export declare type CutsceneEasing = Static<typeof CutsceneEasingSchema>;
2176
+
2177
+ declare const CutsceneEasingSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
2178
+
2179
+ export declare type CutsceneEvent = Static<typeof CutsceneEventSchema>;
2180
+
2181
+ export declare const CutsceneEventSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
2182
+ type: _sinclair_typebox.TLiteral<"emit">;
2183
+ /** Stage event name. */
2184
+ name: _sinclair_typebox.TString;
2185
+ payload: _sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>>;
2186
+ }>, _sinclair_typebox.TObject<{
2187
+ type: _sinclair_typebox.TLiteral<"playAnimation">;
2188
+ /** Entity name. */
2189
+ entity: _sinclair_typebox.TString;
2190
+ /** Animation key as passed to `playAnimation({ key })`. */
2191
+ key: _sinclair_typebox.TString;
2192
+ }>, _sinclair_typebox.TObject<{
2193
+ type: _sinclair_typebox.TLiteral<"playSong">;
2194
+ /** Song slug or URL; resolved by the host. */
2195
+ song: _sinclair_typebox.TString;
2196
+ loop: _sinclair_typebox.TBoolean;
2197
+ }>, _sinclair_typebox.TObject<{
2198
+ type: _sinclair_typebox.TLiteral<"stopSong">;
2199
+ song: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
2200
+ }>, _sinclair_typebox.TObject<{
2201
+ type: _sinclair_typebox.TLiteral<"setVariable">;
2202
+ name: _sinclair_typebox.TString;
2203
+ value: _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>;
2204
+ }>]>;
2205
+
2206
+ export declare interface CutsceneFrame {
2207
+ scene: CutsceneScene | undefined;
2208
+ shot: CameraShot | undefined;
2209
+ camera: CutsceneCamera | undefined;
2210
+ pose: EvaluatedPose | undefined;
2211
+ /** 0…1 while blending in from the previous shot, else 1. */
2212
+ blend: number;
2213
+ }
2214
+
2215
+ /**
2216
+ * What the player needs from the running game. `createStageCutsceneHost`
2217
+ * builds one from a live stage; tests and the editor can hand in stubs.
2218
+ */
2219
+ export declare interface CutsceneHost {
2220
+ /** The camera the cutscene drives; resolved each frame so stage swaps are safe. */
2221
+ camera: () => ZylemCamera | null;
2222
+ /** World position of a named entity, for follow cameras and dolly look-ats. */
2223
+ entityPosition?: (name: string) => Vec3Def | undefined;
2224
+ playAnimation?: (entity: string, key: string) => void;
2225
+ /** Stage event dispatch (`emit` events). */
2226
+ dispatch?: (name: string, payload: Record<string, unknown>) => void;
2227
+ setVariable?: (name: string, value: unknown) => void;
2228
+ playSong?: (ref: string, options: {
2229
+ loop: boolean;
2230
+ volume: number;
2231
+ }) => void;
2232
+ stopSong?: (ref?: string) => void;
2233
+ playSfx?: (url: string, options: {
2234
+ volume: number;
2235
+ loop: boolean;
2236
+ }) => void;
2237
+ /**
2238
+ * Runs a picture transition into the new scene: snapshot the current frame
2239
+ * and blend it into the frames that follow. Omit to hard-cut everywhere.
2240
+ */
2241
+ beginTransition?: (transition: SceneTransition, shader: ZylemTransitionShader | undefined) => void;
2242
+ }
2243
+
2244
+ /** Total length: the declared duration, or the furthest scene end if longer. */
2245
+ export declare function cutsceneLength(definition: Pick<CutsceneDefinition, 'duration' | 'scenes'>): number;
2246
+
2247
+ export { CutsceneLoadPayload }
2248
+
2249
+ export { CutscenePlaybackState }
2250
+
2251
+ export declare interface CutscenePlayer {
2252
+ readonly definition: CutsceneDefinition;
2253
+ readonly state: CutscenePlayerState;
2254
+ /** Seconds. */
2255
+ readonly time: number;
2256
+ readonly length: number;
2257
+ /** The pose the picture shows right now, if a shot is active. */
2258
+ readonly pose: EvaluatedPose | undefined;
2259
+ play(from?: number): void;
2260
+ pause(): void;
2261
+ /** Stops, rewinds, and returns the camera to gameplay. */
2262
+ stop(): void;
2263
+ seek(time: number): void;
2264
+ /** Jumps to the end (when `skippable`) and completes. */
2265
+ skip(): boolean;
2266
+ /** Advances by `dt` seconds; only needed with `tick: 'manual'`. */
2267
+ update(dt: number): void;
2268
+ /** Swaps the definition in place, keeping time and state (live editing). */
2269
+ setDefinition(definition: CutsceneDefinition): void;
2270
+ on<K extends keyof CutscenePlayerEvents>(event: K, handler: CutscenePlayerEvents[K]): () => void;
2271
+ dispose(): void;
2272
+ }
2273
+
2274
+ export declare interface CutscenePlayerEvents {
2275
+ time: (time: number) => void;
2276
+ state: (state: CutscenePlayerState) => void;
2277
+ scene: (scene: CutsceneScene | undefined) => void;
2278
+ shot: (shot: CameraShot | undefined) => void;
2279
+ event: (item: EventItem) => void;
2280
+ audio: (item: AudioItem) => void;
2281
+ complete: () => void;
2282
+ skip: () => void;
2283
+ }
2284
+
2285
+ export declare interface CutscenePlayerOptions {
2286
+ host: CutsceneHost;
2287
+ /**
2288
+ * `auto` (default) advances on `requestAnimationFrame`; `manual` leaves it
2289
+ * to the caller's `update(dt)` — e.g. a stage `update` hook, so the
2290
+ * cutscene pauses with the game.
2291
+ */
2292
+ tick?: 'auto' | 'manual';
2293
+ /** Maps a transition type to a blend shader (e.g. `createStageTransition({ pattern }).shader`). */
2294
+ transitionShader?: (type: SceneTransitionType) => ZylemTransitionShader | undefined;
2295
+ /** Fire events/audio crossed by a `seek`. Off by default: scrubbing should not trigger gameplay. */
2296
+ fireEventsOnSeek?: boolean;
2297
+ timeScale?: number;
2298
+ }
2299
+
2300
+ export declare type CutscenePlayerState = 'idle' | 'playing' | 'paused' | 'finished';
2301
+
2302
+ /**
2303
+ * Editor preview of a cutscene inside the running game: answers the bridge's
2304
+ * `cutscene:*` commands with a player bound to the current stage and reports
2305
+ * progress back. Owned by `ZylemGame`; Director mode drives it.
2306
+ */
2307
+ export declare class CutscenePreviewController {
2308
+ private readonly getStage;
2309
+ private readonly publish;
2310
+ private readonly hostOptions;
2311
+ private readonly publishView?;
2312
+ private player;
2313
+ private lastStatus;
2314
+ /** A load that arrived before the stage existed; replayed by `stageReady()`. */
2315
+ private pending;
2316
+ private readonly viewInverse;
2317
+ private readonly viewProjection;
2318
+ private lastView;
2319
+ constructor(getStage: () => ZylemStage | null, publish: (status: CutsceneStatusPayload) => void, hostOptions?: StageCutsceneHostOptions, publishView?: ((view: CutsceneViewPayload) => void) | undefined);
2320
+ get active(): boolean;
2321
+ /**
2322
+ * The game reports itself running before its first stage finishes loading,
2323
+ * so an editor that loads a cutscene straight away would find no stage.
2324
+ * The game calls this once a stage is up; a held load runs then.
2325
+ */
2326
+ stageReady(): void;
2327
+ load(payload: CutsceneLoadPayload): void;
2328
+ play(from?: number): void;
2329
+ pause(): void;
2330
+ stop(): void;
2331
+ seek(time: number): void;
2332
+ /** Drops the player because its stage is going away; a held load survives for the next stage. */
2333
+ releaseStage(): void;
2334
+ /**
2335
+ * Once per rendered frame while a cutscene is loaded: publishes the
2336
+ * camera's projection and the canvas box when either changed, so the
2337
+ * editor's overlays track the view without polling.
2338
+ */
2339
+ frame(): void;
2340
+ unload(): void;
2341
+ /** The live camera as position + look-at, for "capture from viewport". */
2342
+ cameraPose(): Omit<CameraPosePayload, 'requestId'> | null;
2343
+ private report;
2344
+ }
2345
+
2346
+ export declare type CutsceneScene = Static<typeof CutsceneSceneSchema>;
2347
+
2348
+ export declare const CutsceneSceneSchema: _sinclair_typebox.TObject<{
2349
+ id: _sinclair_typebox.TString;
2350
+ name: _sinclair_typebox.TString;
2351
+ /** Seconds from the cutscene start. */
2352
+ start: _sinclair_typebox.TNumber;
2353
+ end: _sinclair_typebox.TNumber;
2354
+ /** How the picture arrives at this scene's start. */
2355
+ transitionIn: _sinclair_typebox.TObject<{
2356
+ type: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"cut">, _sinclair_typebox.TLiteral<"fade">, _sinclair_typebox.TLiteral<"wipe">, _sinclair_typebox.TLiteral<"radial">, _sinclair_typebox.TLiteral<"noise">, _sinclair_typebox.TLiteral<"cells">]>;
2357
+ /** Seconds; ignored for `cut`. */
2358
+ duration: _sinclair_typebox.TNumber;
2359
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
2360
+ }>;
2361
+ }>;
2362
+
2363
+ /**
2364
+ * A `CutsceneHost` bound to a live stage: drives the stage camera, resolves
2365
+ * entities by name, dispatches stage events, writes stage variables, plays
2366
+ * songs through `@zylem/game-lib/audio` (loaded on demand) and one-shots
2367
+ * through Howler, and runs scene transitions on the stage renderer.
2368
+ */
2369
+ /** What a stage-bound cutscene plays on: the public `Stage` wrapper or the internal stage. */
2370
+ export declare type CutsceneStageLike = ZylemStage | Stage;
2371
+
2372
+ export { CutsceneStatusPayload }
2373
+
2374
+ export declare type CutsceneTrack = Static<typeof CutsceneTrackSchema>;
2375
+
2376
+ export declare const CutsceneTrackSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
2377
+ kind: _sinclair_typebox.TLiteral<"camera">;
2378
+ id: _sinclair_typebox.TString;
2379
+ name: _sinclair_typebox.TString;
2380
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2381
+ id: _sinclair_typebox.TString;
2382
+ cameraId: _sinclair_typebox.TString;
2383
+ start: _sinclair_typebox.TNumber;
2384
+ end: _sinclair_typebox.TNumber;
2385
+ blend: _sinclair_typebox.TObject<{
2386
+ /** Seconds spent blending from the previous shot's camera; 0 is a hard cut. */
2387
+ duration: _sinclair_typebox.TNumber;
2388
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
2389
+ }>;
2390
+ }>>;
2391
+ }>, _sinclair_typebox.TObject<{
2392
+ kind: _sinclair_typebox.TLiteral<"event">;
2393
+ id: _sinclair_typebox.TString;
2394
+ name: _sinclair_typebox.TString;
2395
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2396
+ id: _sinclair_typebox.TString;
2397
+ time: _sinclair_typebox.TNumber;
2398
+ event: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
2399
+ type: _sinclair_typebox.TLiteral<"emit">;
2400
+ /** Stage event name. */
2401
+ name: _sinclair_typebox.TString;
2402
+ payload: _sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>>;
2403
+ }>, _sinclair_typebox.TObject<{
2404
+ type: _sinclair_typebox.TLiteral<"playAnimation">;
2405
+ /** Entity name. */
2406
+ entity: _sinclair_typebox.TString;
2407
+ /** Animation key as passed to `playAnimation({ key })`. */
2408
+ key: _sinclair_typebox.TString;
2409
+ }>, _sinclair_typebox.TObject<{
2410
+ type: _sinclair_typebox.TLiteral<"playSong">;
2411
+ /** Song slug or URL; resolved by the host. */
2412
+ song: _sinclair_typebox.TString;
2413
+ loop: _sinclair_typebox.TBoolean;
2414
+ }>, _sinclair_typebox.TObject<{
2415
+ type: _sinclair_typebox.TLiteral<"stopSong">;
2416
+ song: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
2417
+ }>, _sinclair_typebox.TObject<{
2418
+ type: _sinclair_typebox.TLiteral<"setVariable">;
2419
+ name: _sinclair_typebox.TString;
2420
+ value: _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>;
2421
+ }>]>;
2422
+ }>>;
2423
+ }>, _sinclair_typebox.TObject<{
2424
+ kind: _sinclair_typebox.TLiteral<"audio">;
2425
+ id: _sinclair_typebox.TString;
2426
+ name: _sinclair_typebox.TString;
2427
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2428
+ id: _sinclair_typebox.TString;
2429
+ time: _sinclair_typebox.TNumber;
2430
+ kind: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"song">, _sinclair_typebox.TLiteral<"sfx">]>;
2431
+ /** Song slug for `song`, asset URL for `sfx`. */
2432
+ ref: _sinclair_typebox.TString;
2433
+ loop: _sinclair_typebox.TBoolean;
2434
+ /** Gain in dB. */
2435
+ volume: _sinclair_typebox.TNumber;
2436
+ }>>;
2437
+ }>]>;
2438
+
2439
+ export { CutsceneViewPayload }
2440
+
1724
2441
  export declare const CYLINDER_TYPE: unique symbol;
1725
2442
 
1726
2443
  /**
@@ -1755,6 +2472,8 @@ declare interface CylinderMeshOptions extends BaseMeshOptions {
1755
2472
 
1756
2473
  declare type CylinderOptions = BaseNode | Partial<ZylemCylinderOptions>;
1757
2474
 
2475
+ export declare function dbToGain(db: number): number;
2476
+
1758
2477
  /** Resolves a UUID to the live entity owned by the active stage. */
1759
2478
  export declare type DebugEntityResolver = (uuid: string) => GameEntity<any> | null;
1760
2479
 
@@ -1945,16 +2664,57 @@ declare type DiskOptions = BaseNode | Partial<ZylemDiskOptions>;
1945
2664
  */
1946
2665
  export declare function dispatchStageState(): void;
1947
2666
 
2667
+ export declare type DollyPath = Static<typeof DollyPathSchema>;
2668
+
2669
+ export declare const DollyPathSchema: _sinclair_typebox.TObject<{
2670
+ id: _sinclair_typebox.TString;
2671
+ name: _sinclair_typebox.TString;
2672
+ points: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
2673
+ x: _sinclair_typebox.TNumber;
2674
+ y: _sinclair_typebox.TNumber;
2675
+ z: _sinclair_typebox.TNumber;
2676
+ }>>;
2677
+ closed: _sinclair_typebox.TBoolean;
2678
+ /** Catmull-Rom tension; 0.5 is centripetal. */
2679
+ tension: _sinclair_typebox.TNumber;
2680
+ }>;
2681
+
2682
+ /** Point along a dolly path at `u` in 0…1 (arc-length parameterised). */
2683
+ export declare function dollyPointAt(path: DollyPath, u: number): Vec3Def;
2684
+
1948
2685
  export { dot }
1949
2686
 
2687
+ /**
2688
+ * Pure evaluation of a cutscene at a point in time: which scene and shot are
2689
+ * active, where each camera is, and the blended pose the picture should
2690
+ * show. Nothing here touches Three.js cameras or the stage, so the same code
2691
+ * drives the runtime player, the editor's scrubbing, and the unit specs.
2692
+ */
2693
+ export declare function easeValue(easing: CutsceneEasing, t: number): number;
2694
+
1950
2695
  export { EditorToGameMessages }
1951
2696
 
2697
+ export declare type EffectType = Static<typeof EffectTypeSchema>;
2698
+
2699
+ declare const EffectTypeSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"reverb">, _sinclair_typebox.TLiteral<"delay">, _sinclair_typebox.TLiteral<"distortion">, _sinclair_typebox.TLiteral<"filter">]>;
2700
+
1952
2701
  export { emitRuntimeGoal }
1953
2702
 
1954
2703
  export { emitRuntimeRicochet }
1955
2704
 
1956
2705
  export { emitRuntimeTriggerRegionEnter }
1957
2706
 
2707
+ export declare function encodeWav(buffer: PcmSource): ArrayBuffer;
2708
+
2709
+ /** `encodeWav` as a `Blob` ready for upload or download. */
2710
+ export declare function encodeWavBlob(buffer: PcmSource): Blob;
2711
+
2712
+ /**
2713
+ * Loads Tone.js and resumes the AudioContext. Call from a click or key
2714
+ * handler the first time; later calls are cheap.
2715
+ */
2716
+ export declare function ensureAudio(): Promise<ToneModule>;
2717
+
1958
2718
  declare interface Entity<T = any> {
1959
2719
  setup: (entity: T) => void;
1960
2720
  destroy: () => void;
@@ -2238,9 +2998,38 @@ export declare interface EntityTypeMap {
2238
2998
  [LINE_TYPE]: ZylemLine;
2239
2999
  }
2240
3000
 
3001
+ export declare type Envelope = Static<typeof EnvelopeSchema>;
3002
+
3003
+ declare const EnvelopeSchema: _sinclair_typebox.TObject<{
3004
+ attack: _sinclair_typebox.TNumber;
3005
+ decay: _sinclair_typebox.TNumber;
3006
+ sustain: _sinclair_typebox.TNumber;
3007
+ release: _sinclair_typebox.TNumber;
3008
+ }>;
3009
+
2241
3010
  /** Convert Euler angles (radians, XYZ order) to a quaternion. */
2242
3011
  export declare function eulerToQuaternion(rotation: Vec3): Quat;
2243
3012
 
3013
+ /**
3014
+ * Where a camera is at `time` while `shot` is active: base pose, then dolly
3015
+ * progress or follow target, then keyframes on top.
3016
+ */
3017
+ export declare function evaluateCameraPose(camera: CutsceneCamera, definition: Pick<CutsceneDefinition, 'dollies'>, shot: Pick<CameraShot, 'start' | 'end'>, time: number, lookup?: TargetLookup): EvaluatedPose;
3018
+
3019
+ /**
3020
+ * Everything the picture needs at `time`: the active scene and shot, and the
3021
+ * camera pose after blending from the previous shot when the shot asks for
3022
+ * it. Without an active shot the pose is `undefined` and the gameplay camera
3023
+ * keeps control.
3024
+ */
3025
+ export declare function evaluateCutscene(definition: CutsceneDefinition, time: number, lookup?: TargetLookup): CutsceneFrame;
3026
+
3027
+ export declare interface EvaluatedPose {
3028
+ position: Vec3Def;
3029
+ lookAt: Vec3Def;
3030
+ fov: number;
3031
+ }
3032
+
2244
3033
  /**
2245
3034
  * Reusable delegate for event emission and subscription.
2246
3035
  * Use via composition in Game, Stage, and Entity classes.
@@ -2276,6 +3065,73 @@ export declare class EventEmitterDelegate<TEvents extends Record<string, unknown
2276
3065
  dispose(): void;
2277
3066
  }
2278
3067
 
3068
+ export declare type EventItem = Static<typeof EventItemSchema>;
3069
+
3070
+ export declare const EventItemSchema: _sinclair_typebox.TObject<{
3071
+ id: _sinclair_typebox.TString;
3072
+ time: _sinclair_typebox.TNumber;
3073
+ event: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
3074
+ type: _sinclair_typebox.TLiteral<"emit">;
3075
+ /** Stage event name. */
3076
+ name: _sinclair_typebox.TString;
3077
+ payload: _sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>>;
3078
+ }>, _sinclair_typebox.TObject<{
3079
+ type: _sinclair_typebox.TLiteral<"playAnimation">;
3080
+ /** Entity name. */
3081
+ entity: _sinclair_typebox.TString;
3082
+ /** Animation key as passed to `playAnimation({ key })`. */
3083
+ key: _sinclair_typebox.TString;
3084
+ }>, _sinclair_typebox.TObject<{
3085
+ type: _sinclair_typebox.TLiteral<"playSong">;
3086
+ /** Song slug or URL; resolved by the host. */
3087
+ song: _sinclair_typebox.TString;
3088
+ loop: _sinclair_typebox.TBoolean;
3089
+ }>, _sinclair_typebox.TObject<{
3090
+ type: _sinclair_typebox.TLiteral<"stopSong">;
3091
+ song: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
3092
+ }>, _sinclair_typebox.TObject<{
3093
+ type: _sinclair_typebox.TLiteral<"setVariable">;
3094
+ name: _sinclair_typebox.TString;
3095
+ value: _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>;
3096
+ }>]>;
3097
+ }>;
3098
+
3099
+ export declare type EventTrack = Static<typeof EventTrackSchema>;
3100
+
3101
+ declare const EventTrackSchema: _sinclair_typebox.TObject<{
3102
+ kind: _sinclair_typebox.TLiteral<"event">;
3103
+ id: _sinclair_typebox.TString;
3104
+ name: _sinclair_typebox.TString;
3105
+ items: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
3106
+ id: _sinclair_typebox.TString;
3107
+ time: _sinclair_typebox.TNumber;
3108
+ event: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
3109
+ type: _sinclair_typebox.TLiteral<"emit">;
3110
+ /** Stage event name. */
3111
+ name: _sinclair_typebox.TString;
3112
+ payload: _sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>>;
3113
+ }>, _sinclair_typebox.TObject<{
3114
+ type: _sinclair_typebox.TLiteral<"playAnimation">;
3115
+ /** Entity name. */
3116
+ entity: _sinclair_typebox.TString;
3117
+ /** Animation key as passed to `playAnimation({ key })`. */
3118
+ key: _sinclair_typebox.TString;
3119
+ }>, _sinclair_typebox.TObject<{
3120
+ type: _sinclair_typebox.TLiteral<"playSong">;
3121
+ /** Song slug or URL; resolved by the host. */
3122
+ song: _sinclair_typebox.TString;
3123
+ loop: _sinclair_typebox.TBoolean;
3124
+ }>, _sinclair_typebox.TObject<{
3125
+ type: _sinclair_typebox.TLiteral<"stopSong">;
3126
+ song: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
3127
+ }>, _sinclair_typebox.TObject<{
3128
+ type: _sinclair_typebox.TLiteral<"setVariable">;
3129
+ name: _sinclair_typebox.TString;
3130
+ value: _sinclair_typebox.TUnion<[_sinclair_typebox.TString, _sinclair_typebox.TNumber, _sinclair_typebox.TBoolean]>;
3131
+ }>]>;
3132
+ }>>;
3133
+ }>;
3134
+
2279
3135
  export { exp }
2280
3136
 
2281
3137
  export { FacingAngle2DEntity }
@@ -2363,6 +3219,7 @@ export declare interface FirstPersonOptions {
2363
3219
  */
2364
3220
  export declare class FirstPersonPerspective implements CameraPerspective {
2365
3221
  readonly id = "first-person";
3222
+ readonly projection: "perspective";
2366
3223
  readonly defaults: {
2367
3224
  damping: number;
2368
3225
  };
@@ -2447,6 +3304,7 @@ export declare interface Fixed2DOptions {
2447
3304
  */
2448
3305
  export declare class Fixed2DPerspective implements CameraPerspective {
2449
3306
  readonly id = "fixed-2d";
3307
+ readonly projection: "orthographic";
2450
3308
  readonly defaults: {
2451
3309
  damping: number;
2452
3310
  };
@@ -2494,6 +3352,8 @@ export { FractureOptions }
2494
3352
 
2495
3353
  export { FractureOptionsInput }
2496
3354
 
3355
+ export declare function gainToDb(gain: number): number;
3356
+
2497
3357
  export declare class Game<TGlobals extends BaseGlobals> implements IGame<TGlobals> {
2498
3358
  private wrappedGame;
2499
3359
  options: GameOptions<TGlobals>;
@@ -2635,6 +3495,10 @@ export declare class GameBridge {
2635
3495
  * @param announceTarget DOM node the `zylem:bridge:ready` event bubbles from
2636
3496
  */
2637
3497
  connect(host: GameBridgeHost, announceTarget?: EventTarget): void;
3498
+ /** Cutscene playback progress for Director mode's transport. */
3499
+ publishCutsceneStatus(status: CutsceneStatusPayload): void;
3500
+ /** The previewing camera's projection, for Director mode's viewport overlays. */
3501
+ publishCutsceneView(view: CutsceneViewPayload): void;
2638
3502
  disconnect(): void;
2639
3503
  /**
2640
3504
  * Run a swatch batch and report back.
@@ -2750,6 +3614,17 @@ export declare interface GameBridgeHost {
2750
3614
  applySwatches?(payload: EntityApplySwatchPayload & {
2751
3615
  opId: string;
2752
3616
  }): SwatchApplyOutcome;
3617
+ /** Cutscene preview hooks (`cutscene:*`); publish progress via `publishCutsceneStatus`. */
3618
+ cutscene?: {
3619
+ load(payload: CutsceneLoadPayload): void;
3620
+ play(from?: number): void;
3621
+ pause(): void;
3622
+ stop(): void;
3623
+ seek(time: number): void;
3624
+ unload(): void;
3625
+ };
3626
+ /** Describe the live camera (`camera:pose:get`), for capturing framing into a cutscene. */
3627
+ cameraPose?(): Omit<CameraPosePayload, 'requestId'> | null;
2753
3628
  }
2754
3629
 
2755
3630
  /**
@@ -3590,6 +4465,9 @@ export { GameToEditorMessages }
3590
4465
 
3591
4466
  export { GameVariablePayload }
3592
4467
 
4468
+ /** The most recently created, still-live song player, if any. */
4469
+ export declare function getActiveSongPlayer(): SongPlayer | null;
4470
+
3593
4471
  export { getCooldown }
3594
4472
 
3595
4473
  export { getCooldownStore }
@@ -3890,6 +4768,70 @@ declare class InstanceManager {
3890
4768
  private growPack;
3891
4769
  }
3892
4770
 
4771
+ /**
4772
+ * A playable instrument: a Tone.js synth for the preset, its effects chain,
4773
+ * and an output node the song player routes into a track channel.
4774
+ */
4775
+ export declare interface Instrument {
4776
+ readonly definition: InstrumentDefinition;
4777
+ /** Connect this to a channel or destination. */
4778
+ readonly output: ToneNs.ToneAudioNode;
4779
+ /** Plays a note. `time` is in the Tone context clock (seconds); omit for now. */
4780
+ trigger(pitch: number, duration: number, time?: number, velocity?: number): void;
4781
+ /** Silences ringing notes. */
4782
+ releaseAll(time?: number): void;
4783
+ dispose(): void;
4784
+ }
4785
+
4786
+ export declare type InstrumentDefinition = Static<typeof InstrumentDefinitionSchema>;
4787
+
4788
+ export declare const InstrumentDefinitionSchema: _sinclair_typebox.TObject<{
4789
+ id: _sinclair_typebox.TString;
4790
+ name: _sinclair_typebox.TString;
4791
+ preset: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"synth">, _sinclair_typebox.TLiteral<"polySynth">, _sinclair_typebox.TLiteral<"fmSynth">, _sinclair_typebox.TLiteral<"amSynth">, _sinclair_typebox.TLiteral<"membraneSynth">, _sinclair_typebox.TLiteral<"metalSynth">, _sinclair_typebox.TLiteral<"noiseSynth">, _sinclair_typebox.TLiteral<"pluckSynth">]>;
4792
+ oscillator: _sinclair_typebox.TOptional<_sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"sine">, _sinclair_typebox.TLiteral<"square">, _sinclair_typebox.TLiteral<"sawtooth">, _sinclair_typebox.TLiteral<"triangle">]>>;
4793
+ envelope: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
4794
+ attack: _sinclair_typebox.TNumber;
4795
+ decay: _sinclair_typebox.TNumber;
4796
+ sustain: _sinclair_typebox.TNumber;
4797
+ release: _sinclair_typebox.TNumber;
4798
+ }>>;
4799
+ /** Output trim in dB. */
4800
+ volume: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
4801
+ effects: _sinclair_typebox.TOptional<_sinclair_typebox.TArray<_sinclair_typebox.TObject<{
4802
+ id: _sinclair_typebox.TString;
4803
+ type: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"reverb">, _sinclair_typebox.TLiteral<"delay">, _sinclair_typebox.TLiteral<"distortion">, _sinclair_typebox.TLiteral<"filter">]>;
4804
+ /** Dry/wet mix, 0–1. */
4805
+ wet: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
4806
+ /** Effect-specific settings forwarded to the Tone.js constructor. */
4807
+ options: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnion<[_sinclair_typebox.TNumber, _sinclair_typebox.TString, _sinclair_typebox.TBoolean]>>>;
4808
+ }>>>;
4809
+ }>;
4810
+
4811
+ export declare type InstrumentEffect = Static<typeof InstrumentEffectSchema>;
4812
+
4813
+ export declare const InstrumentEffectSchema: _sinclair_typebox.TObject<{
4814
+ id: _sinclair_typebox.TString;
4815
+ type: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"reverb">, _sinclair_typebox.TLiteral<"delay">, _sinclair_typebox.TLiteral<"distortion">, _sinclair_typebox.TLiteral<"filter">]>;
4816
+ /** Dry/wet mix, 0–1. */
4817
+ wet: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
4818
+ /** Effect-specific settings forwarded to the Tone.js constructor. */
4819
+ options: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnion<[_sinclair_typebox.TNumber, _sinclair_typebox.TString, _sinclair_typebox.TBoolean]>>>;
4820
+ }>;
4821
+
4822
+ export declare type InstrumentPreset = Static<typeof InstrumentPresetSchema>;
4823
+
4824
+ /**
4825
+ * TypeBox schema for a song the audio module can play: instruments (Tone.js
4826
+ * presets with an effects chain), tracks (one instrument or audio lane each)
4827
+ * and clips placed on those tracks. All positions and lengths are in beats at
4828
+ * the song's tempo; audio clips reference a URL the runtime can fetch.
4829
+ *
4830
+ * Creator's Music mode authors `.song.json` documents that strip down to this
4831
+ * shape (`toRuntimeSong` in `@zylem-creator/shared`).
4832
+ */
4833
+ export declare const InstrumentPresetSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"synth">, _sinclair_typebox.TLiteral<"polySynth">, _sinclair_typebox.TLiteral<"fmSynth">, _sinclair_typebox.TLiteral<"amSynth">, _sinclair_typebox.TLiteral<"membraneSynth">, _sinclair_typebox.TLiteral<"metalSynth">, _sinclair_typebox.TLiteral<"noiseSynth">, _sinclair_typebox.TLiteral<"pluckSynth">]>;
4834
+
3893
4835
  /**
3894
4836
  * Intersect a ray with the plane through `origin` with the given normal.
3895
4837
  *
@@ -3898,6 +4840,9 @@ declare class InstanceManager {
3898
4840
  */
3899
4841
  export declare function intersectPlane(ray: GizmoRay, origin: Vector3, normal: Vector3, target: Vector3): Vector3 | null;
3900
4842
 
4843
+ /** True once `ensureAudio()` has successfully started the context. */
4844
+ export declare function isAudioReady(): boolean;
4845
+
3901
4846
  /**
3902
4847
  * Check if a shader is a GLSL shader
3903
4848
  */
@@ -3909,6 +4854,44 @@ export declare function isManagedRenderEntity(entity: {
3909
4854
  isBundled?: boolean;
3910
4855
  }): boolean;
3911
4856
 
4857
+ /**
4858
+ * Configuration for the isometric perspective.
4859
+ * The offset is world-locked along (1, 1, 1): yaw 45°, elevation atan(√2).
4860
+ */
4861
+ export declare interface IsometricOptions {
4862
+ /** Distance from the target along the isometric axis. Default 10. */
4863
+ distance?: number;
4864
+ /** Orthographic frustum size. Default 10. */
4865
+ zoom?: number;
4866
+ /** Key in CameraContext.targets to frame. Default 'primary'. */
4867
+ targetKey?: string;
4868
+ /** Fallback camera position when no target exists. */
4869
+ initialPosition?: Vec3Input;
4870
+ /** Fallback lookAt point when no target exists. */
4871
+ initialLookAt?: Vec3Input;
4872
+ }
4873
+
4874
+ /**
4875
+ * Orthographic isometric perspective.
4876
+ *
4877
+ * The view direction stays locked in world space, so the target can move
4878
+ * without the camera orbiting around it. Player look input is not accepted.
4879
+ */
4880
+ export declare class IsometricPerspective implements CameraPerspective {
4881
+ readonly id = "isometric";
4882
+ readonly projection: "orthographic";
4883
+ readonly defaults: {
4884
+ damping: number;
4885
+ };
4886
+ private opts;
4887
+ private initialPosition?;
4888
+ private initialLookAt?;
4889
+ constructor(options?: IsometricOptions);
4890
+ getBasePose(ctx: CameraContext): CameraPose;
4891
+ private staticPose;
4892
+ private pose;
4893
+ }
4894
+
3912
4895
  export declare function isPickMode(): boolean;
3913
4896
 
3914
4897
  declare interface IStage {
@@ -3933,6 +4916,11 @@ export declare function isTSLShader(shader: ZylemShader): shader is ZylemTSLShad
3933
4916
  */
3934
4917
  export declare function isWebGPUSupported(): Promise<boolean>;
3935
4918
 
4919
+ /** Items on every event/audio track with `time` in `(from, to]`, in time order. */
4920
+ export declare function itemsBetween<T extends {
4921
+ time: number;
4922
+ }>(items: readonly T[], from: number, to: number): T[];
4923
+
3936
4924
  /**
3937
4925
  * Stylized joystick base SVG: outer ring, subtle inner ring, and four
3938
4926
  * directional tabs. Designed to scale to any size; consumes only theme
@@ -3994,6 +4982,10 @@ export declare const KeyboardMappingSchema: _sinclair_typebox.TRecord<_sinclair_
3994
4982
 
3995
4983
  export { length_2 as length }
3996
4984
 
4985
+ export declare function lerpPose(a: EvaluatedPose, b: EvaluatedPose, t: number): EvaluatedPose;
4986
+
4987
+ export declare function lerpVec3(a: Vec3Def, b: Vec3Def, t: number): Vec3Def;
4988
+
3997
4989
  /**
3998
4990
  * Provides BaseNode-like lifecycle without ECS/children. Consumers implement
3999
4991
  * the protected hooks and may assign public setup/update/destroy callbacks.
@@ -4102,6 +5094,9 @@ export declare type LoadingEvent = {
4102
5094
  current?: number;
4103
5095
  };
4104
5096
 
5097
+ /** Loads Tone.js (once) without touching the AudioContext. */
5098
+ export declare function loadTone(): Promise<ToneModule>;
5099
+
4105
5100
  /** Per-axis lock input: `true` locks all axes, or pass an [x, y, z] tuple. */
4106
5101
  declare type LockAxesInput = boolean | readonly [boolean, boolean, boolean];
4107
5102
 
@@ -4170,6 +5165,9 @@ declare interface MaterialOptions {
4170
5165
 
4171
5166
  export { max }
4172
5167
 
5168
+ /** The default selection view: the object's world AABB, padded. */
5169
+ export declare function measureObjectSelectionBounds(object: Object3D, target: Box3): Box3;
5170
+
4173
5171
  /**
4174
5172
  * Deep-merges multiple GameInputConfig objects into one.
4175
5173
  * At the player level, configs are merged (both apply).
@@ -4190,6 +5188,12 @@ declare class MeshBuilder {
4190
5188
  */
4191
5189
  declare type MeshBuilderOptions = Partial<Pick<GameEntityOptions, 'material'>>;
4192
5190
 
5191
+ /** MIDI pitch to Hz with A4 = 440. */
5192
+ export declare function midiToFrequency(pitch: number): number;
5193
+
5194
+ /** `60` → `C4`, the spelling Tone.js accepts as a note name. */
5195
+ export declare function midiToNoteName(pitch: number): string;
5196
+
4193
5197
  export { min }
4194
5198
 
4195
5199
  export { mix }
@@ -4344,6 +5348,30 @@ export declare function normalizeVec2(input?: Vec2Input | null, defaults?: Vec2I
4344
5348
 
4345
5349
  export declare function normalizeVec3(input?: Vec3Input | null, defaults?: Vec3Input | Partial<Vec3Components>): Vec3Components;
4346
5350
 
5351
+ export declare type NoteClip = Static<typeof NoteClipSchema>;
5352
+
5353
+ export declare const NoteClipSchema: _sinclair_typebox.TObject<{
5354
+ kind: _sinclair_typebox.TLiteral<"notes">;
5355
+ id: _sinclair_typebox.TString;
5356
+ trackId: _sinclair_typebox.TString;
5357
+ name: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
5358
+ /** Beats from the song start. */
5359
+ start: _sinclair_typebox.TNumber;
5360
+ /** Beats; notes past the end are not played. */
5361
+ length: _sinclair_typebox.TNumber;
5362
+ notes: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
5363
+ id: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
5364
+ /** MIDI pitch, 0–127. */
5365
+ pitch: _sinclair_typebox.TInteger;
5366
+ /** Beats from the clip start. */
5367
+ start: _sinclair_typebox.TNumber;
5368
+ /** Beats. */
5369
+ duration: _sinclair_typebox.TNumber;
5370
+ /** 0–1; defaults to 0.8. */
5371
+ velocity: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
5372
+ }>>;
5373
+ }>;
5374
+
4347
5375
  declare interface ObjectBounds {
4348
5376
  width: number;
4349
5377
  height: number;
@@ -4465,6 +5493,11 @@ export declare type OpacityEntity = {
4465
5493
  mesh?: Object3D | null;
4466
5494
  };
4467
5495
 
5496
+ declare type OscillatorType_2 = Static<typeof OscillatorTypeSchema>;
5497
+ export { OscillatorType_2 as OscillatorType }
5498
+
5499
+ declare const OscillatorTypeSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"sine">, _sinclair_typebox.TLiteral<"square">, _sinclair_typebox.TLiteral<"sawtooth">, _sinclair_typebox.TLiteral<"triangle">]>;
5500
+
4468
5501
  /**
4469
5502
  * Pack a collision type + filter into the runtime's interaction-groups u32
4470
5503
  * (high 16 bits = membership mask, low 16 bits = filter mask).
@@ -4480,6 +5513,14 @@ declare interface PackKeyConfig {
4480
5513
  colorHex?: number;
4481
5514
  }
4482
5515
 
5516
+ /**
5517
+ * Thicken any axis thinner than the minimum and add the uniform margin, in
5518
+ * place. The minimum is proportional to the entity's largest extent so a
5519
+ * 10-unit floor gets a visible slab while a coin-sized disk does not turn
5520
+ * into a cube. Empty or non-finite boxes are returned untouched.
5521
+ */
5522
+ export declare function padSelectionBounds(box: Box3): Box3;
5523
+
4483
5524
  /**
4484
5525
  * Run all actions simultaneously. Done when all children are done.
4485
5526
  *
@@ -4528,15 +5569,27 @@ export { ParticlePresetMaterialOptions }
4528
5569
 
4529
5570
  export { particlePresets }
4530
5571
 
5572
+ /**
5573
+ * Minimal WAV (RIFF, 16-bit PCM) encoder for rendered audio. Works on any
5574
+ * `AudioBuffer`-shaped object so it can run without a Web Audio context.
5575
+ */
5576
+ export declare interface PcmSource {
5577
+ numberOfChannels: number;
5578
+ sampleRate: number;
5579
+ length: number;
5580
+ getChannelData(channel: number): Float32Array;
5581
+ }
5582
+
4531
5583
  /**
4532
5584
  * Perspective-specific options union.
4533
5585
  * Extend as new perspective types are added.
4534
5586
  */
4535
- export declare type PerspectiveOptions = ThirdPersonOptions | Fixed2DOptions | FirstPersonOptions;
5587
+ export declare type PerspectiveOptions = ThirdPersonOptions | Fixed2DOptions | FirstPersonOptions | IsometricOptions | TopDownOptions | SecondPersonOptions;
4536
5588
 
4537
5589
  export declare const Perspectives: {
4538
5590
  readonly FirstPerson: "first-person";
4539
5591
  readonly ThirdPerson: "third-person";
5592
+ readonly SecondPerson: "second-person";
4540
5593
  readonly Isometric: "isometric";
4541
5594
  readonly Flat2D: "flat-2d";
4542
5595
  readonly Fixed2D: "fixed-2d";
@@ -4642,6 +5695,15 @@ declare interface PlaneCollisionOptions extends BaseCollisionOptions {
4642
5695
 
4643
5696
  declare type PlaneOptions = BaseNode | Partial<ZylemPlaneOptions>;
4644
5697
 
5698
+ /** How one axis of the follow focus tracks the target. */
5699
+ export declare type PlatformAxisMode = 'delay' | 'settle' | 'off';
5700
+
5701
+ export declare interface PlatformAxisModes {
5702
+ x?: PlatformAxisMode;
5703
+ y?: PlatformAxisMode;
5704
+ z?: PlatformAxisMode;
5705
+ }
5706
+
4645
5707
  export { Platformer2DBehavior }
4646
5708
 
4647
5709
  export { Platformer2DBehaviorOptions }
@@ -4686,6 +5748,45 @@ export { Platformer3DStateComponent }
4686
5748
 
4687
5749
  export { PlatformerCollisionContext }
4688
5750
 
5751
+ /**
5752
+ * Options for the Super Mario World style follow.
5753
+ *
5754
+ * `delay` lerps toward the target and can wait inside a deadzone.
5755
+ * `settle` holds still while the axis is moving (a jump, a lane change) and
5756
+ * eases to the new rest once the axis goes quiet — landing on a platform.
5757
+ * `off` leaves that axis of the incoming pose alone.
5758
+ */
5759
+ export declare interface PlatformFollowOptions {
5760
+ /** Key in CameraContext.targets to follow. Default 'primary'. */
5761
+ targetKey?: string;
5762
+ /**
5763
+ * Per-axis mode. Default: x and z delay, y settles. Vertical jumps do not
5764
+ * drag the camera; landing does. The same settle mode works on a horizontal axis.
5765
+ */
5766
+ axes?: PlatformAxisModes;
5767
+ /**
5768
+ * Interpolation factor for `delay` axes, in 0..1 per 60Hz frame.
5769
+ * 1 = instant. Scaled by dt. Default 0.1.
5770
+ */
5771
+ lerpFactor?: number;
5772
+ /**
5773
+ * Deadzone in world units for `delay` axes. The focus holds until the
5774
+ * target (plus lookahead) leaves this window. Default 0.
5775
+ */
5776
+ window?: number;
5777
+ /** Speed, in units/second, at or below which a `settle` axis counts as resting. Default 0.75. */
5778
+ settleSpeed?: number;
5779
+ /** Seconds a `settle` axis must stay slow before the focus accepts the new rest. Default 0.15. */
5780
+ settleTime?: number;
5781
+ /** Interpolation factor used once a `settle` axis has a new rest. Default 0.08. */
5782
+ settleLerp?: number;
5783
+ /**
5784
+ * World units of lookahead along the last travel direction.
5785
+ * Applied on `delay` axes only. Default 0.
5786
+ */
5787
+ lookahead?: number;
5788
+ }
5789
+
4689
5790
  export { PlayerInput }
4690
5791
 
4691
5792
  export declare interface PointLightOptions extends BaseLightOptions {
@@ -4720,6 +5821,9 @@ export { PrebakeWorkerRequest }
4720
5821
 
4721
5822
  export { PrebakeWorkerResponse }
4722
5823
 
5824
+ /** The shot that ended most recently before `shot` began, on any camera track. */
5825
+ export declare function previousShot(definition: CutsceneDefinition, shot: CameraShot): CameraShot | undefined;
5826
+
4723
5827
  export declare const PYRAMID_TYPE: unique symbol;
4724
5828
 
4725
5829
  /**
@@ -4888,6 +5992,12 @@ declare class RendererManager {
4888
5992
  * replacement for the old `EffectComposer` + `RenderPass`.
4889
5993
  */
4890
5994
  setupPostProcessing(scene: Scene, camera: Camera): void;
5995
+ /**
5996
+ * Point an already-built post-processing pass at a replacement camera.
5997
+ * No-ops when post-processing has not been set up; the next setup call
5998
+ * receives whatever camera the stage passes in.
5999
+ */
6000
+ rebindPostProcessingCamera(camera: Camera): void;
4891
6001
  /** Whether a stage transition is currently in flight. */
4892
6002
  get transitionActive(): boolean;
4893
6003
  /**
@@ -4896,6 +6006,14 @@ declare class RendererManager {
4896
6006
  * its pipeline is set up. Call before tearing down the outgoing stage.
4897
6007
  */
4898
6008
  beginSnapshotTransition(resolved: ResolvedStageTransition, scene: Scene, camera: Camera): void;
6009
+ /**
6010
+ * Blend from the current picture into the frames that follow without
6011
+ * changing stage: snapshot the outgoing frame, then rebuild the pipeline
6012
+ * so the blend is composed immediately. Used by cutscene scene changes
6013
+ * and any in-stage "cut" the game wants to soften. Move the camera right
6014
+ * after calling this so the snapshot shows the outgoing shot.
6015
+ */
6016
+ beginInStageTransition(resolved: ResolvedStageTransition, scene: Scene, camera: Camera): void;
4899
6017
  /**
4900
6018
  * Complete the active transition immediately: rebuild the normal
4901
6019
  * pipeline, release transition resources, and fire `onComplete`.
@@ -4983,6 +6101,22 @@ declare class RendererManager {
4983
6101
  dispose(): void;
4984
6102
  }
4985
6103
 
6104
+ /**
6105
+ * Renders a song (or a subset of its tracks) to an `AudioBuffer` offline,
6106
+ * faster than real time. Pair with `encodeWav` to get a file. Works without
6107
+ * a user gesture: offline contexts do not need to be resumed.
6108
+ */
6109
+ export declare function renderSong(song: SongDefinition, options?: RenderSongOptions): Promise<AudioBuffer>;
6110
+
6111
+ export declare interface RenderSongOptions {
6112
+ /** Render only these tracks (mute/solo are ignored so a muted track can still be bounced). */
6113
+ trackIds?: Iterable<string>;
6114
+ sampleRate?: number;
6115
+ /** Extra seconds after the song end so releases and reverb tails finish. */
6116
+ tail?: number;
6117
+ resolveUrl?: (url: string) => string;
6118
+ }
6119
+
4986
6120
  /**
4987
6121
  * Routes entities to scene-direct (`none`), WebGPU bundles (`environment`), or
4988
6122
  * instanced meshes (`pack`) based on `options.category`.
@@ -5080,6 +6214,13 @@ export declare interface ResolveGameConfigRuntime {
5080
6214
  /** Resolve the render category for an entity. Defaults to `none`. */
5081
6215
  export declare function resolveRenderCategory(options?: RenderCategoryOptions | null): RenderCategory;
5082
6216
 
6217
+ /**
6218
+ * The selection bounds for an entity: its own {@link SelectionBoundsProvider}
6219
+ * answer when it has one, otherwise the padded AABB of `group ?? mesh`.
6220
+ * Returns `null` when there is nothing to select, so callers need one check.
6221
+ */
6222
+ export declare function resolveSelectionBounds(entity: unknown, target: Box3): Box3 | null;
6223
+
5083
6224
  /**
5084
6225
  * Normalize a theme input to a fully populated {@link TouchTheme}.
5085
6226
  *
@@ -5359,6 +6500,12 @@ export { RuntimeTriggerRegion2DHandle }
5359
6500
 
5360
6501
  export { RuntimeTriggerRegion2DOptions }
5361
6502
 
6503
+ /** Evenly spaced samples of a dolly path, for drawing it. */
6504
+ export declare function sampleDollyPath(path: DollyPath, segments?: number): Vec3Def[];
6505
+
6506
+ /** The scene containing `time` (last one wins on shared boundaries; the final scene past the end). */
6507
+ export declare function sceneAt(scenes: readonly CutsceneScene[], time: number): CutsceneScene | undefined;
6508
+
5362
6509
  declare interface SceneState {
5363
6510
  backgroundColor: Color | string;
5364
6511
  backgroundImage: string | null;
@@ -5372,6 +6519,59 @@ declare interface SceneState {
5372
6519
  defaultLighting?: boolean;
5373
6520
  }
5374
6521
 
6522
+ export declare type SceneTransition = Static<typeof SceneTransitionSchema>;
6523
+
6524
+ export declare const SceneTransitionSchema: _sinclair_typebox.TObject<{
6525
+ type: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"cut">, _sinclair_typebox.TLiteral<"fade">, _sinclair_typebox.TLiteral<"wipe">, _sinclair_typebox.TLiteral<"radial">, _sinclair_typebox.TLiteral<"noise">, _sinclair_typebox.TLiteral<"cells">]>;
6526
+ /** Seconds; ignored for `cut`. */
6527
+ duration: _sinclair_typebox.TNumber;
6528
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
6529
+ }>;
6530
+
6531
+ export declare type SceneTransitionType = Static<typeof SceneTransitionTypeSchema>;
6532
+
6533
+ declare const SceneTransitionTypeSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"cut">, _sinclair_typebox.TLiteral<"fade">, _sinclair_typebox.TLiteral<"wipe">, _sinclair_typebox.TLiteral<"radial">, _sinclair_typebox.TLiteral<"noise">, _sinclair_typebox.TLiteral<"cells">]>;
6534
+
6535
+ export declare interface ScheduledAudio {
6536
+ trackId: string;
6537
+ clipId: string;
6538
+ url: string;
6539
+ /** Seconds from the song start. */
6540
+ time: number;
6541
+ /** Seconds into the file. */
6542
+ offset: number;
6543
+ /** Seconds. */
6544
+ duration: number;
6545
+ /** dB. */
6546
+ gain: number;
6547
+ }
6548
+
6549
+ export declare interface ScheduledNote {
6550
+ trackId: string;
6551
+ clipId: string;
6552
+ instrumentId: string;
6553
+ /** Seconds from the song start. */
6554
+ time: number;
6555
+ /** Seconds. */
6556
+ duration: number;
6557
+ pitch: number;
6558
+ velocity: number;
6559
+ }
6560
+
6561
+ export declare interface ScheduleOptions {
6562
+ /** Only schedule these tracks (mute/solo are still honored). */
6563
+ trackIds?: Iterable<string>;
6564
+ /** Ignore mute/solo and schedule every listed track. */
6565
+ ignoreMix?: boolean;
6566
+ }
6567
+
6568
+ /**
6569
+ * Flattens a song into absolute note and audio events in seconds. Notes are
6570
+ * clipped to their clip's length and to the song end; audio clips are
6571
+ * clipped to the song end.
6572
+ */
6573
+ export declare function scheduleSong(song: SongDefinition, options?: ScheduleOptions): SongSchedule;
6574
+
5375
6575
  /**
5376
6576
  * CooldownIcon -- a WoW-style cooldown icon UI entity.
5377
6577
  *
@@ -5447,6 +6647,72 @@ export { ScreenWrapOptions }
5447
6647
 
5448
6648
  export { ScreenWrapState }
5449
6649
 
6650
+ /**
6651
+ * Configuration for the second-person perspective.
6652
+ *
6653
+ * The camera sits on another entity (`anchorKey`) and looks at the subject.
6654
+ * Nothing here reads player look input.
6655
+ */
6656
+ export declare interface SecondPersonOptions {
6657
+ /** Key of the entity whose eyes the camera uses. Default 'anchor'. */
6658
+ anchorKey?: string;
6659
+ /** Key of the entity to look at. Default 'primary'. */
6660
+ subjectKey?: string;
6661
+ /** Height above the anchor's position. Default 1.7. */
6662
+ eyeHeight?: number;
6663
+ /** Perspective field of view. Default 75. */
6664
+ fov?: number;
6665
+ /** Fallback camera position when the anchor is missing. */
6666
+ initialPosition?: Vec3Input;
6667
+ /** Fallback lookAt point when the anchor is missing. */
6668
+ initialLookAt?: Vec3Input;
6669
+ }
6670
+
6671
+ /**
6672
+ * Second-person perspective.
6673
+ *
6674
+ * Position comes from an anchor entity. The subject, when present, is the
6675
+ * look-at; otherwise the camera looks along the anchor's forward (−Z).
6676
+ * The player's facing does not move this camera.
6677
+ */
6678
+ export declare class SecondPersonPerspective implements CameraPerspective {
6679
+ readonly id = "second-person";
6680
+ readonly projection: "perspective";
6681
+ readonly defaults: {
6682
+ damping: number;
6683
+ };
6684
+ private opts;
6685
+ private initialPosition?;
6686
+ private initialLookAt?;
6687
+ constructor(options?: SecondPersonOptions);
6688
+ getBasePose(ctx: CameraContext): CameraPose;
6689
+ private staticPose;
6690
+ /** Anchor forward in world space. Three.js objects look down −Z. */
6691
+ private anchorForward;
6692
+ }
6693
+
6694
+ export declare function secondsToBeats(seconds: number, bpm: number): number;
6695
+
6696
+ /** Uniform margin around the box, as a fraction of its largest extent. */
6697
+ export declare const SELECTION_BOUNDS_MARGIN = 0.02;
6698
+
6699
+ /** A thin axis is padded up to this fraction of the largest extent... */
6700
+ export declare const SELECTION_THIN_AXIS_FRACTION = 0.05;
6701
+
6702
+ export declare const SELECTION_THIN_AXIS_MAX = 1;
6703
+
6704
+ /** ...clamped between these world-unit bounds. */
6705
+ export declare const SELECTION_THIN_AXIS_MIN = 0.1;
6706
+
6707
+ /**
6708
+ * Implemented by entities that define their own selection view. `target`
6709
+ * is a scratch box to write into; return it, or `null` when the entity
6710
+ * currently has no selectable volume. World space.
6711
+ */
6712
+ export declare interface SelectionBoundsProvider {
6713
+ getSelectionBounds(target: Box3): Box3 | null;
6714
+ }
6715
+
5450
6716
  export { SemanticParticlePresetOptions }
5451
6717
 
5452
6718
  /**
@@ -5495,6 +6761,19 @@ export declare function setAddType(typeId: string | null, props?: Record<string,
5495
6761
  */
5496
6762
  export declare function setCameraFeed(entity: StageEntity, camera: CameraWrapper, options?: CameraFeedOptions): void;
5497
6763
 
6764
+ /**
6765
+ * Registers the blend shaders every stage-bound cutscene uses for its scene
6766
+ * transitions, typically once at startup:
6767
+ *
6768
+ * ```ts
6769
+ * import { createStageTransition } from '@zylem/shaders';
6770
+ * setCutsceneTransitionShaders((type) => createStageTransition({ pattern: type }).shader);
6771
+ * ```
6772
+ *
6773
+ * Without this, every non-`cut` transition is a plain crossfade.
6774
+ */
6775
+ export declare function setCutsceneTransitionShaders(resolver: ((type: SceneTransitionType) => ZylemTransitionShader | undefined) | null): void;
6776
+
5498
6777
  export declare function setDebugTool(tool: DebugTools): void;
5499
6778
 
5500
6779
  /**
@@ -5644,6 +6923,17 @@ export declare function shortestAngleDelta(from: number, to: number): number;
5644
6923
 
5645
6924
  declare function shortHash(objString: string): string;
5646
6925
 
6926
+ /** The shot covering `time` on one track, if any (last one wins on overlaps). */
6927
+ export declare function shotAt(shots: readonly CameraShot[], time: number): CameraShot | undefined;
6928
+
6929
+ export declare type ShotBlend = Static<typeof ShotBlendSchema>;
6930
+
6931
+ declare const ShotBlendSchema: _sinclair_typebox.TObject<{
6932
+ /** Seconds spent blending from the previous shot's camera; 0 is a hard cut. */
6933
+ duration: _sinclair_typebox.TNumber;
6934
+ easing: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"linear">, _sinclair_typebox.TLiteral<"easeIn">, _sinclair_typebox.TLiteral<"easeOut">, _sinclair_typebox.TLiteral<"easeInOut">]>;
6935
+ }>;
6936
+
5647
6937
  export { Simulation }
5648
6938
 
5649
6939
  export declare class SimulationBody implements PhysicsRenderPoseProvider {
@@ -5794,6 +7084,238 @@ export declare function snapToIncrement(value: number, increment: number): numbe
5794
7084
  /** {@link snapToIncrement} across all three components. */
5795
7085
  export declare function snapVec3(value: Vec3, increment: number): Vec3;
5796
7086
 
7087
+ export declare type SongClip = Static<typeof SongClipSchema>;
7088
+
7089
+ export declare const SongClipSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
7090
+ kind: _sinclair_typebox.TLiteral<"notes">;
7091
+ id: _sinclair_typebox.TString;
7092
+ trackId: _sinclair_typebox.TString;
7093
+ name: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7094
+ /** Beats from the song start. */
7095
+ start: _sinclair_typebox.TNumber;
7096
+ /** Beats; notes past the end are not played. */
7097
+ length: _sinclair_typebox.TNumber;
7098
+ notes: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
7099
+ id: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7100
+ /** MIDI pitch, 0–127. */
7101
+ pitch: _sinclair_typebox.TInteger;
7102
+ /** Beats from the clip start. */
7103
+ start: _sinclair_typebox.TNumber;
7104
+ /** Beats. */
7105
+ duration: _sinclair_typebox.TNumber;
7106
+ /** 0–1; defaults to 0.8. */
7107
+ velocity: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7108
+ }>>;
7109
+ }>, _sinclair_typebox.TObject<{
7110
+ kind: _sinclair_typebox.TLiteral<"audio">;
7111
+ id: _sinclair_typebox.TString;
7112
+ trackId: _sinclair_typebox.TString;
7113
+ name: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7114
+ /** URL of the audio file. */
7115
+ url: _sinclair_typebox.TString;
7116
+ /** Beats from the song start. */
7117
+ start: _sinclair_typebox.TNumber;
7118
+ /** Seconds trimmed from the start of the file. */
7119
+ offset: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7120
+ /** Beats. */
7121
+ length: _sinclair_typebox.TNumber;
7122
+ /** Clip gain in dB. */
7123
+ gain: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7124
+ }>]>;
7125
+
7126
+ export declare type SongDefinition = Static<typeof SongDefinitionSchema>;
7127
+
7128
+ export declare const SongDefinitionSchema: _sinclair_typebox.TObject<{
7129
+ id: _sinclair_typebox.TString;
7130
+ name: _sinclair_typebox.TString;
7131
+ bpm: _sinclair_typebox.TNumber;
7132
+ timeSignature: _sinclair_typebox.TObject<{
7133
+ numerator: _sinclair_typebox.TInteger;
7134
+ denominator: _sinclair_typebox.TInteger;
7135
+ }>;
7136
+ lengthBars: _sinclair_typebox.TInteger;
7137
+ loop: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
7138
+ enabled: _sinclair_typebox.TBoolean;
7139
+ /** Beats. */
7140
+ start: _sinclair_typebox.TNumber;
7141
+ end: _sinclair_typebox.TNumber;
7142
+ }>>;
7143
+ instruments: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
7144
+ id: _sinclair_typebox.TString;
7145
+ name: _sinclair_typebox.TString;
7146
+ preset: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"synth">, _sinclair_typebox.TLiteral<"polySynth">, _sinclair_typebox.TLiteral<"fmSynth">, _sinclair_typebox.TLiteral<"amSynth">, _sinclair_typebox.TLiteral<"membraneSynth">, _sinclair_typebox.TLiteral<"metalSynth">, _sinclair_typebox.TLiteral<"noiseSynth">, _sinclair_typebox.TLiteral<"pluckSynth">]>;
7147
+ oscillator: _sinclair_typebox.TOptional<_sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"sine">, _sinclair_typebox.TLiteral<"square">, _sinclair_typebox.TLiteral<"sawtooth">, _sinclair_typebox.TLiteral<"triangle">]>>;
7148
+ envelope: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
7149
+ attack: _sinclair_typebox.TNumber;
7150
+ decay: _sinclair_typebox.TNumber;
7151
+ sustain: _sinclair_typebox.TNumber;
7152
+ release: _sinclair_typebox.TNumber;
7153
+ }>>;
7154
+ /** Output trim in dB. */
7155
+ volume: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7156
+ effects: _sinclair_typebox.TOptional<_sinclair_typebox.TArray<_sinclair_typebox.TObject<{
7157
+ id: _sinclair_typebox.TString;
7158
+ type: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"reverb">, _sinclair_typebox.TLiteral<"delay">, _sinclair_typebox.TLiteral<"distortion">, _sinclair_typebox.TLiteral<"filter">]>;
7159
+ /** Dry/wet mix, 0–1. */
7160
+ wet: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7161
+ /** Effect-specific settings forwarded to the Tone.js constructor. */
7162
+ options: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TUnion<[_sinclair_typebox.TNumber, _sinclair_typebox.TString, _sinclair_typebox.TBoolean]>>>;
7163
+ }>>>;
7164
+ }>>;
7165
+ tracks: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
7166
+ id: _sinclair_typebox.TString;
7167
+ name: _sinclair_typebox.TString;
7168
+ kind: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"instrument">, _sinclair_typebox.TLiteral<"audio">]>;
7169
+ instrumentId: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7170
+ color: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7171
+ /** Fader in dB. */
7172
+ volume: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7173
+ /** -1 (left) … 1 (right). */
7174
+ pan: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7175
+ mute: _sinclair_typebox.TOptional<_sinclair_typebox.TBoolean>;
7176
+ solo: _sinclair_typebox.TOptional<_sinclair_typebox.TBoolean>;
7177
+ }>>;
7178
+ clips: _sinclair_typebox.TArray<_sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
7179
+ kind: _sinclair_typebox.TLiteral<"notes">;
7180
+ id: _sinclair_typebox.TString;
7181
+ trackId: _sinclair_typebox.TString;
7182
+ name: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7183
+ /** Beats from the song start. */
7184
+ start: _sinclair_typebox.TNumber;
7185
+ /** Beats; notes past the end are not played. */
7186
+ length: _sinclair_typebox.TNumber;
7187
+ notes: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
7188
+ id: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7189
+ /** MIDI pitch, 0–127. */
7190
+ pitch: _sinclair_typebox.TInteger;
7191
+ /** Beats from the clip start. */
7192
+ start: _sinclair_typebox.TNumber;
7193
+ /** Beats. */
7194
+ duration: _sinclair_typebox.TNumber;
7195
+ /** 0–1; defaults to 0.8. */
7196
+ velocity: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7197
+ }>>;
7198
+ }>, _sinclair_typebox.TObject<{
7199
+ kind: _sinclair_typebox.TLiteral<"audio">;
7200
+ id: _sinclair_typebox.TString;
7201
+ trackId: _sinclair_typebox.TString;
7202
+ name: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7203
+ /** URL of the audio file. */
7204
+ url: _sinclair_typebox.TString;
7205
+ /** Beats from the song start. */
7206
+ start: _sinclair_typebox.TNumber;
7207
+ /** Seconds trimmed from the start of the file. */
7208
+ offset: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7209
+ /** Beats. */
7210
+ length: _sinclair_typebox.TNumber;
7211
+ /** Clip gain in dB. */
7212
+ gain: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7213
+ }>]>>;
7214
+ /** Master fader in dB. */
7215
+ masterVolume: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7216
+ }>;
7217
+
7218
+ export declare function songLengthBeats(song: Pick<SongDefinition, 'lengthBars' | 'timeSignature'>): number;
7219
+
7220
+ export declare function songLengthSeconds(song: Pick<SongDefinition, 'lengthBars' | 'timeSignature' | 'bpm'>): number;
7221
+
7222
+ export declare type SongLoop = Static<typeof SongLoopSchema>;
7223
+
7224
+ export declare const SongLoopSchema: _sinclair_typebox.TObject<{
7225
+ enabled: _sinclair_typebox.TBoolean;
7226
+ /** Beats. */
7227
+ start: _sinclair_typebox.TNumber;
7228
+ end: _sinclair_typebox.TNumber;
7229
+ }>;
7230
+
7231
+ export declare type SongNote = Static<typeof SongNoteSchema>;
7232
+
7233
+ export declare const SongNoteSchema: _sinclair_typebox.TObject<{
7234
+ id: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7235
+ /** MIDI pitch, 0–127. */
7236
+ pitch: _sinclair_typebox.TInteger;
7237
+ /** Beats from the clip start. */
7238
+ start: _sinclair_typebox.TNumber;
7239
+ /** Beats. */
7240
+ duration: _sinclair_typebox.TNumber;
7241
+ /** 0–1; defaults to 0.8. */
7242
+ velocity: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7243
+ }>;
7244
+
7245
+ export declare interface SongPlayer {
7246
+ readonly definition: SongDefinition;
7247
+ readonly state: SongPlayerState;
7248
+ /** Resolves once Tone.js and every audio clip are loaded. */
7249
+ readonly ready: Promise<void>;
7250
+ /** Starts (or resumes) playback; needs a prior user gesture the first time. */
7251
+ play(fromBeat?: number): Promise<void>;
7252
+ pause(): void;
7253
+ /** Stops and rewinds to the start. */
7254
+ stop(): void;
7255
+ seek(beat: number): void;
7256
+ /** Playhead in beats. */
7257
+ position(): number;
7258
+ /** Playhead in seconds at the current tempo. */
7259
+ seconds(): number;
7260
+ setBpm(bpm: number): void;
7261
+ setLoop(loop: SongLoop | null): void;
7262
+ setTrackMute(trackId: string, mute: boolean): void;
7263
+ setTrackSolo(trackId: string, solo: boolean): void;
7264
+ /** dB. */
7265
+ setTrackVolume(trackId: string, volume: number): void;
7266
+ setTrackPan(trackId: string, pan: number): void;
7267
+ /** dB. */
7268
+ setMasterVolume(volume: number): void;
7269
+ /** Plays one note on a track's instrument right now (for auditioning). */
7270
+ preview(trackId: string, pitch: number, duration?: number, velocity?: number): Promise<void>;
7271
+ /** Swaps in a new definition, keeping the playhead and state. */
7272
+ update(definition: SongDefinition): Promise<void>;
7273
+ on<K extends keyof SongPlayerEvents>(event: K, handler: SongPlayerEvents[K]): () => void;
7274
+ dispose(): void;
7275
+ }
7276
+
7277
+ export declare interface SongPlayerEvents {
7278
+ /** Fires at the start of every bar with the 0-based bar index. */
7279
+ bar: (bar: number) => void;
7280
+ /** Fires at the start of every beat with the 0-based beat index. */
7281
+ beat: (beat: number) => void;
7282
+ /** Fires when a non-looping song reaches its end. */
7283
+ complete: () => void;
7284
+ state: (state: SongPlayerState) => void;
7285
+ }
7286
+
7287
+ export declare interface SongPlayerOptions {
7288
+ /** Resolve clip URLs (for example, relative asset paths) before loading. */
7289
+ resolveUrl?: (url: string) => string;
7290
+ /** Route the master output here instead of the speakers. */
7291
+ destination?: ToneNs.InputNode;
7292
+ }
7293
+
7294
+ export declare type SongPlayerState = 'stopped' | 'playing' | 'paused';
7295
+
7296
+ export declare interface SongSchedule {
7297
+ notes: ScheduledNote[];
7298
+ audio: ScheduledAudio[];
7299
+ /** Seconds. */
7300
+ length: number;
7301
+ }
7302
+
7303
+ export declare type SongTrack = Static<typeof SongTrackSchema>;
7304
+
7305
+ export declare const SongTrackSchema: _sinclair_typebox.TObject<{
7306
+ id: _sinclair_typebox.TString;
7307
+ name: _sinclair_typebox.TString;
7308
+ kind: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"instrument">, _sinclair_typebox.TLiteral<"audio">]>;
7309
+ instrumentId: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7310
+ color: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
7311
+ /** Fader in dB. */
7312
+ volume: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7313
+ /** -1 (left) … 1 (right). */
7314
+ pan: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
7315
+ mute: _sinclair_typebox.TOptional<_sinclair_typebox.TBoolean>;
7316
+ solo: _sinclair_typebox.TOptional<_sinclair_typebox.TBoolean>;
7317
+ }>;
7318
+
5797
7319
  export declare const SPHERE_TYPE: unique symbol;
5798
7320
 
5799
7321
  /**
@@ -6044,6 +7566,19 @@ export declare type StageConfigLike = Partial<{
6044
7566
 
6045
7567
  export { StageConfigPayload }
6046
7568
 
7569
+ export declare interface StageCutsceneHostOptions {
7570
+ /**
7571
+ * Looks a song reference (slug or URL from a `playSong` event / audio
7572
+ * item) up to a definition the audio module can play. Without it song
7573
+ * items are ignored.
7574
+ */
7575
+ resolveSong?: (ref: string) => SongDefinition | Promise<SongDefinition | undefined> | undefined;
7576
+ /** Maps a transition type to a blend shader; defaults to a crossfade for every type. */
7577
+ transitionShader?: (type: SceneTransitionType) => ZylemTransitionShader | undefined;
7578
+ /** Called for `emit` events in addition to the stage dispatch. */
7579
+ onEvent?: (name: string, payload: Record<string, unknown>) => void;
7580
+ }
7581
+
6047
7582
  /**
6048
7583
  * Self-managing debug delegate that subscribes to `debugState` internally.
6049
7584
  *
@@ -6069,6 +7604,10 @@ declare class StageDebugDelegate {
6069
7604
  private warnedMissingAddFactory;
6070
7605
  private transformTool;
6071
7606
  private swatchApplier;
7607
+ private marquee;
7608
+ private selectionHighlight;
7609
+ private selectionBoundsPool;
7610
+ private hoverBounds;
6072
7611
  private grid;
6073
7612
  private lastTool;
6074
7613
  /** Element the current gizmo drag captured, so pointerup is never missed. */
@@ -6082,6 +7621,13 @@ declare class StageDebugDelegate {
6082
7621
  /** Camera used for debug orbit / raycasts (active primary, usually `__debug__`). */
6083
7622
  private getDebugViewCamera;
6084
7623
  private resolveEntity;
7624
+ /**
7625
+ * Every entity a marquee may catch. `childrenMap` is the live stage;
7626
+ * `debugMap` is consulted too so anything only registered there (the same
7627
+ * set the single pick resolves through) is not skipped. Whether an entity
7628
+ * has a selectable volume is the marquee's call, via its selection bounds.
7629
+ */
7630
+ private forEachSelectableEntity;
6085
7631
  /** Copy all stage children into debugMap so raycast/select tools work after enabling debug mid-session. */
6086
7632
  private populateDebugMap;
6087
7633
  private ensureCameraDebugDelegate;
@@ -6114,6 +7660,12 @@ declare class StageDebugDelegate {
6114
7660
  * available when a tool is armed with debug off.
6115
7661
  */
6116
7662
  private ensureToolVisuals;
7663
+ /**
7664
+ * Outline every selected entity. Re-fitted each frame so the boxes follow
7665
+ * entities that move, and so a uuid whose entity has gone (deleted, or
7666
+ * undone) simply drops out instead of leaving a stale box behind.
7667
+ */
7668
+ private updateSelectionHighlight;
6117
7669
  /**
6118
7670
  * Hide the overlays whose tool has just gone away.
6119
7671
  *
@@ -6744,6 +8296,55 @@ export declare const standardShader: {
6744
8296
 
6745
8297
  export { step }
6746
8298
 
8299
+ export declare interface StrategyPanBehavior extends CameraBehavior {
8300
+ /** Follow `key`, or pass null to pan freely. Clears a manual-pan suspension. */
8301
+ setFollowKey(key: string | null): void;
8302
+ }
8303
+
8304
+ /** What {@link StrategyPanOptions.sampleInput} returns each frame. */
8305
+ export declare interface StrategyPanInput {
8306
+ pointer?: StrategyPointer;
8307
+ /** Stick or arrow intent, −1..1. +x is screen right, +y is screen up. */
8308
+ pan?: {
8309
+ x: number;
8310
+ y: number;
8311
+ };
8312
+ }
8313
+
8314
+ export declare interface StrategyPanOptions {
8315
+ /**
8316
+ * Read pointer and pan intent. Kept as a closure so the behavior does not
8317
+ * import InputManager. Typical source: `inputs.p1.pointer` and directions.
8318
+ */
8319
+ sampleInput?: () => StrategyPanInput;
8320
+ /** Fraction of the viewport that counts as an edge. Default 0.08. */
8321
+ edgeMargin?: number;
8322
+ /** World units per second at a flush edge. Default 12. */
8323
+ edgeSpeed?: number;
8324
+ /** World units per second at full stick deflection. Default 16. */
8325
+ panSpeed?: number;
8326
+ /** Target key to ease toward. Null follows nothing. */
8327
+ followKey?: string | null;
8328
+ /** Interpolation factor while following, per 60Hz frame. Default 0.12. */
8329
+ followLerp?: number;
8330
+ /**
8331
+ * A manual pan or edge scroll drops follow until {@link StrategyPanBehavior.setFollowKey}.
8332
+ * Default true.
8333
+ */
8334
+ breakFollowOnPan?: boolean;
8335
+ }
8336
+
8337
+ /**
8338
+ * Pointer for edge scrolling.
8339
+ * `x`/`y` are 0..1 from the top-left, unless `centered` is set, in which case
8340
+ * they are −1..1 with −1 at the left and top (the shape of `inputs.p1.pointer.centerX/Y`).
8341
+ */
8342
+ export declare interface StrategyPointer {
8343
+ x: number;
8344
+ y: number;
8345
+ centered?: boolean;
8346
+ }
8347
+
6747
8348
  export { SwatchApplyFailureReason }
6748
8349
 
6749
8350
  /** What a host reports back from a swatch batch. */
@@ -6780,6 +8381,9 @@ export { SwatchKind }
6780
8381
 
6781
8382
  export { SwatchSpec }
6782
8383
 
8384
+ /** Positions of named entities the cameras may reference, by name. */
8385
+ export declare type TargetLookup = (name: string) => Vec3Def | undefined;
8386
+
6783
8387
  /**
6784
8388
  * Factory interface for generating entity copies
6785
8389
  */
@@ -6857,6 +8461,7 @@ export declare interface ThirdPersonOptions {
6857
8461
  */
6858
8462
  export declare class ThirdPersonPerspective implements CameraPerspective {
6859
8463
  readonly id = "third-person";
8464
+ readonly projection: "perspective";
6860
8465
  /**
6861
8466
  * Slightly looser than the previous 0.15 to compose better with the
6862
8467
  * trailing-delay follow: the trail absorbs short, fast moves and the
@@ -7053,6 +8658,20 @@ declare class Timer {
7053
8658
  update(timestamp?: number): Timer;
7054
8659
  }
7055
8660
 
8661
+ export declare type TimeSignature = Static<typeof TimeSignatureSchema>;
8662
+
8663
+ export declare const TimeSignatureSchema: _sinclair_typebox.TObject<{
8664
+ numerator: _sinclair_typebox.TInteger;
8665
+ denominator: _sinclair_typebox.TInteger;
8666
+ }>;
8667
+
8668
+ /**
8669
+ * Tone.js is loaded on demand so games without music never download it, and
8670
+ * so the AudioContext is only started after a user gesture (browsers refuse
8671
+ * to start one otherwise).
8672
+ */
8673
+ export declare type ToneModule = typeof ToneNs;
8674
+
7056
8675
  export { TopDownMovementBehavior }
7057
8676
 
7058
8677
  export { TopDownMovementBehaviorOptions }
@@ -7067,6 +8686,44 @@ export { TopDownMovementInputComponent }
7067
8686
 
7068
8687
  export { TopDownMovementStateComponent }
7069
8688
 
8689
+ /**
8690
+ * Configuration for the top-down perspective.
8691
+ * The camera sits above the target and looks straight down at the XZ plane.
8692
+ */
8693
+ export declare interface TopDownOptions {
8694
+ /** Height above the target, in world units. Default 10. */
8695
+ height?: number;
8696
+ /** Orthographic frustum size. Default 10. */
8697
+ zoom?: number;
8698
+ /** Key in CameraContext.targets to frame. Default 'primary'. */
8699
+ targetKey?: string;
8700
+ /** Fallback camera position when no target exists. */
8701
+ initialPosition?: Vec3Input;
8702
+ /** Fallback lookAt point when no target exists. */
8703
+ initialLookAt?: Vec3Input;
8704
+ }
8705
+
8706
+ /**
8707
+ * Orthographic top-down perspective.
8708
+ *
8709
+ * Rotation is locked to world -Y. The camera follows the target's XZ and
8710
+ * stays `height` above it. Player look input is not accepted.
8711
+ */
8712
+ export declare class TopDownPerspective implements CameraPerspective {
8713
+ readonly id = "top-down";
8714
+ readonly projection: "orthographic";
8715
+ readonly defaults: {
8716
+ damping: number;
8717
+ };
8718
+ private opts;
8719
+ private initialPosition?;
8720
+ private initialLookAt?;
8721
+ constructor(options?: TopDownOptions);
8722
+ getBasePose(ctx: CameraContext): CameraPose;
8723
+ private staticPose;
8724
+ private pose;
8725
+ }
8726
+
7070
8727
  export { TopDownShooterCoordinator }
7071
8728
 
7072
8729
  export { TopDownShooterEntity }
@@ -7455,6 +9112,8 @@ export declare type Vec3Components = {
7455
9112
  /** Gravity as `[x, y, z]` components (JSON-serializable). */
7456
9113
  export declare const Vec3ComponentsSchema: _sinclair_typebox.TTuple<[_sinclair_typebox.TNumber, _sinclair_typebox.TNumber, _sinclair_typebox.TNumber]>;
7457
9114
 
9115
+ export declare type Vec3Def = Static<typeof Vec3Schema>;
9116
+
7458
9117
  export declare type Vec3Input = Vec3 | {
7459
9118
  x?: number;
7460
9119
  y?: number;
@@ -7463,6 +9122,21 @@ export declare type Vec3Input = Vec3 | {
7463
9122
 
7464
9123
  export { Vec3Like }
7465
9124
 
9125
+ /**
9126
+ * TypeBox schema for a cutscene the cinematics module can play: a timeline in
9127
+ * seconds split into scenes, cameras (static, dolly along a spline, or
9128
+ * following an entity) placed on camera tracks as shots, camera keyframes,
9129
+ * and event/audio tracks that fire gameplay hooks at points in time.
9130
+ *
9131
+ * Creator's Director mode authors `.cutscene.json` documents that strip down
9132
+ * to this shape (`toRuntimeCutscene` in `@zylem-creator/shared`).
9133
+ */
9134
+ declare const Vec3Schema: _sinclair_typebox.TObject<{
9135
+ x: _sinclair_typebox.TNumber;
9136
+ y: _sinclair_typebox.TNumber;
9137
+ z: _sinclair_typebox.TNumber;
9138
+ }>;
9139
+
7466
9140
  declare type Vec3Tuple = readonly [number?, number?, number?] & {
7467
9141
  x?: number;
7468
9142
  y?: number;
@@ -8135,10 +9809,19 @@ declare class ZylemCamera {
8135
9809
  * Apply the final pipeline pose to the Three.js camera.
8136
9810
  */
8137
9811
  private commitPose;
9812
+ /**
9813
+ * Install a perspective and replace the Three.js camera when its projection
9814
+ * kind differs from the live one. Pose is copied across; orbit controls and
9815
+ * post-processing are rebound to the new instance.
9816
+ */
9817
+ applyPerspective(type: PerspectiveType, perspective: CameraPerspective): void;
9818
+ private ensureProjection;
8138
9819
  /**
8139
9820
  * Create a Three.js camera based on perspective type.
8140
9821
  */
8141
9822
  private createCameraForPerspective;
9823
+ private createPerspectiveCamera;
9824
+ private createOrthographicCamera;
8142
9825
  }
8143
9826
 
8144
9827
  /**
@@ -8433,6 +10116,8 @@ declare class ZylemGame<TGlobals extends BaseGlobals> {
8433
10116
  private lastPublishedGameConfig;
8434
10117
  /** Editor ↔ game bridge adapter (RAF-coalesced publishes, command intake). */
8435
10118
  private gameBridge;
10119
+ /** Director mode's in-game cutscene preview, driven over the bridge. */
10120
+ private cutscenePreview;
8436
10121
  /** Stops republishing the entity catalog on registry changes. */
8437
10122
  private catalogUnsubscribe;
8438
10123
  private readonly gameUpdateParams;
@@ -8671,10 +10356,12 @@ export declare type ZylemLineOptions = GameEntityOptions & {
8671
10356
  pickThreshold?: number;
8672
10357
  };
8673
10358
 
8674
- export declare class ZylemParticleSystem extends GameEntity<ZylemParticleSystemOptions> {
10359
+ export declare class ZylemParticleSystem extends GameEntity<ZylemParticleSystemOptions> implements SelectionBoundsProvider {
8675
10360
  static type: symbol;
8676
10361
  __zylemParticleSystemEntity: true;
8677
10362
  private particleHandle;
10363
+ /** The emitter's `group` is empty, so measuring it yields nothing; see {@link PARTICLE_SYSTEM_SELECTION_EXTENT}. */
10364
+ getSelectionBounds(target: Box3): Box3 | null;
8678
10365
  constructor(options?: Partial<ZylemParticleSystemOptions>, initializeBehavior?: boolean);
8679
10366
  private bindStandaloneTransforms;
8680
10367
  private resolveParticleHandle;
@@ -9315,12 +11002,18 @@ declare class ZylemWorld implements Entity<ZylemWorld> {
9315
11002
  private clearEntityPhysicsState;
9316
11003
  }
9317
11004
 
9318
- export declare class ZylemZone extends GameEntity<ZylemZoneOptions> implements CollisionHandlerDelegate {
11005
+ export declare class ZylemZone extends GameEntity<ZylemZoneOptions> implements CollisionHandlerDelegate, SelectionBoundsProvider {
9319
11006
  static type: symbol;
9320
11007
  private _enteredZone;
9321
11008
  private _exitedZone;
9322
11009
  private _zoneEntities;
9323
11010
  constructor(options?: ZylemZoneOptions);
11011
+ /**
11012
+ * A zone has no render object, so the editor cannot measure it. Its
11013
+ * selection view is the sensor volume itself: `options.size` centred on
11014
+ * the live pose (or the configured position before spawn).
11015
+ */
11016
+ getSelectionBounds(target: Box3): Box3 | null;
9324
11017
  handlePostCollision({ delta }: {
9325
11018
  delta: number;
9326
11019
  }): boolean;