@forgeax/engine-app 0.1.3 → 0.1.6
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 +20 -14
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/create-app-error-retention.integration.test.d.ts +2 -0
- package/dist/__tests__/create-app-error-retention.integration.test.d.ts.map +1 -0
- package/dist/__tests__/create-app-physics-plugin-failure.integration.test.d.ts +2 -0
- package/dist/__tests__/create-app-physics-plugin-failure.integration.test.d.ts.map +1 -0
- package/dist/animation-asset-lookup.d.ts +1 -2
- package/dist/animation-asset-lookup.d.ts.map +1 -1
- package/dist/create-app.d.ts +31 -10
- package/dist/create-app.d.ts.map +1 -1
- package/dist/engine-worker-runtime.mjs +72 -129
- package/dist/engine-worker-runtime.mjs.map +1 -1
- package/dist/errors.d.ts +3 -12
- package/dist/errors.d.ts.map +1 -1
- package/dist/execution/attached-world-swap.d.ts +1 -12
- package/dist/execution/attached-world-swap.d.ts.map +1 -1
- package/dist/execution/bootstrap-url.d.ts +5 -0
- package/dist/execution/bootstrap-url.d.ts.map +1 -0
- package/dist/execution/control.d.ts +0 -2
- package/dist/execution/control.d.ts.map +1 -1
- package/dist/execution/engine-worker.d.ts +1 -0
- package/dist/execution/engine-worker.d.ts.map +1 -1
- package/dist/execution/host-controller.d.ts.map +1 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/protocol.d.ts +4 -1
- package/dist/execution/protocol.d.ts.map +1 -1
- package/dist/execution/types.d.ts +17 -1
- package/dist/execution/types.d.ts.map +1 -1
- package/dist/game-context.d.ts +1 -1
- package/dist/game-context.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +332 -366
- package/dist/index.mjs.map +1 -1
- package/dist/internal/assembled-engine-profile.d.ts.map +1 -1
- package/dist/internal/assets-world-plugin.d.ts +3 -17
- package/dist/internal/assets-world-plugin.d.ts.map +1 -1
- package/dist/internal/browser-remote-bridge.d.ts +1 -2
- package/dist/internal/browser-remote-bridge.d.ts.map +1 -1
- package/dist/internal/browser-rhi-debug-runtime.d.ts +1 -1
- package/dist/internal/browser-rhi-debug-runtime.d.ts.map +1 -1
- package/dist/internal/debug-draw.d.ts +9 -0
- package/dist/internal/debug-draw.d.ts.map +1 -0
- package/dist/internal/engine-profile-common.d.ts +2 -2
- package/dist/internal/engine-profile-common.d.ts.map +1 -1
- package/dist/internal/frame-loop.d.ts +7 -4
- package/dist/internal/frame-loop.d.ts.map +1 -1
- package/dist/internal/main-engine-profile.d.ts +4 -0
- package/dist/internal/main-engine-profile.d.ts.map +1 -1
- package/dist/internal/remote-serve-flag.d.ts +3 -7
- package/dist/internal/remote-serve-flag.d.ts.map +1 -1
- package/dist/internal/rhi-capture.d.ts +1 -1
- package/dist/internal/rhi-capture.d.ts.map +1 -1
- package/dist/internal/worker-engine-profile.d.ts +2 -0
- package/dist/internal/worker-engine-profile.d.ts.map +1 -1
- package/dist/renderer-plugin.d.ts +25 -0
- package/dist/renderer-plugin.d.ts.map +1 -0
- package/dist/tool-preview/bootstrap.d.ts.map +1 -1
- package/dist/types.d.ts +21 -61
- package/dist/types.d.ts.map +1 -1
- package/package.json +25 -26
- package/src/__tests__/callback-inference.test-d.ts +7 -3
- package/src/__tests__/consumer-migration.unit.test.ts +13 -0
- package/src/__tests__/create-app-error-retention.integration.test.ts +125 -0
- package/src/__tests__/create-app-features.test.ts +21 -10
- package/src/__tests__/create-app-listener-sync.test.ts +23 -19
- package/src/__tests__/create-app-physics-plugin-failure.integration.test.ts +142 -0
- package/src/__tests__/create-app-stop.test.ts +4 -12
- package/src/__tests__/create-app.test-d.ts +12 -11
- package/src/__tests__/create-app.test.ts +1 -60
- package/src/__tests__/create-renderer-error.integration.test.ts +3 -2
- package/src/__tests__/create-renderer-lifecycle.integration.test.ts +10 -5
- package/src/__tests__/draw-source-injected-world-update-visibility.test.ts +7 -13
- package/src/__tests__/draw-source-single-world-regression.test.ts +23 -24
- package/src/__tests__/engine-worker-bootstrap-channel.unit.test.ts +8 -0
- package/src/__tests__/engine-worker-world-swap.unit.test.ts +15 -22
- package/src/__tests__/errors-pointer-lock-failed.test.ts +4 -7
- package/src/__tests__/execution-bootstrap-isolation.unit.test.ts +5 -6
- package/src/__tests__/execution-frame-order.unit.test.ts +2 -2
- package/src/__tests__/execution-frame-protocol.unit.test.ts +3 -4
- package/src/__tests__/execution-public-api.test-d.ts +4 -0
- package/src/__tests__/frame-loop-time-elapsed.test.ts +1 -1
- package/src/__tests__/frame-loop-time.unit.test.ts +1 -1
- package/src/__tests__/frame-loop-world-array.test.ts +82 -73
- package/src/__tests__/plugin-profiles.unit.test.ts +3 -3
- package/src/__tests__/profiler-default-off.test.ts +1 -1
- package/src/__tests__/profiler-frame-token.test.ts +17 -30
- package/src/__tests__/profiler-phase-integration.test.ts +15 -27
- package/src/__tests__/surface-handoff.test.ts +1 -4
- package/src/__tests__/visibility-remote.integration.test.ts +2 -5
- package/src/__tests__/worker-execution-stop.test.ts +64 -7
- package/src/animation-asset-lookup.ts +2 -2
- package/src/create-app.ts +197 -296
- package/src/errors.ts +27 -39
- package/src/execution/attached-world-swap.ts +4 -38
- package/src/execution/bootstrap-url.ts +25 -0
- package/src/execution/control.ts +3 -7
- package/src/execution/engine-worker-runtime.ts +23 -40
- package/src/execution/engine-worker.ts +2 -0
- package/src/execution/host-controller.ts +8 -2
- package/src/execution/index.ts +1 -0
- package/src/execution/protocol.ts +4 -1
- package/src/execution/types.ts +18 -1
- package/src/game-context.ts +1 -1
- package/src/index.ts +11 -4
- package/src/internal/assembled-engine-profile.ts +3 -11
- package/src/internal/assets-world-plugin.ts +7 -53
- package/src/internal/browser-remote-bridge.ts +12 -10
- package/src/internal/browser-rhi-debug-runtime.ts +1 -1
- package/src/internal/debug-draw.ts +38 -0
- package/src/internal/engine-profile-common.ts +2 -3
- package/src/internal/frame-loop.ts +77 -63
- package/src/internal/main-engine-profile.ts +21 -17
- package/src/internal/remote-serve-flag.ts +5 -14
- package/src/internal/rhi-capture.ts +1 -1
- package/src/internal/worker-engine-profile.ts +10 -10
- package/src/renderer-plugin.ts +96 -0
- package/src/tool-preview/bootstrap.ts +1 -14
- package/src/types.ts +22 -77
- package/src/vite-env.d.ts +0 -2
- package/dist/__tests__/app-rebuild.test.d.ts +0 -2
- package/dist/__tests__/app-rebuild.test.d.ts.map +0 -1
- package/dist/__tests__/asset-registry-types.test-d.d.ts +0 -2
- package/dist/__tests__/asset-registry-types.test-d.d.ts.map +0 -1
- package/dist/__tests__/assets-runtime-assembly.integration.test.d.ts +0 -2
- package/dist/__tests__/assets-runtime-assembly.integration.test.d.ts.map +0 -1
- package/dist/__tests__/draw-source-headless-full-chain.test.d.ts +0 -2
- package/dist/__tests__/draw-source-headless-full-chain.test.d.ts.map +0 -1
- package/dist/__tests__/ecs-import.unit.test.d.ts +0 -2
- package/dist/__tests__/ecs-import.unit.test.d.ts.map +0 -1
- package/dist/__tests__/execution-world-health-owner.test-d.d.ts +0 -2
- package/dist/__tests__/execution-world-health-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/remote-serve-flag.test.d.ts +0 -2
- package/dist/__tests__/remote-serve-flag.test.d.ts.map +0 -1
- package/dist/assets-runtime-assembly.d.ts +0 -19
- package/dist/assets-runtime-assembly.d.ts.map +0 -1
- package/src/__tests__/app-rebuild.test.ts +0 -31
- package/src/__tests__/asset-registry-types.test-d.ts +0 -16
- package/src/__tests__/assets-runtime-assembly.integration.test.ts +0 -68
- package/src/__tests__/draw-source-headless-full-chain.test.ts +0 -226
- package/src/__tests__/ecs-import.unit.test.ts +0 -40
- package/src/__tests__/execution-world-health-owner.test-d.ts +0 -9
- package/src/__tests__/remote-serve-flag.test.ts +0 -24
- package/src/assets-runtime-assembly.ts +0 -70
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-app-error-retention.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/create-app-error-retention.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-app-physics-plugin-failure.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/create-app-physics-plugin-failure.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { AnimationPayloadLookup } from '@forgeax/engine-animation';
|
|
2
|
-
import type { Asset } from '@forgeax/engine-types';
|
|
3
2
|
export interface AnimationPayloadSource {
|
|
4
|
-
lookup<T
|
|
3
|
+
lookup<T = unknown>(guid: string): T | undefined;
|
|
5
4
|
}
|
|
6
5
|
/** Bridge the renderer-owned GUID catalogue into the animation plugin. */
|
|
7
6
|
export declare function createAnimationPayloadLookup(source: AnimationPayloadSource | undefined): AnimationPayloadLookup;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animation-asset-lookup.d.ts","sourceRoot":"","sources":["../src/animation-asset-lookup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"animation-asset-lookup.d.ts","sourceRoot":"","sources":["../src/animation-asset-lookup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAGxE,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAClD;AAED,0EAA0E;AAC1E,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,sBAAsB,GAAG,SAAS,GACzC,sBAAsB,CAExB"}
|
package/dist/create-app.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { World } from '@forgeax/engine-ecs';
|
|
1
2
|
import { type Result } from '@forgeax/engine-types';
|
|
2
|
-
|
|
3
|
-
import type { App, AppAssembleArgs, AssembleAppError, BundlerOptions, CanvasAppError, CanvasDrawingBufferSize, CreateAppOptions, ExecutionApp } from './types';
|
|
3
|
+
import type { App, AppAssembleArgs, AssembleAppError, BundlerOptions, CanvasAppError, CreateAppOptions, ExecutionApp } from './types';
|
|
4
4
|
/**
|
|
5
5
|
* createApp(canvas, opts?, bundler?) -- canvas thin wrapper SSOT (per
|
|
6
6
|
* plan-strategy D-5). Resolves with Result.ok(app) on success; failure routes
|
|
@@ -27,7 +27,8 @@ export declare function createApp(canvas: HTMLCanvasElement, opts: CreateAppOpti
|
|
|
27
27
|
}, bundler?: BundlerOptions): Promise<Result<ExecutionApp, CanvasAppError>>;
|
|
28
28
|
export declare function createApp(canvas: HTMLCanvasElement, opts?: CreateAppOptions, bundler?: BundlerOptions): Promise<Result<App, CanvasAppError>>;
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* Create the browser host for the single RenderScene -> FrameReceipt path.
|
|
31
|
+
* `createApp({ renderer, world, input?, schedule?, ... })` is the assemble form
|
|
31
32
|
* SSOT (per plan-strategy D-5). Host already owns renderer / world; the
|
|
32
33
|
* returned App holds them by reference equality (per AC-02).
|
|
33
34
|
*
|
|
@@ -45,13 +46,33 @@ export declare function createApp(args: AppAssembleArgs): Promise<Result<App, As
|
|
|
45
46
|
*/
|
|
46
47
|
export declare function syncCanvasDrawingBuffer(canvas: Pick<HTMLCanvasElement, 'clientWidth' | 'clientHeight' | 'width' | 'height'> & {
|
|
47
48
|
readonly style?: Pick<CSSStyleDeclaration, 'width' | 'height'>;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Measure the next effective drawing buffer without writing the DOM canvas.
|
|
51
|
-
* This is the Worker host path because transferControlToOffscreen makes the
|
|
52
|
-
* HTML canvas dimensions immutable; the Worker owns the transferred surface.
|
|
53
|
-
*/
|
|
49
|
+
}): void;
|
|
50
|
+
/** Measure a CSS-sized canvas without mutating its drawing buffer. */
|
|
54
51
|
export declare function measureCanvasDrawingBuffer(canvas: Pick<HTMLCanvasElement, 'clientWidth' | 'clientHeight' | 'width' | 'height'> & {
|
|
55
52
|
readonly style?: Pick<CSSStyleDeclaration, 'width' | 'height'>;
|
|
56
|
-
}, maxCanvasPixelRatio?: number):
|
|
53
|
+
}, maxCanvasPixelRatio?: number): {
|
|
54
|
+
readonly width: number;
|
|
55
|
+
readonly height: number;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Per-frame aspect-sync body for the createApp(canvas) path (feat-20260617
|
|
59
|
+
* M3 / w13). Walks every Camera entity and, for perspective cameras with
|
|
60
|
+
* `autoAspect === true`, writes `canvasW / canvasH` into `Camera.aspect`.
|
|
61
|
+
*
|
|
62
|
+
* Read discipline (D-5 / research Finding 2): `autoAspect` is read through
|
|
63
|
+
* `world.get` (the readRow path narrows the bool column to a JS boolean).
|
|
64
|
+
* The query bundle is used only to enumerate the entity handles -- reading
|
|
65
|
+
* the bool column off the bundle would return a raw 0/1 number, so a
|
|
66
|
+
* `!== 0` test is always true (the
|
|
67
|
+
* bool-field-compared-with-not-equal-zero-always-true trap).
|
|
68
|
+
*
|
|
69
|
+
* Best-effort + side-effect-isolated:
|
|
70
|
+
* - canvas size 0 (detached / display:none) -> skip entirely so `aspect`
|
|
71
|
+
* never becomes NaN / 0.
|
|
72
|
+
* - orthographic cameras and `autoAspect === false` cameras are left
|
|
73
|
+
* untouched.
|
|
74
|
+
*
|
|
75
|
+
* @see {@link https://github.com/Ubpa/forgeax-engine/blob/main/docs/how-to/2026-06-18-host-engine-contract.md | Host-engine contract SSOT}
|
|
76
|
+
*/
|
|
77
|
+
export declare function syncCameraAspect(world: World, canvasW: number, canvasH: number): void;
|
|
57
78
|
//# sourceMappingURL=create-app.d.ts.map
|
package/dist/create-app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-app.d.ts","sourceRoot":"","sources":["../src/create-app.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-app.d.ts","sourceRoot":"","sources":["../src/create-app.ts"],"names":[],"mappings":"AA4BA,OAAO,EAA8B,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAkBxE,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAkC7D,OAAO,KAAK,EACV,GAAG,EACH,eAAe,EAEf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,YAAY,EACb,MAAM,SAAS,CAAC;AAyCjB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,gBAAgB,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAA;CAAE,EAC3F,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;AACjD,wBAAgB,SAAS,CACvB,MAAM,EAAE,iBAAiB,EACzB,IAAI,CAAC,EAAE,gBAAgB,EACvB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;AAExC;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAwezF;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC,GAAG;IACrF,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,QAAQ,CAAC,CAAC;CAChE,GACA,IAAI,CA2CN;AAED,sEAAsE;AACtE,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC,GAAG;IACrF,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,QAAQ,CAAC,CAAC;CAChE,EACD,mBAAmB,CAAC,EAAE,MAAM,GAC3B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAsCrD;AAYD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAiBrF"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { createAssetRegistry, createCatalogSource } from '@forgeax/engine-assets-runtime';
|
|
2
1
|
import { createAudioIntentBackend, audioBackendPlugin } from '@forgeax/engine-audio';
|
|
3
2
|
import { World, createWorldContext, Update } from '@forgeax/engine-ecs';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { ownedRendererPlugin, renderComponentsPlugin, Camera, CAMERA_PROJECTION_PERSPECTIVE } from '@forgeax/engine-render';
|
|
3
|
+
import { constructRuntimeRendererHost } from '@forgeax/engine-runtime/internal/renderer-host';
|
|
4
|
+
import { renderComponentsPlugin, Camera, CAMERA_PROJECTION_PERSPECTIVE } from '@forgeax/engine-render';
|
|
7
5
|
import { animationPayloadsPlugin, animationRuntimePlugin } from '@forgeax/engine-animation';
|
|
8
6
|
import { inputBackendPlugin, INPUT_BACKEND_KEY, InputSet, InputFrameStartScan } from '@forgeax/engine-input';
|
|
9
7
|
import { scenePlugin } from '@forgeax/engine-scene';
|
|
10
8
|
import { statePlugin } from '@forgeax/engine-state';
|
|
9
|
+
import { err, ok } from '@forgeax/engine-types';
|
|
11
10
|
import { splitSharedSpan, bindSharedSpan, isSharedSpan } from '@forgeax/engine-ecs/shared';
|
|
12
11
|
|
|
13
12
|
// src/execution/engine-worker-runtime.ts
|
|
@@ -16,49 +15,6 @@ import { splitSharedSpan, bindSharedSpan, isSharedSpan } from '@forgeax/engine-e
|
|
|
16
15
|
function createAnimationPayloadLookup(source) {
|
|
17
16
|
return (guid) => source?.lookup(guid);
|
|
18
17
|
}
|
|
19
|
-
function assembleAssetRuntime(registry, contributions) {
|
|
20
|
-
const leases = [];
|
|
21
|
-
const overrides = new Set(contributions.map((contribution) => contribution.kind.kind));
|
|
22
|
-
const defaults = defaultAssetDecoderContributions ?? [];
|
|
23
|
-
const assembledContributions = [
|
|
24
|
-
...defaults.filter((contribution) => !overrides.has(contribution.kind.kind)),
|
|
25
|
-
...contributions
|
|
26
|
-
];
|
|
27
|
-
try {
|
|
28
|
-
const installedKinds = /* @__PURE__ */ new Set();
|
|
29
|
-
for (const contribution of assembledContributions) {
|
|
30
|
-
if (installedKinds.has(contribution.kind.kind)) {
|
|
31
|
-
throw new TypeError(`duplicate decoder kind "${contribution.kind.kind}"`);
|
|
32
|
-
}
|
|
33
|
-
installedKinds.add(contribution.kind.kind);
|
|
34
|
-
leases.push(
|
|
35
|
-
registry.installDecoder(
|
|
36
|
-
contribution.kind,
|
|
37
|
-
contribution.decoder
|
|
38
|
-
)
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
} catch (cause) {
|
|
42
|
-
for (const lease of leases) lease.dispose();
|
|
43
|
-
const failed = assembledContributions[leases.length];
|
|
44
|
-
return err({
|
|
45
|
-
code: "asset-assembly-failed",
|
|
46
|
-
expected: "each owner decoder contribution to install exactly once in the realm registry",
|
|
47
|
-
hint: "remove the conflicting owner contribution and assemble the current realm again",
|
|
48
|
-
detail: { kind: failed?.kind.kind ?? "unknown", cause }
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
let disposed = false;
|
|
52
|
-
return ok({
|
|
53
|
-
registry,
|
|
54
|
-
leases: Object.freeze([...leases]),
|
|
55
|
-
dispose() {
|
|
56
|
-
if (disposed) return;
|
|
57
|
-
disposed = true;
|
|
58
|
-
for (const lease of leases) lease.dispose();
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
18
|
function syncCameraAspect(world, canvasW, canvasH) {
|
|
63
19
|
if (canvasW <= 0 || canvasH <= 0) return;
|
|
64
20
|
const aspect = canvasW / canvasH;
|
|
@@ -93,61 +49,70 @@ function inputPlugin() {
|
|
|
93
49
|
};
|
|
94
50
|
}
|
|
95
51
|
|
|
96
|
-
// src/
|
|
97
|
-
|
|
98
|
-
var ASSET_REGISTRY_RESOURCE_KEY = "AssetRegistry";
|
|
99
|
-
function rendererAssetsPlugin() {
|
|
52
|
+
// src/renderer-plugin.ts
|
|
53
|
+
function createRenderFeatureHost(host) {
|
|
100
54
|
return {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
55
|
+
async installFeature(feature) {
|
|
56
|
+
const installed = await host.installRenderFeature(feature);
|
|
57
|
+
if (!installed.ok) return installed;
|
|
58
|
+
let released = false;
|
|
59
|
+
return {
|
|
60
|
+
ok: true,
|
|
61
|
+
value: {
|
|
62
|
+
release: async () => {
|
|
63
|
+
if (released) return { ok: true, value: void 0 };
|
|
64
|
+
released = true;
|
|
65
|
+
return host.uninstallRenderFeature(feature);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function ownedRendererPlugin(renderer2) {
|
|
73
|
+
return {
|
|
74
|
+
name: "renderer",
|
|
75
|
+
provide: "renderer",
|
|
104
76
|
apply(ctx) {
|
|
105
|
-
|
|
106
|
-
ctx.
|
|
77
|
+
ctx.provide("renderer", renderer2);
|
|
78
|
+
ctx.effect(() => () => renderer2.dispose(), "render/renderer");
|
|
107
79
|
}
|
|
108
80
|
};
|
|
109
81
|
}
|
|
110
|
-
function
|
|
82
|
+
function renderFeatureHostPlugin(host) {
|
|
111
83
|
return {
|
|
112
|
-
name: "
|
|
113
|
-
provide: "
|
|
84
|
+
name: "render-feature-host",
|
|
85
|
+
provide: "renderFeatureHost",
|
|
114
86
|
apply(ctx) {
|
|
115
|
-
ctx.provide("
|
|
116
|
-
ctx.effect(
|
|
117
|
-
() => () => {
|
|
118
|
-
assembly.dispose();
|
|
119
|
-
assembly.registry.dispose();
|
|
120
|
-
},
|
|
121
|
-
"assets/registry"
|
|
122
|
-
);
|
|
87
|
+
ctx.provide("renderFeatureHost", host);
|
|
123
88
|
}
|
|
124
89
|
};
|
|
125
90
|
}
|
|
126
|
-
|
|
91
|
+
|
|
92
|
+
// src/internal/assets-world-plugin.ts
|
|
93
|
+
var ASSET_REGISTRY_RESOURCE_KEY = "AssetRegistry";
|
|
94
|
+
function rendererAssetsPlugin(assets2) {
|
|
127
95
|
return {
|
|
128
|
-
name: "assets
|
|
129
|
-
inject: ["
|
|
96
|
+
name: "renderer-assets",
|
|
97
|
+
inject: ["renderer"],
|
|
98
|
+
provide: "assets",
|
|
130
99
|
apply(ctx) {
|
|
131
|
-
ctx.
|
|
132
|
-
ctx.world.insertResource(RENDER_ASSET_PORT_RESOURCE_KEY, ctx.assets);
|
|
133
|
-
return () => {
|
|
134
|
-
ctx.world.removeResource(RENDER_ASSET_PORT_RESOURCE_KEY);
|
|
135
|
-
};
|
|
136
|
-
}, "assets/world-render-projection");
|
|
100
|
+
if (assets2 !== void 0) ctx.provide("assets", assets2);
|
|
137
101
|
}
|
|
138
102
|
};
|
|
139
103
|
}
|
|
140
|
-
function
|
|
104
|
+
function assetsWorldPlugin() {
|
|
141
105
|
return {
|
|
142
|
-
name: "
|
|
143
|
-
inject: ["world", "
|
|
106
|
+
name: "assets-world",
|
|
107
|
+
inject: ["world", "assets"],
|
|
144
108
|
apply(ctx) {
|
|
109
|
+
if (ctx.assets === void 0) return;
|
|
145
110
|
ctx.effect(() => {
|
|
146
|
-
ctx.world.insertResource(ASSET_REGISTRY_RESOURCE_KEY, ctx.
|
|
111
|
+
ctx.world.insertResource(ASSET_REGISTRY_RESOURCE_KEY, ctx.assets);
|
|
147
112
|
return () => {
|
|
148
113
|
ctx.world.removeResource(ASSET_REGISTRY_RESOURCE_KEY);
|
|
149
114
|
};
|
|
150
|
-
}, "assets/world-
|
|
115
|
+
}, "assets/world-resource");
|
|
151
116
|
}
|
|
152
117
|
};
|
|
153
118
|
}
|
|
@@ -157,8 +122,8 @@ function workerEngineProfile(options) {
|
|
|
157
122
|
return [
|
|
158
123
|
ownedRendererPlugin(options.renderer),
|
|
159
124
|
renderComponentsPlugin(),
|
|
160
|
-
|
|
161
|
-
|
|
125
|
+
...options.rendererFeatureHost === void 0 ? [] : [renderFeatureHostPlugin(options.rendererFeatureHost)],
|
|
126
|
+
rendererAssetsPlugin(options.assets),
|
|
162
127
|
assetsWorldPlugin(),
|
|
163
128
|
inputBackendPlugin(options.input),
|
|
164
129
|
audioBackendPlugin(options.audio),
|
|
@@ -180,19 +145,18 @@ var SerializedRebuildQueue = class {
|
|
|
180
145
|
return current;
|
|
181
146
|
}
|
|
182
147
|
};
|
|
183
|
-
async function commitAttachedWorld(renderer2,
|
|
184
|
-
const attached = renderer2.
|
|
148
|
+
async function commitAttachedWorld(renderer2, nextWorld, initializeCandidate) {
|
|
149
|
+
const attached = renderer2.attach(nextWorld);
|
|
185
150
|
if (!attached.ok) throw attached.error;
|
|
186
151
|
try {
|
|
187
152
|
if (!await initializeCandidate()) {
|
|
188
|
-
|
|
153
|
+
attached.value.dispose();
|
|
189
154
|
return false;
|
|
190
155
|
}
|
|
191
156
|
} catch (cause) {
|
|
192
|
-
|
|
157
|
+
attached.value.dispose();
|
|
193
158
|
throw cause;
|
|
194
159
|
}
|
|
195
|
-
if (previousWorld !== void 0) renderer2.detachWorld(previousWorld);
|
|
196
160
|
return true;
|
|
197
161
|
}
|
|
198
162
|
|
|
@@ -257,10 +221,6 @@ var appErrorPolicy = {
|
|
|
257
221
|
expected: "canvas.isConnected === true at createApp(canvas) entry",
|
|
258
222
|
hint: "append the canvas to the document tree before calling createApp(canvas), or use the assemble entry createApp({ renderer, world }) when the host already manages canvas lifetime"
|
|
259
223
|
},
|
|
260
|
-
"app-invalid-canvas-pixel-ratio": {
|
|
261
|
-
expected: "maxCanvasPixelRatio is finite and greater than 0",
|
|
262
|
-
hint: "omit maxCanvasPixelRatio to keep the device pixel ratio, or pass a finite value > 0 from the Host policy"
|
|
263
|
-
},
|
|
264
224
|
"app-frame-step-invalid": {
|
|
265
225
|
expected: "stepFrame(deltaSeconds) runs only while the App is paused and deltaSeconds is finite and non-negative",
|
|
266
226
|
hint: "pause the App before deterministic stepping and pass an explicit finite delta; resume after the bounded step sequence completes"
|
|
@@ -561,6 +521,7 @@ function createKernelPool(options = {}) {
|
|
|
561
521
|
// src/execution/engine-worker-runtime.ts
|
|
562
522
|
var scope = globalThis;
|
|
563
523
|
var renderer;
|
|
524
|
+
var assets;
|
|
564
525
|
var currentSample = {
|
|
565
526
|
downKeys: /* @__PURE__ */ new Set(),
|
|
566
527
|
upKeys: /* @__PURE__ */ new Set(),
|
|
@@ -613,13 +574,6 @@ function serializableDetail(cause) {
|
|
|
613
574
|
if (cause instanceof Error) return serializableCause(cause);
|
|
614
575
|
if (Array.isArray(cause)) return cause.map(serializableDetail);
|
|
615
576
|
if (typeof cause === "object" && cause !== null) {
|
|
616
|
-
const named = cause;
|
|
617
|
-
if (typeof named.name === "string" || typeof named.message === "string") {
|
|
618
|
-
return {
|
|
619
|
-
name: typeof named.name === "string" ? named.name : "Error",
|
|
620
|
-
message: typeof named.message === "string" ? named.message : String(cause)
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
577
|
return Object.fromEntries(
|
|
624
578
|
Object.entries(cause).map(([key, value]) => [key, serializableDetail(value)])
|
|
625
579
|
);
|
|
@@ -669,7 +623,6 @@ async function createRealm(init) {
|
|
|
669
623
|
emit: (intent) => candidate.pendingAudioIntents.push(intent)
|
|
670
624
|
});
|
|
671
625
|
let candidateRenderer;
|
|
672
|
-
let assetAssembly;
|
|
673
626
|
let rendererLifecycleTransferred = false;
|
|
674
627
|
const previousRenderer = renderer;
|
|
675
628
|
let previousSurfaceReleased = false;
|
|
@@ -679,33 +632,24 @@ async function createRealm(init) {
|
|
|
679
632
|
if (!released.ok) throw released.error;
|
|
680
633
|
previousSurfaceReleased = true;
|
|
681
634
|
}
|
|
682
|
-
|
|
635
|
+
const constructed = await constructRuntimeRendererHost(
|
|
683
636
|
init.canvas,
|
|
684
637
|
prepared.features === void 0 ? {} : { features: prepared.features },
|
|
685
638
|
init.shaderManifestUrl === void 0 ? void 0 : { shaderManifestUrl: init.shaderManifestUrl }
|
|
686
639
|
);
|
|
687
|
-
|
|
688
|
-
|
|
640
|
+
if (!constructed.ok) throw constructed.error;
|
|
641
|
+
candidateRenderer = constructed.value.renderer;
|
|
642
|
+
assets = constructed.value.assets;
|
|
689
643
|
rendererLifecycleTransferred = true;
|
|
690
|
-
const assetRegistry = createAssetRegistry({
|
|
691
|
-
catalog: createCatalogSource({
|
|
692
|
-
url: new URL("pack-index.json", globalThis.location?.href ?? "http://localhost/").href
|
|
693
|
-
})
|
|
694
|
-
});
|
|
695
|
-
const assembledAssets = assembleAssetRuntime(assetRegistry, []);
|
|
696
|
-
if (!assembledAssets.ok) {
|
|
697
|
-
assetRegistry.dispose();
|
|
698
|
-
throw assembledAssets.error;
|
|
699
|
-
}
|
|
700
|
-
assetAssembly = assembledAssets.value;
|
|
701
644
|
const pluginContext = await createWorldContext(
|
|
702
645
|
nextWorld,
|
|
703
646
|
workerEngineProfile({
|
|
704
647
|
renderer: candidateRenderer,
|
|
705
|
-
|
|
648
|
+
rendererFeatureHost: createRenderFeatureHost(constructed.value.featureHost),
|
|
649
|
+
assets,
|
|
706
650
|
input: inputBackend,
|
|
707
651
|
audio: audioBackend,
|
|
708
|
-
animationPayloads: createAnimationPayloadLookup(
|
|
652
|
+
animationPayloads: createAnimationPayloadLookup(assets),
|
|
709
653
|
extensions: [
|
|
710
654
|
...init.tier === "shared" ? [sharedKernelPlugin(candidate)] : [],
|
|
711
655
|
executionBootstrapHostPlugin({
|
|
@@ -725,15 +669,10 @@ async function createRealm(init) {
|
|
|
725
669
|
candidate.pluginContext = pluginContext;
|
|
726
670
|
const activeRenderer = candidateRenderer;
|
|
727
671
|
const previousRealm = realm;
|
|
728
|
-
const committed = await commitAttachedWorld(
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
async () => {
|
|
733
|
-
await candidate.kernelPool?.ready();
|
|
734
|
-
return true;
|
|
735
|
-
}
|
|
736
|
-
);
|
|
672
|
+
const committed = await commitAttachedWorld(candidateRenderer, nextWorld, async () => {
|
|
673
|
+
await candidate.kernelPool?.ready();
|
|
674
|
+
return true;
|
|
675
|
+
});
|
|
737
676
|
if (!committed) {
|
|
738
677
|
await disposeRealm(candidate);
|
|
739
678
|
if (previousSurfaceReleased) previousRenderer?.restoreSurface();
|
|
@@ -746,8 +685,6 @@ async function createRealm(init) {
|
|
|
746
685
|
return true;
|
|
747
686
|
} catch (cause) {
|
|
748
687
|
await disposeRealm(candidate);
|
|
749
|
-
assetAssembly?.dispose();
|
|
750
|
-
assetAssembly?.registry.dispose();
|
|
751
688
|
if (!rendererLifecycleTransferred) candidateRenderer?.dispose();
|
|
752
689
|
if (previousSurfaceReleased) previousRenderer?.restoreSurface();
|
|
753
690
|
throw cause;
|
|
@@ -805,8 +742,14 @@ function runFrame(message) {
|
|
|
805
742
|
return;
|
|
806
743
|
}
|
|
807
744
|
const updateFinished = performance.now();
|
|
808
|
-
const
|
|
809
|
-
if (
|
|
745
|
+
const attached = renderer.attach(world);
|
|
746
|
+
if (!attached.ok) throw attached.error;
|
|
747
|
+
const draw = renderer.draw({
|
|
748
|
+
leases: [attached.value],
|
|
749
|
+
camera: { lease: attached.value },
|
|
750
|
+
environment: { lease: attached.value }
|
|
751
|
+
});
|
|
752
|
+
if (!draw.ok) throw draw.error;
|
|
810
753
|
lastFrameId = message.frameId;
|
|
811
754
|
const kernelDispatch = activeRealm.kernelPool?.takeLastDispatch() ?? null;
|
|
812
755
|
const audioIntents = activeRealm.pendingAudioIntents;
|