@forgeax/engine-scene 0.1.20 → 0.1.23

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 (80) hide show
  1. package/README.md +37 -9
  2. package/dist/__tests__/flat-propagation.contract.test.d.ts +2 -0
  3. package/dist/__tests__/flat-propagation.contract.test.d.ts.map +1 -0
  4. package/dist/__tests__/flat-propagation.derived-writer.contract.test.d.ts +2 -0
  5. package/dist/__tests__/flat-propagation.derived-writer.contract.test.d.ts.map +1 -0
  6. package/dist/__tests__/flat-propagation.perf.test.d.ts +2 -0
  7. package/dist/__tests__/flat-propagation.perf.test.d.ts.map +1 -0
  8. package/dist/__tests__/scene-binding.integration.test.d.ts +2 -0
  9. package/dist/__tests__/scene-binding.integration.test.d.ts.map +1 -0
  10. package/dist/__tests__/schedule-order.contract.test.d.ts +2 -0
  11. package/dist/__tests__/schedule-order.contract.test.d.ts.map +1 -0
  12. package/dist/__tests__/structural.test.d.ts +2 -0
  13. package/dist/__tests__/structural.test.d.ts.map +1 -0
  14. package/dist/__tests__/transform-carrier-consumers.test-d.d.ts +2 -0
  15. package/dist/__tests__/transform-carrier-consumers.test-d.d.ts.map +1 -0
  16. package/dist/__tests__/transform-carrier-prototype.bench.d.ts +39 -0
  17. package/dist/__tests__/transform-carrier-prototype.bench.d.ts.map +1 -0
  18. package/dist/__tests__/transform-carrier-prototype.test-d.d.ts +2 -0
  19. package/dist/__tests__/transform-carrier-prototype.test-d.d.ts.map +1 -0
  20. package/dist/__tests__/transform-carrier-prototype.test.d.ts +2 -0
  21. package/dist/__tests__/transform-carrier-prototype.test.d.ts.map +1 -0
  22. package/dist/__tests__/transform-component-version.unit.test.d.ts +2 -0
  23. package/dist/__tests__/transform-component-version.unit.test.d.ts.map +1 -0
  24. package/dist/assets/scene-decoder.d.ts.map +1 -1
  25. package/dist/components/child-of.d.ts +15 -8
  26. package/dist/components/child-of.d.ts.map +1 -1
  27. package/dist/components/children.d.ts.map +1 -1
  28. package/dist/components/transform.d.ts +7 -43
  29. package/dist/components/transform.d.ts.map +1 -1
  30. package/dist/errors.d.ts +23 -2
  31. package/dist/errors.d.ts.map +1 -1
  32. package/dist/index.d.ts +3 -2
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.mjs +616 -372
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/instances/binding.d.ts +29 -0
  37. package/dist/instances/binding.d.ts.map +1 -0
  38. package/dist/instances/externalization.d.ts.map +1 -1
  39. package/dist/instances/scene-instances.d.ts +5 -17
  40. package/dist/instances/scene-instances.d.ts.map +1 -1
  41. package/dist/instances/state.d.ts +28 -0
  42. package/dist/instances/state.d.ts.map +1 -0
  43. package/dist/plugin.d.ts.map +1 -1
  44. package/dist/systems/hierarchy-projection.d.ts.map +1 -1
  45. package/dist/systems/index.d.ts +1 -1
  46. package/dist/systems/index.d.ts.map +1 -1
  47. package/dist/systems/propagate-transforms.d.ts +1 -2
  48. package/dist/systems/propagate-transforms.d.ts.map +1 -1
  49. package/package.json +5 -5
  50. package/src/__tests__/components.unit.test.ts +34 -2
  51. package/src/__tests__/flat-propagation.contract.test.ts +128 -0
  52. package/src/__tests__/flat-propagation.derived-writer.contract.test.ts +39 -0
  53. package/src/__tests__/flat-propagation.perf.test.ts +336 -0
  54. package/src/__tests__/plugin.integration.test.ts +2 -2
  55. package/src/__tests__/propagation.unit.test.ts +207 -91
  56. package/src/__tests__/scene-binding.integration.test.ts +124 -0
  57. package/src/__tests__/schedule-order.contract.test.ts +43 -0
  58. package/src/__tests__/structural.test.ts +23 -0
  59. package/src/__tests__/transform-carrier-consumers.test-d.ts +156 -0
  60. package/src/__tests__/transform-carrier-prototype.bench.ts +168 -0
  61. package/src/__tests__/transform-carrier-prototype.test-d.ts +71 -0
  62. package/src/__tests__/transform-carrier-prototype.test.ts +170 -0
  63. package/src/__tests__/{transform-change-journal.unit.test.ts → transform-component-version.unit.test.ts} +32 -39
  64. package/src/assets/scene-decoder.ts +6 -1
  65. package/src/components/child-of.ts +15 -8
  66. package/src/components/children.ts +6 -0
  67. package/src/components/transform.ts +23 -81
  68. package/src/errors.ts +26 -2
  69. package/src/index.ts +10 -1
  70. package/src/instances/binding.ts +77 -0
  71. package/src/instances/externalization.ts +7 -1
  72. package/src/instances/scene-instances.ts +47 -76
  73. package/src/instances/state.ts +62 -0
  74. package/src/plugin.ts +9 -2
  75. package/src/systems/hierarchy-projection.ts +25 -8
  76. package/src/systems/index.ts +3 -0
  77. package/src/systems/propagate-transforms.ts +376 -245
  78. package/dist/.tsbuildinfo +0 -1
  79. package/dist/__tests__/transform-change-journal.unit.test.d.ts +0 -2
  80. package/dist/__tests__/transform-change-journal.unit.test.d.ts.map +0 -1
package/README.md CHANGED
@@ -6,12 +6,14 @@
6
6
  ## Smallest useful example
7
7
 
8
8
  ```ts
9
- import { scenePlugin, Transform } from '@forgeax/engine-scene';
10
- import { createWorldContext, World } from '@forgeax/engine-ecs';
9
+ import { scenePlugin, Transform } from '@forgeax/engine/scene';
10
+ import { createWorldContext, World } from '@forgeax/engine/ecs';
11
11
 
12
12
  const world = new World();
13
13
  const context = await createWorldContext(world, [scenePlugin()]);
14
- const entity = world.spawn({ component: Transform, data: {} }).unwrap();
14
+ const entity = world
15
+ .spawn({ component: Transform, data: {} })
16
+ .unwrap();
15
17
  void entity;
16
18
  await context.fiber.restart();
17
19
  ```
@@ -20,13 +22,39 @@ await context.fiber.restart();
20
22
  propagation and removes it when the realm unloads. Read failures as
21
23
  `SceneError` and branch on `error.code`; do not parse messages.
22
24
 
23
- Transform propagation publishes the exact recomputed frontier to the World's
24
- engine-owned change journal after a successful pass. A no-change pass publishes
25
- nothing. Persistent consumers can therefore update a moved subtree without
26
- rescanning unrelated transforms, while `Transform.world` remains the sole
27
- resolved world-space authority.
25
+ Transform propagation writes the exact recomputed frontier into
26
+ `GlobalTransform` and advances those rows' ordinary component versions only
27
+ after a successful pass. A no-change pass advances no `GlobalTransform` row.
28
+ Persistent consumers keep a `changed: [GlobalTransform]` Query, so a moved
29
+ subtree is exposed as contiguous spans without a parallel event journal.
30
+ `Transform` remains authored local TRS; `GlobalTransform` is the resolved
31
+ world-space authority.
28
32
 
29
- The authority also applies to dynamic loading: import `Transform`, `ChildOf`, and `scenePlugin` from `@forgeax/engine-scene` when a host resolves packages at runtime.
33
+ Flat propagation uses the same numeric kernel inline or through an installed
34
+ SharedKernel executor. It borrows the existing changed query, joins root
35
+ matrices before resolving the hierarchy, and leaves small or fragmented ranges
36
+ inline. Scene builds its self-contained kernel module into `pkg/` from the same
37
+ TypeScript source; no new Worker pool, component-name registry, or transform
38
+ change journal is introduced. Partial shared writes poison the owning World.
39
+
40
+ `Transform` declares the generic ECS requirement `GlobalTransform`. Therefore
41
+ ordinary `world.spawn`, `world.addComponent`, and deferred `Commands.spawn`
42
+ materialize the transient world column automatically at the structural
43
+ boundary; scene code does not need a special pair-completion helper and the
44
+ frame loop never scans entities to repair them. Explicit `GlobalTransform`
45
+ data remains valid when an importer or recovery path needs to provide it.
46
+
47
+ `ChildOf` declares `Transform` as a relationship-source requirement. A child
48
+ created with only `{ component: ChildOf, data: { parent } }` therefore receives
49
+ the full local/world pair transitively, while explicit `Transform` data still
50
+ wins. This keeps hierarchy authoring small without adding per-frame repair or
51
+ an additional scene-side component registry.
52
+
53
+ Removing the required component is still an explicit malformed-state escape
54
+ hatch, not an automatic cascade. Propagation reports that state as a
55
+ structured `SceneError`, preserving a clear owner and recovery path.
56
+
57
+ The authority also applies to dynamic loading: import `Transform`, `ChildOf`, and `scenePlugin` from `@forgeax/engine/scene` when a host resolves packages at runtime.
30
58
 
31
59
  ## Boundary
32
60
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flat-propagation.contract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flat-propagation.contract.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/flat-propagation.contract.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flat-propagation.derived-writer.contract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flat-propagation.derived-writer.contract.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/flat-propagation.derived-writer.contract.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flat-propagation.perf.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flat-propagation.perf.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/flat-propagation.perf.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scene-binding.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-binding.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/scene-binding.integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schedule-order.contract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-order.contract.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/schedule-order.contract.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=structural.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structural.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/structural.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transform-carrier-consumers.test-d.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-carrier-consumers.test-d.d.ts","sourceRoot":"","sources":["../../src/__tests__/transform-carrier-consumers.test-d.ts"],"names":[],"mappings":""}
@@ -0,0 +1,39 @@
1
+ type Workload = {
2
+ readonly workloadId: 'flat-dynamic' | 'hierarchy-dynamic' | 'sparse-dynamic' | 'structural-churn';
3
+ readonly rows: number;
4
+ readonly movers: number;
5
+ };
6
+ type CandidateId = 'B-independent-lanes' | 'C-ordinary-pair';
7
+ type CandidateReceipt = {
8
+ readonly schemaVersion: 1;
9
+ readonly candidateId: CandidateId;
10
+ readonly workload: Workload;
11
+ readonly seed: number;
12
+ readonly frameCount: number;
13
+ readonly moverDensity: number;
14
+ readonly writerInference: 'local-only';
15
+ readonly queryInference: 'world-only';
16
+ readonly consumers: {
17
+ readonly authoringImport: boolean;
18
+ readonly propagation: boolean;
19
+ readonly query: boolean;
20
+ readonly querySpan: boolean;
21
+ readonly rendererSync: boolean;
22
+ };
23
+ readonly allocations: {
24
+ readonly warmup: number;
25
+ readonly steadyState: number;
26
+ };
27
+ readonly memoryBytes: number;
28
+ readonly stageTimingMs: {
29
+ readonly writer: number;
30
+ readonly propagation: number;
31
+ readonly query: number;
32
+ readonly total: number;
33
+ };
34
+ readonly worldChecksum: number;
35
+ readonly conceptCount: number;
36
+ };
37
+ export declare function collectPrototypeReceipts(): readonly CandidateReceipt[];
38
+ export {};
39
+ //# sourceMappingURL=transform-carrier-prototype.bench.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-carrier-prototype.bench.d.ts","sourceRoot":"","sources":["../../src/__tests__/transform-carrier-prototype.bench.ts"],"names":[],"mappings":"AAUA,KAAK,QAAQ,GAAG;IACd,QAAQ,CAAC,UAAU,EAAE,cAAc,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;IAClG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,KAAK,WAAW,GAAG,qBAAqB,GAAG,iBAAiB,CAAC;AAE7D,KAAK,gBAAgB,GAAG;IACtB,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,YAAY,CAAC;IACvC,QAAQ,CAAC,cAAc,EAAE,YAAY,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;QAClC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;QAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;QAC5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;KAChC,CAAC;IACF,QAAQ,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAChF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE;QACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAAC;AAiFF,wBAAgB,wBAAwB,IAAI,SAAS,gBAAgB,EAAE,CAKtE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transform-carrier-prototype.test-d.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-carrier-prototype.test-d.d.ts","sourceRoot":"","sources":["../../src/__tests__/transform-carrier-prototype.test-d.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transform-carrier-prototype.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-carrier-prototype.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/transform-carrier-prototype.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transform-component-version.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-component-version.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/transform-component-version.unit.test.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"scene-decoder.d.ts","sourceRoot":"","sources":["../../src/assets/scene-decoder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EAKd,KAAK,UAAU,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,cAAc,EAAE,SAAS,CAAC,UAAU,EAAE,OAAO,CAEvB,CAAC;AAqBpC,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAEnF;AA+FD,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,EAAE,YAAY,CAAC,UAAU,CAWtD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAIhF,CAAC"}
1
+ {"version":3,"file":"scene-decoder.d.ts","sourceRoot":"","sources":["../../src/assets/scene-decoder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EAKd,KAAK,UAAU,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,cAAc,EAAE,SAAS,CAAC,UAAU,EAAE,OAAO,CAEvB,CAAC;AAqBpC,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAEnF;AAoGD,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,EAAE,YAAY,CAAC,UAAU,CAWtD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAIhF,CAAC"}
@@ -4,24 +4,31 @@ export { ChildOf } from './children';
4
4
  *
5
5
  * Store the parent `Entity` handle (returned by `world.spawn(...).unwrap()`)
6
6
  * in the `parent` field; `propagateTransforms` reads it each frame to
7
- * compose the child's derived `Transform.world` mat4 (child.world =
8
- * parent.world x child local). Despawning a child auto-detaches it from the
7
+ * compose the child's derived `GlobalTransform.world` mat4 (child.world =
8
+ * parent.world x child local). `Transform` declares `GlobalTransform` as a
9
+ * generic ECS requirement, so normal spawn/add/command paths materialize the
10
+ * pair without scene-specific repair. Propagation still fails closed when an
11
+ * owner explicitly removes one half. Despawning a child auto-detaches it from the
9
12
  * parent's Children list (relationship `onRemove` hook). Despawning the
10
13
  * parent does not auto-clean the child's ChildOf; the consumer removes the
11
14
  * stale ChildOf (`world.removeComponent`) or checks `world.get(parent, Entity)` for liveness.
12
15
  *
13
- * Because ChildOf declares a `relationship` mirror, the engine keeps the
14
- * parent's `Children.entities` reverse list consistent automatically: adding
15
- * ChildOf appends the child to the parent's Children, removing it (or
16
- * reparenting via the `exclusive` arm) prunes the stale entry. AI users no
17
- * longer hand-maintain both sides (the prior OOS-10 contract is retired).
16
+ * Because ChildOf declares a `relationship` mirror and a structural
17
+ * `Transform` requirement, the engine keeps the parent's `Children.entities`
18
+ * reverse list consistent automatically and materializes the local/world pair
19
+ * when the child did not author one: adding ChildOf appends the child to the
20
+ * parent's Children, removing it (or reparenting via the `exclusive` arm)
21
+ * prunes the stale entry. AI users no longer hand-maintain both sides (the
22
+ * prior OOS-10 contract is retired).
18
23
  * Reparenting is a plain re-add: `world.addComponent(child, { component:
19
24
  * ChildOf, data: { parent: newParent } })` on an entity that already carries
20
25
  * ChildOf auto-reparents (exclusive arm), or use `world.reparent(child,
21
26
  * newParent)`.
22
27
  *
23
28
  * @example Spawn a child entity referencing an already-spawned root:
24
- * const root = world.spawn({ component: Transform, data: {...} }).unwrap();
29
+ * const root = world.spawn(
30
+ * { component: Transform, data: {...} },
31
+ * ).unwrap();
25
32
  * const child = world.spawn(
26
33
  * { component: Transform, data: {...} },
27
34
  * { component: ChildOf, data: { parent: root } },
@@ -1 +1 @@
1
- {"version":3,"file":"child-of.d.ts","sourceRoot":"","sources":["../../src/components/child-of.ts"],"names":[],"mappings":"AA2DA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG"}
1
+ {"version":3,"file":"child-of.d.ts","sourceRoot":"","sources":["../../src/components/child-of.ts"],"names":[],"mappings":"AA2DA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG"}
@@ -1 +1 @@
1
- {"version":3,"file":"children.d.ts","sourceRoot":"","sources":["../../src/components/children.ts"],"names":[],"mappings":"AA+DA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,MAAgB,OAAO;;IAAU,QAAQ;;GAO9C,CAAC"}
1
+ {"version":3,"file":"children.d.ts","sourceRoot":"","sources":["../../src/components/children.ts"],"names":[],"mappings":"AAgEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,MAAgB,OAAO;;IAAU,QAAQ;;GAY9C,CAAC"}
@@ -1,52 +1,16 @@
1
+ /** Scene-owned derived world transform. Only TransformPropagation writes it. */
2
+ export declare const GlobalTransform: import("@forgeax/engine-ecs").Component<"GlobalTransform", {
3
+ readonly world: "array<f32, 16>";
4
+ }>;
1
5
  /**
2
- * Transform: local position `pos` (xyz), rotation `quat` (quaternion,
3
- * component order [x, y, z, w]), scale `scale` (xyz), plus the resolved
4
- * `world` mat4 (column-major 16 floats).
5
- *
6
- * Local TRS is stored as three inline stride-N array<f32, N> columns. The
7
- * propagate kernel composes each entity's local TRS into a mat4 and writes it
8
- * into the `world` column (root: world = local; child: world = parent.world x
9
- * local) using `@forgeax/engine-math` mat4 / vec3 / quat APIs (charter P4: do
10
- * not reinvent math). MVP recomposes every frame; dirty-flag optimization is
11
- * owned by feat-future-render-world.
12
- *
13
- * The `world` column is a fixed-capacity `array<f32, 16>` (feat-20260602):
14
- * the 16 contiguous floats live inline in a stride-16 column -- no BufferPool
15
- * slot. Read it via `world.get(e, Transform).world` which returns a live
16
- * `Float32Array` aliasing the column buffer. The view is transient: it aliases
17
- * the archetype column buffer and is valid only until the next structural
18
- * change (spawn / despawn / addComponent / removeComponent). Re-fetch the view
19
- * on every access; holding a view across a structural change is undefined
20
- * behaviour (the backing `ArrayBuffer` is detached on column growth, and
21
- * swap-remove at the same row index points to the wrong entity). All existing
22
- * hot paths (propagate / render-extract / pick) already comply -- see
23
- * `packages/ecs/README.md` Transient view contract section.
6
+ * Authored local position, rotation and scale columns.
24
7
  *
25
- * All three local columns carry explicit layer-2 defaults (identity
26
- * transform): `pos: [0, 0, 0]`, `quat: [0, 0, 0, 1]` (identity quaternion,
27
- * [x, y, z, w]), `scale: [1, 1, 1]`. quat and scale MUST stay explicit: the
28
- * layer-3 fallback for array<f32, N> is all-zero, which would land an invalid
29
- * zero quaternion / zero scale. The `world` field defaults to the identity
30
- * mat4. AI users spawn with `data: {}` or with only the fields they need to
31
- * override.
32
- *
33
- * @example Minimal spawn (local defaulted to identity, world = identity mat4):
34
- * world.spawn({ component: Transform, data: {} });
35
- *
36
- * @example Override only the position, leaving rotation/scale at identity:
37
- * world.spawn({ component: Transform, data: { pos: [0, 6, 0] } });
38
- *
39
- * @example Full explicit local form (defaults are opt-in):
40
- * world.spawn({ component: Transform, data: {
41
- * pos: [1, 2, 3],
42
- * quat: [0, 0, 0, 1], // [x, y, z, w]
43
- * scale: [1, 1, 1],
44
- * } });
8
+ * The ECS `requires` declaration is the generic structural invariant: callers
9
+ * add `Transform`, while `GlobalTransform` is materialized once at spawn/add.
45
10
  */
46
11
  export declare const Transform: import("@forgeax/engine-ecs").Component<"Transform", {
47
12
  readonly pos: "array<f32, 3>";
48
13
  readonly quat: "array<f32, 4>";
49
14
  readonly scale: "array<f32, 3>";
50
- readonly world: "array<f32, 16>";
51
15
  }>;
52
16
  //# sourceMappingURL=transform.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/components/transform.ts"],"names":[],"mappings":"AAiCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,SAAS;;;;;EAUpB,CAAC"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/components/transform.ts"],"names":[],"mappings":"AAMA,gFAAgF;AAChF,eAAO,MAAM,eAAe;;EAM3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,SAAS;;;;EASrB,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -1,12 +1,33 @@
1
- import type { EntityHandle } from '@forgeax/engine-ecs';
1
+ import type { EcsError, EntityHandle } from '@forgeax/engine-ecs';
2
2
  export type SceneErrorCode = 'hierarchy-broken' | 'hierarchy-cycle';
3
3
  /** Scene-instantiation failures owned by the scene package. */
4
4
  export type SceneInstanceErrorCode = 'component-not-defined' | 'scene-override-type-mismatch';
5
5
  export { ComponentNotDefinedError } from '@forgeax/engine-ecs/projection';
6
- export interface SceneErrorDetail {
6
+ /** The structured ECS failure retained by a Scene derived-write diagnostic. */
7
+ export interface SceneErrorCause {
8
+ readonly code: EcsError['code'];
9
+ readonly expected?: string;
10
+ readonly hint?: string;
11
+ readonly detail?: unknown;
12
+ }
13
+ /** Location detail shared by hierarchy diagnostics and derived-write errors. */
14
+ export interface SceneHierarchyErrorDetail {
15
+ readonly kind?: 'hierarchy';
16
+ readonly entity: EntityHandle;
17
+ readonly parent: EntityHandle;
18
+ }
19
+ /** A flat derived publication failure with its original ECS error intact. */
20
+ export interface SceneDerivedWriteErrorDetail {
21
+ readonly kind: 'derived-write';
7
22
  readonly entity: EntityHandle;
8
23
  readonly parent: EntityHandle;
24
+ readonly bindingIndex: number;
25
+ readonly base: number;
26
+ readonly start: number;
27
+ readonly count: number;
28
+ readonly cause: SceneErrorCause;
9
29
  }
30
+ export type SceneErrorDetail = SceneHierarchyErrorDetail | SceneDerivedWriteErrorDetail;
10
31
  export declare class SceneError extends Error {
11
32
  readonly code: SceneErrorCode;
12
33
  readonly expected: string;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AAEpE,+DAA+D;AAC/D,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,GAAG,8BAA8B,CAAC;AAE9F,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B;AAED,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;gBAElC,IAAI,EAAE;QAChB,IAAI,EAAE,cAAc,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,gBAAgB,CAAC;KAC3B;CAQF"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAElE,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AAEpE,+DAA+D;AAC/D,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,GAAG,8BAA8B,CAAC;AAE9F,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,gFAAgF;AAChF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B;AAED,6EAA6E;AAC7E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;CACjC;AAED,MAAM,MAAM,gBAAgB,GAAG,yBAAyB,GAAG,4BAA4B,CAAC;AAExF,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;gBAElC,IAAI,EAAE;QAChB,IAAI,EAAE,cAAc,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,gBAAgB,CAAC;KAC3B;CAQF"}
package/dist/index.d.ts CHANGED
@@ -4,11 +4,12 @@ export { ChildOf } from './components/child-of';
4
4
  export { Children } from './components/children';
5
5
  export { MorphWeights } from './components/morph-weights';
6
6
  export { Name } from './components/name';
7
- export { Transform } from './components/transform';
7
+ export { GlobalTransform, Transform } from './components/transform';
8
8
  export { ComponentNotDefinedError, SceneError, type SceneErrorCode, type SceneInstanceErrorCode, } from './errors';
9
+ export { resolveSceneEntity, type SceneBindingDeclarationError, type SceneBindingError, type SceneEntityRef, sceneEntity, validateSceneBindings, } from './instances/binding';
9
10
  export { SCENE_COLLECT_PROFILE, type SceneCollectProfile } from './instances/collect-profile';
10
11
  export { type ExternalizedSceneAsset, externalizeSceneAsset, type SceneComponentSchemaResolver, type SceneExternalizationError, } from './instances/externalization';
11
- export { type SceneAssetResolver, type SceneInstanceStatePayload, type SceneInstantiateDiagnostic, type SceneInstantiateFlatOk, type SceneInstantiateOk, type SceneMembersSpawn, worldApplyMountOverride, worldBuildSceneEntityComponentDatas, worldDespawnDescendants, worldDespawnScene, worldDetachSceneMember, worldGetSceneAssetForInstance, worldGetSceneAssetResolver, worldGetSceneInstanceState, worldInstantiateScene, worldInstantiateSceneAsset, worldInstantiateSceneAssetFlat, worldInstantiateSceneFlat, worldInstantiateScenePayload, worldInstantiateSceneRec, worldMountOverridesToStateMap, worldReattachSceneMember, worldRemoveSceneOverride, worldResolveMountSource, worldResolveSceneAsset, worldResolveSceneInstanceStatePayload, worldSetSceneAssetResolver, worldSetSceneOverride, worldSpawnMountEntity, worldSpawnSceneMembers, worldValidateMountOverrides, } from './instances/scene-instances';
12
+ export { type SceneAssetResolver, type SceneInstanceStatePayload, type SceneInstantiateDiagnostic, type SceneInstantiateFlatOk, type SceneInstantiateOk, type SceneMembersSpawn, worldApplyMountOverride, worldBuildSceneEntityComponentDatas, worldDespawnDescendants, worldDespawnScene, worldDetachSceneMember, worldGetSceneAssetForInstance, worldGetSceneAssetResolver, worldGetSceneInstanceState, worldInstantiateScene, worldInstantiateSceneAsset, worldInstantiateSceneAssetFlat, worldInstantiateSceneFlat, worldInstantiateScenePayload, worldInstantiateSceneRec, worldMountOverridesToStateMap, worldReattachSceneMember, worldRemoveSceneOverride, worldResolveMountSource, worldResolveSceneAsset, worldResolveSceneEntity, worldResolveSceneInstanceStatePayload, worldSetSceneAssetResolver, worldSetSceneOverride, worldSpawnMountEntity, worldSpawnSceneMembers, worldValidateMountOverrides, } from './instances/scene-instances';
12
13
  export { scenePlugin } from './plugin';
13
14
  export { projectHierarchy, type SceneHierarchyDiagnostic, type SceneHierarchySnapshot, } from './systems/hierarchy-projection';
14
15
  export { PROPAGATE_TRANSFORMS_SYSTEM, propagateTransforms, registerPropagateTransforms, TransformSet, } from './systems/propagate-transforms';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EACL,wBAAwB,EACxB,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC9F,OAAO,EACL,KAAK,sBAAsB,EAC3B,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,GAC/B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,uBAAuB,EACvB,mCAAmC,EACnC,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,0BAA0B,EAC1B,qBAAqB,EACrB,0BAA0B,EAC1B,8BAA8B,EAC9B,yBAAyB,EACzB,4BAA4B,EAC5B,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,qCAAqC,EACrC,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EACL,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,2BAA2B,EAC3B,YAAY,GACb,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EACL,wBAAwB,EACxB,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,kBAAkB,EAClB,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,WAAW,EACX,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC9F,OAAO,EACL,KAAK,sBAAsB,EAC3B,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,GAC/B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,uBAAuB,EACvB,mCAAmC,EACnC,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,0BAA0B,EAC1B,qBAAqB,EACrB,0BAA0B,EAC1B,8BAA8B,EAC9B,yBAAyB,EACzB,4BAA4B,EAC5B,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,qCAAqC,EACrC,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EACL,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,2BAA2B,EAC3B,YAAY,GACb,MAAM,gCAAgC,CAAC"}