@forgeax/engine-scene 0.1.21 → 0.1.24

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 (87) hide show
  1. package/README.md +82 -11
  2. package/dist/__tests__/fixtures/malformed-hierarchy-edge.d.ts +5 -3
  3. package/dist/__tests__/fixtures/malformed-hierarchy-edge.d.ts.map +1 -1
  4. package/dist/__tests__/flat-propagation.contract.test.d.ts +2 -0
  5. package/dist/__tests__/flat-propagation.contract.test.d.ts.map +1 -0
  6. package/dist/__tests__/flat-propagation.derived-writer.contract.test.d.ts +2 -0
  7. package/dist/__tests__/flat-propagation.derived-writer.contract.test.d.ts.map +1 -0
  8. package/dist/__tests__/flat-propagation.perf.test.d.ts +2 -0
  9. package/dist/__tests__/flat-propagation.perf.test.d.ts.map +1 -0
  10. package/dist/__tests__/hierarchy-propagation.perf.test.d.ts +2 -0
  11. package/dist/__tests__/hierarchy-propagation.perf.test.d.ts.map +1 -0
  12. package/dist/__tests__/scene-binding.integration.test.d.ts +2 -0
  13. package/dist/__tests__/scene-binding.integration.test.d.ts.map +1 -0
  14. package/dist/__tests__/schedule-order.contract.test.d.ts +2 -0
  15. package/dist/__tests__/schedule-order.contract.test.d.ts.map +1 -0
  16. package/dist/__tests__/structural.test.d.ts +2 -0
  17. package/dist/__tests__/structural.test.d.ts.map +1 -0
  18. package/dist/__tests__/transform-carrier-consumers.test-d.d.ts +2 -0
  19. package/dist/__tests__/transform-carrier-consumers.test-d.d.ts.map +1 -0
  20. package/dist/__tests__/transform-carrier-prototype.bench.d.ts +39 -0
  21. package/dist/__tests__/transform-carrier-prototype.bench.d.ts.map +1 -0
  22. package/dist/__tests__/transform-carrier-prototype.test-d.d.ts +2 -0
  23. package/dist/__tests__/transform-carrier-prototype.test-d.d.ts.map +1 -0
  24. package/dist/__tests__/transform-carrier-prototype.test.d.ts +2 -0
  25. package/dist/__tests__/transform-carrier-prototype.test.d.ts.map +1 -0
  26. package/dist/__tests__/transform-component-version.unit.test.d.ts +2 -0
  27. package/dist/__tests__/transform-component-version.unit.test.d.ts.map +1 -0
  28. package/dist/assets/scene-decoder.d.ts.map +1 -1
  29. package/dist/components/child-of.d.ts +23 -14
  30. package/dist/components/child-of.d.ts.map +1 -1
  31. package/dist/components/children.d.ts +14 -13
  32. package/dist/components/children.d.ts.map +1 -1
  33. package/dist/components/transform.d.ts +7 -43
  34. package/dist/components/transform.d.ts.map +1 -1
  35. package/dist/errors.d.ts +23 -2
  36. package/dist/errors.d.ts.map +1 -1
  37. package/dist/index.d.ts +3 -2
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.mjs +1122 -358
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/instances/binding.d.ts +29 -0
  42. package/dist/instances/binding.d.ts.map +1 -0
  43. package/dist/instances/externalization.d.ts.map +1 -1
  44. package/dist/instances/scene-instances.d.ts +6 -18
  45. package/dist/instances/scene-instances.d.ts.map +1 -1
  46. package/dist/instances/state.d.ts +28 -0
  47. package/dist/instances/state.d.ts.map +1 -0
  48. package/dist/plugin.d.ts.map +1 -1
  49. package/dist/systems/hierarchy-projection.d.ts.map +1 -1
  50. package/dist/systems/index.d.ts +1 -1
  51. package/dist/systems/index.d.ts.map +1 -1
  52. package/dist/systems/propagate-transforms.d.ts +22 -2
  53. package/dist/systems/propagate-transforms.d.ts.map +1 -1
  54. package/package.json +5 -5
  55. package/src/__tests__/components.unit.test.ts +34 -2
  56. package/src/__tests__/fixtures/malformed-hierarchy-edge.ts +26 -4
  57. package/src/__tests__/flat-propagation.contract.test.ts +128 -0
  58. package/src/__tests__/flat-propagation.derived-writer.contract.test.ts +39 -0
  59. package/src/__tests__/flat-propagation.perf.test.ts +336 -0
  60. package/src/__tests__/hierarchy-propagation.perf.test.ts +149 -0
  61. package/src/__tests__/plugin.integration.test.ts +2 -2
  62. package/src/__tests__/propagation.unit.test.ts +271 -91
  63. package/src/__tests__/scene-binding.integration.test.ts +124 -0
  64. package/src/__tests__/schedule-order.contract.test.ts +43 -0
  65. package/src/__tests__/structural.test.ts +23 -0
  66. package/src/__tests__/transform-carrier-consumers.test-d.ts +156 -0
  67. package/src/__tests__/transform-carrier-prototype.bench.ts +168 -0
  68. package/src/__tests__/transform-carrier-prototype.test-d.ts +71 -0
  69. package/src/__tests__/transform-carrier-prototype.test.ts +170 -0
  70. package/src/__tests__/{transform-change-journal.unit.test.ts → transform-component-version.unit.test.ts} +32 -39
  71. package/src/assets/scene-decoder.ts +6 -1
  72. package/src/components/child-of.ts +38 -27
  73. package/src/components/children.ts +36 -37
  74. package/src/components/transform.ts +23 -81
  75. package/src/errors.ts +26 -2
  76. package/src/index.ts +10 -1
  77. package/src/instances/binding.ts +77 -0
  78. package/src/instances/externalization.ts +7 -1
  79. package/src/instances/scene-instances.ts +51 -80
  80. package/src/instances/state.ts +62 -0
  81. package/src/plugin.ts +9 -2
  82. package/src/systems/hierarchy-projection.ts +25 -8
  83. package/src/systems/index.ts +3 -0
  84. package/src/systems/propagate-transforms.ts +1142 -240
  85. package/dist/.tsbuildinfo +0 -1
  86. package/dist/__tests__/transform-change-journal.unit.test.d.ts +0 -2
  87. package/dist/__tests__/transform-change-journal.unit.test.d.ts.map +0 -1
@@ -0,0 +1,29 @@
1
+ import type { EntityHandle } from '@forgeax/engine-ecs';
2
+ import type { SceneEntityRef } from '@forgeax/engine-types';
3
+ import { type Result } from '@forgeax/engine-types';
4
+ export type { SceneEntityRef } from '@forgeax/engine-types';
5
+ export type SceneBindingError = {
6
+ readonly code: 'scene-binding-missing' | 'scene-binding-wrong-instance';
7
+ readonly expected: string;
8
+ readonly hint: string;
9
+ readonly detail: {
10
+ readonly sceneSourceKey: string;
11
+ readonly bindingKey: string;
12
+ };
13
+ };
14
+ export type SceneBindingDeclarationError = {
15
+ readonly code: 'scene-binding-duplicate' | 'scene-binding-source-missing';
16
+ readonly expected: string;
17
+ readonly hint: string;
18
+ readonly detail: {
19
+ readonly sceneSourceKey?: string;
20
+ readonly bindingKey?: string;
21
+ };
22
+ };
23
+ export declare function validateSceneBindings(sceneSourceKey: string, bindingKeys: readonly string[]): Result<readonly string[], SceneBindingDeclarationError>;
24
+ export declare function sceneEntity(sceneSourceKey: string, bindingKey: string): SceneEntityRef;
25
+ export declare function resolveSceneEntity(ref: SceneEntityRef, instance: {
26
+ readonly sceneSourceKey: string;
27
+ readonly bindings: ReadonlyMap<string, EntityHandle | number>;
28
+ }): Result<EntityHandle | number, SceneBindingError>;
29
+ //# sourceMappingURL=binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../src/instances/binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE7D,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,uBAAuB,GAAG,8BAA8B,CAAC;IACxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACnF,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,QAAQ,CAAC,IAAI,EAAE,yBAAyB,GAAG,8BAA8B,CAAC;IAC1E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrF,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,SAAS,MAAM,EAAE,GAC7B,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,4BAA4B,CAAC,CAsBzD;AAED,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc,CAEtF;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,cAAc,EACnB,QAAQ,EAAE;IACR,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,CAAC;CAC/D,GACA,MAAM,CAAC,YAAY,GAAG,MAAM,EAAE,iBAAiB,CAAC,CAmBlD"}
@@ -1 +1 @@
1
- {"version":3,"file":"externalization.d.ts","sourceRoot":"","sources":["../../src/instances/externalization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAiB,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,4BAA4B,GAAG,CACzC,aAAa,EAAE,MAAM,KAClB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;CACpC;AA+BD,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,UAAU,EACjB,aAAa,EAAE,4BAA4B,GAC1C,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,CAsF3D"}
1
+ {"version":3,"file":"externalization.d.ts","sourceRoot":"","sources":["../../src/instances/externalization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAiB,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,4BAA4B,GAAG,CACzC,aAAa,EAAE,MAAM,KAClB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;CACpC;AA+BD,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,UAAU,EACjB,aAAa,EAAE,4BAA4B,GAC1C,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,CA4F3D"}
@@ -1,6 +1,8 @@
1
1
  import { type Component, type ComponentData, type ComponentSchema, type EcsError, type EntityHandle, type ShapeOf, type World } from '@forgeax/engine-ecs';
2
- import type { Handle, LocalEntityId, MountOverride, SceneAsset, SceneInstanceMount } from '@forgeax/engine-types';
2
+ import type { Handle, LocalEntityId, MountOverride, SceneAsset, SceneEntityRef, SceneInstanceMount } from '@forgeax/engine-types';
3
3
  import { type Result } from '@forgeax/engine-types';
4
+ import { type SceneInstanceStatePayload } from './state.js';
5
+ export type { SceneInstanceStatePayload } from './state.js';
4
6
  /**
5
7
  * C-R2 (feat-20260622-s5 / studio-issues): one structured, non-fatal record of
6
8
  * a SceneAsset payload field that did NOT match the target component's schema.
@@ -248,7 +250,7 @@ export declare function worldValidateMountOverrides(world: World, mount: SceneIn
248
250
  * chain `cube -> innerSyntheticRoot -> mountEntity -> outerSyntheticRoot`,
249
251
  * so it MUST carry Transform whenever Transform is registered (mirrors
250
252
  * the D-V-0 synthetic-root invariant). Otherwise propagateTransforms
251
- * walking the chain hits a Transform-less parent and emits per-frame
253
+ * expanding the chain hits a Transform-less parent and emits per-frame
252
254
  * `RhiError(hierarchy-broken)` (verify R1 root cause of the
253
255
  * hello-scene-nesting demo black frames).
254
256
  */
@@ -283,6 +285,8 @@ export declare function worldResolveSceneInstanceStatePayload(world: World, root
283
285
  * `ref<T>` slot resolution mechanic for the common read path.
284
286
  */
285
287
  export declare function worldGetSceneInstanceState(world: World, root: EntityHandle): Result<SceneInstanceStatePayload, EcsError>;
288
+ /** Resolve a generated SceneEntityRef against one concrete SceneInstance. */
289
+ export declare function worldResolveSceneEntity(world: World, root: EntityHandle, ref: SceneEntityRef): Result<EntityHandle, EcsError>;
286
290
  /**
287
291
  * Despawn a SceneInstance root + all its members. `opts.keepDetached`
288
292
  * preserves members marked via `worldDetachSceneMember` (plan-strategy
@@ -331,20 +335,4 @@ export declare function worldReattachSceneMember(world: World, root: EntityHandl
331
335
  * Returns Err on a plain entity (no SceneInstance component).
332
336
  */
333
337
  export declare function worldGetSceneAssetForInstance(world: World, root: EntityHandle): Result<Handle<'SceneAsset', 'shared'>, EcsError>;
334
- /** @internal Structural payload behind `SceneInstance.state` ref column. */
335
- export interface SceneInstanceStatePayload {
336
- readonly source: Handle<'SceneAsset', 'shared'>;
337
- readonly entityToLocalId: Map<EntityHandle, LocalEntityId>;
338
- readonly detachedLocalIds: Set<LocalEntityId>;
339
- readonly overrides: Map<LocalEntityId, Map<string, {
340
- readonly comp: string;
341
- readonly field?: string;
342
- readonly value: unknown;
343
- }>>;
344
- readonly rootEntities: EntityHandle[];
345
- /** Synthetic roots of recursively mounted SceneAssets owned by this instance. */
346
- readonly mountRoots: EntityHandle[];
347
- readonly totalSlots: number;
348
- readonly mountTimeOverrides: readonly MountOverride[];
349
- }
350
338
  //# sourceMappingURL=scene-instances.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scene-instances.d.ts","sourceRoot":"","sources":["../../src/instances/scene-instances.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scene-instances.d.ts","sourceRoot":"","sources":["../../src/instances/scene-instances.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { EntityHandle, World } from '@forgeax/engine-ecs';
2
+ import type { Handle, LocalEntityId, MountOverride } from '@forgeax/engine-types';
3
+ /** Internal state retained by a SceneInstance root. */
4
+ export interface SceneInstanceStatePayload {
5
+ readonly source: Handle<'SceneAsset', 'shared'>;
6
+ readonly sceneSourceKey?: string;
7
+ readonly bindings: Map<string, EntityHandle>;
8
+ readonly entityToLocalId: Map<EntityHandle, LocalEntityId>;
9
+ readonly detachedLocalIds: Set<LocalEntityId>;
10
+ readonly overrides: Map<LocalEntityId, Map<string, {
11
+ readonly comp: string;
12
+ readonly field?: string;
13
+ readonly value: unknown;
14
+ }>>;
15
+ readonly rootEntities: EntityHandle[];
16
+ readonly mountRoots: EntityHandle[];
17
+ readonly totalSlots: number;
18
+ readonly mountTimeOverrides: readonly MountOverride[];
19
+ }
20
+ export interface SceneWorldState {
21
+ resolver: unknown;
22
+ readonly statePayloads: Map<number, unknown>;
23
+ }
24
+ export declare function sceneWorldState(world: World): SceneWorldState;
25
+ export declare function mountOverrideStateKey(ov: MountOverride): string;
26
+ export declare function isPrimitiveScalarFieldType(fieldType: string): boolean;
27
+ export declare function primitiveJsType(fieldType: string): string;
28
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/instances/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAElF,uDAAuD;AACvD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC7C,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAC3D,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;IAC9C,QAAQ,CAAC,SAAS,EAAE,GAAG,CACrB,aAAa,EACb,GAAG,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CACzF,CAAC;IACF,QAAQ,CAAC,YAAY,EAAE,YAAY,EAAE,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,kBAAkB,EAAE,SAAS,aAAa,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9C;AAID,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,eAAe,CAM7D;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,CAE/D;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAgBrE;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAiBrD,wBAAgB,WAAW,IAAI,MAAM,CASpC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAwBrD,wBAAgB,WAAW,IAAI,MAAM,CASpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"hierarchy-projection.d.ts","sourceRoot":"","sources":["../../src/systems/hierarchy-projection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAG5E,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElE,MAAM,WAAW,wBAAwB;IACvC,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,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC3D,QAAQ,CAAC,WAAW,EAAE,SAAS,wBAAwB,EAAE,CAAC;IAC1D,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,GAAG,SAAS,CAAC;CAC3D;AAqCD,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,sBAAsB,CA+ErE"}
1
+ {"version":3,"file":"hierarchy-projection.d.ts","sourceRoot":"","sources":["../../src/systems/hierarchy-projection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,YAAY,EAAc,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAExF,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElE,MAAM,WAAW,wBAAwB;IACvC,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,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC3D,QAAQ,CAAC,WAAW,EAAE,SAAS,wBAAwB,EAAE,CAAC;IAC1D,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,GAAG,SAAS,CAAC;CAC3D;AAkDD,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,sBAAsB,CAoFrE"}
@@ -1,3 +1,3 @@
1
1
  export { projectHierarchy, type SceneHierarchyDiagnostic, type SceneHierarchySnapshot, } from './hierarchy-projection';
2
- export { PROPAGATE_TRANSFORMS_SYSTEM, propagateTransforms, registerPropagateTransforms, TransformSet, } from './propagate-transforms';
2
+ export { PROPAGATE_TRANSFORMS_FIXED_SYSTEM, PROPAGATE_TRANSFORMS_SYSTEM, PropagateTransformsFixed, propagateTransforms, registerPropagateTransforms, TransformFixedSet, TransformSet, } from './propagate-transforms';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/systems/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,2BAA2B,EAC3B,YAAY,GACb,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/systems/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,iCAAiC,EACjC,2BAA2B,EAC3B,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC3B,iBAAiB,EACjB,YAAY,GACb,MAAM,wBAAwB,CAAC"}
@@ -1,12 +1,32 @@
1
1
  import { type SystemHandle, type World } from '@forgeax/engine-ecs';
2
2
  import { type Result } from '@forgeax/engine-types';
3
3
  import { SceneError } from '../errors';
4
- import { type SceneHierarchySnapshot } from './hierarchy-projection';
5
4
  export declare const PROPAGATE_TRANSFORMS_SYSTEM: "propagateTransforms";
6
5
  export declare const PROPAGATE_TRANSFORMS_FIXED_SYSTEM: "propagateTransformsFixed";
7
6
  export declare const TransformSet: import("@forgeax/engine-ecs").SystemSet;
8
7
  export declare const TransformFixedSet: import("@forgeax/engine-ecs").SystemSet;
9
- export declare function propagateTransforms(world: World, _hierarchy?: SceneHierarchySnapshot): Result<void, SceneError>;
8
+ /**
9
+ * Optional, test-owned counters for the parent-first executor. The counters
10
+ * are disabled unless a caller brackets a run with begin/end; production
11
+ * propagation therefore pays only one predictable branch per instrumented
12
+ * event. They are deliberately not a second execution state or a public
13
+ * dirty/cache contract.
14
+ */
15
+ export interface TransformPropagationTrace {
16
+ hierarchyRootInvocations: number;
17
+ hierarchyRootCursorReuses: number;
18
+ hierarchyRootCursorAllocations: number;
19
+ hierarchyEntityLookups: number;
20
+ hierarchyRowsEvaluated: number;
21
+ hierarchyEdgesVisited: number;
22
+ hierarchyPublishedRows: number;
23
+ hierarchyPublishedRuns: number;
24
+ hierarchyResidualParentProbes: number;
25
+ flatStructuralRootRows: number;
26
+ }
27
+ export declare function beginTransformPropagationTrace(): void;
28
+ export declare function endTransformPropagationTrace(): TransformPropagationTrace;
29
+ export declare function propagateTransforms(world: World): Result<void, SceneError>;
10
30
  export declare const PropagateTransforms: SystemHandle<readonly []>;
11
31
  export declare const PropagateTransformsFixed: SystemHandle<readonly []>;
12
32
  export declare function registerPropagateTransforms(world: World, options?: {
@@ -1 +1 @@
1
- {"version":3,"file":"propagate-transforms.d.ts","sourceRoot":"","sources":["../../src/systems/propagate-transforms.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,YAAY,EAEjB,KAAK,KAAK,EACX,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG7D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAoB,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEvF,eAAO,MAAM,2BAA2B,EAAG,qBAA8B,CAAC;AAC1E,eAAO,MAAM,iCAAiC,EAAG,0BAAmC,CAAC;AACrF,eAAO,MAAM,YAAY,yCAAyC,CAAC;AACnE,eAAO,MAAM,iBAAiB,yCAA+C,CAAC;AAgM9E,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,KAAK,EACZ,UAAU,CAAC,EAAE,sBAAsB,GAClC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CA2F1B;AAED,eAAO,MAAM,mBAAmB,EAAE,YAAY,CAAC,SAAS,EAAE,CAOxD,CAAC;AAEH,eAAO,MAAM,wBAAwB,EAAE,YAAY,CAAC,SAAS,EAAE,CAI7D,CAAC;AAEH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1C,MAAM,IAAI,CA6CZ"}
1
+ {"version":3,"file":"propagate-transforms.d.ts","sourceRoot":"","sources":["../../src/systems/propagate-transforms.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,YAAY,EAEjB,KAAK,KAAK,EACX,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAI7D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,eAAO,MAAM,2BAA2B,EAAG,qBAA8B,CAAC;AAC1E,eAAO,MAAM,iCAAiC,EAAG,0BAAmC,CAAC;AACrF,eAAO,MAAM,YAAY,yCAAyC,CAAC;AACnE,eAAO,MAAM,iBAAiB,yCAA+C,CAAC;AAE9E;;;;;;GAMG;AACH,MAAM,WAAW,yBAAyB;IACxC,wBAAwB,EAAE,MAAM,CAAC;IACjC,yBAAyB,EAAE,MAAM,CAAC;IAClC,8BAA8B,EAAE,MAAM,CAAC;IACvC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,6BAA6B,EAAE,MAAM,CAAC;IACtC,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAWD,wBAAgB,8BAA8B,IAAI,IAAI,CAcrD;AAED,wBAAgB,4BAA4B,IAAI,yBAAyB,CAsBxE;AAklCD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAO1E;AAED,eAAO,MAAM,mBAAmB,EAAE,YAAY,CAAC,SAAS,EAAE,CAOxD,CAAC;AAEH,eAAO,MAAM,wBAAwB,EAAE,YAAY,CAAC,SAAS,EAAE,CAI7D,CAAC;AAEH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1C,MAAM,IAAI,CA8CZ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/engine-scene",
3
- "version": "0.1.21",
3
+ "version": "0.1.24",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -22,10 +22,10 @@
22
22
  "LICENSE"
23
23
  ],
24
24
  "dependencies": {
25
- "@forgeax/engine-ecs": "0.1.21",
26
- "@forgeax/engine-math": "0.1.21",
27
- "@forgeax/engine-plugin": "0.1.21",
28
- "@forgeax/engine-types": "0.1.21"
25
+ "@forgeax/engine-ecs": "0.1.24",
26
+ "@forgeax/engine-math": "0.1.24",
27
+ "@forgeax/engine-plugin": "0.1.24",
28
+ "@forgeax/engine-types": "0.1.24"
29
29
  },
30
30
  "forgeax": {
31
31
  "metrics": {
@@ -1,12 +1,22 @@
1
1
  import { World } from '@forgeax/engine-ecs';
2
+ import { createRenderReadLease } from '@forgeax/engine-ecs/projection';
2
3
  import { describe, expect, it } from 'vitest';
3
- import { ChildOf, Children, Name, Transform } from '../index';
4
+ import {
5
+ ChildOf,
6
+ Children,
7
+ GlobalTransform,
8
+ MorphWeights,
9
+ Name,
10
+ propagateTransforms,
11
+ Transform,
12
+ } from '../index';
4
13
 
5
14
  describe('scene component roster', () => {
6
15
  it('exports exactly the four scene components', () => {
7
- expect(Object.keys({ Name, Transform, ChildOf, Children }).sort()).toEqual([
16
+ expect(Object.keys({ Name, Transform, GlobalTransform, ChildOf, Children }).sort()).toEqual([
8
17
  'ChildOf',
9
18
  'Children',
19
+ 'GlobalTransform',
10
20
  'Name',
11
21
  'Transform',
12
22
  ]);
@@ -23,4 +33,26 @@ describe('scene component roster', () => {
23
33
  .unwrap();
24
34
  expect(world.get(entity, Name).unwrap().value).toBe('root');
25
35
  });
36
+
37
+ it('keeps world transform reads on the renderer projection boundary', () => {
38
+ const world = new World();
39
+ const entity = world.spawn({ component: Transform, data: { pos: [3, 0, 0] } }).unwrap();
40
+ expect(propagateTransforms(world).ok).toBe(true);
41
+
42
+ const lease = createRenderReadLease(world);
43
+ const projection = lease.querySpans({
44
+ components: [{ component: GlobalTransform, fields: ['world'] }],
45
+ });
46
+ const worldColumn = projection.spans[0]?.fields.world;
47
+ expect(worldColumn?.[12]).toBeCloseTo(3);
48
+ expect(lease.generation).toBeGreaterThan(0);
49
+ lease.dispose();
50
+ expect(world.get(entity, GlobalTransform).unwrap().world[12]).toBeCloseTo(3);
51
+ });
52
+
53
+ it('keeps morph weights outside the transform carrier lane', () => {
54
+ expect(MorphWeights.name).toBe('MorphWeights');
55
+ expect(Transform.name).toBe('Transform');
56
+ expect(MorphWeights).not.toBe(Transform);
57
+ });
26
58
  });
@@ -1,15 +1,37 @@
1
1
  import type { EntityHandle, World } from '@forgeax/engine-ecs';
2
+ import { componentId } from '../../../../ecs/src/component';
3
+ import { entityIndex } from '../../../../ecs/src/entity-handle';
4
+ import { worldInternal } from '../../../../ecs/src/world-internal';
2
5
  import { ChildOf } from '../../index';
3
6
 
4
7
  /**
5
- * Scene-owned malformed-edge fixture. The public relationship write accepts
6
- * stale handles as data; the projection then owns the liveness diagnostic.
7
- * Keeping this fixture on `world.set` avoids a private ECS graph seam.
8
+ * Scene-owned malformed-edge fixture. Production relationship writes reject
9
+ * stale targets and cycles before touching either side of the relationship.
10
+ * This test-only fixture deliberately corrupts the source column through the
11
+ * existing package-internal graph seam so projection can exercise its
12
+ * fail-closed diagnostics without weakening the public write contract.
8
13
  */
9
14
  export function setMalformedParentEdge(
10
15
  world: World,
11
16
  child: EntityHandle,
12
17
  parent: EntityHandle,
13
18
  ): void {
14
- world.set(child, ChildOf, { parent }).unwrap();
19
+ const record = world[worldInternal].getRecords()[entityIndex(child)];
20
+ if (record === undefined || record.archetypeId < 0) {
21
+ throw new Error(`Malformed hierarchy fixture child ${child} is not live.`);
22
+ }
23
+ const graph = world[worldInternal].getGraph();
24
+ const archetype = graph.archetypes[record.archetypeId];
25
+ if (archetype === undefined) throw new Error(`Missing archetype ${record.archetypeId}.`);
26
+ const table = graph.tables[archetype.tableId];
27
+ const column = table?.storage.get(componentId(ChildOf))?.fields.get('parent');
28
+ const tableRow = archetype.rows[record.archetypeRow];
29
+ if (column === undefined || tableRow === undefined) {
30
+ throw new Error(`Malformed hierarchy fixture child ${child} lacks ChildOf storage.`);
31
+ }
32
+ column.view[tableRow] = parent as number;
33
+ // Keep the corruption internal, but make the source mutation observable to
34
+ // the normal change-token consumers so an already-built projection cannot
35
+ // mask the deliberately malformed value.
36
+ world[worldInternal].markComponentChanged(child, componentId(ChildOf));
15
37
  }
@@ -0,0 +1,128 @@
1
+ // @ts-expect-error The Vitest runtime provides Node's fs module; scene package declarations stay browser-safe.
2
+ import { readFileSync } from 'node:fs';
3
+ import { type EntityHandle, FixedUpdate, Update, World } from '@forgeax/engine-ecs';
4
+ import { describe, expect, it } from 'vitest';
5
+ import { GlobalTransform, propagateTransforms, Transform } from '../index';
6
+ import { registerPropagateTransforms } from '../systems';
7
+
8
+ const COUNTS = [10_000, 100_000] as const;
9
+ const MOVERS = [1, 100, 10_000] as const;
10
+
11
+ function spawnFlatWorld(count: number): { world: World; entities: EntityHandle[] } {
12
+ const world = new World();
13
+ const entities = Array.from({ length: count }, (_, index) =>
14
+ world.spawn({ component: Transform, data: { pos: [index, 0, 0] } }).unwrap(),
15
+ );
16
+ registerPropagateTransforms(world);
17
+ return { world, entities };
18
+ }
19
+
20
+ describe('flat Transform propagation contract', () => {
21
+ it.each(COUNTS)('keeps %s independent rows on the simple lane', (count) => {
22
+ const { world } = spawnFlatWorld(count);
23
+ expect(world.update(0).ok).toBe(true);
24
+
25
+ const query = world.query({ read: [Transform, GlobalTransform] }).unwrap();
26
+ const spans = query.spans();
27
+ expect(spans.ok).toBe(true);
28
+ expect([...spans.unwrap()]).toHaveLength(1);
29
+ expect([...query]).toHaveLength(count);
30
+ });
31
+
32
+ it.each(MOVERS)('publishes a same-tick world checksum for %s movers', (movers) => {
33
+ const { world, entities } = spawnFlatWorld(10_000);
34
+ const first = entities[0];
35
+ if (first === undefined) throw new Error('expected first flat entity');
36
+ let observed = 0;
37
+ world
38
+ .addSystem(Update, {
39
+ name: `flat-writer-${movers}`,
40
+ queries: [],
41
+ before: ['propagateTransforms'],
42
+ fn: () => {
43
+ for (let index = 0; index < movers; index += 1) {
44
+ const entity = entities[index];
45
+ if (entity !== undefined) world.set(entity, Transform, { pos: [index + 1, 0, 0] });
46
+ }
47
+ },
48
+ })
49
+ .unwrap();
50
+ world
51
+ .addSystem(Update, {
52
+ name: `flat-reader-${movers}`,
53
+ queries: [],
54
+ after: ['propagateTransforms'],
55
+ fn: () => {
56
+ observed = 0;
57
+ for (const row of world.query({ read: [GlobalTransform] }).unwrap()) {
58
+ observed += row.get(GlobalTransform).world[12] ?? 0;
59
+ }
60
+ },
61
+ })
62
+ .unwrap();
63
+
64
+ expect(world.update(0).ok).toBe(true);
65
+ expect(observed).toBeGreaterThan(0);
66
+ expect(world.get(first, GlobalTransform).unwrap().world[12]).toBeCloseTo(1);
67
+ });
68
+
69
+ it('runs local writers before propagation and world readers after it in FixedUpdate', () => {
70
+ const { world, entities } = spawnFlatWorld(10_000);
71
+ const first = entities[0];
72
+ if (first === undefined) throw new Error('expected first flat entity');
73
+ const trace: string[] = [];
74
+ world
75
+ .addSystem(FixedUpdate, {
76
+ name: 'flat-fixed-writer',
77
+ queries: [],
78
+ before: ['propagateTransformsFixed'],
79
+ fn: () => {
80
+ trace.push('writer');
81
+ world.set(first, Transform, { pos: [9, 0, 0] });
82
+ },
83
+ })
84
+ .unwrap();
85
+ world
86
+ .addSystem(FixedUpdate, {
87
+ name: 'flat-fixed-reader',
88
+ queries: [],
89
+ after: ['propagateTransformsFixed'],
90
+ fn: () => {
91
+ trace.push('reader');
92
+ expect(world.get(first, GlobalTransform).unwrap().world[12]).toBeCloseTo(9);
93
+ },
94
+ })
95
+ .unwrap();
96
+
97
+ expect(world.update(1 / 60).ok).toBe(true);
98
+ expect(trace).toEqual(['writer', 'reader']);
99
+ });
100
+
101
+ it('does not retain an entity collection or a second lane in the flat owner', async () => {
102
+ const source = readFileSync('packages/scene/src/systems/propagate-transforms.ts', 'utf8');
103
+ expect(source).not.toMatch(/new (Map|Set)|\b(Map|Set)</);
104
+ expect(source).not.toMatch(/PropagationCache/);
105
+ expect(source).toContain('changed: [Transform]');
106
+ expect(source).toContain('composeFlatColumns');
107
+ expect(source).not.toContain('.subarray(');
108
+ });
109
+
110
+ it('reuses cached queries after warmup while a dynamic mover changes', () => {
111
+ const { world, entities } = spawnFlatWorld(10_000);
112
+ world.update(0).unwrap();
113
+ const originalQuery = world.query.bind(world);
114
+ let queryCalls = 0;
115
+ world.query = ((descriptor: Parameters<World['query']>[0]) => {
116
+ queryCalls += 1;
117
+ return originalQuery(descriptor);
118
+ }) as World['query'];
119
+
120
+ const first = entities[0];
121
+ if (first === undefined) throw new Error('expected first flat entity');
122
+ world.set(first, Transform, { pos: [42, 0, 0] }).unwrap();
123
+ propagateTransforms(world).unwrap();
124
+
125
+ expect(queryCalls).toBe(0);
126
+ expect(world.get(first, GlobalTransform).unwrap().world[12]).toBeCloseTo(42);
127
+ });
128
+ });
@@ -0,0 +1,39 @@
1
+ import { type EntityHandle, World } from '@forgeax/engine-ecs';
2
+ import { getDerivedWriter } from '@forgeax/engine-ecs/internal';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { GlobalTransform, Transform } from '../index';
5
+
6
+ describe('C flat propagation derived writer contract', () => {
7
+ it('writes a contiguous GlobalTransform range while keeping authored local values separate', () => {
8
+ const world = new World();
9
+ const entities: EntityHandle[] = [];
10
+ for (let index = 0; index < 4; index += 1) {
11
+ entities.push(world.spawn({ component: Transform, data: { pos: [index, 0, 0] } }).unwrap());
12
+ }
13
+ const first = entities[0];
14
+ const second = entities[1];
15
+ const third = entities[2];
16
+ if (first === undefined || second === undefined || third === undefined) {
17
+ throw new Error('expected fixture entities');
18
+ }
19
+ const query = world.query({ read: [Transform], write: [GlobalTransform] }).unwrap();
20
+ const writer = getDerivedWriter(query, GlobalTransform).unwrap();
21
+ const result = writer.writeRange(
22
+ 0,
23
+ 0,
24
+ 1,
25
+ 2,
26
+ (binding, _base, start, count) => {
27
+ expect(count).toBe(2);
28
+ binding.write.world[(start + 0) * 16 + 12] = 101;
29
+ binding.write.world[(start + 1) * 16 + 12] = 102;
30
+ },
31
+ undefined,
32
+ );
33
+ expect(result.ok).toBe(true);
34
+ expect(world.get(first, Transform).unwrap().pos[0]).toBe(0);
35
+ expect(world.get(second, Transform).unwrap().pos[0]).toBe(1);
36
+ expect(world.get(second, GlobalTransform).unwrap().world[12]).toBe(101);
37
+ expect(world.get(third, GlobalTransform).unwrap().world[12]).toBe(102);
38
+ });
39
+ });