@codexo/exojs 0.6.2 → 0.6.4
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/CHANGELOG.md +585 -499
- package/README.md +156 -156
- package/dist/esm/core/Application.d.ts +8 -0
- package/dist/esm/core/Application.js +17 -0
- package/dist/esm/core/Application.js.map +1 -1
- package/dist/esm/core/capabilities.d.ts +38 -0
- package/dist/esm/core/capabilities.js +198 -0
- package/dist/esm/core/capabilities.js.map +1 -0
- package/dist/esm/core/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/rendering/webgl2/glsl/mask-compose.frag.js +1 -1
- package/dist/esm/rendering/webgl2/glsl/mask-compose.vert.js +1 -1
- package/dist/esm/rendering/webgl2/glsl/particle.frag.js +1 -1
- package/dist/esm/rendering/webgl2/glsl/primitive.frag.js +1 -1
- package/dist/esm/rendering/webgl2/glsl/primitive.vert.js +1 -1
- package/dist/esm/rendering/webgl2/glsl/sprite.frag.js +1 -1
- package/dist/esm/rendering/webgpu/WebGpuBackend.js +41 -41
- package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js +44 -44
- package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js +65 -65
- package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.js +25 -25
- package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.js.map +1 -1
- package/dist/esm/vendor/webgl-debug.js +1156 -1156
- package/dist/esm/vendor/webgl-debug.js.map +1 -1
- package/dist/exo.esm.js +1550 -1338
- package/dist/exo.esm.js.map +1 -1
- package/package.json +105 -105
package/README.md
CHANGED
|
@@ -1,156 +1,156 @@
|
|
|
1
|
-
# ExoJS
|
|
2
|
-
|
|
3
|
-
ExoJS is a TypeScript-first 2D runtime for browser games and interactive apps. It is designed around explicit scene flow, practical rendering features, and predictable runtime behavior.
|
|
4
|
-
|
|
5
|
-
## Project status
|
|
6
|
-
|
|
7
|
-
ExoJS is **pre-1.0**. The public API is still under active design — scene graph, rendering pipeline, and resource lifecycle boundaries may change between minor versions. Pin exact versions in downstream experiments. `1.0.0` will mark the first stable API contract.
|
|
8
|
-
|
|
9
|
-
## Why ExoJS
|
|
10
|
-
|
|
11
|
-
- TypeScript-first API surface with strong runtime contracts
|
|
12
|
-
- Scene and asset workflows built for real game loops
|
|
13
|
-
- Modern rendering stack: WebGPU-first with WebGL2 fallback
|
|
14
|
-
- Practical visuals: filters, masks, render passes, cache-as-bitmap
|
|
15
|
-
- Gameplay tools: animated sprites, scene stacking, camera helpers, audio sprites
|
|
16
|
-
- Performance visibility with built-in render stats and benchmark harness
|
|
17
|
-
- Optional Rapier physics integration without forcing physics on every app
|
|
18
|
-
|
|
19
|
-
## What Is Shipped Today
|
|
20
|
-
|
|
21
|
-
- `Application`, `Scene`, and scene-manager lifecycle
|
|
22
|
-
- Typed `Loader` with manifest/bundle workflow (`defineAssetManifest`, `registerManifest`, `loadBundle`)
|
|
23
|
-
- Drawables: `Sprite`, `AnimatedSprite`, `Graphics`, `ParticleSystem`, `Text`, `Video`
|
|
24
|
-
- Scene stacking (`overlay` / `modal` / `opaque`) with input routing and fade transitions
|
|
25
|
-
- View/camera helpers (`follow`, bounds clamp, shake, zoom)
|
|
26
|
-
- Rendering composition primitives (`RenderTexture`, `RenderTargetPass`, filter chains, visual masks, cache-as-bitmap)
|
|
27
|
-
- Render stats (`submittedNodes`, `culledNodes`, `drawCalls`, `batches`, `renderPasses`, ...)
|
|
28
|
-
- Optional Rapier adapter (`createRapierPhysicsWorld`)
|
|
29
|
-
|
|
30
|
-
## Installation
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm install @codexo/exojs
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
ExoJS currently publishes an ESM-first package shape. Use `import` syntax with modern bundlers/runtime tooling.
|
|
37
|
-
CommonJS `require()` usage is not part of the supported contract for this pre-1.0 line.
|
|
38
|
-
|
|
39
|
-
## Quickstart
|
|
40
|
-
|
|
41
|
-
```ts
|
|
42
|
-
import { Application, Scene, Graphics, Color, type RenderBackend } from '@codexo/exojs';
|
|
43
|
-
|
|
44
|
-
class HelloScene extends Scene {
|
|
45
|
-
private readonly box = new Graphics();
|
|
46
|
-
|
|
47
|
-
public constructor() {
|
|
48
|
-
super();
|
|
49
|
-
|
|
50
|
-
this.box.fillColor = Color.white;
|
|
51
|
-
this.box.drawRectangle(-32, -32, 64, 64);
|
|
52
|
-
this.box.setPosition(400, 300);
|
|
53
|
-
|
|
54
|
-
this.addChild(this.box);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
public override update(delta: import('@codexo/exojs').Time): void {
|
|
58
|
-
this.box.rotation += delta.seconds * 45;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public override draw(backend: RenderBackend): void {
|
|
62
|
-
this.root.render(backend);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const canvas = document.querySelector('canvas');
|
|
67
|
-
|
|
68
|
-
if (!canvas) {
|
|
69
|
-
throw new Error('Missing <canvas> element.');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const app = new Application({
|
|
73
|
-
canvas,
|
|
74
|
-
width: 800,
|
|
75
|
-
height: 600,
|
|
76
|
-
clearColor: Color.cornflowerBlue,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
await app.start(new HelloScene());
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Next Steps
|
|
83
|
-
|
|
84
|
-
- In-repo examples: [examples/README.md](examples/README.md)
|
|
85
|
-
|
|
86
|
-
## WebGPU and WebGL2
|
|
87
|
-
|
|
88
|
-
`Application` defaults to backend auto-selection:
|
|
89
|
-
|
|
90
|
-
- prefers WebGPU when available
|
|
91
|
-
- falls back to WebGL2 if WebGPU is unavailable or initialization fails
|
|
92
|
-
|
|
93
|
-
You can force backend selection when needed:
|
|
94
|
-
|
|
95
|
-
```ts
|
|
96
|
-
new Application({ backend: { type: 'webgpu' } });
|
|
97
|
-
new Application({ backend: { type: 'webgl2' } });
|
|
98
|
-
new Application({ backend: { type: 'auto' } });
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Optional Rapier Physics
|
|
102
|
-
|
|
103
|
-
Rapier integration is opt-in and loaded only when you use it.
|
|
104
|
-
|
|
105
|
-
```ts
|
|
106
|
-
import { createRapierPhysicsWorld } from '@codexo/exojs';
|
|
107
|
-
|
|
108
|
-
const physics = await createRapierPhysicsWorld({ gravityY: 9.81 });
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
If Rapier is unavailable, creation fails with a clear setup error.
|
|
112
|
-
|
|
113
|
-
### Physics scope policy
|
|
114
|
-
|
|
115
|
-
ExoJS ships **one** physics adapter: Rapier. The integration is intentionally
|
|
116
|
-
narrow:
|
|
117
|
-
|
|
118
|
-
- Physics is **optional**. `@dimforge/rapier2d-compat` is a peer dependency
|
|
119
|
-
marked `optional`. Apps that do not call `createRapierPhysicsWorld` never
|
|
120
|
-
load it and never pay for it at runtime.
|
|
121
|
-
- Rendering, application, and core scene code **do not** depend on physics.
|
|
122
|
-
The adapter binds Rapier bodies to scene nodes from the outside; the core
|
|
123
|
-
has no knowledge of physics.
|
|
124
|
-
- ExoJS is **not** a physics-engine abstraction layer. There is no
|
|
125
|
-
`PhysicsWorld` interface that spans multiple backends, and no plan to
|
|
126
|
-
add one. If you need a different physics library, integrate it directly
|
|
127
|
-
in your app code without library involvement.
|
|
128
|
-
- A second physics adapter (Box2D, Matter.js, Planck, etc.) is **not** on
|
|
129
|
-
the 1.0 roadmap and will not be accepted as a contribution. The honesty
|
|
130
|
-
rule that applies to rendering backends applies here too: one chosen
|
|
131
|
-
physics, not a fake-universal physics layer.
|
|
132
|
-
|
|
133
|
-
For full integration details see [docs/physics/rapier-integration.md](docs/physics/rapier-integration.md).
|
|
134
|
-
|
|
135
|
-
## Examples
|
|
136
|
-
|
|
137
|
-
The runnable live site (Astro + Lit + Monaco preview) lives in [`examples/`](examples/README.md) and is deployed as the repository's GitHub Pages site at <https://exoridus.github.io/ExoJS/>.
|
|
138
|
-
|
|
139
|
-
## Development
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
npm run typecheck
|
|
143
|
-
npm run lint
|
|
144
|
-
npm test
|
|
145
|
-
npm run build
|
|
146
|
-
npm run verify:package
|
|
147
|
-
npm run perf:benchmark
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
Internal imports use the `@/*` path alias (mapped to `src/*`) — the same convention used by Vite, Next.js, and other modern TypeScript setups. Building the library requires TypeScript 6.
|
|
151
|
-
|
|
152
|
-
## Links
|
|
153
|
-
|
|
154
|
-
- Repository: <https://github.com/Exoridus/ExoJS>
|
|
155
|
-
- Issues: <https://github.com/Exoridus/ExoJS/issues>
|
|
156
|
-
- Changelog: [CHANGELOG.md](CHANGELOG.md)
|
|
1
|
+
# ExoJS
|
|
2
|
+
|
|
3
|
+
ExoJS is a TypeScript-first 2D runtime for browser games and interactive apps. It is designed around explicit scene flow, practical rendering features, and predictable runtime behavior.
|
|
4
|
+
|
|
5
|
+
## Project status
|
|
6
|
+
|
|
7
|
+
ExoJS is **pre-1.0**. The public API is still under active design — scene graph, rendering pipeline, and resource lifecycle boundaries may change between minor versions. Pin exact versions in downstream experiments. `1.0.0` will mark the first stable API contract.
|
|
8
|
+
|
|
9
|
+
## Why ExoJS
|
|
10
|
+
|
|
11
|
+
- TypeScript-first API surface with strong runtime contracts
|
|
12
|
+
- Scene and asset workflows built for real game loops
|
|
13
|
+
- Modern rendering stack: WebGPU-first with WebGL2 fallback
|
|
14
|
+
- Practical visuals: filters, masks, render passes, cache-as-bitmap
|
|
15
|
+
- Gameplay tools: animated sprites, scene stacking, camera helpers, audio sprites
|
|
16
|
+
- Performance visibility with built-in render stats and benchmark harness
|
|
17
|
+
- Optional Rapier physics integration without forcing physics on every app
|
|
18
|
+
|
|
19
|
+
## What Is Shipped Today
|
|
20
|
+
|
|
21
|
+
- `Application`, `Scene`, and scene-manager lifecycle
|
|
22
|
+
- Typed `Loader` with manifest/bundle workflow (`defineAssetManifest`, `registerManifest`, `loadBundle`)
|
|
23
|
+
- Drawables: `Sprite`, `AnimatedSprite`, `Graphics`, `ParticleSystem`, `Text`, `Video`
|
|
24
|
+
- Scene stacking (`overlay` / `modal` / `opaque`) with input routing and fade transitions
|
|
25
|
+
- View/camera helpers (`follow`, bounds clamp, shake, zoom)
|
|
26
|
+
- Rendering composition primitives (`RenderTexture`, `RenderTargetPass`, filter chains, visual masks, cache-as-bitmap)
|
|
27
|
+
- Render stats (`submittedNodes`, `culledNodes`, `drawCalls`, `batches`, `renderPasses`, ...)
|
|
28
|
+
- Optional Rapier adapter (`createRapierPhysicsWorld`)
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @codexo/exojs
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
ExoJS currently publishes an ESM-first package shape. Use `import` syntax with modern bundlers/runtime tooling.
|
|
37
|
+
CommonJS `require()` usage is not part of the supported contract for this pre-1.0 line.
|
|
38
|
+
|
|
39
|
+
## Quickstart
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { Application, Scene, Graphics, Color, type RenderBackend } from '@codexo/exojs';
|
|
43
|
+
|
|
44
|
+
class HelloScene extends Scene {
|
|
45
|
+
private readonly box = new Graphics();
|
|
46
|
+
|
|
47
|
+
public constructor() {
|
|
48
|
+
super();
|
|
49
|
+
|
|
50
|
+
this.box.fillColor = Color.white;
|
|
51
|
+
this.box.drawRectangle(-32, -32, 64, 64);
|
|
52
|
+
this.box.setPosition(400, 300);
|
|
53
|
+
|
|
54
|
+
this.addChild(this.box);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public override update(delta: import('@codexo/exojs').Time): void {
|
|
58
|
+
this.box.rotation += delta.seconds * 45;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public override draw(backend: RenderBackend): void {
|
|
62
|
+
this.root.render(backend);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const canvas = document.querySelector('canvas');
|
|
67
|
+
|
|
68
|
+
if (!canvas) {
|
|
69
|
+
throw new Error('Missing <canvas> element.');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const app = new Application({
|
|
73
|
+
canvas,
|
|
74
|
+
width: 800,
|
|
75
|
+
height: 600,
|
|
76
|
+
clearColor: Color.cornflowerBlue,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
await app.start(new HelloScene());
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Next Steps
|
|
83
|
+
|
|
84
|
+
- In-repo examples: [examples/README.md](examples/README.md)
|
|
85
|
+
|
|
86
|
+
## WebGPU and WebGL2
|
|
87
|
+
|
|
88
|
+
`Application` defaults to backend auto-selection:
|
|
89
|
+
|
|
90
|
+
- prefers WebGPU when available
|
|
91
|
+
- falls back to WebGL2 if WebGPU is unavailable or initialization fails
|
|
92
|
+
|
|
93
|
+
You can force backend selection when needed:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
new Application({ backend: { type: 'webgpu' } });
|
|
97
|
+
new Application({ backend: { type: 'webgl2' } });
|
|
98
|
+
new Application({ backend: { type: 'auto' } });
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Optional Rapier Physics
|
|
102
|
+
|
|
103
|
+
Rapier integration is opt-in and loaded only when you use it.
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { createRapierPhysicsWorld } from '@codexo/exojs';
|
|
107
|
+
|
|
108
|
+
const physics = await createRapierPhysicsWorld({ gravityY: 9.81 });
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
If Rapier is unavailable, creation fails with a clear setup error.
|
|
112
|
+
|
|
113
|
+
### Physics scope policy
|
|
114
|
+
|
|
115
|
+
ExoJS ships **one** physics adapter: Rapier. The integration is intentionally
|
|
116
|
+
narrow:
|
|
117
|
+
|
|
118
|
+
- Physics is **optional**. `@dimforge/rapier2d-compat` is a peer dependency
|
|
119
|
+
marked `optional`. Apps that do not call `createRapierPhysicsWorld` never
|
|
120
|
+
load it and never pay for it at runtime.
|
|
121
|
+
- Rendering, application, and core scene code **do not** depend on physics.
|
|
122
|
+
The adapter binds Rapier bodies to scene nodes from the outside; the core
|
|
123
|
+
has no knowledge of physics.
|
|
124
|
+
- ExoJS is **not** a physics-engine abstraction layer. There is no
|
|
125
|
+
`PhysicsWorld` interface that spans multiple backends, and no plan to
|
|
126
|
+
add one. If you need a different physics library, integrate it directly
|
|
127
|
+
in your app code without library involvement.
|
|
128
|
+
- A second physics adapter (Box2D, Matter.js, Planck, etc.) is **not** on
|
|
129
|
+
the 1.0 roadmap and will not be accepted as a contribution. The honesty
|
|
130
|
+
rule that applies to rendering backends applies here too: one chosen
|
|
131
|
+
physics, not a fake-universal physics layer.
|
|
132
|
+
|
|
133
|
+
For full integration details see [docs/physics/rapier-integration.md](docs/physics/rapier-integration.md).
|
|
134
|
+
|
|
135
|
+
## Examples
|
|
136
|
+
|
|
137
|
+
The runnable live site (Astro + Lit + Monaco preview) lives in [`examples/`](examples/README.md) and is deployed as the repository's GitHub Pages site at <https://exoridus.github.io/ExoJS/>.
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npm run typecheck
|
|
143
|
+
npm run lint
|
|
144
|
+
npm test
|
|
145
|
+
npm run build
|
|
146
|
+
npm run verify:package
|
|
147
|
+
npm run perf:benchmark
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Internal imports use the `@/*` path alias (mapped to `src/*`) — the same convention used by Vite, Next.js, and other modern TypeScript setups. Building the library requires TypeScript 6.
|
|
151
|
+
|
|
152
|
+
## Links
|
|
153
|
+
|
|
154
|
+
- Repository: <https://github.com/Exoridus/ExoJS>
|
|
155
|
+
- Issues: <https://github.com/Exoridus/ExoJS/issues>
|
|
156
|
+
- Changelog: [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Capabilities } from './capabilities';
|
|
1
2
|
import { SceneManager } from './SceneManager';
|
|
2
3
|
import { InputManager } from '@/input/InputManager';
|
|
3
4
|
import { Loader } from '@/resources/Loader';
|
|
@@ -57,6 +58,7 @@ export declare class Application {
|
|
|
57
58
|
private _frameRequest;
|
|
58
59
|
private _backendType;
|
|
59
60
|
private _backend;
|
|
61
|
+
private _capabilities;
|
|
60
62
|
constructor(appSettings?: Partial<ApplicationOptions>);
|
|
61
63
|
get status(): ApplicationStatus;
|
|
62
64
|
get startupTime(): Time;
|
|
@@ -64,6 +66,12 @@ export declare class Application {
|
|
|
64
66
|
get frameTime(): Time;
|
|
65
67
|
get frameCount(): number;
|
|
66
68
|
get backend(): RenderBackend;
|
|
69
|
+
/**
|
|
70
|
+
* Resolved capabilities for the host browser. Available after
|
|
71
|
+
* {@link Application.start} resolves; reading before that throws.
|
|
72
|
+
* For pre-start access use {@link Capabilities.ready} directly.
|
|
73
|
+
*/
|
|
74
|
+
get capabilities(): Capabilities;
|
|
67
75
|
start(scene: Scene): Promise<this>;
|
|
68
76
|
update(): this;
|
|
69
77
|
stop(): this;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Capabilities } from './capabilities.js';
|
|
1
2
|
import { Clock } from './Clock.js';
|
|
2
3
|
import { SceneManager } from './SceneManager.js';
|
|
3
4
|
import { WebGl2Backend } from '../rendering/webgl2/WebGl2Backend.js';
|
|
@@ -59,6 +60,7 @@ class Application {
|
|
|
59
60
|
_frameRequest = 0;
|
|
60
61
|
_backendType;
|
|
61
62
|
_backend;
|
|
63
|
+
_capabilities = null;
|
|
62
64
|
constructor(appSettings) {
|
|
63
65
|
this.options = {
|
|
64
66
|
canvas: appSettings?.canvas ?? createDefaultCanvas(),
|
|
@@ -100,11 +102,26 @@ class Application {
|
|
|
100
102
|
get backend() {
|
|
101
103
|
return this._backend;
|
|
102
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Resolved capabilities for the host browser. Available after
|
|
107
|
+
* {@link Application.start} resolves; reading before that throws.
|
|
108
|
+
* For pre-start access use {@link Capabilities.ready} directly.
|
|
109
|
+
*/
|
|
110
|
+
get capabilities() {
|
|
111
|
+
if (this._capabilities === null) {
|
|
112
|
+
throw new Error('Application.capabilities is unavailable before start() resolves. Use `await Capabilities.ready` for pre-start checks.');
|
|
113
|
+
}
|
|
114
|
+
return this._capabilities;
|
|
115
|
+
}
|
|
103
116
|
async start(scene) {
|
|
104
117
|
if (this._status === ApplicationStatus.Stopped) {
|
|
105
118
|
this._status = ApplicationStatus.Loading;
|
|
119
|
+
// Kick off capability detection in parallel with renderer init —
|
|
120
|
+
// both are mostly-async startup work, no point serializing them.
|
|
121
|
+
const capabilitiesPromise = Capabilities.ready;
|
|
106
122
|
try {
|
|
107
123
|
await this.initializeRenderManager();
|
|
124
|
+
this._capabilities = await capabilitiesPromise;
|
|
108
125
|
await this.sceneManager.setScene(scene);
|
|
109
126
|
this._frameRequest = requestAnimationFrame(this._updateHandler);
|
|
110
127
|
this._frameClock.restart();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Application.js","sources":["../../../../src/core/Application.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Application.js","sources":["../../../../src/core/Application.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export declare class Capabilities {
|
|
2
|
+
private static _readyPromise;
|
|
3
|
+
/**
|
|
4
|
+
* Lazy-cached Promise that resolves to a frozen Capabilities instance.
|
|
5
|
+
*
|
|
6
|
+
* The first read kicks off the async probes (currently just the WebGPU
|
|
7
|
+
* adapter request); every subsequent read returns the same Promise.
|
|
8
|
+
* Concurrent callers share the in-flight detection — no double work.
|
|
9
|
+
*
|
|
10
|
+
* Early-warmup pattern for callers who want to overlap detection with
|
|
11
|
+
* other startup work:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* void Capabilities.ready; // fire-and-forget; starts probes now
|
|
15
|
+
* // ... unrelated bootstrap ...
|
|
16
|
+
* const caps = await Capabilities.ready; // typically already resolved
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
static get ready(): Promise<Capabilities>;
|
|
20
|
+
readonly webgl2: boolean;
|
|
21
|
+
readonly webgpu: boolean;
|
|
22
|
+
readonly webgpuAdapter: GPUAdapter | null;
|
|
23
|
+
readonly webgpuVendor: string | null;
|
|
24
|
+
readonly webgpuArchitecture: string | null;
|
|
25
|
+
readonly pointer: boolean;
|
|
26
|
+
readonly keyboard: boolean;
|
|
27
|
+
readonly gamepad: boolean;
|
|
28
|
+
readonly touch: boolean;
|
|
29
|
+
readonly maxTouchPoints: number;
|
|
30
|
+
readonly audio: boolean;
|
|
31
|
+
readonly fullscreen: boolean;
|
|
32
|
+
readonly vibration: boolean;
|
|
33
|
+
readonly offscreenCanvas: boolean;
|
|
34
|
+
readonly webWorkers: boolean;
|
|
35
|
+
readonly devicePixelRatio: number;
|
|
36
|
+
private constructor();
|
|
37
|
+
private static _detect;
|
|
38
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/// <reference types="@webgpu/types" />
|
|
2
|
+
// Browser-environment feature detection. Construction is private; the
|
|
3
|
+
// only public entry is `Capabilities.ready`, a lazy-cached `Promise<Capabilities>`
|
|
4
|
+
// that fires the (mostly) async probes on first access and returns the
|
|
5
|
+
// same Promise for every subsequent call. Once it resolves, the returned
|
|
6
|
+
// instance is frozen — every property is read once and never mutates.
|
|
7
|
+
//
|
|
8
|
+
// Synchronous callsites should keep the resolved instance in scope (e.g.,
|
|
9
|
+
// `app.capabilities` after `await app.start(...)`); there is no global
|
|
10
|
+
// sync mirror, by design.
|
|
11
|
+
const hasWindow = typeof window !== 'undefined';
|
|
12
|
+
const hasDocument = typeof document !== 'undefined';
|
|
13
|
+
const hasNavigator = typeof navigator !== 'undefined';
|
|
14
|
+
class Capabilities {
|
|
15
|
+
static _readyPromise = null;
|
|
16
|
+
/**
|
|
17
|
+
* Lazy-cached Promise that resolves to a frozen Capabilities instance.
|
|
18
|
+
*
|
|
19
|
+
* The first read kicks off the async probes (currently just the WebGPU
|
|
20
|
+
* adapter request); every subsequent read returns the same Promise.
|
|
21
|
+
* Concurrent callers share the in-flight detection — no double work.
|
|
22
|
+
*
|
|
23
|
+
* Early-warmup pattern for callers who want to overlap detection with
|
|
24
|
+
* other startup work:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* void Capabilities.ready; // fire-and-forget; starts probes now
|
|
28
|
+
* // ... unrelated bootstrap ...
|
|
29
|
+
* const caps = await Capabilities.ready; // typically already resolved
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
static get ready() {
|
|
33
|
+
if (Capabilities._readyPromise === null) {
|
|
34
|
+
Capabilities._readyPromise = Capabilities._detect();
|
|
35
|
+
}
|
|
36
|
+
return Capabilities._readyPromise;
|
|
37
|
+
}
|
|
38
|
+
webgl2;
|
|
39
|
+
webgpu;
|
|
40
|
+
webgpuAdapter;
|
|
41
|
+
webgpuVendor;
|
|
42
|
+
webgpuArchitecture;
|
|
43
|
+
pointer;
|
|
44
|
+
keyboard;
|
|
45
|
+
gamepad;
|
|
46
|
+
touch;
|
|
47
|
+
maxTouchPoints;
|
|
48
|
+
audio;
|
|
49
|
+
fullscreen;
|
|
50
|
+
vibration;
|
|
51
|
+
offscreenCanvas;
|
|
52
|
+
webWorkers;
|
|
53
|
+
devicePixelRatio;
|
|
54
|
+
constructor(values) {
|
|
55
|
+
this.webgl2 = values.webgl2;
|
|
56
|
+
this.webgpu = values.webgpu;
|
|
57
|
+
this.webgpuAdapter = values.webgpuAdapter;
|
|
58
|
+
this.webgpuVendor = values.webgpuVendor;
|
|
59
|
+
this.webgpuArchitecture = values.webgpuArchitecture;
|
|
60
|
+
this.pointer = values.pointer;
|
|
61
|
+
this.keyboard = values.keyboard;
|
|
62
|
+
this.gamepad = values.gamepad;
|
|
63
|
+
this.touch = values.touch;
|
|
64
|
+
this.maxTouchPoints = values.maxTouchPoints;
|
|
65
|
+
this.audio = values.audio;
|
|
66
|
+
this.fullscreen = values.fullscreen;
|
|
67
|
+
this.vibration = values.vibration;
|
|
68
|
+
this.offscreenCanvas = values.offscreenCanvas;
|
|
69
|
+
this.webWorkers = values.webWorkers;
|
|
70
|
+
this.devicePixelRatio = values.devicePixelRatio;
|
|
71
|
+
Object.freeze(this);
|
|
72
|
+
}
|
|
73
|
+
static async _detect() {
|
|
74
|
+
const [webgpuAdapter, webgpuInfo] = await probeWebGpu();
|
|
75
|
+
return new Capabilities({
|
|
76
|
+
webgl2: probeWebGl2(),
|
|
77
|
+
webgpu: probeWebGpuApiSurface(),
|
|
78
|
+
webgpuAdapter,
|
|
79
|
+
webgpuVendor: webgpuInfo?.vendor ?? null,
|
|
80
|
+
webgpuArchitecture: webgpuInfo?.architecture ?? null,
|
|
81
|
+
pointer: probePointer(),
|
|
82
|
+
keyboard: probeKeyboard(),
|
|
83
|
+
gamepad: probeGamepad(),
|
|
84
|
+
touch: probeTouchSupported(),
|
|
85
|
+
maxTouchPoints: probeMaxTouchPoints(),
|
|
86
|
+
audio: probeAudio(),
|
|
87
|
+
fullscreen: probeFullscreen(),
|
|
88
|
+
vibration: probeVibration(),
|
|
89
|
+
offscreenCanvas: probeOffscreenCanvas(),
|
|
90
|
+
webWorkers: probeWebWorkers(),
|
|
91
|
+
devicePixelRatio: hasWindow ? window.devicePixelRatio : 1,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// --- probes ---------------------------------------------------------------
|
|
96
|
+
function probeWebGl2() {
|
|
97
|
+
if (!hasDocument)
|
|
98
|
+
return false;
|
|
99
|
+
try {
|
|
100
|
+
const canvas = document.createElement('canvas');
|
|
101
|
+
const gl = canvas.getContext('webgl2');
|
|
102
|
+
return gl !== null;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function probeWebGpuApiSurface() {
|
|
109
|
+
return hasNavigator && 'gpu' in navigator;
|
|
110
|
+
}
|
|
111
|
+
async function probeWebGpu() {
|
|
112
|
+
if (!probeWebGpuApiSurface())
|
|
113
|
+
return [null, null];
|
|
114
|
+
const gpu = navigator.gpu;
|
|
115
|
+
if (!gpu || typeof gpu.requestAdapter !== 'function')
|
|
116
|
+
return [null, null];
|
|
117
|
+
try {
|
|
118
|
+
const adapter = await gpu.requestAdapter();
|
|
119
|
+
if (!adapter)
|
|
120
|
+
return [null, null];
|
|
121
|
+
// Modern path: GPUAdapter.info is a sync property (Chrome 116+,
|
|
122
|
+
// Safari 18+). Older browsers exposed a deprecated async
|
|
123
|
+
// requestAdapterInfo() instead. Try the modern path first, fall
|
|
124
|
+
// back if needed.
|
|
125
|
+
const adapterAny = adapter;
|
|
126
|
+
if (adapterAny.info) {
|
|
127
|
+
return [adapter, adapterAny.info];
|
|
128
|
+
}
|
|
129
|
+
if (typeof adapterAny.requestAdapterInfo === 'function') {
|
|
130
|
+
try {
|
|
131
|
+
return [adapter, await adapterAny.requestAdapterInfo()];
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return [adapter, null];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return [adapter, null];
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return [null, null];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function probePointer() {
|
|
144
|
+
return hasWindow && 'PointerEvent' in window;
|
|
145
|
+
}
|
|
146
|
+
function probeKeyboard() {
|
|
147
|
+
return hasWindow && 'KeyboardEvent' in window;
|
|
148
|
+
}
|
|
149
|
+
function probeGamepad() {
|
|
150
|
+
return hasNavigator && typeof navigator.getGamepads === 'function';
|
|
151
|
+
}
|
|
152
|
+
function probeTouchSupported() {
|
|
153
|
+
if (!hasWindow)
|
|
154
|
+
return false;
|
|
155
|
+
if ('ontouchstart' in window)
|
|
156
|
+
return true;
|
|
157
|
+
if (probeMaxTouchPoints() > 0)
|
|
158
|
+
return true;
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
function probeMaxTouchPoints() {
|
|
162
|
+
if (!hasNavigator)
|
|
163
|
+
return 0;
|
|
164
|
+
const points = navigator.maxTouchPoints;
|
|
165
|
+
return typeof points === 'number' ? points : 0;
|
|
166
|
+
}
|
|
167
|
+
function probeAudio() {
|
|
168
|
+
if (!hasWindow)
|
|
169
|
+
return false;
|
|
170
|
+
const w = window;
|
|
171
|
+
return typeof w.AudioContext !== 'undefined' || typeof w.webkitAudioContext !== 'undefined';
|
|
172
|
+
}
|
|
173
|
+
function probeFullscreen() {
|
|
174
|
+
if (!hasDocument)
|
|
175
|
+
return false;
|
|
176
|
+
const el = document.documentElement;
|
|
177
|
+
return typeof el.requestFullscreen === 'function' || typeof el.webkitRequestFullscreen === 'function';
|
|
178
|
+
}
|
|
179
|
+
function probeVibration() {
|
|
180
|
+
return hasNavigator && typeof navigator.vibrate === 'function';
|
|
181
|
+
}
|
|
182
|
+
function probeOffscreenCanvas() {
|
|
183
|
+
// The browser global is verbatim `OffscreenCanvas`; eslint's
|
|
184
|
+
// strict-camelCase rule rejects the property name even though we
|
|
185
|
+
// can't rename a web standard.
|
|
186
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
187
|
+
return hasWindow && typeof window.OffscreenCanvas !== 'undefined';
|
|
188
|
+
}
|
|
189
|
+
function probeWebWorkers() {
|
|
190
|
+
// The browser global is verbatim `Worker`; eslint's strict-camelCase
|
|
191
|
+
// rule rejects the property name even though we can't rename a web
|
|
192
|
+
// standard.
|
|
193
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
194
|
+
return hasWindow && typeof window.Worker === 'function';
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export { Capabilities };
|
|
198
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sources":["../../../../src/core/capabilities.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/dist/esm/core/index.d.ts
CHANGED