melonjs 20.0.0 → 20.1.1
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/build/camera/effects/fade_effect.d.ts.map +1 -1
- package/build/camera/effects/mask_effect.d.ts.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +459 -46
- package/build/index.js.map +3 -3
- package/build/level/gltf/GLTFModel.d.ts +17 -1
- package/build/level/gltf/GLTFModel.d.ts.map +1 -1
- package/build/loader/parsers/fontface.d.ts.map +1 -1
- package/build/physics/adapter.d.ts +74 -0
- package/build/physics/adapter.d.ts.map +1 -1
- package/build/physics/builtin/body.d.ts +0 -9
- package/build/physics/builtin/body.d.ts.map +1 -1
- package/build/physics/builtin/builtin-adapter.d.ts.map +1 -1
- package/build/physics/builtin/detector.d.ts +174 -1
- package/build/physics/builtin/detector.d.ts.map +1 -1
- package/build/renderable/container.d.ts.map +1 -1
- package/build/renderable/frameAnimation.d.ts +20 -2
- package/build/renderable/frameAnimation.d.ts.map +1 -1
- package/build/renderable/renderable.d.ts.map +1 -1
- package/build/system/timer.d.ts.map +1 -1
- package/build/utils/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* melonJS Game Engine - 20.
|
|
2
|
+
* melonJS Game Engine - 20.1.1
|
|
3
3
|
* http://www.melonjs.org
|
|
4
4
|
* melonjs is licensed under the MIT License.
|
|
5
5
|
* http://www.opensource.org/licenses/mit-license
|
|
@@ -6665,8 +6665,8 @@ function resetGUID(base, index = 0) {
|
|
|
6665
6665
|
GUID_base = toHex(base.toUpperCase());
|
|
6666
6666
|
GUID_index = index;
|
|
6667
6667
|
}
|
|
6668
|
-
function createGUID(index
|
|
6669
|
-
GUID_index
|
|
6668
|
+
function createGUID(index) {
|
|
6669
|
+
GUID_index++;
|
|
6670
6670
|
return `${GUID_base}-${index || GUID_index}`;
|
|
6671
6671
|
}
|
|
6672
6672
|
var isStringArray = (value) => {
|
|
@@ -12366,7 +12366,10 @@ var Timer = class {
|
|
|
12366
12366
|
* @ignore
|
|
12367
12367
|
*/
|
|
12368
12368
|
updateTimers() {
|
|
12369
|
-
for (const timer2 of this.timers) {
|
|
12369
|
+
for (const timer2 of [...this.timers]) {
|
|
12370
|
+
if (!this.timers.includes(timer2)) {
|
|
12371
|
+
continue;
|
|
12372
|
+
}
|
|
12370
12373
|
if (!(timer2.pauseable && state_default.isPaused())) {
|
|
12371
12374
|
timer2.elapsed += this.delta;
|
|
12372
12375
|
}
|
|
@@ -13193,9 +13196,15 @@ var FadeEffect = class extends CameraEffect {
|
|
|
13193
13196
|
}
|
|
13194
13197
|
}
|
|
13195
13198
|
destroy() {
|
|
13196
|
-
this.tween
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
+
if (this.tween !== void 0) {
|
|
13200
|
+
this.tween.stop();
|
|
13201
|
+
tweenPool.release(this.tween);
|
|
13202
|
+
this.tween = void 0;
|
|
13203
|
+
}
|
|
13204
|
+
if (this.color !== void 0) {
|
|
13205
|
+
colorPool.release(this.color);
|
|
13206
|
+
this.color = void 0;
|
|
13207
|
+
}
|
|
13199
13208
|
}
|
|
13200
13209
|
};
|
|
13201
13210
|
|
|
@@ -13594,13 +13603,22 @@ var MaskEffect = class extends CameraEffect {
|
|
|
13594
13603
|
r.restore();
|
|
13595
13604
|
}
|
|
13596
13605
|
destroy() {
|
|
13597
|
-
this.tween
|
|
13598
|
-
|
|
13599
|
-
|
|
13600
|
-
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
|
|
13606
|
+
if (this.tween !== void 0) {
|
|
13607
|
+
this.tween.stop();
|
|
13608
|
+
tweenPool.release(this.tween);
|
|
13609
|
+
this.tween = void 0;
|
|
13610
|
+
}
|
|
13611
|
+
if (this.color !== void 0) {
|
|
13612
|
+
colorPool.release(this.color);
|
|
13613
|
+
this.color = void 0;
|
|
13614
|
+
}
|
|
13615
|
+
if (this._maskShape !== void 0) {
|
|
13616
|
+
if (this._maskShape.type === "Ellipse") {
|
|
13617
|
+
ellipsePool.release(this._maskShape);
|
|
13618
|
+
} else {
|
|
13619
|
+
polygonPool.release(this._maskShape);
|
|
13620
|
+
}
|
|
13621
|
+
this._maskShape = void 0;
|
|
13604
13622
|
}
|
|
13605
13623
|
}
|
|
13606
13624
|
};
|
|
@@ -16678,6 +16696,7 @@ var collision = {
|
|
|
16678
16696
|
};
|
|
16679
16697
|
|
|
16680
16698
|
// src/physics/builtin/body.js
|
|
16699
|
+
var shapeContactIdCounter = 0;
|
|
16681
16700
|
var Body = class {
|
|
16682
16701
|
/**
|
|
16683
16702
|
* @param {Renderable|Container|Entity|Sprite|NineSliceSprite} ancestor - the parent object this body is attached to
|
|
@@ -17046,6 +17065,9 @@ var Body = class {
|
|
|
17046
17065
|
* @private
|
|
17047
17066
|
*/
|
|
17048
17067
|
_initShapeCollision(stored, source) {
|
|
17068
|
+
if (stored._contactId === void 0) {
|
|
17069
|
+
stored._contactId = ++shapeContactIdCounter;
|
|
17070
|
+
}
|
|
17049
17071
|
if (source === void 0) {
|
|
17050
17072
|
stored.collisionType = void 0;
|
|
17051
17073
|
stored.collisionMask = void 0;
|
|
@@ -17502,6 +17524,7 @@ var Body = class {
|
|
|
17502
17524
|
shape.collisionMask = void 0;
|
|
17503
17525
|
shape.isTrigger = false;
|
|
17504
17526
|
shape.isActive = true;
|
|
17527
|
+
shape._contactId = void 0;
|
|
17505
17528
|
if (shape instanceof Point) {
|
|
17506
17529
|
pointPool.release(shape);
|
|
17507
17530
|
} else if (shape instanceof Line) {
|
|
@@ -17587,7 +17610,7 @@ var Renderable = class _Renderable extends Rect {
|
|
|
17587
17610
|
*/
|
|
17588
17611
|
get parentApp() {
|
|
17589
17612
|
if (!this._parentApp && this.ancestor) {
|
|
17590
|
-
this._parentApp = this.ancestor.getRootAncestor()
|
|
17613
|
+
this._parentApp = this.ancestor.getRootAncestor()?.app;
|
|
17591
17614
|
}
|
|
17592
17615
|
return this._parentApp;
|
|
17593
17616
|
}
|
|
@@ -21056,6 +21079,9 @@ var FrameAnimation = class {
|
|
|
21056
21079
|
this.resetAnim = () => {
|
|
21057
21080
|
if (typeof onComplete === "function") {
|
|
21058
21081
|
onComplete();
|
|
21082
|
+
if (!this._isCurrentAnimationLive()) {
|
|
21083
|
+
return false;
|
|
21084
|
+
}
|
|
21059
21085
|
}
|
|
21060
21086
|
this.setCurrentAnimation(next, null, true);
|
|
21061
21087
|
};
|
|
@@ -21063,6 +21089,9 @@ var FrameAnimation = class {
|
|
|
21063
21089
|
this.resetAnim = () => {
|
|
21064
21090
|
if (typeof onComplete === "function") {
|
|
21065
21091
|
onComplete();
|
|
21092
|
+
if (!this._isCurrentAnimationLive()) {
|
|
21093
|
+
return false;
|
|
21094
|
+
}
|
|
21066
21095
|
}
|
|
21067
21096
|
this._animDone = true;
|
|
21068
21097
|
return false;
|
|
@@ -21148,6 +21177,26 @@ var FrameAnimation = class {
|
|
|
21148
21177
|
* @param {number} id - the frame id
|
|
21149
21178
|
* @returns {object} the frame data
|
|
21150
21179
|
*/
|
|
21180
|
+
/**
|
|
21181
|
+
* Whether the current animation is still resolvable.
|
|
21182
|
+
*
|
|
21183
|
+
* `update()` hands control to user code in the middle of its frame loop:
|
|
21184
|
+
* `onended`, and the completion callback behind `resetAnim`. That code is
|
|
21185
|
+
* free to tear the host down — "remove me once the animation finishes" is
|
|
21186
|
+
* an entirely reasonable reaction, and `removeChildNow()` destroys the
|
|
21187
|
+
* sprite, whose `destroy()` empties `anim`. Everything after the callback
|
|
21188
|
+
* reads out of `anim`, so the loop has to check it is still there rather
|
|
21189
|
+
* than resume into a map the callback just cleared.
|
|
21190
|
+
*
|
|
21191
|
+
* A callback that switches animations with `setCurrentAnimation()` leaves
|
|
21192
|
+
* this true, which is the point: only a genuinely torn-down host stops the
|
|
21193
|
+
* loop.
|
|
21194
|
+
* @ignore
|
|
21195
|
+
* @returns {boolean} true while the current animation can still be read
|
|
21196
|
+
*/
|
|
21197
|
+
_isCurrentAnimationLive() {
|
|
21198
|
+
return this.current !== void 0 && this.current !== null && this.anim[this.current.name] !== void 0;
|
|
21199
|
+
}
|
|
21151
21200
|
getAnimationFrameObjectByIndex(id) {
|
|
21152
21201
|
return this.anim[this.current.name].frames[id];
|
|
21153
21202
|
}
|
|
@@ -21181,6 +21230,9 @@ var FrameAnimation = class {
|
|
|
21181
21230
|
*/
|
|
21182
21231
|
update(dt) {
|
|
21183
21232
|
let changed = false;
|
|
21233
|
+
if (!this._isCurrentAnimationLive()) {
|
|
21234
|
+
return changed;
|
|
21235
|
+
}
|
|
21184
21236
|
if (!this.animationpause && !this._animDone && this.current.length > 1) {
|
|
21185
21237
|
let duration = this.getAnimationFrameObjectByIndex(
|
|
21186
21238
|
this.current.idx
|
|
@@ -21194,9 +21246,16 @@ var FrameAnimation = class {
|
|
|
21194
21246
|
if (this.current.idx === 0) {
|
|
21195
21247
|
if (typeof this.host.onended === "function") {
|
|
21196
21248
|
this.host.onended();
|
|
21249
|
+
if (!this._isCurrentAnimationLive()) {
|
|
21250
|
+
break;
|
|
21251
|
+
}
|
|
21197
21252
|
}
|
|
21198
21253
|
if (typeof this.resetAnim === "function") {
|
|
21199
|
-
|
|
21254
|
+
const keepPlaying = this.resetAnim();
|
|
21255
|
+
if (!this._isCurrentAnimationLive()) {
|
|
21256
|
+
break;
|
|
21257
|
+
}
|
|
21258
|
+
if (keepPlaying === false) {
|
|
21200
21259
|
this.setAnimationFrame(this.current.length - 1);
|
|
21201
21260
|
this.dt %= duration;
|
|
21202
21261
|
break;
|
|
@@ -23294,11 +23353,13 @@ function preloadBinary(data2, onload2, onerror, settings) {
|
|
|
23294
23353
|
// src/loader/parsers/fontface.js
|
|
23295
23354
|
function preloadFontFace(data2, onload2, onerror) {
|
|
23296
23355
|
const fontFaceSet = typeof globalThis.document !== "undefined" ? globalThis.document.fonts : void 0;
|
|
23297
|
-
|
|
23298
|
-
|
|
23356
|
+
let src = data2.src;
|
|
23357
|
+
if (!src.startsWith("url(") && !src.startsWith("local(")) {
|
|
23358
|
+
const escaped = src.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
23359
|
+
src = `url('${escaped}')`;
|
|
23299
23360
|
}
|
|
23300
23361
|
if (typeof fontFaceSet !== "undefined") {
|
|
23301
|
-
const font = new FontFace(data2.name,
|
|
23362
|
+
const font = new FontFace(data2.name, src);
|
|
23302
23363
|
font.load().then(
|
|
23303
23364
|
() => {
|
|
23304
23365
|
fontList[data2.name] = font;
|
|
@@ -26691,9 +26752,12 @@ var Container = class _Container extends Renderable {
|
|
|
26691
26752
|
let isFloating = false;
|
|
26692
26753
|
const isPaused = state_default.isPaused();
|
|
26693
26754
|
const children = this.getChildren();
|
|
26694
|
-
const childrenLength = children.length;
|
|
26695
26755
|
const cameras = state_default.current().cameras;
|
|
26696
|
-
|
|
26756
|
+
const pass = children.slice();
|
|
26757
|
+
for (let i = pass.length, obj; i--, obj = pass[i]; ) {
|
|
26758
|
+
if (obj.ancestor !== this) {
|
|
26759
|
+
continue;
|
|
26760
|
+
}
|
|
26697
26761
|
if (isPaused && !obj.updateWhenPaused) {
|
|
26698
26762
|
continue;
|
|
26699
26763
|
}
|
|
@@ -27033,6 +27097,9 @@ var GLTFModel = class extends Container {
|
|
|
27033
27097
|
this.resetAnim = () => {
|
|
27034
27098
|
if (typeof onComplete === "function") {
|
|
27035
27099
|
onComplete();
|
|
27100
|
+
if (!this._isLive()) {
|
|
27101
|
+
return false;
|
|
27102
|
+
}
|
|
27036
27103
|
}
|
|
27037
27104
|
this.setCurrentAnimation(next);
|
|
27038
27105
|
};
|
|
@@ -27040,6 +27107,9 @@ var GLTFModel = class extends Container {
|
|
|
27040
27107
|
this.resetAnim = () => {
|
|
27041
27108
|
if (typeof onComplete === "function") {
|
|
27042
27109
|
onComplete();
|
|
27110
|
+
if (!this._isLive()) {
|
|
27111
|
+
return false;
|
|
27112
|
+
}
|
|
27043
27113
|
}
|
|
27044
27114
|
this._animDone = true;
|
|
27045
27115
|
return false;
|
|
@@ -27119,6 +27189,9 @@ var GLTFModel = class extends Container {
|
|
|
27119
27189
|
if (this.current.time >= duration) {
|
|
27120
27190
|
if (typeof this.onended === "function") {
|
|
27121
27191
|
this.onended();
|
|
27192
|
+
if (!this._isLive()) {
|
|
27193
|
+
return super.update(dt);
|
|
27194
|
+
}
|
|
27122
27195
|
}
|
|
27123
27196
|
if (typeof this.resetAnim === "function") {
|
|
27124
27197
|
if (this.resetAnim() === false) {
|
|
@@ -27130,6 +27203,9 @@ var GLTFModel = class extends Container {
|
|
|
27130
27203
|
this.current.time %= duration;
|
|
27131
27204
|
}
|
|
27132
27205
|
}
|
|
27206
|
+
if (!this._isLive()) {
|
|
27207
|
+
return super.update(dt);
|
|
27208
|
+
}
|
|
27133
27209
|
this._pose();
|
|
27134
27210
|
this.isDirty = true;
|
|
27135
27211
|
}
|
|
@@ -27141,6 +27217,24 @@ var GLTFModel = class extends Container {
|
|
|
27141
27217
|
* not animate use their cached rest matrix.
|
|
27142
27218
|
* @ignore
|
|
27143
27219
|
*/
|
|
27220
|
+
/**
|
|
27221
|
+
* Whether this model is still alive.
|
|
27222
|
+
*
|
|
27223
|
+
* `update()` hands control to user code — `onended`, and the completion
|
|
27224
|
+
* callback behind `resetAnim` — and then poses the hierarchy. A callback
|
|
27225
|
+
* that removed the model (a death animation removing its own model is the
|
|
27226
|
+
* obvious case) has had `Renderable.destroy()` run, which releases `pos` to
|
|
27227
|
+
* the pool and leaves it undefined on every part. `_pose()` writes
|
|
27228
|
+
* `mesh.pos`, so it must not run on a torn-down model.
|
|
27229
|
+
*
|
|
27230
|
+
* `pos` and not `ancestor`: a model that was never added to a container is
|
|
27231
|
+
* perfectly poseable, and several callers do exactly that.
|
|
27232
|
+
* @ignore
|
|
27233
|
+
* @returns {boolean} true while the model can still be posed
|
|
27234
|
+
*/
|
|
27235
|
+
_isLive() {
|
|
27236
|
+
return this.pos !== void 0;
|
|
27237
|
+
}
|
|
27144
27238
|
_pose() {
|
|
27145
27239
|
const clip = this.current.name ? this.anim[this.current.name] : null;
|
|
27146
27240
|
const t = this.current.time;
|
|
@@ -47811,6 +47905,56 @@ var Detector = class {
|
|
|
47811
47905
|
isTriggerContact: false
|
|
47812
47906
|
}
|
|
47813
47907
|
];
|
|
47908
|
+
this._activeShapePairs = /* @__PURE__ */ new Map();
|
|
47909
|
+
this._frameShapeSeen = /* @__PURE__ */ new Map();
|
|
47910
|
+
this._shapeViews = [
|
|
47911
|
+
{
|
|
47912
|
+
a: null,
|
|
47913
|
+
b: null,
|
|
47914
|
+
shapeA: null,
|
|
47915
|
+
shapeB: null,
|
|
47916
|
+
overlap: 0,
|
|
47917
|
+
overlapN: { x: 0, y: 0 },
|
|
47918
|
+
overlapV: { x: 0, y: 0 },
|
|
47919
|
+
normal: { x: 0, y: 0 },
|
|
47920
|
+
depth: 0,
|
|
47921
|
+
overlapNZ: 0,
|
|
47922
|
+
overlapZ: 0,
|
|
47923
|
+
normalZ: 0,
|
|
47924
|
+
indexShapeA: -1,
|
|
47925
|
+
indexShapeB: -1,
|
|
47926
|
+
isTrigger: false
|
|
47927
|
+
},
|
|
47928
|
+
{
|
|
47929
|
+
a: null,
|
|
47930
|
+
b: null,
|
|
47931
|
+
shapeA: null,
|
|
47932
|
+
shapeB: null,
|
|
47933
|
+
overlap: 0,
|
|
47934
|
+
overlapN: { x: 0, y: 0 },
|
|
47935
|
+
overlapV: { x: 0, y: 0 },
|
|
47936
|
+
normal: { x: 0, y: 0 },
|
|
47937
|
+
depth: 0,
|
|
47938
|
+
overlapNZ: 0,
|
|
47939
|
+
overlapZ: 0,
|
|
47940
|
+
normalZ: 0,
|
|
47941
|
+
indexShapeA: -1,
|
|
47942
|
+
indexShapeB: -1,
|
|
47943
|
+
isTrigger: false
|
|
47944
|
+
}
|
|
47945
|
+
];
|
|
47946
|
+
this._contactObjA = null;
|
|
47947
|
+
this._contactObjB = null;
|
|
47948
|
+
this._onShapeContact = (shapeA, indexA, shapeB, indexB, isTrigger, res) => {
|
|
47949
|
+
this._dispatchShapeContact(
|
|
47950
|
+
shapeA,
|
|
47951
|
+
indexA,
|
|
47952
|
+
shapeB,
|
|
47953
|
+
indexB,
|
|
47954
|
+
isTrigger,
|
|
47955
|
+
res
|
|
47956
|
+
);
|
|
47957
|
+
};
|
|
47814
47958
|
}
|
|
47815
47959
|
/**
|
|
47816
47960
|
* Populate one of the pooled symmetric views from a SAT response.
|
|
@@ -47869,6 +48013,7 @@ var Detector = class {
|
|
|
47869
48013
|
*/
|
|
47870
48014
|
beginFrame() {
|
|
47871
48015
|
this._frameSeen.clear();
|
|
48016
|
+
this._frameShapeSeen.clear();
|
|
47872
48017
|
}
|
|
47873
48018
|
/**
|
|
47874
48019
|
* Called by the adapter at the end of a physics step. Diffs the
|
|
@@ -47895,9 +48040,58 @@ var Detector = class {
|
|
|
47895
48040
|
b.onCollisionEnd(void 0, a);
|
|
47896
48041
|
}
|
|
47897
48042
|
}
|
|
48043
|
+
for (const [key, entry2] of this._activeShapePairs) {
|
|
48044
|
+
if (this._frameShapeSeen.has(key)) {
|
|
48045
|
+
continue;
|
|
48046
|
+
}
|
|
48047
|
+
const [a, b, shapeA, shapeB] = entry2;
|
|
48048
|
+
const aAttached = a.ancestor != null;
|
|
48049
|
+
const bAttached = b.ancestor != null;
|
|
48050
|
+
if (!aAttached && !bAttached) {
|
|
48051
|
+
continue;
|
|
48052
|
+
}
|
|
48053
|
+
if (aAttached && typeof a.onShapeCollisionEnd === "function") {
|
|
48054
|
+
a.onShapeCollisionEnd(this._fillEndedView(0, a, b, shapeA, shapeB), b);
|
|
48055
|
+
}
|
|
48056
|
+
if (bAttached && typeof b.onShapeCollisionEnd === "function") {
|
|
48057
|
+
b.onShapeCollisionEnd(this._fillEndedView(1, b, a, shapeB, shapeA), a);
|
|
48058
|
+
}
|
|
48059
|
+
}
|
|
47898
48060
|
const prev = this._activePairs;
|
|
47899
48061
|
this._activePairs = this._frameSeen;
|
|
47900
48062
|
this._frameSeen = prev;
|
|
48063
|
+
const prevShapes = this._activeShapePairs;
|
|
48064
|
+
this._activeShapePairs = this._frameShapeSeen;
|
|
48065
|
+
this._frameShapeSeen = prevShapes;
|
|
48066
|
+
this._frameShapeSeen.clear();
|
|
48067
|
+
}
|
|
48068
|
+
/**
|
|
48069
|
+
* Identity-only shape-contact view for `onShapeCollisionEnd`: the shapes
|
|
48070
|
+
* have separated, so every geometric field is zeroed rather than left
|
|
48071
|
+
* holding the last overlap, which would read as a live contact.
|
|
48072
|
+
* @ignore
|
|
48073
|
+
*/
|
|
48074
|
+
_fillEndedView(slot, receiver, partner, ownShape, otherShape) {
|
|
48075
|
+
const view = this._shapeViews[slot];
|
|
48076
|
+
view.a = receiver;
|
|
48077
|
+
view.b = partner;
|
|
48078
|
+
view.shapeA = ownShape;
|
|
48079
|
+
view.shapeB = otherShape;
|
|
48080
|
+
view.indexShapeA = receiver.body?.shapes.indexOf(ownShape) ?? -1;
|
|
48081
|
+
view.indexShapeB = partner.body?.shapes.indexOf(otherShape) ?? -1;
|
|
48082
|
+
view.isTrigger = ownShape?.isTrigger === true || otherShape?.isTrigger === true;
|
|
48083
|
+
view.overlap = 0;
|
|
48084
|
+
view.depth = 0;
|
|
48085
|
+
view.overlapN.x = 0;
|
|
48086
|
+
view.overlapN.y = 0;
|
|
48087
|
+
view.overlapV.x = 0;
|
|
48088
|
+
view.overlapV.y = 0;
|
|
48089
|
+
view.normal.x = 0;
|
|
48090
|
+
view.normal.y = 0;
|
|
48091
|
+
view.overlapNZ = 0;
|
|
48092
|
+
view.overlapZ = 0;
|
|
48093
|
+
view.normalZ = 0;
|
|
48094
|
+
return view;
|
|
47901
48095
|
}
|
|
47902
48096
|
/**
|
|
47903
48097
|
* Build a stable order-independent key for a pair of renderables,
|
|
@@ -47913,6 +48107,188 @@ var Detector = class {
|
|
|
47913
48107
|
}
|
|
47914
48108
|
return ga < gb ? `${ga}|${gb}` : `${gb}|${ga}`;
|
|
47915
48109
|
}
|
|
48110
|
+
/**
|
|
48111
|
+
* Re-run the narrowphase for a remembered shape pair and repopulate
|
|
48112
|
+
* `response` from it.
|
|
48113
|
+
*
|
|
48114
|
+
* The scan clears `response` on every test, so whichever pair won has to be
|
|
48115
|
+
* measured again before handlers and the solver read it. Indices are looked
|
|
48116
|
+
* up here rather than carried from the scan because an enumeration handler
|
|
48117
|
+
* may have mutated either body in between: `removeShape()` re-indexes, and
|
|
48118
|
+
* `destroy()` empties the array outright. A shape that is no longer on its
|
|
48119
|
+
* body has no contact left to resolve, so this reports failure and the
|
|
48120
|
+
* caller falls through instead of throwing.
|
|
48121
|
+
* @ignore
|
|
48122
|
+
* @returns {boolean} true when the pair was re-measured
|
|
48123
|
+
*/
|
|
48124
|
+
_retest(bodyA, bodyB, shapeA, shapeB, response) {
|
|
48125
|
+
const indexA = bodyA.shapes.indexOf(shapeA);
|
|
48126
|
+
const indexB = bodyB.shapes.indexOf(shapeB);
|
|
48127
|
+
if (indexA < 0 || indexB < 0) {
|
|
48128
|
+
return false;
|
|
48129
|
+
}
|
|
48130
|
+
const test = SAT_LOOKUP[shapeA.type + shapeB.type];
|
|
48131
|
+
if (test === void 0) {
|
|
48132
|
+
return false;
|
|
48133
|
+
}
|
|
48134
|
+
test.call(
|
|
48135
|
+
this,
|
|
48136
|
+
bodyA.ancestor,
|
|
48137
|
+
shapeA,
|
|
48138
|
+
bodyB.ancestor,
|
|
48139
|
+
shapeB,
|
|
48140
|
+
response.clear()
|
|
48141
|
+
);
|
|
48142
|
+
response.indexShapeA = indexA;
|
|
48143
|
+
response.indexShapeB = indexB;
|
|
48144
|
+
return true;
|
|
48145
|
+
}
|
|
48146
|
+
/**
|
|
48147
|
+
* Stable, order-independent key for one SHAPE pair (#1596).
|
|
48148
|
+
*
|
|
48149
|
+
* The renderable GUIDs order the pair, exactly as `_pairKey` does, and the
|
|
48150
|
+
* two shape ids MUST swap alongside them: keying `guidA|guidB|idA|idB`
|
|
48151
|
+
* without that swap gives the same physical contact two different keys
|
|
48152
|
+
* depending on which object the outer loop visited first, and the contact
|
|
48153
|
+
* would then End and Start every step.
|
|
48154
|
+
*
|
|
48155
|
+
* Shape identity is `_contactId`, stamped once in `Body#addShape` and never
|
|
48156
|
+
* derived from array position, because `removeShape()` re-indexes every
|
|
48157
|
+
* surviving shape.
|
|
48158
|
+
* @ignore
|
|
48159
|
+
*/
|
|
48160
|
+
_shapePairKey(a, b, shapeA, shapeB) {
|
|
48161
|
+
const ga = a.GUID;
|
|
48162
|
+
const gb = b.GUID;
|
|
48163
|
+
const sa = shapeA?._contactId;
|
|
48164
|
+
const sb = shapeB?._contactId;
|
|
48165
|
+
if (ga === void 0 || gb === void 0 || sa === void 0 || sb === void 0) {
|
|
48166
|
+
return void 0;
|
|
48167
|
+
}
|
|
48168
|
+
const left = `${ga}#${sa}`;
|
|
48169
|
+
const right = `${gb}#${sb}`;
|
|
48170
|
+
return left < right ? `${left}|${right}` : `${right}|${left}`;
|
|
48171
|
+
}
|
|
48172
|
+
/**
|
|
48173
|
+
* True when an object subscribes to any shape-contact event.
|
|
48174
|
+
*
|
|
48175
|
+
* This is the opt-in gate: `collides()` only runs the full M x N scan when
|
|
48176
|
+
* this returns true for one of the two objects, so an application that
|
|
48177
|
+
* never declares these handlers performs exactly the narrowphase work it
|
|
48178
|
+
* did before the feature existed.
|
|
48179
|
+
* @ignore
|
|
48180
|
+
*/
|
|
48181
|
+
_wantsShapeContacts(obj) {
|
|
48182
|
+
return typeof obj.onShapeCollisionStart === "function" || typeof obj.onShapeCollisionActive === "function" || typeof obj.onShapeCollisionEnd === "function";
|
|
48183
|
+
}
|
|
48184
|
+
/**
|
|
48185
|
+
* Populate a pooled shape-contact view, same flip convention as
|
|
48186
|
+
* `_fillSymView`: `flip=false` builds the view for `response.a`'s side,
|
|
48187
|
+
* `flip=true` for `response.b`'s, so `shapeA` is always the receiver's.
|
|
48188
|
+
* @ignore
|
|
48189
|
+
*/
|
|
48190
|
+
_fillShapeView(slot, satResponse, flip, shapeA, shapeB, isTrigger) {
|
|
48191
|
+
const view = this._shapeViews[slot];
|
|
48192
|
+
const oN = satResponse.overlapN;
|
|
48193
|
+
const oV = satResponse.overlapV;
|
|
48194
|
+
const oNZ = satResponse.overlapNZ;
|
|
48195
|
+
const oZ = satResponse.overlapZ;
|
|
48196
|
+
view.overlap = satResponse.overlap;
|
|
48197
|
+
view.depth = satResponse.overlap;
|
|
48198
|
+
view.isTrigger = isTrigger === true;
|
|
48199
|
+
if (flip) {
|
|
48200
|
+
view.a = satResponse.b;
|
|
48201
|
+
view.b = satResponse.a;
|
|
48202
|
+
view.shapeA = shapeB;
|
|
48203
|
+
view.shapeB = shapeA;
|
|
48204
|
+
view.indexShapeA = satResponse.indexShapeB;
|
|
48205
|
+
view.indexShapeB = satResponse.indexShapeA;
|
|
48206
|
+
view.overlapN.x = -oN.x;
|
|
48207
|
+
view.overlapN.y = -oN.y;
|
|
48208
|
+
view.overlapV.x = -oV.x;
|
|
48209
|
+
view.overlapV.y = -oV.y;
|
|
48210
|
+
view.overlapNZ = -oNZ;
|
|
48211
|
+
view.overlapZ = -oZ;
|
|
48212
|
+
view.normal.x = oN.x;
|
|
48213
|
+
view.normal.y = oN.y;
|
|
48214
|
+
view.normalZ = oNZ;
|
|
48215
|
+
} else {
|
|
48216
|
+
view.a = satResponse.a;
|
|
48217
|
+
view.b = satResponse.b;
|
|
48218
|
+
view.shapeA = shapeA;
|
|
48219
|
+
view.shapeB = shapeB;
|
|
48220
|
+
view.indexShapeA = satResponse.indexShapeA;
|
|
48221
|
+
view.indexShapeB = satResponse.indexShapeB;
|
|
48222
|
+
view.overlapN.x = oN.x;
|
|
48223
|
+
view.overlapN.y = oN.y;
|
|
48224
|
+
view.overlapV.x = oV.x;
|
|
48225
|
+
view.overlapV.y = oV.y;
|
|
48226
|
+
view.overlapNZ = oNZ;
|
|
48227
|
+
view.overlapZ = oZ;
|
|
48228
|
+
view.normal.x = -oN.x;
|
|
48229
|
+
view.normal.y = -oN.y;
|
|
48230
|
+
view.normalZ = -oNZ;
|
|
48231
|
+
}
|
|
48232
|
+
return view;
|
|
48233
|
+
}
|
|
48234
|
+
/**
|
|
48235
|
+
* Fire Start / Active for one overlapping shape pair. Called back from
|
|
48236
|
+
* `collides()` once per pair, in scan order.
|
|
48237
|
+
* @ignore
|
|
48238
|
+
*/
|
|
48239
|
+
_dispatchShapeContact(shapeA, shapeB, isTrigger, response) {
|
|
48240
|
+
const objA = this._contactObjA;
|
|
48241
|
+
const objB = this._contactObjB;
|
|
48242
|
+
const key = this._shapePairKey(objA, objB, shapeA, shapeB);
|
|
48243
|
+
if (key === void 0 || this._frameShapeSeen.has(key)) {
|
|
48244
|
+
return;
|
|
48245
|
+
}
|
|
48246
|
+
this._frameShapeSeen.set(key, [objA, objB, shapeA, shapeB]);
|
|
48247
|
+
const isEntry = !this._activeShapePairs.has(key);
|
|
48248
|
+
const viewA = this._fillShapeView(
|
|
48249
|
+
0,
|
|
48250
|
+
response,
|
|
48251
|
+
false,
|
|
48252
|
+
shapeA,
|
|
48253
|
+
shapeB,
|
|
48254
|
+
isTrigger
|
|
48255
|
+
);
|
|
48256
|
+
const viewB = this._fillShapeView(
|
|
48257
|
+
1,
|
|
48258
|
+
response,
|
|
48259
|
+
true,
|
|
48260
|
+
shapeA,
|
|
48261
|
+
shapeB,
|
|
48262
|
+
isTrigger
|
|
48263
|
+
);
|
|
48264
|
+
if (isEntry) {
|
|
48265
|
+
if (typeof objA.onShapeCollisionStart === "function") {
|
|
48266
|
+
objA.onShapeCollisionStart(viewA, objB);
|
|
48267
|
+
}
|
|
48268
|
+
if (typeof objB.onShapeCollisionStart === "function") {
|
|
48269
|
+
objB.onShapeCollisionStart(viewB, objA);
|
|
48270
|
+
}
|
|
48271
|
+
}
|
|
48272
|
+
if (typeof objA.onShapeCollisionActive === "function") {
|
|
48273
|
+
objA.onShapeCollisionActive(viewA, objB);
|
|
48274
|
+
}
|
|
48275
|
+
if (typeof objB.onShapeCollisionActive === "function") {
|
|
48276
|
+
objB.onShapeCollisionActive(viewB, objA);
|
|
48277
|
+
}
|
|
48278
|
+
}
|
|
48279
|
+
/**
|
|
48280
|
+
* Drop the references the enumeration callback reads.
|
|
48281
|
+
*
|
|
48282
|
+
* They are plain fields rather than a per-pair closure so the hot path
|
|
48283
|
+
* allocates nothing, which means they outlive the pair unless cleared, and
|
|
48284
|
+
* would hold two renderables (and everything they reach) against garbage
|
|
48285
|
+
* collection until the next subscribed pair happened to overwrite them.
|
|
48286
|
+
* @ignore
|
|
48287
|
+
*/
|
|
48288
|
+
_clearContactPair() {
|
|
48289
|
+
this._contactObjA = null;
|
|
48290
|
+
this._contactObjB = null;
|
|
48291
|
+
}
|
|
47916
48292
|
/**
|
|
47917
48293
|
* determine if two objects should collide (based on both respective objects body collision mask and type).<br>
|
|
47918
48294
|
* you can redefine this function if you need any specific rules over what should collide with what.
|
|
@@ -47931,9 +48307,12 @@ var Detector = class {
|
|
|
47931
48307
|
* @param {Body} bodyB - a reference to body B.
|
|
47932
48308
|
* @returns {boolean} true if colliding
|
|
47933
48309
|
*/
|
|
47934
|
-
collides(bodyA, bodyB, response = this.response) {
|
|
47935
|
-
|
|
47936
|
-
let
|
|
48310
|
+
collides(bodyA, bodyB, response = this.response, onContact = void 0) {
|
|
48311
|
+
const enumerate = onContact !== void 0;
|
|
48312
|
+
let solidShapeA = null;
|
|
48313
|
+
let solidShapeB = null;
|
|
48314
|
+
let triggerShapeA = null;
|
|
48315
|
+
let triggerShapeB = null;
|
|
47937
48316
|
for (let indexA = bodyA.shapes.length, shapeA; indexA--, shapeA = bodyA.shapes[indexA]; ) {
|
|
47938
48317
|
for (let indexB = bodyB.shapes.length, shapeB; indexB--, shapeB = bodyB.shapes[indexB]; ) {
|
|
47939
48318
|
if (shapeA.isActive === false || shapeB.isActive === false) {
|
|
@@ -47968,10 +48347,24 @@ var Detector = class {
|
|
|
47968
48347
|
// clear response object before reusing
|
|
47969
48348
|
response.clear()
|
|
47970
48349
|
) === true) {
|
|
47971
|
-
|
|
47972
|
-
|
|
47973
|
-
|
|
47974
|
-
|
|
48350
|
+
const pairIsTrigger = shapeA.isTrigger === true || shapeB.isTrigger === true;
|
|
48351
|
+
if (enumerate === true) {
|
|
48352
|
+
response.indexShapeA = indexA;
|
|
48353
|
+
response.indexShapeB = indexB;
|
|
48354
|
+
response.isTriggerContact = pairIsTrigger;
|
|
48355
|
+
onContact(shapeA, shapeB, pairIsTrigger, response);
|
|
48356
|
+
}
|
|
48357
|
+
if (pairIsTrigger) {
|
|
48358
|
+
if (triggerShapeA === null) {
|
|
48359
|
+
triggerShapeA = shapeA;
|
|
48360
|
+
triggerShapeB = shapeB;
|
|
48361
|
+
}
|
|
48362
|
+
continue;
|
|
48363
|
+
}
|
|
48364
|
+
if (enumerate === true) {
|
|
48365
|
+
if (solidShapeA === null) {
|
|
48366
|
+
solidShapeA = shapeA;
|
|
48367
|
+
solidShapeB = shapeB;
|
|
47975
48368
|
}
|
|
47976
48369
|
continue;
|
|
47977
48370
|
}
|
|
@@ -47981,22 +48374,15 @@ var Detector = class {
|
|
|
47981
48374
|
}
|
|
47982
48375
|
}
|
|
47983
48376
|
}
|
|
47984
|
-
if (
|
|
47985
|
-
const shapeA = bodyA.shapes[triggerIndexA];
|
|
47986
|
-
const shapeB = bodyB.shapes[triggerIndexB];
|
|
47987
|
-
SAT_LOOKUP[shapeA.type + shapeB.type].call(
|
|
47988
|
-
this,
|
|
47989
|
-
bodyA.ancestor,
|
|
47990
|
-
shapeA,
|
|
47991
|
-
bodyB.ancestor,
|
|
47992
|
-
shapeB,
|
|
47993
|
-
response.clear()
|
|
47994
|
-
);
|
|
47995
|
-
response.indexShapeA = triggerIndexA;
|
|
47996
|
-
response.indexShapeB = triggerIndexB;
|
|
47997
|
-
response.isTriggerContact = true;
|
|
48377
|
+
if (solidShapeA !== null && this._retest(bodyA, bodyB, solidShapeA, solidShapeB, response)) {
|
|
47998
48378
|
return true;
|
|
47999
48379
|
}
|
|
48380
|
+
if (triggerShapeA !== null) {
|
|
48381
|
+
if (this._retest(bodyA, bodyB, triggerShapeA, triggerShapeB, response)) {
|
|
48382
|
+
response.isTriggerContact = true;
|
|
48383
|
+
return true;
|
|
48384
|
+
}
|
|
48385
|
+
}
|
|
48000
48386
|
return false;
|
|
48001
48387
|
}
|
|
48002
48388
|
/**
|
|
@@ -48016,7 +48402,23 @@ var Detector = class {
|
|
|
48016
48402
|
boundsB.addBounds(objB.getBounds(), true);
|
|
48017
48403
|
boundsB.addBounds(objB.body.getBounds());
|
|
48018
48404
|
if (boundsA.overlaps(boundsB)) {
|
|
48019
|
-
|
|
48405
|
+
const wantsContacts = this._wantsShapeContacts(objA) || this._wantsShapeContacts(objB);
|
|
48406
|
+
let onContact;
|
|
48407
|
+
if (wantsContacts === true) {
|
|
48408
|
+
this._contactObjA = objA;
|
|
48409
|
+
this._contactObjB = objB;
|
|
48410
|
+
onContact = this._onShapeContact;
|
|
48411
|
+
}
|
|
48412
|
+
const didCollide = this.collides(
|
|
48413
|
+
objA.body,
|
|
48414
|
+
objB.body,
|
|
48415
|
+
this.response,
|
|
48416
|
+
onContact
|
|
48417
|
+
);
|
|
48418
|
+
if (wantsContacts === true) {
|
|
48419
|
+
this._clearContactPair();
|
|
48420
|
+
}
|
|
48421
|
+
if (didCollide) {
|
|
48020
48422
|
collisionCounter++;
|
|
48021
48423
|
const pairKey = this._pairKey(objA, objB);
|
|
48022
48424
|
const firstVisitThisFrame = pairKey !== void 0 && !this._frameSeen.has(pairKey);
|
|
@@ -48040,14 +48442,23 @@ var Detector = class {
|
|
|
48040
48442
|
objB.onCollisionActive(viewB, objA);
|
|
48041
48443
|
}
|
|
48042
48444
|
}
|
|
48445
|
+
if (objA.body === void 0 || objB.body === void 0) {
|
|
48446
|
+
continue;
|
|
48447
|
+
}
|
|
48043
48448
|
const eitherSensor = objA.body.isSensor === true || objB.body.isSensor === true || this.response.isTriggerContact === true;
|
|
48044
48449
|
const aHasModern = typeof objA.onCollisionActive === "function";
|
|
48045
48450
|
const bHasModern = typeof objB.onCollisionActive === "function";
|
|
48046
48451
|
const aOptsOut = !aHasModern && typeof objA.onCollision === "function" && objA.onCollision(this.response, objB) === false;
|
|
48452
|
+
if (objA.body === void 0 || objB.body === void 0) {
|
|
48453
|
+
continue;
|
|
48454
|
+
}
|
|
48047
48455
|
if (!aOptsOut && objA.body.isStatic === false && !eitherSensor) {
|
|
48048
48456
|
objA.body.respondToCollision.call(objA.body, this.response);
|
|
48049
48457
|
}
|
|
48050
48458
|
const bOptsOut = !bHasModern && typeof objB.onCollision === "function" && objB.onCollision(this.response, objA) === false;
|
|
48459
|
+
if (objA.body === void 0 || objB.body === void 0) {
|
|
48460
|
+
continue;
|
|
48461
|
+
}
|
|
48051
48462
|
if (!bOptsOut && objB.body.isStatic === false && !eitherSensor) {
|
|
48052
48463
|
objB.body.respondToCollision.call(objB.body, this.response);
|
|
48053
48464
|
}
|
|
@@ -48323,8 +48734,10 @@ var BuiltinAdapter = class {
|
|
|
48323
48734
|
this.detector.collisions(ancestor);
|
|
48324
48735
|
}
|
|
48325
48736
|
}
|
|
48326
|
-
body.force
|
|
48327
|
-
|
|
48737
|
+
if (body.force !== void 0) {
|
|
48738
|
+
body.force.set(0, 0);
|
|
48739
|
+
body.forceZ = 0;
|
|
48740
|
+
}
|
|
48328
48741
|
}
|
|
48329
48742
|
this.detector.endFrame();
|
|
48330
48743
|
}
|
|
@@ -50064,7 +50477,7 @@ var Trigger = class extends Renderable {
|
|
|
50064
50477
|
};
|
|
50065
50478
|
|
|
50066
50479
|
// src/version.ts
|
|
50067
|
-
var version = "20.
|
|
50480
|
+
var version = "20.1.1";
|
|
50068
50481
|
|
|
50069
50482
|
// src/system/bootstrap.ts
|
|
50070
50483
|
var initialized = false;
|