chore: init clean tree
This commit is contained in:
103
src/renderer/debug-hud.ts
Normal file
103
src/renderer/debug-hud.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import type { CanvasRenderingContext2D } from "@napi-rs/canvas";
|
||||
|
||||
import type { Layout } from "./layout";
|
||||
|
||||
export type DebugStats = Record<string, string | number | boolean | undefined>;
|
||||
|
||||
export type DebugHudOptions = {
|
||||
showGlobal: boolean;
|
||||
showRenderer: boolean;
|
||||
showCustom?: boolean;
|
||||
};
|
||||
|
||||
export type DebugHudData = {
|
||||
global: DebugStats | string[];
|
||||
renderer: {
|
||||
id: string;
|
||||
label: string;
|
||||
stats: DebugStats;
|
||||
fps: number;
|
||||
};
|
||||
custom?: DebugStats;
|
||||
};
|
||||
|
||||
export type DebugHud = {
|
||||
draw: (ctx: CanvasRenderingContext2D, layout: Layout, data: DebugHudData) => void;
|
||||
};
|
||||
|
||||
export function createDebugHud(options: DebugHudOptions): DebugHud {
|
||||
const padding = 8;
|
||||
const lineHeight = 16;
|
||||
const bg = "rgba(0, 0, 0, 0.65)";
|
||||
const fg = "yellow"; // global
|
||||
const rendererFg = "#ff66cc"; // renderer
|
||||
const customFg = "#00c6ff"; // custom
|
||||
|
||||
const drawBlock = (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
x: number,
|
||||
y: number,
|
||||
title: string,
|
||||
stats: DebugStats | string[],
|
||||
color: string
|
||||
): { width: number; height: number } => {
|
||||
let lines: string[] = [];
|
||||
if (Array.isArray(stats)) {
|
||||
lines = stats
|
||||
} else {
|
||||
const keys = Object.keys(stats);
|
||||
lines = [title, ...keys.map((k) => `${k}: ${String(stats[k])}`)];
|
||||
}
|
||||
ctx.font = "14px \"JetBrains Mono\", monospace";
|
||||
const textWidth = Math.max(...lines.map((l) => ctx.measureText(l).width));
|
||||
const height = lines.length * lineHeight + padding * 2;
|
||||
const width = textWidth + padding * 2;
|
||||
|
||||
ctx.save();
|
||||
ctx.fillStyle = bg;
|
||||
ctx.fillRect(x, y, width, height);
|
||||
ctx.fillStyle = color;
|
||||
ctx.textBaseline = "top";
|
||||
lines.forEach((line, i) => {
|
||||
ctx.fillText(line, x + padding, y + padding + i * lineHeight);
|
||||
});
|
||||
ctx.restore();
|
||||
|
||||
return { width, height };
|
||||
};
|
||||
|
||||
const draw = (ctx: CanvasRenderingContext2D, layout: Layout, data: DebugHudData) => {
|
||||
if (!options.showGlobal && !options.showRenderer && !options.showCustom) return;
|
||||
ctx.save();
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
ctx.globalAlpha = 0.9;
|
||||
|
||||
let cursorY = padding;
|
||||
const originX = padding;
|
||||
|
||||
if (options.showGlobal) {
|
||||
const { height } = drawBlock(ctx, originX, cursorY, "Global", data.global, fg);
|
||||
cursorY += height + padding;
|
||||
}
|
||||
|
||||
if (options.showRenderer) {
|
||||
const { height } = drawBlock(
|
||||
ctx,
|
||||
originX,
|
||||
cursorY,
|
||||
`Renderer: ${data.renderer.label}`,
|
||||
{ fps: data.renderer.fps.toFixed(2), ...data.renderer.stats },
|
||||
rendererFg
|
||||
);
|
||||
cursorY += height + padding;
|
||||
}
|
||||
|
||||
if (options.showCustom && data.custom) {
|
||||
drawBlock(ctx, originX, cursorY, "Custom", data.custom, customFg);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
return { draw };
|
||||
}
|
||||
Reference in New Issue
Block a user