@codexo/exojs 0.6.6 → 0.6.8
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 +104 -0
- package/README.md +0 -36
- package/dist/esm/index.d.ts +0 -1
- package/dist/esm/index.js +1 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/input/GestureRecognizer.d.ts +28 -0
- package/dist/esm/input/GestureRecognizer.js +132 -0
- package/dist/esm/input/GestureRecognizer.js.map +1 -0
- package/dist/esm/input/InputManager.d.ts +11 -0
- package/dist/esm/input/InputManager.js +79 -7
- package/dist/esm/input/InputManager.js.map +1 -1
- package/dist/esm/input/Pointer.d.ts +89 -1
- package/dist/esm/input/Pointer.js +163 -3
- package/dist/esm/input/Pointer.js.map +1 -1
- package/dist/esm/input/index.d.ts +1 -1
- package/dist/esm/input/types.d.ts +80 -0
- package/dist/esm/input/types.js +84 -1
- package/dist/esm/input/types.js.map +1 -1
- package/dist/exo.esm.js +451 -479
- package/dist/exo.esm.js.map +1 -1
- package/package.json +1 -9
- package/dist/esm/physics/RapierPhysicsWorld.d.ts +0 -136
- package/dist/esm/physics/RapierPhysicsWorld.js +0 -475
- package/dist/esm/physics/RapierPhysicsWorld.js.map +0 -1
- package/dist/esm/physics/index.d.ts +0 -1
package/dist/exo.esm.js
CHANGED
|
@@ -10851,6 +10851,89 @@ var ChannelOffset;
|
|
|
10851
10851
|
ChannelOffset[ChannelOffset["Pointers"] = 256] = "Pointers";
|
|
10852
10852
|
ChannelOffset[ChannelOffset["Gamepads"] = 512] = "Gamepads";
|
|
10853
10853
|
})(ChannelOffset || (ChannelOffset = {}));
|
|
10854
|
+
/** Maximum number of simultaneous tracked pointers (mouse / touch / pen). */
|
|
10855
|
+
const maxPointers = 16;
|
|
10856
|
+
/** Number of channel slots reserved per pointer. 16 pointers × 16 slots = 256 (fills the Pointers category exactly). */
|
|
10857
|
+
const pointerSlotSize = 16;
|
|
10858
|
+
/**
|
|
10859
|
+
* Channel offsets for unified pointer (mouse / touch / pen) state.
|
|
10860
|
+
*
|
|
10861
|
+
* The un-prefixed aliases (Active, X, Y, …) are identical to Slot0Active, Slot0X, Slot0Y, …
|
|
10862
|
+
* and address the primary pointer (slot 0). Use Slot{N}Active / Slot{N}X / Slot{N}Y for
|
|
10863
|
+
* multi-pointer (e.g. pinch) access. Other per-slot channels beyond Active/X/Y are reachable
|
|
10864
|
+
* via arithmetic: `Pointer.X + slotIndex * pointerSlotSize + channelOffset` (Pointer.X = PointerChannel.X).
|
|
10865
|
+
*
|
|
10866
|
+
* @internal — accessed publicly via the `Pointer` class namespace (see Pointer.ts).
|
|
10867
|
+
*/
|
|
10868
|
+
var PointerChannel;
|
|
10869
|
+
(function (PointerChannel) {
|
|
10870
|
+
// --- Convenience aliases for the primary pointer (slot 0) ---
|
|
10871
|
+
PointerChannel[PointerChannel["Active"] = 256] = "Active";
|
|
10872
|
+
PointerChannel[PointerChannel["X"] = 257] = "X";
|
|
10873
|
+
PointerChannel[PointerChannel["Y"] = 258] = "Y";
|
|
10874
|
+
PointerChannel[PointerChannel["Pressure"] = 259] = "Pressure";
|
|
10875
|
+
PointerChannel[PointerChannel["Width"] = 260] = "Width";
|
|
10876
|
+
PointerChannel[PointerChannel["Height"] = 261] = "Height";
|
|
10877
|
+
PointerChannel[PointerChannel["Twist"] = 262] = "Twist";
|
|
10878
|
+
PointerChannel[PointerChannel["TiltX"] = 263] = "TiltX";
|
|
10879
|
+
PointerChannel[PointerChannel["TiltY"] = 264] = "TiltY";
|
|
10880
|
+
PointerChannel[PointerChannel["Left"] = 265] = "Left";
|
|
10881
|
+
PointerChannel[PointerChannel["Right"] = 266] = "Right";
|
|
10882
|
+
PointerChannel[PointerChannel["Middle"] = 267] = "Middle";
|
|
10883
|
+
PointerChannel[PointerChannel["IsMouse"] = 268] = "IsMouse";
|
|
10884
|
+
PointerChannel[PointerChannel["IsTouch"] = 269] = "IsTouch";
|
|
10885
|
+
PointerChannel[PointerChannel["IsPen"] = 270] = "IsPen";
|
|
10886
|
+
PointerChannel[PointerChannel["IsPrimary"] = 271] = "IsPrimary";
|
|
10887
|
+
// --- Per-slot Active/X/Y for multi-pointer access ---
|
|
10888
|
+
PointerChannel[PointerChannel["Slot0Active"] = 256] = "Slot0Active";
|
|
10889
|
+
PointerChannel[PointerChannel["Slot0X"] = 257] = "Slot0X";
|
|
10890
|
+
PointerChannel[PointerChannel["Slot0Y"] = 258] = "Slot0Y";
|
|
10891
|
+
PointerChannel[PointerChannel["Slot1Active"] = 272] = "Slot1Active";
|
|
10892
|
+
PointerChannel[PointerChannel["Slot1X"] = 273] = "Slot1X";
|
|
10893
|
+
PointerChannel[PointerChannel["Slot1Y"] = 274] = "Slot1Y";
|
|
10894
|
+
PointerChannel[PointerChannel["Slot2Active"] = 288] = "Slot2Active";
|
|
10895
|
+
PointerChannel[PointerChannel["Slot2X"] = 289] = "Slot2X";
|
|
10896
|
+
PointerChannel[PointerChannel["Slot2Y"] = 290] = "Slot2Y";
|
|
10897
|
+
PointerChannel[PointerChannel["Slot3Active"] = 304] = "Slot3Active";
|
|
10898
|
+
PointerChannel[PointerChannel["Slot3X"] = 305] = "Slot3X";
|
|
10899
|
+
PointerChannel[PointerChannel["Slot3Y"] = 306] = "Slot3Y";
|
|
10900
|
+
PointerChannel[PointerChannel["Slot4Active"] = 320] = "Slot4Active";
|
|
10901
|
+
PointerChannel[PointerChannel["Slot4X"] = 321] = "Slot4X";
|
|
10902
|
+
PointerChannel[PointerChannel["Slot4Y"] = 322] = "Slot4Y";
|
|
10903
|
+
PointerChannel[PointerChannel["Slot5Active"] = 336] = "Slot5Active";
|
|
10904
|
+
PointerChannel[PointerChannel["Slot5X"] = 337] = "Slot5X";
|
|
10905
|
+
PointerChannel[PointerChannel["Slot5Y"] = 338] = "Slot5Y";
|
|
10906
|
+
PointerChannel[PointerChannel["Slot6Active"] = 352] = "Slot6Active";
|
|
10907
|
+
PointerChannel[PointerChannel["Slot6X"] = 353] = "Slot6X";
|
|
10908
|
+
PointerChannel[PointerChannel["Slot6Y"] = 354] = "Slot6Y";
|
|
10909
|
+
PointerChannel[PointerChannel["Slot7Active"] = 368] = "Slot7Active";
|
|
10910
|
+
PointerChannel[PointerChannel["Slot7X"] = 369] = "Slot7X";
|
|
10911
|
+
PointerChannel[PointerChannel["Slot7Y"] = 370] = "Slot7Y";
|
|
10912
|
+
PointerChannel[PointerChannel["Slot8Active"] = 384] = "Slot8Active";
|
|
10913
|
+
PointerChannel[PointerChannel["Slot8X"] = 385] = "Slot8X";
|
|
10914
|
+
PointerChannel[PointerChannel["Slot8Y"] = 386] = "Slot8Y";
|
|
10915
|
+
PointerChannel[PointerChannel["Slot9Active"] = 400] = "Slot9Active";
|
|
10916
|
+
PointerChannel[PointerChannel["Slot9X"] = 401] = "Slot9X";
|
|
10917
|
+
PointerChannel[PointerChannel["Slot9Y"] = 402] = "Slot9Y";
|
|
10918
|
+
PointerChannel[PointerChannel["Slot10Active"] = 416] = "Slot10Active";
|
|
10919
|
+
PointerChannel[PointerChannel["Slot10X"] = 417] = "Slot10X";
|
|
10920
|
+
PointerChannel[PointerChannel["Slot10Y"] = 418] = "Slot10Y";
|
|
10921
|
+
PointerChannel[PointerChannel["Slot11Active"] = 432] = "Slot11Active";
|
|
10922
|
+
PointerChannel[PointerChannel["Slot11X"] = 433] = "Slot11X";
|
|
10923
|
+
PointerChannel[PointerChannel["Slot11Y"] = 434] = "Slot11Y";
|
|
10924
|
+
PointerChannel[PointerChannel["Slot12Active"] = 448] = "Slot12Active";
|
|
10925
|
+
PointerChannel[PointerChannel["Slot12X"] = 449] = "Slot12X";
|
|
10926
|
+
PointerChannel[PointerChannel["Slot12Y"] = 450] = "Slot12Y";
|
|
10927
|
+
PointerChannel[PointerChannel["Slot13Active"] = 464] = "Slot13Active";
|
|
10928
|
+
PointerChannel[PointerChannel["Slot13X"] = 465] = "Slot13X";
|
|
10929
|
+
PointerChannel[PointerChannel["Slot13Y"] = 466] = "Slot13Y";
|
|
10930
|
+
PointerChannel[PointerChannel["Slot14Active"] = 480] = "Slot14Active";
|
|
10931
|
+
PointerChannel[PointerChannel["Slot14X"] = 481] = "Slot14X";
|
|
10932
|
+
PointerChannel[PointerChannel["Slot14Y"] = 482] = "Slot14Y";
|
|
10933
|
+
PointerChannel[PointerChannel["Slot15Active"] = 496] = "Slot15Active";
|
|
10934
|
+
PointerChannel[PointerChannel["Slot15X"] = 497] = "Slot15X";
|
|
10935
|
+
PointerChannel[PointerChannel["Slot15Y"] = 498] = "Slot15Y";
|
|
10936
|
+
})(PointerChannel || (PointerChannel = {}));
|
|
10854
10937
|
var Keyboard;
|
|
10855
10938
|
(function (Keyboard) {
|
|
10856
10939
|
Keyboard[Keyboard["Backspace"] = 8] = "Backspace";
|
|
@@ -11132,14 +11215,21 @@ class Pointer {
|
|
|
11132
11215
|
tilt;
|
|
11133
11216
|
stateFlags = new Flags();
|
|
11134
11217
|
_canvas;
|
|
11218
|
+
_channels;
|
|
11219
|
+
_slotIndex;
|
|
11220
|
+
_channelBase;
|
|
11135
11221
|
_buttons;
|
|
11136
11222
|
_pressure;
|
|
11137
11223
|
_rotation;
|
|
11224
|
+
_isPrimary;
|
|
11138
11225
|
_currentState = PointerState.Unknown;
|
|
11139
|
-
constructor(event, canvas) {
|
|
11140
|
-
const { pointerId, pointerType, clientX, clientY, width, height, tiltX, tiltY, buttons, pressure, twist } = event;
|
|
11226
|
+
constructor(event, canvas, channels, slotIndex) {
|
|
11227
|
+
const { pointerId, pointerType, clientX, clientY, width, height, tiltX, tiltY, buttons, pressure, twist, isPrimary } = event;
|
|
11141
11228
|
const { left, top } = canvas.getBoundingClientRect();
|
|
11142
11229
|
this._canvas = canvas;
|
|
11230
|
+
this._channels = channels;
|
|
11231
|
+
this._slotIndex = slotIndex;
|
|
11232
|
+
this._channelBase = ChannelOffset.Pointers + slotIndex * pointerSlotSize;
|
|
11143
11233
|
this.id = pointerId;
|
|
11144
11234
|
this.type = pointerType;
|
|
11145
11235
|
this.position = new Vector(clientX - left, clientY - top);
|
|
@@ -11148,7 +11238,9 @@ class Pointer {
|
|
|
11148
11238
|
this._buttons = buttons;
|
|
11149
11239
|
this._pressure = pressure;
|
|
11150
11240
|
this._rotation = twist;
|
|
11241
|
+
this._isPrimary = isPrimary;
|
|
11151
11242
|
this.stateFlags.push(PointerStateFlag.Over);
|
|
11243
|
+
this._writeChannels(true);
|
|
11152
11244
|
}
|
|
11153
11245
|
get x() {
|
|
11154
11246
|
return this.position.x;
|
|
@@ -11171,48 +11263,71 @@ class Pointer {
|
|
|
11171
11263
|
get rotation() {
|
|
11172
11264
|
return this._rotation;
|
|
11173
11265
|
}
|
|
11266
|
+
get twist() {
|
|
11267
|
+
return this._rotation;
|
|
11268
|
+
}
|
|
11269
|
+
get tiltX() {
|
|
11270
|
+
return this.tilt.x;
|
|
11271
|
+
}
|
|
11272
|
+
get tiltY() {
|
|
11273
|
+
return this.tilt.y;
|
|
11274
|
+
}
|
|
11275
|
+
get isPrimary() {
|
|
11276
|
+
return this._isPrimary;
|
|
11277
|
+
}
|
|
11278
|
+
get slotIndex() {
|
|
11279
|
+
return this._slotIndex;
|
|
11280
|
+
}
|
|
11174
11281
|
get currentState() {
|
|
11175
11282
|
return this._currentState;
|
|
11176
11283
|
}
|
|
11177
11284
|
handleEnter(event) {
|
|
11178
11285
|
this.handleEvent(event);
|
|
11179
11286
|
this._currentState = PointerState.InsideCanvas;
|
|
11287
|
+
this._writeChannels(true);
|
|
11180
11288
|
}
|
|
11181
11289
|
handleLeave(event) {
|
|
11182
11290
|
this.handleEvent(event);
|
|
11183
11291
|
this.stateFlags.push(PointerStateFlag.Leave);
|
|
11184
11292
|
this._currentState = PointerState.OutsideCanvas;
|
|
11293
|
+
this._writeChannels(false);
|
|
11185
11294
|
}
|
|
11186
11295
|
handlePress(event) {
|
|
11187
11296
|
this.handleEvent(event);
|
|
11188
11297
|
this.startPos.copy(this.position);
|
|
11189
11298
|
this.stateFlags.push(PointerStateFlag.Down);
|
|
11190
11299
|
this._currentState = PointerState.Pressed;
|
|
11300
|
+
this._writeChannels(true);
|
|
11191
11301
|
}
|
|
11192
11302
|
handleMove(event) {
|
|
11193
11303
|
this.handleEvent(event);
|
|
11194
11304
|
this.stateFlags.push(PointerStateFlag.Move);
|
|
11195
11305
|
this._currentState = PointerState.Moving;
|
|
11306
|
+
this._writeChannels(true);
|
|
11196
11307
|
}
|
|
11197
11308
|
handleRelease(event) {
|
|
11198
11309
|
this.handleEvent(event);
|
|
11199
11310
|
this.stateFlags.push(PointerStateFlag.Up);
|
|
11200
11311
|
this._currentState = PointerState.Released;
|
|
11312
|
+
this._writeChannels(true);
|
|
11201
11313
|
}
|
|
11202
11314
|
handleCancel(event) {
|
|
11203
11315
|
this.handleEvent(event);
|
|
11204
11316
|
this.stateFlags.push(PointerStateFlag.Cancel);
|
|
11205
11317
|
this._currentState = PointerState.Cancelled;
|
|
11318
|
+
this._writeChannels(false);
|
|
11206
11319
|
}
|
|
11207
11320
|
destroy() {
|
|
11321
|
+
this._clearChannels();
|
|
11208
11322
|
this.position.destroy();
|
|
11209
11323
|
this.startPos.destroy();
|
|
11210
11324
|
this.size.destroy();
|
|
11211
11325
|
this.tilt.destroy();
|
|
11212
11326
|
this._canvas = null;
|
|
11327
|
+
this._channels = null;
|
|
11213
11328
|
}
|
|
11214
11329
|
handleEvent(event) {
|
|
11215
|
-
const { clientX, clientY, width, height, tiltX, tiltY, buttons, pressure, twist } = event;
|
|
11330
|
+
const { clientX, clientY, width, height, tiltX, tiltY, buttons, pressure, twist, isPrimary } = event;
|
|
11216
11331
|
const { left, top } = this._canvas.getBoundingClientRect();
|
|
11217
11332
|
this.position.set(clientX - left, clientY - top);
|
|
11218
11333
|
this.size.set(width, height);
|
|
@@ -11220,8 +11335,263 @@ class Pointer {
|
|
|
11220
11335
|
this._buttons = buttons;
|
|
11221
11336
|
this._pressure = pressure;
|
|
11222
11337
|
this._rotation = twist;
|
|
11338
|
+
this._isPrimary = isPrimary;
|
|
11223
11339
|
return this;
|
|
11224
11340
|
}
|
|
11341
|
+
/** Write the full 16-channel per-pointer state into the shared channel buffer. */
|
|
11342
|
+
_writeChannels(active) {
|
|
11343
|
+
const ch = this._channels;
|
|
11344
|
+
const canvas = this._canvas;
|
|
11345
|
+
if (!ch || !canvas) {
|
|
11346
|
+
return;
|
|
11347
|
+
}
|
|
11348
|
+
const base = this._channelBase;
|
|
11349
|
+
const w = canvas.width || 1;
|
|
11350
|
+
const h = canvas.height || 1;
|
|
11351
|
+
if (!active) {
|
|
11352
|
+
// Zero the entire slot for a clean release.
|
|
11353
|
+
for (let i = 0; i < pointerSlotSize; i++) {
|
|
11354
|
+
ch[base + i] = 0;
|
|
11355
|
+
}
|
|
11356
|
+
return;
|
|
11357
|
+
}
|
|
11358
|
+
const x = Math.min(1, Math.max(0, this.position.x / w));
|
|
11359
|
+
const y = Math.min(1, Math.max(0, this.position.y / h));
|
|
11360
|
+
ch[base + 0] = 1; // active
|
|
11361
|
+
ch[base + 1] = x; // x (normalized)
|
|
11362
|
+
ch[base + 2] = y; // y (normalized)
|
|
11363
|
+
ch[base + 3] = this._pressure; // pressure
|
|
11364
|
+
ch[base + 4] = Math.min(1, this.size.width / w); // width (normalized)
|
|
11365
|
+
ch[base + 5] = Math.min(1, this.size.height / h); // height (normalized)
|
|
11366
|
+
ch[base + 6] = this._rotation / 359; // twist (0..359 → 0..1)
|
|
11367
|
+
ch[base + 7] = (this.tilt.x + 90) / 180; // tiltX (-90..90 → 0..1)
|
|
11368
|
+
ch[base + 8] = (this.tilt.y + 90) / 180; // tiltY (-90..90 → 0..1)
|
|
11369
|
+
ch[base + 9] = (this._buttons & 1) ? 1 : 0; // button.left
|
|
11370
|
+
ch[base + 10] = (this._buttons & 2) ? 1 : 0; // button.right
|
|
11371
|
+
ch[base + 11] = (this._buttons & 4) ? 1 : 0; // button.middle
|
|
11372
|
+
ch[base + 12] = this.type === 'mouse' ? 1 : 0; // isMouse
|
|
11373
|
+
ch[base + 13] = this.type === 'touch' ? 1 : 0; // isTouch
|
|
11374
|
+
ch[base + 14] = this.type === 'pen' ? 1 : 0; // isPen
|
|
11375
|
+
ch[base + 15] = this._isPrimary ? 1 : 0; // isPrimary
|
|
11376
|
+
}
|
|
11377
|
+
/** Zero the slot when this pointer is fully released/destroyed. */
|
|
11378
|
+
_clearChannels() {
|
|
11379
|
+
const ch = this._channels;
|
|
11380
|
+
if (!ch) {
|
|
11381
|
+
return;
|
|
11382
|
+
}
|
|
11383
|
+
const base = this._channelBase;
|
|
11384
|
+
for (let i = 0; i < pointerSlotSize; i++) {
|
|
11385
|
+
ch[base + i] = 0;
|
|
11386
|
+
}
|
|
11387
|
+
}
|
|
11388
|
+
}
|
|
11389
|
+
/**
|
|
11390
|
+
* Namespace merged onto the `Pointer` class to expose channel-offset constants.
|
|
11391
|
+
* All members mirror `PointerChannel` so callers can write `Pointer.Active`, `Pointer.X`, etc.
|
|
11392
|
+
*
|
|
11393
|
+
* The un-prefixed members (Active, X, Y, …) address slot 0 (the primary pointer).
|
|
11394
|
+
* For multi-touch access use `Pointer.Slot{N}Active / Slot{N}X / Slot{N}Y`, or compute:
|
|
11395
|
+
* `Pointer.X + slotIndex * pointerSlotSize + channelOffset`.
|
|
11396
|
+
*/
|
|
11397
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
11398
|
+
(function (Pointer) {
|
|
11399
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
11400
|
+
// --- Primary-pointer convenience aliases (slot 0) ---
|
|
11401
|
+
Pointer.Active = PointerChannel.Active;
|
|
11402
|
+
Pointer.X = PointerChannel.X;
|
|
11403
|
+
Pointer.Y = PointerChannel.Y;
|
|
11404
|
+
Pointer.Pressure = PointerChannel.Pressure;
|
|
11405
|
+
Pointer.Width = PointerChannel.Width;
|
|
11406
|
+
Pointer.Height = PointerChannel.Height;
|
|
11407
|
+
Pointer.Twist = PointerChannel.Twist;
|
|
11408
|
+
Pointer.TiltX = PointerChannel.TiltX;
|
|
11409
|
+
Pointer.TiltY = PointerChannel.TiltY;
|
|
11410
|
+
Pointer.Left = PointerChannel.Left;
|
|
11411
|
+
Pointer.Right = PointerChannel.Right;
|
|
11412
|
+
Pointer.Middle = PointerChannel.Middle;
|
|
11413
|
+
Pointer.IsMouse = PointerChannel.IsMouse;
|
|
11414
|
+
Pointer.IsTouch = PointerChannel.IsTouch;
|
|
11415
|
+
Pointer.IsPen = PointerChannel.IsPen;
|
|
11416
|
+
Pointer.IsPrimary = PointerChannel.IsPrimary;
|
|
11417
|
+
// --- Per-slot Active/X/Y for multi-pointer access ---
|
|
11418
|
+
Pointer.Slot0Active = PointerChannel.Slot0Active;
|
|
11419
|
+
Pointer.Slot0X = PointerChannel.Slot0X;
|
|
11420
|
+
Pointer.Slot0Y = PointerChannel.Slot0Y;
|
|
11421
|
+
Pointer.Slot1Active = PointerChannel.Slot1Active;
|
|
11422
|
+
Pointer.Slot1X = PointerChannel.Slot1X;
|
|
11423
|
+
Pointer.Slot1Y = PointerChannel.Slot1Y;
|
|
11424
|
+
Pointer.Slot2Active = PointerChannel.Slot2Active;
|
|
11425
|
+
Pointer.Slot2X = PointerChannel.Slot2X;
|
|
11426
|
+
Pointer.Slot2Y = PointerChannel.Slot2Y;
|
|
11427
|
+
Pointer.Slot3Active = PointerChannel.Slot3Active;
|
|
11428
|
+
Pointer.Slot3X = PointerChannel.Slot3X;
|
|
11429
|
+
Pointer.Slot3Y = PointerChannel.Slot3Y;
|
|
11430
|
+
Pointer.Slot4Active = PointerChannel.Slot4Active;
|
|
11431
|
+
Pointer.Slot4X = PointerChannel.Slot4X;
|
|
11432
|
+
Pointer.Slot4Y = PointerChannel.Slot4Y;
|
|
11433
|
+
Pointer.Slot5Active = PointerChannel.Slot5Active;
|
|
11434
|
+
Pointer.Slot5X = PointerChannel.Slot5X;
|
|
11435
|
+
Pointer.Slot5Y = PointerChannel.Slot5Y;
|
|
11436
|
+
Pointer.Slot6Active = PointerChannel.Slot6Active;
|
|
11437
|
+
Pointer.Slot6X = PointerChannel.Slot6X;
|
|
11438
|
+
Pointer.Slot6Y = PointerChannel.Slot6Y;
|
|
11439
|
+
Pointer.Slot7Active = PointerChannel.Slot7Active;
|
|
11440
|
+
Pointer.Slot7X = PointerChannel.Slot7X;
|
|
11441
|
+
Pointer.Slot7Y = PointerChannel.Slot7Y;
|
|
11442
|
+
Pointer.Slot8Active = PointerChannel.Slot8Active;
|
|
11443
|
+
Pointer.Slot8X = PointerChannel.Slot8X;
|
|
11444
|
+
Pointer.Slot8Y = PointerChannel.Slot8Y;
|
|
11445
|
+
Pointer.Slot9Active = PointerChannel.Slot9Active;
|
|
11446
|
+
Pointer.Slot9X = PointerChannel.Slot9X;
|
|
11447
|
+
Pointer.Slot9Y = PointerChannel.Slot9Y;
|
|
11448
|
+
Pointer.Slot10Active = PointerChannel.Slot10Active;
|
|
11449
|
+
Pointer.Slot10X = PointerChannel.Slot10X;
|
|
11450
|
+
Pointer.Slot10Y = PointerChannel.Slot10Y;
|
|
11451
|
+
Pointer.Slot11Active = PointerChannel.Slot11Active;
|
|
11452
|
+
Pointer.Slot11X = PointerChannel.Slot11X;
|
|
11453
|
+
Pointer.Slot11Y = PointerChannel.Slot11Y;
|
|
11454
|
+
Pointer.Slot12Active = PointerChannel.Slot12Active;
|
|
11455
|
+
Pointer.Slot12X = PointerChannel.Slot12X;
|
|
11456
|
+
Pointer.Slot12Y = PointerChannel.Slot12Y;
|
|
11457
|
+
Pointer.Slot13Active = PointerChannel.Slot13Active;
|
|
11458
|
+
Pointer.Slot13X = PointerChannel.Slot13X;
|
|
11459
|
+
Pointer.Slot13Y = PointerChannel.Slot13Y;
|
|
11460
|
+
Pointer.Slot14Active = PointerChannel.Slot14Active;
|
|
11461
|
+
Pointer.Slot14X = PointerChannel.Slot14X;
|
|
11462
|
+
Pointer.Slot14Y = PointerChannel.Slot14Y;
|
|
11463
|
+
Pointer.Slot15Active = PointerChannel.Slot15Active;
|
|
11464
|
+
Pointer.Slot15X = PointerChannel.Slot15X;
|
|
11465
|
+
Pointer.Slot15Y = PointerChannel.Slot15Y;
|
|
11466
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
11467
|
+
})(Pointer || (Pointer = {}));
|
|
11468
|
+
|
|
11469
|
+
/** Long-press threshold in milliseconds. */
|
|
11470
|
+
const longPressMs = 500;
|
|
11471
|
+
/**
|
|
11472
|
+
* Internal gesture recognizer — NOT exported publicly.
|
|
11473
|
+
* Receives pointer lifecycle events from InputManager and fires gesture signals.
|
|
11474
|
+
*/
|
|
11475
|
+
class GestureRecognizer {
|
|
11476
|
+
onPinch;
|
|
11477
|
+
onRotate;
|
|
11478
|
+
onLongPress;
|
|
11479
|
+
distanceThreshold;
|
|
11480
|
+
// Active touch pointers (only touch type; index in order of arrival).
|
|
11481
|
+
touchPointers = new Map();
|
|
11482
|
+
// Long-press state per pointer.
|
|
11483
|
+
longPressEntries = new Map();
|
|
11484
|
+
// Previous two-touch distance and angle for incremental deltas.
|
|
11485
|
+
prevDistance = -1;
|
|
11486
|
+
prevAngle = 0;
|
|
11487
|
+
// Reusable Vector for center dispatches (avoids heap churn).
|
|
11488
|
+
centerVec = new Vector();
|
|
11489
|
+
constructor(distanceThreshold, onPinch, onRotate, onLongPress) {
|
|
11490
|
+
this.distanceThreshold = distanceThreshold;
|
|
11491
|
+
this.onPinch = onPinch;
|
|
11492
|
+
this.onRotate = onRotate;
|
|
11493
|
+
this.onLongPress = onLongPress;
|
|
11494
|
+
}
|
|
11495
|
+
onPointerDown(pointer) {
|
|
11496
|
+
if (pointer.type === 'touch') {
|
|
11497
|
+
this.touchPointers.set(pointer.id, pointer);
|
|
11498
|
+
this._resetTwoTouchBaseline();
|
|
11499
|
+
}
|
|
11500
|
+
// Start long-press timer for every pointer type.
|
|
11501
|
+
const timerId = setTimeout(() => {
|
|
11502
|
+
this.longPressEntries.delete(pointer.id);
|
|
11503
|
+
this.onLongPress.dispatch(pointer);
|
|
11504
|
+
}, longPressMs);
|
|
11505
|
+
this.longPressEntries.set(pointer.id, {
|
|
11506
|
+
pointerId: pointer.id,
|
|
11507
|
+
pointer,
|
|
11508
|
+
timerId,
|
|
11509
|
+
startX: pointer.x,
|
|
11510
|
+
startY: pointer.y,
|
|
11511
|
+
});
|
|
11512
|
+
}
|
|
11513
|
+
onPointerMove(pointer, distanceThreshold) {
|
|
11514
|
+
// Cancel long-press if moved beyond threshold.
|
|
11515
|
+
const entry = this.longPressEntries.get(pointer.id);
|
|
11516
|
+
if (entry) {
|
|
11517
|
+
const dx = pointer.x - entry.startX;
|
|
11518
|
+
const dy = pointer.y - entry.startY;
|
|
11519
|
+
if (Math.sqrt(dx * dx + dy * dy) > distanceThreshold) {
|
|
11520
|
+
clearTimeout(entry.timerId);
|
|
11521
|
+
this.longPressEntries.delete(pointer.id);
|
|
11522
|
+
}
|
|
11523
|
+
}
|
|
11524
|
+
if (pointer.type !== 'touch') {
|
|
11525
|
+
return;
|
|
11526
|
+
}
|
|
11527
|
+
// Update the stored pointer reference's position via the live object.
|
|
11528
|
+
// (We store the actual Pointer object so position is already updated by the caller.)
|
|
11529
|
+
if (this.touchPointers.size < 2) {
|
|
11530
|
+
return;
|
|
11531
|
+
}
|
|
11532
|
+
this._processTwoTouchGestures();
|
|
11533
|
+
}
|
|
11534
|
+
onPointerUp(pointer) {
|
|
11535
|
+
this._cancelLongPress(pointer.id);
|
|
11536
|
+
}
|
|
11537
|
+
onPointerLeave(pointer) {
|
|
11538
|
+
this._cancelLongPress(pointer.id);
|
|
11539
|
+
if (pointer.type === 'touch') {
|
|
11540
|
+
this.touchPointers.delete(pointer.id);
|
|
11541
|
+
this._resetTwoTouchBaseline();
|
|
11542
|
+
}
|
|
11543
|
+
}
|
|
11544
|
+
onPointerCancel(pointer) {
|
|
11545
|
+
this._cancelLongPress(pointer.id);
|
|
11546
|
+
if (pointer.type === 'touch') {
|
|
11547
|
+
this.touchPointers.delete(pointer.id);
|
|
11548
|
+
this._resetTwoTouchBaseline();
|
|
11549
|
+
}
|
|
11550
|
+
}
|
|
11551
|
+
destroy() {
|
|
11552
|
+
for (const entry of this.longPressEntries.values()) {
|
|
11553
|
+
clearTimeout(entry.timerId);
|
|
11554
|
+
}
|
|
11555
|
+
this.longPressEntries.clear();
|
|
11556
|
+
this.touchPointers.clear();
|
|
11557
|
+
this.centerVec.destroy();
|
|
11558
|
+
}
|
|
11559
|
+
_cancelLongPress(pointerId) {
|
|
11560
|
+
const entry = this.longPressEntries.get(pointerId);
|
|
11561
|
+
if (entry) {
|
|
11562
|
+
clearTimeout(entry.timerId);
|
|
11563
|
+
this.longPressEntries.delete(pointerId);
|
|
11564
|
+
}
|
|
11565
|
+
}
|
|
11566
|
+
_resetTwoTouchBaseline() {
|
|
11567
|
+
this.prevDistance = -1;
|
|
11568
|
+
this.prevAngle = 0;
|
|
11569
|
+
}
|
|
11570
|
+
_processTwoTouchGestures() {
|
|
11571
|
+
const iter = this.touchPointers.values();
|
|
11572
|
+
const pA = iter.next().value;
|
|
11573
|
+
const pB = iter.next().value;
|
|
11574
|
+
const dx = pB.x - pA.x;
|
|
11575
|
+
const dy = pB.y - pA.y;
|
|
11576
|
+
const currentDistance = Math.sqrt(dx * dx + dy * dy);
|
|
11577
|
+
const currentAngle = Math.atan2(dy, dx);
|
|
11578
|
+
const centerX = (pA.x + pB.x) / 2;
|
|
11579
|
+
const centerY = (pA.y + pB.y) / 2;
|
|
11580
|
+
this.centerVec.set(centerX, centerY);
|
|
11581
|
+
if (this.prevDistance > 0) {
|
|
11582
|
+
const scale = currentDistance / this.prevDistance;
|
|
11583
|
+
// Only fire if there's a meaningful distance change.
|
|
11584
|
+
if (Math.abs(scale - 1) > 0.0001) {
|
|
11585
|
+
this.onPinch.dispatch(scale, this.centerVec);
|
|
11586
|
+
}
|
|
11587
|
+
const angleDelta = currentAngle - this.prevAngle;
|
|
11588
|
+
if (Math.abs(angleDelta) > 0.0001) {
|
|
11589
|
+
this.onRotate.dispatch(angleDelta, this.centerVec);
|
|
11590
|
+
}
|
|
11591
|
+
}
|
|
11592
|
+
this.prevDistance = currentDistance;
|
|
11593
|
+
this.prevAngle = currentAngle;
|
|
11594
|
+
}
|
|
11225
11595
|
}
|
|
11226
11596
|
|
|
11227
11597
|
var GamepadChannel;
|
|
@@ -11602,6 +11972,10 @@ class InputManager {
|
|
|
11602
11972
|
channelsPressed = [];
|
|
11603
11973
|
channelsReleased = [];
|
|
11604
11974
|
gamepadDefinitions;
|
|
11975
|
+
// Slot allocation for unified pointer tracking (mouse / touch / pen).
|
|
11976
|
+
pointerSlots = new Map(); // pointerId → slotIndex
|
|
11977
|
+
freeSlots = Array.from({ length: maxPointers }, (_, i) => i);
|
|
11978
|
+
gestureRecognizer;
|
|
11605
11979
|
canvasFocusedValue;
|
|
11606
11980
|
pointerDistanceThreshold;
|
|
11607
11981
|
keyDownHandler = this.handleKeyDown.bind(this);
|
|
@@ -11630,12 +12004,23 @@ class InputManager {
|
|
|
11630
12004
|
onGamepadConnected = new Signal();
|
|
11631
12005
|
onGamepadDisconnected = new Signal();
|
|
11632
12006
|
onGamepadUpdated = new Signal();
|
|
12007
|
+
/** Fires on every two-touch-pointer move where the distance between them changed. `scale` > 1 = spreading, < 1 = pinching. */
|
|
12008
|
+
onPinch = new Signal();
|
|
12009
|
+
/** Fires on every two-touch-pointer move where the angle between them changed. `angleDelta` is in radians. */
|
|
12010
|
+
onRotate = new Signal();
|
|
12011
|
+
/** Fires when a pointer has been held without significant movement for ≥ 500 ms. */
|
|
12012
|
+
onLongPress = new Signal();
|
|
11633
12013
|
constructor(app) {
|
|
11634
12014
|
const { gamepadDefinitions = [], pointerDistanceThreshold } = app.options;
|
|
11635
12015
|
this.canvas = app.canvas;
|
|
11636
12016
|
this.canvasFocusedValue = document.activeElement === this.canvas;
|
|
11637
12017
|
this.pointerDistanceThreshold = pointerDistanceThreshold;
|
|
11638
12018
|
this.gamepadDefinitions = [...gamepadDefinitions, ...builtInGamepadDefinitions];
|
|
12019
|
+
// Disable the browser's default pan/zoom/double-tap-zoom on touch devices so
|
|
12020
|
+
// pointer events reach the canvas without being swallowed by the browser's
|
|
12021
|
+
// native touch gestures.
|
|
12022
|
+
this.canvas.style.touchAction = 'none';
|
|
12023
|
+
this.gestureRecognizer = new GestureRecognizer(pointerDistanceThreshold, this.onPinch, this.onRotate, this.onLongPress);
|
|
11639
12024
|
this.addEventListeners();
|
|
11640
12025
|
}
|
|
11641
12026
|
get pointersInCanvas() {
|
|
@@ -11688,6 +12073,7 @@ class InputManager {
|
|
|
11688
12073
|
}
|
|
11689
12074
|
destroy() {
|
|
11690
12075
|
this.removeEventListeners();
|
|
12076
|
+
this.gestureRecognizer.destroy();
|
|
11691
12077
|
for (const pointer of Object.values(this.pointers)) {
|
|
11692
12078
|
pointer.destroy();
|
|
11693
12079
|
}
|
|
@@ -11699,6 +12085,8 @@ class InputManager {
|
|
|
11699
12085
|
this.gamepadsValue.length = 0;
|
|
11700
12086
|
this.channelsPressed.length = 0;
|
|
11701
12087
|
this.channelsReleased.length = 0;
|
|
12088
|
+
this.pointerSlots.clear();
|
|
12089
|
+
this.freeSlots.length = 0;
|
|
11702
12090
|
this.wheelOffset.destroy();
|
|
11703
12091
|
this.flags.destroy();
|
|
11704
12092
|
this.onPointerEnter.destroy();
|
|
@@ -11715,6 +12103,28 @@ class InputManager {
|
|
|
11715
12103
|
this.onGamepadConnected.destroy();
|
|
11716
12104
|
this.onGamepadDisconnected.destroy();
|
|
11717
12105
|
this.onGamepadUpdated.destroy();
|
|
12106
|
+
this.onPinch.destroy();
|
|
12107
|
+
this.onRotate.destroy();
|
|
12108
|
+
this.onLongPress.destroy();
|
|
12109
|
+
}
|
|
12110
|
+
_assignSlot(pointerId) {
|
|
12111
|
+
if (this.pointerSlots.has(pointerId)) {
|
|
12112
|
+
return this.pointerSlots.get(pointerId);
|
|
12113
|
+
}
|
|
12114
|
+
if (this.freeSlots.length === 0) {
|
|
12115
|
+
return null; // All 16 slots occupied — silently drop.
|
|
12116
|
+
}
|
|
12117
|
+
const slot = this.freeSlots.shift();
|
|
12118
|
+
this.pointerSlots.set(pointerId, slot);
|
|
12119
|
+
return slot;
|
|
12120
|
+
}
|
|
12121
|
+
_releaseSlot(pointerId) {
|
|
12122
|
+
const slot = this.pointerSlots.get(pointerId);
|
|
12123
|
+
if (slot !== undefined) {
|
|
12124
|
+
this.pointerSlots.delete(pointerId);
|
|
12125
|
+
// Push to the front so slot 0 is recovered first, keeping allocation predictable.
|
|
12126
|
+
this.freeSlots.unshift(slot);
|
|
12127
|
+
}
|
|
11718
12128
|
}
|
|
11719
12129
|
handleKeyDown(event) {
|
|
11720
12130
|
// Game-engine convention: keys only register while the canvas
|
|
@@ -11743,17 +12153,32 @@ class InputManager {
|
|
|
11743
12153
|
stopEvent(event);
|
|
11744
12154
|
}
|
|
11745
12155
|
handlePointerOver(event) {
|
|
11746
|
-
|
|
12156
|
+
const slot = this._assignSlot(event.pointerId);
|
|
12157
|
+
if (slot === null) {
|
|
12158
|
+
return; // 17th+ simultaneous pointer — silently drop.
|
|
12159
|
+
}
|
|
12160
|
+
this.pointers[event.pointerId] = new Pointer(event, this.canvas, this.channels, slot);
|
|
11747
12161
|
this.flags.push(InputManagerFlag.PointerUpdate);
|
|
11748
12162
|
}
|
|
11749
12163
|
handlePointerLeave(event) {
|
|
11750
|
-
this.pointers[event.pointerId]
|
|
12164
|
+
const pointer = this.pointers[event.pointerId];
|
|
12165
|
+
if (!pointer) {
|
|
12166
|
+
return;
|
|
12167
|
+
}
|
|
12168
|
+
pointer.handleLeave(event);
|
|
12169
|
+
this.gestureRecognizer.onPointerLeave(pointer);
|
|
12170
|
+
this._releaseSlot(event.pointerId);
|
|
11751
12171
|
this.flags.push(InputManagerFlag.PointerUpdate);
|
|
11752
12172
|
}
|
|
11753
12173
|
handlePointerDown(event) {
|
|
11754
12174
|
this.canvas.focus();
|
|
11755
12175
|
this.canvasFocusedValue = true;
|
|
11756
|
-
this.pointers[event.pointerId]
|
|
12176
|
+
const pointer = this.pointers[event.pointerId];
|
|
12177
|
+
if (!pointer) {
|
|
12178
|
+
return;
|
|
12179
|
+
}
|
|
12180
|
+
pointer.handlePress(event);
|
|
12181
|
+
this.gestureRecognizer.onPointerDown(pointer);
|
|
11757
12182
|
this.flags.push(InputManagerFlag.PointerUpdate);
|
|
11758
12183
|
// preventDefault stops native drag / text-selection;
|
|
11759
12184
|
// stopImmediatePropagation prevents bubbling to host-page click
|
|
@@ -11762,16 +12187,32 @@ class InputManager {
|
|
|
11762
12187
|
stopEvent(event);
|
|
11763
12188
|
}
|
|
11764
12189
|
handlePointerMove(event) {
|
|
11765
|
-
this.pointers[event.pointerId]
|
|
12190
|
+
const pointer = this.pointers[event.pointerId];
|
|
12191
|
+
if (!pointer) {
|
|
12192
|
+
return;
|
|
12193
|
+
}
|
|
12194
|
+
pointer.handleMove(event);
|
|
12195
|
+
this.gestureRecognizer.onPointerMove(pointer, this.pointerDistanceThreshold);
|
|
11766
12196
|
this.flags.push(InputManagerFlag.PointerUpdate);
|
|
11767
12197
|
}
|
|
11768
12198
|
handlePointerUp(event) {
|
|
11769
|
-
this.pointers[event.pointerId]
|
|
12199
|
+
const pointer = this.pointers[event.pointerId];
|
|
12200
|
+
if (!pointer) {
|
|
12201
|
+
return;
|
|
12202
|
+
}
|
|
12203
|
+
pointer.handleRelease(event);
|
|
12204
|
+
this.gestureRecognizer.onPointerUp(pointer);
|
|
11770
12205
|
this.flags.push(InputManagerFlag.PointerUpdate);
|
|
11771
12206
|
stopEvent(event);
|
|
11772
12207
|
}
|
|
11773
12208
|
handlePointerCancel(event) {
|
|
11774
|
-
this.pointers[event.pointerId]
|
|
12209
|
+
const pointer = this.pointers[event.pointerId];
|
|
12210
|
+
if (!pointer) {
|
|
12211
|
+
return;
|
|
12212
|
+
}
|
|
12213
|
+
pointer.handleCancel(event);
|
|
12214
|
+
this.gestureRecognizer.onPointerCancel(pointer);
|
|
12215
|
+
this._releaseSlot(event.pointerId);
|
|
11775
12216
|
this.flags.push(InputManagerFlag.PointerUpdate);
|
|
11776
12217
|
}
|
|
11777
12218
|
handleMouseWheel(event) {
|
|
@@ -18078,474 +18519,5 @@ class IndexedDbStore {
|
|
|
18078
18519
|
}
|
|
18079
18520
|
}
|
|
18080
18521
|
|
|
18081
|
-
|
|
18082
|
-
const maxCollisionGroup = 15;
|
|
18083
|
-
const fullGroupMask = 0xFFFF;
|
|
18084
|
-
const defaultDeltaSeconds = 1 / 60;
|
|
18085
|
-
const defaultDebugDrawOptions = {
|
|
18086
|
-
lineWidth: 1,
|
|
18087
|
-
solidLineColor: new Color(64, 196, 255, 1),
|
|
18088
|
-
solidFillColor: new Color(64, 196, 255, 0.12),
|
|
18089
|
-
triggerLineColor: new Color(255, 180, 48, 1),
|
|
18090
|
-
triggerFillColor: new Color(255, 180, 48, 0.08),
|
|
18091
|
-
};
|
|
18092
|
-
const resolveRapierModule = (module) => {
|
|
18093
|
-
const rapier = module;
|
|
18094
|
-
const vector2 = rapier.Vector2;
|
|
18095
|
-
const worldConstructor = rapier.World;
|
|
18096
|
-
const eventQueueConstructor = rapier.EventQueue;
|
|
18097
|
-
const rigidBodyDescFactory = rapier.RigidBodyDesc;
|
|
18098
|
-
const colliderDescFactory = rapier.ColliderDesc;
|
|
18099
|
-
if (typeof vector2 !== 'function' || typeof worldConstructor !== 'function' || typeof eventQueueConstructor !== 'function') {
|
|
18100
|
-
throw new Error('Invalid Rapier module loader result. Expected Vector2, World, and EventQueue exports.');
|
|
18101
|
-
}
|
|
18102
|
-
if (typeof rigidBodyDescFactory !== 'object'
|
|
18103
|
-
|| rigidBodyDescFactory === null
|
|
18104
|
-
|| typeof colliderDescFactory !== 'object'
|
|
18105
|
-
|| colliderDescFactory === null) {
|
|
18106
|
-
throw new Error('Invalid Rapier module loader result. Expected RigidBodyDesc and ColliderDesc exports.');
|
|
18107
|
-
}
|
|
18108
|
-
const activeEvents = rapier.ActiveEvents;
|
|
18109
|
-
const activeCollisionEvents = typeof activeEvents?.COLLISION_EVENTS === 'number'
|
|
18110
|
-
? activeEvents.COLLISION_EVENTS
|
|
18111
|
-
: undefined;
|
|
18112
|
-
return {
|
|
18113
|
-
init: typeof rapier.init === 'function'
|
|
18114
|
-
? rapier.init
|
|
18115
|
-
: undefined,
|
|
18116
|
-
vector2: vector2,
|
|
18117
|
-
worldConstructor: worldConstructor,
|
|
18118
|
-
eventQueueConstructor: eventQueueConstructor,
|
|
18119
|
-
rigidBodyDescFactory: rigidBodyDescFactory,
|
|
18120
|
-
colliderDescFactory: colliderDescFactory,
|
|
18121
|
-
activeCollisionEvents,
|
|
18122
|
-
};
|
|
18123
|
-
};
|
|
18124
|
-
const defaultRapierModuleLoader = async () => {
|
|
18125
|
-
return await import(rapierModuleName);
|
|
18126
|
-
};
|
|
18127
|
-
const assertFiniteNumber = (value, label) => {
|
|
18128
|
-
if (!Number.isFinite(value)) {
|
|
18129
|
-
throw new Error(`${label} must be a finite number.`);
|
|
18130
|
-
}
|
|
18131
|
-
};
|
|
18132
|
-
const assertPositiveNumber = (value, label) => {
|
|
18133
|
-
assertFiniteNumber(value, label);
|
|
18134
|
-
if (value <= 0) {
|
|
18135
|
-
throw new Error(`${label} must be greater than zero.`);
|
|
18136
|
-
}
|
|
18137
|
-
};
|
|
18138
|
-
const assertGroup = (group, label) => {
|
|
18139
|
-
if (!Number.isInteger(group) || group < 0 || group > maxCollisionGroup) {
|
|
18140
|
-
throw new Error(`${label} must be an integer between 0 and ${maxCollisionGroup}.`);
|
|
18141
|
-
}
|
|
18142
|
-
};
|
|
18143
|
-
const toGroupMask = (groups, fallback) => {
|
|
18144
|
-
if (groups === undefined) {
|
|
18145
|
-
return fallback;
|
|
18146
|
-
}
|
|
18147
|
-
if (typeof groups === 'number') {
|
|
18148
|
-
assertGroup(groups, 'collision group');
|
|
18149
|
-
return 1 << groups;
|
|
18150
|
-
}
|
|
18151
|
-
if (groups.length === 0) {
|
|
18152
|
-
return 0;
|
|
18153
|
-
}
|
|
18154
|
-
return groups.reduce((mask, group, index) => {
|
|
18155
|
-
assertGroup(group, `collision groups[${index}]`);
|
|
18156
|
-
return mask | (1 << group);
|
|
18157
|
-
}, 0);
|
|
18158
|
-
};
|
|
18159
|
-
const toPackedCollisionGroups = (filter) => {
|
|
18160
|
-
const membershipMask = toGroupMask(filter?.membership, 1 << 0);
|
|
18161
|
-
const collisionMask = toGroupMask(filter?.collidesWith, fullGroupMask);
|
|
18162
|
-
return ((membershipMask & fullGroupMask) << 16) | (collisionMask & fullGroupMask);
|
|
18163
|
-
};
|
|
18164
|
-
const getOffset = (shape) => ({
|
|
18165
|
-
x: shape.offsetX ?? 0,
|
|
18166
|
-
y: shape.offsetY ?? 0,
|
|
18167
|
-
});
|
|
18168
|
-
const rotatePoint = (x, y, rotation) => {
|
|
18169
|
-
const cos = Math.cos(rotation);
|
|
18170
|
-
const sin = Math.sin(rotation);
|
|
18171
|
-
return {
|
|
18172
|
-
x: (x * cos) - (y * sin),
|
|
18173
|
-
y: (x * sin) + (y * cos),
|
|
18174
|
-
};
|
|
18175
|
-
};
|
|
18176
|
-
const assertShape = (shape) => {
|
|
18177
|
-
if (shape.type === 'box') {
|
|
18178
|
-
assertPositiveNumber(shape.width, 'Box width');
|
|
18179
|
-
assertPositiveNumber(shape.height, 'Box height');
|
|
18180
|
-
assertFiniteNumber(shape.offsetX ?? 0, 'Box offsetX');
|
|
18181
|
-
assertFiniteNumber(shape.offsetY ?? 0, 'Box offsetY');
|
|
18182
|
-
assertFiniteNumber(shape.offsetRotation ?? 0, 'Box offsetRotation');
|
|
18183
|
-
return;
|
|
18184
|
-
}
|
|
18185
|
-
assertPositiveNumber(shape.radius, 'Circle radius');
|
|
18186
|
-
assertFiniteNumber(shape.offsetX ?? 0, 'Circle offsetX');
|
|
18187
|
-
assertFiniteNumber(shape.offsetY ?? 0, 'Circle offsetY');
|
|
18188
|
-
};
|
|
18189
|
-
const assertBodyOptions = (options) => {
|
|
18190
|
-
assertShape(options.shape);
|
|
18191
|
-
assertFiniteNumber(options.friction ?? 0, 'friction');
|
|
18192
|
-
assertFiniteNumber(options.restitution ?? 0, 'restitution');
|
|
18193
|
-
assertFiniteNumber(options.density ?? 0, 'density');
|
|
18194
|
-
assertFiniteNumber(options.gravityScale ?? 1, 'gravityScale');
|
|
18195
|
-
assertFiniteNumber(options.linearDamping ?? 0, 'linearDamping');
|
|
18196
|
-
assertFiniteNumber(options.angularDamping ?? 0, 'angularDamping');
|
|
18197
|
-
toPackedCollisionGroups(options.collisionFilter);
|
|
18198
|
-
};
|
|
18199
|
-
class RapierPhysicsBinding {
|
|
18200
|
-
_world;
|
|
18201
|
-
_body;
|
|
18202
|
-
_collider;
|
|
18203
|
-
_syncMode;
|
|
18204
|
-
node;
|
|
18205
|
-
bodyType;
|
|
18206
|
-
shape;
|
|
18207
|
-
trigger;
|
|
18208
|
-
constructor(world, node, body, collider, options) {
|
|
18209
|
-
this._world = world;
|
|
18210
|
-
this.node = node;
|
|
18211
|
-
this._body = body;
|
|
18212
|
-
this._collider = collider;
|
|
18213
|
-
this.bodyType = options.type ?? 'dynamic';
|
|
18214
|
-
this.shape = options.shape;
|
|
18215
|
-
this.trigger = options.trigger ?? false;
|
|
18216
|
-
this._syncMode = options.syncMode ?? 'physicsToNode';
|
|
18217
|
-
}
|
|
18218
|
-
get bodyHandle() {
|
|
18219
|
-
return this._body.handle;
|
|
18220
|
-
}
|
|
18221
|
-
get colliderHandle() {
|
|
18222
|
-
return this._collider.handle;
|
|
18223
|
-
}
|
|
18224
|
-
getBody() {
|
|
18225
|
-
return this._body;
|
|
18226
|
-
}
|
|
18227
|
-
get syncMode() {
|
|
18228
|
-
return this._syncMode;
|
|
18229
|
-
}
|
|
18230
|
-
set syncMode(syncMode) {
|
|
18231
|
-
this._syncMode = syncMode;
|
|
18232
|
-
}
|
|
18233
|
-
get x() {
|
|
18234
|
-
return this._body.translation().x;
|
|
18235
|
-
}
|
|
18236
|
-
get y() {
|
|
18237
|
-
return this._body.translation().y;
|
|
18238
|
-
}
|
|
18239
|
-
get rotation() {
|
|
18240
|
-
return this._body.rotation();
|
|
18241
|
-
}
|
|
18242
|
-
setSyncMode(syncMode) {
|
|
18243
|
-
this._syncMode = syncMode;
|
|
18244
|
-
return this;
|
|
18245
|
-
}
|
|
18246
|
-
teleport(x, y, rotation = this.node.rotation) {
|
|
18247
|
-
this._world.writeBodyTransform(this._body, x, y, rotation, true);
|
|
18248
|
-
this.node.setPosition(x, y);
|
|
18249
|
-
this.node.setRotation(rotation);
|
|
18250
|
-
return this;
|
|
18251
|
-
}
|
|
18252
|
-
syncBodyFromNode(wakeUp = true) {
|
|
18253
|
-
this._world.writeBodyTransform(this._body, this.node.x, this.node.y, this.node.rotation, wakeUp);
|
|
18254
|
-
return this;
|
|
18255
|
-
}
|
|
18256
|
-
syncNodeFromBody() {
|
|
18257
|
-
const translation = this._body.translation();
|
|
18258
|
-
this.node.setPosition(translation.x, translation.y);
|
|
18259
|
-
this.node.setRotation(this._body.rotation());
|
|
18260
|
-
return this;
|
|
18261
|
-
}
|
|
18262
|
-
setCollisionFilter(filter) {
|
|
18263
|
-
const groups = toPackedCollisionGroups(filter);
|
|
18264
|
-
this._collider.setCollisionGroups(groups);
|
|
18265
|
-
this._collider.setSolverGroups(groups);
|
|
18266
|
-
return this;
|
|
18267
|
-
}
|
|
18268
|
-
destroy() {
|
|
18269
|
-
this._world.removeBinding(this);
|
|
18270
|
-
}
|
|
18271
|
-
}
|
|
18272
|
-
class RapierPhysicsWorld {
|
|
18273
|
-
onCollisionEnter = new Signal();
|
|
18274
|
-
onCollisionExit = new Signal();
|
|
18275
|
-
onTriggerEnter = new Signal();
|
|
18276
|
-
onTriggerExit = new Signal();
|
|
18277
|
-
_rapier;
|
|
18278
|
-
_world;
|
|
18279
|
-
_eventQueue;
|
|
18280
|
-
_bindings = new Set();
|
|
18281
|
-
_nodeBindings = new Map();
|
|
18282
|
-
_colliderBindings = new Map();
|
|
18283
|
-
constructor(rapier, world, eventQueue) {
|
|
18284
|
-
this._rapier = rapier;
|
|
18285
|
-
this._world = world;
|
|
18286
|
-
this._eventQueue = eventQueue;
|
|
18287
|
-
}
|
|
18288
|
-
static async create(options = {}) {
|
|
18289
|
-
const moduleLoader = options.moduleLoader ?? defaultRapierModuleLoader;
|
|
18290
|
-
let loadedModule = null;
|
|
18291
|
-
try {
|
|
18292
|
-
loadedModule = await moduleLoader();
|
|
18293
|
-
}
|
|
18294
|
-
catch (error) {
|
|
18295
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
18296
|
-
throw new Error(`Rapier physics module is unavailable. Install "${rapierModuleName}" or provide a custom module loader. Original error: ${message}`, { cause: error });
|
|
18297
|
-
}
|
|
18298
|
-
const rapier = resolveRapierModule(loadedModule);
|
|
18299
|
-
if (typeof rapier.init === 'function') {
|
|
18300
|
-
await rapier.init();
|
|
18301
|
-
}
|
|
18302
|
-
const gravityX = options.gravityX ?? 0;
|
|
18303
|
-
const gravityY = options.gravityY ?? 9.81;
|
|
18304
|
-
assertFiniteNumber(gravityX, 'gravityX');
|
|
18305
|
-
assertFiniteNumber(gravityY, 'gravityY');
|
|
18306
|
-
const world = new rapier.worldConstructor(new rapier.vector2(gravityX, gravityY));
|
|
18307
|
-
const eventQueue = new rapier.eventQueueConstructor(true);
|
|
18308
|
-
return new RapierPhysicsWorld(rapier, world, eventQueue);
|
|
18309
|
-
}
|
|
18310
|
-
get gravity() {
|
|
18311
|
-
return {
|
|
18312
|
-
x: this._world.gravity.x,
|
|
18313
|
-
y: this._world.gravity.y,
|
|
18314
|
-
};
|
|
18315
|
-
}
|
|
18316
|
-
setGravity(x, y) {
|
|
18317
|
-
assertFiniteNumber(x, 'gravityX');
|
|
18318
|
-
assertFiniteNumber(y, 'gravityY');
|
|
18319
|
-
this._world.gravity.x = x;
|
|
18320
|
-
this._world.gravity.y = y;
|
|
18321
|
-
return this;
|
|
18322
|
-
}
|
|
18323
|
-
hasNode(node) {
|
|
18324
|
-
return this._nodeBindings.has(node);
|
|
18325
|
-
}
|
|
18326
|
-
getBinding(node) {
|
|
18327
|
-
return this._nodeBindings.get(node) ?? null;
|
|
18328
|
-
}
|
|
18329
|
-
attachNode(node, options) {
|
|
18330
|
-
if (this._nodeBindings.has(node)) {
|
|
18331
|
-
throw new Error('This SceneNode is already attached to a physics body.');
|
|
18332
|
-
}
|
|
18333
|
-
assertBodyOptions(options);
|
|
18334
|
-
const bodyDescriptor = this.createBodyDescriptor(node, options);
|
|
18335
|
-
const body = this._world.createRigidBody(bodyDescriptor);
|
|
18336
|
-
const colliderDescriptor = this.createColliderDescriptor(options);
|
|
18337
|
-
const collider = this._world.createCollider(colliderDescriptor, body);
|
|
18338
|
-
const binding = new RapierPhysicsBinding(this, node, body, collider, options);
|
|
18339
|
-
this._bindings.add(binding);
|
|
18340
|
-
this._nodeBindings.set(node, binding);
|
|
18341
|
-
this._colliderBindings.set(collider.handle, binding);
|
|
18342
|
-
return binding;
|
|
18343
|
-
}
|
|
18344
|
-
detachNode(node) {
|
|
18345
|
-
const binding = this._nodeBindings.get(node);
|
|
18346
|
-
if (binding) {
|
|
18347
|
-
this.removeBinding(binding);
|
|
18348
|
-
}
|
|
18349
|
-
return this;
|
|
18350
|
-
}
|
|
18351
|
-
step(deltaSeconds = defaultDeltaSeconds) {
|
|
18352
|
-
assertFiniteNumber(deltaSeconds, 'deltaSeconds');
|
|
18353
|
-
if (deltaSeconds < 0) {
|
|
18354
|
-
throw new Error('deltaSeconds must be zero or greater.');
|
|
18355
|
-
}
|
|
18356
|
-
this.applyStepDelta(deltaSeconds);
|
|
18357
|
-
this._world.step(this._eventQueue);
|
|
18358
|
-
this.drainCollisionEvents();
|
|
18359
|
-
this.syncNodeTransforms();
|
|
18360
|
-
return this;
|
|
18361
|
-
}
|
|
18362
|
-
syncNodeTransforms() {
|
|
18363
|
-
for (const binding of this._bindings) {
|
|
18364
|
-
if (binding.syncMode === 'physicsToNode') {
|
|
18365
|
-
binding.syncNodeFromBody();
|
|
18366
|
-
}
|
|
18367
|
-
}
|
|
18368
|
-
return this;
|
|
18369
|
-
}
|
|
18370
|
-
createDebugGraphics(options = {}) {
|
|
18371
|
-
const graphics = new Graphics();
|
|
18372
|
-
graphics.setCullable(false);
|
|
18373
|
-
this.updateDebugGraphics(graphics, options);
|
|
18374
|
-
return graphics;
|
|
18375
|
-
}
|
|
18376
|
-
updateDebugGraphics(graphics, options = {}) {
|
|
18377
|
-
const lineWidth = options.lineWidth ?? defaultDebugDrawOptions.lineWidth;
|
|
18378
|
-
const solidLineColor = options.solidLineColor ?? defaultDebugDrawOptions.solidLineColor;
|
|
18379
|
-
const solidFillColor = options.solidFillColor ?? defaultDebugDrawOptions.solidFillColor;
|
|
18380
|
-
const triggerLineColor = options.triggerLineColor ?? defaultDebugDrawOptions.triggerLineColor;
|
|
18381
|
-
const triggerFillColor = options.triggerFillColor ?? defaultDebugDrawOptions.triggerFillColor;
|
|
18382
|
-
graphics.clear();
|
|
18383
|
-
graphics.lineWidth = lineWidth;
|
|
18384
|
-
for (const binding of this._bindings) {
|
|
18385
|
-
const bodyTranslation = {
|
|
18386
|
-
x: binding.x,
|
|
18387
|
-
y: binding.y,
|
|
18388
|
-
};
|
|
18389
|
-
const rotation = binding.rotation;
|
|
18390
|
-
const lineColor = binding.trigger ? triggerLineColor : solidLineColor;
|
|
18391
|
-
const fillColor = binding.trigger ? triggerFillColor : solidFillColor;
|
|
18392
|
-
graphics.lineColor = lineColor;
|
|
18393
|
-
graphics.fillColor = fillColor;
|
|
18394
|
-
if (binding.shape.type === 'box') {
|
|
18395
|
-
const path = this.buildBoxPath(binding.shape, bodyTranslation.x, bodyTranslation.y, rotation);
|
|
18396
|
-
graphics.drawPolygon(path);
|
|
18397
|
-
}
|
|
18398
|
-
else {
|
|
18399
|
-
const offset = getOffset(binding.shape);
|
|
18400
|
-
const rotatedOffset = rotatePoint(offset.x, offset.y, rotation);
|
|
18401
|
-
graphics.drawCircle(bodyTranslation.x + rotatedOffset.x, bodyTranslation.y + rotatedOffset.y, binding.shape.radius);
|
|
18402
|
-
}
|
|
18403
|
-
}
|
|
18404
|
-
return graphics;
|
|
18405
|
-
}
|
|
18406
|
-
destroy() {
|
|
18407
|
-
for (const binding of Array.from(this._bindings)) {
|
|
18408
|
-
this.removeBinding(binding);
|
|
18409
|
-
}
|
|
18410
|
-
this.onCollisionEnter.destroy();
|
|
18411
|
-
this.onCollisionExit.destroy();
|
|
18412
|
-
this.onTriggerEnter.destroy();
|
|
18413
|
-
this.onTriggerExit.destroy();
|
|
18414
|
-
}
|
|
18415
|
-
writeBodyTransform(body, x, y, rotation, wakeUp) {
|
|
18416
|
-
body.setTranslation(new this._rapier.vector2(x, y), wakeUp);
|
|
18417
|
-
body.setRotation(rotation, wakeUp);
|
|
18418
|
-
}
|
|
18419
|
-
removeBinding(binding) {
|
|
18420
|
-
if (!this._bindings.has(binding)) {
|
|
18421
|
-
return;
|
|
18422
|
-
}
|
|
18423
|
-
this._bindings.delete(binding);
|
|
18424
|
-
this._nodeBindings.delete(binding.node);
|
|
18425
|
-
this._colliderBindings.delete(binding.colliderHandle);
|
|
18426
|
-
this._world.removeRigidBody(binding.getBody());
|
|
18427
|
-
}
|
|
18428
|
-
createBodyDescriptor(node, options) {
|
|
18429
|
-
const type = options.type ?? 'dynamic';
|
|
18430
|
-
let descriptor = this._rapier.rigidBodyDescFactory.dynamic();
|
|
18431
|
-
switch (type) {
|
|
18432
|
-
case 'static':
|
|
18433
|
-
descriptor = this._rapier.rigidBodyDescFactory.fixed();
|
|
18434
|
-
break;
|
|
18435
|
-
case 'kinematic':
|
|
18436
|
-
if (typeof this._rapier.rigidBodyDescFactory.kinematicPositionBased === 'function') {
|
|
18437
|
-
descriptor = this._rapier.rigidBodyDescFactory.kinematicPositionBased();
|
|
18438
|
-
}
|
|
18439
|
-
else if (typeof this._rapier.rigidBodyDescFactory.kinematicVelocityBased === 'function') {
|
|
18440
|
-
descriptor = this._rapier.rigidBodyDescFactory.kinematicVelocityBased();
|
|
18441
|
-
}
|
|
18442
|
-
else {
|
|
18443
|
-
throw new Error('Rapier module does not expose a kinematic rigid-body descriptor.');
|
|
18444
|
-
}
|
|
18445
|
-
break;
|
|
18446
|
-
default:
|
|
18447
|
-
descriptor = this._rapier.rigidBodyDescFactory.dynamic();
|
|
18448
|
-
break;
|
|
18449
|
-
}
|
|
18450
|
-
descriptor
|
|
18451
|
-
.setTranslation(node.x, node.y)
|
|
18452
|
-
.setRotation(node.rotation)
|
|
18453
|
-
.setLinearDamping(options.linearDamping ?? 0)
|
|
18454
|
-
.setAngularDamping(options.angularDamping ?? 0)
|
|
18455
|
-
.setGravityScale(options.gravityScale ?? 1)
|
|
18456
|
-
.lockRotations(options.lockRotation ?? false);
|
|
18457
|
-
return descriptor;
|
|
18458
|
-
}
|
|
18459
|
-
createColliderDescriptor(options) {
|
|
18460
|
-
const shape = options.shape;
|
|
18461
|
-
const descriptor = shape.type === 'box'
|
|
18462
|
-
? this._rapier.colliderDescFactory.cuboid(shape.width / 2, shape.height / 2)
|
|
18463
|
-
: this._rapier.colliderDescFactory.ball(shape.radius);
|
|
18464
|
-
const offset = getOffset(shape);
|
|
18465
|
-
const groups = toPackedCollisionGroups(options.collisionFilter);
|
|
18466
|
-
descriptor
|
|
18467
|
-
.setTranslation(offset.x, offset.y)
|
|
18468
|
-
.setRotation(shape.type === 'box' ? (shape.offsetRotation ?? 0) : 0)
|
|
18469
|
-
.setSensor(options.trigger ?? false)
|
|
18470
|
-
.setFriction(options.friction ?? 0.5)
|
|
18471
|
-
.setRestitution(options.restitution ?? 0)
|
|
18472
|
-
.setDensity(options.density ?? 1)
|
|
18473
|
-
.setCollisionGroups(groups)
|
|
18474
|
-
.setSolverGroups(groups);
|
|
18475
|
-
const collisionEvents = this._rapier.activeCollisionEvents;
|
|
18476
|
-
if (typeof collisionEvents === 'number') {
|
|
18477
|
-
descriptor.setActiveEvents(collisionEvents);
|
|
18478
|
-
}
|
|
18479
|
-
return descriptor;
|
|
18480
|
-
}
|
|
18481
|
-
applyStepDelta(deltaSeconds) {
|
|
18482
|
-
const worldWithTimestep = this._world;
|
|
18483
|
-
if (typeof worldWithTimestep.timestep === 'number') {
|
|
18484
|
-
worldWithTimestep.timestep = deltaSeconds;
|
|
18485
|
-
}
|
|
18486
|
-
if (worldWithTimestep.integrationParameters
|
|
18487
|
-
&& typeof worldWithTimestep.integrationParameters.dt === 'number') {
|
|
18488
|
-
worldWithTimestep.integrationParameters.dt = deltaSeconds;
|
|
18489
|
-
}
|
|
18490
|
-
}
|
|
18491
|
-
drainCollisionEvents() {
|
|
18492
|
-
this._eventQueue.drainCollisionEvents((handleA, handleB, started) => {
|
|
18493
|
-
const first = this._colliderBindings.get(handleA);
|
|
18494
|
-
const second = this._colliderBindings.get(handleB);
|
|
18495
|
-
if (!first || !second) {
|
|
18496
|
-
return;
|
|
18497
|
-
}
|
|
18498
|
-
const trigger = first.trigger || second.trigger;
|
|
18499
|
-
const event = {
|
|
18500
|
-
started,
|
|
18501
|
-
trigger,
|
|
18502
|
-
first,
|
|
18503
|
-
second,
|
|
18504
|
-
};
|
|
18505
|
-
if (trigger) {
|
|
18506
|
-
if (started) {
|
|
18507
|
-
this.onTriggerEnter.dispatch(event);
|
|
18508
|
-
}
|
|
18509
|
-
else {
|
|
18510
|
-
this.onTriggerExit.dispatch(event);
|
|
18511
|
-
}
|
|
18512
|
-
return;
|
|
18513
|
-
}
|
|
18514
|
-
if (started) {
|
|
18515
|
-
this.onCollisionEnter.dispatch(event);
|
|
18516
|
-
}
|
|
18517
|
-
else {
|
|
18518
|
-
this.onCollisionExit.dispatch(event);
|
|
18519
|
-
}
|
|
18520
|
-
});
|
|
18521
|
-
}
|
|
18522
|
-
buildBoxPath(shape, bodyX, bodyY, bodyRotation) {
|
|
18523
|
-
const halfWidth = shape.width / 2;
|
|
18524
|
-
const halfHeight = shape.height / 2;
|
|
18525
|
-
const corners = [
|
|
18526
|
-
{ x: -halfWidth, y: -halfHeight },
|
|
18527
|
-
{ x: halfWidth, y: -halfHeight },
|
|
18528
|
-
{ x: halfWidth, y: halfHeight },
|
|
18529
|
-
{ x: -halfWidth, y: halfHeight },
|
|
18530
|
-
];
|
|
18531
|
-
const offset = getOffset(shape);
|
|
18532
|
-
const offsetRotation = shape.offsetRotation ?? 0;
|
|
18533
|
-
const path = [];
|
|
18534
|
-
for (const corner of corners) {
|
|
18535
|
-
const local = rotatePoint(corner.x, corner.y, offsetRotation);
|
|
18536
|
-
const withOffset = {
|
|
18537
|
-
x: local.x + offset.x,
|
|
18538
|
-
y: local.y + offset.y,
|
|
18539
|
-
};
|
|
18540
|
-
const worldPoint = rotatePoint(withOffset.x, withOffset.y, bodyRotation);
|
|
18541
|
-
path.push(bodyX + worldPoint.x, bodyY + worldPoint.y);
|
|
18542
|
-
}
|
|
18543
|
-
return path;
|
|
18544
|
-
}
|
|
18545
|
-
}
|
|
18546
|
-
const createRapierPhysicsWorld = async (options = {}) => {
|
|
18547
|
-
return await RapierPhysicsWorld.create(options);
|
|
18548
|
-
};
|
|
18549
|
-
|
|
18550
|
-
export { AbstractAssetFactory, AbstractMedia, AbstractWebGl2BatchedRenderer, AbstractWebGl2Renderer, AbstractWebGpuRenderer, AnimatedSprite, Application, ApplicationStatus, ArcadeStickGamepadMapping, AudioAnalyser, BinaryFactory, BlendModes, BlurFilter, Bounds, BufferTypes, BufferUsage, BundleLoadError, CacheFirstStrategy, CallbackRenderPass, Capabilities, ChannelOffset, ChannelSize, Circle, Clock, CollisionType, Color, ColorAffector, ColorFilter, Container, Drawable, Ellipse, FactoryRegistry, Filter, Flags, FontFactory, ForceAffector, GameCubeGamepadMapping, Gamepad, GamepadChannel, GamepadControl, GamepadMapping, GamepadMappingFamily, GamepadPromptLayouts, GenericDualAnalogGamepadMapping, Graphics, ImageFactory, IndexedDbDatabase, IndexedDbStore, Input, InputManager, Interval, JoyConLeftGamepadMapping, JoyConRightGamepadMapping, Json, JsonFactory, Keyboard, Line, Loader, Matrix, Mesh, Music, MusicFactory, NetworkOnlyStrategy, ObservableSize, ObservableVector, Particle, ParticleOptions, ParticleSystem, PlayStationGamepadMapping, Pointer, PointerState, PointerStateFlag, PolarVector, Polygon, Quadtree, Random, RapierPhysicsBinding, RapierPhysicsWorld, Rectangle, RenderBackendType, RenderNode, RenderTarget, RenderTargetPass, RenderTexture, RendererRegistry, RenderingPrimitives, Sampler, ScaleAffector, ScaleModes, Scene, SceneManager, SceneNode, Segment, Shader, ShaderAttribute, ShaderPrimitives, ShaderUniform, Signal, Size, Sound, SoundFactory, Sprite, SpriteFlags, Spritesheet, SteamControllerGamepadMapping, SvgAsset, SvgFactory, SwitchProGamepadMapping, Text, TextAsset, TextFactory, TextStyle, Texture, TextureFactory, Time, Timer, TorqueAffector, UniversalEmitter, Vector, Video, VideoFactory, View, ViewFlags, VoronoiRegion, VttAsset, VttFactory, WasmFactory, WebGl2Backend, WebGl2MeshRenderer, WebGl2ParticleRenderer, WebGl2RenderBuffer, WebGl2ShaderBlock, WebGl2SpriteRenderer, WebGl2VertexArrayObject, WebGpuBackend, WebGpuMeshRenderer, WebGpuParticleRenderer, WebGpuSpriteRenderer, WrapModes, XboxGamepadMapping, bezierCurveTo, buildCircle, buildEllipse, buildLine, buildPath, buildPolygon, buildRectangle, buildStar, builtInGamepadDefinitions, canvasSourceToDataUrl, clamp, createRapierPhysicsWorld, createRenderStats, createWebGl2ShaderProgram, decodeAudioData, defineAssetManifest, degreesPerRadian, degreesToRadians, determineMimeType, emptyArrayBuffer, getAudioContext, getCanvasSourceSize, getCollisionCircleCircle, getCollisionCircleRectangle, getCollisionPolygonCircle, getCollisionRectangleRectangle, getCollisionSat, getDistance, getOfflineAudioContext, getPreciseTime, getTextureSourceSize, getVoronoiRegion$1 as getVoronoiRegion, getWebGpuBlendState, hours, inRange, intersectionCircleCircle, intersectionCircleEllipse, intersectionCirclePoly, intersectionEllipseEllipse, intersectionEllipsePoly, intersectionLineCircle, intersectionLineEllipse, intersectionLineLine, intersectionLinePoly, intersectionLineRect, intersectionPointCircle, intersectionPointEllipse, intersectionPointLine, intersectionPointPoint, intersectionPointPoly, intersectionPointRect, intersectionPolyPoly, intersectionRectCircle, intersectionRectEllipse, intersectionRectPoly, intersectionRectRect, intersectionSat, isAudioContextReady, isPowerOfTwo, lerp, matchesIds, milliseconds, minutes, noop$1 as noop, normalizeIds, onAudioContextReady, parseGamepadDescriptor, quadraticCurveTo, radiansPerDegree, radiansToDegrees, rand, removeArrayItems, resetRenderStats, resolveDefinition, resolveGamepadDefinition, seconds, sign$1 as sign, stopEvent, supportsCodec, supportsEventOptions, supportsIndexedDb, supportsPointerEvents, supportsTouchEvents, supportsWebAudio, tau, trimRotation, webGl2PrimitiveArrayConstructors, webGl2PrimitiveByteSizeMapping, webGl2PrimitiveTypeNames };
|
|
18522
|
+
export { AbstractAssetFactory, AbstractMedia, AbstractWebGl2BatchedRenderer, AbstractWebGl2Renderer, AbstractWebGpuRenderer, AnimatedSprite, Application, ApplicationStatus, ArcadeStickGamepadMapping, AudioAnalyser, BinaryFactory, BlendModes, BlurFilter, Bounds, BufferTypes, BufferUsage, BundleLoadError, CacheFirstStrategy, CallbackRenderPass, Capabilities, ChannelOffset, ChannelSize, Circle, Clock, CollisionType, Color, ColorAffector, ColorFilter, Container, Drawable, Ellipse, FactoryRegistry, Filter, Flags, FontFactory, ForceAffector, GameCubeGamepadMapping, Gamepad, GamepadChannel, GamepadControl, GamepadMapping, GamepadMappingFamily, GamepadPromptLayouts, GenericDualAnalogGamepadMapping, Graphics, ImageFactory, IndexedDbDatabase, IndexedDbStore, Input, InputManager, Interval, JoyConLeftGamepadMapping, JoyConRightGamepadMapping, Json, JsonFactory, Keyboard, Line, Loader, Matrix, Mesh, Music, MusicFactory, NetworkOnlyStrategy, ObservableSize, ObservableVector, Particle, ParticleOptions, ParticleSystem, PlayStationGamepadMapping, Pointer, PointerState, PointerStateFlag, PolarVector, Polygon, Quadtree, Random, Rectangle, RenderBackendType, RenderNode, RenderTarget, RenderTargetPass, RenderTexture, RendererRegistry, RenderingPrimitives, Sampler, ScaleAffector, ScaleModes, Scene, SceneManager, SceneNode, Segment, Shader, ShaderAttribute, ShaderPrimitives, ShaderUniform, Signal, Size, Sound, SoundFactory, Sprite, SpriteFlags, Spritesheet, SteamControllerGamepadMapping, SvgAsset, SvgFactory, SwitchProGamepadMapping, Text, TextAsset, TextFactory, TextStyle, Texture, TextureFactory, Time, Timer, TorqueAffector, UniversalEmitter, Vector, Video, VideoFactory, View, ViewFlags, VoronoiRegion, VttAsset, VttFactory, WasmFactory, WebGl2Backend, WebGl2MeshRenderer, WebGl2ParticleRenderer, WebGl2RenderBuffer, WebGl2ShaderBlock, WebGl2SpriteRenderer, WebGl2VertexArrayObject, WebGpuBackend, WebGpuMeshRenderer, WebGpuParticleRenderer, WebGpuSpriteRenderer, WrapModes, XboxGamepadMapping, bezierCurveTo, buildCircle, buildEllipse, buildLine, buildPath, buildPolygon, buildRectangle, buildStar, builtInGamepadDefinitions, canvasSourceToDataUrl, clamp, createRenderStats, createWebGl2ShaderProgram, decodeAudioData, defineAssetManifest, degreesPerRadian, degreesToRadians, determineMimeType, emptyArrayBuffer, getAudioContext, getCanvasSourceSize, getCollisionCircleCircle, getCollisionCircleRectangle, getCollisionPolygonCircle, getCollisionRectangleRectangle, getCollisionSat, getDistance, getOfflineAudioContext, getPreciseTime, getTextureSourceSize, getVoronoiRegion$1 as getVoronoiRegion, getWebGpuBlendState, hours, inRange, intersectionCircleCircle, intersectionCircleEllipse, intersectionCirclePoly, intersectionEllipseEllipse, intersectionEllipsePoly, intersectionLineCircle, intersectionLineEllipse, intersectionLineLine, intersectionLinePoly, intersectionLineRect, intersectionPointCircle, intersectionPointEllipse, intersectionPointLine, intersectionPointPoint, intersectionPointPoly, intersectionPointRect, intersectionPolyPoly, intersectionRectCircle, intersectionRectEllipse, intersectionRectPoly, intersectionRectRect, intersectionSat, isAudioContextReady, isPowerOfTwo, lerp, matchesIds, maxPointers, milliseconds, minutes, noop$1 as noop, normalizeIds, onAudioContextReady, parseGamepadDescriptor, pointerSlotSize, quadraticCurveTo, radiansPerDegree, radiansToDegrees, rand, removeArrayItems, resetRenderStats, resolveDefinition, resolveGamepadDefinition, seconds, sign$1 as sign, stopEvent, supportsCodec, supportsEventOptions, supportsIndexedDb, supportsPointerEvents, supportsTouchEvents, supportsWebAudio, tau, trimRotation, webGl2PrimitiveArrayConstructors, webGl2PrimitiveByteSizeMapping, webGl2PrimitiveTypeNames };
|
|
18551
18523
|
//# sourceMappingURL=exo.esm.js.map
|