bee-ladybug 0.6.1 → 0.6.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/package.json +1 -1
- package/src/adapters/CanvasAdapter.js +56 -15
- package/src/adapters/WebDOMAdapter.js +60 -21
- package/src/core/BeeLadybugCore.js +1 -1
- package/src/index.d.ts +3 -0
- package/src/index.js +1 -1
package/package.json
CHANGED
|
@@ -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.#
|
|
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 =
|
|
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
|
-
|
|
412
|
-
overlay.
|
|
413
|
-
overlay.
|
|
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
|
-
|
|
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
|
}
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
import { isReportNoise } from '../core/ReportExporter.js';
|
|
18
18
|
|
|
19
19
|
const MAX_PROBLEM_ROWS = 40;
|
|
20
|
+
const OBSERVE_OPTIONS = Object.freeze({
|
|
21
|
+
childList: true,
|
|
22
|
+
subtree: true,
|
|
23
|
+
attributes: true,
|
|
24
|
+
attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
|
|
25
|
+
});
|
|
20
26
|
|
|
21
27
|
export const WEB_DOM_ADAPTER_DEFAULTS = Object.freeze({
|
|
22
28
|
overlay: true,
|
|
@@ -74,6 +80,7 @@ export class WebDOMAdapter {
|
|
|
74
80
|
this.#seenAttr = 0;
|
|
75
81
|
this.#mutTimer = 0;
|
|
76
82
|
this.#lastHoverKey = '';
|
|
83
|
+
this.#overlayStyle = null;
|
|
77
84
|
this.#onMove = (event) => {
|
|
78
85
|
this.#pointer.x = event.clientX;
|
|
79
86
|
this.#pointer.y = event.clientY;
|
|
@@ -104,6 +111,8 @@ export class WebDOMAdapter {
|
|
|
104
111
|
#seenAttr;
|
|
105
112
|
#mutTimer;
|
|
106
113
|
#lastHoverKey;
|
|
114
|
+
/** Last style values written to the overlay. */
|
|
115
|
+
#overlayStyle;
|
|
107
116
|
#onMove;
|
|
108
117
|
#onResize;
|
|
109
118
|
#onTick;
|
|
@@ -118,6 +127,7 @@ export class WebDOMAdapter {
|
|
|
118
127
|
if (this.core && typeof this.core.subscribe === 'function') {
|
|
119
128
|
this.#unsubscribe = this.core.subscribe((packet) => this.#onCore(packet));
|
|
120
129
|
}
|
|
130
|
+
this.#reporting = true;
|
|
121
131
|
if (this.overlayEnabled) this.#mountOverlay();
|
|
122
132
|
if (typeof window !== 'undefined') {
|
|
123
133
|
window.addEventListener('mousemove', this.#onMove, true);
|
|
@@ -126,18 +136,12 @@ export class WebDOMAdapter {
|
|
|
126
136
|
}
|
|
127
137
|
if (this.root && typeof MutationObserver !== 'undefined') {
|
|
128
138
|
this.#observer = new MutationObserver(this.#onMutate);
|
|
129
|
-
this.#observer.observe(this.root,
|
|
130
|
-
childList: true,
|
|
131
|
-
subtree: true,
|
|
132
|
-
attributes: true,
|
|
133
|
-
attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
|
|
134
|
-
});
|
|
139
|
+
this.#observer.observe(this.root, OBSERVE_OPTIONS);
|
|
135
140
|
}
|
|
136
141
|
if (this.autoTick && typeof requestAnimationFrame === 'function') {
|
|
137
142
|
this.#rafId = requestAnimationFrame(this.#onTick);
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
this.#reporting = true;
|
|
141
145
|
this.core?.registerAdapter('dom', {
|
|
142
146
|
label: 'DOM',
|
|
143
147
|
enabled: true,
|
|
@@ -178,24 +182,41 @@ export class WebDOMAdapter {
|
|
|
178
182
|
window.removeEventListener('scroll', this.#onResize, true);
|
|
179
183
|
}
|
|
180
184
|
this.#unmountOverlay();
|
|
185
|
+
this.hover = null;
|
|
186
|
+
this.#lastHoverKey = '';
|
|
187
|
+
this.#lastPump = 0;
|
|
188
|
+
this.#fps = 0;
|
|
189
|
+
this.#pointer = { x: 0, y: 0, dirty: false };
|
|
190
|
+
this.#mutAdded = 0;
|
|
191
|
+
this.#mutRemoved = 0;
|
|
192
|
+
this.#mutAttr = 0;
|
|
193
|
+
this.#seenAdded = 0;
|
|
194
|
+
this.#seenRemoved = 0;
|
|
195
|
+
this.#seenAttr = 0;
|
|
181
196
|
return this;
|
|
182
197
|
}
|
|
183
198
|
|
|
184
199
|
/** @param {ParentNode | null} root */
|
|
185
200
|
setRoot(root) {
|
|
186
201
|
this.root = root;
|
|
187
|
-
if (this.#
|
|
188
|
-
|
|
189
|
-
this.#observer
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
|
|
194
|
-
});
|
|
202
|
+
if (this.#observer) this.#observer.disconnect();
|
|
203
|
+
if (!root) {
|
|
204
|
+
this.#observer = null;
|
|
205
|
+
} else if (this.#attached && typeof MutationObserver !== 'undefined') {
|
|
206
|
+
if (!this.#observer) this.#observer = new MutationObserver(this.#onMutate);
|
|
207
|
+
this.#observer.observe(root, OBSERVE_OPTIONS);
|
|
195
208
|
}
|
|
209
|
+
if (this.hover && !this.#rootHolds(this.hover)) this.hover = null;
|
|
196
210
|
return this;
|
|
197
211
|
}
|
|
198
212
|
|
|
213
|
+
#rootHolds(node) {
|
|
214
|
+
const root = this.root;
|
|
215
|
+
if (!root) return false;
|
|
216
|
+
if (typeof document !== 'undefined' && root === document) return true;
|
|
217
|
+
return node === root || Boolean(root.contains?.(node));
|
|
218
|
+
}
|
|
219
|
+
|
|
199
220
|
/**
|
|
200
221
|
* Box model of the hover and watched nodes, layout problems under root,
|
|
201
222
|
* and the latest mutation counts. Returns null when detached.
|
|
@@ -311,6 +332,7 @@ export class WebDOMAdapter {
|
|
|
311
332
|
this.#lastHoverKey = '';
|
|
312
333
|
this.core.sendData('state', { source: this.source, key: 'hover', value: '—' });
|
|
313
334
|
this.core.sendData('state', { source: this.source, key: 'box', value: '—' });
|
|
335
|
+
this.core.sendData('state', { source: this.source, key: 'display', value: '—' });
|
|
314
336
|
}
|
|
315
337
|
return;
|
|
316
338
|
}
|
|
@@ -341,7 +363,7 @@ export class WebDOMAdapter {
|
|
|
341
363
|
}
|
|
342
364
|
|
|
343
365
|
#queueMutations(records) {
|
|
344
|
-
if (this.frozen) return;
|
|
366
|
+
if (this.frozen || !this.#reporting) return;
|
|
345
367
|
for (let i = 0; i < records.length; i++) {
|
|
346
368
|
const rec = records[i];
|
|
347
369
|
if (isBeeChrome(rec.target)) continue;
|
|
@@ -433,12 +455,14 @@ export class WebDOMAdapter {
|
|
|
433
455
|
canvas.style.margin = '0';
|
|
434
456
|
document.body.appendChild(canvas);
|
|
435
457
|
this.#overlay = canvas;
|
|
458
|
+
this.#overlayStyle = null;
|
|
436
459
|
this.#syncOverlay();
|
|
437
460
|
}
|
|
438
461
|
|
|
439
462
|
#unmountOverlay() {
|
|
440
463
|
if (this.#overlay?.parentNode) this.#overlay.parentNode.removeChild(this.#overlay);
|
|
441
464
|
this.#overlay = null;
|
|
465
|
+
this.#overlayStyle = null;
|
|
442
466
|
}
|
|
443
467
|
|
|
444
468
|
#syncOverlay() {
|
|
@@ -447,12 +471,22 @@ export class WebDOMAdapter {
|
|
|
447
471
|
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
448
472
|
const w = window.innerWidth;
|
|
449
473
|
const h = window.innerHeight;
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
canvas.
|
|
474
|
+
// Assigning width/height clears and reallocates the bitmap: only when they change.
|
|
475
|
+
const bitmapW = Math.round(w * dpr);
|
|
476
|
+
const bitmapH = Math.round(h * dpr);
|
|
477
|
+
if (canvas.width !== bitmapW) canvas.width = bitmapW;
|
|
478
|
+
if (canvas.height !== bitmapH) canvas.height = bitmapH;
|
|
454
479
|
const hidden = !this.#reporting || (this.core && this.core.visible === false);
|
|
455
|
-
|
|
480
|
+
const next = {
|
|
481
|
+
width: `${w}px`,
|
|
482
|
+
height: `${h}px`,
|
|
483
|
+
display: hidden ? 'none' : 'block'
|
|
484
|
+
};
|
|
485
|
+
const prev = this.#overlayStyle;
|
|
486
|
+
for (const key of Object.keys(next)) {
|
|
487
|
+
if (!prev || prev[key] !== next[key]) canvas.style[key] = next[key];
|
|
488
|
+
}
|
|
489
|
+
this.#overlayStyle = next;
|
|
456
490
|
}
|
|
457
491
|
|
|
458
492
|
#enable() {
|
|
@@ -462,6 +496,11 @@ export class WebDOMAdapter {
|
|
|
462
496
|
|
|
463
497
|
#disable() {
|
|
464
498
|
this.#reporting = false;
|
|
499
|
+
if (this.#mutTimer && typeof clearTimeout === 'function') clearTimeout(this.#mutTimer);
|
|
500
|
+
this.#mutTimer = 0;
|
|
501
|
+
this.#mutAdded = 0;
|
|
502
|
+
this.#mutRemoved = 0;
|
|
503
|
+
this.#mutAttr = 0;
|
|
465
504
|
this.#syncOverlay();
|
|
466
505
|
}
|
|
467
506
|
|
|
@@ -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.
|
|
13
|
+
export const BEE_LADYBUG_VERSION = '0.6.3';
|
|
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;
|
|
@@ -355,6 +356,8 @@ export interface WebDOMAdapterOptions {
|
|
|
355
356
|
|
|
356
357
|
export const WEB_DOM_ADAPTER_DEFAULTS: Required<Omit<WebDOMAdapterOptions, 'root'>>;
|
|
357
358
|
|
|
359
|
+
export function domNoiseQuiet(cssEnabled: boolean, frozen: boolean, timeScale: number): boolean;
|
|
360
|
+
|
|
358
361
|
export class WebDOMAdapter {
|
|
359
362
|
core: BeeLadybugCore | null;
|
|
360
363
|
root: ParentNode | null;
|
package/src/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { BeeLadybugCore, BEE_LADYBUG_VERSION, CORE_DEFAULTS, WELL_KNOWN_TYPES, f
|
|
|
2
2
|
export { exportReport, isReportNoise } from './core/ReportExporter.js';
|
|
3
3
|
export { UIOverlay } from './core/UIOverlay.js';
|
|
4
4
|
export { CanvasAdapter, CANVAS_ADAPTER_DEFAULTS } from './adapters/CanvasAdapter.js';
|
|
5
|
-
export { WebDOMAdapter, WEB_DOM_ADAPTER_DEFAULTS } from './adapters/WebDOMAdapter.js';
|
|
5
|
+
export { WebDOMAdapter, WEB_DOM_ADAPTER_DEFAULTS, domNoiseQuiet } from './adapters/WebDOMAdapter.js';
|
|
6
6
|
export { CSSAdapter, CSS_ADAPTER_DEFAULTS } from './adapters/CSSAdapter.js';
|
|
7
7
|
export { AntAdapter, ANT_ADAPTER_DEFAULTS } from './adapters/AntAdapter.js';
|
|
8
8
|
export { SpiderAdapter, SPIDER_ADAPTER_DEFAULTS } from './adapters/SpiderAdapter.js';
|