@threenative/core 0.3.3 → 0.3.4

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.
@@ -1,4 +1,4 @@
1
- import { Texture, Object3D, AnimationClip } from 'three';
1
+ import { Texture, Wrapping, Object3D, AnimationClip } from 'three';
2
2
 
3
3
  interface IAssetLoaderOptions {
4
4
  readonly basePath?: string;
@@ -49,10 +49,41 @@ interface ICompressedTextureSupport {
49
49
  readonly loader: Promise<IKTX2LoaderLike | undefined>;
50
50
  readonly ready: Promise<void>;
51
51
  }
52
+ /** Which pipeline served a logical path: the compile step's manifest, or the project's own files. */
53
+ type AssetSource = "manifest" | "source";
54
+ /** Where one settled load's bytes actually came from. */
55
+ interface IResolvedAsset {
56
+ readonly url: string;
57
+ readonly via: AssetSource;
58
+ }
59
+ interface ITextureOptions {
60
+ /**
61
+ * The pixels are data, not colour: a normal map, a roughness map, a mask. Data textures are
62
+ * sampled without a colour-space conversion, which is wrong for an albedo and right for these.
63
+ * Left out, the copy is sRGB — the space an image file is authored in. A loader leaves a plain
64
+ * image linear, which washes out every albedo, so an options call never inherits that.
65
+ */
66
+ readonly data?: boolean;
67
+ /** Both axes at once. Absent leaves the loaded texture's own wrapping. */
68
+ readonly wrap?: Wrapping;
69
+ /** Tiling counts, one for both axes or one per axis. Absent leaves the loaded texture's own. */
70
+ readonly repeat?: number | readonly [number, number];
71
+ /** Samples to take at grazing angles. Absent leaves the loaded texture's own. */
72
+ readonly anisotropy?: number;
73
+ }
52
74
  interface IAssetLoader {
53
75
  readonly compressedTextures?: ICompressedTextureSupport;
54
76
  model<T = unknown>(path: string): Promise<T>;
55
- texture(path: string): Promise<Texture>;
77
+ /**
78
+ * Load a texture, optionally configured in one call.
79
+ *
80
+ * @situation set color space, wrap, repeat or anisotropy on a loaded texture
81
+ *
82
+ * With no options this is the shared cached instance, exactly as before. With options it is a
83
+ * copy of it: the cached texture is shared by every other caller of that path, and a wrap or a
84
+ * colour-space write on it would silently change how another material draws.
85
+ */
86
+ texture(path: string, options?: ITextureOptions): Promise<Texture>;
56
87
  audio(path: string): Promise<AudioBuffer>;
57
88
  release(kind: "audio" | "model" | "texture", path: string): boolean;
58
89
  /**
@@ -86,6 +117,17 @@ interface IAssetLoader {
86
117
  readonly settled: number;
87
118
  readonly settledBytes: number;
88
119
  };
120
+ /**
121
+ * Where each settled load was actually served from, keyed by the logical path asked for.
122
+ *
123
+ * `progress` counts loads and cannot say which of a path's candidate urls answered, so a game
124
+ * whose manifest 404s and a game whose manifest named the output look identical from the game's
125
+ * own side — which is how an unreadable manifest became a silent uncompiled fallback on the
126
+ * native hosts, where a failed read arrives as a rejected fetch rather than a 404. `via` is
127
+ * `"manifest"` only for the compiled output the manifest named; `"source"` is the verbatim or
128
+ * source-directory path, and an external url, which no manifest governs.
129
+ */
130
+ readonly resolved: ReadonlyMap<string, IResolvedAsset>;
89
131
  clear(): void;
90
132
  }
91
133
  /**
@@ -107,4 +149,4 @@ interface IAssetLoader {
107
149
  declare function reconcileMirroredClips(root: Object3D, clips: readonly AnimationClip[]): boolean;
108
150
  declare function createAssetLoader(options?: IAssetLoaderOptions): IAssetLoader;
109
151
 
110
- export { type IAssetLoader as I, type IAssetLoaderOptions as a, createAssetLoader as c, reconcileMirroredClips as r };
152
+ export { type IAssetLoader as I, type IAssetLoaderOptions as a, type ITextureOptions as b, createAssetLoader as c, reconcileMirroredClips as r };
@@ -1,6 +1,6 @@
1
1
  import * as three from 'three';
2
2
  import { Camera, Vector2, Vector3, Scene, OrthographicCamera } from 'three';
3
- import { I as IRendererLike } from './renderer-Cy4qeBOA.js';
3
+ import { I as IRendererLike } from './renderer-CfsS2hxi.js';
4
4
 
5
5
  interface IViewportSize {
6
6
  readonly aspect: number;
@@ -1,7 +1,7 @@
1
- import { I as IAssetLoader, a as IAssetLoaderOptions } from './assets-CYKk2WTu.js';
2
- import { F as FramePassKind, H as IRenderPassSample, m as IFramePhaseSample, n as IPipelineCensus, I as IRendererLike, ad as IRendererOptions, a as IFrameBudgetWindow, i as IFrameBudgetOptions } from './renderer-Cy4qeBOA.js';
1
+ import { I as IAssetLoader, a as IAssetLoaderOptions } from './assets-CqvE429w.js';
2
+ import { F as FramePassKind, K as IRenderPassSample, n as IFramePhaseSample, o as IPipelineCensus, I as IRendererLike, as as IRendererOptions, a as IFrameBudgetWindow, j as IFrameBudgetOptions } from './renderer-CfsS2hxi.js';
3
3
  import { Vector2, Vector3, Object3D, Camera, Intersection, Scene as Scene$1 } from 'three';
4
- import { V as Viewport, C as CanvasLayer, I as IViewportOptions } from './canvas-layer-C1SnMoJ-.js';
4
+ import { V as Viewport, C as CanvasLayer, I as IViewportOptions } from './canvas-layer-DDmC_VVF.js';
5
5
  import { StoreApi } from 'zustand/vanilla';
6
6
 
7
7
  type ThreeNativeOrientation = "landscape" | "portrait" | "sensor";
@@ -101,6 +101,23 @@ interface IThreeNativeModelPassesConfig {
101
101
  }
102
102
  /** Model optimization options for the asset compile step; `"none"` ships sources verbatim. */
103
103
  interface IThreeNativeModelsConfig {
104
+ /**
105
+ * Lossless scene-graph compaction: flatten empty transform chains, join sibling primitives
106
+ * that share a material, and batch a mesh several nodes reuse as `EXT_mesh_gpu_instancing`.
107
+ *
108
+ * On by default; `false` ships the scene graph as authored. A node matching `protectedPattern`,
109
+ * named in `protectedNames`, targeted by an animation or a skin joint is never merged or
110
+ * instanced, so an exact-name lookup or a bone-driven node survives.
111
+ */
112
+ readonly compact?: boolean | {
113
+ readonly flatten?: boolean;
114
+ readonly instance?: boolean | {
115
+ readonly min?: number;
116
+ };
117
+ readonly join?: boolean;
118
+ readonly protectedNames?: readonly string[];
119
+ readonly protectedPattern?: string;
120
+ };
104
121
  /** Standard glTF TEXCOORD_1 atlas generation for offline static-light assets. */
105
122
  readonly lightmap?: {
106
123
  readonly atlasSize: number;
@@ -237,6 +254,43 @@ interface IThreeNativeLodConfig {
237
254
  readonly preset?: ThreeNativeLodPreset;
238
255
  readonly runtime?: IThreeNativeLodRuntimeConfig;
239
256
  }
257
+ /** One measured byte ceiling on a produced artifact, and what crossing it does. */
258
+ interface IThreeNativeArtifactBudgetLimit {
259
+ /** Bytes, exclusive: a build measuring exactly the limit is inside it. */
260
+ readonly limit: number;
261
+ /** `"error"` refuses the build and keeps the previous artifact; `"warn"` prints and publishes. */
262
+ readonly severity: "error" | "warn";
263
+ }
264
+ /**
265
+ * Runtime ceilings a profile wants every playtest of the artifact it builds to hold.
266
+ *
267
+ * The fields are the playtest harness's own `assert.performance` fields, one name for one meaning:
268
+ * a budget declared here is merged into each scenario's performance assertion, so a budget and a
269
+ * scenario bound the same number instead of two vocabularies for one measurement. Spelled out
270
+ * rather than imported — the harness runs against plain Three.js with no dependency on this
271
+ * package, and core must not invert that. A closed key list validated in both places is the price;
272
+ * `create-threenative/__tests__/build-report.spec.ts` fails if the two lists drift.
273
+ */
274
+ interface IThreeNativePerformanceBudget {
275
+ /** Per-pass draw-call ceilings, keyed by pass kind: main, shadow, reflection, nested. */
276
+ readonly maxPassDrawCalls?: Readonly<Partial<Record<ThreeNativeRenderPassKind, number>>>;
277
+ /** Per-pass triangle ceilings, keyed by pass kind: main, shadow, reflection, nested. */
278
+ readonly maxPassTriangles?: Readonly<Partial<Record<ThreeNativeRenderPassKind, number>>>;
279
+ /** Per-phase millisecond ceilings at nearest-rank p95: hostGap, update, render, overlay, residual. */
280
+ readonly maxPhaseMsP95?: Readonly<Partial<Record<ThreeNativeFramePhase, number>>>;
281
+ /** Maximum renderer draw-call count across every pass combined. */
282
+ readonly maxDrawCalls?: number;
283
+ /** Maximum nearest-rank 95th-percentile frame time in milliseconds. */
284
+ readonly maxFrameMsP95?: number;
285
+ /** Maximum renderer triangle count across every pass combined. */
286
+ readonly maxTriangles?: number;
287
+ /** Frame-budget floor: the median presented frame must sustain at least this many frames a second. */
288
+ readonly minFps?: number;
289
+ }
290
+ /** The engine's frame-budget phases, as a budget spells them. */
291
+ type ThreeNativeFramePhase = "hostGap" | "overlay" | "render" | "residual" | "update";
292
+ /** The render-pass kinds a per-pass budget bounds. */
293
+ type ThreeNativeRenderPassKind = "main" | "shadow" | "reflection" | "nested";
240
294
  interface IThreeNativeConfig {
241
295
  readonly app?: {
242
296
  readonly id?: string;
@@ -251,7 +305,10 @@ interface IThreeNativeConfig {
251
305
  readonly fullscreen?: boolean;
252
306
  readonly keepScreenOn?: boolean;
253
307
  /**
254
- * Maximum native presentation rate in frames per second. Defaults to 60; `0` removes the
308
+ * Maximum native presentation rate in frames per second. Left out, it follows the display's own
309
+ * refresh rate capped at 120 on desktop and web, and stays 60 on mobile where the ceiling is
310
+ * power and heat; the resolved value and its source are reported on every `TN_FRAME_BUDGET`
311
+ * line as `targetFps` and `targetSource`. A number set here wins outright, and `0` removes the
255
312
  * software ceiling. Android also submits this value as the surface's preferred frame rate,
256
313
  * which the display policy may decline because of hardware, power, or thermal state. Android
257
314
  * uses non-blocking presentation above 60 fps so a missed high-refresh interval does not fall
@@ -277,6 +334,43 @@ interface IThreeNativeConfig {
277
334
  readonly maximized?: boolean;
278
335
  readonly resizable?: boolean;
279
336
  };
337
+ /**
338
+ * Named cook profiles: one authored asset tree, one compiler, a different representation per
339
+ * artifact. `--profile` on `threenative build` wins over `defaults[target]`; with neither, the
340
+ * `assets` block is used exactly as declared. An overlay changes resource-processing options
341
+ * only — the source root, the output root, worker concurrency and exclusions stay in `assets`.
342
+ */
343
+ readonly buildProfiles?: {
344
+ readonly defaults?: {
345
+ readonly android?: string;
346
+ readonly desktop?: string;
347
+ readonly ios?: string;
348
+ readonly web?: string;
349
+ };
350
+ readonly profiles: Readonly<Record<string, {
351
+ /**
352
+ * Byte ceilings on what this profile actually produced, measured after packaging and
353
+ * checked before the artifact is published. `artifactBytes` is the artifact itself (a
354
+ * file, or the recursive sum of a directory, `.app` bundle or outDir);
355
+ * `packagedAssetBytes` is the sum of the asset files that survived the packaging
356
+ * selector. `"error"` refuses the build and leaves the previous artifact in place;
357
+ * `"warn"` prints and publishes.
358
+ */
359
+ readonly artifactBudget?: {
360
+ readonly artifactBytes?: IThreeNativeArtifactBudgetLimit;
361
+ readonly packagedAssetBytes?: IThreeNativeArtifactBudgetLimit;
362
+ };
363
+ /**
364
+ * Runtime ceilings this profile's artifact must hold, published into the
365
+ * `<artifact>.build-report.json` a build writes beside it and merged by
366
+ * `threenative-playtest --build-report` into every scenario's `assert.performance`. The
367
+ * build measures none of it — it cannot; the numbers exist only once a runtime drew
368
+ * frames — so a budget never refuses a build and never passes one either.
369
+ */
370
+ readonly performanceBudget?: IThreeNativePerformanceBudget;
371
+ readonly assets?: Pick<NonNullable<IThreeNativeConfig["assets"]>, "audio" | "budget" | "lod" | "models" | "targets" | "textures">;
372
+ }>>;
373
+ };
280
374
  readonly assets?: {
281
375
  /**
282
376
  * Audio conditioning options, or `"none"` to ship every clip exactly as committed. Absent
@@ -294,6 +388,11 @@ interface IThreeNativeConfig {
294
388
  };
295
389
  /** Source-relative globs omitted from builds; excluded bytes are still reported. */
296
390
  readonly exclude?: readonly string[];
391
+ /**
392
+ * How many cook workers a bake may run at once; absent means the driver's default,
393
+ * min(4, cores - 1). Not part of any cache key, so changing it re-cooks nothing.
394
+ */
395
+ readonly concurrency?: number;
297
396
  /**
298
397
  * Automatic discrete LOD. `assets.lod: {}` opts in with the balanced default; `false` or
299
398
  * `{ enabled: false }` is the absolute kill switch, and per-asset overrides key off canonical
@@ -336,7 +435,8 @@ interface IThreeNativeConfig {
336
435
  */
337
436
  readonly alphaAntialiasing?: boolean;
338
437
  /**
339
- * Whether the engine may render an internal mirror of the scene to collapse repeated draws.
438
+ * Whether the engine may render an internal mirror of the scene to collapse repeated draws,
439
+ * and how often that mirror proves a batched material still matches its group's shared draw.
340
440
  *
341
441
  * On by default, which is the shipping behaviour and is what an unset option means. The mirror
342
442
  * is opportunistic and correctness-preserving, but it pays a reconciliation cost per frame, so
@@ -345,8 +445,24 @@ interface IThreeNativeConfig {
345
445
  * eligibility scan, so the opt-out costs nothing rather than declining each frame; the authored
346
446
  * scene is what renders. The `TN_RENDER_PROJECTION` marker still reports it, with its own
347
447
  * reason code rather than one of the measured declines.
448
+ *
449
+ * An object instead of `false` names the material check:
450
+ *
451
+ * - `materialChecks: "spread"` — **the default.** A bounded slice of the batched materials is
452
+ * proved per frame instead of all of them, so a frame of 4,096 colour-only materials costs
453
+ * 512 checks rather than 4,096. A material that gains a roughness, a map or a define still
454
+ * leaves its group and is drawn exactly; it is caught up to `materialCheckStaleFrames` frames
455
+ * later, and `TN_RENDER_PROJECTION` reports that bound. A base-colour edit never waits: the
456
+ * per-instance colour is O(1) per member and always exact.
457
+ * - `materialChecks: "everyFrame"` — the named alternative, and the check exactly as it shipped
458
+ * before the sweep existed: every material proved every frame, at about 1.1 µs a material. Use
459
+ * it when a game would rather pay the per-frame cost than accept the bound.
460
+ *
461
+ * Any other value throws at startup rather than falling back to a default nobody asked for.
348
462
  */
349
- readonly projection?: boolean;
463
+ readonly projection?: boolean | {
464
+ readonly materialChecks?: "spread" | "everyFrame";
465
+ };
350
466
  /**
351
467
  * Projected diameter, in raster pixels, below which the engine does not submit an object to
352
468
  * the render camera. On by default at a conservative **0.5 px**: an object under half a pixel
@@ -691,6 +807,14 @@ interface IRawInputState {
691
807
  buttons: readonly boolean[];
692
808
  };
693
809
  }
810
+ /**
811
+ * Ask the browser to lock the pointer to `target`, the capture every first-person mouse look needs.
812
+ *
813
+ * Returns the platform's own promise when it has one, so the caller can wait for the lock the way
814
+ * the browser reports it, and `undefined` when the platform answered synchronously. A target that
815
+ * cannot capture at all throws rather than leaving a game with a camera that never turns.
816
+ */
817
+ declare function captureMouse(target: EventTarget): Promise<void> | undefined;
694
818
  declare class InputMap {
695
819
  #private;
696
820
  readonly raw: IRawInputState;
@@ -1326,12 +1450,22 @@ interface IGamePluginRuntime {
1326
1450
  readonly enableRuntimeDiagnostics?: () => void;
1327
1451
  /** The frame's cost attribution so far, or undefined when the game turned the budget off. */
1328
1452
  readonly frameBudgetWindow?: () => IFrameBudgetWindow | undefined;
1453
+ /**
1454
+ * Stop the live clock, so a rendered frame simulates nothing and banks no wall-clock time.
1455
+ *
1456
+ * A run that counts fixed-step ticks must not also accumulate real seconds into the same
1457
+ * simulation, and the frames before its first `advance()` are exactly where a boot's seconds
1458
+ * used to land. Optional: a runtime without a clock just never freezes one.
1459
+ */
1460
+ readonly freezeClock?: () => void;
1329
1461
  /**
1330
1462
  * Hold start-scene entry until `gate` settles.
1331
1463
  *
1332
- * The returned promise settles after `Scene.enter()` has run. A runner can therefore release the
1333
- * gate after applying pre-entry setup, then await the returned promise before describing
1334
- * entity-derived capabilities. The frame loop remains held throughout.
1464
+ * The returned promise settles after the scene that owns the world has entered: the start scene
1465
+ * unless it navigated out of its own `enter()`, in which case it is the scene it navigated to,
1466
+ * loaded and entered. A runner can therefore release the gate after applying pre-entry setup,
1467
+ * then await the returned promise before describing entity-derived capabilities — the entities
1468
+ * they read are the ones the world actually has. The frame loop remains held throughout.
1335
1469
  */
1336
1470
  readonly holdStart?: (gate: Promise<void>) => Promise<void>;
1337
1471
  readonly observations: IGameRuntimeObservations;
@@ -1521,4 +1655,4 @@ interface IGame<TState extends Record<string, unknown> = Record<string, unknown>
1521
1655
  }
1522
1656
  declare function defineGame<TState extends Record<string, unknown>, TPhysics = undefined>(config: IGameConfig<TState, TPhysics>): IGame<TState, TPhysics>;
1523
1657
 
1524
- export { type IWarmUpRenderer as $, type AfterPhysicsCallback as A, type IRandom as B, type ContextMenuPolicy as C, type IRawInputPointer as D, type IRawInputPointerEdge as E, type IRawInputState as F, GEOMETRY_ASSET_KEY as G, type IRaycastOptions as H, type IGame as I, type IScenePickerOptions as J, type IThreeNativeAudioConfig as K, type IThreeNativeAudioLoop as L, type IThreeNativeAudioOverride as M, type IThreeNativeAudioSpectrum as N, type IThreeNativeBootSplash as O, type IThreeNativeConfig as P, type IThreeNativeIconVariants as Q, type IThreeNativeLodConfig as R, type IThreeNativeLodGenerationConfig as S, type IThreeNativeLodOverride as T, type IThreeNativeLodRuntimeConfig as U, type IThreeNativeTexturesConfig as V, type ITweenOptions as W, type IWarmUpCacheOptions as X, type IWarmUpObservation as Y, type IWarmUpOptions as Z, type IWarmUpProgress as _, type IGamePluginRuntime as a, type IWarmUpReport as a0, type InputBindings as a1, type InputPlatformSource as a2, type PointerEvent3DListener as a3, type PointerEvent3DType as a4, PointerEvents3D as a5, Scene as a6, type SceneFrame as a7, ScenePicker as a8, type ScheduleHandle as a9, Scheduler as aa, type ThreeNativeBackgroundMode as ab, type ThreeNativeLodMinTrianglesScope as ac, type ThreeNativeLodPreset as ad, type ThreeNativeOrientation as ae, type ThreeNativeUiRenderer as af, type WarmUpCacheStatus as ag, type WarmUpObservationStatus as ah, afterPhysics as ai, createRandom as aj, defineGame as ak, warmUpScene as al, type IGamePluginHooks as b, GEOMETRY_CAPTURE_DEFAULT_LIMIT as c, GEOMETRY_CAPTURE_MAX_LIMIT as d, GEOMETRY_CAPTURE_SORTS as e, GEOMETRY_CAPTURE_TIMEOUT_MS as f, GEOMETRY_CAPTURE_WALK_CAP as g, type GeometryCaptureSort as h, type ICtx as i, type IGameObservationContribution as j, type IGameObservationSampleRequest as k, type IGamePlatformSource as l, type IGeometryCaptureAsset as m, type IGeometryCaptureMesh as n, type IGeometryCapturePass as o, type IGeometryCaptureReport as p, type IGeometryCaptureRequest as q, type IGeometryCaptureRow as r, type IInputAction as s, type IInputGamepad as t, type IPointerDragHandle as u, type IPointerEvent3D as v, type IPointerEvents3D as w, type IPointerEvents3DOptions as x, type IPointerEvents3DPicker as y, type IPointerState as z };
1658
+ export { type IWarmUpRenderer as $, type AfterPhysicsCallback as A, type IRandom as B, type ContextMenuPolicy as C, type IRawInputPointer as D, type IRawInputPointerEdge as E, type IRawInputState as F, GEOMETRY_ASSET_KEY as G, type IRaycastOptions as H, type IGame as I, type IScenePickerOptions as J, type IThreeNativeAudioConfig as K, type IThreeNativeAudioLoop as L, type IThreeNativeAudioOverride as M, type IThreeNativeAudioSpectrum as N, type IThreeNativeBootSplash as O, type IThreeNativeConfig as P, type IThreeNativeIconVariants as Q, type IThreeNativeLodConfig as R, type IThreeNativeLodGenerationConfig as S, type IThreeNativeLodOverride as T, type IThreeNativeLodRuntimeConfig as U, type IThreeNativeTexturesConfig as V, type ITweenOptions as W, type IWarmUpCacheOptions as X, type IWarmUpObservation as Y, type IWarmUpOptions as Z, type IWarmUpProgress as _, type IGamePluginRuntime as a, type IWarmUpReport as a0, type InputBindings as a1, InputMap as a2, type InputPlatformSource as a3, type PointerEvent3DListener as a4, type PointerEvent3DType as a5, PointerEvents3D as a6, Scene as a7, type SceneFrame as a8, ScenePicker as a9, type ScheduleHandle as aa, Scheduler as ab, type ThreeNativeBackgroundMode as ac, type ThreeNativeLodMinTrianglesScope as ad, type ThreeNativeLodPreset as ae, type ThreeNativeOrientation as af, type ThreeNativeUiRenderer as ag, type WarmUpCacheStatus as ah, type WarmUpObservationStatus as ai, afterPhysics as aj, captureMouse as ak, createRandom as al, defineGame as am, warmUpScene as an, type IGamePluginHooks as b, GEOMETRY_CAPTURE_DEFAULT_LIMIT as c, GEOMETRY_CAPTURE_MAX_LIMIT as d, GEOMETRY_CAPTURE_SORTS as e, GEOMETRY_CAPTURE_TIMEOUT_MS as f, GEOMETRY_CAPTURE_WALK_CAP as g, type GeometryCaptureSort as h, type ICtx as i, type IGameObservationContribution as j, type IGameObservationSampleRequest as k, type IGamePlatformSource as l, type IGeometryCaptureAsset as m, type IGeometryCaptureMesh as n, type IGeometryCapturePass as o, type IGeometryCaptureReport as p, type IGeometryCaptureRequest as q, type IGeometryCaptureRow as r, type IInputAction as s, type IInputGamepad as t, type IPointerDragHandle as u, type IPointerEvent3D as v, type IPointerEvents3D as w, type IPointerEvents3DOptions as x, type IPointerEvents3DPicker as y, type IPointerState as z };
@@ -1,5 +1,5 @@
1
- import { Object3D } from 'three';
2
- import { I as IRendererLike } from './renderer-Cy4qeBOA.js';
1
+ import { Object3D, Camera } from 'three';
2
+ import { I as IRendererLike } from './renderer-CfsS2hxi.js';
3
3
 
4
4
  /**
5
5
  * The lifecycle contract for a game-owned GPU simulation.
@@ -17,8 +17,15 @@ interface IComputeDriven {
17
17
  * existing behavior of consumers whose simulation is intentionally tied to presentation.
18
18
  */
19
19
  readonly processCadence?: "fixed" | "render";
20
- /** Dispatched once per fixed step, in scene-add order unless render cadence is declared. */
21
- process(renderer: IRendererLike): void;
20
+ /**
21
+ * Dispatched once per fixed step, in scene-add order unless render cadence is declared.
22
+ *
23
+ * `camera` is the frame's render camera, handed over at render cadence so a consumer that culls by
24
+ * the view — a streamed world narrowing its instanced windows to what the frustum covers — can do
25
+ * it from the driver that runs every frame rather than from a draw three will not submit. An
26
+ * implementation that does not need it simply declares one parameter.
27
+ */
28
+ process(renderer: IRendererLike, camera?: Camera): void;
22
29
  detach(): void;
23
30
  readonly released: boolean;
24
31
  }
@@ -34,8 +41,11 @@ declare class ComputeDrivenRegistry {
34
41
  get warmupNodes(): readonly unknown[];
35
42
  /** Dispatch fixed-step objects once; detached scene children are released before dispatch. */
36
43
  process(renderer: IRendererLike): void;
37
- /** Dispatch render-cadence objects once; detached scene children are released before dispatch. */
38
- processRender(renderer: IRendererLike): void;
44
+ /**
45
+ * Dispatch render-cadence objects once with the frame's render camera; detached scene children are
46
+ * released before dispatch.
47
+ */
48
+ processRender(renderer: IRendererLike, camera?: Camera): void;
39
49
  /** Release every registered object, continuing after a failure so no resource is stranded. */
40
50
  clear(): void;
41
51
  }
package/dist/hot.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { a as audioRuntimeSnapshot } from './audio-7i3Xl0l3.js';
2
- import { I as IGame } from './game-D_6r-k4Y.js';
2
+ import { I as IGame } from './game-CljaDv4D.js';
3
3
  import 'three';
4
- import './assets-CYKk2WTu.js';
5
- import './renderer-Cy4qeBOA.js';
4
+ import './assets-CqvE429w.js';
5
+ import './renderer-CfsS2hxi.js';
6
6
  import 'three/webgpu';
7
- import './canvas-layer-C1SnMoJ-.js';
7
+ import './canvas-layer-DDmC_VVF.js';
8
8
  import 'zustand/vanilla';
9
9
 
10
10
  interface IHotDiagnostics {