@waica/engine 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/dist/assets/asset-loader.d.ts +76 -0
- package/dist/assets/asset-loader.js +138 -0
- package/dist/assets/texture-backend.d.ts +17 -0
- package/dist/assets/texture-backend.js +15 -0
- package/dist/camera-effects.d.ts +142 -0
- package/dist/camera-effects.js +334 -0
- package/dist/components/animated-sprite.d.ts +17 -4
- package/dist/components/animated-sprite.js +41 -12
- package/dist/components/sprite.d.ts +6 -0
- package/dist/components/sprite.js +28 -6
- package/dist/components/tilemap.d.ts +6 -0
- package/dist/components/tilemap.js +28 -4
- package/dist/game-time.d.ts +4 -0
- package/dist/game-time.js +2 -1
- package/dist/game.d.ts +21 -0
- package/dist/game.js +53 -8
- package/dist/index.d.ts +6 -1
- package/dist/index.js +2 -0
- package/dist/runtime-bridge.d.ts +13 -2
- package/dist/runtime-bridge.js +15 -2
- package/dist/runtime-inspection.d.ts +9 -0
- package/dist/runtime-inspection.js +1 -0
- package/package.json +1 -1
package/dist/game.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
+
import { AssetLoader } from './assets/asset-loader.js';
|
|
3
|
+
import type { TextureBackend } from './assets/texture-backend.js';
|
|
2
4
|
import type { AudioBackend } from './audio/backend.js';
|
|
3
5
|
import { AudioSubsystem } from './audio/audio-subsystem.js';
|
|
4
6
|
import { type SceneCameraJson } from './camera.js';
|
|
7
|
+
import { CameraEffects } from './camera-effects.js';
|
|
5
8
|
import type { Component } from './component.js';
|
|
6
9
|
import { Entity } from './entity.js';
|
|
7
10
|
import { Emitter } from './events.js';
|
|
@@ -38,6 +41,13 @@ export interface GameOptions {
|
|
|
38
41
|
* first unlock (CA-6), never eagerly here.
|
|
39
42
|
*/
|
|
40
43
|
audio?: AudioBackend;
|
|
44
|
+
/**
|
|
45
|
+
* Replaces the real `THREE.TextureLoader` implementation behind
|
|
46
|
+
* `game.assets` (ADR 0013's seam, applied to textures — ADR 0019), mainly
|
|
47
|
+
* for a project's own tests: `happy-dom` decodes no images. Defaults to
|
|
48
|
+
* the real backend either way; `game.assets` always exists.
|
|
49
|
+
*/
|
|
50
|
+
textures?: TextureBackend;
|
|
41
51
|
}
|
|
42
52
|
export type UpdateFn = (dt: number) => void;
|
|
43
53
|
export interface SpawnPrefabOptions {
|
|
@@ -68,6 +78,17 @@ export declare class Game {
|
|
|
68
78
|
readonly ui: GameUi;
|
|
69
79
|
/** The audio mixer: channels, master, playback. See ADR 0012, ADR 0013. */
|
|
70
80
|
readonly audio: AudioSubsystem;
|
|
81
|
+
/**
|
|
82
|
+
* The texture cache: keep-all for the Game's life, `preload`, `status`
|
|
83
|
+
* and the Assets Ready promise `ready()`. Session-scoped by construction
|
|
84
|
+
* (ADR 0011): `unloadScene()` never touches it. See ADR 0019.
|
|
85
|
+
*/
|
|
86
|
+
readonly assets: AssetLoader;
|
|
87
|
+
/**
|
|
88
|
+
* Shake, Fade and Flash, beside `camera` and never written into it
|
|
89
|
+
* (ADR 0020). A Fade survives `unloadScene()`; a Shake or Flash does not.
|
|
90
|
+
*/
|
|
91
|
+
readonly cameraEffects: CameraEffects;
|
|
71
92
|
/** Simulated scheduling: `after`, `every`, `tween`, `now`. See ADR 0017. */
|
|
72
93
|
readonly time: GameTime;
|
|
73
94
|
/** Registry retained by loadScene for runtime prefab spawning. */
|
package/dist/game.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import { gameViewport } from './anchored-pieces.js';
|
|
3
|
+
import { AssetLoader } from './assets/asset-loader.js';
|
|
3
4
|
import { AudioSubsystem } from './audio/audio-subsystem.js';
|
|
4
5
|
import { dispatchCollisions as dispatchHitboxCollisions } from './collision-dispatch.js';
|
|
5
6
|
import { isCameraVelocityProvider, resolveSceneCamera, stepSceneCamera, } from './camera.js';
|
|
7
|
+
import { advanceCameraEffects, CameraEffects, layoutCameraEffects } from './camera-effects.js';
|
|
6
8
|
import { resolveComponentUpdateSchedule } from './component-update-schedule.js';
|
|
7
9
|
import { Entity } from './entity.js';
|
|
8
10
|
import { Emitter } from './events.js';
|
|
@@ -35,6 +37,17 @@ export class Game {
|
|
|
35
37
|
ui;
|
|
36
38
|
/** The audio mixer: channels, master, playback. See ADR 0012, ADR 0013. */
|
|
37
39
|
audio;
|
|
40
|
+
/**
|
|
41
|
+
* The texture cache: keep-all for the Game's life, `preload`, `status`
|
|
42
|
+
* and the Assets Ready promise `ready()`. Session-scoped by construction
|
|
43
|
+
* (ADR 0011): `unloadScene()` never touches it. See ADR 0019.
|
|
44
|
+
*/
|
|
45
|
+
assets;
|
|
46
|
+
/**
|
|
47
|
+
* Shake, Fade and Flash, beside `camera` and never written into it
|
|
48
|
+
* (ADR 0020). A Fade survives `unloadScene()`; a Shake or Flash does not.
|
|
49
|
+
*/
|
|
50
|
+
cameraEffects;
|
|
38
51
|
/** Simulated scheduling: `after`, `every`, `tween`, `now`. See ADR 0017. */
|
|
39
52
|
time = new GameTime();
|
|
40
53
|
/** Registry retained by loadScene for runtime prefab spawning. */
|
|
@@ -103,6 +116,17 @@ export class Game {
|
|
|
103
116
|
// music bed needs across a scene swap.
|
|
104
117
|
resolveAsset: (uri) => this.sceneCatalog?.registry.resolveAsset?.(uri) ?? uri,
|
|
105
118
|
});
|
|
119
|
+
this.assets = new AssetLoader({
|
|
120
|
+
backend: options.textures,
|
|
121
|
+
// Same late lookup as audio's: preload() resolves through whatever
|
|
122
|
+
// catalog is registered at call time, which outlives every scene.
|
|
123
|
+
resolveAsset: (uri) => this.sceneCatalog?.registry.resolveAsset?.(uri) ?? uri,
|
|
124
|
+
});
|
|
125
|
+
this.cameraEffects = new CameraEffects({
|
|
126
|
+
host: () => canvas.parentElement ?? document.body,
|
|
127
|
+
// One screen pixel in world units: the shake snaps to it (never the base).
|
|
128
|
+
pixel: () => (this.resolution ? this.viewHeight / this.resolution.height : null),
|
|
129
|
+
});
|
|
106
130
|
this.renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
|
|
107
131
|
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
108
132
|
this.scene.background = new THREE.Color(background);
|
|
@@ -160,6 +184,7 @@ export class Game {
|
|
|
160
184
|
// Scene-scoped timers/tweens die here too (ADR 0017): before entities are
|
|
161
185
|
// destroyed below, so an owner's own destroy() cancellation is a no-op.
|
|
162
186
|
this.time.cancelSceneScoped();
|
|
187
|
+
this.cameraEffects.unloadScene();
|
|
163
188
|
// An explicit unload means "no scene": a swap queued earlier this frame
|
|
164
189
|
// would otherwise flush next frame and resurrect one.
|
|
165
190
|
this.pendingSceneLoad = null;
|
|
@@ -310,6 +335,7 @@ export class Game {
|
|
|
310
335
|
},
|
|
311
336
|
loadScene: (name) => this.loadSceneByName(name),
|
|
312
337
|
availableScenes: () => this.availableScenes,
|
|
338
|
+
assets: () => this.assets.status,
|
|
313
339
|
});
|
|
314
340
|
activation.register(this.runtimeBridge);
|
|
315
341
|
this.audio.setSilenced(true);
|
|
@@ -352,11 +378,15 @@ export class Game {
|
|
|
352
378
|
this.resizeObserver.disconnect();
|
|
353
379
|
this.ui.dispose();
|
|
354
380
|
this.audio.dispose();
|
|
381
|
+
this.cameraEffects.dispose();
|
|
355
382
|
// Cancels both scopes, including session-scoped work no entity owns
|
|
356
383
|
// (entity.destroy() below only ever reaches owned work) — ADR 0017.
|
|
357
384
|
this.time.cancelAll();
|
|
358
385
|
for (const entity of [...this.entities])
|
|
359
386
|
entity.destroy();
|
|
387
|
+
// After the entities: their clones go with the cascade above, the
|
|
388
|
+
// cached bases go here, exactly once (ADR 0019).
|
|
389
|
+
this.assets.dispose();
|
|
360
390
|
this.renderer.dispose();
|
|
361
391
|
}
|
|
362
392
|
/**
|
|
@@ -461,6 +491,7 @@ export class Game {
|
|
|
461
491
|
}
|
|
462
492
|
this.dispatchCollisions();
|
|
463
493
|
this.updateSceneCamera(SIMULATION_STEP);
|
|
494
|
+
advanceCameraEffects(this.cameraEffects);
|
|
464
495
|
this.finishStep();
|
|
465
496
|
}
|
|
466
497
|
/** Closes a step (real or the non-simulating stand-in): host callbacks, then the input frame. */
|
|
@@ -518,15 +549,28 @@ export class Game {
|
|
|
518
549
|
if (this.renderSort === 'y')
|
|
519
550
|
this.applyYSort();
|
|
520
551
|
this.ui.setActive(this.simulate);
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
552
|
+
// The shake offset exists only while drawing (ADR 0020): Anchored Pieces
|
|
553
|
+
// and the render see the drawn center, then the base comes back exactly,
|
|
554
|
+
// so follow smoothing never starts from its own jitter.
|
|
555
|
+
const { x, y } = this.camera.position;
|
|
556
|
+
const { shake } = this.cameraEffects.state;
|
|
557
|
+
this.camera.position.x = x + shake.x;
|
|
558
|
+
this.camera.position.y = y + shake.y;
|
|
559
|
+
try {
|
|
560
|
+
anchoredPiecesOf(this.ui).place();
|
|
561
|
+
if (this.resolution) {
|
|
562
|
+
// Letterbox bars: clear the whole canvas, then render inside the scissor.
|
|
563
|
+
this.renderer.setScissorTest(false);
|
|
564
|
+
this.renderer.setClearColor(0x000000, 1);
|
|
565
|
+
this.renderer.clear(true, false, false);
|
|
566
|
+
this.renderer.setScissorTest(true);
|
|
567
|
+
}
|
|
568
|
+
this.renderer.render(this.scene, this.camera);
|
|
569
|
+
}
|
|
570
|
+
finally {
|
|
571
|
+
this.camera.position.x = x;
|
|
572
|
+
this.camera.position.y = y;
|
|
528
573
|
}
|
|
529
|
-
this.renderer.render(this.scene, this.camera);
|
|
530
574
|
}
|
|
531
575
|
componentUpdateSchedule(entity) {
|
|
532
576
|
const components = [...entity.components];
|
|
@@ -638,5 +682,6 @@ export class Game {
|
|
|
638
682
|
this.camera.top = halfH;
|
|
639
683
|
this.camera.bottom = -halfH;
|
|
640
684
|
this.camera.updateProjectionMatrix();
|
|
685
|
+
layoutCameraEffects(this.cameraEffects, gameViewport(w, h, this.resolution));
|
|
641
686
|
}
|
|
642
687
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { Game } from './game.js';
|
|
2
2
|
export type { GameOptions, GameResolution, SceneCatalog, SpawnPrefabOptions, UpdateFn, ParamOverrides, } from './game.js';
|
|
3
|
+
export { AssetLoader } from './assets/asset-loader.js';
|
|
4
|
+
export type { AssetStatus } from './assets/asset-loader.js';
|
|
5
|
+
export type { TextureBackend } from './assets/texture-backend.js';
|
|
3
6
|
export { AudioSubsystem } from './audio/audio-subsystem.js';
|
|
4
7
|
export type { AudioSubsystemOptions } from './audio/audio-subsystem.js';
|
|
5
8
|
export type { AudioBackend, AudioResource, BackendPlayHandle, BackendPlayOptions } from './audio/backend.js';
|
|
@@ -14,6 +17,8 @@ export { spritePlacement } from './sprite-placement.js';
|
|
|
14
17
|
export type { SpritePlacement, SpritePlacementInput } from './sprite-placement.js';
|
|
15
18
|
export { CAMERA_DEFAULTS, isCameraVelocityProvider, resolveSceneCamera, stepSceneCamera } from './camera.js';
|
|
16
19
|
export { SIMULATION_STEP, SIMULATION_TIME_EPSILON } from './fixed-step.js';
|
|
20
|
+
export { CameraEffects } from './camera-effects.js';
|
|
21
|
+
export type { CameraEffectColor, CameraEffectHandle, CameraEffectsOptions, CameraEffectsState, FadeOptions, FlashOptions, ShakeOptions, } from './camera-effects.js';
|
|
17
22
|
export { GameTime, advanceGameTime } from './game-time.js';
|
|
18
23
|
export type { EasingName, TimerHandle, TimerOptions, TweenOptions } from './game-time.js';
|
|
19
24
|
export type { SceneCameraJson, CameraLimitsJson, CameraVelocity, CameraVelocityProvider, ResolvedSceneCamera, } from './camera.js';
|
|
@@ -32,7 +37,7 @@ export type { PointerCamera, PointerDeps, PointerPick, PointerResolution } from
|
|
|
32
37
|
export { RUNTIME_BRIDGE_CAPABILITIES, RUNTIME_BRIDGE_PROTOCOL_VERSION, RUNTIME_BRIDGE_SYMBOL, RuntimeBridgeOperationError, } from './runtime-bridge.js';
|
|
33
38
|
export type { RuntimeBridge, RuntimeBridgeActivation, RuntimeControlRequest, RuntimeControlResult, RuntimeMetadata, RuntimeMode, } from './runtime-bridge.js';
|
|
34
39
|
export { RUNTIME_PROJECTION_LIMITS } from './runtime-inspection.js';
|
|
35
|
-
export type { ProjectedValue, ProjectionIssue, ProjectionMarker, ProjectionMarkerKind, RuntimeComponentSnapshot, RuntimeEntitySnapshot, RuntimeSnapshot, RuntimeSnapshotAudio, RuntimeSnapshotFilters, RuntimeSnapshotTime, RuntimeSnapshotUi, RuntimeTransformSnapshot, } from './runtime-inspection.js';
|
|
40
|
+
export type { ProjectedValue, ProjectionIssue, ProjectionMarker, ProjectionMarkerKind, RuntimeComponentSnapshot, RuntimeEntitySnapshot, RuntimeSnapshot, RuntimeSnapshotAudio, RuntimeSnapshotCamera, RuntimeSnapshotFilters, RuntimeSnapshotTime, RuntimeSnapshotUi, RuntimeTransformSnapshot, } from './runtime-inspection.js';
|
|
36
41
|
export type { ArchetypeArt, ArchetypeManifest, BrowserArchetypeManifest, EntityTemplate, } from './archetype.js';
|
|
37
42
|
export { Stats } from './stats.js';
|
|
38
43
|
export type { StatValue } from './stats.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Game } from './game.js';
|
|
2
|
+
export { AssetLoader } from './assets/asset-loader.js';
|
|
2
3
|
export { AudioSubsystem } from './audio/audio-subsystem.js';
|
|
3
4
|
export { installDirectionalAnimation, installedDirectionalAnimation, isAnimationFacingProvider, resolveDirectionalClip, } from './animation/directional.js';
|
|
4
5
|
export { isYSortParticipant, ySortZ } from './render-sort.js';
|
|
@@ -6,6 +7,7 @@ export { projectIsometric, screenInputToLogical, unprojectIsometric } from './pr
|
|
|
6
7
|
export { spritePlacement } from './sprite-placement.js';
|
|
7
8
|
export { CAMERA_DEFAULTS, isCameraVelocityProvider, resolveSceneCamera, stepSceneCamera } from './camera.js';
|
|
8
9
|
export { SIMULATION_STEP, SIMULATION_TIME_EPSILON } from './fixed-step.js';
|
|
10
|
+
export { CameraEffects } from './camera-effects.js';
|
|
9
11
|
export { GameTime, advanceGameTime } from './game-time.js';
|
|
10
12
|
export { Entity } from './entity.js';
|
|
11
13
|
export { Component } from './component.js';
|
package/dist/runtime-bridge.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AssetStatus } from './assets/asset-loader.js';
|
|
1
2
|
import type { RuntimeSnapshot, RuntimeSnapshotFilters } from './runtime-inspection.js';
|
|
2
3
|
export declare const RUNTIME_BRIDGE_PROTOCOL_VERSION: 1;
|
|
3
4
|
export declare const RUNTIME_BRIDGE_SYMBOL: unique symbol;
|
|
@@ -10,9 +11,15 @@ export type RuntimeMode = 'paused' | 'real-time';
|
|
|
10
11
|
* gating on capabilities check for (review finding #4) — protocol 1 alone
|
|
11
12
|
* doesn't distinguish an engine that silently no-ops an unknown operation
|
|
12
13
|
* from one that runs it. `fixed-step` (ADR 0014) announces that `step`
|
|
13
|
-
* advances whole 1/60 s Simulation Steps and takes no `dt`.
|
|
14
|
+
* advances whole 1/60 s Simulation Steps and takes no `dt`. `assets`
|
|
15
|
+
* (ADR 0019) announces that every metadata carries `assets: { pending,
|
|
16
|
+
* loaded, failed }` from `game.assets.status`, so a Run Session can wait
|
|
17
|
+
* for Assets Ready (`pending === 0`) at readiness, after a `scene`
|
|
18
|
+
* operation and before a screenshot. `camera-effects` (issue #74, ADR 0020)
|
|
19
|
+
* announces that every snapshot carries `camera: { shake, fade, flash }`
|
|
20
|
+
* from `game.cameraEffects`; the `scene` operation stays a hard cut.
|
|
14
21
|
*/
|
|
15
|
-
export declare const RUNTIME_BRIDGE_CAPABILITIES: readonly ['click', 'scene', 'fixed-step'];
|
|
22
|
+
export declare const RUNTIME_BRIDGE_CAPABILITIES: readonly ['click', 'scene', 'fixed-step', 'assets', 'camera-effects'];
|
|
16
23
|
export interface RuntimeMetadata {
|
|
17
24
|
bridgeVersion: typeof RUNTIME_BRIDGE_PROTOCOL_VERSION;
|
|
18
25
|
engineVersion: string;
|
|
@@ -20,6 +27,8 @@ export interface RuntimeMetadata {
|
|
|
20
27
|
frame: number;
|
|
21
28
|
simulationTime: number;
|
|
22
29
|
capabilities: readonly string[];
|
|
30
|
+
/** `game.assets.status` at the moment of the read — reading it never advances `frame`. */
|
|
31
|
+
assets: AssetStatus;
|
|
23
32
|
}
|
|
24
33
|
export type RuntimeControlRequest = {
|
|
25
34
|
operation: 'press' | 'hold' | 'release';
|
|
@@ -81,6 +90,8 @@ export interface RuntimeBridgeHost {
|
|
|
81
90
|
/** Resolves `name` through the registered catalog and loads it. */
|
|
82
91
|
loadScene(name: string): boolean;
|
|
83
92
|
availableScenes(): string[];
|
|
93
|
+
/** A fresh `game.assets.status`. */
|
|
94
|
+
assets(): AssetStatus;
|
|
84
95
|
}
|
|
85
96
|
export declare class EngineRuntimeBridge implements RuntimeBridge {
|
|
86
97
|
readonly surface: HTMLCanvasElement;
|
package/dist/runtime-bridge.js
CHANGED
|
@@ -10,9 +10,21 @@ export const RUNTIME_BRIDGE_SYMBOL = Symbol.for('@waica/runtime-bridge/v1');
|
|
|
10
10
|
* gating on capabilities check for (review finding #4) — protocol 1 alone
|
|
11
11
|
* doesn't distinguish an engine that silently no-ops an unknown operation
|
|
12
12
|
* from one that runs it. `fixed-step` (ADR 0014) announces that `step`
|
|
13
|
-
* advances whole 1/60 s Simulation Steps and takes no `dt`.
|
|
13
|
+
* advances whole 1/60 s Simulation Steps and takes no `dt`. `assets`
|
|
14
|
+
* (ADR 0019) announces that every metadata carries `assets: { pending,
|
|
15
|
+
* loaded, failed }` from `game.assets.status`, so a Run Session can wait
|
|
16
|
+
* for Assets Ready (`pending === 0`) at readiness, after a `scene`
|
|
17
|
+
* operation and before a screenshot. `camera-effects` (issue #74, ADR 0020)
|
|
18
|
+
* announces that every snapshot carries `camera: { shake, fade, flash }`
|
|
19
|
+
* from `game.cameraEffects`; the `scene` operation stays a hard cut.
|
|
14
20
|
*/
|
|
15
|
-
export const RUNTIME_BRIDGE_CAPABILITIES = [
|
|
21
|
+
export const RUNTIME_BRIDGE_CAPABILITIES = [
|
|
22
|
+
'click',
|
|
23
|
+
'scene',
|
|
24
|
+
'fixed-step',
|
|
25
|
+
'assets',
|
|
26
|
+
'camera-effects',
|
|
27
|
+
];
|
|
16
28
|
export class RuntimeBridgeOperationError extends Error {
|
|
17
29
|
code;
|
|
18
30
|
availableActions;
|
|
@@ -61,6 +73,7 @@ export class EngineRuntimeBridge {
|
|
|
61
73
|
// Derived, never summed: 60 steps are exactly 1 s, with no float drift.
|
|
62
74
|
simulationTime: this.frame * SIMULATION_STEP,
|
|
63
75
|
capabilities: RUNTIME_BRIDGE_CAPABILITIES,
|
|
76
|
+
assets: this.host.assets(),
|
|
64
77
|
};
|
|
65
78
|
}
|
|
66
79
|
inspect(filters = {}) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AudioChannelState, LiveSoundInfo } from './audio/types.js';
|
|
2
|
+
import type { CameraEffectsState } from './camera-effects.js';
|
|
2
3
|
import type { Game } from './game.js';
|
|
3
4
|
import type { RuntimeMetadata } from './runtime-bridge.js';
|
|
4
5
|
import type { StatValue } from './stats.js';
|
|
@@ -106,6 +107,13 @@ export interface RuntimeSnapshotUi {
|
|
|
106
107
|
values: Record<string, StatValue | ProjectionMarker> | ProjectionMarker;
|
|
107
108
|
}>;
|
|
108
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* `game.cameraEffects.state` (issue #74 CA-17), beside `time` and `ui`: the
|
|
112
|
+
* shake offset (world units, added to the camera only while drawing) and
|
|
113
|
+
* the Fade and Flash layers' `#rrggbb` color and opacity, all from the
|
|
114
|
+
* last completed Simulation Step. Emitted unconditionally — never filtered.
|
|
115
|
+
*/
|
|
116
|
+
export type RuntimeSnapshotCamera = CameraEffectsState;
|
|
109
117
|
export interface RuntimeSnapshot extends RuntimeMetadata {
|
|
110
118
|
stats: Record<string, StatValue>;
|
|
111
119
|
/** The live scene's name (its catalog key), or null with no scene loaded. */
|
|
@@ -115,6 +123,7 @@ export interface RuntimeSnapshot extends RuntimeMetadata {
|
|
|
115
123
|
audio: RuntimeSnapshotAudio;
|
|
116
124
|
time: RuntimeSnapshotTime;
|
|
117
125
|
ui: RuntimeSnapshotUi;
|
|
126
|
+
camera: RuntimeSnapshotCamera;
|
|
118
127
|
}
|
|
119
128
|
export declare const RUNTIME_PROJECTION_LIMITS: {
|
|
120
129
|
readonly depth: 5;
|