@forgeax/engine-app 0.1.6 → 0.1.7
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/dist/.tsbuildinfo +1 -1
- package/dist/browser-frame-signal.d.ts +17 -0
- package/dist/browser-frame-signal.d.ts.map +1 -0
- package/dist/create-app.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +30 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +25 -25
- package/src/browser-frame-signal.ts +44 -0
- package/src/create-app.ts +12 -0
- package/src/index.ts +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -23,32 +23,32 @@
|
|
|
23
23
|
"LICENSE"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@forgeax/engine-animation": "0.1.
|
|
27
|
-
"@forgeax/engine-assets-runtime": "0.1.
|
|
28
|
-
"@forgeax/engine-audio": "0.1.
|
|
29
|
-
"@forgeax/engine-audio-webaudio": "0.1.
|
|
30
|
-
"@forgeax/engine-debug-draw": "0.1.
|
|
31
|
-
"@forgeax/engine-ecs": "0.1.
|
|
32
|
-
"@forgeax/engine-input": "0.1.
|
|
33
|
-
"@forgeax/engine-physics": "0.1.
|
|
34
|
-
"@forgeax/engine-physics-rapier2d": "0.1.
|
|
35
|
-
"@forgeax/engine-physics-rapier3d": "0.1.
|
|
36
|
-
"@forgeax/engine-plugin": "0.1.
|
|
37
|
-
"@forgeax/engine-profiler": "0.1.
|
|
38
|
-
"@forgeax/engine-render": "0.1.
|
|
39
|
-
"@forgeax/engine-rhi": "0.1.
|
|
40
|
-
"@forgeax/engine-runtime": "0.1.
|
|
41
|
-
"@forgeax/engine-scene": "0.1.
|
|
42
|
-
"@forgeax/engine-state": "0.1.
|
|
43
|
-
"@forgeax/engine-tool-runtime": "0.1.
|
|
44
|
-
"@forgeax/engine-types": "0.1.
|
|
26
|
+
"@forgeax/engine-animation": "0.1.7",
|
|
27
|
+
"@forgeax/engine-assets-runtime": "0.1.7",
|
|
28
|
+
"@forgeax/engine-audio": "0.1.7",
|
|
29
|
+
"@forgeax/engine-audio-webaudio": "0.1.7",
|
|
30
|
+
"@forgeax/engine-debug-draw": "0.1.7",
|
|
31
|
+
"@forgeax/engine-ecs": "0.1.7",
|
|
32
|
+
"@forgeax/engine-input": "0.1.7",
|
|
33
|
+
"@forgeax/engine-physics": "0.1.7",
|
|
34
|
+
"@forgeax/engine-physics-rapier2d": "0.1.7",
|
|
35
|
+
"@forgeax/engine-physics-rapier3d": "0.1.7",
|
|
36
|
+
"@forgeax/engine-plugin": "0.1.7",
|
|
37
|
+
"@forgeax/engine-profiler": "0.1.7",
|
|
38
|
+
"@forgeax/engine-render": "0.1.7",
|
|
39
|
+
"@forgeax/engine-rhi": "0.1.7",
|
|
40
|
+
"@forgeax/engine-runtime": "0.1.7",
|
|
41
|
+
"@forgeax/engine-scene": "0.1.7",
|
|
42
|
+
"@forgeax/engine-state": "0.1.7",
|
|
43
|
+
"@forgeax/engine-tool-runtime": "0.1.7",
|
|
44
|
+
"@forgeax/engine-types": "0.1.7"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@forgeax/engine-remote": "0.1.
|
|
48
|
-
"@forgeax/engine-rhi-debug": "0.1.
|
|
49
|
-
"@forgeax/engine-rhi-null": "0.1.
|
|
50
|
-
"@forgeax/engine-rhi-webgpu": "0.1.
|
|
51
|
-
"@forgeax/engine-rhi-wgpu": "0.1.
|
|
47
|
+
"@forgeax/engine-remote": "0.1.7",
|
|
48
|
+
"@forgeax/engine-rhi-debug": "0.1.7",
|
|
49
|
+
"@forgeax/engine-rhi-null": "0.1.7",
|
|
50
|
+
"@forgeax/engine-rhi-webgpu": "0.1.7",
|
|
51
|
+
"@forgeax/engine-rhi-wgpu": "0.1.7",
|
|
52
52
|
"@types/ws": "^8.5.10",
|
|
53
53
|
"@webgpu/types": "^0.1.71",
|
|
54
54
|
"ws": "^8.20.0"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-visible render progress owned by the App frame loop.
|
|
3
|
+
*
|
|
4
|
+
* The Renderer already emits `frame-submitted` after its sole queue-submit
|
|
5
|
+
* boundary. This adapter projects that event onto the document without
|
|
6
|
+
* exposing a renderer handle or creating a second readiness registry. DevKit
|
|
7
|
+
* capture waits on the same projection, then verifies compositor pixels.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const FORGEAX_FRAME_SUBMITTED_DATASET = 'forgeaxFrameSubmitted';
|
|
11
|
+
export const FORGEAX_FRAME_SUBMITTED_EVENT = 'forgeax:frame-submitted';
|
|
12
|
+
|
|
13
|
+
export interface BrowserFrameSubmitted {
|
|
14
|
+
readonly frameId: number;
|
|
15
|
+
readonly deviceGeneration: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function resetBrowserFrameSubmitted(canvas: HTMLCanvasElement): void {
|
|
19
|
+
const documentElement = canvas.ownerDocument?.documentElement;
|
|
20
|
+
if (documentElement !== undefined) {
|
|
21
|
+
delete documentElement.dataset[FORGEAX_FRAME_SUBMITTED_DATASET];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function publishBrowserFrameSubmitted(
|
|
26
|
+
canvas: HTMLCanvasElement,
|
|
27
|
+
event: BrowserFrameSubmitted,
|
|
28
|
+
): void {
|
|
29
|
+
const documentElement = canvas.ownerDocument?.documentElement;
|
|
30
|
+
if (documentElement !== undefined) {
|
|
31
|
+
documentElement.dataset[FORGEAX_FRAME_SUBMITTED_DATASET] = String(event.frameId);
|
|
32
|
+
}
|
|
33
|
+
// Native/Web test canvases may be structural objects without DOM event
|
|
34
|
+
// methods. The dataset projection above remains optional as well, so the
|
|
35
|
+
// signal must stay a no-op outside a browser host instead of poisoning the
|
|
36
|
+
// frame loop with a listener exception.
|
|
37
|
+
if (typeof CustomEvent === 'function' && typeof canvas.dispatchEvent === 'function') {
|
|
38
|
+
canvas.dispatchEvent(
|
|
39
|
+
new CustomEvent(FORGEAX_FRAME_SUBMITTED_EVENT, {
|
|
40
|
+
detail: Object.freeze({ ...event }),
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/create-app.ts
CHANGED
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
48
48
|
|
|
49
49
|
import { createAnimationPayloadLookup } from './animation-asset-lookup';
|
|
50
|
+
import { publishBrowserFrameSubmitted, resetBrowserFrameSubmitted } from './browser-frame-signal';
|
|
50
51
|
import type { AppErrorCode, AppErrorDetailFor } from './errors';
|
|
51
52
|
import { APP_ERROR_HINTS, APP_EXPECTED, AppError } from './errors';
|
|
52
53
|
import {
|
|
@@ -564,6 +565,7 @@ async function createAppFromCanvas(
|
|
|
564
565
|
world,
|
|
565
566
|
pluginContext,
|
|
566
567
|
executionControl,
|
|
568
|
+
onFrameSubmitted: (event) => publishBrowserFrameSubmitted(canvas, event),
|
|
567
569
|
...(inputBackend !== undefined ? { inputBackend } : {}),
|
|
568
570
|
...(inputHandle === undefined
|
|
569
571
|
? {}
|
|
@@ -600,6 +602,7 @@ async function createAppFromCanvas(
|
|
|
600
602
|
|
|
601
603
|
// The aspect-sync sidecar belongs to the canvas path because it owns the DOM
|
|
602
604
|
// canvas. It runs as an Update system so it shares World scheduling semantics.
|
|
605
|
+
resetBrowserFrameSubmitted(canvas);
|
|
603
606
|
const built = await buildApp(buildArgs);
|
|
604
607
|
if (!built.ok) {
|
|
605
608
|
await pluginContext.fiber.dispose();
|
|
@@ -994,6 +997,11 @@ interface BuildAppArgs {
|
|
|
994
997
|
| undefined;
|
|
995
998
|
readonly profiler?: import('@forgeax/engine-profiler').Profiler;
|
|
996
999
|
readonly executionControl?: import('./execution/control').LocalExecutionControl;
|
|
1000
|
+
/** Canvas-form projection of the Renderer frame-submitted event. */
|
|
1001
|
+
readonly onFrameSubmitted?: (event: {
|
|
1002
|
+
readonly frameId: number;
|
|
1003
|
+
readonly deviceGeneration: number;
|
|
1004
|
+
}) => void;
|
|
997
1005
|
}
|
|
998
1006
|
|
|
999
1007
|
/**
|
|
@@ -1118,6 +1126,10 @@ async function buildApp(args: BuildAppArgs): Promise<Result<App, AppError | RhiE
|
|
|
1118
1126
|
return;
|
|
1119
1127
|
}
|
|
1120
1128
|
rendererUnsubscribe = renderer.subscribe((event) => {
|
|
1129
|
+
if (event.kind === 'frame-submitted') {
|
|
1130
|
+
args.onFrameSubmitted?.(event);
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1121
1133
|
if (event.kind !== 'error') return;
|
|
1122
1134
|
const e: RenderError = event.error;
|
|
1123
1135
|
dispatch(e);
|
package/src/index.ts
CHANGED
|
@@ -39,6 +39,13 @@ export {
|
|
|
39
39
|
createFullscreenRenderFeature,
|
|
40
40
|
type FullscreenRenderFeatureOptions,
|
|
41
41
|
} from '@forgeax/engine-render/authoring';
|
|
42
|
+
export {
|
|
43
|
+
type BrowserFrameSubmitted,
|
|
44
|
+
FORGEAX_FRAME_SUBMITTED_DATASET,
|
|
45
|
+
FORGEAX_FRAME_SUBMITTED_EVENT,
|
|
46
|
+
publishBrowserFrameSubmitted,
|
|
47
|
+
resetBrowserFrameSubmitted,
|
|
48
|
+
} from './browser-frame-signal';
|
|
42
49
|
export { createApp, measureCanvasDrawingBuffer, syncCanvasDrawingBuffer } from './create-app';
|
|
43
50
|
export type {
|
|
44
51
|
AppDetailCanvasDetached,
|