@zkmake/three-meter 0.11.5 → 0.12.0
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 +12 -0
- package/dist/index.d.ts +1 -5
- package/dist/index.js +2 -3
- package/dist/{mount-perf-hud-Cu7Jjwmm.js → mount-perf-hud-CJju0oTc.js} +30 -35
- package/dist/mount-perf-hud-CJju0oTc.js.map +1 -0
- package/dist/{mount-perf-hud-MTPYNhG9.d.ts → mount-perf-hud-Cg_iAuFQ.d.ts} +28 -22
- package/dist/{performance-monitor-BqnoiLEs.js → performance-monitor-CKAI0-Dp.js} +6 -11
- package/dist/{performance-monitor-BqnoiLEs.js.map → performance-monitor-CKAI0-Dp.js.map} +1 -1
- package/dist/{performance-monitor-BoY_-GTt.d.ts → performance-monitor-CrYmNIdv.d.ts} +1 -5
- package/dist/react.d.ts +2 -8
- package/dist/react.js +5 -8
- package/dist/react.js.map +1 -1
- package/dist/ui.d.ts +3 -9
- package/dist/ui.js +1 -2
- package/package.json +1 -1
- package/dist/mount-perf-hud-Cu7Jjwmm.js.map +0 -1
package/README.md
CHANGED
|
@@ -182,6 +182,18 @@ hud.setBudgets({ gpu: null }); // null drops a default; false drops them all
|
|
|
182
182
|
|
|
183
183
|
`PerfHud` takes the same `budgets` prop and applies changes live.
|
|
184
184
|
|
|
185
|
+
An app that keeps its budgets in one file with [three-audit](../three-audit)'s `defineBudgets`
|
|
186
|
+
passes that file as is. The HUD applies its `frame`: `fps` as `targetFps`, `calls` and
|
|
187
|
+
`triangles`. The same file holds the per-part budgets its tests and the `three-audit` CLI check.
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import budgets from "./budgets.ts"; // defineBudgets({ frame: { fps: 60, calls: 150, … }, parts })
|
|
191
|
+
|
|
192
|
+
mountPerfHud(monitor, { budgets });
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
three-meter reads the file's shape (`AppBudgets`) and doesn't depend on three-audit.
|
|
196
|
+
|
|
185
197
|
## Top costs
|
|
186
198
|
|
|
187
199
|
The HUD tells you there are 400 draw calls; **top costs** tells you which objects they come from.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { a as GpuTiming, c as RenderBackend, d as Sample, f as SceneCost, i as FrameStats, l as RenderCounts, n as CostEntry, o as PerfRenderer, p as TimingMetric, r as Environment, s as PerformanceMonitorOptions, t as PerformanceMonitor, u as ResourceCounts } from "./performance-monitor-
|
|
2
|
-
//#region src/core/ring-buffer.d.ts
|
|
1
|
+
import { a as GpuTiming, c as RenderBackend, d as Sample, f as SceneCost, i as FrameStats, l as RenderCounts, n as CostEntry, o as PerfRenderer, p as TimingMetric, r as Environment, s as PerformanceMonitorOptions, t as PerformanceMonitor, u as ResourceCounts } from "./performance-monitor-CrYmNIdv.js";
|
|
3
2
|
/**
|
|
4
3
|
* Fixed-capacity numeric ring buffer. Backs the per-frame timing history the
|
|
5
4
|
* view reads to draw sparklines. Push is O(1); `toArray()` returns values in
|
|
@@ -16,8 +15,6 @@ declare class RingBuffer {
|
|
|
16
15
|
toArray(): number[];
|
|
17
16
|
clear(): void;
|
|
18
17
|
}
|
|
19
|
-
//#endregion
|
|
20
|
-
//#region src/core/wrap-animation-loop.d.ts
|
|
21
18
|
type AnimationLoop<Args extends unknown[]> = (...args: Args) => void;
|
|
22
19
|
/**
|
|
23
20
|
* Wrap a `renderer.setAnimationLoop` callback so each tick is one frame:
|
|
@@ -31,6 +28,5 @@ type AnimationLoop<Args extends unknown[]> = (...args: Args) => void;
|
|
|
31
28
|
* ```
|
|
32
29
|
*/
|
|
33
30
|
declare function wrapAnimationLoop<Args extends unknown[]>(monitor: PerformanceMonitor, loop: AnimationLoop<Args>): AnimationLoop<Args>;
|
|
34
|
-
//#endregion
|
|
35
31
|
export { type CostEntry, type Environment, type FrameStats, type GpuTiming, type PerfRenderer, PerformanceMonitor, type PerformanceMonitorOptions, type RenderBackend, type RenderCounts, type ResourceCounts, RingBuffer, type Sample, type SceneCost, type TimingMetric, wrapAnimationLoop };
|
|
36
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as RingBuffer, t as PerformanceMonitor } from "./performance-monitor-
|
|
2
|
-
|
|
1
|
+
import { n as RingBuffer, t as PerformanceMonitor } from "./performance-monitor-CKAI0-Dp.js";
|
|
2
|
+
// src/core/wrap-animation-loop.ts
|
|
3
3
|
/**
|
|
4
4
|
* Wrap a `renderer.setAnimationLoop` callback so each tick is one frame:
|
|
5
5
|
* `begin()` before your code, `end()` after it returns. CPU time is your
|
|
@@ -21,7 +21,6 @@ function wrapAnimationLoop(monitor, loop) {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
//#endregion
|
|
25
24
|
export { PerformanceMonitor, RingBuffer, wrapAnimationLoop };
|
|
26
25
|
|
|
27
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
// src/ui/budgets.ts
|
|
2
2
|
const DEFAULT_TARGET_FPS = 60;
|
|
3
3
|
const FLOORS = /* @__PURE__ */ new Set([
|
|
4
4
|
"fps",
|
|
5
5
|
"headroom",
|
|
6
6
|
"low"
|
|
7
7
|
]);
|
|
8
|
+
const isAppBudgets = (budgets) => "frame" in budgets;
|
|
9
|
+
/** An app's frame budget as the HUD's: only the limits it sets, so the rest keep their defaults. */
|
|
10
|
+
const fromApp = ({ frame }) => {
|
|
11
|
+
const budgets = {};
|
|
12
|
+
if (frame.fps !== void 0) budgets.targetFps = frame.fps;
|
|
13
|
+
if (frame.calls !== void 0) budgets.calls = frame.calls;
|
|
14
|
+
if (frame.triangles !== void 0) budgets.triangles = frame.triangles;
|
|
15
|
+
return budgets;
|
|
16
|
+
};
|
|
8
17
|
/** `detectedHz` is the monitor's refresh reading; an explicit `targetFps` wins over it. */
|
|
9
|
-
const resolveBudgets = (
|
|
18
|
+
const resolveBudgets = (input, detectedHz = null) => {
|
|
19
|
+
const budgets = input && isAppBudgets(input) ? fromApp(input) : input;
|
|
10
20
|
const targetFps = budgets && budgets.targetFps || detectedHz || DEFAULT_TARGET_FPS;
|
|
11
21
|
const frameMs = 1e3 / targetFps;
|
|
12
22
|
if (budgets === false) return {
|
|
@@ -38,8 +48,7 @@ const isOverBudget = (resolved, key, value) => {
|
|
|
38
48
|
if (limit === void 0 || value === null) return false;
|
|
39
49
|
return isFloor(key) ? value < limit : value > limit;
|
|
40
50
|
};
|
|
41
|
-
|
|
42
|
-
//#region src/ui/theme.ts
|
|
51
|
+
// src/ui/theme.ts
|
|
43
52
|
const THEME_MODES = [
|
|
44
53
|
"dark",
|
|
45
54
|
"light",
|
|
@@ -125,8 +134,7 @@ var HudTheme = class {
|
|
|
125
134
|
const applyTheme = (element, theme) => {
|
|
126
135
|
element.dataset.theme = theme.resolved;
|
|
127
136
|
};
|
|
128
|
-
|
|
129
|
-
//#region src/ui/hud-settings.ts
|
|
137
|
+
// src/ui/hud-settings.ts
|
|
130
138
|
const DEFAULT_STORAGE_KEY = "three-meter";
|
|
131
139
|
const DEFAULT_DIM = false;
|
|
132
140
|
const DEFAULT_INFO = false;
|
|
@@ -242,8 +250,7 @@ var HudSettings = class {
|
|
|
242
250
|
for (const listener of this.listeners) listener();
|
|
243
251
|
}
|
|
244
252
|
};
|
|
245
|
-
|
|
246
|
-
//#region src/ui/dock-panel.ts
|
|
253
|
+
// src/ui/dock-panel.ts
|
|
247
254
|
/**
|
|
248
255
|
* Dock a fixed-position panel to a screen edge. Dragging the handle snaps it
|
|
249
256
|
* to the nearest edge on drop; the edge and the offset along it persist under
|
|
@@ -458,8 +465,7 @@ const dockPanel = (element, options = {}) => {
|
|
|
458
465
|
refresh: apply
|
|
459
466
|
};
|
|
460
467
|
};
|
|
461
|
-
|
|
462
|
-
//#region src/ui/icons.ts
|
|
468
|
+
// src/ui/icons.ts
|
|
463
469
|
const ICON_MARKUP = {
|
|
464
470
|
eye: "<path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>",
|
|
465
471
|
eyeOff: "<path d=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\"/><path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\"/><path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\"/><path d=\"m2 2 20 20\"/>",
|
|
@@ -503,8 +509,7 @@ const createIcon = (name, className) => {
|
|
|
503
509
|
svg.innerHTML = ICON_MARKUP[name];
|
|
504
510
|
return svg;
|
|
505
511
|
};
|
|
506
|
-
|
|
507
|
-
//#region src/ui/styles.ts
|
|
512
|
+
// src/ui/styles.ts
|
|
508
513
|
/**
|
|
509
514
|
* The HUD stylesheet as a string, so the package works without a bundler and
|
|
510
515
|
* injects itself once per document. `.perf-monitor` is the metrics card,
|
|
@@ -1245,8 +1250,7 @@ const injectStyles = (target = document) => {
|
|
|
1245
1250
|
style.textContent = PERF_HUD_STYLES;
|
|
1246
1251
|
target.head.append(style);
|
|
1247
1252
|
};
|
|
1248
|
-
|
|
1249
|
-
//#region src/ui/dev-panel.ts
|
|
1253
|
+
// src/ui/dev-panel.ts
|
|
1250
1254
|
/**
|
|
1251
1255
|
* The frame every zkmake dev panel shares, so they look and handle alike: a fixed host docked to a
|
|
1252
1256
|
* screen edge, a card with a brand label on top and the panel's content under it, and three discs
|
|
@@ -1294,6 +1298,7 @@ const mountDevPanel = (options) => {
|
|
|
1294
1298
|
const host = document.createElement("div");
|
|
1295
1299
|
host.className = "perf-hud";
|
|
1296
1300
|
host.dataset.edge = "left";
|
|
1301
|
+
host.setAttribute("role", "group");
|
|
1297
1302
|
host.setAttribute("aria-label", options.label);
|
|
1298
1303
|
const hotspot = document.createElement("div");
|
|
1299
1304
|
hotspot.className = "perf-hud__hotspot";
|
|
@@ -1393,12 +1398,10 @@ const mountDevPanel = (options) => {
|
|
|
1393
1398
|
}
|
|
1394
1399
|
};
|
|
1395
1400
|
};
|
|
1396
|
-
|
|
1397
|
-
//#region package.json
|
|
1401
|
+
// package.json
|
|
1398
1402
|
var name = "@zkmake/three-meter";
|
|
1399
|
-
var version = "0.
|
|
1400
|
-
|
|
1401
|
-
//#region src/ui/clipboard.ts
|
|
1403
|
+
var version = "0.12.0";
|
|
1404
|
+
// src/ui/clipboard.ts
|
|
1402
1405
|
/**
|
|
1403
1406
|
* Copy text from a click handler. The async Clipboard API needs a secure
|
|
1404
1407
|
* context and the `clipboard-write` permission; a dev server opened over a LAN
|
|
@@ -1432,8 +1435,7 @@ const copyText = async (text) => {
|
|
|
1432
1435
|
return copyWithSelection(text);
|
|
1433
1436
|
}
|
|
1434
1437
|
};
|
|
1435
|
-
|
|
1436
|
-
//#region src/ui/format.ts
|
|
1438
|
+
// src/ui/format.ts
|
|
1437
1439
|
/**
|
|
1438
1440
|
* Number formatting for the card. Counts stay exact with thousands separators
|
|
1439
1441
|
* while they fit the compact grid's 6ch value column (`99,999`), then switch
|
|
@@ -1447,8 +1449,7 @@ const compact = new Intl.NumberFormat("en-US", {
|
|
|
1447
1449
|
notation: "compact"
|
|
1448
1450
|
});
|
|
1449
1451
|
const formatCount = (value) => Math.abs(value) < COMPACT_FROM ? exact.format(value) : compact.format(value);
|
|
1450
|
-
|
|
1451
|
-
//#region src/ui/hider.ts
|
|
1452
|
+
// src/ui/hider.ts
|
|
1452
1453
|
var Hider = class {
|
|
1453
1454
|
groups = /* @__PURE__ */ new Map();
|
|
1454
1455
|
/** Each hidden object's `visible` from before the first group hid it. */
|
|
@@ -1486,8 +1487,7 @@ var Hider = class {
|
|
|
1486
1487
|
return false;
|
|
1487
1488
|
}
|
|
1488
1489
|
};
|
|
1489
|
-
|
|
1490
|
-
//#region src/ui/metric-help.ts
|
|
1490
|
+
// src/ui/metric-help.ts
|
|
1491
1491
|
/**
|
|
1492
1492
|
* One plain-language line per metric: what it is, and what a bad reading
|
|
1493
1493
|
* means. Shown as the label's tooltip and, with "explain metrics" on, under
|
|
@@ -1511,8 +1511,7 @@ const METRIC_HELP = {
|
|
|
1511
1511
|
textures: "Textures held in GPU memory. Should level off; a steady climb is a leak, so dispose() what you remove.",
|
|
1512
1512
|
triangles: "Triangles drawn this frame. Mostly GPU cost: use lower-poly models or level of detail to cut it."
|
|
1513
1513
|
};
|
|
1514
|
-
|
|
1515
|
-
//#region src/ui/report.ts
|
|
1514
|
+
// src/ui/report.ts
|
|
1516
1515
|
/**
|
|
1517
1516
|
* A plain-text snapshot of the monitor for bug reports: versions, backend and
|
|
1518
1517
|
* GPU, the current sample, stutter stats, the scene's top meshes and the page. Fenced as a `text`
|
|
@@ -1594,8 +1593,7 @@ const formatReport = (monitor) => renderReport({
|
|
|
1594
1593
|
sample: monitor.getSample(),
|
|
1595
1594
|
stats: monitor.getFrameStats()
|
|
1596
1595
|
});
|
|
1597
|
-
|
|
1598
|
-
//#region src/ui/sparkline.ts
|
|
1596
|
+
// src/ui/sparkline.ts
|
|
1599
1597
|
function drawSparkline(ctx, width, height, values, style, guide) {
|
|
1600
1598
|
ctx.clearRect(0, 0, width, height);
|
|
1601
1599
|
if (values.length < 2) return;
|
|
@@ -1627,8 +1625,7 @@ function drawSparkline(ctx, width, height, values, style, guide) {
|
|
|
1627
1625
|
ctx.restore();
|
|
1628
1626
|
}
|
|
1629
1627
|
}
|
|
1630
|
-
|
|
1631
|
-
//#region src/ui/performance-view.ts
|
|
1628
|
+
// src/ui/performance-view.ts
|
|
1632
1629
|
const TIMINGS = [
|
|
1633
1630
|
{
|
|
1634
1631
|
format: (value) => Math.round(value).toString(),
|
|
@@ -2496,8 +2493,7 @@ var PerformanceView = class {
|
|
|
2496
2493
|
sizeAll(this.hudGraphs.values());
|
|
2497
2494
|
}
|
|
2498
2495
|
};
|
|
2499
|
-
|
|
2500
|
-
//#region src/ui/mount-perf-hud.ts
|
|
2496
|
+
// src/ui/mount-perf-hud.ts
|
|
2501
2497
|
const mountPerfHud = (monitor, options = {}) => {
|
|
2502
2498
|
const storageKey = options.storageKey === void 0 ? DEFAULT_STORAGE_KEY : options.storageKey;
|
|
2503
2499
|
const settings = options.settings ?? new HudSettings({ storageKey });
|
|
@@ -2555,7 +2551,6 @@ const mountPerfHud = (monitor, options = {}) => {
|
|
|
2555
2551
|
view
|
|
2556
2552
|
};
|
|
2557
2553
|
};
|
|
2558
|
-
//#endregion
|
|
2559
2554
|
export { PERF_HUD_STYLES as a, DEFAULT_STORAGE_KEY as c, THEME_MODES as d, isThemeMode as f, mountDevPanel as i, HudSettings as l, PerformanceView as n, injectStyles as o, resolveBudgets as p, formatReport as r, dockPanel as s, mountPerfHud as t, HudTheme as u };
|
|
2560
2555
|
|
|
2561
|
-
//# sourceMappingURL=mount-perf-hud-
|
|
2556
|
+
//# sourceMappingURL=mount-perf-hud-CJju0oTc.js.map
|