152 lines
4.6 KiB
JavaScript
152 lines
4.6 KiB
JavaScript
import { app } from "/scripts/app.js";
|
|
import { api } from "/scripts/api.js";
|
|
import {
|
|
setVueBadge,
|
|
clearVueBadges,
|
|
startBadgeObserver
|
|
} from "../modules/node_badges.js";
|
|
|
|
const SETTING_ID = "Mudknight Utils.Execution Time.enabled";
|
|
const SETTING_COLOR = "Mudknight Utils.Execution Time.color";
|
|
const BADGE_CLASS = "mk-exec-time";
|
|
const BADGE_EXTRA = ["ml-auto"];
|
|
|
|
// Semantic theme colors available as badge background presets.
|
|
// Values are CSS custom property names defined by the ComfyUI theme.
|
|
const COLOR_PRESETS = [
|
|
["None", null],
|
|
["Grey", "--muted-background"],
|
|
["Blue", "--primary-background"],
|
|
["Yellow", "--warning-background"],
|
|
["Green", "--success-background"],
|
|
["Red", "--color-error"],
|
|
];
|
|
|
|
app.registerExtension({
|
|
name: "Mudknight Utils.Execution Time",
|
|
|
|
setup() {
|
|
startBadgeObserver();
|
|
|
|
app.ui.settings.addSetting({
|
|
id: SETTING_ID,
|
|
name: "Show node execution time",
|
|
type: "boolean",
|
|
defaultValue: false,
|
|
});
|
|
|
|
app.ui.settings.addSetting({
|
|
id: SETTING_COLOR,
|
|
name: "Execution time badge color",
|
|
type: "combo",
|
|
defaultValue: "None",
|
|
options: COLOR_PRESETS.map(([label]) => label),
|
|
});
|
|
|
|
const timeMap = new Map();
|
|
// Map of nodeId -> elapsed seconds, kept for display.
|
|
const durationMap = new Map();
|
|
let lastId = null;
|
|
|
|
api.addEventListener("execution_start", () => {
|
|
// Clear all durations and badges on a new run.
|
|
durationMap.clear();
|
|
timeMap.clear();
|
|
lastId = null;
|
|
|
|
if (!app.graph) return;
|
|
for (const node of app.graph._nodes) {
|
|
node.executionDuration = undefined;
|
|
clearVueBadges(String(node.id));
|
|
}
|
|
});
|
|
|
|
api.addEventListener("executing", (e) => {
|
|
// The executing event detail is the node ID directly.
|
|
const id = e.detail ?? null;
|
|
|
|
// Record elapsed time for the previously executing node.
|
|
if (lastId !== null && timeMap.has(lastId)) {
|
|
const delta =
|
|
(performance.now() - timeMap.get(lastId)) / 1000;
|
|
durationMap.set(lastId, delta);
|
|
|
|
if (app.ui.settings.getSettingValue(SETTING_ID)) {
|
|
const text = `${delta.toFixed(3)}s`;
|
|
// LiteGraph node.
|
|
const node = app.graph?.getNodeById(lastId);
|
|
if (node) node.executionDuration = delta;
|
|
// Vue node DOM badge.
|
|
const label = app.ui.settings
|
|
.getSettingValue(SETTING_COLOR) ?? "None";
|
|
const color = COLOR_PRESETS.find(
|
|
([l]) => l === label)?.[1] ?? null;
|
|
setVueBadge(
|
|
BADGE_CLASS, BADGE_EXTRA, String(lastId),
|
|
text, color, "clock"
|
|
);
|
|
}
|
|
|
|
timeMap.delete(lastId);
|
|
}
|
|
|
|
lastId = id;
|
|
if (id !== null) timeMap.set(id, performance.now());
|
|
});
|
|
},
|
|
|
|
beforeRegisterNodeDef(nodeType) {
|
|
const orig = nodeType.prototype.onDrawForeground;
|
|
|
|
// LiteGraph canvas rendering path.
|
|
nodeType.prototype.onDrawForeground = function(ctx) {
|
|
if (
|
|
this.executionDuration
|
|
&& app.ui.settings.getSettingValue(SETTING_ID)
|
|
) {
|
|
drawTime(ctx, this.executionDuration);
|
|
}
|
|
|
|
if (orig) return orig.apply(this, arguments);
|
|
};
|
|
},
|
|
});
|
|
|
|
function drawTime(ctx, seconds) {
|
|
const text = `${seconds.toFixed(3)}s`;
|
|
|
|
ctx.save();
|
|
ctx.font = "12px sans-serif";
|
|
|
|
const padding = 4;
|
|
const w = ctx.measureText(text).width + padding * 2;
|
|
const h = LiteGraph.NODE_TITLE_HEIGHT - 10;
|
|
const x = 0;
|
|
const y = -LiteGraph.NODE_TITLE_HEIGHT - 22;
|
|
const r = 4;
|
|
|
|
ctx.fillStyle = LiteGraph.NODE_DEFAULT_BGCOLOR;
|
|
roundedRect(ctx, x, y, w, h, r);
|
|
ctx.fill();
|
|
|
|
ctx.fillStyle = LiteGraph.NODE_TITLE_COLOR;
|
|
ctx.fillText(text, x + padding, y + h - 6);
|
|
|
|
ctx.restore();
|
|
}
|
|
|
|
function roundedRect(ctx, x, y, w, h, r) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(x + r, y);
|
|
ctx.lineTo(x + w - r, y);
|
|
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
|
|
ctx.lineTo(x + w, y + h - r);
|
|
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
|
|
ctx.lineTo(x + r, y + h);
|
|
ctx.quadraticCurveTo(x, y + h, x, y + h - r);
|
|
ctx.lineTo(x, y + r);
|
|
ctx.quadraticCurveTo(x, y, x + r, y);
|
|
ctx.closePath();
|
|
}
|
|
|