mis-custom-nodes / comfyui_fill-nodes /web /FL_SystemCheck.js
MarkLilly's picture
Add files using upload-large-folder tool
c225a63 verified
Raw History Blame Contribute Delete
7.12 kB
// custom_nodes/FL_SystemCheck.js
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
app.registerExtension({
name: "FL.SystemCheck",
async nodeCreated(node) {
if (node.comfyClass === "FL_SystemCheck") {
node.color = "#2a363b";
node.bgcolor = "#4F0074";
node.systemInfo = null;
node.animationOffset = 0;
// Add button widget
const widget = node.addWidget("button", "Run System Check", null, () => {
runSystemCheck(node);
});
widget.serialize = false;
// Override the default drawing behavior
node.onDrawForeground = function(ctx) {
if (this.systemInfo) {
drawSystemInfo(ctx, this);
}
};
// Start animation loop
animateNode(node);
}
},
});
function animateNode(node) {
node.animationOffset += 0.005; // Adjust speed as needed
if (node.animationOffset > 1) node.animationOffset -= 1;
node.setDirtyCanvas(true);
requestAnimationFrame(() => animateNode(node));
}
async function runSystemCheck(node) {
try {
const response = await api.fetchApi('/fl_system_info');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
node.systemInfo = await response.json();
// Remove ENV variables
delete node.systemInfo["Env: PYTHONPATH"];
delete node.systemInfo["Env: CUDA_HOME"];
delete node.systemInfo["Env: LD_LIBRARY_PATH"];
node.setDirtyCanvas(true);
} catch (error) {
console.error("Error fetching system info:", error);
node.systemInfo = { "Error": "Failed to fetch system information. Check console for details." };
node.setDirtyCanvas(true);
}
}
function drawSystemInfo(ctx, node) {
const margin = 15;
const componentHeight = 30;
const componentSpacing = 10;
let y = 60; // Start below the node title and button
ctx.save();
ctx.font = "12px Arial";
const components = Object.entries(node.systemInfo).map(([key, value]) => ({
key,
value,
icon: getIconForKey(key),
color: getColorForKey(key)
}));
// Calculate max width
let maxWidth = 0;
components.forEach(comp => {
ctx.font = "bold 12px Arial";
const labelWidth = ctx.measureText(comp.key).width;
ctx.font = "12px Arial";
const valueWidth = ctx.measureText(comp.value).width;
const componentWidth = labelWidth + valueWidth + 80; // 80 for padding and icon
maxWidth = Math.max(maxWidth, componentWidth);
});
// Draw components
components.forEach((comp, index) => {
const staggeredOffset = (node.animationOffset + index * 0.1) % 1; // Stagger the animation
drawComponent(ctx, comp.key, comp.value, y, maxWidth, componentHeight, comp.color, comp.icon, staggeredOffset);
y += componentHeight + componentSpacing;
});
// Adjust node size
node.size[0] = maxWidth + 2 * margin;
node.size[1] = y + margin;
ctx.restore();
}
function drawComponent(ctx, label, value, y, width, height, color, icon, animationOffset) {
const radius = 5;
const iconWidth = 30;
const padding = 5;
// Draw component background
ctx.fillStyle = color;
roundRect(ctx, 15, y, width, height, radius, true, false);
// Draw icon background
ctx.fillStyle = lightenColor(color, 20);
roundRect(ctx, 15, y, iconWidth, height, radius, true, false);
// Draw icon (centered)
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(icon, 15 + iconWidth / 2, y + height / 2);
// Reset text alignment for label and value
ctx.textAlign = "left";
ctx.textBaseline = "alphabetic";
// Draw label and value
ctx.font = "bold 12px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText(label, 55, y + height / 2 + 5);
ctx.font = "12px Arial";
const valueWidth = ctx.measureText(value).width;
ctx.fillText(value, width - valueWidth - padding, y + height / 2 + 5);
// Draw animation
drawFluidAnimation(ctx, 15, y, width, height, lightenColor(color, 10), animationOffset);
}
function drawFluidAnimation(ctx, x, y, width, height, color, offset) {
ctx.save();
ctx.globalCompositeOperation = 'overlay';
ctx.globalAlpha = 0.3;
const gradient = ctx.createLinearGradient(x, y, x + width, y);
gradient.addColorStop(0, 'rgba(255,255,255,0)');
gradient.addColorStop(0.5, color);
gradient.addColorStop(1, 'rgba(255,255,255,0)');
ctx.fillStyle = gradient;
// Create a wavy path
ctx.beginPath();
ctx.moveTo(x, y);
const waveHeight = height * 0.4;
const waveCount = 3;
for (let i = 0; i <= width; i++) {
const dx = i / width;
const offsetY = Math.sin((dx + offset) * Math.PI * 2 * waveCount) * waveHeight;
ctx.lineTo(x + i, y + height / 2 + offsetY);
}
ctx.lineTo(x + width, y + height);
ctx.lineTo(x, y + height);
ctx.closePath();
ctx.fill();
ctx.restore();
}
function roundRect(ctx, x, y, width, height, radius, fill, stroke) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.arcTo(x + width, y, x + width, y + height, radius);
ctx.arcTo(x + width, y + height, x, y + height, radius);
ctx.arcTo(x, y + height, x, y, radius);
ctx.arcTo(x, y, x + width, y, radius);
ctx.closePath();
if (fill) {
ctx.fill();
}
if (stroke) {
ctx.stroke();
}
}
function lightenColor(color, percent) {
const num = parseInt(color.replace("#", ""), 16),
amt = Math.round(2.55 * percent),
R = (num >> 16) + amt,
G = (num >> 8 & 0x00FF) + amt,
B = (num & 0x0000FF) + amt;
return "#" + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
(G < 255 ? G < 1 ? 0 : G : 255) * 0x100 +
(B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1);
}
function getIconForKey(key) {
const iconMap = {
"Operating System": "๐Ÿ–ฅ๏ธ",
"CPU": "โš™๏ธ",
"RAM": "๐Ÿง ",
"GPU": "๐ŸŽฎ",
"CUDA version": "๐Ÿš€",
"Python version": "๐Ÿ",
"PyTorch": "๐Ÿ”ฅ",
"xformers": "โšก",
"torchvision": "๐Ÿ‘๏ธ",
"numpy": "๐Ÿ”ข",
"Pillow": "๐Ÿ–ผ๏ธ",
"OpenCV": "๐Ÿ“ท",
"transformers": "๐Ÿค–"
};
return iconMap[key] || "โ„น๏ธ";
}
function getColorForKey(key) {
const colorMap = {
"Operating System": "#4a90e2",
"CPU": "#50c878",
"RAM": "#9b59b6",
"GPU": "#e74c3c",
"CUDA version": "#f39c12",
"Python version": "#3498db",
"PyTorch": "#e67e22",
"xformers": "#1abc9c",
"torchvision": "#34495e",
"numpy": "#2ecc71",
"Pillow": "#e84393",
"OpenCV": "#c5a01c",
"transformers": "#6c5ce7"
};
return colorMap[key] || "#95a5a6";
}