@vgai/engine 0.5.11 → 0.5.13

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 (152) hide show
  1. package/README.md +6 -5
  2. package/dist/adapter/authoring.d.ts +51 -28
  3. package/dist/adapter/authoring.d.ts.map +1 -1
  4. package/dist/adapter/body-marks.d.ts +59 -0
  5. package/dist/adapter/body-marks.d.ts.map +1 -0
  6. package/dist/adapter/body-marks.js +62 -0
  7. package/dist/adapter/constraint.d.ts +41 -0
  8. package/dist/adapter/constraint.d.ts.map +1 -0
  9. package/dist/adapter/constraint.js +27 -0
  10. package/dist/adapter/hierarchy-marks.d.ts +138 -0
  11. package/dist/adapter/hierarchy-marks.d.ts.map +1 -0
  12. package/dist/adapter/hierarchy-marks.js +148 -0
  13. package/dist/adapter/index.d.ts +1 -1
  14. package/dist/adapter/index.d.ts.map +1 -1
  15. package/dist/adapter/ingest/contract-system-adapters.d.ts +64 -0
  16. package/dist/adapter/ingest/contract-system-adapters.d.ts.map +1 -0
  17. package/dist/adapter/ingest/contract-system-adapters.js +134 -0
  18. package/dist/adapter/ingest/game-contract.d.ts +87 -9
  19. package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
  20. package/dist/adapter/ingest/game-contract.js +7 -6
  21. package/dist/adapter/ingest/scene-capture.d.ts +31 -4
  22. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
  23. package/dist/adapter/ingest/scene-capture.js +29 -7
  24. package/dist/adapter/ingest/structural-ids.d.ts +1 -1
  25. package/dist/adapter/ingest/structural-ids.js +2 -2
  26. package/dist/adapter/reflection-probe.d.ts +53 -0
  27. package/dist/adapter/reflection-probe.d.ts.map +1 -0
  28. package/dist/adapter/reflection-probe.js +18 -0
  29. package/dist/asset-formats/index.d.ts +4 -10
  30. package/dist/asset-formats/index.d.ts.map +1 -1
  31. package/dist/asset-formats/index.js +3 -8
  32. package/dist/asset-formats/material.d.ts +0 -66
  33. package/dist/asset-formats/material.d.ts.map +1 -1
  34. package/dist/asset-formats/material.js +0 -8
  35. package/dist/asset-formats/mesh.d.ts +1 -2
  36. package/dist/asset-formats/mesh.d.ts.map +1 -1
  37. package/dist/asset-formats/mesh.js +3 -13
  38. package/dist/asset-formats/render-env.d.ts +2 -2
  39. package/dist/asset-parse-error.d.ts +4 -5
  40. package/dist/asset-parse-error.d.ts.map +1 -1
  41. package/dist/asset-parse-error.js +4 -5
  42. package/dist/config.d.ts +7 -0
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/config.js +7 -0
  45. package/dist/data/curve.d.ts +116 -0
  46. package/dist/data/curve.d.ts.map +1 -0
  47. package/dist/data/curve.js +230 -0
  48. package/dist/data/vite-plugin-data.d.ts +2 -2
  49. package/dist/data/vite-plugin-data.d.ts.map +1 -1
  50. package/dist/data/vite-plugin-data.js +24 -15
  51. package/dist/dev/performance-profiler.d.ts +1 -0
  52. package/dist/dev/performance-profiler.d.ts.map +1 -1
  53. package/dist/dev/performance-profiler.js +25 -2
  54. package/dist/ecs/user-data.d.ts +49 -1
  55. package/dist/ecs/user-data.d.ts.map +1 -1
  56. package/dist/ecs/user-data.js +34 -0
  57. package/dist/index.d.ts +2 -3
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +2 -3
  60. package/dist/manifest/index.d.ts +3 -3
  61. package/dist/manifest/index.d.ts.map +1 -1
  62. package/dist/manifest/index.js +2 -2
  63. package/dist/manifest/load.d.ts +15 -67
  64. package/dist/manifest/load.d.ts.map +1 -1
  65. package/dist/manifest/load.js +11 -103
  66. package/dist/manifest/schema.d.ts +18 -103
  67. package/dist/manifest/schema.d.ts.map +1 -1
  68. package/dist/manifest/schema.js +59 -179
  69. package/dist/pixi/index.d.ts +2 -3
  70. package/dist/pixi/index.d.ts.map +1 -1
  71. package/dist/pixi/index.js +2 -3
  72. package/dist/pixi/ingest.d.ts +7 -75
  73. package/dist/pixi/ingest.d.ts.map +1 -1
  74. package/dist/pixi/ingest.js +6 -14
  75. package/dist/pixi/scene-capture.d.ts +2 -2
  76. package/dist/pixi/scene-capture.js +2 -2
  77. package/dist/react/use-data.d.ts +10 -5
  78. package/dist/react/use-data.d.ts.map +1 -1
  79. package/dist/react/use-data.js +15 -15
  80. package/dist/render/viewport-shading.d.ts +1 -1
  81. package/dist/render/viewport-shading.d.ts.map +1 -1
  82. package/dist/render/viewport-shading.js +14 -0
  83. package/dist/runtime/create-runtime.d.ts +12 -0
  84. package/dist/runtime/create-runtime.d.ts.map +1 -1
  85. package/dist/runtime/create-runtime.js +7 -2
  86. package/dist/runtime/mount-game.d.ts +1 -1
  87. package/dist/runtime/mount-game.d.ts.map +1 -1
  88. package/dist/runtime/mount-manifest.d.ts.map +1 -1
  89. package/dist/runtime/mount-manifest.js +5 -1
  90. package/dist/world3d-react/r3f-adapter.d.ts.map +1 -1
  91. package/dist/world3d-react/r3f-adapter.js +69 -39
  92. package/dist/world3d-react/renderer-config.d.ts +15 -0
  93. package/dist/world3d-react/renderer-config.d.ts.map +1 -1
  94. package/dist/world3d-react/renderer-config.js +15 -0
  95. package/dist/world3d-react/world-context.d.ts +2 -1
  96. package/dist/world3d-react/world-context.d.ts.map +1 -1
  97. package/dist-config/config.js +140 -20
  98. package/dist-config/config.js.map +4 -4
  99. package/package.json +1 -1
  100. package/schemas/engine-capabilities.json +10 -10
  101. package/schemas/vgai-project.schema.json +21 -76
  102. package/src/adapter/authoring.ts +54 -31
  103. package/src/adapter/body-marks.ts +69 -0
  104. package/src/adapter/constraint.ts +71 -0
  105. package/src/adapter/hierarchy-marks.ts +155 -0
  106. package/src/adapter/index.ts +2 -3
  107. package/src/adapter/ingest/contract-system-adapters.ts +174 -0
  108. package/src/adapter/ingest/game-contract.ts +98 -9
  109. package/src/adapter/ingest/scene-capture.ts +61 -11
  110. package/src/adapter/ingest/structural-ids.ts +2 -2
  111. package/src/adapter/reflection-probe.ts +75 -0
  112. package/src/asset-formats/index.ts +4 -10
  113. package/src/asset-formats/material.ts +0 -11
  114. package/src/asset-formats/mesh.ts +3 -16
  115. package/src/asset-parse-error.ts +4 -5
  116. package/src/config.ts +13 -0
  117. package/src/data/curve.ts +263 -0
  118. package/src/data/vite-plugin-data.ts +48 -14
  119. package/src/dev/performance-profiler.ts +21 -2
  120. package/src/ecs/user-data.ts +50 -0
  121. package/src/index.ts +2 -3
  122. package/src/manifest/index.ts +3 -15
  123. package/src/manifest/load.ts +27 -143
  124. package/src/manifest/schema.ts +65 -223
  125. package/src/pixi/index.ts +2 -15
  126. package/src/pixi/ingest.ts +13 -87
  127. package/src/pixi/scene-capture.ts +2 -2
  128. package/src/react/use-data.ts +15 -20
  129. package/src/render/viewport-shading.ts +16 -1
  130. package/src/runtime/create-runtime.ts +30 -5
  131. package/src/runtime/mount-game.ts +1 -1
  132. package/src/runtime/mount-manifest.ts +5 -1
  133. package/src/world3d-react/r3f-adapter.tsx +73 -39
  134. package/src/world3d-react/renderer-config.ts +31 -0
  135. package/src/world3d-react/world-context.ts +2 -1
  136. package/dist/asset-formats/instances.d.ts +0 -17
  137. package/dist/asset-formats/instances.d.ts.map +0 -1
  138. package/dist/asset-formats/instances.js +0 -31
  139. package/dist/asset-formats/parse.d.ts +0 -20
  140. package/dist/asset-formats/parse.d.ts.map +0 -1
  141. package/dist/asset-formats/parse.js +0 -34
  142. package/dist/pixi/ingest-iframe.d.ts +0 -82
  143. package/dist/pixi/ingest-iframe.d.ts.map +0 -1
  144. package/dist/pixi/ingest-iframe.js +0 -166
  145. package/dist/render/instance-mesh.d.ts +0 -5
  146. package/dist/render/instance-mesh.d.ts.map +0 -1
  147. package/dist/render/instance-mesh.js +0 -19
  148. package/schemas/mat.schema.json +0 -255
  149. package/src/asset-formats/instances.ts +0 -38
  150. package/src/asset-formats/parse.ts +0 -39
  151. package/src/pixi/ingest-iframe.ts +0 -255
  152. package/src/render/instance-mesh.ts +0 -25
@@ -69,6 +69,8 @@ export function installSceneCapture(threeNamespace, effectComposerCtor, opts) {
69
69
  const REAL = Symbol('vgai.realRender');
70
70
  let captured = null;
71
71
  let drawCount = 0;
72
+ /** Set post-capture by the host; see {@link SceneCaptureHandle.setRenderPassHooks}. */
73
+ let renderPassHooks = null;
72
74
  const waiters = [];
73
75
  // Preserve any descriptor already on the prototype so uninstall can restore it.
74
76
  const priorDescriptor = Object.getOwnPropertyDescriptor(proto, 'render');
@@ -101,6 +103,26 @@ export function installSceneCapture(threeNamespace, effectComposerCtor, opts) {
101
103
  };
102
104
  },
103
105
  });
106
+ /**
107
+ * Call the renderer's own real `render`, bracketed by the render-pass hooks
108
+ * when this IS the captured game's renderer (see `setRenderPassHooks`).
109
+ * `after` runs in a `finally`, so a throwing game frame still restores
110
+ * whatever the hook armed.
111
+ */
112
+ function forwardRender(self, args) {
113
+ const real = self[REAL];
114
+ const hooks = renderPassHooks;
115
+ if (hooks === null || !captured || self !== captured.renderer) {
116
+ return real.apply(self, args);
117
+ }
118
+ hooks.before();
119
+ try {
120
+ return real.apply(self, args);
121
+ }
122
+ finally {
123
+ hooks.after();
124
+ }
125
+ }
104
126
  Object.defineProperty(proto, 'render', {
105
127
  configurable: true,
106
128
  set(fn) {
@@ -123,13 +145,11 @@ export function installSceneCapture(threeNamespace, effectComposerCtor, opts) {
123
145
  drawCount++;
124
146
  // Never capture a scene the HOST owns. The trap sits on the shared
125
147
  // `WebGLRenderer.prototype`, so the editor's own viewport renders
126
- // arrive here too — and when a game bundles its own MISMATCHED three
127
- // (the case this whole degrade-to-embed-only path exists for), the
128
- // editor's scene is then the only thing that ever reaches the trap.
148
+ // arrive here too — and when a game bundles its own MISMATCHED three,
149
+ // the editor's scene is then the only thing that ever reaches the trap.
129
150
  // It was duly "captured" as the game: the editor got a hierarchy of
130
151
  // its own GridHelper, BatchedRenderer and viewport lights presented as
131
- // the ingested game's content, and `captureFailed` the signal the
132
- // whole graceful-degradation contract is built on — never fired.
152
+ // the ingested game's content, and the mount reported success.
133
153
  // Whether that happened at all came down to whether the editor
134
154
  // rendered a frame inside the game's capture window, so the same
135
155
  // session could pass or fail on timing alone.
@@ -143,8 +163,7 @@ export function installSceneCapture(threeNamespace, effectComposerCtor, opts) {
143
163
  for (const resolve of waiters.splice(0))
144
164
  resolve(captured);
145
165
  }
146
- // Forward to the renderer's real render with the original args.
147
- return self[REAL].apply(self, args);
166
+ return forwardRender(self, args);
148
167
  };
149
168
  },
150
169
  });
@@ -189,6 +208,9 @@ export function installSceneCapture(threeNamespace, effectComposerCtor, opts) {
189
208
  getDrawCount() {
190
209
  return drawCount;
191
210
  },
211
+ setRenderPassHooks(hooks) {
212
+ renderPassHooks = hooks;
213
+ },
192
214
  getAnimationLoop(renderer) {
193
215
  return loopCallbacks.get(renderer) ?? null;
194
216
  },
@@ -45,7 +45,7 @@ export interface StructuralIdWalk {
45
45
  * tree re-binds the same ids to the same objects.
46
46
  *
47
47
  * EDITOR FURNITURE IS EXCLUDED, and that exclusion is load-bearing rather than
48
- * cosmetic. In ingest mode the editor adds its grid, lights, particle
48
+ * cosmetic. On an ingest root the editor adds its grid, lights, particle
49
49
  * BatchedRenderer and TransformControls gizmo to the GAME'S OWN scene, and
50
50
  * they arrive asynchronously — some before the walk, some after. Indexing them
51
51
  * made a game object's path depend on how much editor furniture happened to be
@@ -25,7 +25,7 @@ export const CAMERA_ID = 'ingest:camera';
25
25
  * The editor parks its OWN objects — grid, its two lights, the particle
26
26
  * BatchedRenderer, every TransformControls/gizmo helper — on layer 31
27
27
  * (`packages/editor/src/editor-layers.ts`'s `EDITOR_LAYER`) so the game camera
28
- * never sees them. In ingest mode those objects are added to the GAME'S OWN
28
+ * never sees them. On an ingest root those objects are added to the GAME'S OWN
29
29
  * scene, which is the same tree this walk indexes.
30
30
  */
31
31
  const EDITOR_ONLY_LAYER_MASK = 1 << 31;
@@ -60,7 +60,7 @@ export function colorMaterialOf(o) {
60
60
  * tree re-binds the same ids to the same objects.
61
61
  *
62
62
  * EDITOR FURNITURE IS EXCLUDED, and that exclusion is load-bearing rather than
63
- * cosmetic. In ingest mode the editor adds its grid, lights, particle
63
+ * cosmetic. On an ingest root the editor adds its grid, lights, particle
64
64
  * BatchedRenderer and TransformControls gizmo to the GAME'S OWN scene, and
65
65
  * they arrive asynchronously — some before the walk, some after. Indexing them
66
66
  * made a game object's path depend on how much editor furniture happened to be
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Format-neutral live reflection-probe mark.
3
+ *
4
+ * A project-owned scene component writes this mark onto the Object3D it
5
+ * returns. The renderer capability owns capture and material integration; the
6
+ * editor only reads the mark to draw ordinary probe gizmos and expose the
7
+ * capture command/status. Authored truth remains the component's JSX props —
8
+ * this is a live adapter seam, not another document format.
9
+ */
10
+ import type * as THREE from 'three';
11
+ export type ReflectionProbeShape = 'box' | 'sphere';
12
+ export type ReflectionProbeCaptureMode = 'on-change' | 'manual' | 'realtime';
13
+ export type ReflectionProbeCaptureStatus = 'idle' | 'queued' | 'capturing' | 'ready' | 'error';
14
+ export interface ReflectionProbeConfig {
15
+ readonly shape: ReflectionProbeShape;
16
+ /** Full local-space box dimensions. */
17
+ readonly size: readonly [number, number, number];
18
+ /** Local-space sphere radius when `shape === 'sphere'`. */
19
+ readonly radius: number;
20
+ /** Local-space distance over which this probe fades at its boundary. */
21
+ readonly blendDistance: number;
22
+ /** Larger values win before equal-priority probes blend. */
23
+ readonly priority: number;
24
+ readonly intensity: number;
25
+ readonly parallaxProjection: boolean;
26
+ /** Full local-space projection-box dimensions. */
27
+ readonly parallaxSize: readonly [number, number, number];
28
+ readonly parallaxOffset: readonly [number, number, number];
29
+ readonly captureOffset: readonly [number, number, number];
30
+ readonly captureMode: ReflectionProbeCaptureMode;
31
+ readonly resolution: number;
32
+ readonly near: number;
33
+ readonly far: number;
34
+ readonly cullMask: number;
35
+ readonly captureShadows: boolean;
36
+ }
37
+ export interface ReflectionProbeSnapshot {
38
+ readonly status: ReflectionProbeCaptureStatus;
39
+ /** Monotonic browser time from `performance.now()`, or null before capture. */
40
+ readonly lastCapturedAt: number | null;
41
+ readonly message?: string;
42
+ }
43
+ export interface ReflectionProbeMark {
44
+ readonly config: ReflectionProbeConfig;
45
+ readonly revision: number;
46
+ recapture(): void;
47
+ getSnapshot(): ReflectionProbeSnapshot;
48
+ subscribe(listener: () => void): () => void;
49
+ }
50
+ export declare function reflectionProbeOf(object: THREE.Object3D | null | undefined): ReflectionProbeMark | null;
51
+ export declare function setReflectionProbeMark(object: THREE.Object3D, mark: ReflectionProbeMark): void;
52
+ export declare function clearReflectionProbeMark(object: THREE.Object3D): void;
53
+ //# sourceMappingURL=reflection-probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reflection-probe.d.ts","sourceRoot":"","sources":["../../src/adapter/reflection-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAGpC,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,0BAA0B,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAC7E,MAAM,MAAM,4BAA4B,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC;AAE/F,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IACrC,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,kDAAkD;IAClD,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACzD,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3D,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,4BAA4B,CAAC;IAC9C,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,SAAS,IAAI,IAAI,CAAC;IAClB,WAAW,IAAI,uBAAuB,CAAC;IACvC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,GAAG,SAAS,GACxC,mBAAmB,GAAG,IAAI,CAS5B;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAE9F;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAErE"}
@@ -0,0 +1,18 @@
1
+ import { deleteUserData, getUserData, setUserData } from '../ecs/user-data';
2
+ export function reflectionProbeOf(object) {
3
+ const candidate = getUserData(object, 'reflectionProbe');
4
+ if (!candidate || typeof candidate !== 'object')
5
+ return null;
6
+ const mark = candidate;
7
+ return mark.config &&
8
+ typeof mark.recapture === 'function' &&
9
+ typeof mark.getSnapshot === 'function'
10
+ ? candidate
11
+ : null;
12
+ }
13
+ export function setReflectionProbeMark(object, mark) {
14
+ setUserData(object, 'reflectionProbe', mark);
15
+ }
16
+ export function clearReflectionProbeMark(object) {
17
+ deleteUserData(object, 'reflectionProbe');
18
+ }
@@ -1,14 +1,11 @@
1
1
  /**
2
- * The engine's remaining authored asset formats and descriptor schemas.
2
+ * The engine's runtime descriptor schemas.
3
3
  *
4
4
  * WO-8 deleted the `.vscn.json` scene format and everything under
5
5
  * `engine/src/scene/`. What survived is here, and each module is here because a
6
6
  * real runtime reader still consumes it:
7
7
  *
8
- * - `material.ts` — the `.mat.json` shared-material format (`parseMaterialFile`)
9
- * plus the inline material descriptor `render/material-factory.ts` reads
10
- * - `instances.ts` — the `.instances.json` transform format (`parseInstancesFile`),
11
- * read by `render/instance-mesh.ts`
8
+ * - `material.ts` — the inline material descriptor `render/material-factory.ts` reads
12
9
  * - `mesh.ts` — the geometry descriptor `render/material-factory.ts`'s `createGeometry` reads
13
10
  * - `light.ts` / `camera.ts` — the descriptors `render/light-camera-factory.ts` reads
14
11
  * - `collider.ts` — the descriptor `physics/collider-dimensions.ts` and the editor's
@@ -28,15 +25,12 @@ export type { CameraDescriptor } from './camera';
28
25
  export { CameraDescriptorSchema } from './camera';
29
26
  export type { ColliderDescriptor } from './collider';
30
27
  export { ColliderDescriptorSchema } from './collider';
31
- export type { InstancesFile } from './instances';
32
- export { InstancesFileSchema } from './instances';
33
28
  export type { LightDescriptor } from './light';
34
29
  export { LightDescriptorSchema } from './light';
35
- export type { MaterialDescriptor, MaterialFile } from './material';
36
- export { MaterialDescriptorSchema, MaterialFileSchema } from './material';
30
+ export type { MaterialDescriptor } from './material';
31
+ export { MaterialDescriptorSchema } from './material';
37
32
  export type { MeshDescriptor } from './mesh';
38
33
  export { MeshDescriptorSchema } from './mesh';
39
- export { parseInstancesFile, parseMaterialFile } from './parse';
40
34
  export type { ParticlesDescriptor } from './particles';
41
35
  export { ParticlesDescriptorSchema } from './particles';
42
36
  export type { PostProcessingDescriptor, RenderEnvironment, ToneMappingDescriptor, } from './render-env';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/asset-formats/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC1E,YAAY,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAChE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EACV,wBAAwB,EACxB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,8BAA8B,EAC9B,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/asset-formats/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EACV,wBAAwB,EACxB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,8BAA8B,EAC9B,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
@@ -1,14 +1,11 @@
1
1
  /**
2
- * The engine's remaining authored asset formats and descriptor schemas.
2
+ * The engine's runtime descriptor schemas.
3
3
  *
4
4
  * WO-8 deleted the `.vscn.json` scene format and everything under
5
5
  * `engine/src/scene/`. What survived is here, and each module is here because a
6
6
  * real runtime reader still consumes it:
7
7
  *
8
- * - `material.ts` — the `.mat.json` shared-material format (`parseMaterialFile`)
9
- * plus the inline material descriptor `render/material-factory.ts` reads
10
- * - `instances.ts` — the `.instances.json` transform format (`parseInstancesFile`),
11
- * read by `render/instance-mesh.ts`
8
+ * - `material.ts` — the inline material descriptor `render/material-factory.ts` reads
12
9
  * - `mesh.ts` — the geometry descriptor `render/material-factory.ts`'s `createGeometry` reads
13
10
  * - `light.ts` / `camera.ts` — the descriptors `render/light-camera-factory.ts` reads
14
11
  * - `collider.ts` — the descriptor `physics/collider-dimensions.ts` and the editor's
@@ -26,11 +23,9 @@
26
23
  */
27
24
  export { CameraDescriptorSchema } from './camera';
28
25
  export { ColliderDescriptorSchema } from './collider';
29
- export { InstancesFileSchema } from './instances';
30
26
  export { LightDescriptorSchema } from './light';
31
- export { MaterialDescriptorSchema, MaterialFileSchema } from './material';
27
+ export { MaterialDescriptorSchema } from './material';
32
28
  export { MeshDescriptorSchema } from './mesh';
33
- export { parseInstancesFile, parseMaterialFile } from './parse';
34
29
  export { ParticlesDescriptorSchema } from './particles';
35
30
  export { PostProcessingDescriptorSchema, RenderEnvironmentSchema, ToneMappingDescriptorSchema, } from './render-env';
36
31
  export { QuatSchema, TransformSchema, Vec3Schema } from './tuples';
@@ -60,70 +60,4 @@ export declare const MaterialDescriptorSchema: z.ZodObject<{
60
60
  displacementBias: z.ZodOptional<z.ZodNumber>;
61
61
  }, z.core.$strict>;
62
62
  export type MaterialDescriptor = z.infer<typeof MaterialDescriptorSchema>;
63
- /** .mat.json file format for shared/reusable material assets. */
64
- export declare const MaterialFileSchema: z.ZodObject<{
65
- version: z.ZodNumber;
66
- name: z.ZodString;
67
- material: z.ZodObject<{
68
- type: z.ZodEnum<{
69
- standard: "standard";
70
- physical: "physical";
71
- basic: "basic";
72
- toon: "toon";
73
- }>;
74
- color: z.ZodOptional<z.ZodString>;
75
- metalness: z.ZodOptional<z.ZodNumber>;
76
- roughness: z.ZodOptional<z.ZodNumber>;
77
- map: z.ZodOptional<z.ZodString>;
78
- normalMap: z.ZodOptional<z.ZodString>;
79
- emissive: z.ZodOptional<z.ZodString>;
80
- emissiveIntensity: z.ZodOptional<z.ZodNumber>;
81
- emissiveMap: z.ZodOptional<z.ZodString>;
82
- aoMap: z.ZodOptional<z.ZodString>;
83
- lightMap: z.ZodOptional<z.ZodString>;
84
- lightMapIntensity: z.ZodOptional<z.ZodNumber>;
85
- roughnessMap: z.ZodOptional<z.ZodString>;
86
- metalnessMap: z.ZodOptional<z.ZodString>;
87
- opacity: z.ZodOptional<z.ZodNumber>;
88
- transparent: z.ZodOptional<z.ZodBoolean>;
89
- side: z.ZodOptional<z.ZodEnum<{
90
- front: "front";
91
- back: "back";
92
- double: "double";
93
- }>>;
94
- flatShading: z.ZodOptional<z.ZodBoolean>;
95
- clearcoat: z.ZodOptional<z.ZodObject<{
96
- clearcoat: z.ZodNumber;
97
- clearcoatRoughness: z.ZodOptional<z.ZodNumber>;
98
- clearcoatMap: z.ZodOptional<z.ZodString>;
99
- clearcoatRoughnessMap: z.ZodOptional<z.ZodString>;
100
- }, z.core.$strip>>;
101
- transmission: z.ZodOptional<z.ZodObject<{
102
- transmission: z.ZodNumber;
103
- ior: z.ZodOptional<z.ZodNumber>;
104
- thickness: z.ZodOptional<z.ZodNumber>;
105
- attenuationColor: z.ZodOptional<z.ZodString>;
106
- attenuationDistance: z.ZodOptional<z.ZodNumber>;
107
- transmissionMap: z.ZodOptional<z.ZodString>;
108
- }, z.core.$strip>>;
109
- sheen: z.ZodOptional<z.ZodObject<{
110
- sheen: z.ZodNumber;
111
- sheenColor: z.ZodOptional<z.ZodString>;
112
- sheenRoughness: z.ZodOptional<z.ZodNumber>;
113
- sheenColorMap: z.ZodOptional<z.ZodString>;
114
- sheenRoughnessMap: z.ZodOptional<z.ZodString>;
115
- }, z.core.$strip>>;
116
- iridescence: z.ZodOptional<z.ZodObject<{
117
- iridescence: z.ZodNumber;
118
- iridescenceIOR: z.ZodOptional<z.ZodNumber>;
119
- iridescenceThicknessRange: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
120
- iridescenceMap: z.ZodOptional<z.ZodString>;
121
- iridescenceThicknessMap: z.ZodOptional<z.ZodString>;
122
- }, z.core.$strip>>;
123
- displacementMap: z.ZodOptional<z.ZodString>;
124
- displacementScale: z.ZodOptional<z.ZodNumber>;
125
- displacementBias: z.ZodOptional<z.ZodNumber>;
126
- }, z.core.$strict>;
127
- }, z.core.$strip>;
128
- export type MaterialFile = z.infer<typeof MaterialFileSchema>;
129
63
  //# sourceMappingURL=material.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/asset-formats/material.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwFxB,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAEpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,iEAAiE;AACjE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMsB,CAAC;AAEtD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/asset-formats/material.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwFxB,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAEpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
@@ -78,11 +78,3 @@ const MaterialDescriptorObjectSchema = z
78
78
  })
79
79
  .strict();
80
80
  export const MaterialDescriptorSchema = MaterialDescriptorObjectSchema.describe('Material appearance properties');
81
- /** .mat.json file format for shared/reusable material assets. */
82
- export const MaterialFileSchema = z
83
- .object({
84
- version: z.number().describe('File format version'),
85
- name: z.string().describe('Human-readable material name'),
86
- material: MaterialDescriptorSchema.describe('Material definition'),
87
- })
88
- .describe('Shared material asset file (.mat.json)');
@@ -2,8 +2,8 @@ import { z } from 'zod';
2
2
  export declare const MeshDescriptorSchema: z.ZodObject<{
3
3
  type: z.ZodEnum<{
4
4
  box: "box";
5
- capsule: "capsule";
6
5
  sphere: "sphere";
6
+ capsule: "capsule";
7
7
  plane: "plane";
8
8
  cylinder: "cylinder";
9
9
  gltf: "gltf";
@@ -12,7 +12,6 @@ export declare const MeshDescriptorSchema: z.ZodObject<{
12
12
  args: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
13
13
  src: z.ZodOptional<z.ZodString>;
14
14
  node: z.ZodOptional<z.ZodString>;
15
- instances: z.ZodOptional<z.ZodString>;
16
15
  lod: z.ZodOptional<z.ZodArray<z.ZodObject<{
17
16
  distance: z.ZodNumber;
18
17
  node: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"mesh.d.ts","sourceRoot":"","sources":["../../src/asset-formats/mesh.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoExB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;kBAoBM,CAAC;AAExC,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"mesh.d.ts","sourceRoot":"","sources":["../../src/asset-formats/mesh.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2DxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;kBAgBM,CAAC;AAExC,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -21,13 +21,6 @@ const MeshDescriptorBase = z
21
21
  'Only meaningful with type: "gltf". CONSTRAINT: a skinned/animated node cannot be ' +
22
22
  'lifted out of its armature — if the named node is a SkinnedMesh (or contains one), ' +
23
23
  'resolving it throws (degrade loudly, not silently).'),
24
- instances: z
25
- .string()
26
- .optional()
27
- .describe('Path to an instance-transform asset (.instances.json: an array of ' +
28
- '[posX,posY,posZ, quatX,quatY,quatZ,quatW, scaleX,scaleY,scaleZ] tuples). Renders one ' +
29
- 'THREE.InstancedMesh (one draw call). Bulk transform data is referenced as an asset, ' +
30
- 'never inlined — keeps the document thin.'),
31
24
  lod: z
32
25
  .array(z.object({
33
26
  distance: z
@@ -43,7 +36,7 @@ const MeshDescriptorBase = z
43
36
  .optional()
44
37
  .describe('Per-entity Level-of-Detail: distance-keyed glTF sub-nodes swapped by camera distance ' +
45
38
  '(THREE.LOD). gltf-only. Gated by the environment.rendering.lod master toggle — when ' +
46
- 'off, only the closest level renders. Cannot combine with node/instances.'),
39
+ 'off, only the closest level renders. Cannot combine with node.'),
47
40
  })
48
41
  .strict();
49
42
  export const MeshDescriptorSchema = MeshDescriptorBase.refine((m) => (m.type !== 'gltf' && m.type !== 'splat') || m.src != null, {
@@ -55,10 +48,7 @@ export const MeshDescriptorSchema = MeshDescriptorBase.refine((m) => (m.type !==
55
48
  .refine((m) => m.lod == null || m.type === 'gltf', {
56
49
  message: "Mesh 'lod' is only meaningful with type: 'gltf'",
57
50
  })
58
- .refine((m) => m.instances == null || m.type !== 'splat', {
59
- message: "Mesh 'instances' is not supported with type: 'splat'",
60
- })
61
- .refine((m) => !(m.lod && (m.node || m.instances)), {
62
- message: "Mesh 'lod' cannot combine with 'node'/'instances' — LOD is the multi-level form of a node ref",
51
+ .refine((m) => !(m.lod && m.node), {
52
+ message: "Mesh 'lod' cannot combine with 'node' — LOD is the multi-level form of a node ref",
63
53
  })
64
54
  .describe('Mesh geometry definition');
@@ -12,9 +12,9 @@
12
12
  import { z } from 'zod';
13
13
  export declare const ToneMappingDescriptorSchema: z.ZodObject<{
14
14
  mode: z.ZodOptional<z.ZodEnum<{
15
- aces: "aces";
16
15
  none: "none";
17
16
  linear: "linear";
17
+ aces: "aces";
18
18
  reinhard: "reinhard";
19
19
  cineon: "cineon";
20
20
  agx: "agx";
@@ -199,9 +199,9 @@ export type PostProcessingDescriptor = z.infer<typeof PostProcessingDescriptorSc
199
199
  export declare const RenderEnvironmentSchema: z.ZodObject<{
200
200
  toneMapping: z.ZodOptional<z.ZodObject<{
201
201
  mode: z.ZodOptional<z.ZodEnum<{
202
- aces: "aces";
203
202
  none: "none";
204
203
  linear: "linear";
204
+ aces: "aces";
205
205
  reinhard: "reinhard";
206
206
  cineon: "cineon";
207
207
  agx: "agx";
@@ -4,14 +4,13 @@
4
4
  * Every authored asset format the engine validates at fetch time throws this
5
5
  * when Zod rejects the payload, naming the offending file (T4.6). It lives
6
6
  * here — beside `loader.ts`/`assets.ts` — rather than inside a format module so
7
- * every caller (the `.mat.json` parser, the input-map loader in
8
- * `input/input-manager.ts`) does not have to reach into the format half for
9
- * it.
7
+ * every caller (currently the input-map loader in `input/input-manager.ts`)
8
+ * does not have to reach into an unrelated subsystem for it.
10
9
  *
11
10
  * It was called `SceneParseError` until WO-9 task #6. The extraction that gave
12
11
  * this file its name deliberately deferred the class rename ("extraction, not
13
- * redesign"); with `.vscn` gone the old name described nothing — a `.mat.json`
14
- * or `.inputmap.json` failure is not a scene failure — so the class and its
12
+ * redesign"); with `.vscn` gone the old name described nothing — an
13
+ * `.inputmap.json` failure is not a scene failure — so the class and its
15
14
  * message header now say `asset`.
16
15
  */
17
16
  import type { ZodIssue } from 'zod';
@@ -1 +1 @@
1
- {"version":3,"file":"asset-parse-error.d.ts","sourceRoot":"","sources":["../src/asset-parse-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAEpC,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE3B,MAAM,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM;CAQlD"}
1
+ {"version":3,"file":"asset-parse-error.d.ts","sourceRoot":"","sources":["../src/asset-parse-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAEpC,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE3B,MAAM,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM;CAQlD"}
@@ -4,14 +4,13 @@
4
4
  * Every authored asset format the engine validates at fetch time throws this
5
5
  * when Zod rejects the payload, naming the offending file (T4.6). It lives
6
6
  * here — beside `loader.ts`/`assets.ts` — rather than inside a format module so
7
- * every caller (the `.mat.json` parser, the input-map loader in
8
- * `input/input-manager.ts`) does not have to reach into the format half for
9
- * it.
7
+ * every caller (currently the input-map loader in `input/input-manager.ts`)
8
+ * does not have to reach into an unrelated subsystem for it.
10
9
  *
11
10
  * It was called `SceneParseError` until WO-9 task #6. The extraction that gave
12
11
  * this file its name deliberately deferred the class rename ("extraction, not
13
- * redesign"); with `.vscn` gone the old name described nothing — a `.mat.json`
14
- * or `.inputmap.json` failure is not a scene failure — so the class and its
12
+ * redesign"); with `.vscn` gone the old name described nothing — an
13
+ * `.inputmap.json` failure is not a scene failure — so the class and its
15
14
  * message header now say `asset`.
16
15
  */
17
16
  export class AssetParseError extends Error {
package/dist/config.d.ts CHANGED
@@ -3,7 +3,14 @@
3
3
  * evaluated. The package build emits this entry as ordinary JavaScript, so
4
4
  * project config remains package-native without asking Node to execute raw
5
5
  * TypeScript or reach into an adjacent checkout.
6
+ *
7
+ * A project's `*.schema.ts` is reached from `vite.config.ts` itself (through
8
+ * `./src/data/assets`, so the dangling-ref gate can run the real Zod), which
9
+ * is why every schema-time field factory belongs here: `dataRef` and `curve`
10
+ * are both authored in a schema, and a schema module must stay loadable by
11
+ * plain Node.
6
12
  */
13
+ export { type CurveAxes, type CurvePoint, type CurveValue, curve, sampleCurve, } from './data/curve';
7
14
  export { type DataRef, dataRef, getRef } from './data/data-ref';
8
15
  export { type VgaiDataCheckOptions, vgaiDataCheck } from './data/vite-plugin-data';
9
16
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EACL,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,EACL,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/config.js CHANGED
@@ -3,6 +3,13 @@
3
3
  * evaluated. The package build emits this entry as ordinary JavaScript, so
4
4
  * project config remains package-native without asking Node to execute raw
5
5
  * TypeScript or reach into an adjacent checkout.
6
+ *
7
+ * A project's `*.schema.ts` is reached from `vite.config.ts` itself (through
8
+ * `./src/data/assets`, so the dangling-ref gate can run the real Zod), which
9
+ * is why every schema-time field factory belongs here: `dataRef` and `curve`
10
+ * are both authored in a schema, and a schema module must stay loadable by
11
+ * plain Node.
6
12
  */
13
+ export { curve, sampleCurve, } from './data/curve';
7
14
  export { dataRef, getRef } from './data/data-ref';
8
15
  export { vgaiDataCheck } from './data/vite-plugin-data';
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Curve FIELDS in data assets — a response curve a designer shapes, living
3
+ * inside an ordinary `.data.json` like any other tunable value.
4
+ *
5
+ * A curve is a FIELD TYPE, never a file type: there is no `.curve.json`, no
6
+ * curve asset class, no baked LUT, and no document. `curve(axes)` is a real
7
+ * Zod schema you drop into a `*.schema.ts` beside `z.number()`, so the value
8
+ * lives in the same data file, hot-swaps through the same `defineData` handle,
9
+ * and is edited by the same Data panel that edits everything else.
10
+ *
11
+ * The JSON a designer (or an agent) reads and writes:
12
+ *
13
+ * ```json
14
+ * { "interpolation": "smooth",
15
+ * "points": [{ "x": 0, "y": 1 }, { "x": 12, "y": 0.85 }, { "x": 30, "y": 0.2 }] }
16
+ * ```
17
+ *
18
+ * TWO MODES, NO TANGENTS. `linear` and `smooth`, and nothing else. Per-key
19
+ * tangent handles would double the JSON, make it unreadable to an agent, and
20
+ * hand every author a way to make a curve overshoot its own points. Smoothness
21
+ * is DERIVED instead — Fritsch–Carlson monotone cubic tangents, computed from
22
+ * the points themselves — so the interpolant is guaranteed to stay inside each
23
+ * segment's `[yLeft, yRight]` band. "Shape it by moving points" is the whole
24
+ * authoring model.
25
+ *
26
+ * RUNG AUDIT (recorded decision, 2026-08-14): no npm dependency. The candidate
27
+ * packages (`monotone-cubic-spline` and its siblings) are unmaintained
28
+ * micro-packages, and d3's `curveMonotoneX` is an SVG PATH GENERATOR — it
29
+ * draws, it does not sample `y` at an `x`. What we need is ~40 lines of
30
+ * well-known numerics with no API surface, so it is written here.
31
+ *
32
+ * `sampleCurve` is the entire runtime: a pure function, no class, no cache
33
+ * object, no "curve system". Game code calls it every frame from its own
34
+ * update, the same way it reads any other tuning value.
35
+ */
36
+ import { z } from 'zod';
37
+ /** One authored key: a `y` value at an `x` position. No tangents — see above. */
38
+ export interface CurvePoint {
39
+ x: number;
40
+ y: number;
41
+ }
42
+ /** A curve field's value, exactly as it sits in the `.data.json`. */
43
+ export interface CurveValue {
44
+ interpolation: 'linear' | 'smooth';
45
+ points: CurvePoint[];
46
+ }
47
+ /**
48
+ * The curve's DOMAIN, declared by the engineer in the schema (never by the
49
+ * data): what the axes mean and how far they run. The editor draws its rails
50
+ * from this and clamps every drag to it; the schema rejects a point outside
51
+ * it.
52
+ */
53
+ export interface CurveAxes {
54
+ x: {
55
+ min: number;
56
+ max: number;
57
+ label?: string;
58
+ };
59
+ y: {
60
+ min: number;
61
+ max: number;
62
+ label?: string;
63
+ };
64
+ }
65
+ /**
66
+ * A Zod schema for a data-asset FIELD holding a response curve. Use it in a
67
+ * `.schema.ts` exactly like any other field:
68
+ *
69
+ * ```ts
70
+ * export const TuningSchema = z.object({
71
+ * spawnRate: z.number().min(0).max(10).default(1),
72
+ * difficultyRamp: curve({
73
+ * x: { min: 0, max: 300, label: 'Sim time (s)' },
74
+ * y: { min: 0, max: 2, label: 'Spawn multiplier' },
75
+ * }).describe('How hard the game leans on the player as the round runs.'),
76
+ * });
77
+ * ```
78
+ *
79
+ * The schema is STRICT (an unrecognized key is an error, never a silent
80
+ * strip), demands at least two points, and enforces strictly-increasing `x`
81
+ * with every point inside the declared axes — each with a message that names
82
+ * the fix rather than the rule.
83
+ *
84
+ * The emitted JSON Schema (`toDataJsonSchema`) carries
85
+ * `"x-vgai-curve": axes` — a Zod `.meta()`, which survives `z.toJSONSchema`
86
+ * including inside a table's `additionalProperties` row schema, exactly the
87
+ * way `dataRef`'s `"x-vgai-ref"` does. That marker is what makes the editor's
88
+ * Data panel render a curve EDITOR instead of a raw-JSON cell, with no emitter
89
+ * changes anywhere.
90
+ */
91
+ export declare function curve(axes: CurveAxes): z.ZodType<CurveValue>;
92
+ /**
93
+ * Read a curve field's declared axes back off a LIVE Zod schema (as opposed to
94
+ * the emitted JSON Schema, which the editor's Data panel reads instead).
95
+ *
96
+ * This is the dev-menu capability's detection door: it derives its rows by
97
+ * walking the game's own `TuningSchema` object, so it needs the axes from the
98
+ * schema in hand. Wrappers (`.optional()`, `.default(…)`, `.describe(…)` chains
99
+ * that re-wrap) hide the metadata behind an inner type, so a bounded unwrap
100
+ * walks down to it.
101
+ */
102
+ export declare function curveAxesOf(schema: z.ZodType): CurveAxes | undefined;
103
+ /**
104
+ * The curve's value at `x` — the whole runtime API.
105
+ *
106
+ * Read it every frame from the game's own update, the way every other data
107
+ * value is read (`tuning.get()` then sample); never precompute a table, and
108
+ * never hold the result across frames — an edit to the `.data.json` hot-swaps
109
+ * underneath you and that is the point.
110
+ *
111
+ * Outside `[first.x, last.x]` the value CLAMPS to the nearest endpoint: a
112
+ * curve declares what it knows about, and extrapolating past it would invent
113
+ * numbers nobody authored.
114
+ */
115
+ export declare function sampleCurve(value: CurveValue, x: number): number;
116
+ //# sourceMappingURL=curve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"curve.d.ts","sourceRoot":"","sources":["../../src/data/curve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,iFAAiF;AACjF,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,qEAAqE;AACrE,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACnC,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AA0CD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAwB5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,GAAG,SAAS,CASpE;AAoDD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA0BhE"}