@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.
Files changed (30) hide show
  1. package/CHANGELOG.md +585 -499
  2. package/README.md +156 -156
  3. package/dist/esm/core/Application.d.ts +8 -0
  4. package/dist/esm/core/Application.js +17 -0
  5. package/dist/esm/core/Application.js.map +1 -1
  6. package/dist/esm/core/capabilities.d.ts +38 -0
  7. package/dist/esm/core/capabilities.js +198 -0
  8. package/dist/esm/core/capabilities.js.map +1 -0
  9. package/dist/esm/core/index.d.ts +1 -0
  10. package/dist/esm/index.js +1 -0
  11. package/dist/esm/index.js.map +1 -1
  12. package/dist/esm/rendering/webgl2/glsl/mask-compose.frag.js +1 -1
  13. package/dist/esm/rendering/webgl2/glsl/mask-compose.vert.js +1 -1
  14. package/dist/esm/rendering/webgl2/glsl/particle.frag.js +1 -1
  15. package/dist/esm/rendering/webgl2/glsl/primitive.frag.js +1 -1
  16. package/dist/esm/rendering/webgl2/glsl/primitive.vert.js +1 -1
  17. package/dist/esm/rendering/webgl2/glsl/sprite.frag.js +1 -1
  18. package/dist/esm/rendering/webgpu/WebGpuBackend.js +41 -41
  19. package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
  20. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js +44 -44
  21. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js.map +1 -1
  22. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js +65 -65
  23. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js.map +1 -1
  24. package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.js +25 -25
  25. package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.js.map +1 -1
  26. package/dist/esm/vendor/webgl-debug.js +1156 -1156
  27. package/dist/esm/vendor/webgl-debug.js.map +1 -1
  28. package/dist/exo.esm.js +1550 -1338
  29. package/dist/exo.esm.js.map +1 -1
  30. 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":"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"}
1
+ {"version":3,"file":"Application.js","sources":["../../../../src/core/Application.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;IAeY;AAAZ,CAAA,UAAY,iBAAiB,EAAA;AACzB,IAAA,iBAAA,CAAA,iBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AACX,IAAA,iBAAA,CAAA,iBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AACX,IAAA,iBAAA,CAAA,iBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AACX,IAAA,iBAAA,CAAA,iBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AACf,CAAC,EALW,iBAAiB,KAAjB,iBAAiB,GAAA,EAAA,CAAA,CAAA;AAyC7B,MAAM,mBAAmB,GAAG,MAAyB,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAsB;AAC1G,MAAM,oBAAoB,GAAsB,EAAE,IAAI,EAAE,MAAM,EAAE;AAEhE,MAAM,kBAAkB,GAA8B;AAClD,IAAA,KAAK,EAAE,GAAG;AACV,IAAA,MAAM,EAAE,GAAG;IACX,UAAU,EAAE,KAAK,CAAC,cAAc;AAChC,IAAA,KAAK,EAAE,KAAK;IACZ,uBAAuB,EAAE,IAAI;IAC7B,yBAAyB,EAAE,IAAI;IAC/B,0BAA0B,EAAE,KAAK;AACjC,IAAA,kBAAkB,EAAE,EAAE;AACtB,IAAA,wBAAwB,EAAE,EAAE;AAC5B,IAAA,eAAe,EAAE;AACb,QAAA,KAAK,EAAE,KAAK;AACZ,QAAA,SAAS,EAAE,KAAK;AAChB,QAAA,kBAAkB,EAAE,KAAK;AACzB,QAAA,qBAAqB,EAAE,KAAK;AAC5B,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,KAAK,EAAE,KAAK;AACf,KAAA;AACD,IAAA,YAAY,EAAE,EAAE;AAChB,IAAA,cAAc,EAAE;AACZ,QAAA,MAAM,EAAE,KAAK;AACb,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,KAAK,EAAE,SAAS;AACnB,KAAA;AACD,IAAA,KAAK,EAAE,SAAS;AAChB,IAAA,OAAO,EAAE,oBAAoB;CAChC;MAEY,WAAW,CAAA;AACJ,IAAA,OAAO;AACP,IAAA,MAAM;AACN,IAAA,MAAM;AACN,IAAA,YAAY;AACZ,IAAA,YAAY;AACZ,IAAA,QAAQ,GAAG,IAAI,MAAM,EAAiC;AAErD,IAAA,cAAc;AACd,IAAA,aAAa,GAAU,IAAI,KAAK,EAAE;AAClC,IAAA,YAAY,GAAU,IAAI,KAAK,EAAE;AACjC,IAAA,WAAW,GAAU,IAAI,KAAK,EAAE;AAEzC,IAAA,OAAO,GAAsB,iBAAiB,CAAC,OAAO;IACtD,WAAW,GAAG,CAAC;IACf,aAAa,GAAG,CAAC;AACjB,IAAA,YAAY;AACZ,IAAA,QAAQ;IACR,aAAa,GAAwB,IAAI;AAEjD,IAAA,WAAA,CAAmB,WAAyC,EAAA;QACxD,IAAI,CAAC,OAAO,GAAG;AACX,YAAA,MAAM,EAAE,WAAW,EAAE,MAAM,IAAI,mBAAmB,EAAE;AACpD,YAAA,GAAG,kBAAkB;AACrB,YAAA,GAAG,WAAW;AACd,YAAA,OAAO,EAAE,WAAW,EAAE,OAAO,IAAI,oBAAoB;SACxD;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM;QAEjC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE;YACvC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC;QAC9C;AAEA,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC;AACrB,YAAA,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY;AACvC,YAAA,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc;AAC3C,YAAA,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;AAC5B,SAAA,CAAC;AACF,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,yBAAyB,EAAE;QACpD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC;QACrD,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC;QAC1C,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC;QAC1C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAE5C,QAAA,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;IAC9B;AAEA,IAAA,IAAW,MAAM,GAAA;QACb,OAAO,IAAI,CAAC,OAAO;IACvB;AAEA,IAAA,IAAW,WAAW,GAAA;AAClB,QAAA,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW;IACzC;AAEA,IAAA,IAAW,UAAU,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW;IACxC;AAEA,IAAA,IAAW,SAAS,GAAA;AAChB,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW;IACvC;AAEA,IAAA,IAAW,UAAU,GAAA;QACjB,OAAO,IAAI,CAAC,WAAW;IAC3B;AAEA,IAAA,IAAW,OAAO,GAAA;QACd,OAAO,IAAI,CAAC,QAAQ;IACxB;AAEA;;;;AAIG;AACH,IAAA,IAAW,YAAY,GAAA;AACnB,QAAA,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,EAAE;AAC7B,YAAA,MAAM,IAAI,KAAK,CAAC,uHAAuH,CAAC;QAC5I;QAEA,OAAO,IAAI,CAAC,aAAa;IAC7B;IAEO,MAAM,KAAK,CAAC,KAAY,EAAA;QAC3B,IAAI,IAAI,CAAC,OAAO,KAAK,iBAAiB,CAAC,OAAO,EAAE;AAC5C,YAAA,IAAI,CAAC,OAAO,GAAG,iBAAiB,CAAC,OAAO;;;AAIxC,YAAA,MAAM,mBAAmB,GAAG,YAAY,CAAC,KAAK;AAE9C,YAAA,IAAI;AACA,gBAAA,MAAM,IAAI,CAAC,uBAAuB,EAAE;AACpC,gBAAA,IAAI,CAAC,aAAa,GAAG,MAAM,mBAAmB;gBAC9C,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvC,IAAI,CAAC,aAAa,GAAG,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC;AAC/D,gBAAA,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;AAC1B,gBAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE;AACzB,gBAAA,IAAI,CAAC,OAAO,GAAG,iBAAiB,CAAC,OAAO;YAC5C;YAAE,OAAO,KAAK,EAAE;AACZ,gBAAA,IAAI,CAAC,OAAO,GAAG,iBAAiB,CAAC,OAAO;AACxC,gBAAA,MAAM,KAAK;YACf;QACJ;AAEA,QAAA,OAAO,IAAI;IACf;IAEO,MAAM,GAAA;QACT,IAAI,IAAI,CAAC,OAAO,KAAK,iBAAiB,CAAC,OAAO,EAAE;AAC5C,YAAA,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW;AAC/C,YAAA,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;AAEpC,YAAA,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;AAEzB,YAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;AAC1B,YAAA,MAAM,WAAW,GAAI,IAAI,CAAC,OAEvB,CAAC,IAAI;YAER,IAAI,WAAW,IAAI,OAAO,WAAW,CAAC,MAAM,KAAK,UAAU,EAAE;AACzD,gBAAA,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC;YAC/C;AAEA,YAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC;AACpC,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;AACpB,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,UAAU;YAC/D,IAAI,CAAC,aAAa,GAAG,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC;AAC/D,YAAA,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;YAC1B,IAAI,CAAC,WAAW,EAAE;QACtB;AAEA,QAAA,OAAO,IAAI;IACf;IAEO,IAAI,GAAA;QACP,IAAI,IAAI,CAAC,OAAO,KAAK,iBAAiB,CAAC,OAAO,EAAE;AAC5C,YAAA,IAAI,CAAC,OAAO,GAAG,iBAAiB,CAAC,OAAO;AACxC,YAAA,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC;AACxC,YAAA,KAAK,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,KAAI;AAC3D,gBAAA,OAAO,CAAC,KAAK,CAAC,uDAAuD,EAAE,KAAK,CAAC;AACjF,YAAA,CAAC,CAAC;AACF,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;AACxB,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;AACvB,YAAA,IAAI,CAAC,OAAO,GAAG,iBAAiB,CAAC,OAAO;QAC5C;AAEA,QAAA,OAAO,IAAI;IACf;IAEO,MAAM,CAAC,KAAa,EAAE,MAAc,EAAA;QACvC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC;AAE3C,QAAA,OAAO,IAAI;IACf;IAEO,OAAO,GAAA;QACV,IAAI,CAAC,IAAI,EAAE;AACX,QAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AACrB,QAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AAC3B,QAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;AACvB,QAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AAC3B,QAAA,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE;AAC5B,QAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;AAC3B,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;AAC1B,QAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;IAC3B;IAEQ,yBAAyB,GAAA;QAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI;AAE9C,QAAA,IAAI,WAAW,KAAK,QAAQ,EAAE;AAC1B,YAAA,OAAO,QAAQ;QACnB;AAEA,QAAA,IAAI,WAAW,KAAK,QAAQ,EAAE;AAC1B,YAAA,OAAO,QAAQ;QACnB;AAEA,QAAA,OAAO,IAAI,CAAC,YAAY,EAAE,GAAG,QAAQ,GAAG,QAAQ;IACpD;AAEQ,IAAA,aAAa,CAAC,WAAgC,EAAA;AAClD,QAAA,IAAI,WAAW,KAAK,QAAQ,EAAE;AAC1B,YAAA,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC;QAClC;AAEA,QAAA,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC;IAClC;AAEQ,IAAA,MAAM,uBAAuB,GAAA;AACjC,QAAA,IAAI;AACA,YAAA,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE;QACpC;QAAE,OAAO,KAAK,EAAE;AACZ,YAAA,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE;AACzE,gBAAA,MAAM,KAAK;YACf;AAEA,YAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;AACvB,YAAA,IAAI,CAAC,YAAY,GAAG,QAAQ;YAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC;AACrD,YAAA,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE;QACpC;IACJ;IAEQ,YAAY,GAAA;QAChB,MAAM,YAAY,GAAG,SAA+C;AAEpE,QAAA,OAAO,CAAC,CAAC,YAAY,CAAC,GAAG;IAC7B;AACH;;;;"}
@@ -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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"}
@@ -2,6 +2,7 @@ export * from './types';
2
2
  export * from './utils';
3
3
  export * from './Application';
4
4
  export * from './Bounds';
5
+ export * from './capabilities';
5
6
  export * from './Clock';
6
7
  export * from './Color';
7
8
  export * from './Quadtree';