@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.
- package/README.md +82 -11
- package/dist/__tests__/fixtures/malformed-hierarchy-edge.d.ts +5 -3
- package/dist/__tests__/fixtures/malformed-hierarchy-edge.d.ts.map +1 -1
- package/dist/__tests__/flat-propagation.contract.test.d.ts +2 -0
- package/dist/__tests__/flat-propagation.contract.test.d.ts.map +1 -0
- package/dist/__tests__/flat-propagation.derived-writer.contract.test.d.ts +2 -0
- package/dist/__tests__/flat-propagation.derived-writer.contract.test.d.ts.map +1 -0
- package/dist/__tests__/flat-propagation.perf.test.d.ts +2 -0
- package/dist/__tests__/flat-propagation.perf.test.d.ts.map +1 -0
- package/dist/__tests__/hierarchy-propagation.perf.test.d.ts +2 -0
- package/dist/__tests__/hierarchy-propagation.perf.test.d.ts.map +1 -0
- package/dist/__tests__/scene-binding.integration.test.d.ts +2 -0
- package/dist/__tests__/scene-binding.integration.test.d.ts.map +1 -0
- package/dist/__tests__/schedule-order.contract.test.d.ts +2 -0
- package/dist/__tests__/schedule-order.contract.test.d.ts.map +1 -0
- package/dist/__tests__/structural.test.d.ts +2 -0
- package/dist/__tests__/structural.test.d.ts.map +1 -0
- package/dist/__tests__/transform-carrier-consumers.test-d.d.ts +2 -0
- package/dist/__tests__/transform-carrier-consumers.test-d.d.ts.map +1 -0
- package/dist/__tests__/transform-carrier-prototype.bench.d.ts +39 -0
- package/dist/__tests__/transform-carrier-prototype.bench.d.ts.map +1 -0
- package/dist/__tests__/transform-carrier-prototype.test-d.d.ts +2 -0
- package/dist/__tests__/transform-carrier-prototype.test-d.d.ts.map +1 -0
- package/dist/__tests__/transform-carrier-prototype.test.d.ts +2 -0
- package/dist/__tests__/transform-carrier-prototype.test.d.ts.map +1 -0
- package/dist/__tests__/transform-component-version.unit.test.d.ts +2 -0
- package/dist/__tests__/transform-component-version.unit.test.d.ts.map +1 -0
- package/dist/assets/scene-decoder.d.ts.map +1 -1
- package/dist/components/child-of.d.ts +23 -14
- package/dist/components/child-of.d.ts.map +1 -1
- package/dist/components/children.d.ts +14 -13
- package/dist/components/children.d.ts.map +1 -1
- package/dist/components/transform.d.ts +7 -43
- package/dist/components/transform.d.ts.map +1 -1
- package/dist/errors.d.ts +23 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1122 -358
- package/dist/index.mjs.map +1 -1
- package/dist/instances/binding.d.ts +29 -0
- package/dist/instances/binding.d.ts.map +1 -0
- package/dist/instances/externalization.d.ts.map +1 -1
- package/dist/instances/scene-instances.d.ts +6 -18
- package/dist/instances/scene-instances.d.ts.map +1 -1
- package/dist/instances/state.d.ts +28 -0
- package/dist/instances/state.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/systems/hierarchy-projection.d.ts.map +1 -1
- package/dist/systems/index.d.ts +1 -1
- package/dist/systems/index.d.ts.map +1 -1
- package/dist/systems/propagate-transforms.d.ts +22 -2
- package/dist/systems/propagate-transforms.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/components.unit.test.ts +34 -2
- package/src/__tests__/fixtures/malformed-hierarchy-edge.ts +26 -4
- package/src/__tests__/flat-propagation.contract.test.ts +128 -0
- package/src/__tests__/flat-propagation.derived-writer.contract.test.ts +39 -0
- package/src/__tests__/flat-propagation.perf.test.ts +336 -0
- package/src/__tests__/hierarchy-propagation.perf.test.ts +149 -0
- package/src/__tests__/plugin.integration.test.ts +2 -2
- package/src/__tests__/propagation.unit.test.ts +271 -91
- package/src/__tests__/scene-binding.integration.test.ts +124 -0
- package/src/__tests__/schedule-order.contract.test.ts +43 -0
- package/src/__tests__/structural.test.ts +23 -0
- package/src/__tests__/transform-carrier-consumers.test-d.ts +156 -0
- package/src/__tests__/transform-carrier-prototype.bench.ts +168 -0
- package/src/__tests__/transform-carrier-prototype.test-d.ts +71 -0
- package/src/__tests__/transform-carrier-prototype.test.ts +170 -0
- package/src/__tests__/{transform-change-journal.unit.test.ts → transform-component-version.unit.test.ts} +32 -39
- package/src/assets/scene-decoder.ts +6 -1
- package/src/components/child-of.ts +38 -27
- package/src/components/children.ts +36 -37
- package/src/components/transform.ts +23 -81
- package/src/errors.ts +26 -2
- package/src/index.ts +10 -1
- package/src/instances/binding.ts +77 -0
- package/src/instances/externalization.ts +7 -1
- package/src/instances/scene-instances.ts +51 -80
- package/src/instances/state.ts +62 -0
- package/src/plugin.ts +9 -2
- package/src/systems/hierarchy-projection.ts +25 -8
- package/src/systems/index.ts +3 -0
- package/src/systems/propagate-transforms.ts +1142 -240
- package/dist/.tsbuildinfo +0 -1
- package/dist/__tests__/transform-change-journal.unit.test.d.ts +0 -2
- 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,
|
|
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
|
-
*
|
|
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":"AAEA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,QAAQ,EAEb,KAAK,YAAY,EAEjB,KAAK,OAAO,EACZ,KAAK,KAAK,EACX,MAAM,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EACV,MAAM,EACN,aAAa,EACb,aAAa,EAGb,UAAU,EACV,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAIL,KAAK,MAAM,EAGZ,MAAM,uBAAuB,CAAC;
|
|
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"}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -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;
|
|
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,
|
|
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"}
|
package/dist/systems/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
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.
|
|
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.
|
|
26
|
-
"@forgeax/engine-math": "0.1.
|
|
27
|
-
"@forgeax/engine-plugin": "0.1.
|
|
28
|
-
"@forgeax/engine-types": "0.1.
|
|
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 {
|
|
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.
|
|
6
|
-
* stale
|
|
7
|
-
*
|
|
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
|
-
|
|
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
|
+
});
|