bee-ladybug 0.6.1 → 0.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bee-ladybug",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Universal telemetry and visual inspection overlay for Canvas, DOM, Python and AI flows.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -70,6 +70,8 @@ export class CanvasAdapter {
70
70
  this.#fps = 0;
71
71
  this.#fpsSamples = [];
72
72
  this.#wasColliding = new Set();
73
+ this.#names = new Map();
74
+ this.#overlayStyle = null;
73
75
  this.#onResize = () => this.#syncOverlay();
74
76
  this.#onTick = () => {
75
77
  this.#rafId = requestAnimationFrame(this.#onTick);
@@ -93,6 +95,10 @@ export class CanvasAdapter {
93
95
  #fps;
94
96
  #fpsSamples;
95
97
  #wasColliding;
98
+ /** id -> display name, refreshed on every pump. */
99
+ #names;
100
+ /** Last style values written to the overlay. */
101
+ #overlayStyle;
96
102
  #onResize;
97
103
  #onTick;
98
104
 
@@ -126,6 +132,12 @@ export class CanvasAdapter {
126
132
  source: this.source,
127
133
  message: `CanvasAdapter attached (${this.entities.length} entities).`
128
134
  });
135
+ if (this.overlayEnabled && !this.canvas) {
136
+ this.core?.sendData('warn', {
137
+ source: this.source,
138
+ message: 'no canvas: hitboxes are not drawn. Pass { canvas } or call setCanvas().'
139
+ });
140
+ }
129
141
  this.core?.sendData('state', {
130
142
  source: this.source,
131
143
  key: 'adapter',
@@ -146,6 +158,11 @@ export class CanvasAdapter {
146
158
  window.removeEventListener('resize', this.#onResize);
147
159
  window.removeEventListener('scroll', this.#onResize, true);
148
160
  }
161
+ this.#wasColliding = new Set();
162
+ this.#names = new Map();
163
+ this.#lastPump = 0;
164
+ this.#fps = 0;
165
+ this.#fpsSamples = [];
149
166
  return this;
150
167
  }
151
168
 
@@ -163,10 +180,26 @@ export class CanvasAdapter {
163
180
  return this;
164
181
  }
165
182
 
183
+ /**
184
+ * Stop the internal loop and make a manual `pump()` valid again.
185
+ * Mirror of `startAutoPump()`.
186
+ */
187
+ stopAutoPump() {
188
+ this.autoPump = false;
189
+ this.#stopAutoPumpLoop();
190
+ return this;
191
+ }
192
+
166
193
  /** @param {HTMLCanvasElement | null} canvas */
167
194
  setCanvas(canvas) {
168
195
  this.canvas = canvas;
169
- this.#syncOverlay();
196
+ if (!this.#attached) return this;
197
+ if (!canvas) {
198
+ this.#unmountOverlay();
199
+ } else if (this.overlayEnabled) {
200
+ if (this.#overlay) this.#syncOverlay();
201
+ else this.#mountOverlay();
202
+ }
170
203
  return this;
171
204
  }
172
205
 
@@ -327,7 +360,9 @@ export class CanvasAdapter {
327
360
 
328
361
  #emitCollisionEdges(boxes) {
329
362
  const now = new Set();
363
+ const names = new Map();
330
364
  for (let i = 0; i < boxes.length; i++) {
365
+ names.set(boxes[i].id, boxes[i].name);
331
366
  if (!boxes[i].hit) continue;
332
367
  now.add(boxes[i].id);
333
368
  if (!this.#wasColliding.has(boxes[i].id)) {
@@ -339,13 +374,14 @@ export class CanvasAdapter {
339
374
  }
340
375
  for (const id of this.#wasColliding) {
341
376
  if (now.has(id)) continue;
342
- const name = idFromKey(id);
377
+ const name = names.get(id) ?? this.#names.get(id) ?? id;
343
378
  this.core.sendData('log', {
344
379
  source: this.source,
345
380
  message: `${name} left collision`
346
381
  });
347
382
  }
348
383
  this.#wasColliding = now;
384
+ this.#names = names;
349
385
  }
350
386
 
351
387
  #drawHitboxes(boxes, hostCtx) {
@@ -386,7 +422,7 @@ export class CanvasAdapter {
386
422
  }
387
423
 
388
424
  #mountOverlay() {
389
- if (typeof document === 'undefined' || this.#overlay) return;
425
+ if (typeof document === 'undefined' || this.#overlay || !this.canvas) return;
390
426
  const canvas = document.createElement('canvas');
391
427
  canvas.setAttribute('data-bee-ladybug-canvas', '');
392
428
  canvas.style.pointerEvents = 'none';
@@ -395,12 +431,14 @@ export class CanvasAdapter {
395
431
  canvas.style.margin = '0';
396
432
  document.body.appendChild(canvas);
397
433
  this.#overlay = canvas;
434
+ this.#overlayStyle = null;
398
435
  this.#syncOverlay();
399
436
  }
400
437
 
401
438
  #unmountOverlay() {
402
439
  if (this.#overlay?.parentNode) this.#overlay.parentNode.removeChild(this.#overlay);
403
440
  this.#overlay = null;
441
+ this.#overlayStyle = null;
404
442
  }
405
443
 
406
444
  #syncOverlay() {
@@ -408,14 +446,22 @@ export class CanvasAdapter {
408
446
  const overlay = this.#overlay;
409
447
  if (!host || !overlay) return;
410
448
  const rect = host.getBoundingClientRect();
411
- overlay.width = host.width;
412
- overlay.height = host.height;
413
- overlay.style.left = `${rect.left}px`;
414
- overlay.style.top = `${rect.top}px`;
415
- overlay.style.width = `${rect.width}px`;
416
- overlay.style.height = `${rect.height}px`;
449
+ // Assigning width/height clears and reallocates the bitmap: only when they change.
450
+ if (overlay.width !== host.width) overlay.width = host.width;
451
+ if (overlay.height !== host.height) overlay.height = host.height;
417
452
  const hidden = !this.#reporting || (this.core && this.core.visible === false);
418
- overlay.style.display = hidden ? 'none' : 'block';
453
+ const next = {
454
+ left: `${rect.left}px`,
455
+ top: `${rect.top}px`,
456
+ width: `${rect.width}px`,
457
+ height: `${rect.height}px`,
458
+ display: hidden ? 'none' : 'block'
459
+ };
460
+ const prev = this.#overlayStyle;
461
+ for (const key of Object.keys(next)) {
462
+ if (!prev || prev[key] !== next[key]) overlay.style[key] = next[key];
463
+ }
464
+ this.#overlayStyle = next;
419
465
  }
420
466
 
421
467
  #enable() {
@@ -487,11 +533,6 @@ function isPrimary(entity) {
487
533
  return key === 'player' || key === 'hero' || entity.primary === true;
488
534
  }
489
535
 
490
- function idFromKey(id) {
491
- const parts = String(id).split(':');
492
- return parts[parts.length - 1] || id;
493
- }
494
-
495
536
  function round1(value) {
496
537
  return Math.round(Number(value) * 10) / 10;
497
538
  }
@@ -10,7 +10,7 @@ import { UIOverlay } from './UIOverlay.js';
10
10
  import { buildAssistantSnapshot, normalizeAssistant } from './AiAssistant.js';
11
11
  import { exportReport as writeReport } from './ReportExporter.js';
12
12
 
13
- export const BEE_LADYBUG_VERSION = '0.6.1';
13
+ export const BEE_LADYBUG_VERSION = '0.6.2';
14
14
 
15
15
  export const CORE_DEFAULTS = Object.freeze({
16
16
  toggleKey: 'F2',
package/src/index.d.ts CHANGED
@@ -334,6 +334,7 @@ export class CanvasAdapter {
334
334
  attach(): this;
335
335
  detach(): this;
336
336
  startAutoPump(): this;
337
+ stopAutoPump(): this;
337
338
  setCanvas(canvas: HTMLCanvasElement | null): this;
338
339
  setEntities(entities: CanvasEntity[]): this;
339
340
  pump(ctx?: CanvasRenderingContext2D): this;