@blorkfield/overlay-core 0.11.2 → 0.11.3

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 CHANGED
@@ -42,7 +42,7 @@ scene.spawnObject({ tags: [STATIC], ... });
42
42
  |----------|-------|----------|
43
43
  | `TAG_STATIC` / `TAGS.STATIC` | `'static'` | Object is a static obstacle, not affected by gravity. Without this tag, objects are dynamic by default. |
44
44
  | `TAG_FOLLOW_WINDOW` / `TAGS.FOLLOW_WINDOW` | `'follow_window'` | Object walks toward a target when grounded (default: mouse) |
45
- | `TAG_GRABABLE` / `TAGS.GRABABLE` | `'grabable'` | Object can be grabbed and moved with mouse |
45
+ | `TAG_GRABABLE` / `TAGS.GRABABLE` | `'grabable'` | Object can be grabbed and moved with mouse or touch |
46
46
  | `TAG_GRAVITY_OVERRIDE` / `TAGS.GRAVITY_OVERRIDE` | `'gravity_override'` | Object uses its own gravity vector instead of scene gravity |
47
47
  | `TAG_SPEED_OVERRIDE` / `TAGS.SPEED_OVERRIDE` | `'speed_override'` | Multiplies movement speed for `follow_window` and future movement behaviors. Negative = run away from target. |
48
48
  | `TAG_MASS_OVERRIDE` / `TAGS.MASS_OVERRIDE` | `'mass_override'` | Overrides the physics mass. Higher mass resists follow forces more; lower mass allows the follow force to overcome gravity. |
@@ -469,7 +469,9 @@ scene.setObjectScale(id, 2, 0.5); // stretch wide, squash tall
469
469
  scene.setObjectScale(id, 1, 1); // restore original size
470
470
  ```
471
471
 
472
- ## Mouse Position and Grab API
472
+ ## Mouse / Touch and Grab API
473
+
474
+ Mouse and touch input are handled automatically. On touch devices, a single finger grabs and drags `grabable` objects; a tap on a static object with `clicksToFall` set triggers the click-to-fall behavior. Two-finger gestures are ignored by the canvas so the browser can handle scroll and pinch-zoom normally. Touching over empty canvas (no `grabable` object) also passes through to the browser.
473
475
 
474
476
  For scenarios where mouse input comes from an external source (e.g., system-wide mouse capture via WebSocket), you can programmatically control mouse position and grab/release behavior. This is useful when the canvas is positioned with an offset from the screen origin.
475
477
 
@@ -802,7 +804,7 @@ Tags are the source of truth for all behavior. Boolean tags (presence = active,
802
804
  | Tag | Behavior |
803
805
  |-----|----------|
804
806
  | `static` | Static obstacle, not affected by gravity. Absent by default — objects are dynamic unless tagged static. |
805
- | `grabable` | Can be grabbed and dragged with the mouse |
807
+ | `grabable` | Can be grabbed and dragged with the mouse or touch |
806
808
  | `follow_window` | Always applies a directional force toward its target (in all axes). Gravity determines whether the entity can actually reach targets above/below it. |
807
809
  | `gravity_override` | Uses its own gravity vector instead of scene gravity (value set via `setObjectGravityOverride`) |
808
810
  | `speed_override` | Multiplies movement speed for `follow_window` and future movement behaviors (value set via `setObjectSpeedOverride`). Negative = runs away from target. Default multiplier: 1 |
package/dist/index.cjs CHANGED
@@ -1522,6 +1522,10 @@ var OverlayScene = class {
1522
1522
  const rect = this.canvas.getBoundingClientRect();
1523
1523
  const x = event.clientX - rect.left;
1524
1524
  const y = event.clientY - rect.top;
1525
+ this.handleTap(x, y);
1526
+ };
1527
+ /** Shared tap logic for mouse click and touch tap */
1528
+ this.handleTap = (x, y) => {
1525
1529
  const bodies = import_matter_js5.default.Query.point(
1526
1530
  import_matter_js5.default.Composite.allBodies(this.engine.world),
1527
1531
  { x, y }
@@ -1539,6 +1543,42 @@ var OverlayScene = class {
1539
1543
  }
1540
1544
  }
1541
1545
  };
1546
+ /** Handle touch start — single finger grabs, multi-finger passes through for scroll/zoom */
1547
+ this.handleTouchStart = (event) => {
1548
+ if (event.touches.length >= 2) return;
1549
+ const touch = event.touches[0];
1550
+ const rect = this.canvas.getBoundingClientRect();
1551
+ const x = touch.clientX - rect.left;
1552
+ const y = touch.clientY - rect.top;
1553
+ this.followTargets.set("mouse", { x, y });
1554
+ const grabbed = this.startGrab();
1555
+ if (grabbed) event.preventDefault();
1556
+ };
1557
+ /** Handle touch move — only tracks if something is grabbed */
1558
+ this.handleTouchMove = (event) => {
1559
+ if (event.touches.length >= 2) return;
1560
+ if (!this.grabbedObjectId) return;
1561
+ event.preventDefault();
1562
+ const touch = event.touches[0];
1563
+ const rect = this.canvas.getBoundingClientRect();
1564
+ const x = touch.clientX - rect.left;
1565
+ const y = touch.clientY - rect.top;
1566
+ this.followTargets.set("mouse", { x, y });
1567
+ };
1568
+ /** Handle touch end/cancel — release grab; if it was a tap (no grab), trigger click-to-fall */
1569
+ this.handleTouchEnd = (event) => {
1570
+ const wasGrabbed = this.grabbedObjectId !== null;
1571
+ this.endGrab();
1572
+ if (wasGrabbed) {
1573
+ event.preventDefault();
1574
+ return;
1575
+ }
1576
+ if (event.changedTouches.length > 0) {
1577
+ const touch = event.changedTouches[0];
1578
+ const rect = this.canvas.getBoundingClientRect();
1579
+ this.handleTap(touch.clientX - rect.left, touch.clientY - rect.top);
1580
+ }
1581
+ };
1542
1582
  /**
1543
1583
  * Handler for Matter.js beforeRender event.
1544
1584
  * Draws base background layers (color + image) before physics objects.
@@ -1691,6 +1731,10 @@ var OverlayScene = class {
1691
1731
  canvas.addEventListener("mousemove", this.handleMouseMove);
1692
1732
  canvas.addEventListener("mouseup", this.handleMouseUp);
1693
1733
  canvas.addEventListener("click", this.handleCanvasClick);
1734
+ canvas.addEventListener("touchstart", this.handleTouchStart, { passive: false });
1735
+ canvas.addEventListener("touchmove", this.handleTouchMove, { passive: false });
1736
+ canvas.addEventListener("touchend", this.handleTouchEnd, { passive: false });
1737
+ canvas.addEventListener("touchcancel", this.handleTouchEnd, { passive: false });
1694
1738
  this.effectManager = new EffectManager(
1695
1739
  this.config.bounds,
1696
1740
  (cfg) => this.spawnObjectAsync(cfg),
@@ -2115,6 +2159,10 @@ var OverlayScene = class {
2115
2159
  this.canvas.removeEventListener("mousemove", this.handleMouseMove);
2116
2160
  this.canvas.removeEventListener("mouseup", this.handleMouseUp);
2117
2161
  this.canvas.removeEventListener("click", this.handleCanvasClick);
2162
+ this.canvas.removeEventListener("touchstart", this.handleTouchStart);
2163
+ this.canvas.removeEventListener("touchmove", this.handleTouchMove);
2164
+ this.canvas.removeEventListener("touchend", this.handleTouchEnd);
2165
+ this.canvas.removeEventListener("touchcancel", this.handleTouchEnd);
2118
2166
  import_matter_js5.default.Events.off(this.render, "beforeRender", this.handleBeforeRender);
2119
2167
  import_matter_js5.default.Events.off(this.render, "afterRender", this.handleAfterRender);
2120
2168
  import_matter_js5.default.Events.off(this.engine, "collisionStart", this.handleCollisionStart);