@codexo/exojs 0.6.3 → 0.6.5
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 +156 -0
- package/dist/esm/core/Application.d.ts +8 -1
- package/dist/esm/core/Application.js +17 -1
- package/dist/esm/core/Application.js.map +1 -1
- package/dist/esm/core/SceneManager.js +11 -12
- package/dist/esm/core/SceneManager.js.map +1 -1
- package/dist/esm/core/capabilities.d.ts +30 -29
- package/dist/esm/core/capabilities.js +163 -61
- package/dist/esm/core/capabilities.js.map +1 -1
- package/dist/esm/index.js +1 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/math/geometry.d.ts +12 -8
- package/dist/esm/math/geometry.js +119 -72
- package/dist/esm/math/geometry.js.map +1 -1
- package/dist/esm/rendering/index.d.ts +0 -5
- package/dist/esm/rendering/primitives/Graphics.d.ts +3 -2
- package/dist/esm/rendering/primitives/Graphics.js +33 -25
- package/dist/esm/rendering/primitives/Graphics.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2Backend.js +1 -4
- package/dist/esm/rendering/webgl2/WebGl2Backend.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuBackend.js +0 -3
- package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js +1 -2
- package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js.map +1 -1
- package/dist/exo.esm.js +710 -1280
- package/dist/exo.esm.js.map +1 -1
- package/package.json +1 -1
- package/dist/esm/rendering/primitives/CircleGeometry.d.ts +0 -4
- package/dist/esm/rendering/primitives/CircleGeometry.js +0 -21
- package/dist/esm/rendering/primitives/CircleGeometry.js.map +0 -1
- package/dist/esm/rendering/primitives/DrawableShape.d.ts +0 -11
- package/dist/esm/rendering/primitives/DrawableShape.js +0 -21
- package/dist/esm/rendering/primitives/DrawableShape.js.map +0 -1
- package/dist/esm/rendering/primitives/Geometry.d.ts +0 -13
- package/dist/esm/rendering/primitives/Geometry.js +0 -16
- package/dist/esm/rendering/primitives/Geometry.js.map +0 -1
- package/dist/esm/rendering/webgl2/WebGl2PrimitiveRenderer.d.ts +0 -26
- package/dist/esm/rendering/webgl2/WebGl2PrimitiveRenderer.js +0 -222
- package/dist/esm/rendering/webgl2/WebGl2PrimitiveRenderer.js.map +0 -1
- package/dist/esm/rendering/webgl2/glsl/primitive.frag.js +0 -4
- package/dist/esm/rendering/webgl2/glsl/primitive.frag.js.map +0 -1
- package/dist/esm/rendering/webgl2/glsl/primitive.vert.js +0 -4
- package/dist/esm/rendering/webgl2/glsl/primitive.vert.js.map +0 -1
- package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.d.ts +0 -38
- package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.js +0 -488
- package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.js.map +0 -1
|
@@ -1,17 +1,99 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
//
|
|
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.
|
|
4
7
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// backend selection and the Loader respectively. `capabilities.webgpu`
|
|
9
|
-
// returning `true` only guarantees that the browser advertises WebGPU,
|
|
10
|
-
// not that an adapter request will succeed.
|
|
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
11
|
const hasWindow = typeof window !== 'undefined';
|
|
12
12
|
const hasDocument = typeof document !== 'undefined';
|
|
13
13
|
const hasNavigator = typeof navigator !== 'undefined';
|
|
14
|
-
|
|
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() {
|
|
15
97
|
if (!hasDocument)
|
|
16
98
|
return false;
|
|
17
99
|
try {
|
|
@@ -22,75 +104,95 @@ const probeWebGl2 = () => {
|
|
|
22
104
|
catch {
|
|
23
105
|
return false;
|
|
24
106
|
}
|
|
25
|
-
}
|
|
26
|
-
|
|
107
|
+
}
|
|
108
|
+
function probeWebGpuApiSurface() {
|
|
27
109
|
return hasNavigator && 'gpu' in navigator;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (!
|
|
31
|
-
return
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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() {
|
|
36
144
|
return hasWindow && 'PointerEvent' in window;
|
|
37
|
-
}
|
|
38
|
-
|
|
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() {
|
|
39
153
|
if (!hasWindow)
|
|
40
154
|
return false;
|
|
41
155
|
if ('ontouchstart' in window)
|
|
42
156
|
return true;
|
|
43
|
-
if (
|
|
157
|
+
if (probeMaxTouchPoints() > 0)
|
|
44
158
|
return true;
|
|
45
159
|
return false;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
|
|
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() {
|
|
54
174
|
if (!hasDocument)
|
|
55
175
|
return false;
|
|
56
176
|
const el = document.documentElement;
|
|
57
177
|
return typeof el.requestFullscreen === 'function' || typeof el.webkitRequestFullscreen === 'function';
|
|
58
|
-
}
|
|
59
|
-
|
|
178
|
+
}
|
|
179
|
+
function probeVibration() {
|
|
60
180
|
return hasNavigator && typeof navigator.vibrate === 'function';
|
|
61
|
-
}
|
|
62
|
-
|
|
181
|
+
}
|
|
182
|
+
function probeOffscreenCanvas() {
|
|
63
183
|
// The browser global is verbatim `OffscreenCanvas`; eslint's
|
|
64
184
|
// strict-camelCase rule rejects the property name even though we
|
|
65
185
|
// can't rename a web standard.
|
|
66
186
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
67
187
|
return hasWindow && typeof window.OffscreenCanvas !== 'undefined';
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
webgl2: probeWebGl2(),
|
|
76
|
-
webgpu: probeWebGpu(),
|
|
77
|
-
audio: probeAudio(),
|
|
78
|
-
pointer: probePointer(),
|
|
79
|
-
touch: probeTouch(),
|
|
80
|
-
gamepad: probeGamepad(),
|
|
81
|
-
keyboard: probeKeyboard(),
|
|
82
|
-
fullscreen: probeFullscreen(),
|
|
83
|
-
vibration: probeVibration(),
|
|
84
|
-
offscreenCanvas: probeOffscreenCanvas(),
|
|
85
|
-
});
|
|
86
|
-
/**
|
|
87
|
-
* Typed lookup over {@link capabilities}. Identical to
|
|
88
|
-
* `capabilities[name]` but the function form gives clearer call-sites
|
|
89
|
-
* when the name is computed.
|
|
90
|
-
*/
|
|
91
|
-
function isSupported(name) {
|
|
92
|
-
return capabilities[name];
|
|
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';
|
|
93
195
|
}
|
|
94
196
|
|
|
95
|
-
export {
|
|
197
|
+
export { Capabilities };
|
|
96
198
|
//# sourceMappingURL=capabilities.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.js","sources":["../../../../src/core/capabilities.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;
|
|
1
|
+
{"version":3,"file":"capabilities.js","sources":["../../../../src/core/capabilities.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW;AAC/C,MAAM,WAAW,GAAG,OAAO,QAAQ,KAAK,WAAW;AACnD,MAAM,YAAY,GAAG,OAAO,SAAS,KAAK,WAAW;MAqBxC,YAAY,CAAA;AAEb,IAAA,OAAO,aAAa,GAAiC,IAAI;AAEjE;;;;;;;;;;;;;;;AAeG;AACI,IAAA,WAAW,KAAK,GAAA;AACnB,QAAA,IAAI,YAAY,CAAC,aAAa,KAAK,IAAI,EAAE;AACrC,YAAA,YAAY,CAAC,aAAa,GAAG,YAAY,CAAC,OAAO,EAAE;QACvD;QAEA,OAAO,YAAY,CAAC,aAAa;IACrC;AAEgB,IAAA,MAAM;AACN,IAAA,MAAM;AACN,IAAA,aAAa;AACb,IAAA,YAAY;AACZ,IAAA,kBAAkB;AAClB,IAAA,OAAO;AACP,IAAA,QAAQ;AACR,IAAA,OAAO;AACP,IAAA,KAAK;AACL,IAAA,cAAc;AACd,IAAA,KAAK;AACL,IAAA,UAAU;AACV,IAAA,SAAS;AACT,IAAA,eAAe;AACf,IAAA,UAAU;AACV,IAAA,gBAAgB;AAEhC,IAAA,WAAA,CAAoB,MAAwB,EAAA;AACxC,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM;AAC3B,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM;AAC3B,QAAA,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa;AACzC,QAAA,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY;AACvC,QAAA,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC,kBAAkB;AACnD,QAAA,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;AAC7B,QAAA,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ;AAC/B,QAAA,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;AAC7B,QAAA,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK;AACzB,QAAA,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc;AAC3C,QAAA,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK;AACzB,QAAA,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU;AACnC,QAAA,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS;AACjC,QAAA,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe;AAC7C,QAAA,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU;AACnC,QAAA,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB;AAE/C,QAAA,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;IACvB;IAEQ,aAAa,OAAO,GAAA;QACxB,MAAM,CAAC,aAAa,EAAE,UAAU,CAAC,GAAG,MAAM,WAAW,EAAE;QAEvD,OAAO,IAAI,YAAY,CAAC;YACpB,MAAM,EAAE,WAAW,EAAE;YACrB,MAAM,EAAE,qBAAqB,EAAE;YAC/B,aAAa;AACb,YAAA,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,IAAI;AACxC,YAAA,kBAAkB,EAAE,UAAU,EAAE,YAAY,IAAI,IAAI;YACpD,OAAO,EAAE,YAAY,EAAE;YACvB,QAAQ,EAAE,aAAa,EAAE;YACzB,OAAO,EAAE,YAAY,EAAE;YACvB,KAAK,EAAE,mBAAmB,EAAE;YAC5B,cAAc,EAAE,mBAAmB,EAAE;YACrC,KAAK,EAAE,UAAU,EAAE;YACnB,UAAU,EAAE,eAAe,EAAE;YAC7B,SAAS,EAAE,cAAc,EAAE;YAC3B,eAAe,EAAE,oBAAoB,EAAE;YACvC,UAAU,EAAE,eAAe,EAAE;YAC7B,gBAAgB,EAAE,SAAS,GAAG,MAAM,CAAC,gBAAgB,GAAG,CAAC;AAC5D,SAAA,CAAC;IACN;;AAGJ;AAEA,SAAS,WAAW,GAAA;AAChB,IAAA,IAAI,CAAC,WAAW;AAAE,QAAA,OAAO,KAAK;AAE9B,IAAA,IAAI;QACA,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;QAC/C,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;QACtC,OAAO,EAAE,KAAK,IAAI;IACtB;AAAE,IAAA,MAAM;AACJ,QAAA,OAAO,KAAK;IAChB;AACJ;AAEA,SAAS,qBAAqB,GAAA;AAC1B,IAAA,OAAO,YAAY,IAAI,KAAK,IAAI,SAAS;AAC7C;AAEA,eAAe,WAAW,GAAA;IACtB,IAAI,CAAC,qBAAqB,EAAE;AAAE,QAAA,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;AAEjD,IAAA,MAAM,GAAG,GAAI,SAAwC,CAAC,GAAG;IAEzD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,UAAU;AAAE,QAAA,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;AAEzE,IAAA,IAAI;AACA,QAAA,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,cAAc,EAAE;AAE1C,QAAA,IAAI,CAAC,OAAO;AAAE,YAAA,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;;;;;QAMjC,MAAM,UAAU,GAAG,OAGlB;AAED,QAAA,IAAI,UAAU,CAAC,IAAI,EAAE;AACjB,YAAA,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC;QACrC;AAEA,QAAA,IAAI,OAAO,UAAU,CAAC,kBAAkB,KAAK,UAAU,EAAE;AACrD,YAAA,IAAI;gBACA,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,CAAC,kBAAkB,EAAE,CAAC;YAC3D;AAAE,YAAA,MAAM;AACJ,gBAAA,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;YAC1B;QACJ;AAEA,QAAA,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;IAC1B;AAAE,IAAA,MAAM;AACJ,QAAA,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;IACvB;AACJ;AAEA,SAAS,YAAY,GAAA;AACjB,IAAA,OAAO,SAAS,IAAI,cAAc,IAAI,MAAM;AAChD;AAEA,SAAS,aAAa,GAAA;AAClB,IAAA,OAAO,SAAS,IAAI,eAAe,IAAI,MAAM;AACjD;AAEA,SAAS,YAAY,GAAA;IACjB,OAAO,YAAY,IAAI,OAAO,SAAS,CAAC,WAAW,KAAK,UAAU;AACtE;AAEA,SAAS,mBAAmB,GAAA;AACxB,IAAA,IAAI,CAAC,SAAS;AAAE,QAAA,OAAO,KAAK;IAC5B,IAAI,cAAc,IAAI,MAAM;AAAE,QAAA,OAAO,IAAI;IACzC,IAAI,mBAAmB,EAAE,GAAG,CAAC;AAAE,QAAA,OAAO,IAAI;AAC1C,IAAA,OAAO,KAAK;AAChB;AAEA,SAAS,mBAAmB,GAAA;AACxB,IAAA,IAAI,CAAC,YAAY;AAAE,QAAA,OAAO,CAAC;AAC3B,IAAA,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc;AACvC,IAAA,OAAO,OAAO,MAAM,KAAK,QAAQ,GAAG,MAAM,GAAG,CAAC;AAClD;AAEA,SAAS,UAAU,GAAA;AACf,IAAA,IAAI,CAAC,SAAS;AAAE,QAAA,OAAO,KAAK;IAC5B,MAAM,CAAC,GAAG,MAA2D;AACrE,IAAA,OAAO,OAAO,CAAC,CAAC,YAAY,KAAK,WAAW,IAAI,OAAO,CAAC,CAAC,kBAAkB,KAAK,WAAW;AAC/F;AAEA,SAAS,eAAe,GAAA;AACpB,IAAA,IAAI,CAAC,WAAW;AAAE,QAAA,OAAO,KAAK;AAC9B,IAAA,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAuE;AAC3F,IAAA,OAAO,OAAO,EAAE,CAAC,iBAAiB,KAAK,UAAU,IAAI,OAAO,EAAE,CAAC,uBAAuB,KAAK,UAAU;AACzG;AAEA,SAAS,cAAc,GAAA;IACnB,OAAO,YAAY,IAAI,OAAO,SAAS,CAAC,OAAO,KAAK,UAAU;AAClE;AAEA,SAAS,oBAAoB,GAAA;;;;;IAKzB,OAAO,SAAS,IAAI,OAAQ,MAAyD,CAAC,eAAe,KAAK,WAAW;AACzH;AAEA,SAAS,eAAe,GAAA;;;;;IAKpB,OAAO,SAAS,IAAI,OAAQ,MAAgD,CAAC,MAAM,KAAK,UAAU;AACtG;;;;"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { canvasSourceToDataUrl, emptyArrayBuffer, getCanvasSourceSize, getPreciseTime, getTextureSourceSize, hours, milliseconds, minutes, noop, rand, removeArrayItems, seconds, stopEvent, supportsCodec, supportsEventOptions, supportsIndexedDb, supportsPointerEvents, supportsTouchEvents, supportsWebAudio } from './core/utils.js';
|
|
2
2
|
export { Application, ApplicationStatus } from './core/Application.js';
|
|
3
3
|
export { Bounds } from './core/Bounds.js';
|
|
4
|
-
export {
|
|
4
|
+
export { Capabilities } from './core/capabilities.js';
|
|
5
5
|
export { Clock } from './core/Clock.js';
|
|
6
6
|
export { Color } from './core/Color.js';
|
|
7
7
|
export { Quadtree } from './core/Quadtree.js';
|
|
@@ -63,9 +63,6 @@ export { UniversalEmitter } from './particles/emitters/UniversalEmitter.js';
|
|
|
63
63
|
export { Particle } from './particles/Particle.js';
|
|
64
64
|
export { ParticleSystem } from './particles/ParticleSystem.js';
|
|
65
65
|
export { Mesh } from './rendering/mesh/Mesh.js';
|
|
66
|
-
export { CircleGeometry } from './rendering/primitives/CircleGeometry.js';
|
|
67
|
-
export { Geometry } from './rendering/primitives/Geometry.js';
|
|
68
|
-
export { DrawableShape } from './rendering/primitives/DrawableShape.js';
|
|
69
66
|
export { Graphics } from './rendering/primitives/Graphics.js';
|
|
70
67
|
export { Shader } from './rendering/shader/Shader.js';
|
|
71
68
|
export { ShaderAttribute } from './rendering/shader/ShaderAttribute.js';
|
|
@@ -87,7 +84,6 @@ export { webGl2PrimitiveArrayConstructors, webGl2PrimitiveByteSizeMapping, webGl
|
|
|
87
84
|
export { WebGl2VertexArrayObject } from './rendering/webgl2/WebGl2VertexArrayObject.js';
|
|
88
85
|
export { WebGl2MeshRenderer } from './rendering/webgl2/WebGl2MeshRenderer.js';
|
|
89
86
|
export { WebGl2ParticleRenderer } from './rendering/webgl2/WebGl2ParticleRenderer.js';
|
|
90
|
-
export { WebGl2PrimitiveRenderer } from './rendering/webgl2/WebGl2PrimitiveRenderer.js';
|
|
91
87
|
export { WebGl2Backend } from './rendering/webgl2/WebGl2Backend.js';
|
|
92
88
|
export { createWebGl2ShaderProgram } from './rendering/webgl2/WebGl2ShaderProgram.js';
|
|
93
89
|
export { WebGl2SpriteRenderer } from './rendering/webgl2/WebGl2SpriteRenderer.js';
|
|
@@ -95,7 +91,6 @@ export { AbstractWebGpuRenderer } from './rendering/webgpu/AbstractWebGpuRendere
|
|
|
95
91
|
export { getWebGpuBlendState } from './rendering/webgpu/WebGpuBlendState.js';
|
|
96
92
|
export { WebGpuMeshRenderer } from './rendering/webgpu/WebGpuMeshRenderer.js';
|
|
97
93
|
export { WebGpuParticleRenderer } from './rendering/webgpu/WebGpuParticleRenderer.js';
|
|
98
|
-
export { WebGpuPrimitiveRenderer } from './rendering/webgpu/WebGpuPrimitiveRenderer.js';
|
|
99
94
|
export { WebGpuBackend } from './rendering/webgpu/WebGpuBackend.js';
|
|
100
95
|
export { WebGpuSpriteRenderer } from './rendering/webgpu/WebGpuSpriteRenderer.js';
|
|
101
96
|
export { BlendModes, BufferTypes, BufferUsage, RenderingPrimitives, ScaleModes, ShaderPrimitives, WrapModes } from './rendering/types.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export declare const
|
|
7
|
-
export declare const
|
|
8
|
-
export declare const
|
|
1
|
+
export interface MeshGeometryData {
|
|
2
|
+
readonly vertices: Float32Array;
|
|
3
|
+
readonly indices: Uint16Array;
|
|
4
|
+
readonly points: Array<number>;
|
|
5
|
+
}
|
|
6
|
+
export declare const buildLine: (startX: number, startY: number, endX: number, endY: number, width: number) => MeshGeometryData;
|
|
7
|
+
export declare const buildPath: (points: Array<number>, width: number) => MeshGeometryData;
|
|
8
|
+
export declare const buildCircle: (centerX: number, centerY: number, radius: number) => MeshGeometryData;
|
|
9
|
+
export declare const buildEllipse: (centerX: number, centerY: number, radiusX: number, radiusY: number) => MeshGeometryData;
|
|
10
|
+
export declare const buildPolygon: (points: Array<number>) => MeshGeometryData;
|
|
11
|
+
export declare const buildRectangle: (x: number, y: number, width: number, height: number) => MeshGeometryData;
|
|
12
|
+
export declare const buildStar: (centerX: number, centerY: number, points: number, radius: number, innerRadius?: number, rotation?: number) => MeshGeometryData;
|
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
import earcut from 'earcut';
|
|
2
|
-
import { Geometry } from '../rendering/primitives/Geometry.js';
|
|
3
2
|
import { Vector } from './Vector.js';
|
|
4
3
|
import { tau } from './utils.js';
|
|
5
4
|
|
|
6
|
-
const buildLine = (startX, startY, endX, endY, width
|
|
5
|
+
const buildLine = (startX, startY, endX, endY, width) => {
|
|
7
6
|
const points = [startX, startY, endX, endY];
|
|
8
7
|
const distance = width / 2;
|
|
9
|
-
const index = vertices.length / 6;
|
|
10
8
|
const perpA = new Vector(startX - endX, startY - endY).perp().normalize().multiply(distance);
|
|
11
9
|
const perpB = new Vector(endX - startX, endY - startY).perp().normalize().multiply(distance);
|
|
12
|
-
vertices
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
const vertices = new Float32Array([
|
|
11
|
+
startX - perpA.x, startY - perpA.y, // 0: start-left
|
|
12
|
+
startX + perpA.x, startY + perpA.y, // 1: start-right
|
|
13
|
+
endX - perpB.x, endY - perpB.y, // 2: end-left
|
|
14
|
+
endX + perpB.x, endY + perpB.y, // 3: end-right
|
|
15
|
+
]);
|
|
16
|
+
perpA.destroy();
|
|
17
|
+
perpB.destroy();
|
|
18
|
+
const indices = new Uint16Array([0, 1, 3, 0, 3, 2]);
|
|
19
|
+
return { vertices, indices, points };
|
|
18
20
|
};
|
|
19
|
-
const buildPath = (points, width
|
|
21
|
+
const buildPath = (points, width) => {
|
|
20
22
|
if (points.length < 4) {
|
|
21
23
|
throw new Error('At least two X/Y pairs are required to build a line.');
|
|
22
24
|
}
|
|
23
|
-
const lineWidth = width / 2
|
|
25
|
+
const lineWidth = width / 2;
|
|
26
|
+
const firstPoint = new Vector(points[0], points[1]);
|
|
27
|
+
const lastPoint = new Vector(points[points.length - 2], points[points.length - 1]);
|
|
28
|
+
const outlinePoints = points;
|
|
24
29
|
if (firstPoint.x === lastPoint.x && firstPoint.y === lastPoint.y) {
|
|
25
30
|
points = points.slice();
|
|
26
31
|
points.pop();
|
|
@@ -31,9 +36,10 @@ const buildPath = (points, width, vertices = [], indices = []) => {
|
|
|
31
36
|
points.unshift(midPointX, midPointY);
|
|
32
37
|
points.push(midPointX, midPointY);
|
|
33
38
|
}
|
|
39
|
+
firstPoint.destroy();
|
|
40
|
+
lastPoint.destroy();
|
|
34
41
|
const length = points.length / 2;
|
|
35
|
-
|
|
36
|
-
let indexStart = vertices.length / 6;
|
|
42
|
+
const stripVertices = [];
|
|
37
43
|
let p1x = points[0];
|
|
38
44
|
let p1y = points[1];
|
|
39
45
|
let p2x = points[2];
|
|
@@ -51,8 +57,8 @@ const buildPath = (points, width, vertices = [], indices = []) => {
|
|
|
51
57
|
perpy /= dist;
|
|
52
58
|
perpx *= lineWidth;
|
|
53
59
|
perpy *= lineWidth;
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
stripVertices.push(p1x - perpx, p1y - perpy);
|
|
61
|
+
stripVertices.push(p1x + perpx, p1y + perpy);
|
|
56
62
|
for (let i = 1; i < length - 1; i++) {
|
|
57
63
|
p1x = points[(i - 1) * 2];
|
|
58
64
|
p1y = points[((i - 1) * 2) + 1];
|
|
@@ -83,8 +89,8 @@ const buildPath = (points, width, vertices = [], indices = []) => {
|
|
|
83
89
|
let denom = (a1 * b2) - (a2 * b1);
|
|
84
90
|
if (Math.abs(denom) < 0.1) {
|
|
85
91
|
denom += 10.1;
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
stripVertices.push(p2x - perpx, p2y - perpy);
|
|
93
|
+
stripVertices.push(p2x + perpx, p2y + perpy);
|
|
88
94
|
continue;
|
|
89
95
|
}
|
|
90
96
|
const px = ((b1 * c2) - (b2 * c1)) / denom;
|
|
@@ -98,14 +104,13 @@ const buildPath = (points, width, vertices = [], indices = []) => {
|
|
|
98
104
|
perp3y /= dist;
|
|
99
105
|
perp3x *= lineWidth;
|
|
100
106
|
perp3y *= lineWidth;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
indexCount++;
|
|
107
|
+
stripVertices.push(p2x - perp3x, p2y - perp3y);
|
|
108
|
+
stripVertices.push(p2x + perp3x, p2y + perp3y);
|
|
109
|
+
stripVertices.push(p2x - perp3x, p2y - perp3y);
|
|
105
110
|
}
|
|
106
111
|
else {
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
stripVertices.push(px, py);
|
|
113
|
+
stripVertices.push(p2x - (px - p2x), p2y - (py - p2y));
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
p1x = points[(length - 2) * 2];
|
|
@@ -119,70 +124,112 @@ const buildPath = (points, width, vertices = [], indices = []) => {
|
|
|
119
124
|
perpy /= dist;
|
|
120
125
|
perpx *= lineWidth;
|
|
121
126
|
perpy *= lineWidth;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
indices.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
+
stripVertices.push(p2x - perpx, p2y - perpy);
|
|
128
|
+
stripVertices.push(p2x + perpx, p2y + perpy);
|
|
129
|
+
// Convert strip-style vertex sequence to triangle-list indices.
|
|
130
|
+
// For N strip vertices (N = stripVertices.length / 2), each i in [0, N-3]
|
|
131
|
+
// produces a triangle. Even i: (i, i+1, i+2). Odd i: (i+1, i, i+2).
|
|
132
|
+
// This preserves the same winding the original triangle-strip pipeline saw.
|
|
133
|
+
const stripVertexCount = stripVertices.length / 2;
|
|
134
|
+
const vertices = new Float32Array(stripVertices);
|
|
135
|
+
const triangleCount = stripVertexCount >= 3 ? stripVertexCount - 2 : 0;
|
|
136
|
+
const indices = new Uint16Array(triangleCount * 3);
|
|
137
|
+
for (let i = 0; i < triangleCount; i++) {
|
|
138
|
+
const base = i * 3;
|
|
139
|
+
if ((i & 1) === 0) {
|
|
140
|
+
indices[base] = i;
|
|
141
|
+
indices[base + 1] = i + 1;
|
|
142
|
+
indices[base + 2] = i + 2;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
indices[base] = i + 1;
|
|
146
|
+
indices[base + 1] = i;
|
|
147
|
+
indices[base + 2] = i + 2;
|
|
148
|
+
}
|
|
127
149
|
}
|
|
128
|
-
indices
|
|
129
|
-
return new Geometry({ vertices, indices, points });
|
|
150
|
+
return { vertices, indices, points: outlinePoints };
|
|
130
151
|
};
|
|
131
|
-
const buildCircle = (centerX, centerY, radius
|
|
132
|
-
const length = Math.floor(15 * Math.sqrt(radius + radius))
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
const buildCircle = (centerX, centerY, radius) => {
|
|
153
|
+
const length = Math.floor(15 * Math.sqrt(radius + radius));
|
|
154
|
+
const segment = (Math.PI * 2) / length;
|
|
155
|
+
const points = [];
|
|
156
|
+
// 1 center vertex + N perimeter vertices.
|
|
157
|
+
const vertices = new Float32Array((length + 1) * 2);
|
|
158
|
+
vertices[0] = centerX;
|
|
159
|
+
vertices[1] = centerY;
|
|
160
|
+
for (let i = 0; i < length; i++) {
|
|
161
|
+
const segmentX = centerX + (Math.sin(segment * i) * radius);
|
|
162
|
+
const segmentY = centerY + (Math.cos(segment * i) * radius);
|
|
137
163
|
points.push(segmentX, segmentY);
|
|
138
|
-
|
|
139
|
-
vertices
|
|
140
|
-
|
|
164
|
+
const offset = (i + 1) * 2;
|
|
165
|
+
vertices[offset] = segmentX;
|
|
166
|
+
vertices[offset + 1] = segmentY;
|
|
141
167
|
}
|
|
142
|
-
indices
|
|
143
|
-
|
|
168
|
+
const indices = new Uint16Array(length * 3);
|
|
169
|
+
for (let i = 0; i < length; i++) {
|
|
170
|
+
const base = i * 3;
|
|
171
|
+
indices[base] = 0;
|
|
172
|
+
indices[base + 1] = i + 1;
|
|
173
|
+
indices[base + 2] = i + 2 > length ? 1 : i + 2;
|
|
174
|
+
}
|
|
175
|
+
return { vertices, indices, points };
|
|
144
176
|
};
|
|
145
|
-
const buildEllipse = (centerX, centerY, radiusX, radiusY
|
|
146
|
-
const length = Math.floor(15 * Math.sqrt(radiusX + radiusY))
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
177
|
+
const buildEllipse = (centerX, centerY, radiusX, radiusY) => {
|
|
178
|
+
const length = Math.floor(15 * Math.sqrt(radiusX + radiusY));
|
|
179
|
+
const segment = (Math.PI * 2) / length;
|
|
180
|
+
const points = [];
|
|
181
|
+
const vertices = new Float32Array((length + 1) * 2);
|
|
182
|
+
vertices[0] = centerX;
|
|
183
|
+
vertices[1] = centerY;
|
|
184
|
+
for (let i = 0; i < length; i++) {
|
|
185
|
+
const segmentX = centerX + (Math.sin(segment * i) * radiusX);
|
|
186
|
+
const segmentY = centerY + (Math.cos(segment * i) * radiusY);
|
|
151
187
|
points.push(segmentX, segmentY);
|
|
152
|
-
|
|
153
|
-
vertices
|
|
154
|
-
|
|
188
|
+
const offset = (i + 1) * 2;
|
|
189
|
+
vertices[offset] = segmentX;
|
|
190
|
+
vertices[offset + 1] = segmentY;
|
|
155
191
|
}
|
|
156
|
-
indices
|
|
157
|
-
|
|
192
|
+
const indices = new Uint16Array(length * 3);
|
|
193
|
+
for (let i = 0; i < length; i++) {
|
|
194
|
+
const base = i * 3;
|
|
195
|
+
indices[base] = 0;
|
|
196
|
+
indices[base + 1] = i + 1;
|
|
197
|
+
indices[base + 2] = i + 2 > length ? 1 : i + 2;
|
|
198
|
+
}
|
|
199
|
+
return { vertices, indices, points };
|
|
158
200
|
};
|
|
159
|
-
const buildPolygon = (points
|
|
201
|
+
const buildPolygon = (points) => {
|
|
160
202
|
if (points.length < 6) {
|
|
161
203
|
throw new Error('At least three X/Y pairs are required to build a polygon.');
|
|
162
204
|
}
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
indices.push(triangles[i + 2] + index);
|
|
170
|
-
indices.push(triangles[i + 2] + index);
|
|
171
|
-
}
|
|
172
|
-
for (let i = 0; i < length; i++) {
|
|
173
|
-
vertices.push(points[i * 2], points[(i * 2) + 1]);
|
|
174
|
-
}
|
|
205
|
+
const length = points.length / 2;
|
|
206
|
+
const triangles = earcut(points, [], 2);
|
|
207
|
+
const vertices = new Float32Array(points.length);
|
|
208
|
+
for (let i = 0; i < length; i++) {
|
|
209
|
+
vertices[i * 2] = points[i * 2];
|
|
210
|
+
vertices[(i * 2) + 1] = points[(i * 2) + 1];
|
|
175
211
|
}
|
|
176
|
-
|
|
212
|
+
const indices = triangles ? new Uint16Array(triangles) : new Uint16Array(0);
|
|
213
|
+
return { vertices, indices, points };
|
|
177
214
|
};
|
|
178
|
-
const buildRectangle = (x, y, width, height
|
|
179
|
-
|
|
180
|
-
vertices
|
|
181
|
-
|
|
182
|
-
|
|
215
|
+
const buildRectangle = (x, y, width, height) => {
|
|
216
|
+
// 4 vertices: TL, TR, BL, BR. Triangles [0, 1, 2, 1, 3, 2] (clockwise).
|
|
217
|
+
const vertices = new Float32Array([
|
|
218
|
+
x, y, // 0 TL
|
|
219
|
+
x + width, y, // 1 TR
|
|
220
|
+
x, y + height, // 2 BL
|
|
221
|
+
x + width, y + height, // 3 BR
|
|
222
|
+
]);
|
|
223
|
+
const indices = new Uint16Array([0, 1, 2, 1, 3, 2]);
|
|
224
|
+
// Outline points walk the perimeter (TL -> TR -> BR -> BL).
|
|
225
|
+
const points = [x, y, x + width, y, x + width, y + height, x, y + height];
|
|
226
|
+
return { vertices, indices, points };
|
|
183
227
|
};
|
|
184
228
|
const buildStar = (centerX, centerY, points, radius, innerRadius = radius / 2, rotation = 0) => {
|
|
185
|
-
const startAngle = (Math.PI / -2) + rotation
|
|
229
|
+
const startAngle = (Math.PI / -2) + rotation;
|
|
230
|
+
const length = points * 2;
|
|
231
|
+
const delta = tau / length;
|
|
232
|
+
const path = [];
|
|
186
233
|
for (let i = 0; i < length; i++) {
|
|
187
234
|
const angle = startAngle + (i * delta);
|
|
188
235
|
const rad = i % 2 ? innerRadius : radius;
|