@blorkfield/overlay-core 0.8.9 → 0.8.11
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 +2 -0
- package/dist/index.cjs +40 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +40 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -7,8 +7,6 @@ interface OverlaySceneConfig {
|
|
|
7
7
|
debug?: boolean;
|
|
8
8
|
/** Background configuration with color, image, and transparency layers */
|
|
9
9
|
background?: BackgroundConfig;
|
|
10
|
-
/** @deprecated Use floorConfig instead. Pressure threshold for the floor boundary. */
|
|
11
|
-
floorThreshold?: number;
|
|
12
10
|
/** Distance below floor (as fraction of container height) at which objects despawn. Default: 1.0 (100%) */
|
|
13
11
|
despawnBelowFloor?: number;
|
|
14
12
|
/** Configuration for floor segments and thresholds */
|
|
@@ -536,7 +534,6 @@ declare class OverlayScene {
|
|
|
536
534
|
private updateCallbacks;
|
|
537
535
|
private config;
|
|
538
536
|
private animationFrameId;
|
|
539
|
-
private mouse;
|
|
540
537
|
private effectManager;
|
|
541
538
|
private fonts;
|
|
542
539
|
private fontsInitialized;
|
|
@@ -554,6 +551,10 @@ declare class OverlayScene {
|
|
|
554
551
|
private lastGrabMousePosition;
|
|
555
552
|
private grabbedWasDynamic;
|
|
556
553
|
private grabVelocity;
|
|
554
|
+
private bodyPositionHistory;
|
|
555
|
+
private readonly grabHistoryFrames;
|
|
556
|
+
private readonly grabHistoryRadius;
|
|
557
|
+
private readonly substeps;
|
|
557
558
|
static createContainer(parent: HTMLElement, options?: ContainerOptions): {
|
|
558
559
|
canvas: HTMLCanvasElement;
|
|
559
560
|
bounds: Bounds;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,8 +7,6 @@ interface OverlaySceneConfig {
|
|
|
7
7
|
debug?: boolean;
|
|
8
8
|
/** Background configuration with color, image, and transparency layers */
|
|
9
9
|
background?: BackgroundConfig;
|
|
10
|
-
/** @deprecated Use floorConfig instead. Pressure threshold for the floor boundary. */
|
|
11
|
-
floorThreshold?: number;
|
|
12
10
|
/** Distance below floor (as fraction of container height) at which objects despawn. Default: 1.0 (100%) */
|
|
13
11
|
despawnBelowFloor?: number;
|
|
14
12
|
/** Configuration for floor segments and thresholds */
|
|
@@ -536,7 +534,6 @@ declare class OverlayScene {
|
|
|
536
534
|
private updateCallbacks;
|
|
537
535
|
private config;
|
|
538
536
|
private animationFrameId;
|
|
539
|
-
private mouse;
|
|
540
537
|
private effectManager;
|
|
541
538
|
private fonts;
|
|
542
539
|
private fontsInitialized;
|
|
@@ -554,6 +551,10 @@ declare class OverlayScene {
|
|
|
554
551
|
private lastGrabMousePosition;
|
|
555
552
|
private grabbedWasDynamic;
|
|
556
553
|
private grabVelocity;
|
|
554
|
+
private bodyPositionHistory;
|
|
555
|
+
private readonly grabHistoryFrames;
|
|
556
|
+
private readonly grabHistoryRadius;
|
|
557
|
+
private readonly substeps;
|
|
557
558
|
static createContainer(parent: HTMLElement, options?: ContainerOptions): {
|
|
558
559
|
canvas: HTMLCanvasElement;
|
|
559
560
|
bounds: Bounds;
|
package/dist/index.js
CHANGED
|
@@ -1375,7 +1375,6 @@ var OverlayScene = class {
|
|
|
1375
1375
|
this.boundaries = [];
|
|
1376
1376
|
this.updateCallbacks = [];
|
|
1377
1377
|
this.animationFrameId = null;
|
|
1378
|
-
this.mouse = null;
|
|
1379
1378
|
this.fonts = [];
|
|
1380
1379
|
this.fontsInitialized = false;
|
|
1381
1380
|
this.letterDebugInfo = /* @__PURE__ */ new Map();
|
|
@@ -1402,6 +1401,12 @@ var OverlayScene = class {
|
|
|
1402
1401
|
this.lastGrabMousePosition = null;
|
|
1403
1402
|
this.grabbedWasDynamic = false;
|
|
1404
1403
|
this.grabVelocity = { x: 0, y: 0 };
|
|
1404
|
+
// Position history for sweep-based grab detection (catches fast-moving bodies)
|
|
1405
|
+
this.bodyPositionHistory = /* @__PURE__ */ new Map();
|
|
1406
|
+
this.grabHistoryFrames = 5;
|
|
1407
|
+
this.grabHistoryRadius = 20;
|
|
1408
|
+
// Number of physics substeps per frame — more substeps = better collision at high speeds, more CPU
|
|
1409
|
+
this.substeps = 2;
|
|
1405
1410
|
/** Handle mouse down - start grab via programmatic API */
|
|
1406
1411
|
this.handleMouseDown = (event) => {
|
|
1407
1412
|
const rect = this.canvas.getBoundingClientRect();
|
|
@@ -1478,13 +1483,14 @@ var OverlayScene = class {
|
|
|
1478
1483
|
};
|
|
1479
1484
|
// ==================== PRIVATE ====================
|
|
1480
1485
|
this.loop = () => {
|
|
1486
|
+
const substepDelta = 1e3 / 60 / this.substeps;
|
|
1487
|
+
for (let i = 0; i < this.substeps; i++) {
|
|
1488
|
+
Matter5.Engine.update(this.engine, substepDelta);
|
|
1489
|
+
}
|
|
1481
1490
|
this.effectManager.update();
|
|
1482
1491
|
this.checkTTLExpiration();
|
|
1483
1492
|
this.checkDespawnBelowFloor();
|
|
1484
1493
|
this.updatePressure();
|
|
1485
|
-
if (!this.followTargets.has("mouse") && this.mouse) {
|
|
1486
|
-
this.followTargets.set("mouse", { x: this.mouse.position.x, y: this.mouse.position.y });
|
|
1487
|
-
}
|
|
1488
1494
|
if (this.grabbedObjectId && this.lastGrabMousePosition) {
|
|
1489
1495
|
const entry = this.objects.get(this.grabbedObjectId);
|
|
1490
1496
|
const mouseTarget = this.followTargets.get("mouse");
|
|
@@ -1521,6 +1527,14 @@ var OverlayScene = class {
|
|
|
1521
1527
|
if (entry.domElement && entry.tags.includes("falling")) {
|
|
1522
1528
|
this.updateDOMElementTransform(entry);
|
|
1523
1529
|
}
|
|
1530
|
+
if (entry.tags.includes("grabable") && !entry.body.isStatic) {
|
|
1531
|
+
const history = this.bodyPositionHistory.get(entry.body.id) ?? [];
|
|
1532
|
+
history.push({ x: entry.body.position.x, y: entry.body.position.y });
|
|
1533
|
+
if (history.length > this.grabHistoryFrames) {
|
|
1534
|
+
history.shift();
|
|
1535
|
+
}
|
|
1536
|
+
this.bodyPositionHistory.set(entry.body.id, history);
|
|
1537
|
+
}
|
|
1524
1538
|
}
|
|
1525
1539
|
if (!this.config.debug) {
|
|
1526
1540
|
this.drawTTFGlyphs();
|
|
@@ -1546,7 +1560,6 @@ var OverlayScene = class {
|
|
|
1546
1560
|
this.floorSegments = boundariesResult.floorSegments;
|
|
1547
1561
|
Matter5.Composite.add(this.engine.world, this.boundaries);
|
|
1548
1562
|
this.checkInitialFloorIntegrity();
|
|
1549
|
-
this.mouse = Matter5.Mouse.create(canvas);
|
|
1550
1563
|
canvas.addEventListener("mousedown", this.handleMouseDown);
|
|
1551
1564
|
canvas.addEventListener("mousemove", this.handleMouseMove);
|
|
1552
1565
|
canvas.addEventListener("mouseup", this.handleMouseUp);
|
|
@@ -1782,7 +1795,7 @@ var OverlayScene = class {
|
|
|
1782
1795
|
}
|
|
1783
1796
|
}
|
|
1784
1797
|
if (parts.length > 0) {
|
|
1785
|
-
|
|
1798
|
+
logger.debug("[Pressure]", parts.join(" "));
|
|
1786
1799
|
}
|
|
1787
1800
|
}
|
|
1788
1801
|
/** Calculate weighted pressure from a set of object IDs */
|
|
@@ -1959,7 +1972,6 @@ var OverlayScene = class {
|
|
|
1959
1972
|
}
|
|
1960
1973
|
start() {
|
|
1961
1974
|
Matter5.Render.run(this.render);
|
|
1962
|
-
Matter5.Runner.run(this.runner, this.engine);
|
|
1963
1975
|
this.loop();
|
|
1964
1976
|
}
|
|
1965
1977
|
stop() {
|
|
@@ -2326,13 +2338,13 @@ var OverlayScene = class {
|
|
|
2326
2338
|
* @returns The ID of the grabbed object, or null if no grabable object at position
|
|
2327
2339
|
*/
|
|
2328
2340
|
startGrab() {
|
|
2329
|
-
const
|
|
2330
|
-
const position = mouseTarget ?? (this.mouse ? { x: this.mouse.position.x, y: this.mouse.position.y } : null);
|
|
2341
|
+
const position = this.followTargets.get("mouse") ?? null;
|
|
2331
2342
|
if (!position) return null;
|
|
2332
2343
|
const bodies = Matter5.Query.point(
|
|
2333
2344
|
Matter5.Composite.allBodies(this.engine.world),
|
|
2334
2345
|
position
|
|
2335
2346
|
);
|
|
2347
|
+
logger.debug("OverlayScene", "Grabbed position " + position + ', had "' + bodies.length + '"');
|
|
2336
2348
|
for (const body of bodies) {
|
|
2337
2349
|
const entry = this.findObjectByBody(body);
|
|
2338
2350
|
if (entry && entry.tags.includes("grabable")) {
|
|
@@ -2344,6 +2356,24 @@ var OverlayScene = class {
|
|
|
2344
2356
|
return entry.id;
|
|
2345
2357
|
}
|
|
2346
2358
|
}
|
|
2359
|
+
const r2 = this.grabHistoryRadius * this.grabHistoryRadius;
|
|
2360
|
+
for (const entry of this.objects.values()) {
|
|
2361
|
+
if (!entry.tags.includes("grabable")) continue;
|
|
2362
|
+
const history = this.bodyPositionHistory.get(entry.body.id);
|
|
2363
|
+
if (!history) continue;
|
|
2364
|
+
for (const pastPos of history) {
|
|
2365
|
+
const dx = position.x - pastPos.x;
|
|
2366
|
+
const dy = position.y - pastPos.y;
|
|
2367
|
+
if (dx * dx + dy * dy <= r2) {
|
|
2368
|
+
this.grabbedObjectId = entry.id;
|
|
2369
|
+
this.lastGrabMousePosition = { x: position.x, y: position.y };
|
|
2370
|
+
this.grabVelocity = { x: 0, y: 0 };
|
|
2371
|
+
this.grabbedWasDynamic = !entry.body.isStatic;
|
|
2372
|
+
Matter5.Body.setStatic(entry.body, true);
|
|
2373
|
+
return entry.id;
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2347
2377
|
return null;
|
|
2348
2378
|
}
|
|
2349
2379
|
/**
|
|
@@ -2357,6 +2387,7 @@ var OverlayScene = class {
|
|
|
2357
2387
|
Matter5.Sleeping.set(entry.body, false);
|
|
2358
2388
|
Matter5.Body.setVelocity(entry.body, this.grabVelocity);
|
|
2359
2389
|
Matter5.Body.setAngularVelocity(entry.body, 0);
|
|
2390
|
+
this.bodyPositionHistory.delete(entry.body.id);
|
|
2360
2391
|
}
|
|
2361
2392
|
}
|
|
2362
2393
|
this.grabbedObjectId = null;
|