@forgeax/engine-app 0.1.4 → 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 +331 -362
- 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 +2 -3
- 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
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { Update, World, createWorldContext, componentDefinition } from '@forgeax/engine-ecs';
|
|
2
2
|
export { Context } from '@forgeax/engine-plugin';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import { err, ok } from '@forgeax/engine-types';
|
|
6
|
-
import { createAssetRegistry, createCatalogSource } from '@forgeax/engine-assets-runtime';
|
|
7
|
-
import { getAssetRegistryResolver } from '@forgeax/engine-assets-runtime/internal';
|
|
8
|
-
import { loadRhiPack, createDebugDrawOnReady, releaseDebugDraw } from '@forgeax/engine-render/internal';
|
|
3
|
+
export { createFullscreenRenderFeature } from '@forgeax/engine-render/authoring';
|
|
4
|
+
import { Camera, perspective, renderComponentsPlugin, CAMERA_PROJECTION_PERSPECTIVE } from '@forgeax/engine-render';
|
|
9
5
|
import { RhiError } from '@forgeax/engine-rhi';
|
|
10
|
-
import {
|
|
6
|
+
import { attachRecorder, decodeTape, openReplay, decodeToRgba8, buildTapeIndex, createRhiDebugError } from '@forgeax/engine-rhi-debug';
|
|
7
|
+
import * as engineRuntimeModule from '@forgeax/engine-runtime';
|
|
8
|
+
import { EngineEnvironmentError } from '@forgeax/engine-runtime';
|
|
9
|
+
import { loadRhiPack, constructRuntimeRendererHost } from '@forgeax/engine-runtime/internal/renderer-host';
|
|
10
|
+
import { ok, err } from '@forgeax/engine-types';
|
|
11
11
|
import { createHostAudioConsumer } from '@forgeax/engine-audio-webaudio';
|
|
12
12
|
import { INPUT_BACKEND_KEY, InputSet, InputFrameStartScan, attachBrowserInputBackend, inputBackendPlugin, ownedInputBackendPlugin, INPUT_MAP_KEY } from '@forgeax/engine-input';
|
|
13
13
|
import { componentSchema } from '@forgeax/engine-ecs/internal';
|
|
14
14
|
import { animationPayloadsPlugin, animationRuntimePlugin } from '@forgeax/engine-animation';
|
|
15
15
|
import { Transform, scenePlugin } from '@forgeax/engine-scene';
|
|
16
16
|
import { statePlugin } from '@forgeax/engine-state';
|
|
17
|
-
import {
|
|
17
|
+
import { createDebugDraw } from '@forgeax/engine-debug-draw';
|
|
18
18
|
import { createProfiler } from '@forgeax/engine-profiler';
|
|
19
19
|
import { isSerializableValue, createPreviewArtifactManifest, validatePreviewArtifactManifest, createArtifactRef, snapshotStaleError } from '@forgeax/engine-tool-runtime';
|
|
20
20
|
|
|
@@ -216,66 +216,11 @@ var init_browser_remote_bridge = __esm({
|
|
|
216
216
|
init_ecs_import();
|
|
217
217
|
}
|
|
218
218
|
});
|
|
219
|
-
function assembleAssetRuntime(registry, contributions) {
|
|
220
|
-
const leases = [];
|
|
221
|
-
const overrides = new Set(contributions.map((contribution) => contribution.kind.kind));
|
|
222
|
-
const defaults = defaultAssetDecoderContributions ?? [];
|
|
223
|
-
const assembledContributions = [
|
|
224
|
-
...defaults.filter((contribution) => !overrides.has(contribution.kind.kind)),
|
|
225
|
-
...contributions
|
|
226
|
-
];
|
|
227
|
-
try {
|
|
228
|
-
const installedKinds = /* @__PURE__ */ new Set();
|
|
229
|
-
for (const contribution of assembledContributions) {
|
|
230
|
-
if (installedKinds.has(contribution.kind.kind)) {
|
|
231
|
-
throw new TypeError(`duplicate decoder kind "${contribution.kind.kind}"`);
|
|
232
|
-
}
|
|
233
|
-
installedKinds.add(contribution.kind.kind);
|
|
234
|
-
leases.push(
|
|
235
|
-
registry.installDecoder(
|
|
236
|
-
contribution.kind,
|
|
237
|
-
contribution.decoder
|
|
238
|
-
)
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
} catch (cause) {
|
|
242
|
-
for (const lease of leases) lease.dispose();
|
|
243
|
-
const failed = assembledContributions[leases.length];
|
|
244
|
-
return err({
|
|
245
|
-
code: "asset-assembly-failed",
|
|
246
|
-
expected: "each owner decoder contribution to install exactly once in the realm registry",
|
|
247
|
-
hint: "remove the conflicting owner contribution and assemble the current realm again",
|
|
248
|
-
detail: { kind: failed?.kind.kind ?? "unknown", cause }
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
let disposed = false;
|
|
252
|
-
return ok({
|
|
253
|
-
registry,
|
|
254
|
-
leases: Object.freeze([...leases]),
|
|
255
|
-
dispose() {
|
|
256
|
-
if (disposed) return;
|
|
257
|
-
disposed = true;
|
|
258
|
-
for (const lease of leases) lease.dispose();
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
219
|
|
|
263
220
|
// src/animation-asset-lookup.ts
|
|
264
221
|
function createAnimationPayloadLookup(source) {
|
|
265
222
|
return (guid) => source?.lookup(guid);
|
|
266
223
|
}
|
|
267
|
-
function syncCameraAspect(world, canvasW, canvasH) {
|
|
268
|
-
if (canvasW <= 0 || canvasH <= 0) return;
|
|
269
|
-
const aspect = canvasW / canvasH;
|
|
270
|
-
const query = world.query({ with: [Camera] }).unwrap();
|
|
271
|
-
for (const row of query) {
|
|
272
|
-
const camera = world.get(row.entity, Camera);
|
|
273
|
-
if (!camera.ok) continue;
|
|
274
|
-
if (camera.value.autoAspect !== true) continue;
|
|
275
|
-
if (camera.value.projection !== CAMERA_PROJECTION_PERSPECTIVE) continue;
|
|
276
|
-
world.set(row.entity, Camera, { aspect });
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
224
|
|
|
280
225
|
// src/errors.ts
|
|
281
226
|
function summarizeCause(cause) {
|
|
@@ -338,10 +283,6 @@ var appErrorPolicy = {
|
|
|
338
283
|
expected: "canvas.isConnected === true at createApp(canvas) entry",
|
|
339
284
|
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"
|
|
340
285
|
},
|
|
341
|
-
"app-invalid-canvas-pixel-ratio": {
|
|
342
|
-
expected: "maxCanvasPixelRatio is finite and greater than 0",
|
|
343
|
-
hint: "omit maxCanvasPixelRatio to keep the device pixel ratio, or pass a finite value > 0 from the Host policy"
|
|
344
|
-
},
|
|
345
286
|
"app-frame-step-invalid": {
|
|
346
287
|
expected: "stepFrame(deltaSeconds) runs only while the App is paused and deltaSeconds is finite and non-negative",
|
|
347
288
|
hint: "pause the App before deterministic stepping and pass an explicit finite delta; resume after the bounded step sequence completes"
|
|
@@ -737,20 +678,17 @@ function createLocalExecutionControl(initial, providers = {}) {
|
|
|
737
678
|
world: providers.world?.() ?? current.world,
|
|
738
679
|
audio: executionAudioReport(providers.audio?.())
|
|
739
680
|
}),
|
|
740
|
-
rebuild: async () =>
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
})
|
|
752
|
-
);
|
|
753
|
-
}
|
|
681
|
+
rebuild: async () => err(
|
|
682
|
+
new AppError({
|
|
683
|
+
code: "app-execution-rebuild-failed",
|
|
684
|
+
expected: APP_EXPECTED["app-execution-rebuild-failed"],
|
|
685
|
+
hint: APP_ERROR_HINTS["app-execution-rebuild-failed"],
|
|
686
|
+
detail: {
|
|
687
|
+
worldIdentity: current.world.identity,
|
|
688
|
+
cause: new Error("This local assembly has no bootstrap module.")
|
|
689
|
+
}
|
|
690
|
+
})
|
|
691
|
+
)
|
|
754
692
|
};
|
|
755
693
|
}
|
|
756
694
|
var ENGINE_WORKER_CAPABILITIES = [
|
|
@@ -825,6 +763,25 @@ function selectExecutionTier(input) {
|
|
|
825
763
|
sharedEvidencePassed: input.sharedEvidencePassed
|
|
826
764
|
});
|
|
827
765
|
}
|
|
766
|
+
function normalizeExecutionBootstrapUrl(bootstrap) {
|
|
767
|
+
const moduleUrl = typeof bootstrap === "string" ? bootstrap : bootstrap.href;
|
|
768
|
+
try {
|
|
769
|
+
return ok(new URL(bootstrap, globalThis.location?.href).href);
|
|
770
|
+
} catch (cause) {
|
|
771
|
+
return err(
|
|
772
|
+
new AppError({
|
|
773
|
+
code: "app-execution-bootstrap-failed",
|
|
774
|
+
expected: APP_EXPECTED["app-execution-bootstrap-failed"],
|
|
775
|
+
hint: APP_ERROR_HINTS["app-execution-bootstrap-failed"],
|
|
776
|
+
detail: {
|
|
777
|
+
phase: "prepare",
|
|
778
|
+
moduleUrl,
|
|
779
|
+
cause: cause instanceof TypeError ? cause : new TypeError(String(cause))
|
|
780
|
+
}
|
|
781
|
+
})
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
828
785
|
|
|
829
786
|
// src/internal/error-fanout.ts
|
|
830
787
|
var ErrorFanoutRegistry = class {
|
|
@@ -974,6 +931,7 @@ async function startEngineWorker(options) {
|
|
|
974
931
|
bootstrapUrl: options.bootstrapUrl,
|
|
975
932
|
...options.bootstrapData === void 0 ? {} : { bootstrapData: options.bootstrapData },
|
|
976
933
|
...options.bootstrapPort === void 0 ? {} : { bootstrapPort: options.bootstrapPort },
|
|
934
|
+
...options.assetCatalog === void 0 ? {} : { assetCatalog: options.assetCatalog },
|
|
977
935
|
...options.shaderManifestUrl !== void 0 ? { shaderManifestUrl: options.shaderManifestUrl } : {},
|
|
978
936
|
...options.time !== void 0 ? { time: options.time } : {},
|
|
979
937
|
tier: options.tier
|
|
@@ -1044,7 +1002,7 @@ var FrameCreditLedger = class {
|
|
|
1044
1002
|
nextFrameId = 1;
|
|
1045
1003
|
inFlight = null;
|
|
1046
1004
|
completed = 0;
|
|
1047
|
-
issue(deltaSeconds, sampleInput, canvasSize) {
|
|
1005
|
+
issue(deltaSeconds, sampleInput, canvasSize = { width: 0, height: 0 }) {
|
|
1048
1006
|
if (this.inFlight !== null) return void 0;
|
|
1049
1007
|
const frameId = this.nextFrameId;
|
|
1050
1008
|
this.nextFrameId += 1;
|
|
@@ -1106,15 +1064,18 @@ function runtimeError(message) {
|
|
|
1106
1064
|
async function createWorkerExecutionApp(options) {
|
|
1107
1065
|
const executionOptions = options.appOptions.execution;
|
|
1108
1066
|
if (executionOptions === void 0) throw new Error("execution options are required");
|
|
1109
|
-
const
|
|
1110
|
-
|
|
1067
|
+
const normalizedBootstrap = normalizeExecutionBootstrapUrl(executionOptions.bootstrap);
|
|
1068
|
+
if (!normalizedBootstrap.ok) return normalizedBootstrap;
|
|
1069
|
+
const bootstrapUrl = normalizedBootstrap.value;
|
|
1111
1070
|
const startupTimeoutMs = executionOptions.startupTimeoutMs ?? 1e4;
|
|
1112
1071
|
const frameTimeoutMs = executionOptions.frameTimeoutMs ?? 2e3;
|
|
1072
|
+
const syncCanvas = options.syncCanvas;
|
|
1113
1073
|
const started = await startEngineWorker({
|
|
1114
1074
|
canvas: options.canvas,
|
|
1115
1075
|
bootstrapUrl,
|
|
1116
1076
|
...executionOptions.bootstrapData === void 0 ? {} : { bootstrapData: executionOptions.bootstrapData },
|
|
1117
1077
|
...executionOptions.bootstrapPort === void 0 ? {} : { bootstrapPort: executionOptions.bootstrapPort },
|
|
1078
|
+
...executionOptions.assetCatalog === void 0 ? {} : { assetCatalog: executionOptions.assetCatalog },
|
|
1118
1079
|
...options.bundler?.shaderManifestUrl !== void 0 ? { shaderManifestUrl: options.bundler.shaderManifestUrl } : {},
|
|
1119
1080
|
...options.appOptions.time !== void 0 ? { time: options.appOptions.time } : {},
|
|
1120
1081
|
timeoutMs: startupTimeoutMs,
|
|
@@ -1450,61 +1411,99 @@ async function createWorkerExecutionApp(options) {
|
|
|
1450
1411
|
return ok(app);
|
|
1451
1412
|
}
|
|
1452
1413
|
|
|
1453
|
-
// src/
|
|
1454
|
-
|
|
1455
|
-
var ASSET_REGISTRY_RESOURCE_KEY = "AssetRegistry";
|
|
1456
|
-
function rendererAssetsPlugin() {
|
|
1414
|
+
// src/renderer-plugin.ts
|
|
1415
|
+
function createRenderFeatureHost(host) {
|
|
1457
1416
|
return {
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1417
|
+
async installFeature(feature) {
|
|
1418
|
+
const installed = await host.installRenderFeature(feature);
|
|
1419
|
+
if (!installed.ok) return installed;
|
|
1420
|
+
let released = false;
|
|
1421
|
+
return {
|
|
1422
|
+
ok: true,
|
|
1423
|
+
value: {
|
|
1424
|
+
release: async () => {
|
|
1425
|
+
if (released) return { ok: true, value: void 0 };
|
|
1426
|
+
released = true;
|
|
1427
|
+
return host.uninstallRenderFeature(feature);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
function rendererPlugin(renderer) {
|
|
1435
|
+
return {
|
|
1436
|
+
name: "renderer",
|
|
1437
|
+
provide: "renderer",
|
|
1461
1438
|
apply(ctx) {
|
|
1462
|
-
|
|
1463
|
-
ctx.provide("assets", ctx.renderer.assets);
|
|
1439
|
+
ctx.provide("renderer", renderer);
|
|
1464
1440
|
}
|
|
1465
1441
|
};
|
|
1466
1442
|
}
|
|
1467
|
-
function
|
|
1443
|
+
function ownedRendererPlugin(renderer) {
|
|
1468
1444
|
return {
|
|
1469
|
-
name: "
|
|
1470
|
-
provide: "
|
|
1445
|
+
name: "renderer",
|
|
1446
|
+
provide: "renderer",
|
|
1471
1447
|
apply(ctx) {
|
|
1472
|
-
ctx.provide("
|
|
1448
|
+
ctx.provide("renderer", renderer);
|
|
1449
|
+
ctx.effect(() => () => renderer.dispose(), "render/renderer");
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
function renderFeatureHostPlugin(host) {
|
|
1454
|
+
return {
|
|
1455
|
+
name: "render-feature-host",
|
|
1456
|
+
provide: "renderFeatureHost",
|
|
1457
|
+
apply(ctx) {
|
|
1458
|
+
ctx.provide("renderFeatureHost", host);
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
function renderFeaturePlugin(feature) {
|
|
1463
|
+
return {
|
|
1464
|
+
name: `render-feature:${feature.identity}`,
|
|
1465
|
+
inject: ["renderFeatureHost"],
|
|
1466
|
+
async apply(ctx) {
|
|
1467
|
+
if (ctx.renderFeatureHost === void 0) {
|
|
1468
|
+
throw new Error("render-feature host capability is unavailable in this App realm");
|
|
1469
|
+
}
|
|
1470
|
+
const installed = await ctx.renderFeatureHost.installFeature(feature);
|
|
1471
|
+
if (!installed.ok) throw installed.error;
|
|
1473
1472
|
ctx.effect(
|
|
1474
|
-
() => () => {
|
|
1475
|
-
|
|
1476
|
-
|
|
1473
|
+
() => async () => {
|
|
1474
|
+
const removed = await installed.value.release();
|
|
1475
|
+
if (!removed.ok) throw removed.error;
|
|
1477
1476
|
},
|
|
1478
|
-
|
|
1477
|
+
`render-feature/${feature.identity}`
|
|
1479
1478
|
);
|
|
1480
1479
|
}
|
|
1481
1480
|
};
|
|
1482
1481
|
}
|
|
1483
|
-
|
|
1482
|
+
|
|
1483
|
+
// src/internal/assets-world-plugin.ts
|
|
1484
|
+
var ASSET_REGISTRY_RESOURCE_KEY = "AssetRegistry";
|
|
1485
|
+
function rendererAssetsPlugin(assets) {
|
|
1484
1486
|
return {
|
|
1485
|
-
name: "assets
|
|
1486
|
-
inject: ["
|
|
1487
|
+
name: "renderer-assets",
|
|
1488
|
+
inject: ["renderer"],
|
|
1489
|
+
provide: "assets",
|
|
1487
1490
|
apply(ctx) {
|
|
1488
|
-
ctx.
|
|
1489
|
-
ctx.world.insertResource(RENDER_ASSET_PORT_RESOURCE_KEY, ctx.assets);
|
|
1490
|
-
return () => {
|
|
1491
|
-
ctx.world.removeResource(RENDER_ASSET_PORT_RESOURCE_KEY);
|
|
1492
|
-
};
|
|
1493
|
-
}, "assets/world-render-projection");
|
|
1491
|
+
if (assets !== void 0) ctx.provide("assets", assets);
|
|
1494
1492
|
}
|
|
1495
1493
|
};
|
|
1496
1494
|
}
|
|
1497
|
-
function
|
|
1495
|
+
function assetsWorldPlugin() {
|
|
1498
1496
|
return {
|
|
1499
|
-
name: "
|
|
1500
|
-
inject: ["world", "
|
|
1497
|
+
name: "assets-world",
|
|
1498
|
+
inject: ["world", "assets"],
|
|
1501
1499
|
apply(ctx) {
|
|
1500
|
+
if (ctx.assets === void 0) return;
|
|
1502
1501
|
ctx.effect(() => {
|
|
1503
|
-
ctx.world.insertResource(ASSET_REGISTRY_RESOURCE_KEY, ctx.
|
|
1502
|
+
ctx.world.insertResource(ASSET_REGISTRY_RESOURCE_KEY, ctx.assets);
|
|
1504
1503
|
return () => {
|
|
1505
1504
|
ctx.world.removeResource(ASSET_REGISTRY_RESOURCE_KEY);
|
|
1506
1505
|
};
|
|
1507
|
-
}, "assets/world-
|
|
1506
|
+
}, "assets/world-resource");
|
|
1508
1507
|
}
|
|
1509
1508
|
};
|
|
1510
1509
|
}
|
|
@@ -1513,8 +1512,7 @@ function assetRegistryWorldPlugin() {
|
|
|
1513
1512
|
function assembledEngineProfile(options) {
|
|
1514
1513
|
return [
|
|
1515
1514
|
rendererPlugin(options.renderer),
|
|
1516
|
-
rendererAssetsPlugin(),
|
|
1517
|
-
...options.assetAssembly === void 0 ? [] : [assetRegistryPlugin(options.assetAssembly), assetRegistryWorldPlugin()],
|
|
1515
|
+
rendererAssetsPlugin(options.assets),
|
|
1518
1516
|
assetsWorldPlugin(),
|
|
1519
1517
|
...options.extensions ?? []
|
|
1520
1518
|
];
|
|
@@ -1677,7 +1675,6 @@ function resolveCaf(opts) {
|
|
|
1677
1675
|
}
|
|
1678
1676
|
function createFrameLoop(opts) {
|
|
1679
1677
|
const { world, renderer } = opts;
|
|
1680
|
-
const primaryDrawWorlds = [world];
|
|
1681
1678
|
const phaseCatalogRegistration = opts.profiler?.registerPhaseCatalog("app", APP_PHASE_CATALOG);
|
|
1682
1679
|
let releasePhaseCatalog = phaseCatalogRegistration?.ok === true ? phaseCatalogRegistration.value : void 0;
|
|
1683
1680
|
let drawSource = opts.drawSource;
|
|
@@ -1689,53 +1686,50 @@ function createFrameLoop(opts) {
|
|
|
1689
1686
|
let pendingFrameId = 0;
|
|
1690
1687
|
let profilerFrameId = 0;
|
|
1691
1688
|
let profilerCaptureId;
|
|
1692
|
-
|
|
1693
|
-
let activeInjectedWorlds;
|
|
1694
|
-
let nextInjectedWorlds;
|
|
1689
|
+
const leases = /* @__PURE__ */ new Map();
|
|
1695
1690
|
function attachPrimary(fireError) {
|
|
1696
|
-
if (
|
|
1691
|
+
if (leases.has(world)) return;
|
|
1697
1692
|
try {
|
|
1698
|
-
const result = renderer.
|
|
1699
|
-
|
|
1700
|
-
|
|
1693
|
+
const result = renderer.attach(world);
|
|
1694
|
+
if (result.ok) leases.set(world, result.value);
|
|
1695
|
+
else fireError(result.error);
|
|
1701
1696
|
} catch (cause) {
|
|
1702
1697
|
fireError(makeWorldUpdateError(cause));
|
|
1703
1698
|
}
|
|
1704
1699
|
}
|
|
1705
1700
|
function syncInjectedAttachments(worlds, fireError) {
|
|
1706
1701
|
if (worlds === void 0) {
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1702
|
+
for (const [attached, lease] of leases) {
|
|
1703
|
+
if (attached !== world) {
|
|
1704
|
+
lease.dispose();
|
|
1705
|
+
leases.delete(attached);
|
|
1706
|
+
}
|
|
1710
1707
|
}
|
|
1711
1708
|
return void 0;
|
|
1712
1709
|
}
|
|
1713
|
-
const next =
|
|
1714
|
-
nextInjectedWorlds = next;
|
|
1715
|
-
next.clear();
|
|
1716
|
-
const active = activeInjectedWorlds;
|
|
1710
|
+
const next = /* @__PURE__ */ new Set();
|
|
1717
1711
|
for (const candidate of worlds) {
|
|
1718
1712
|
if (candidate === world || next.has(candidate)) continue;
|
|
1719
|
-
if (
|
|
1713
|
+
if (leases.has(candidate)) {
|
|
1720
1714
|
next.add(candidate);
|
|
1721
1715
|
continue;
|
|
1722
1716
|
}
|
|
1723
1717
|
try {
|
|
1724
|
-
const result = renderer.
|
|
1725
|
-
if (result.ok)
|
|
1726
|
-
|
|
1718
|
+
const result = renderer.attach(candidate);
|
|
1719
|
+
if (result.ok) {
|
|
1720
|
+
leases.set(candidate, result.value);
|
|
1721
|
+
next.add(candidate);
|
|
1722
|
+
} else fireError?.(result.error);
|
|
1727
1723
|
} catch (cause) {
|
|
1728
1724
|
fireError?.(makeWorldUpdateError(cause));
|
|
1729
1725
|
}
|
|
1730
1726
|
}
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1727
|
+
for (const [attached, lease] of leases) {
|
|
1728
|
+
if (attached !== world && !next.has(attached)) {
|
|
1729
|
+
lease.dispose();
|
|
1730
|
+
leases.delete(attached);
|
|
1734
1731
|
}
|
|
1735
|
-
active.clear();
|
|
1736
1732
|
}
|
|
1737
|
-
activeInjectedWorlds = next;
|
|
1738
|
-
nextInjectedWorlds = active;
|
|
1739
1733
|
return next;
|
|
1740
1734
|
}
|
|
1741
1735
|
function releaseInjectedAttachments() {
|
|
@@ -1743,9 +1737,11 @@ function createFrameLoop(opts) {
|
|
|
1743
1737
|
}
|
|
1744
1738
|
function releaseAttachments() {
|
|
1745
1739
|
releaseInjectedAttachments();
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1740
|
+
const lease = leases.get(world);
|
|
1741
|
+
if (lease !== void 0) {
|
|
1742
|
+
lease.dispose();
|
|
1743
|
+
leases.delete(world);
|
|
1744
|
+
}
|
|
1749
1745
|
}
|
|
1750
1746
|
function runProfiledPhase(session, phase, action) {
|
|
1751
1747
|
const opened = beginPhase(session, phase);
|
|
@@ -1796,7 +1792,7 @@ function createFrameLoop(opts) {
|
|
|
1796
1792
|
});
|
|
1797
1793
|
const attachedInjectedWorlds = syncInjectedAttachments(injected?.worlds, reportError);
|
|
1798
1794
|
const updatedWorlds = injected === void 0 ? void 0 : /* @__PURE__ */ new Set();
|
|
1799
|
-
if (updatedWorlds !== void 0 && primaryUpdated &&
|
|
1795
|
+
if (updatedWorlds !== void 0 && primaryUpdated && leases.has(world)) {
|
|
1800
1796
|
updatedWorlds.add(world);
|
|
1801
1797
|
}
|
|
1802
1798
|
runProfiledPhase(session, "world-update-injected", () => {
|
|
@@ -1813,27 +1809,34 @@ function createFrameLoop(opts) {
|
|
|
1813
1809
|
});
|
|
1814
1810
|
runProfiledPhase(session, "renderer-draw", () => {
|
|
1815
1811
|
try {
|
|
1816
|
-
const profileOptions = profileFrame === void 0 ? {} : { profileFrame };
|
|
1817
1812
|
let drawResult;
|
|
1818
1813
|
if (injected === void 0) {
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1814
|
+
const primaryLease = leases.get(world);
|
|
1815
|
+
if (!primaryUpdated || primaryLease === void 0) return;
|
|
1816
|
+
drawResult = renderer.draw({
|
|
1817
|
+
leases: [primaryLease],
|
|
1818
|
+
camera: { lease: primaryLease },
|
|
1819
|
+
environment: { lease: primaryLease },
|
|
1820
|
+
...profileFrame === void 0 ? {} : { profileFrame }
|
|
1824
1821
|
});
|
|
1825
1822
|
} else {
|
|
1826
1823
|
if (updatedWorlds === void 0) return;
|
|
1827
|
-
const
|
|
1824
|
+
const readyEntries = injected.worlds.filter((candidate) => updatedWorlds.has(candidate)).map((candidate) => ({ candidate, lease: leases.get(candidate) })).filter(
|
|
1825
|
+
(entry) => entry.lease !== void 0
|
|
1826
|
+
);
|
|
1827
|
+
const readyLeases = readyEntries.map((entry) => entry.lease);
|
|
1828
1828
|
const cameraWorld = injected.worlds[injected.cameraOwner];
|
|
1829
|
-
const
|
|
1830
|
-
|
|
1831
|
-
const
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1829
|
+
const environmentWorld = injected.worlds[injected.resourceOwner];
|
|
1830
|
+
if (cameraWorld === void 0 || environmentWorld === void 0) return;
|
|
1831
|
+
const cameraLease = leases.get(cameraWorld);
|
|
1832
|
+
const environmentLease = leases.get(environmentWorld);
|
|
1833
|
+
if (readyLeases.length === 0 || cameraLease === void 0 || environmentLease === void 0)
|
|
1834
|
+
return;
|
|
1835
|
+
drawResult = renderer.draw({
|
|
1836
|
+
leases: readyLeases,
|
|
1837
|
+
camera: { lease: cameraLease },
|
|
1838
|
+
environment: { lease: environmentLease },
|
|
1839
|
+
...profileFrame === void 0 ? {} : { profileFrame }
|
|
1837
1840
|
});
|
|
1838
1841
|
}
|
|
1839
1842
|
if (drawResult !== void 0) {
|
|
@@ -1848,14 +1851,14 @@ function createFrameLoop(opts) {
|
|
|
1848
1851
|
});
|
|
1849
1852
|
});
|
|
1850
1853
|
endFrame(session);
|
|
1854
|
+
try {
|
|
1855
|
+
opts.debugRhi?.onFrameEnd();
|
|
1856
|
+
} catch {
|
|
1857
|
+
}
|
|
1851
1858
|
return frameError === void 0 ? ok(void 0) : err(frameError);
|
|
1852
1859
|
}
|
|
1853
1860
|
function tick() {
|
|
1854
1861
|
if (state !== "running") return;
|
|
1855
|
-
if (renderer.health?.().reason === "device-lost") {
|
|
1856
|
-
pendingFrameId = raf(tick);
|
|
1857
|
-
return;
|
|
1858
|
-
}
|
|
1859
1862
|
const timestamp = now();
|
|
1860
1863
|
const deltaSeconds = (timestamp - lastTimestamp) / 1e3;
|
|
1861
1864
|
lastTimestamp = timestamp;
|
|
@@ -2063,17 +2066,53 @@ function inputPlugin() {
|
|
|
2063
2066
|
};
|
|
2064
2067
|
}
|
|
2065
2068
|
|
|
2069
|
+
// ../render/src/record/render-context.ts
|
|
2070
|
+
function selectSwapChainFormat(storageBufferCapable) {
|
|
2071
|
+
if (!storageBufferCapable) return { storage: "rgba8unorm", view: "rgba8unorm-srgb" };
|
|
2072
|
+
const nav = globalThis.navigator;
|
|
2073
|
+
const gpu = nav?.gpu;
|
|
2074
|
+
const getPreferred = gpu?.getPreferredCanvasFormat;
|
|
2075
|
+
if (gpu !== void 0 && typeof getPreferred === "function") {
|
|
2076
|
+
const storage = getPreferred.call(gpu);
|
|
2077
|
+
const view = storage === "rgba8unorm" ? "rgba8unorm-srgb" : storage === "bgra8unorm" ? "bgra8unorm-srgb" : storage;
|
|
2078
|
+
return { storage, view };
|
|
2079
|
+
}
|
|
2080
|
+
return {
|
|
2081
|
+
storage: "rgba8unorm",
|
|
2082
|
+
view: "rgba8unorm-srgb",
|
|
2083
|
+
fallbackReason: "preferred-canvas-format-missing"
|
|
2084
|
+
};
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
// src/internal/debug-draw.ts
|
|
2088
|
+
async function createDebugDrawOnReady(context, format) {
|
|
2089
|
+
const ready = await context.initialization;
|
|
2090
|
+
if (!ready.ok) throw ready.error;
|
|
2091
|
+
const resolvedFormat = selectSwapChainFormat(context.device.caps.storageBuffer).view;
|
|
2092
|
+
const result = await createDebugDraw({
|
|
2093
|
+
device: context.device,
|
|
2094
|
+
queue: context.device.queue,
|
|
2095
|
+
createShaderModule: context._internal_createShaderModule,
|
|
2096
|
+
format: resolvedFormat
|
|
2097
|
+
});
|
|
2098
|
+
if (!result.ok) throw result.error;
|
|
2099
|
+
context._internal_setRenderOverlay(result.value);
|
|
2100
|
+
return result.value;
|
|
2101
|
+
}
|
|
2102
|
+
function releaseDebugDraw(context, debugDraw) {
|
|
2103
|
+
context._internal_setRenderOverlay(void 0);
|
|
2104
|
+
debugDraw.destroy();
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2066
2107
|
// src/internal/main-engine-profile.ts
|
|
2067
|
-
function debugDrawPlugin(onReady) {
|
|
2108
|
+
function debugDrawPlugin(context, onReady) {
|
|
2068
2109
|
return {
|
|
2069
2110
|
name: "debug-draw",
|
|
2070
|
-
inject: ["renderer"],
|
|
2071
2111
|
async apply(ctx) {
|
|
2072
|
-
if (ctx.renderer === void 0) throw new Error("debug draw requires the renderer service");
|
|
2073
2112
|
try {
|
|
2074
|
-
const debugDraw = await createDebugDrawOnReady(
|
|
2113
|
+
const debugDraw = await createDebugDrawOnReady(context);
|
|
2075
2114
|
onReady(debugDraw);
|
|
2076
|
-
ctx.effect(() => () => releaseDebugDraw(debugDraw), "render/debug-draw");
|
|
2115
|
+
ctx.effect(() => () => releaseDebugDraw(context, debugDraw), "render/debug-draw");
|
|
2077
2116
|
} catch {
|
|
2078
2117
|
}
|
|
2079
2118
|
}
|
|
@@ -2083,8 +2122,8 @@ function mainEngineProfile(options) {
|
|
|
2083
2122
|
return [
|
|
2084
2123
|
ownedRendererPlugin(options.renderer),
|
|
2085
2124
|
renderComponentsPlugin(),
|
|
2086
|
-
|
|
2087
|
-
|
|
2125
|
+
...options.rendererFeatureHost === void 0 ? [] : [renderFeatureHostPlugin(options.rendererFeatureHost)],
|
|
2126
|
+
rendererAssetsPlugin(options.assets),
|
|
2088
2127
|
assetsWorldPlugin(),
|
|
2089
2128
|
...options.input === void 0 ? [] : [
|
|
2090
2129
|
options.inputDispose === void 0 ? inputBackendPlugin(options.input) : ownedInputBackendPlugin(options.input, options.inputDispose)
|
|
@@ -2093,7 +2132,7 @@ function mainEngineProfile(options) {
|
|
|
2093
2132
|
animationPayloadsPlugin(options.animationPayloads),
|
|
2094
2133
|
animationRuntimePlugin(),
|
|
2095
2134
|
statePlugin(),
|
|
2096
|
-
...options.onDebugDrawReady === void 0 ? [] : [debugDrawPlugin(options.onDebugDrawReady)],
|
|
2135
|
+
...options.onDebugDrawReady === void 0 || options.rendererDebugDrawHost === void 0 ? [] : [debugDrawPlugin(options.rendererDebugDrawHost, options.onDebugDrawReady)],
|
|
2097
2136
|
...options.input === void 0 ? [] : [inputPlugin()],
|
|
2098
2137
|
...options.inputMap === void 0 ? [] : [inputMapPlugin(options.inputMap)],
|
|
2099
2138
|
...options.extensions ?? []
|
|
@@ -2101,8 +2140,7 @@ function mainEngineProfile(options) {
|
|
|
2101
2140
|
}
|
|
2102
2141
|
|
|
2103
2142
|
// src/internal/remote-serve-flag.ts
|
|
2104
|
-
function resolveRemoteServeFlag(isDev, processEnv
|
|
2105
|
-
if (isBrowser) return false;
|
|
2143
|
+
function resolveRemoteServeFlag(isDev, processEnv) {
|
|
2106
2144
|
if (isDev === true) return true;
|
|
2107
2145
|
if (processEnv?.FORGEAX_ENGINE_REMOTE_SERVE === "1") return true;
|
|
2108
2146
|
return false;
|
|
@@ -2289,38 +2327,10 @@ function resolveRhiDebugFlag(importMetaEnv, processEnv) {
|
|
|
2289
2327
|
}
|
|
2290
2328
|
|
|
2291
2329
|
// src/create-app.ts
|
|
2292
|
-
var DEFAULT_ASSET_CATALOG_PATH = "pack-index.json";
|
|
2293
|
-
function defaultAssetCatalogUrl() {
|
|
2294
|
-
const base = typeof document !== "undefined" ? document.baseURI : globalThis.location?.href;
|
|
2295
|
-
return base === void 0 ? DEFAULT_ASSET_CATALOG_PATH : new URL(DEFAULT_ASSET_CATALOG_PATH, base).href;
|
|
2296
|
-
}
|
|
2297
|
-
function assembleAppAssetRuntime(catalog, contributions) {
|
|
2298
|
-
const registry = createAssetRegistry({
|
|
2299
|
-
catalog: catalog ?? createCatalogSource({ url: defaultAssetCatalogUrl() })
|
|
2300
|
-
});
|
|
2301
|
-
const assembled = assembleAssetRuntime(registry, contributions ?? []);
|
|
2302
|
-
if (!assembled.ok) registry.dispose();
|
|
2303
|
-
return assembled;
|
|
2304
|
-
}
|
|
2305
2330
|
function makeAppError2(code, expected, hint, detail) {
|
|
2306
2331
|
return new AppError({ code, expected, hint, detail });
|
|
2307
2332
|
}
|
|
2308
|
-
function
|
|
2309
|
-
const moduleUrl = typeof bootstrap === "string" ? bootstrap : bootstrap.href;
|
|
2310
|
-
try {
|
|
2311
|
-
return ok(new URL(bootstrap, globalThis.location?.href).href);
|
|
2312
|
-
} catch (cause) {
|
|
2313
|
-
return err(
|
|
2314
|
-
makeAppError2(
|
|
2315
|
-
"app-execution-bootstrap-failed",
|
|
2316
|
-
APP_EXPECTED["app-execution-bootstrap-failed"],
|
|
2317
|
-
APP_ERROR_HINTS["app-execution-bootstrap-failed"],
|
|
2318
|
-
{ phase: "prepare", moduleUrl, cause }
|
|
2319
|
-
)
|
|
2320
|
-
);
|
|
2321
|
-
}
|
|
2322
|
-
}
|
|
2323
|
-
function canvasAspectPlugin(canvas, maxCanvasPixelRatio) {
|
|
2333
|
+
function canvasAspectPlugin(canvas) {
|
|
2324
2334
|
return {
|
|
2325
2335
|
name: "canvas-aspect",
|
|
2326
2336
|
inject: ["world"],
|
|
@@ -2330,7 +2340,7 @@ function canvasAspectPlugin(canvas, maxCanvasPixelRatio) {
|
|
|
2330
2340
|
name: "app-sync-camera-aspect",
|
|
2331
2341
|
queries: [],
|
|
2332
2342
|
fn: () => {
|
|
2333
|
-
syncCanvasDrawingBuffer(canvas
|
|
2343
|
+
syncCanvasDrawingBuffer(canvas);
|
|
2334
2344
|
syncCameraAspect(ctx.world, canvas.width, canvas.height);
|
|
2335
2345
|
}
|
|
2336
2346
|
};
|
|
@@ -2355,17 +2365,6 @@ function createApp(arg, opts, bundler) {
|
|
|
2355
2365
|
return createAppFromAssemble(arg);
|
|
2356
2366
|
}
|
|
2357
2367
|
async function createAppFromCanvas(canvas, opts, bundler) {
|
|
2358
|
-
const maxCanvasPixelRatio = opts?.maxCanvasPixelRatio;
|
|
2359
|
-
if (maxCanvasPixelRatio !== void 0 && (!Number.isFinite(maxCanvasPixelRatio) || maxCanvasPixelRatio <= 0)) {
|
|
2360
|
-
return err(
|
|
2361
|
-
makeAppError2(
|
|
2362
|
-
"app-invalid-canvas-pixel-ratio",
|
|
2363
|
-
APP_EXPECTED["app-invalid-canvas-pixel-ratio"],
|
|
2364
|
-
APP_ERROR_HINTS["app-invalid-canvas-pixel-ratio"],
|
|
2365
|
-
{ value: maxCanvasPixelRatio }
|
|
2366
|
-
)
|
|
2367
|
-
);
|
|
2368
|
-
}
|
|
2369
2368
|
if (!canvas.isConnected) {
|
|
2370
2369
|
return err(
|
|
2371
2370
|
makeAppError2(
|
|
@@ -2376,22 +2375,18 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2376
2375
|
)
|
|
2377
2376
|
);
|
|
2378
2377
|
}
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
if (
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
if (opts?.execution !== void 0 && normalizedExecutionBootstrap?.ok === true) {
|
|
2378
|
+
syncCanvasDrawingBuffer(canvas);
|
|
2379
|
+
let executionBootstrapUrl;
|
|
2380
|
+
if (opts?.execution !== void 0) {
|
|
2381
|
+
const normalizedBootstrap = normalizeExecutionBootstrapUrl(opts.execution.bootstrap);
|
|
2382
|
+
if (!normalizedBootstrap.ok) return err(normalizedBootstrap.error);
|
|
2383
|
+
executionBootstrapUrl = normalizedBootstrap.value;
|
|
2386
2384
|
const realmBoundOption = [
|
|
2387
2385
|
["features", opts.features],
|
|
2388
2386
|
["plugins", opts.plugins],
|
|
2389
2387
|
["rhi", opts.rhi],
|
|
2390
|
-
["
|
|
2388
|
+
["rhiInstrumentation", opts.rhiInstrumentation],
|
|
2391
2389
|
["drawSource", opts.drawSource],
|
|
2392
|
-
["membershipTiming", opts.membershipTiming],
|
|
2393
|
-
["assetCatalog", opts.assetCatalog],
|
|
2394
|
-
["assetDecoders", opts.assetDecoders],
|
|
2395
2390
|
["bundler.importTransport", bundler?.importTransport]
|
|
2396
2391
|
].find(([, value]) => value !== void 0)?.[0];
|
|
2397
2392
|
if (realmBoundOption !== void 0) {
|
|
@@ -2402,7 +2397,7 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2402
2397
|
APP_ERROR_HINTS["app-execution-bootstrap-failed"],
|
|
2403
2398
|
{
|
|
2404
2399
|
phase: "prepare",
|
|
2405
|
-
moduleUrl:
|
|
2400
|
+
moduleUrl: executionBootstrapUrl,
|
|
2406
2401
|
cause: new TypeError(
|
|
2407
2402
|
`${realmBoundOption} must be constructed by the execution bootstrap module`
|
|
2408
2403
|
)
|
|
@@ -2413,11 +2408,10 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2413
2408
|
}
|
|
2414
2409
|
let executionContext;
|
|
2415
2410
|
let preparedExecutionBootstrap;
|
|
2416
|
-
if (opts?.execution !== void 0
|
|
2417
|
-
const executionOptions2 = opts.execution;
|
|
2411
|
+
if (opts?.execution !== void 0) {
|
|
2418
2412
|
const capabilities = await probeExecutionCapabilities(canvas);
|
|
2419
2413
|
const selected = selectExecutionTier({
|
|
2420
|
-
requestedTier:
|
|
2414
|
+
requestedTier: opts.execution.tier ?? "auto",
|
|
2421
2415
|
capabilities,
|
|
2422
2416
|
sharedEvidencePassed: true
|
|
2423
2417
|
});
|
|
@@ -2427,15 +2421,18 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2427
2421
|
return createWorkerExecutionApp({
|
|
2428
2422
|
canvas,
|
|
2429
2423
|
appOptions: opts,
|
|
2430
|
-
syncCanvas: () => measureCanvasDrawingBuffer(canvas
|
|
2424
|
+
syncCanvas: () => measureCanvasDrawingBuffer(canvas),
|
|
2431
2425
|
...bundler !== void 0 ? { bundler } : {},
|
|
2432
2426
|
capabilities,
|
|
2433
2427
|
selection: selected.value
|
|
2434
2428
|
});
|
|
2435
2429
|
}
|
|
2430
|
+
if (executionBootstrapUrl === void 0) {
|
|
2431
|
+
throw new Error("execution bootstrap URL was not normalized");
|
|
2432
|
+
}
|
|
2436
2433
|
const prepared = await prepareBootstrapEntry(
|
|
2437
|
-
|
|
2438
|
-
|
|
2434
|
+
executionBootstrapUrl,
|
|
2435
|
+
opts.execution.bootstrapData
|
|
2439
2436
|
);
|
|
2440
2437
|
if (!prepared.ok) return err(prepared.error);
|
|
2441
2438
|
preparedExecutionBootstrap = prepared.value;
|
|
@@ -2444,24 +2441,19 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2444
2441
|
if (opts?.rhi !== void 0) {
|
|
2445
2442
|
Object.assign(rendererOpts, { rhi: opts.rhi });
|
|
2446
2443
|
}
|
|
2447
|
-
if (opts?.rhiInstrumentation !== void 0) {
|
|
2448
|
-
Object.assign(rendererOpts, { rhiInstrumentation: opts.rhiInstrumentation });
|
|
2449
|
-
}
|
|
2450
|
-
if (opts?.rawDeviceForContextConfigure !== void 0) {
|
|
2451
|
-
Object.assign(rendererOpts, {
|
|
2452
|
-
rawDeviceForContextConfigure: opts.rawDeviceForContextConfigure
|
|
2453
|
-
});
|
|
2454
|
-
}
|
|
2455
2444
|
if (opts?.profiler !== void 0) {
|
|
2456
2445
|
Object.assign(rendererOpts, { profiler: opts.profiler });
|
|
2457
2446
|
}
|
|
2458
|
-
if (opts?.membershipTiming !== void 0) {
|
|
2459
|
-
Object.assign(rendererOpts, { membershipTiming: opts.membershipTiming });
|
|
2460
|
-
}
|
|
2461
2447
|
const rendererFeatures = preparedExecutionBootstrap?.features ?? opts?.features;
|
|
2462
2448
|
if (rendererFeatures !== void 0) {
|
|
2463
2449
|
Object.assign(rendererOpts, { features: rendererFeatures });
|
|
2464
2450
|
}
|
|
2451
|
+
if (opts?.standardProfile !== void 0) {
|
|
2452
|
+
Object.assign(rendererOpts, { standardProfile: opts.standardProfile });
|
|
2453
|
+
}
|
|
2454
|
+
if (opts?.rhiInstrumentation !== void 0) {
|
|
2455
|
+
Object.assign(rendererOpts, { rhiInstrumentation: opts.rhiInstrumentation });
|
|
2456
|
+
}
|
|
2465
2457
|
let rhiAttachment;
|
|
2466
2458
|
let rhiCapture;
|
|
2467
2459
|
let rhiDebugGlobal;
|
|
@@ -2479,61 +2471,54 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2479
2471
|
const rhiDebugFlag = resolveRhiDebugFlag(importMetaEnv, processEnv);
|
|
2480
2472
|
const nav = typeof globalThis !== "undefined" ? globalThis.navigator : void 0;
|
|
2481
2473
|
const hasWebGPU = nav !== void 0 && "gpu" in nav && nav.gpu !== void 0;
|
|
2482
|
-
if (
|
|
2483
|
-
const
|
|
2484
|
-
if (!hasWebGPU && "ensureReady" in
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
'@forgeax/engine-rhi-debug'
|
|
2489
|
-
);
|
|
2474
|
+
if ((browserBuildRhiDebugFlag === void 0 || browserBuildRhiDebugFlag === "1") && rhiDebugFlag === "1") {
|
|
2475
|
+
const realBackend = hasWebGPU ? await import('@forgeax/engine-rhi-webgpu') : await import('@forgeax/engine-rhi-wgpu');
|
|
2476
|
+
if (!hasWebGPU && "ensureReady" in realBackend) {
|
|
2477
|
+
await realBackend.ensureReady();
|
|
2478
|
+
}
|
|
2479
|
+
const pack = loadRhiPack(realBackend);
|
|
2490
2480
|
if (pack.createShaderModule === void 0) {
|
|
2491
|
-
throw new Error("RHI
|
|
2481
|
+
throw new Error("RHI-debug requires a backend createShaderModule capability");
|
|
2492
2482
|
}
|
|
2493
|
-
const
|
|
2494
|
-
const attached = debugModule.attachRecorder({
|
|
2483
|
+
const attached = attachRecorder({
|
|
2495
2484
|
rhi: pack.rhi,
|
|
2496
|
-
createShaderModule
|
|
2485
|
+
createShaderModule: pack.createShaderModule
|
|
2497
2486
|
});
|
|
2498
2487
|
if (!attached.ok) throw new Error(attached.error.hint);
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
const capture =
|
|
2502
|
-
|
|
2488
|
+
rhiAttachment = attached.value;
|
|
2489
|
+
rhiCapture = createRhiCapture(attached.value);
|
|
2490
|
+
const capture = rhiCapture;
|
|
2491
|
+
rhiDebugGlobal = { captureFrame: (options) => capture.captureFrame(options) };
|
|
2503
2492
|
Object.assign(rendererOpts, {
|
|
2504
|
-
rhi:
|
|
2505
|
-
rhiInstrumentation: createRhiInstrumentation(
|
|
2493
|
+
rhi: attached.value.backend.rhi,
|
|
2494
|
+
rhiInstrumentation: createRhiInstrumentation(attached.value)
|
|
2506
2495
|
});
|
|
2507
|
-
rhiDebugGlobal = {
|
|
2508
|
-
captureFrame: (options) => capture.captureFrame(options)
|
|
2509
|
-
};
|
|
2510
2496
|
globalThis.__forgeax = rhiDebugGlobal;
|
|
2511
2497
|
}
|
|
2512
|
-
const assetAssemblyResult = assembleAppAssetRuntime(opts?.assetCatalog, opts?.assetDecoders);
|
|
2513
|
-
if (!assetAssemblyResult.ok) {
|
|
2514
|
-
cleanupRhiDebugHost();
|
|
2515
|
-
return err(assetAssemblyResult.error);
|
|
2516
|
-
}
|
|
2517
|
-
const assetAssembly = assetAssemblyResult.value;
|
|
2518
2498
|
let renderer;
|
|
2499
|
+
let rendererDebugDrawHost;
|
|
2500
|
+
let rendererFeatureHost;
|
|
2501
|
+
let assets;
|
|
2519
2502
|
try {
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2503
|
+
const constructed = await constructRuntimeRendererHost(canvas, rendererOpts, bundler);
|
|
2504
|
+
if (!constructed.ok) throw constructed.error;
|
|
2505
|
+
renderer = constructed.value.renderer;
|
|
2506
|
+
rendererDebugDrawHost = constructed.value.debugDrawHost;
|
|
2507
|
+
rendererFeatureHost = createRenderFeatureHost(constructed.value.featureHost);
|
|
2508
|
+
assets = constructed.value.assets;
|
|
2524
2509
|
} catch (e) {
|
|
2525
2510
|
cleanupRhiDebugHost();
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2511
|
+
if (e instanceof EngineEnvironmentError) return err(e);
|
|
2512
|
+
const detail = e instanceof Error ? e : new Error(String(e));
|
|
2513
|
+
return err(
|
|
2514
|
+
new EngineEnvironmentError("renderer construction failed", {
|
|
2515
|
+
webgpuError: detail
|
|
2516
|
+
})
|
|
2517
|
+
);
|
|
2532
2518
|
}
|
|
2533
2519
|
const shouldStartRemote = resolveRemoteServeFlag(
|
|
2534
2520
|
typeof import.meta !== "undefined" ? import.meta.env?.DEV : void 0,
|
|
2535
|
-
globalThis.process?.env
|
|
2536
|
-
typeof window !== "undefined"
|
|
2521
|
+
globalThis.process?.env
|
|
2537
2522
|
);
|
|
2538
2523
|
let debugDraw;
|
|
2539
2524
|
const world = new World(opts?.time !== void 0 ? { time: opts.time } : {});
|
|
@@ -2557,8 +2542,10 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2557
2542
|
world,
|
|
2558
2543
|
mainEngineProfile({
|
|
2559
2544
|
renderer,
|
|
2560
|
-
|
|
2561
|
-
|
|
2545
|
+
rendererDebugDrawHost,
|
|
2546
|
+
rendererFeatureHost,
|
|
2547
|
+
assets,
|
|
2548
|
+
animationPayloads: createAnimationPayloadLookup(assets),
|
|
2562
2549
|
...inputBackend === void 0 ? {} : { input: inputBackend },
|
|
2563
2550
|
...inputHandle === void 0 ? {} : { inputDispose: inputHandle.cleanup },
|
|
2564
2551
|
...opts?.inputMap === void 0 ? {} : { inputMap: opts.inputMap },
|
|
@@ -2568,14 +2555,12 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2568
2555
|
extensions: [
|
|
2569
2556
|
rhiDebugHostPlugin(cleanupRhiDebugHost),
|
|
2570
2557
|
...userPlugins,
|
|
2571
|
-
canvasAspectPlugin(canvas
|
|
2558
|
+
canvasAspectPlugin(canvas)
|
|
2572
2559
|
]
|
|
2573
2560
|
})
|
|
2574
2561
|
);
|
|
2575
2562
|
} catch (cause) {
|
|
2576
2563
|
cleanupRhiDebugHost();
|
|
2577
|
-
assetAssembly.dispose();
|
|
2578
|
-
assetAssembly.registry.dispose();
|
|
2579
2564
|
return err(
|
|
2580
2565
|
makeAppError2(
|
|
2581
2566
|
"app-plugin-activation-failed",
|
|
@@ -2623,18 +2608,11 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2623
2608
|
})
|
|
2624
2609
|
}
|
|
2625
2610
|
);
|
|
2626
|
-
const remoteHandle = shouldStartRemote ? await startRemoteServer(
|
|
2627
|
-
world,
|
|
2628
|
-
renderer,
|
|
2629
|
-
assetAssembly.registry,
|
|
2630
|
-
rhiCapture,
|
|
2631
|
-
opts?.profiler,
|
|
2632
|
-
executionControl
|
|
2633
|
-
) : void 0;
|
|
2611
|
+
const remoteHandle = shouldStartRemote ? await startRemoteServer(world, renderer, assets, rhiCapture, opts?.profiler, executionControl) : void 0;
|
|
2634
2612
|
if (remoteHandle !== void 0) await pluginContext.plugin(remoteServerPlugin(remoteHandle));
|
|
2635
2613
|
const buildArgs = {
|
|
2636
2614
|
renderer,
|
|
2637
|
-
assets
|
|
2615
|
+
assets,
|
|
2638
2616
|
world,
|
|
2639
2617
|
pluginContext,
|
|
2640
2618
|
executionControl,
|
|
@@ -2660,10 +2638,7 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2660
2638
|
Object.assign(buildArgs, { profiler: opts.profiler });
|
|
2661
2639
|
}
|
|
2662
2640
|
if (rhiCapture !== void 0) {
|
|
2663
|
-
Object.assign(buildArgs, {
|
|
2664
|
-
rhiCapture,
|
|
2665
|
-
...rhiAttachment === void 0 ? {} : { rhiAttachment }
|
|
2666
|
-
});
|
|
2641
|
+
Object.assign(buildArgs, { rhiCapture });
|
|
2667
2642
|
}
|
|
2668
2643
|
if (debugDraw !== void 0) {
|
|
2669
2644
|
Object.assign(buildArgs, { debugDraw });
|
|
@@ -2681,17 +2656,17 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2681
2656
|
const bridgePort = import.meta.env?.VITE_FORGEAX_ENGINE_BRIDGE_PORT ?? "5733";
|
|
2682
2657
|
await pluginContext.plugin({
|
|
2683
2658
|
name: "browser-remote-bridge",
|
|
2684
|
-
inject: ["world", "renderer", "
|
|
2659
|
+
inject: ["world", "renderer", "assets"],
|
|
2685
2660
|
async apply(ctx) {
|
|
2686
|
-
if (ctx.renderer === void 0 || ctx.
|
|
2687
|
-
throw new Error("browser remote bridge requires renderer and
|
|
2661
|
+
if (ctx.renderer === void 0 || ctx.assets === void 0) {
|
|
2662
|
+
throw new Error("browser remote bridge requires renderer and assets services");
|
|
2688
2663
|
}
|
|
2689
2664
|
try {
|
|
2690
2665
|
const bridge = await Promise.resolve().then(() => (init_browser_remote_bridge(), browser_remote_bridge_exports));
|
|
2691
2666
|
const teardown = await bridge.installBrowserRemoteBridge({
|
|
2692
2667
|
world: ctx.world,
|
|
2693
2668
|
renderer: ctx.renderer,
|
|
2694
|
-
assets: ctx.
|
|
2669
|
+
assets: ctx.assets,
|
|
2695
2670
|
runtimeModule: engineRuntimeModule,
|
|
2696
2671
|
...rhiCapture !== void 0 ? { rhiCapture } : {},
|
|
2697
2672
|
...opts?.profiler !== void 0 ? { profiler: opts.profiler } : {},
|
|
@@ -2707,43 +2682,62 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2707
2682
|
}
|
|
2708
2683
|
return built;
|
|
2709
2684
|
}
|
|
2710
|
-
function syncCanvasDrawingBuffer(canvas
|
|
2711
|
-
const size = resolveCanvasDrawingBufferSize(canvas, maxCanvasPixelRatio);
|
|
2712
|
-
if (size === void 0) return { width: canvas.width, height: canvas.height };
|
|
2713
|
-
if (canvas.width !== size.width) canvas.width = size.width;
|
|
2714
|
-
if (canvas.height !== size.height) canvas.height = size.height;
|
|
2715
|
-
return size;
|
|
2716
|
-
}
|
|
2717
|
-
function measureCanvasDrawingBuffer(canvas, maxCanvasPixelRatio) {
|
|
2718
|
-
return resolveCanvasDrawingBufferSize(canvas, maxCanvasPixelRatio) ?? {
|
|
2719
|
-
width: canvas.width,
|
|
2720
|
-
height: canvas.height
|
|
2721
|
-
};
|
|
2722
|
-
}
|
|
2723
|
-
function resolveCanvasDrawingBufferSize(canvas, maxCanvasPixelRatio) {
|
|
2685
|
+
function syncCanvasDrawingBuffer(canvas) {
|
|
2724
2686
|
if (!Number.isFinite(canvas.clientWidth) || !Number.isFinite(canvas.clientHeight) || canvas.clientWidth <= 0 || canvas.clientHeight <= 0)
|
|
2725
|
-
return
|
|
2687
|
+
return;
|
|
2726
2688
|
const hasExplicitCssSize = (canvas.style?.width ?? "") !== "" || (canvas.style?.height ?? "") !== "";
|
|
2727
2689
|
if (!hasExplicitCssSize && canvas.clientWidth === canvas.width && canvas.clientHeight === canvas.height) {
|
|
2728
|
-
return
|
|
2690
|
+
return;
|
|
2729
2691
|
}
|
|
2730
|
-
const
|
|
2731
|
-
const dpr = maxCanvasPixelRatio === void 0 || !Number.isFinite(maxCanvasPixelRatio) || maxCanvasPixelRatio <= 0 ? devicePixelRatio : Math.min(devicePixelRatio, maxCanvasPixelRatio);
|
|
2692
|
+
const dpr = Math.max(1, globalThis.devicePixelRatio || 1);
|
|
2732
2693
|
const previous = syncedCanvasSizes.get(canvas);
|
|
2733
2694
|
const drawingBufferIsTheLayoutMeasurement = previous !== void 0 && canvas.width === previous.drawingWidth && canvas.height === previous.drawingHeight && canvas.clientWidth === previous.drawingWidth && canvas.clientHeight === previous.drawingHeight;
|
|
2734
2695
|
const cssWidth = drawingBufferIsTheLayoutMeasurement ? previous.cssWidth : canvas.clientWidth;
|
|
2735
2696
|
const cssHeight = drawingBufferIsTheLayoutMeasurement ? previous.cssHeight : canvas.clientHeight;
|
|
2736
2697
|
const width = Math.max(1, Math.round(cssWidth * dpr));
|
|
2737
2698
|
const height = Math.max(1, Math.round(cssHeight * dpr));
|
|
2699
|
+
if (canvas.width !== width) canvas.width = width;
|
|
2700
|
+
if (canvas.height !== height) canvas.height = height;
|
|
2738
2701
|
syncedCanvasSizes.set(canvas, {
|
|
2739
2702
|
cssWidth,
|
|
2740
2703
|
cssHeight,
|
|
2741
2704
|
drawingWidth: width,
|
|
2742
2705
|
drawingHeight: height
|
|
2743
2706
|
});
|
|
2744
|
-
|
|
2707
|
+
}
|
|
2708
|
+
function measureCanvasDrawingBuffer(canvas, maxCanvasPixelRatio) {
|
|
2709
|
+
if (!Number.isFinite(canvas.clientWidth) || !Number.isFinite(canvas.clientHeight) || canvas.clientWidth <= 0 || canvas.clientHeight <= 0) {
|
|
2710
|
+
return { width: canvas.width, height: canvas.height };
|
|
2711
|
+
}
|
|
2712
|
+
const hasExplicitCssSize = (canvas.style?.width ?? "") !== "" || (canvas.style?.height ?? "") !== "";
|
|
2713
|
+
if (!hasExplicitCssSize && canvas.clientWidth === canvas.width && canvas.clientHeight === canvas.height) {
|
|
2714
|
+
return { width: canvas.width, height: canvas.height };
|
|
2715
|
+
}
|
|
2716
|
+
const devicePixelRatio = Math.max(1, globalThis.devicePixelRatio || 1);
|
|
2717
|
+
const dpr = maxCanvasPixelRatio === void 0 || !Number.isFinite(maxCanvasPixelRatio) || maxCanvasPixelRatio <= 0 ? devicePixelRatio : Math.min(devicePixelRatio, maxCanvasPixelRatio);
|
|
2718
|
+
const previous = syncedCanvasSizes.get(canvas);
|
|
2719
|
+
const drawingBufferIsTheLayoutMeasurement = previous !== void 0 && canvas.width === previous.drawingWidth && canvas.height === previous.drawingHeight && canvas.clientWidth === previous.drawingWidth && canvas.clientHeight === previous.drawingHeight;
|
|
2720
|
+
const cssWidth = drawingBufferIsTheLayoutMeasurement ? previous.cssWidth : canvas.clientWidth;
|
|
2721
|
+
const cssHeight = drawingBufferIsTheLayoutMeasurement ? previous.cssHeight : canvas.clientHeight;
|
|
2722
|
+
return {
|
|
2723
|
+
width: Math.max(1, Math.round(cssWidth * dpr)),
|
|
2724
|
+
height: Math.max(1, Math.round(cssHeight * dpr))
|
|
2725
|
+
};
|
|
2745
2726
|
}
|
|
2746
2727
|
var syncedCanvasSizes = /* @__PURE__ */ new WeakMap();
|
|
2728
|
+
function syncCameraAspect(world, canvasW, canvasH) {
|
|
2729
|
+
if (canvasW <= 0 || canvasH <= 0) return;
|
|
2730
|
+
const aspect = canvasW / canvasH;
|
|
2731
|
+
const query = world.query({ with: [Camera] }).unwrap();
|
|
2732
|
+
for (const row of query) {
|
|
2733
|
+
const entity = row.entity;
|
|
2734
|
+
const r = world.get(entity, Camera);
|
|
2735
|
+
if (!r.ok) continue;
|
|
2736
|
+
if (r.value.autoAspect !== true) continue;
|
|
2737
|
+
if (r.value.projection !== CAMERA_PROJECTION_PERSPECTIVE) continue;
|
|
2738
|
+
world.set(entity, Camera, { aspect });
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2747
2741
|
async function startRemoteServer(world, renderer, assets, rhiCapture, profiler, execution) {
|
|
2748
2742
|
try {
|
|
2749
2743
|
const remoteServerMod = await import(
|
|
@@ -2769,22 +2763,17 @@ async function startRemoteServer(world, renderer, assets, rhiCapture, profiler,
|
|
|
2769
2763
|
return void 0;
|
|
2770
2764
|
}
|
|
2771
2765
|
async function createAppFromAssemble(args) {
|
|
2772
|
-
const assetAssemblyResult = assembleAppAssetRuntime(args.assetCatalog, args.assetDecoders);
|
|
2773
|
-
if (!assetAssemblyResult.ok) return err(assetAssemblyResult.error);
|
|
2774
|
-
const assetAssembly = assetAssemblyResult.value;
|
|
2775
2766
|
let pluginContext;
|
|
2776
2767
|
try {
|
|
2777
2768
|
pluginContext = await createWorldContext(
|
|
2778
2769
|
args.world,
|
|
2779
2770
|
assembledEngineProfile({
|
|
2780
2771
|
renderer: args.renderer,
|
|
2781
|
-
|
|
2772
|
+
...args.assets === void 0 ? {} : { assets: args.assets },
|
|
2782
2773
|
extensions: args.plugins ?? []
|
|
2783
2774
|
})
|
|
2784
2775
|
);
|
|
2785
2776
|
} catch (cause) {
|
|
2786
|
-
assetAssembly.dispose();
|
|
2787
|
-
assetAssembly.registry.dispose();
|
|
2788
2777
|
return err(
|
|
2789
2778
|
makeAppError2(
|
|
2790
2779
|
"app-plugin-activation-failed",
|
|
@@ -2826,7 +2815,7 @@ async function createAppFromAssemble(args) {
|
|
|
2826
2815
|
const remoteHandle = shouldStartRemote ? await startRemoteServer(
|
|
2827
2816
|
args.world,
|
|
2828
2817
|
args.renderer,
|
|
2829
|
-
|
|
2818
|
+
args.assets,
|
|
2830
2819
|
void 0,
|
|
2831
2820
|
args.profiler,
|
|
2832
2821
|
executionControl
|
|
@@ -2834,7 +2823,6 @@ async function createAppFromAssemble(args) {
|
|
|
2834
2823
|
if (remoteHandle !== void 0) await pluginContext.plugin(remoteServerPlugin(remoteHandle));
|
|
2835
2824
|
const buildArgs = {
|
|
2836
2825
|
renderer: args.renderer,
|
|
2837
|
-
assets: assetAssembly.registry,
|
|
2838
2826
|
world: args.world,
|
|
2839
2827
|
pluginContext,
|
|
2840
2828
|
executionControl,
|
|
@@ -2867,14 +2855,12 @@ async function createAppFromAssemble(args) {
|
|
|
2867
2855
|
async function buildApp(args) {
|
|
2868
2856
|
const {
|
|
2869
2857
|
renderer,
|
|
2870
|
-
assets,
|
|
2871
2858
|
world,
|
|
2872
2859
|
pluginContext,
|
|
2873
2860
|
inputBackend,
|
|
2874
2861
|
audioBackend,
|
|
2875
2862
|
silenceUnhandledErrors,
|
|
2876
2863
|
rhiCapture,
|
|
2877
|
-
rhiAttachment,
|
|
2878
2864
|
debugDraw,
|
|
2879
2865
|
remoteHandle,
|
|
2880
2866
|
profiler
|
|
@@ -2885,6 +2871,7 @@ async function buildApp(args) {
|
|
|
2885
2871
|
const fanout = new ErrorFanoutRegistry(
|
|
2886
2872
|
silenceUnhandledErrors !== void 0 ? { silenceUnhandledErrors } : {}
|
|
2887
2873
|
);
|
|
2874
|
+
let lastError;
|
|
2888
2875
|
const execution = args.executionControl ?? createLocalExecutionControl(
|
|
2889
2876
|
{
|
|
2890
2877
|
...createExecutionReport("main-serial", unavailableExecutionCapabilities("not required")),
|
|
@@ -2910,6 +2897,7 @@ async function buildApp(args) {
|
|
|
2910
2897
|
}
|
|
2911
2898
|
);
|
|
2912
2899
|
function dispatch(e) {
|
|
2900
|
+
lastError = e;
|
|
2913
2901
|
fanout.fire(e);
|
|
2914
2902
|
}
|
|
2915
2903
|
if (args.wireOnLockErrorDispatch) {
|
|
@@ -2927,7 +2915,7 @@ async function buildApp(args) {
|
|
|
2927
2915
|
Object.assign(loopOpts, { profiler });
|
|
2928
2916
|
}
|
|
2929
2917
|
const loop = createFrameLoop(loopOpts);
|
|
2930
|
-
if (rhiCapture !== void 0
|
|
2918
|
+
if (rhiCapture !== void 0) {
|
|
2931
2919
|
bindRhiCaptureFrameDriver(rhiCapture, {
|
|
2932
2920
|
getState: () => loop.getState(),
|
|
2933
2921
|
pause: () => {
|
|
@@ -2943,17 +2931,15 @@ async function buildApp(args) {
|
|
|
2943
2931
|
stepFrame: (deltaSeconds) => loop.stepFrame(deltaSeconds)
|
|
2944
2932
|
});
|
|
2945
2933
|
}
|
|
2946
|
-
let lastError;
|
|
2947
2934
|
let rendererUnsubscribe;
|
|
2948
2935
|
let resumeAfterSurfaceRestore = false;
|
|
2949
2936
|
function subscribeRendererErrors() {
|
|
2950
2937
|
if (rendererUnsubscribe !== void 0) {
|
|
2951
2938
|
return;
|
|
2952
2939
|
}
|
|
2953
|
-
rendererUnsubscribe = renderer.
|
|
2954
|
-
if (
|
|
2955
|
-
|
|
2956
|
-
}
|
|
2940
|
+
rendererUnsubscribe = renderer.subscribe((event) => {
|
|
2941
|
+
if (event.kind !== "error") return;
|
|
2942
|
+
const e = event.error;
|
|
2957
2943
|
dispatch(e);
|
|
2958
2944
|
});
|
|
2959
2945
|
}
|
|
@@ -2965,7 +2951,7 @@ async function buildApp(args) {
|
|
|
2965
2951
|
}
|
|
2966
2952
|
const stub = {
|
|
2967
2953
|
renderer,
|
|
2968
|
-
assets,
|
|
2954
|
+
...args.assets === void 0 ? {} : { assets: args.assets },
|
|
2969
2955
|
world,
|
|
2970
2956
|
execution,
|
|
2971
2957
|
async releaseSurfacePreserveWorld() {
|
|
@@ -3060,7 +3046,7 @@ async function buildApp(args) {
|
|
|
3060
3046
|
loop.setDrawSource(drawSource);
|
|
3061
3047
|
},
|
|
3062
3048
|
/**
|
|
3063
|
-
* Most recent
|
|
3049
|
+
* Most recent dispatched error retained for host self-inspection.
|
|
3064
3050
|
*/
|
|
3065
3051
|
get lastError() {
|
|
3066
3052
|
return lastError;
|
|
@@ -3069,10 +3055,6 @@ async function buildApp(args) {
|
|
|
3069
3055
|
...debugDraw !== void 0 ? { debugDraw } : {},
|
|
3070
3056
|
...remoteHandle !== void 0 ? { remote: remoteHandle } : {}
|
|
3071
3057
|
};
|
|
3072
|
-
const readyResult = await renderer.ready;
|
|
3073
|
-
if (!readyResult.ok) {
|
|
3074
|
-
return err(readyResult.error);
|
|
3075
|
-
}
|
|
3076
3058
|
return ok(stub);
|
|
3077
3059
|
}
|
|
3078
3060
|
function ensureFallbackCamera(world, aspect = 1) {
|
|
@@ -3679,19 +3661,6 @@ async function createToolPreviewHost(options) {
|
|
|
3679
3661
|
const app = appResult.value;
|
|
3680
3662
|
const appErrors = [];
|
|
3681
3663
|
const unsubscribeAppErrors = app.onError((error) => appErrors.push(error));
|
|
3682
|
-
const rendererReady = await app.renderer.ready;
|
|
3683
|
-
if (!rendererReady.ok) {
|
|
3684
|
-
unsubscribeAppErrors();
|
|
3685
|
-
await app.dispose();
|
|
3686
|
-
await runtime.attachment.dispose();
|
|
3687
|
-
removeOwnedCanvas(canvas, ownsCanvas);
|
|
3688
|
-
return err({
|
|
3689
|
-
code: "tool-preview-bootstrap-failed",
|
|
3690
|
-
expected: "the real WebGPU Renderer to finish pipeline initialization before preview frames",
|
|
3691
|
-
hint: rendererReady.error.hint,
|
|
3692
|
-
detail: { phase: "renderer-ready", cause: rendererReady.error }
|
|
3693
|
-
});
|
|
3694
|
-
}
|
|
3695
3664
|
let resourceFacts;
|
|
3696
3665
|
try {
|
|
3697
3666
|
const prepared = await options.prepare?.(app);
|
|
@@ -3716,7 +3685,7 @@ async function createToolPreviewHost(options) {
|
|
|
3716
3685
|
detail: { phase: bootstrapFailure.phase, cause }
|
|
3717
3686
|
});
|
|
3718
3687
|
}
|
|
3719
|
-
const attached = app.renderer.
|
|
3688
|
+
const attached = app.renderer.attach(app.world);
|
|
3720
3689
|
if (!attached.ok) {
|
|
3721
3690
|
unsubscribeAppErrors();
|
|
3722
3691
|
await app.dispose();
|
|
@@ -3977,6 +3946,6 @@ function fitToolPreviewCameraToAabb(aabb, options) {
|
|
|
3977
3946
|
};
|
|
3978
3947
|
}
|
|
3979
3948
|
|
|
3980
|
-
export { APP_ERROR_HINTS, APP_EXPECTED, APP_PHASE_CATALOG, AppError, EXECUTION_CAPABILITY_NAMES, EXECUTION_REPORT_SCHEMA_VERSION, EXECUTION_REQUESTED_TIERS, EXECUTION_TIERS, LOAD_GAME_ERROR_HINTS, LOAD_GAME_EXPECTED, LoadGameError,
|
|
3949
|
+
export { APP_ERROR_HINTS, APP_EXPECTED, APP_PHASE_CATALOG, AppError, EXECUTION_CAPABILITY_NAMES, EXECUTION_REPORT_SCHEMA_VERSION, EXECUTION_REQUESTED_TIERS, EXECUTION_TIERS, LOAD_GAME_ERROR_HINTS, LOAD_GAME_EXPECTED, LoadGameError, createApp, createExecutionReport, createToolPreviewEvidence, createToolPreviewHost, createToolPreviewRecipe, ensureFallbackCamera, executionBootstrapHostPlugin, fitToolPreviewCameraToAabb, gameHostPlugin, inputPlugin, isAppError, isExecutionReport, isLoadGameError, joinResourcePreviewEvidence, joinToolPreviewEvidence, loadBootstrapEntry, loadGame, measureCanvasDrawingBuffer, missingExecutionCapabilities, ownedRendererPlugin, prepareBootstrapEntry, probeExecutionCapabilities, renderFeatureHostPlugin, renderFeaturePlugin, rendererPlugin, replayToolPreviewCapture, selectExecutionTier, syncCanvasDrawingBuffer, unavailableExecutionCapabilities, validateExecutionBootstrapData, validateToolPreviewTrace };
|
|
3981
3950
|
//# sourceMappingURL=index.mjs.map
|
|
3982
3951
|
//# sourceMappingURL=index.mjs.map
|