@vgai/engine 0.5.40 → 0.5.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
@@ -436,7 +436,12 @@ export function createGame(opts) {
436
436
  reportGateShortfallOnce('loop', world.id, 'self-driven world, adapter declares no setPaused capability');
437
437
  }
438
438
  }
439
- const audio = world.mounted.systems?.audio;
439
+ // A native entry's static `systems` export is this root's primary
440
+ // declaration surface. `computeSystemAdapters()` already gives it
441
+ // precedence over a substrate-seeded mounted adapter; pause must read
442
+ // the same source or a valid entry-declared audio graph is visible to
443
+ // the editor yet paradoxically reported as ungateable here.
444
+ const audio = declaredSystemAdapters.get(world.id)?.audio ?? world.mounted.systems?.audio;
440
445
  if (audio) {
441
446
  audio.setMuted(next);
442
447
  }
@@ -644,11 +649,19 @@ export function createGame(opts) {
644
649
  // Checklist item 2: same isolation for the opaque-world fallback —
645
650
  // one foreign mount's `update` throwing must not starve its
646
651
  // siblings' `endFrame`/`update` calls this same loop.
647
- try {
648
- world.mounted.update?.(dt);
649
- }
650
- catch (err) {
651
- console.error(`[game] world "${world.id}" (kind: ${world.kind}) update() threw:`, err);
652
+ // A display-cadence opaque update is the root's indivisible native
653
+ // presentation (R3F `advance()` is callbacks + draw). The real
654
+ // rAF host withholds render phases from EVERY fixed catch-up step;
655
+ // withhold this update beside them, then run it once in
656
+ // `runRenderFrameImpl`. A direct/offline `runFrame` includes render
657
+ // phases and therefore still advances the root exactly once.
658
+ if (!(skipRenderPhases && world.mounted.updateCadence === 'display')) {
659
+ try {
660
+ world.mounted.update?.(dt);
661
+ }
662
+ catch (err) {
663
+ console.error(`[game] world "${world.id}" (kind: ${world.kind}) update() threw:`, err);
664
+ }
652
665
  }
653
666
  }
654
667
  }
@@ -747,6 +760,28 @@ export function createGame(opts) {
747
760
  }
748
761
  profiler.endPhase(phase);
749
762
  }
763
+ // An opaque display-cadence root cannot expose phase hooks because its
764
+ // native advance is inseparable. It still belongs to THIS presentation
765
+ // frame, once — never to every fixed catch-up substep that preceded it.
766
+ // A frozen world redraws at dt=0, preserving the established pause rule.
767
+ for (let i = 0; i < n; i++) {
768
+ const world = roots[i];
769
+ if (world.disposed)
770
+ continue;
771
+ if (world.mounted.drivesOwnLoop)
772
+ continue;
773
+ if (world.frame)
774
+ continue;
775
+ if (world.mounted.updateCadence !== 'display')
776
+ continue;
777
+ const frozen = paused && world.pausable;
778
+ try {
779
+ world.mounted.update?.(frozen ? 0 : displayDt);
780
+ }
781
+ catch (err) {
782
+ console.error(`[game] world "${world.id}" (kind: ${world.kind}) update() threw (display frame):`, err);
783
+ }
784
+ }
750
785
  profiler.endFrame();
751
786
  if (rngTrapEnabled)
752
787
  rngTrap.disable();
@@ -1 +1 @@
1
- {"version":3,"file":"r3f-root-factory.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-root-factory.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAWH,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAelF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AA4ZnE;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/F;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,qBAO5B,CAAC"}
1
+ {"version":3,"file":"r3f-root-factory.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-root-factory.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAWH,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAelF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAmanE;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/F;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,qBAO5B,CAAC"}
@@ -292,11 +292,10 @@ function threeWorldAdapter(id, component) {
292
292
  if (renderDebugWiring)
293
293
  systemAdapters.renderDebug = renderDebugWiring.adapter;
294
294
  // The engine drives every `useFrame` through the mounted world's
295
- // `update(dt)` hook, never off a raw host-loop callback. That is the
296
- // whole pause story: `runFrameImpl` (`runtime/game.ts`) calls
297
- // `mounted.update?.(dt)` per substep for a host-driven world and SKIPS
298
- // it while that world is frozen, and `Game.play.step()` ticks it exactly
299
- // once.
295
+ // `update(dt)` hook, never off a raw Fiber loop. This mount declares
296
+ // that indivisible Fiber advance at DISPLAY cadence below: the real
297
+ // host calls it once per presentation, a paused world gets dt=0, and an
298
+ // explicit `Game.play.step()` still ticks it exactly once.
300
299
  //
301
300
  // `advance(timestamp, runGlobalEffects, state)`'s `timestamp` is
302
301
  // consumed as `THREE.Clock.elapsedTime` DIRECTLY when
@@ -328,6 +327,14 @@ function threeWorldAdapter(id, component) {
328
327
  return live().camera;
329
328
  },
330
329
  drivesOwnLoop: false,
330
+ // Fiber's `advance()` cannot separate its `useFrame` callbacks from
331
+ // its WebGL draw. Running this opaque update in every fixed catch-up
332
+ // substep renders N complete frames inside one rAF callback: once a
333
+ // scene costs more than 16.7ms, the accumulator asks for more draws,
334
+ // those draws make the next gap larger, and the loop spirals to its
335
+ // max-substep ceiling. The host's display pass is the one clock that
336
+ // must own this inseparable native advance.
337
+ updateCadence: 'display',
331
338
  // Adapter surface: `debug` (the shared game registry) and, when a real
332
339
  // WebGL2 context exists, `renderDebug` are engine-seeded. The game's
333
340
  // own capabilities arrive as the entry module's declared `systems`.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@vgai/engine",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "Apache-2.0",
5
- "version": "0.5.40",
5
+ "version": "0.5.41",
6
6
  "description": "Readable TypeScript game engine and universal host for Three.js, PixiJS, and React games.",
7
7
  "keywords": [
8
8
  "game-engine",
@@ -110,6 +110,12 @@ export interface EditorNode {
110
110
  typeLabel?: string;
111
111
  parentId: string | null;
112
112
  childIds: string[];
113
+ /** Opaque project-owned identity shared by authored rows across adapter roots. */
114
+ crossSurfaceId?: string;
115
+ /** Optional authored parent identity resolved against another row's cross-surface id. */
116
+ crossSurfaceParentId?: string;
117
+ /** Source-owned sibling ordinal used only when native rows are joined across surfaces. */
118
+ crossSurfaceOrder?: number;
113
119
  }
114
120
 
115
121
  export interface PropertyDescriptor {
@@ -65,6 +65,23 @@ export interface MountedRootBase {
65
65
  */
66
66
  readonly drivesOwnLoop: boolean;
67
67
 
68
+ /**
69
+ * Which host clock owns an opaque mounted root's single `update(dt)` hook.
70
+ *
71
+ * `fixed` (the default) preserves the adapter seam's original contract:
72
+ * the callback runs once per consumed simulation substep. `display` is for
73
+ * a reconciler whose one native advance is inseparably BOTH its callbacks
74
+ * and its draw (React Three Fiber's `advance()` is the measured case). The
75
+ * real host then withholds it from fixed catch-up substeps and invokes it
76
+ * exactly once from the display pass. A direct/offline `runFrame` that does
77
+ * not skip render phases still invokes it once, preserving capture and
78
+ * explicit-tick semantics.
79
+ *
80
+ * Absent means `fixed`. This changes no foreign/ingest adapter unless that
81
+ * adapter opts in explicitly.
82
+ */
83
+ readonly updateCadence?: 'fixed' | 'display';
84
+
68
85
  update?(dt: number): void; // host-driven only
69
86
  fixedUpdate?(dt: number): void;
70
87
  setPaused?(paused: boolean): void; // capability, not promise — see loop-model note above
@@ -18,6 +18,7 @@ export const ROOT_ADAPTER_SHAPE = defineSeamShape<RootAdapter<AdapterSurface>>()
18
18
 
19
19
  export const MOUNTED_ROOT_BASE_SHAPE = defineSeamShape<MountedRootBase>()({
20
20
  drivesOwnLoop: { optional: false, kind: 'value', required: 'shape' },
21
+ updateCadence: { optional: true, kind: 'value', required: 'shape' },
21
22
  update: { optional: true, kind: 'function', required: 'effect' },
22
23
  fixedUpdate: { optional: true, kind: 'function', required: 'effect' },
23
24
  setPaused: { optional: true, kind: 'function', required: 'effect' },
@@ -67,6 +67,37 @@ export interface NavMeshBuildParams {
67
67
  mergeRegionArea?: number | undefined;
68
68
  }
69
69
 
70
+ /** One authored Detour polygon. Vertex order is clockwise in the engine's XZ world basis. */
71
+ export interface NavMeshPolygon {
72
+ readonly vertices: readonly number[];
73
+ readonly flags?: number | undefined;
74
+ readonly area?: number | undefined;
75
+ }
76
+
77
+ /** Detail-row offsets/counts for the polygon at the same index. */
78
+ export interface NavMeshDetailMesh {
79
+ readonly vertexBase: number;
80
+ readonly triangleBase: number;
81
+ readonly vertexCount: number;
82
+ readonly triangleCount: number;
83
+ }
84
+
85
+ /**
86
+ * An already-authored polygon mesh, before Detour's ABI-specific tile serialization.
87
+ *
88
+ * This is the direct-data sibling of {@link buildFromMeshes}: use it when a source ecosystem has
89
+ * already baked navigation. Re-rasterizing an editor bake is lossy—the polygon borders and detail
90
+ * heights are the output, not another input mesh.
91
+ */
92
+ export interface NavMeshPolygonData {
93
+ readonly vertices: readonly (readonly [number, number, number])[];
94
+ readonly polygons: readonly NavMeshPolygon[];
95
+ readonly detailMeshes: readonly NavMeshDetailMesh[];
96
+ readonly detailVertices: readonly (readonly [number, number, number])[];
97
+ /** Three local vertex indices plus Detour edge flags; all four values are uint8. */
98
+ readonly detailTriangles: readonly (readonly [number, number, number, number])[];
99
+ }
100
+
70
101
  let wasmInitialized = false;
71
102
 
72
103
  export async function initNavigation(): Promise<void> {
@@ -103,24 +134,47 @@ function reverseTriangleWinding(geometry: BufferGeometry): void {
103
134
  index.needsUpdate = true;
104
135
  }
105
136
 
137
+ /** Signed world-up area across a geometry's triangles. Closed obstacle meshes cancel to zero;
138
+ * broad walkable surfaces retain the winding Recast uses for its slope test. */
139
+ function upwardTriangleArea(geometry: BufferGeometry): number {
140
+ const position = geometry.getAttribute('position');
141
+ const index = geometry.getIndex();
142
+ const vertexAt = (offset: number): number => index?.getX(offset) ?? offset;
143
+ let area = 0;
144
+ const count = index?.count ?? position.count;
145
+ for (let triangle = 0; triangle + 2 < count; triangle += 3) {
146
+ const a = vertexAt(triangle);
147
+ const b = vertexAt(triangle + 1);
148
+ const c = vertexAt(triangle + 2);
149
+ const ux = position.getX(b) - position.getX(a);
150
+ const uz = position.getZ(b) - position.getZ(a);
151
+ const vx = position.getX(c) - position.getX(a);
152
+ const vz = position.getZ(c) - position.getZ(a);
153
+ area += uz * vx - ux * vz;
154
+ }
155
+ return area;
156
+ }
157
+
106
158
  function recastInputMeshes(meshes: Mesh[]): {
107
159
  readonly meshes: Mesh[];
108
160
  readonly temporaryGeometries: BufferGeometry[];
109
161
  } {
110
162
  const temporaryGeometries: BufferGeometry[] = [];
111
- const mirroredGeometries = new WeakMap<BufferGeometry, BufferGeometry>();
112
- const geometryForMatrix = (source: BufferGeometry, matrix: Matrix4): BufferGeometry => {
113
- if (matrix.determinant() >= 0) return source;
114
- const cached = mirroredGeometries.get(source);
115
- if (cached !== undefined) return cached;
116
- const geometry = source.clone();
117
- reverseTriangleWinding(geometry);
118
- mirroredGeometries.set(source, geometry);
119
- temporaryGeometries.push(geometry);
120
- return geometry;
121
- };
122
163
  const proxyAt = (geometry: BufferGeometry, matrix: Matrix4): Mesh => {
123
- const proxy = new Mesh(geometryForMatrix(geometry, matrix));
164
+ if (matrix.determinant() < 0) {
165
+ // Bake the complete mirrored transform into this clone. Passing a negative-determinant
166
+ // matrix through `@recast-navigation/three` after reversing the source indices still lets
167
+ // its geometry merge recalculate the triangle orientation from that matrix. An identity
168
+ // proxy over already-world-space vertices has exactly one winding decision.
169
+ const transformed = geometry.clone().applyMatrix4(matrix);
170
+ // A negative determinant alone is insufficient: reflecting across a plane's normal axis
171
+ // leaves every vertex in place, while reflecting an in-plane axis reverses its triangles.
172
+ // Inspect the transformed walkable area instead of guessing from the 3D transform.
173
+ if (upwardTriangleArea(transformed) < 0) reverseTriangleWinding(transformed);
174
+ temporaryGeometries.push(transformed);
175
+ return new Mesh(transformed);
176
+ }
177
+ const proxy = new Mesh(geometry);
124
178
  // The proxy has no parent, so its local matrix is the source mesh's complete world matrix.
125
179
  // The recast bridge calls updateMatrixWorld() itself; disabling auto-update preserves it.
126
180
  proxy.matrixAutoUpdate = false;
@@ -148,6 +202,224 @@ function recastInputMeshes(meshes: Mesh[]): {
148
202
  return { meshes: corrected, temporaryGeometries };
149
203
  }
150
204
 
205
+ const NAV_MESH_SET_MAGIC = 0x4d53_4554;
206
+ const NAV_MESH_SET_VERSION = 1;
207
+ const DETOUR_NAV_MESH_MAGIC = 0x444e_4156;
208
+ const DETOUR_NAV_MESH_VERSION = 7;
209
+
210
+ function nextPowerOfTwo(value: number): number {
211
+ let result = 1;
212
+ while (result < value) result *= 2;
213
+ return result;
214
+ }
215
+
216
+ /** Serialize portable polygon/detail arrays as one ordinary Detour tile. */
217
+ function polygonNavMeshData(data: NavMeshPolygonData, params?: NavMeshBuildParams): Uint8Array {
218
+ const vertexCount = data.vertices.length;
219
+ const polygonCount = data.polygons.length;
220
+ if (vertexCount === 0 || polygonCount === 0) {
221
+ throw new Error('NavMeshManager.buildFromPolygons: vertices and polygons must be non-empty');
222
+ }
223
+ if (vertexCount > 0xffff) {
224
+ throw new Error(
225
+ `NavMeshManager.buildFromPolygons: ${vertexCount} vertices exceed Detour's uint16 tile index`,
226
+ );
227
+ }
228
+ if (data.detailMeshes.length !== polygonCount) {
229
+ throw new Error(
230
+ `NavMeshManager.buildFromPolygons: ${polygonCount} polygons require the same number of detail rows`,
231
+ );
232
+ }
233
+
234
+ const neighbours = data.polygons.map((polygon) => polygon.vertices.map(() => 0));
235
+ const edges = new Map<string, readonly [number, number]>();
236
+ let maxLinkCount = 0;
237
+ for (let polygonIndex = 0; polygonIndex < polygonCount; polygonIndex += 1) {
238
+ const polygon = data.polygons[polygonIndex] as NavMeshPolygon;
239
+ if (polygon.vertices.length < 3 || polygon.vertices.length > 6) {
240
+ throw new Error(
241
+ `NavMeshManager.buildFromPolygons: polygon ${polygonIndex} has ` +
242
+ `${polygon.vertices.length} vertices; Detour permits 3..6`,
243
+ );
244
+ }
245
+ maxLinkCount += polygon.vertices.length;
246
+ for (let edgeIndex = 0; edgeIndex < polygon.vertices.length; edgeIndex += 1) {
247
+ const from = polygon.vertices[edgeIndex] as number;
248
+ const to = polygon.vertices[(edgeIndex + 1) % polygon.vertices.length] as number;
249
+ if (
250
+ !Number.isInteger(from) ||
251
+ !Number.isInteger(to) ||
252
+ from < 0 ||
253
+ to < 0 ||
254
+ from >= vertexCount ||
255
+ to >= vertexCount
256
+ ) {
257
+ throw new Error(
258
+ `NavMeshManager.buildFromPolygons: polygon ${polygonIndex} references an invalid vertex`,
259
+ );
260
+ }
261
+ const directed = `${from},${to}`;
262
+ if (edges.has(directed)) {
263
+ throw new Error(
264
+ `NavMeshManager.buildFromPolygons: directed edge ${directed} occurs more than once`,
265
+ );
266
+ }
267
+ const reverse = edges.get(`${to},${from}`);
268
+ if (reverse === undefined) {
269
+ edges.set(directed, [polygonIndex, edgeIndex]);
270
+ } else {
271
+ const [otherPolygon, otherEdge] = reverse;
272
+ neighbours[polygonIndex]![edgeIndex] = otherPolygon + 1;
273
+ neighbours[otherPolygon]![otherEdge] = polygonIndex + 1;
274
+ }
275
+ }
276
+ }
277
+
278
+ for (let polygonIndex = 0; polygonIndex < polygonCount; polygonIndex += 1) {
279
+ const row = data.detailMeshes[polygonIndex] as NavMeshDetailMesh;
280
+ if (
281
+ row.vertexBase < 0 ||
282
+ row.vertexCount < 0 ||
283
+ row.vertexBase + row.vertexCount > data.detailVertices.length ||
284
+ row.triangleBase < 0 ||
285
+ row.triangleCount < 0 ||
286
+ row.triangleBase + row.triangleCount > data.detailTriangles.length ||
287
+ row.vertexCount > 0xff ||
288
+ row.triangleCount > 0xff
289
+ ) {
290
+ throw new Error(
291
+ `NavMeshManager.buildFromPolygons: polygon ${polygonIndex} has an invalid detail row`,
292
+ );
293
+ }
294
+ }
295
+ for (const triangle of data.detailTriangles) {
296
+ if (triangle.some((value) => !Number.isInteger(value) || value < 0 || value > 0xff)) {
297
+ throw new Error(
298
+ 'NavMeshManager.buildFromPolygons: detail triangles must contain uint8 values',
299
+ );
300
+ }
301
+ }
302
+
303
+ const boundsMin = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY];
304
+ const boundsMax = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY];
305
+ for (const vertex of [...data.vertices, ...data.detailVertices]) {
306
+ for (let component = 0; component < 3; component += 1) {
307
+ const value = vertex[component] as number;
308
+ if (!Number.isFinite(value)) {
309
+ throw new Error('NavMeshManager.buildFromPolygons: every vertex component must be finite');
310
+ }
311
+ boundsMin[component] = Math.min(boundsMin[component] as number, value);
312
+ boundsMax[component] = Math.max(boundsMax[component] as number, value);
313
+ }
314
+ }
315
+
316
+ // Detour's in-memory structs are emitted in its stable 32-bit serialized layout. `importNavMesh`
317
+ // owns the ABI boundary and recreates live WASM objects from these ordinary bytes.
318
+ const headerBytes = 100;
319
+ const polygonBytes = 32;
320
+ const linkBytes = 12;
321
+ const detailMeshBytes = 12;
322
+ const detailTriangleBytes = 4;
323
+ const tileBytes =
324
+ headerBytes +
325
+ vertexCount * 12 +
326
+ polygonCount * polygonBytes +
327
+ maxLinkCount * linkBytes +
328
+ polygonCount * detailMeshBytes +
329
+ data.detailVertices.length * 12 +
330
+ data.detailTriangles.length * detailTriangleBytes;
331
+ const bytes = new Uint8Array(48 + tileBytes);
332
+ const view = new DataView(bytes.buffer);
333
+ let offset = 0;
334
+ const uint8 = (value: number): void => {
335
+ view.setUint8(offset, value);
336
+ offset += 1;
337
+ };
338
+ const uint16 = (value: number): void => {
339
+ view.setUint16(offset, value, true);
340
+ offset += 2;
341
+ };
342
+ const uint32 = (value: number): void => {
343
+ view.setUint32(offset, value, true);
344
+ offset += 4;
345
+ };
346
+ const int32 = (value: number): void => {
347
+ view.setInt32(offset, value, true);
348
+ offset += 4;
349
+ };
350
+ const float32 = (value: number): void => {
351
+ view.setFloat32(offset, value, true);
352
+ offset += 4;
353
+ };
354
+
355
+ const maxPolygons = nextPowerOfTwo(polygonCount);
356
+ uint32(NAV_MESH_SET_MAGIC);
357
+ uint32(NAV_MESH_SET_VERSION);
358
+ uint32(1);
359
+ for (const value of boundsMin) float32(value);
360
+ float32(Math.max((boundsMax[0] as number) - (boundsMin[0] as number), Number.EPSILON));
361
+ float32(Math.max((boundsMax[2] as number) - (boundsMin[2] as number), Number.EPSILON));
362
+ uint32(1);
363
+ uint32(maxPolygons);
364
+ // With one tile, Detour's first valid salt occupies the bits above maxPolygons.
365
+ uint32(maxPolygons);
366
+ uint32(tileBytes);
367
+
368
+ uint32(DETOUR_NAV_MESH_MAGIC);
369
+ uint32(DETOUR_NAV_MESH_VERSION);
370
+ int32(0);
371
+ int32(0);
372
+ int32(0);
373
+ uint32(0);
374
+ uint32(polygonCount);
375
+ uint32(vertexCount);
376
+ uint32(maxLinkCount);
377
+ uint32(polygonCount);
378
+ uint32(data.detailVertices.length);
379
+ uint32(data.detailTriangles.length);
380
+ uint32(0);
381
+ uint32(0);
382
+ uint32(polygonCount);
383
+ const defaults = DEFAULTS.navigation;
384
+ float32(params?.walkableHeight ?? defaults.walkableHeight);
385
+ float32(params?.walkableRadius ?? defaults.walkableRadius);
386
+ float32(params?.walkableClimb ?? defaults.walkableClimb);
387
+ for (const value of boundsMin) float32(value);
388
+ for (const value of boundsMax) float32(value);
389
+ float32(1 / (params?.cellSize ?? defaults.cellSize));
390
+
391
+ for (const vertex of data.vertices) for (const value of vertex) float32(value);
392
+ for (let polygonIndex = 0; polygonIndex < polygonCount; polygonIndex += 1) {
393
+ const polygon = data.polygons[polygonIndex] as NavMeshPolygon;
394
+ uint32(0xffff_ffff);
395
+ for (let index = 0; index < 6; index += 1) uint16(polygon.vertices[index] ?? 0);
396
+ for (let index = 0; index < 6; index += 1) {
397
+ uint16(neighbours[polygonIndex]?.[index] ?? 0);
398
+ }
399
+ uint16(polygon.flags ?? 1);
400
+ uint8(polygon.vertices.length);
401
+ uint8((polygon.area ?? 0) & 0x3f);
402
+ }
403
+ // `dtNavMesh::addTile` turns this zeroed capacity into its free-list, then populates the
404
+ // internal links from the polygon neighbour indices above.
405
+ offset += maxLinkCount * linkBytes;
406
+ for (const row of data.detailMeshes) {
407
+ uint32(row.vertexBase);
408
+ uint32(row.triangleBase);
409
+ uint8(row.vertexCount);
410
+ uint8(row.triangleCount);
411
+ uint16(0);
412
+ }
413
+ for (const vertex of data.detailVertices) for (const value of vertex) float32(value);
414
+ for (const triangle of data.detailTriangles) for (const value of triangle) uint8(value);
415
+ if (offset !== bytes.length) {
416
+ throw new Error(
417
+ `NavMeshManager.buildFromPolygons: encoded ${offset} bytes into a ${bytes.length}-byte allocation`,
418
+ );
419
+ }
420
+ return bytes;
421
+ }
422
+
151
423
  export class NavMeshManager {
152
424
  private navMesh: NavMesh | null = null;
153
425
  private query: NavMeshQuery | null = null;
@@ -187,7 +459,10 @@ export class NavMeshManager {
187
459
  try {
188
460
  result =
189
461
  params?.tiled === true || input.meshes.length > 256 || triangleCount > 10_000
190
- ? threeToTiledNavMesh(input.meshes, { ...config, tileSize: params?.tileSize ?? 256 })
462
+ ? threeToTiledNavMesh(input.meshes, {
463
+ ...config,
464
+ tileSize: params?.tileSize ?? 256,
465
+ })
191
466
  : threeToSoloNavMesh(input.meshes, config);
192
467
  } finally {
193
468
  for (const geometry of input.temporaryGeometries) geometry.dispose();
@@ -202,6 +477,16 @@ export class NavMeshManager {
202
477
  return true;
203
478
  }
204
479
 
480
+ /** Load an authored polygon/detail mesh directly, without a second rasterization. */
481
+ buildFromPolygons(data: NavMeshPolygonData, params?: NavMeshBuildParams): boolean {
482
+ try {
483
+ this.loadFromData(polygonNavMeshData(data, params));
484
+ return true;
485
+ } catch {
486
+ return false;
487
+ }
488
+ }
489
+
205
490
  /**
206
491
  * Destroy all live recast handles (crowd, query, navmesh) and dispose the
207
492
  * debug helper. Recast objects live on the WASM heap and are NOT GC'd —
@@ -193,6 +193,10 @@ export interface UserDataSchema {
193
193
  readonly name: string;
194
194
  readonly title: string;
195
195
  };
196
+ /** Project-owned identity used to join authored hierarchy rows across adapter roots. */
197
+ authoringHierarchyId: string;
198
+ /** Source-owned sibling ordinal used when hierarchy rows cross native roots. */
199
+ authoringHierarchyOrder: number;
196
200
  editorHelper: boolean;
197
201
  editorHelperType: EditorHelperType;
198
202
  editorIcon: boolean;
@@ -249,6 +253,8 @@ export const UserDataKeys = {
249
253
  vgaiBodyOwner: 'vgaiBodyOwner',
250
254
  authoringComponent: 'authoringComponent',
251
255
  authoringDocument: 'authoringDocument',
256
+ authoringHierarchyId: 'authoringHierarchyId',
257
+ authoringHierarchyOrder: 'authoringHierarchyOrder',
252
258
  editorHelper: 'editorHelper',
253
259
  editorHelperType: 'editorHelperType',
254
260
  editorIcon: 'editorIcon',