@blorkfield/overlay-core 0.8.0 → 0.8.2

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
@@ -312,6 +312,52 @@ const tagged = scene.getObjectIdsByTag('falling');
312
312
  const allTags = scene.getAllTags();
313
313
  ```
314
314
 
315
+ ## Mouse Position and Grab API
316
+
317
+ 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.
318
+
319
+ ### Setting Mouse Position
320
+
321
+ ```typescript
322
+ // Apply your offset and set the adjusted position
323
+ const canvasX = screenMouseX - canvasOffsetX;
324
+ const canvasY = screenMouseY - canvasOffsetY;
325
+ scene.setFollowTarget('mouse', canvasX, canvasY);
326
+
327
+ // This position is now used for:
328
+ // - Objects with 'follow' tag (they move toward this position)
329
+ // - Programmatic grab detection via startGrab()
330
+ // - MouseConstraint during drag (grabbed objects follow this position)
331
+ ```
332
+
333
+ The offset calculation is your responsibility - overlay-core uses whatever position you provide.
334
+
335
+ ### Programmatic Grab/Release
336
+
337
+ ```typescript
338
+ // Grab object at current mouse position (only 'grabable' tagged objects)
339
+ const grabbedId = scene.startGrab();
340
+ if (grabbedId) {
341
+ console.log(`Grabbed: ${grabbedId}`);
342
+ }
343
+
344
+ // Update mouse position while dragging - object follows automatically
345
+ scene.setFollowTarget('mouse', newX, newY);
346
+
347
+ // Release the grabbed object
348
+ scene.endGrab();
349
+
350
+ // Check what's currently grabbed
351
+ const currentGrab = scene.getGrabbedObject(); // Returns ID or null
352
+ ```
353
+
354
+ | Method | Returns | Description |
355
+ |--------|---------|-------------|
356
+ | `setFollowTarget('mouse', x, y)` | void | Set mouse position for follow behavior and grab detection |
357
+ | `startGrab()` | string \| null | Grab object at current mouse position, returns object ID |
358
+ | `endGrab()` | void | Release any currently grabbed object |
359
+ | `getGrabbedObject()` | string \| null | Get ID of currently grabbed object |
360
+
315
361
  ## Configuration
316
362
 
317
363
  ### Scene Config
package/dist/index.cjs CHANGED
@@ -2327,14 +2327,6 @@ var OverlayScene = class {
2327
2327
  }
2328
2328
  return Array.from(tagsSet).sort();
2329
2329
  }
2330
- /**
2331
- * Set the mouse position for follow behavior.
2332
- * This overrides the browser mouse position for the 'follow' and 'follow-mouse' tags.
2333
- * @deprecated Use setFollowTarget('mouse', x, y) instead
2334
- */
2335
- setMousePosition(x, y) {
2336
- this.setFollowTarget("mouse", x, y);
2337
- }
2338
2330
  /**
2339
2331
  * Set a follow target position. Objects with 'follow-{key}' tag will
2340
2332
  * automatically move toward this target each frame.
@@ -2344,6 +2336,12 @@ var OverlayScene = class {
2344
2336
  */
2345
2337
  setFollowTarget(key, x, y) {
2346
2338
  this.followTargets.set(key, { x, y });
2339
+ if (key === "mouse" && this.mouse) {
2340
+ this.mouse.position.x = x;
2341
+ this.mouse.position.y = y;
2342
+ this.mouse.absolute.x = x;
2343
+ this.mouse.absolute.y = y;
2344
+ }
2347
2345
  }
2348
2346
  /**
2349
2347
  * Remove a follow target. Objects with the corresponding tag will stop following.
@@ -2359,6 +2357,52 @@ var OverlayScene = class {
2359
2357
  getFollowTargetKeys() {
2360
2358
  return Array.from(this.followTargets.keys());
2361
2359
  }
2360
+ // ==================== GRAB/DRAG METHODS ====================
2361
+ /**
2362
+ * Programmatically grab an object at the current mouse position.
2363
+ * Uses the externally set mouse position (via setFollowTarget('mouse', x, y))
2364
+ * or the native canvas mouse position if no external position is set.
2365
+ * Only objects with the 'grabable' tag can be grabbed.
2366
+ * @returns The ID of the grabbed object, or null if no grabable object at position
2367
+ */
2368
+ startGrab() {
2369
+ if (!this.mouseConstraint || !this.mouse) return null;
2370
+ const mouseTarget = this.followTargets.get("mouse");
2371
+ const position = mouseTarget ?? { x: this.mouse.position.x, y: this.mouse.position.y };
2372
+ const bodies = import_matter_js5.default.Query.point(
2373
+ import_matter_js5.default.Composite.allBodies(this.engine.world),
2374
+ position
2375
+ );
2376
+ for (const body of bodies) {
2377
+ const entry = this.findObjectByBody(body);
2378
+ if (entry && entry.tags.includes("grabable")) {
2379
+ this.mouseConstraint.constraint.bodyB = entry.body;
2380
+ this.mouseConstraint.constraint.pointB = {
2381
+ x: position.x - entry.body.position.x,
2382
+ y: position.y - entry.body.position.y
2383
+ };
2384
+ return entry.id;
2385
+ }
2386
+ }
2387
+ return null;
2388
+ }
2389
+ /**
2390
+ * Release any currently grabbed object.
2391
+ */
2392
+ endGrab() {
2393
+ if (this.mouseConstraint) {
2394
+ this.mouseConstraint.constraint.bodyB = null;
2395
+ }
2396
+ }
2397
+ /**
2398
+ * Get the ID of the currently grabbed object.
2399
+ * @returns The ID of the grabbed object, or null if nothing is grabbed
2400
+ */
2401
+ getGrabbedObject() {
2402
+ if (!this.mouseConstraint?.constraint.bodyB) return null;
2403
+ const entry = this.findObjectByBody(this.mouseConstraint.constraint.bodyB);
2404
+ return entry?.id ?? null;
2405
+ }
2362
2406
  // ==================== PHYSICS MANIPULATION METHODS ====================
2363
2407
  /**
2364
2408
  * Apply a force to an object.