@vgai/engine 0.5.10 → 0.5.12

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 (157) 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 +89 -5
  19. package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
  20. package/dist/adapter/ingest/game-contract.js +11 -3
  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/dev/register-render-vitals.d.ts +18 -7
  55. package/dist/dev/register-render-vitals.d.ts.map +1 -1
  56. package/dist/dev/register-render-vitals.js +35 -8
  57. package/dist/ecs/user-data.d.ts +49 -1
  58. package/dist/ecs/user-data.d.ts.map +1 -1
  59. package/dist/ecs/user-data.js +34 -0
  60. package/dist/index.d.ts +2 -3
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +2 -3
  63. package/dist/manifest/index.d.ts +3 -3
  64. package/dist/manifest/index.d.ts.map +1 -1
  65. package/dist/manifest/index.js +2 -2
  66. package/dist/manifest/load.d.ts +20 -63
  67. package/dist/manifest/load.d.ts.map +1 -1
  68. package/dist/manifest/load.js +12 -103
  69. package/dist/manifest/schema.d.ts +21 -103
  70. package/dist/manifest/schema.d.ts.map +1 -1
  71. package/dist/manifest/schema.js +66 -142
  72. package/dist/pixi/index.d.ts +2 -3
  73. package/dist/pixi/index.d.ts.map +1 -1
  74. package/dist/pixi/index.js +2 -3
  75. package/dist/pixi/ingest.d.ts +7 -75
  76. package/dist/pixi/ingest.d.ts.map +1 -1
  77. package/dist/pixi/ingest.js +6 -14
  78. package/dist/pixi/scene-capture.d.ts +2 -2
  79. package/dist/pixi/scene-capture.js +2 -2
  80. package/dist/react/use-data.d.ts +10 -5
  81. package/dist/react/use-data.d.ts.map +1 -1
  82. package/dist/react/use-data.js +15 -15
  83. package/dist/render/viewport-shading.d.ts +1 -1
  84. package/dist/render/viewport-shading.d.ts.map +1 -1
  85. package/dist/render/viewport-shading.js +14 -0
  86. package/dist/runtime/create-runtime.d.ts +12 -0
  87. package/dist/runtime/create-runtime.d.ts.map +1 -1
  88. package/dist/runtime/create-runtime.js +7 -2
  89. package/dist/runtime/mount-game.d.ts +1 -1
  90. package/dist/runtime/mount-game.d.ts.map +1 -1
  91. package/dist/runtime/mount-manifest.d.ts.map +1 -1
  92. package/dist/runtime/mount-manifest.js +5 -1
  93. package/dist/world3d-react/r3f-adapter.d.ts.map +1 -1
  94. package/dist/world3d-react/r3f-adapter.js +129 -6
  95. package/dist/world3d-react/renderer-config.d.ts +15 -0
  96. package/dist/world3d-react/renderer-config.d.ts.map +1 -1
  97. package/dist/world3d-react/renderer-config.js +15 -0
  98. package/dist/world3d-react/world-context.d.ts +11 -1
  99. package/dist/world3d-react/world-context.d.ts.map +1 -1
  100. package/dist/world3d-react/world-context.js +1 -0
  101. package/dist-config/config.js +140 -20
  102. package/dist-config/config.js.map +4 -4
  103. package/package.json +1 -1
  104. package/schemas/engine-capabilities.json +10 -10
  105. package/schemas/vgai-project.schema.json +22 -73
  106. package/src/adapter/authoring.ts +54 -31
  107. package/src/adapter/body-marks.ts +69 -0
  108. package/src/adapter/constraint.ts +71 -0
  109. package/src/adapter/hierarchy-marks.ts +155 -0
  110. package/src/adapter/index.ts +2 -3
  111. package/src/adapter/ingest/contract-system-adapters.ts +174 -0
  112. package/src/adapter/ingest/game-contract.ts +104 -6
  113. package/src/adapter/ingest/scene-capture.ts +61 -11
  114. package/src/adapter/ingest/structural-ids.ts +2 -2
  115. package/src/adapter/reflection-probe.ts +75 -0
  116. package/src/asset-formats/index.ts +4 -10
  117. package/src/asset-formats/material.ts +0 -11
  118. package/src/asset-formats/mesh.ts +3 -16
  119. package/src/asset-parse-error.ts +4 -5
  120. package/src/config.ts +13 -0
  121. package/src/data/curve.ts +263 -0
  122. package/src/data/vite-plugin-data.ts +48 -14
  123. package/src/dev/performance-profiler.ts +21 -2
  124. package/src/dev/register-render-vitals.ts +38 -8
  125. package/src/ecs/user-data.ts +50 -0
  126. package/src/index.ts +2 -3
  127. package/src/manifest/index.ts +3 -15
  128. package/src/manifest/load.ts +33 -139
  129. package/src/manifest/schema.ts +72 -181
  130. package/src/pixi/index.ts +2 -15
  131. package/src/pixi/ingest.ts +13 -87
  132. package/src/pixi/scene-capture.ts +2 -2
  133. package/src/react/use-data.ts +15 -20
  134. package/src/render/viewport-shading.ts +16 -1
  135. package/src/runtime/create-runtime.ts +30 -5
  136. package/src/runtime/mount-game.ts +1 -1
  137. package/src/runtime/mount-manifest.ts +5 -1
  138. package/src/world3d-react/r3f-adapter.tsx +142 -6
  139. package/src/world3d-react/renderer-config.ts +31 -0
  140. package/src/world3d-react/world-context.ts +11 -1
  141. package/dist/asset-formats/instances.d.ts +0 -17
  142. package/dist/asset-formats/instances.d.ts.map +0 -1
  143. package/dist/asset-formats/instances.js +0 -31
  144. package/dist/asset-formats/parse.d.ts +0 -20
  145. package/dist/asset-formats/parse.d.ts.map +0 -1
  146. package/dist/asset-formats/parse.js +0 -34
  147. package/dist/pixi/ingest-iframe.d.ts +0 -82
  148. package/dist/pixi/ingest-iframe.d.ts.map +0 -1
  149. package/dist/pixi/ingest-iframe.js +0 -166
  150. package/dist/render/instance-mesh.d.ts +0 -5
  151. package/dist/render/instance-mesh.d.ts.map +0 -1
  152. package/dist/render/instance-mesh.js +0 -19
  153. package/schemas/mat.schema.json +0 -255
  154. package/src/asset-formats/instances.ts +0 -38
  155. package/src/asset-formats/parse.ts +0 -39
  156. package/src/pixi/ingest-iframe.ts +0 -255
  157. package/src/render/instance-mesh.ts +0 -25
@@ -3,14 +3,13 @@ import { installSceneCapture2D } from './scene-capture';
3
3
  * Mount an UNMODIFIED PixiJS game via the shared-instance capture path — the 2D
4
4
  * analog of `mountIngestGame`. Installs the render trap on the host's pixi
5
5
  * instance, runs the game's `load()`, waits for the game to render its first
6
- * frame (capturing its live stage), and exposes loop gating + cleanup. If capture
7
- * times out (pixi unreachable / bundled / mismatched), degrades to embed-only
8
- * never a silent failure.
6
+ * frame (capturing its live stage), and exposes loop gating + cleanup. A game
7
+ * whose pixi the trap cannot reach never captures, and the mount FAILS by name.
9
8
  */
10
9
  export async function mountIngestGame2D(pixiNamespace, game, opts = {}) {
11
10
  const capture = installSceneCapture2D(pixiNamespace);
12
11
  try {
13
- await game.load?.();
12
+ await game.load();
14
13
  }
15
14
  catch (err) {
16
15
  capture.uninstall();
@@ -22,19 +21,12 @@ export async function mountIngestGame2D(pixiNamespace, game, opts = {}) {
22
21
  return {
23
22
  stage: rt.stage,
24
23
  capture,
25
- embedOnly: false,
26
24
  setPaused: (p) => capture.setPaused(p),
27
25
  dispose: () => capture.uninstall(),
28
26
  };
29
27
  }
30
- catch {
31
- // Capture failed → pixi unreachable/mismatched → degrade to embed-only.
32
- return {
33
- stage: null,
34
- capture,
35
- embedOnly: true,
36
- setPaused: () => { },
37
- dispose: () => capture.uninstall(),
38
- };
28
+ catch (err) {
29
+ capture.uninstall();
30
+ throw new Error(`pixi ingest: game "${game.id}" rendered no capturable frame within ${timeout}ms: ${err}`);
39
31
  }
40
32
  }
@@ -14,8 +14,8 @@
14
14
  * CRITICAL (same module-identity gatekeeper as the 3D path): the trap must be
15
15
  * installed on the SAME `pixi.js` module instance the game uses. A bundler/dev-server
16
16
  * that dedupes `pixi.js` makes an ESM game's `import 'pixi.js'` resolve to the host
17
- * instance, so it is trapped; a game bundling its own pixi cannot be captured this
18
- * way (degrade to iframe-reachable or opaque-embed tiers — see the spec).
17
+ * instance, so it is trapped; a game bundling its own pixi cannot be captured at
18
+ * all, and its mount fails by name.
19
19
  */
20
20
  /** A live Pixi runtime captured from an external PixiJS game. */
21
21
  export interface CapturedRuntime2D {
@@ -14,8 +14,8 @@
14
14
  * CRITICAL (same module-identity gatekeeper as the 3D path): the trap must be
15
15
  * installed on the SAME `pixi.js` module instance the game uses. A bundler/dev-server
16
16
  * that dedupes `pixi.js` makes an ESM game's `import 'pixi.js'` resolve to the host
17
- * instance, so it is trapped; a game bundling its own pixi cannot be captured this
18
- * way (degrade to iframe-reachable or opaque-embed tiers — see the spec).
17
+ * instance, so it is trapped; a game bundling its own pixi cannot be captured at
18
+ * all, and its mount fails by name.
19
19
  */
20
20
  /**
21
21
  * Install the render trap on `pixiNamespace.Application.prototype.render`. Pass the
@@ -50,11 +50,16 @@ export declare function useData<T>(handle: DataHandle<T>): T;
50
50
  * this rejects with a teaching error (a shipped game could never reach the
51
51
  * route anyway — builds strip `src/tools/` entirely, §4).
52
52
  *
53
- * Serialization matches the editor Data panel's diff-minimal contract:
54
- * `"$schema"` first, 2-space indent, trailing newline. When `value` carries
55
- * no `"$schema"` key (the common case`DataHandle.get()` strips it), the
56
- * conventional sibling reference (`./<name>.schema.json`, §2.1) is restored
57
- * so a tool write never silently drops VS Code validation from the file.
53
+ * The body is PARSED VALUES, never serialized text: the dev server's fold
54
+ * (`packages/editor/server/data-file-serialize.ts`) owns key order and the
55
+ * `"$schema"`-first diff-minimal serialization, and it must a parsed JS
56
+ * object has already reindexed integer-like keys ("1","2","10"), so only the
57
+ * server, which still has the file's raw text, can keep a one-field write a
58
+ * one-line diff. When `value` carries no `"$schema"` key (the common case —
59
+ * `DataHandle.get()` strips it), the conventional sibling reference
60
+ * (`./<name>.schema.json`, §2.1) is restored so a tool write never silently
61
+ * drops VS Code validation from the file. Undo for data writes is git;
62
+ * every accepted write is recorded server-side as a project revision.
58
63
  */
59
64
  export declare function writeData(projectRelativePath: string, value: Record<string, unknown>): Promise<void>;
60
65
  //# sourceMappingURL=use-data.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-data.d.ts","sourceRoot":"","sources":["../../src/react/use-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAKnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,SAAS,CAC7B,mBAAmB,EAAE,MAAM,EAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAqDf"}
1
+ {"version":3,"file":"use-data.d.ts","sourceRoot":"","sources":["../../src/react/use-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAKnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,SAAS,CAC7B,mBAAmB,EAAE,MAAM,EAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CA2Cf"}
@@ -52,11 +52,16 @@ export function useData(handle) {
52
52
  * this rejects with a teaching error (a shipped game could never reach the
53
53
  * route anyway — builds strip `src/tools/` entirely, §4).
54
54
  *
55
- * Serialization matches the editor Data panel's diff-minimal contract:
56
- * `"$schema"` first, 2-space indent, trailing newline. When `value` carries
57
- * no `"$schema"` key (the common case`DataHandle.get()` strips it), the
58
- * conventional sibling reference (`./<name>.schema.json`, §2.1) is restored
59
- * so a tool write never silently drops VS Code validation from the file.
55
+ * The body is PARSED VALUES, never serialized text: the dev server's fold
56
+ * (`packages/editor/server/data-file-serialize.ts`) owns key order and the
57
+ * `"$schema"`-first diff-minimal serialization, and it must a parsed JS
58
+ * object has already reindexed integer-like keys ("1","2","10"), so only the
59
+ * server, which still has the file's raw text, can keep a one-field write a
60
+ * one-line diff. When `value` carries no `"$schema"` key (the common case —
61
+ * `DataHandle.get()` strips it), the conventional sibling reference
62
+ * (`./<name>.schema.json`, §2.1) is restored so a tool write never silently
63
+ * drops VS Code validation from the file. Undo for data writes is git;
64
+ * every accepted write is recorded server-side as a project revision.
60
65
  */
61
66
  export async function writeData(projectRelativePath, value) {
62
67
  if (!projectRelativePath.startsWith('src/data/') || !projectRelativePath.endsWith('.data.json')) {
@@ -64,27 +69,22 @@ export async function writeData(projectRelativePath, value) {
64
69
  'src/data/**/*.data.json, addressed project-relative, ' +
65
70
  "e.g. writeData('src/data/tuning.data.json', next).");
66
71
  }
67
- // "$schema" first for minimal diffs; restore the conventional sibling
68
- // reference when the caller's object (typically `{ ...handle.get() }`,
69
- // which never carries it) omits the line.
72
+ // Restore the conventional sibling "$schema" reference when the caller's
73
+ // object (typically `{ ...handle.get() }`, which never carries it) omits
74
+ // it; the server fold serializes it first.
70
75
  const { $schema, ...rest } = value;
71
76
  const schemaRef = $schema ??
72
77
  `./${projectRelativePath
73
78
  .split('/')
74
79
  .pop()
75
80
  ?.replace(/\.data\.json$/, '')}.schema.json`;
76
- const content = `${JSON.stringify({ $schema: schemaRef, ...rest }, null, 2)}\n`;
77
- const transactionalWriter = globalThis.__vgaiHistoryWriteData;
78
- if (transactionalWriter) {
79
- await transactionalWriter(projectRelativePath, content);
80
- return;
81
- }
81
+ const values = { $schema: schemaRef, ...rest };
82
82
  let res;
83
83
  try {
84
84
  res = await fetch('/__editor/data-file', {
85
85
  method: 'POST',
86
86
  headers: { 'Content-Type': 'application/json' },
87
- body: JSON.stringify({ path: projectRelativePath, content }),
87
+ body: JSON.stringify({ path: projectRelativePath, values }),
88
88
  });
89
89
  }
90
90
  catch (err) {
@@ -1,6 +1,6 @@
1
1
  import * as THREE from 'three';
2
2
  /** Temporary developer-facing shading modes. These never become scene data. */
3
- export type ViewportShadingMode = 'solid' | 'unlit' | 'wireframe' | 'normals' | 'overdraw';
3
+ export type ViewportShadingMode = 'solid' | 'clay' | 'unlit' | 'wireframe' | 'normals' | 'overdraw';
4
4
  /**
5
5
  * Applies a render-only material view and restores every native material in a
6
6
  * `finally` block. Gameplay and authoring therefore always observe the real
@@ -1 +1 @@
1
- {"version":3,"file":"viewport-shading.d.ts","sourceRoot":"","sources":["../../src/render/viewport-shading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AAoB3F;;;;GAIG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IACpE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CASvB;IAEH,MAAM,CACJ,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE,MAAM,IAAI,EAChB,OAAO,GAAE,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,OAAoB,GAClD,IAAI;IA0BP,OAAO,IAAI,IAAI;IAUf,OAAO,CAAC,YAAY;CAgCrB"}
1
+ {"version":3,"file":"viewport-shading.d.ts","sourceRoot":"","sources":["../../src/render/viewport-shading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AAqBpG;;;;GAIG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IACpE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CASvB;IAEH,MAAM,CACJ,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE,MAAM,IAAI,EAChB,OAAO,GAAE,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,OAAoB,GAClD,IAAI;IA0BP,OAAO,IAAI,IAAI;IAWf,OAAO,CAAC,YAAY;CA6CrB"}
@@ -49,6 +49,7 @@ export class ViewportShadingRenderer {
49
49
  }
50
50
  dispose() {
51
51
  for (const pair of this._derived.values()) {
52
+ pair.clay.dispose();
52
53
  pair.unlit.dispose();
53
54
  pair.wireframe.dispose();
54
55
  }
@@ -77,6 +78,19 @@ export class ViewportShadingRenderer {
77
78
  fog: material.fog ?? true,
78
79
  };
79
80
  pair = {
81
+ clay: new THREE.MeshStandardMaterial({
82
+ color: 0xaeb6c0,
83
+ roughness: 0.82,
84
+ metalness: 0,
85
+ flatShading: true,
86
+ alphaMap: textureOf(material, 'alphaMap'),
87
+ alphaTest: material.alphaTest,
88
+ opacity: material.opacity,
89
+ transparent: material.transparent,
90
+ side: material.side,
91
+ depthTest: material.depthTest,
92
+ depthWrite: material.depthWrite,
93
+ }),
80
94
  unlit: new THREE.MeshBasicMaterial(common),
81
95
  wireframe: new THREE.MeshBasicMaterial({ ...common, wireframe: true }),
82
96
  };
@@ -180,6 +180,18 @@ export interface RootsRuntimeConfig {
180
180
  * a 2D canvas renderer with no GPU. Never set `true` in a real host.
181
181
  */
182
182
  headless?: boolean | undefined;
183
+ /**
184
+ * `vgai.project.json`'s `rendering.antialias` — whether every three root's
185
+ * WebGL context is built with a multisampled drawing buffer.
186
+ *
187
+ * It is a RUNTIME-CONFIG option rather than a world's own
188
+ * `WorldRendererConfig` field for the reason that file's header gives: a
189
+ * context's sample count is fixed at CREATION, before any world exists, so
190
+ * there is no honest moment at which a world could ask for it. The
191
+ * manifest-aware boot path (`mount-manifest.ts`) is the real reader;
192
+ * omitting it leaves `createHostRenderer`'s own registry default alone.
193
+ */
194
+ antialias?: boolean | undefined;
183
195
  /** D15 (T-D15.1) — the root seed `ctx.random` boots from on every world
184
196
  * mounted onto this session's Game, forwarded to `createGame` BEFORE any
185
197
  * world's `mount()`/`setup()` runs (this function constructs the Game
@@ -1 +1 @@
1
- {"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/create-runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/create-runtime.ts"],"names":[],"mappings":"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"}
@@ -130,10 +130,14 @@ function createHeadlessRendererStub() {
130
130
  * `createRootsGameRuntime` purely to keep that function's own branching
131
131
  * simple — see `mountOnePixiRoot` for the canvas sibling. */
132
132
  async function mountOneThreeRoot(spec, ctx) {
133
- const { game, canvas, w, h, dpr, isBottom, headless, assets } = ctx;
133
+ const { game, canvas, w, h, dpr, isBottom, headless, assets, antialias } = ctx;
134
134
  const renderer = headless
135
135
  ? createHeadlessRendererStub()
136
- : createHostRenderer(canvas, w, h, undefined, {
136
+ : createHostRenderer(canvas, w, h,
137
+ // The manifest's `rendering.antialias` reaches the WebGL context here and NOWHERE else:
138
+ // `createHostRenderer` passes it straight to the constructor, and the sample count is
139
+ // fixed from that moment. Omitted → the render-settings registry's own default.
140
+ antialias === undefined ? undefined : { antialias }, {
137
141
  alpha: !isBottom,
138
142
  preserveDrawingBuffer: true,
139
143
  });
@@ -562,6 +566,7 @@ async function createRootsGameRuntime(config) {
562
566
  dpr,
563
567
  headless,
564
568
  assets,
569
+ antialias: config.antialias,
565
570
  });
566
571
  // --- Delegating input router (D5 §2a) ---
567
572
  const router = createInputRouter(container, routerEntries);
@@ -29,7 +29,7 @@ export interface ManifestHost {
29
29
  /** Resolve asset/scene URLs relative to the project — forwarded to a
30
30
  * registered {@link AdapterSurfaceFactory} via {@link AdapterSurfaceFactoryContext},
31
31
  * never called by this module itself (a factory only needs it for a
32
- * non-default resolution scheme, e.g. a hosted-editor iframe). */
32
+ * non-default resolution scheme, e.g. a project served under a base path). */
33
33
  resolveUrl?(path: string): string;
34
34
  readonly width?: number | undefined;
35
35
  readonly height?: number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"mount-game.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-game.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,UAAU,EAAuC,MAAM,kBAAkB,CAAC;AAQxF;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;6DACyD;IACzD,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD;;;uEAGmE;IACnE,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;gEAC4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACzC;AAED,+EAA+E;AAC/E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,KAAK,EAAE,mBAAmB,EAC1B,GAAG,EAAE,4BAA4B,KAC9B,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAQtC;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAUlF;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D;AAcD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,EAAE,qBAexC,CAAC;AAMF,MAAM,WAAW,gBAAgB;IAC/B;;;kEAG8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC;CACrE;AAgBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,OAAO,EACtB,IAAI,EAAE,YAAY,EAClB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,CAAC,CAyCtB"}
1
+ {"version":3,"file":"mount-game.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-game.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,UAAU,EAAuC,MAAM,kBAAkB,CAAC;AAQxF;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;6DACyD;IACzD,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD;;;mFAG+E;IAC/E,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;gEAC4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACzC;AAED,+EAA+E;AAC/E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,KAAK,EAAE,mBAAmB,EAC1B,GAAG,EAAE,4BAA4B,KAC9B,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAQtC;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAUlF;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D;AAcD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,EAAE,qBAexC,CAAC;AAMF,MAAM,WAAW,gBAAgB;IAC/B;;;kEAG8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC;CACrE;AAgBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,OAAO,EACtB,IAAI,EAAE,YAAY,EAClB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,WAAW,CAAC,CAyCtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"mount-manifest.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mount-manifest.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-manifest.ts"],"names":[],"mappings":"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"}
@@ -120,7 +120,7 @@ function resolveThreeAdapter(world, entry) {
120
120
  if (world.adapter.type === 'ingest') {
121
121
  throw new Error(`mountManifestRoots: world "${world.id}" (three) declares an { ingest } adapter — ` +
122
122
  "ingest roots require the editor's dev-server-backed mount machinery (an EditorStore " +
123
- "plus iframe/DOM capture, see adapter-resolver.ts's resolveIngestThreeAdapter) and are " +
123
+ "plus in-realm scene capture, see adapter-resolver.ts's resolveIngestThreeAdapter) and are " +
124
124
  'not supported by mountManifestRoots (no porting aids, no hosted ingest routes).');
125
125
  }
126
126
  // type === 'default'
@@ -252,6 +252,10 @@ export async function mountManifestRoots(opts) {
252
252
  width: opts.width ?? manifest.resolution?.width,
253
253
  height: opts.height ?? manifest.resolution?.height,
254
254
  headless: opts.headless,
255
+ // `rendering.antialias` reaches the WebGL context at CONSTRUCTION and can be honoured
256
+ // nowhere else — see the manifest schema's own `rendering` block and
257
+ // `world3d-react/renderer-config.ts`'s header for why it is not a world-level declaration.
258
+ ...(manifest.rendering === undefined ? {} : { antialias: manifest.rendering.antialias }),
255
259
  seed: resolvedSeed,
256
260
  playtest: opts.playtest,
257
261
  });
@@ -1 +1 @@
1
- {"version":3,"file":"r3f-adapter.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-adapter.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AASH,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAGlF,OAAO,EAA4B,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGvF,sEAAsE;AACtE,MAAM,WAAW,uBAAuB;IACtC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;uBAEmB;IACnB,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B;;;;0CAIsC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD;;;iDAG6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACrD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,WAAW,CA2W9E"}
1
+ {"version":3,"file":"r3f-adapter.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-adapter.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AASH,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAalF,OAAO,EAA4B,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAYvF,sEAAsE;AACtE,MAAM,WAAW,uBAAuB;IACtC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;uBAEmB;IACnB,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B;;;;0CAIsC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD;;;iDAG6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACrD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,WAAW,CAge9E"}
@@ -20,7 +20,13 @@
20
20
  */
21
21
  import { advance, createRoot, extend, events as pointerEvents, } from '@react-three/fiber';
22
22
  import { createElement } from 'react';
23
+ import { registerRenderVitals } from '../dev/register-render-vitals';
24
+ import { createRenderDebugAdapter, frameCaptureContextFor, } from '../dev/render-debug-adapter';
25
+ import { collectRenderMemory } from '../dev/render-memory';
26
+ import { RENDER_SUBMIT_PHASE } from '../dev/render-vitals';
27
+ import { createWebGLFrameCapture } from '../dev/webgl-frame-capture';
23
28
  import { WorldProvider } from '../react/world-state';
29
+ import { devLayersEnabled } from '../runtime/dev-layers';
24
30
  import { EngineBridge } from './engine-bridge';
25
31
  import { applyWorldRendererConfig } from './renderer-config';
26
32
  import { createR3FRootContext } from './world-context';
@@ -279,6 +285,71 @@ export function createR3FAdapter(options) {
279
285
  // `RootState` for precisely this reason, so reading it per frame is the
280
286
  // supported way to see the live root. It is a plain map read.
281
287
  const live = () => state.get();
288
+ // --- Live render vitals (issue #1504), for an R3F world -----------------
289
+ // The SAME door the classic adapter seeds
290
+ // (`../adapter/setup-three-root-adapter.ts`), seeded here for the same
291
+ // reason: a running game must be able to explain its own frame cost
292
+ // through the debug registry, with no capability to install and nothing
293
+ // for a game to write. It has to be seeded in BOTH adapters because they
294
+ // are two independent mount paths onto the same `Game` — and a TSX/R3F
295
+ // world is the only shape a scaffolded project's three root has, so a
296
+ // door wired only into the classic path is a door no scaffolded project
297
+ // ever gets (issue #1518: `game.state('render.vitals')` answered "no
298
+ // state provider registered" in the field while every other dev layer of
299
+ // the same world worked).
300
+ //
301
+ // The gate is the same three conditions, minus the one that cannot
302
+ // arise: `devLayersEnabled()` (`../runtime/dev-layers.ts`, the ONE owner
303
+ // of "is this a dev context" — a ship build registers nothing and pays
304
+ // nothing), and a `Game` shell (the readings are folded out of that
305
+ // game's profiler frames). "Not headless" needs no term here: a headless
306
+ // mount returned above, before fiber was ever configured.
307
+ //
308
+ // Two module instances, one answer: under the packaged editor this
309
+ // module is served out of the PROJECT's own Vite graph (see
310
+ // `packages/editor/vite-plugin-react-world-runtime.ts` — the packaged
311
+ // shell imports `resolveR3FEntryAdapter` through the project-rooted
312
+ // server precisely so fiber/react/three identity is the project's), so
313
+ // `import.meta.env.DEV` here is the project server's `true`, not the
314
+ // prebuilt shell's `false`.
315
+ //
316
+ // OWNER of the registration+fold: this mount, ended by `dispose()` below
317
+ // (the fold) and `runtime.dispose()`'s scoped `strip(id)` (the
318
+ // registrations) — the same split the classic adapter documents.
319
+ let renderVitals = null;
320
+ if (host.game && devLayersEnabled()) {
321
+ // Same auto-enable as the classic adapter: the readings are folded out
322
+ // of profiler frames, and the profiler is a flag the editor already
323
+ // sets on play — under the dev gate this is the same cost arriving a
324
+ // little earlier, not a new one.
325
+ host.game.profiler.enabled = true;
326
+ renderVitals = registerRenderVitals({
327
+ registry: runtime.debugRegistry,
328
+ worldId: id,
329
+ profiler: host.game.profiler,
330
+ scene: live().scene,
331
+ renderer: host.renderer,
332
+ });
333
+ }
334
+ // Engine-owned render introspection, built over the SAME renderer and
335
+ // scene Fiber uses. A design-time stand-in has no context and a
336
+ // headless mount returned above, so both honestly omit the capability.
337
+ // `frameCaptureContextFor` is the same construction gate as the classic
338
+ // Three adapter; no editor-side renderer inference is involved.
339
+ const rendererContext = typeof host.renderer.getContext === 'function' ? host.renderer.getContext() : undefined;
340
+ const frameCaptureContext = frameCaptureContextFor(false, rendererContext);
341
+ const frameCapture = frameCaptureContext
342
+ ? createWebGLFrameCapture(frameCaptureContext)
343
+ : null;
344
+ const renderDebugWiring = frameCapture
345
+ ? createRenderDebugAdapter({
346
+ capture: frameCapture,
347
+ scene: state.scene,
348
+ memory: () => collectRenderMemory(live().scene, host.renderer.info),
349
+ })
350
+ : null;
351
+ if (renderDebugWiring)
352
+ runtime.systemAdapters.renderDebug = renderDebugWiring.adapter;
282
353
  // The engine drives every `useFrame` through the mounted world's
283
354
  // `update(dt)` hook, never off a raw host-loop callback. That is the
284
355
  // whole pause story: `runFrameImpl` (`runtime/game.ts`) calls
@@ -330,9 +401,10 @@ export function createR3FAdapter(options) {
330
401
  return live().camera;
331
402
  },
332
403
  drivesOwnLoop: false,
333
- // Adapter surface: `debug` pre-seeded (the shared game registry's
334
- // adapter); game code adds capabilities via
335
- // `ctx.registerSystemAdapter` exactly as in a classic world.
404
+ // Adapter surface: `debug` (the shared game registry) and, when a real
405
+ // WebGL2 context exists, `renderDebug` are engine-seeded. Game code
406
+ // adds its own capabilities via `ctx.registerSystemAdapter` exactly
407
+ // as in a classic world.
336
408
  systems: runtime.systemAdapters,
337
409
  update(dt) {
338
410
  elapsed += dt;
@@ -350,15 +422,66 @@ export function createR3FAdapter(options) {
350
422
  // then fiber's advance (useFrame callbacks + the actual render see
351
423
  // the fresh state). Both are host-gated: neither runs while frozen.
352
424
  systems.run(dt);
353
- advance(elapsed, true, current);
425
+ renderDebugWiring?.beforeRender();
426
+ try {
427
+ const profiler = host.game?.profiler;
428
+ if (!profiler?.enabled) {
429
+ advance(elapsed, true, current);
430
+ return;
431
+ }
432
+ // Issue #1504's measurement, produced where the draw actually
433
+ // happens. `advance()` under `frameloop: 'never'` is what calls
434
+ // `gl.render(scene, camera)`, so this bracket — not a phase span
435
+ // inside `systems` — is the frame's CPU submission cost, and it is
436
+ // also what makes this frame a PRESENTATION as far as the vitals
437
+ // fold is concerned (`../dev/render-vitals.ts`: no bracket, no
438
+ // display frame). The profiler's phase clock is a stack, so
439
+ // bracketing here cannot truncate an enclosing phase.
440
+ const info = host.renderer.info;
441
+ const passesBefore = info?.render.frame ?? 0;
442
+ profiler.beginPhase();
443
+ try {
444
+ advance(elapsed, true, current);
445
+ }
446
+ finally {
447
+ profiler.endPhase(RENDER_SUBMIT_PHASE);
448
+ }
449
+ // Checked, not assumed — a duck-typed/design-time renderer supplies
450
+ // only what a mount needs, and a mount with no counters must report
451
+ // NOTHING rather than throw once per frame (the classic adapter's
452
+ // `postFrame` pays for the same assumption for the same reason).
453
+ // `gpuMs` is null: this path runs no GPU timer, and the profiler
454
+ // keeps the previous reading rather than inventing a zero.
455
+ if (info) {
456
+ profiler.reportRender({
457
+ gpuMs: null,
458
+ drawCalls: info.render.calls,
459
+ triangles: info.render.triangles,
460
+ geometries: info.memory.geometries,
461
+ textures: info.memory.textures,
462
+ renderPasses: info.render.frame - passesBefore,
463
+ });
464
+ }
465
+ }
466
+ finally {
467
+ renderDebugWiring?.afterRender();
468
+ }
354
469
  },
355
470
  resize(width, height) {
356
471
  live().setSize(width, height);
357
472
  },
358
473
  dispose() {
359
- // Unmount FIRST so component effect cleanups run, then tear the
360
- // runtime down (scoped debug-registry strip).
474
+ // Reject/restore a pending capture while its renderables still
475
+ // exist, then unmount component effects and strip runtime state.
476
+ renderDebugWiring?.dispose();
361
477
  root.unmount();
478
+ // The vitals fold owns two `profiler.subscribe` registrations, and
479
+ // `runtime.dispose()`'s `strip(id)` removes the REGISTRATIONS only —
480
+ // this is the one path that ends the subscriptions, exactly as the
481
+ // classic adapter's teardown documents. Before the strip, so a
482
+ // subscription can never outlive the door it feeds.
483
+ renderVitals?.dispose();
484
+ renderVitals = null;
362
485
  runtime.dispose();
363
486
  restoreRendererConfig();
364
487
  },
@@ -36,11 +36,26 @@ export type WorldToneMapping = 'none' | 'linear' | 'reinhard' | 'cineon' | 'aces
36
36
  * result is already in display space and encoding it a second time washes the frame out.
37
37
  */
38
38
  export type WorldOutputColorSpace = 'srgb' | 'srgb-linear';
39
+ /**
40
+ * The shadow-map filter, named as data rather than as three's numeric enum.
41
+ *
42
+ * This is a renderer INSTANCE property (`WebGLRenderer.shadowMap.type`), not a context attribute,
43
+ * so unlike MSAA it has an honest moment at which a world can ask for it — which is the whole test
44
+ * this file's header states. A source engine that declares its own shadow filter (Godot 3's
45
+ * `rendering/quality/shadows/filter_mode`) would otherwise inherit whatever the host built with.
46
+ */
47
+ export type WorldShadowMapType = 'basic' | 'pcf' | 'pcf-soft' | 'vsm';
39
48
  /** What a world may declare about the renderer that draws it. Every field is optional; see header. */
40
49
  export interface WorldRendererConfig {
41
50
  readonly toneMapping?: WorldToneMapping | undefined;
42
51
  readonly toneMappingExposure?: number | undefined;
43
52
  readonly outputColorSpace?: WorldOutputColorSpace | undefined;
53
+ /**
54
+ * `WebGLRenderer.shadowMap.type`. Writing it after a shadow map has already been built needs
55
+ * `shadowMap.needsUpdate`, which this function sets — three caches the compiled depth material
56
+ * per type and would otherwise keep filtering with the previous one.
57
+ */
58
+ readonly shadowMapType?: WorldShadowMapType | undefined;
44
59
  /**
45
60
  * The colour the frame is cleared to, as a CSS hex string. The renderer's existing clear ALPHA
46
61
  * is preserved: a stacked canvas is transparent on purpose (`create-runtime.ts` gives every
@@ -1 +1 @@
1
- {"version":3,"file":"renderer-config.d.ts","sourceRoot":"","sources":["../../src/world3d-react/renderer-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,mGAAmG;AACnG,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,MAAM,GACN,KAAK,GACL,SAAS,CAAC;AAEd;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,aAAa,CAAC;AAE3D,sGAAsG;AACtG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC9D;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,KAAK,EACnB,QAAQ,EAAE,KAAK,CAAC,aAAa,EAC7B,MAAM,EAAE,mBAAmB,GAC1B,MAAM,IAAI,CAgEZ"}
1
+ {"version":3,"file":"renderer-config.d.ts","sourceRoot":"","sources":["../../src/world3d-react/renderer-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,mGAAmG;AACnG,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,MAAM,GACN,KAAK,GACL,SAAS,CAAC;AAEd;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,aAAa,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,KAAK,GAAG,UAAU,GAAG,KAAK,CAAC;AAEtE,sGAAsG;AACtG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC9D;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,KAAK,EACnB,QAAQ,EAAE,KAAK,CAAC,aAAa,EAC7B,MAAM,EAAE,mBAAmB,GAC1B,MAAM,IAAI,CA+EZ"}
@@ -56,6 +56,12 @@ export function applyWorldRendererConfig(three, renderer, config) {
56
56
  srgb: three.SRGBColorSpace,
57
57
  'srgb-linear': three.LinearSRGBColorSpace,
58
58
  };
59
+ const shadowMapTypes = {
60
+ basic: three.BasicShadowMap,
61
+ pcf: three.PCFShadowMap,
62
+ 'pcf-soft': three.PCFSoftShadowMap,
63
+ vsm: three.VSMShadowMap,
64
+ };
59
65
  const restores = [];
60
66
  if (config.toneMapping !== undefined) {
61
67
  const previous = renderer.toneMapping;
@@ -78,6 +84,15 @@ export function applyWorldRendererConfig(three, renderer, config) {
78
84
  renderer.outputColorSpace = previous;
79
85
  });
80
86
  }
87
+ if (config.shadowMapType !== undefined && renderer.shadowMap !== undefined) {
88
+ const previous = renderer.shadowMap.type;
89
+ renderer.shadowMap.type = shadowMapTypes[config.shadowMapType];
90
+ renderer.shadowMap.needsUpdate = true;
91
+ restores.push(() => {
92
+ renderer.shadowMap.type = previous;
93
+ renderer.shadowMap.needsUpdate = true;
94
+ });
95
+ }
81
96
  if (config.clearColor !== undefined) {
82
97
  const previousColor = new three.Color();
83
98
  renderer.getClearColor(previousColor);
@@ -35,6 +35,7 @@ import type * as THREE from 'three';
35
35
  import type { ThreeHostContext } from '../adapter';
36
36
  import type { SystemAdapters } from '../adapter/system-adapter';
37
37
  import { createSystemRunner } from '../core/system-runner';
38
+ import { type DebugRegistry } from '../runtime/debug-registry';
38
39
  import type { GameContext } from '../runtime/types';
39
40
  /** The classic adapter's default input-map path — the conventional location
40
41
  * every scaffolded project ships (`public/inputmaps/default.inputmap.json`). */
@@ -97,8 +98,17 @@ export interface R3FRootRuntime {
97
98
  /** The world-local phase runner `mount().update(dt)` ticks. */
98
99
  readonly systems: ReturnType<typeof createSystemRunner>;
99
100
  /** The mounted world's `SystemAdapters` bag (`mounted.systems`) —
100
- * `ctx.registerSystemAdapter` writes into it; `debug` is pre-seeded. */
101
+ * `ctx.registerSystemAdapter` writes into it; `debug` is pre-seeded here,
102
+ * and the R3F mount adds renderer-backed engine capabilities after commit. */
101
103
  readonly systemAdapters: SystemAdapters;
104
+ /** The registry every registration of this world's lands in — the game's
105
+ * own when a `Game` hosts it, a private mount-local one otherwise. Exposed
106
+ * (rather than re-derived by the caller) because `createR3FAdapter` seeds
107
+ * the render-vitals door onto THIS registry after fiber's first commit
108
+ * resolves the scene, and two `getDebugRegistry` calls that are "obviously"
109
+ * the same object is exactly the second source of truth the classic
110
+ * adapter's single `debugRegistry` local avoids. */
111
+ readonly debugRegistry: DebugRegistry;
102
112
  /** Resolves once the input map load settles (immediately when skipped).
103
113
  * Never rejects — a failed load reports loudly and resolves. */
104
114
  readonly inputMapReady: Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"world-context.d.ts","sourceRoot":"","sources":["../../src/world3d-react/world-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgCK;AAEL,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAOhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAQ3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;iFACiF;AACjF,eAAO,MAAM,sBAAsB,qCAAqC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,WAAW,EACT,OAAO,GACP,QAAQ,GACR,YAAY,GACZ,OAAO,GACP,QAAQ,GACR,SAAS,GACT,OAAO,GACP,OAAO,GACP,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,GACV,uBAAuB,CAC1B,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC;gFAC4E;IAC5E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACnD;AAED;+EAC+E;AAC/E,MAAM,WAAW,cAAc;IAC7B;6EACyE;IACzE,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;IACxD;6EACyE;IACzE,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;qEACiE;IACjE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC;;;4DAGwD;IACxD,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IAC/D;;gFAE4E;IAC5E,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CAqKhB"}
1
+ {"version":3,"file":"world-context.d.ts","sourceRoot":"","sources":["../../src/world3d-react/world-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgCK;AAEL,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAOhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;iFACiF;AACjF,eAAO,MAAM,sBAAsB,qCAAqC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,WAAW,EACT,OAAO,GACP,QAAQ,GACR,YAAY,GACZ,OAAO,GACP,QAAQ,GACR,SAAS,GACT,OAAO,GACP,OAAO,GACP,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,GACV,uBAAuB,CAC1B,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC;gFAC4E;IAC5E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACnD;AAED;+EAC+E;AAC/E,MAAM,WAAW,cAAc;IAC7B;6EACyE;IACzE,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;IACxD;;mFAE+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;;;;;;yDAMqD;IACrD,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC;qEACiE;IACjE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC;;;4DAGwD;IACxD,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IAC/D;;gFAE4E;IAC5E,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CAsKhB"}
@@ -164,6 +164,7 @@ export function createR3FRootContext(host, options) {
164
164
  ctx,
165
165
  systems,
166
166
  systemAdapters,
167
+ debugRegistry,
167
168
  inputMapReady,
168
169
  setSceneCamera(scene, camera) {
169
170
  const sameScene = ctxRaw['scene'] === scene && sceneIndex !== null;