@blorkfield/overlay-core 0.10.1 → 0.11.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/README.md +18 -1
- package/dist/index.cjs +54 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +54 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -628,7 +628,7 @@ scene.on('objectRemoved', (obj) => {
|
|
|
628
628
|
console.log(`Removed: ${obj.id}`);
|
|
629
629
|
});
|
|
630
630
|
|
|
631
|
-
// Objects collided
|
|
631
|
+
// Objects collided (fires on collision start)
|
|
632
632
|
scene.on('objectCollision', (a, b) => {
|
|
633
633
|
console.log(`Collision: ${a.id} hit ${b.id}`);
|
|
634
634
|
});
|
|
@@ -637,6 +637,23 @@ scene.on('objectCollision', (a, b) => {
|
|
|
637
637
|
scene.off('objectSpawned', myCallback);
|
|
638
638
|
```
|
|
639
639
|
|
|
640
|
+
### Querying Active Collisions
|
|
641
|
+
|
|
642
|
+
The scene tracks which objects are currently in contact, so you can query collision state at any time without maintaining your own bookkeeping:
|
|
643
|
+
|
|
644
|
+
```typescript
|
|
645
|
+
// Get all object IDs currently touching a specific object
|
|
646
|
+
const touching = scene.getCollidingWith('my-object-id'); // string[]
|
|
647
|
+
|
|
648
|
+
// Get all active collision pairs
|
|
649
|
+
const pairs = scene.getActiveCollisions(); // Array<{ a: string, b: string }>
|
|
650
|
+
for (const { a, b } of pairs) {
|
|
651
|
+
console.log(`${a} is touching ${b}`);
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
These reflect live physics state — pairs are added on `collisionStart` and removed on `collisionEnd`. Only tracked objects are included (floor, boundaries, and DOM obstacles are excluded).
|
|
656
|
+
|
|
640
657
|
## Font Setup
|
|
641
658
|
|
|
642
659
|
### Bundled Fonts
|
package/dist/index.cjs
CHANGED
|
@@ -1466,6 +1466,8 @@ var OverlayScene = class {
|
|
|
1466
1466
|
this.followWindowEntries = /* @__PURE__ */ new Set();
|
|
1467
1467
|
// IDs of static objects that have pressure thresholds — empty = skip updatePressure entirely
|
|
1468
1468
|
this.pressureObstacleIds = /* @__PURE__ */ new Set();
|
|
1469
|
+
// Active collision pairs: id -> Set of ids currently colliding with it
|
|
1470
|
+
this.activeCollisions = /* @__PURE__ */ new Map();
|
|
1469
1471
|
/** Handle mouse down - start grab via programmatic API */
|
|
1470
1472
|
this.handleMouseDown = (event) => {
|
|
1471
1473
|
const rect = this.canvas.getBoundingClientRect();
|
|
@@ -1532,6 +1534,10 @@ var OverlayScene = class {
|
|
|
1532
1534
|
const entryA = this.findObjectByBody(pair.bodyA);
|
|
1533
1535
|
const entryB = this.findObjectByBody(pair.bodyB);
|
|
1534
1536
|
if (entryA && entryB) {
|
|
1537
|
+
if (!this.activeCollisions.has(entryA.id)) this.activeCollisions.set(entryA.id, /* @__PURE__ */ new Set());
|
|
1538
|
+
if (!this.activeCollisions.has(entryB.id)) this.activeCollisions.set(entryB.id, /* @__PURE__ */ new Set());
|
|
1539
|
+
this.activeCollisions.get(entryA.id).add(entryB.id);
|
|
1540
|
+
this.activeCollisions.get(entryB.id).add(entryA.id);
|
|
1535
1541
|
this.emitLifecycleEvent(
|
|
1536
1542
|
"objectCollision",
|
|
1537
1543
|
this.toObjectState(entryA),
|
|
@@ -1540,6 +1546,16 @@ var OverlayScene = class {
|
|
|
1540
1546
|
}
|
|
1541
1547
|
}
|
|
1542
1548
|
};
|
|
1549
|
+
this.handleCollisionEnd = (event) => {
|
|
1550
|
+
for (const pair of event.pairs) {
|
|
1551
|
+
const entryA = this.findObjectByBody(pair.bodyA);
|
|
1552
|
+
const entryB = this.findObjectByBody(pair.bodyB);
|
|
1553
|
+
if (entryA && entryB) {
|
|
1554
|
+
this.activeCollisions.get(entryA.id)?.delete(entryB.id);
|
|
1555
|
+
this.activeCollisions.get(entryB.id)?.delete(entryA.id);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1543
1559
|
// ==================== PRIVATE ====================
|
|
1544
1560
|
this.loop = () => {
|
|
1545
1561
|
const substepDelta = 1e3 / 60 / this.substeps;
|
|
@@ -1668,6 +1684,7 @@ var OverlayScene = class {
|
|
|
1668
1684
|
import_matter_js5.default.Events.on(this.render, "beforeRender", this.handleBeforeRender);
|
|
1669
1685
|
import_matter_js5.default.Events.on(this.render, "afterRender", this.handleAfterRender);
|
|
1670
1686
|
import_matter_js5.default.Events.on(this.engine, "collisionStart", this.handleCollisionStart);
|
|
1687
|
+
import_matter_js5.default.Events.on(this.engine, "collisionEnd", this.handleCollisionEnd);
|
|
1671
1688
|
}
|
|
1672
1689
|
static createContainer(parent, options = {}) {
|
|
1673
1690
|
const canvas = document.createElement("canvas");
|
|
@@ -2071,6 +2088,7 @@ var OverlayScene = class {
|
|
|
2071
2088
|
import_matter_js5.default.Events.off(this.render, "beforeRender", this.handleBeforeRender);
|
|
2072
2089
|
import_matter_js5.default.Events.off(this.render, "afterRender", this.handleAfterRender);
|
|
2073
2090
|
import_matter_js5.default.Events.off(this.engine, "collisionStart", this.handleCollisionStart);
|
|
2091
|
+
import_matter_js5.default.Events.off(this.engine, "collisionEnd", this.handleCollisionEnd);
|
|
2074
2092
|
import_matter_js5.default.Engine.clear(this.engine);
|
|
2075
2093
|
this.objects.clear();
|
|
2076
2094
|
this.gravityOverrideEntries.clear();
|
|
@@ -2081,6 +2099,7 @@ var OverlayScene = class {
|
|
|
2081
2099
|
this.pressureLogTimer = 0;
|
|
2082
2100
|
this.floorSegmentPressure.clear();
|
|
2083
2101
|
this.collapsedSegments.clear();
|
|
2102
|
+
this.activeCollisions.clear();
|
|
2084
2103
|
this.updateCallbacks = [];
|
|
2085
2104
|
this.lifecycleCallbacks.objectSpawned = [];
|
|
2086
2105
|
this.lifecycleCallbacks.objectRemoved = [];
|
|
@@ -2532,6 +2551,13 @@ var OverlayScene = class {
|
|
|
2532
2551
|
this.gravityOverrideEntries.delete(entry);
|
|
2533
2552
|
this.followWindowEntries.delete(entry);
|
|
2534
2553
|
this.pressureObstacleIds.delete(id);
|
|
2554
|
+
const colliding = this.activeCollisions.get(id);
|
|
2555
|
+
if (colliding) {
|
|
2556
|
+
for (const otherId of colliding) {
|
|
2557
|
+
this.activeCollisions.get(otherId)?.delete(id);
|
|
2558
|
+
}
|
|
2559
|
+
this.activeCollisions.delete(id);
|
|
2560
|
+
}
|
|
2535
2561
|
this.objects.delete(id);
|
|
2536
2562
|
}
|
|
2537
2563
|
removeObjects(ids) {
|
|
@@ -2781,6 +2807,32 @@ var OverlayScene = class {
|
|
|
2781
2807
|
const idx = arr.indexOf(callback);
|
|
2782
2808
|
if (idx !== -1) arr.splice(idx, 1);
|
|
2783
2809
|
}
|
|
2810
|
+
/**
|
|
2811
|
+
* Get the IDs of all objects currently colliding with a given object.
|
|
2812
|
+
* @param id - The ID of the object to query
|
|
2813
|
+
* @returns Array of IDs of objects currently in contact with it
|
|
2814
|
+
*/
|
|
2815
|
+
getCollidingWith(id) {
|
|
2816
|
+
return Array.from(this.activeCollisions.get(id) ?? []);
|
|
2817
|
+
}
|
|
2818
|
+
/**
|
|
2819
|
+
* Get all currently active collision pairs.
|
|
2820
|
+
* @returns Array of `{ a, b }` pairs where `a` and `b` are colliding object IDs
|
|
2821
|
+
*/
|
|
2822
|
+
getActiveCollisions() {
|
|
2823
|
+
const pairs = [];
|
|
2824
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2825
|
+
for (const [id, others] of this.activeCollisions) {
|
|
2826
|
+
for (const otherId of others) {
|
|
2827
|
+
const key = id < otherId ? `${id}:${otherId}` : `${otherId}:${id}`;
|
|
2828
|
+
if (!seen.has(key)) {
|
|
2829
|
+
seen.add(key);
|
|
2830
|
+
pairs.push({ a: id, b: otherId });
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
return pairs;
|
|
2835
|
+
}
|
|
2784
2836
|
/** Create ObjectState from an ObjectEntry */
|
|
2785
2837
|
toObjectState(entry) {
|
|
2786
2838
|
return {
|
|
@@ -3082,11 +3134,12 @@ var OverlayScene = class {
|
|
|
3082
3134
|
maxDimension = Math.max(maxDimension, dims.width, dims.height);
|
|
3083
3135
|
}
|
|
3084
3136
|
if (maxDimension === 0) maxDimension = 100;
|
|
3137
|
+
const spaceWidth = letterSize / 3;
|
|
3085
3138
|
const calculateLineWidth = (line) => {
|
|
3086
3139
|
let width = 0;
|
|
3087
3140
|
for (const char of line) {
|
|
3088
3141
|
if (char === " ") {
|
|
3089
|
-
width +=
|
|
3142
|
+
width += spaceWidth;
|
|
3090
3143
|
} else if (/^[A-Za-z0-9]$/.test(char)) {
|
|
3091
3144
|
const dims = charDimensions.get(char);
|
|
3092
3145
|
if (dims) {
|
|
@@ -3144,7 +3197,6 @@ var OverlayScene = class {
|
|
|
3144
3197
|
for (let i = 0; i < chars.length; i++) {
|
|
3145
3198
|
const char = chars[i];
|
|
3146
3199
|
if (char === " ") {
|
|
3147
|
-
const spaceWidth = config.letterSpacing ?? letterSize;
|
|
3148
3200
|
currentX += spaceWidth;
|
|
3149
3201
|
globalCharIndex++;
|
|
3150
3202
|
if (inWord) {
|