Files

151 lines
5.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { app } from "/scripts/app.js";
// PixelForge Resolution Matrix - Frontend Extension
console.log("PixelForge: Extension script loaded");
app.registerExtension({
name: "PixelForge.ResolutionMatrix",
async nodeCreated(node) {
console.log("PixelForge: nodeCreated called for", node.comfyClass);
// Handle both Resolution Selector and Resize Image nodes
if (node.comfyClass !== "PixelForge" && node.comfyClass !== "PixelForgeResizeImage") return;
console.log("PixelForge: Initializing", node.comfyClass, "node");
const ASPECT_RATIOS = {
"1:1": [1, 1],
"3:2": [3, 2],
"4:3": [4, 3],
"16:9": [16, 9],
"16:10": [16, 10],
};
const MP_BASE = 1024 * 1024;
const aspectWidget = node.widgets.find(w => w.name === "aspect_ratio");
const orientationWidget = node.widgets.find(w => w.name === "orientation");
const divisibleWidget = node.widgets.find(w => w.name === "divisible_by");
const mpLimitWidget = node.widgets.find(w => w.name === "max_megapixels");
const resolutionWidget = node.widgets.find(w => w.name === "resolution");
console.log("PixelForge: Found widgets:", {
aspectWidget: !!aspectWidget,
orientationWidget: !!orientationWidget,
divisibleWidget: !!divisibleWidget,
mpLimitWidget: !!mpLimitWidget,
resolutionWidget: !!resolutionWidget
});
if (!aspectWidget || !resolutionWidget) {
console.error("PixelForge: Required widgets not found!");
return;
}
const updateResolutions = () => {
const aspect = aspectWidget.value;
const orientation = orientationWidget ? orientationWidget.value : "landscape";
const div = divisibleWidget ? parseInt(divisibleWidget.value) : 16;
const maxMpStr = mpLimitWidget ? mpLimitWidget.value : "4 MP";
const maxMp = parseInt(maxMpStr.split(" ")[0]);
console.log("PixelForge: updateResolutions called with:", { aspect, orientation, div, maxMp });
// Auto-adjust orientation based on aspect ratio
if (orientationWidget) {
if (aspect === "1:1" && orientation !== "square") {
// For 1:1, force square orientation
orientationWidget.value = "square";
console.log("PixelForge: Auto-selected square orientation for 1:1 ratio");
} else if (aspect !== "1:1" && orientation === "square") {
// For non-1:1 ratios, if currently square, switch to landscape
orientationWidget.value = "landscape";
console.log("PixelForge: Auto-switched from square to landscape for non-1:1 ratio");
}
}
const ratio = ASPECT_RATIOS[aspect];
if (!ratio) {
console.error("PixelForge: Invalid aspect ratio:", aspect);
return;
}
const [ratio_w, ratio_h] = ratio;
const maxPixels = maxMp * MP_BASE;
const resolutions = [];
let k = div;
while (true) {
let w = ratio_w * k;
let h = ratio_h * k;
const total = w * h;
if (total > maxPixels) break;
// For square aspect ratio (1:1), orientation doesn't matter
// For portrait, swap dimensions
const currentOrientation = orientationWidget ? orientationWidget.value : orientation;
if (currentOrientation === "portrait" && aspect !== "1:1") {
[w, h] = [h, w];
}
resolutions.push(`${w}×${h}`);
k += div;
}
if (resolutions.length === 0) {
resolutions.push("INVALID");
}
console.log("PixelForge: Generated resolutions:", resolutions.length, resolutions.slice(0, 5));
// Update the widget options
resolutionWidget.options.values = resolutions;
// If current value is not in the new list, pick the first one
if (!resolutions.includes(resolutionWidget.value)) {
console.log("PixelForge: Current value not in list, setting to:", resolutions[0]);
resolutionWidget.value = resolutions[0];
}
node.setDirtyCanvas(true, true);
console.log("PixelForge: Canvas marked dirty");
};
// Hook callbacks for all triggers
const widgetsToWatch = [aspectWidget, orientationWidget, divisibleWidget, mpLimitWidget];
widgetsToWatch.forEach(widget => {
if (!widget) return;
const origCallback = widget.callback;
widget.callback = function () {
console.log("PixelForge: Widget callback triggered for:", widget.name);
const result = origCallback ? origCallback.apply(this, arguments) : undefined;
updateResolutions();
return result;
};
});
console.log("PixelForge: Callbacks hooked, running initial update");
// Initial update
setTimeout(() => updateResolutions(), 10);
},
async loadedGraphNode(node) {
// Handle both Resolution Selector and Resize Image nodes
if (node.comfyClass !== "PixelForge" && node.comfyClass !== "PixelForgeResizeImage") return;
console.log("PixelForge: loadedGraphNode called for", node.comfyClass);
// Re-trigger the same logic when a node is loaded
const aspectWidget = node.widgets.find(w => w.name === "aspect_ratio");
if (aspectWidget && aspectWidget.callback) {
aspectWidget.callback();
}
}
});
console.log("PixelForge: Extension registered");