Files
SatadalAI-SATA_UtilityNode/js/resolution_machine.js
T

165 lines
6.5 KiB
JavaScript

import { app } from "../../../scripts/app.js";
app.registerExtension({
name: "SATA_UtilityNode.Resolution_Machine",
async nodeCreated(node) {
if (node.comfyClass !== "Resolution_Machine" && node.comfyClass !== "Latent_Machine") return;
// Find widgets
const modelWidget = node.widgets.find(w => w.name === "model");
const dimensionWidget = node.widgets.find(w => w.name === "dimension");
const resolutionWidget = node.widgets.find(w => w.name === "resolution");
const widthWidget = node.widgets.find(w => w.name === "width") || node.widgets.find(w => w.name === "custom_width");
const heightWidget = node.widgets.find(w => w.name === "height") || node.widgets.find(w => w.name === "custom_height");
if (!modelWidget || !dimensionWidget || !resolutionWidget || !widthWidget || !heightWidget) {
console.warn("[Resolution_Machine] Missing widgets, check backend definition.");
return;
}
// Store resolution config
let resolutionsConfig = {};
// Fetch resolution config from backend
async function loadConfig() {
try {
const resp = await fetch("/SATA_UtilityNode/resolutions_config");
resolutionsConfig = await resp.json();
} catch (err) {
console.error("[Resolution_Machine] Failed to load config:", err);
}
}
await loadConfig();
// --- Utility: refresh resolution dropdown when model/dimension changes ---
function refreshResolutions() {
const selectedModel = modelWidget.value;
const selectedDimension = dimensionWidget.value;
let available = [];
if (resolutionsConfig.models && resolutionsConfig.models[selectedModel]) {
const buckets = resolutionsConfig.models[selectedModel];
buckets.forEach(bucket => {
// Check if bucket exists and has the selected dimension
if (resolutionsConfig.resolutions && resolutionsConfig.resolutions[bucket] && resolutionsConfig.resolutions[bucket][selectedDimension]) {
available.push(...Object.keys(resolutionsConfig.resolutions[bucket][selectedDimension]));
}
});
}
// Always include "Custom" option so that switching model/dimension dropdowns doesn't kick the user out of custom mode
if (!available.includes("Custom")) {
available.push("Custom");
}
resolutionWidget.options.values = available;
// Pick safe default if current value is not valid
if (!available.includes(resolutionWidget.value)) {
resolutionWidget.value = available[0];
}
// If we switched to a preset (not Custom), lock fields
// If we defaulted to Custom (e.g. empty available), unlock
checkCustomMode();
}
function checkCustomMode() {
if (resolutionWidget.value === "Custom") {
widthWidget.type = "INT";
heightWidget.type = "INT";
delete widthWidget.computeSize;
delete heightWidget.computeSize;
widthWidget.disabled = false;
heightWidget.disabled = false;
} else {
widthWidget.type = "hidden";
heightWidget.type = "hidden";
widthWidget.computeSize = () => [0, -4];
heightWidget.computeSize = () => [0, -4];
applyResolutionPreset();
}
node.setSize(node.computeSize());
app.graph.change();
}
// --- Utility: apply resolution preset to width/height ---
function applyResolutionPreset() {
const selectedModel = modelWidget.value;
const selectedDimension = dimensionWidget.value;
const selectedResolution = resolutionWidget.value;
if (selectedResolution === "Custom") {
return;
}
let resolutionData = null;
// Lookup
if (resolutionsConfig.models && resolutionsConfig.models[selectedModel]) {
const buckets = resolutionsConfig.models[selectedModel];
for (const bucket of buckets) {
if (resolutionsConfig.resolutions[bucket] &&
resolutionsConfig.resolutions[bucket][selectedDimension] &&
resolutionsConfig.resolutions[bucket][selectedDimension][selectedResolution]) {
resolutionData = resolutionsConfig.resolutions[bucket][selectedDimension][selectedResolution];
break;
}
}
}
if (resolutionData) {
widthWidget.value = resolutionData.width;
heightWidget.value = resolutionData.height;
}
}
// --- Hook model change ---
const oldModelCallback = modelWidget.callback;
modelWidget.callback = function (value) {
if (oldModelCallback) oldModelCallback(value);
refreshResolutions();
};
// --- Hook dimension change ---
const oldDimensionCallback = dimensionWidget.callback;
dimensionWidget.callback = function (value) {
if (oldDimensionCallback) oldDimensionCallback(value);
refreshResolutions();
};
// --- Hook resolution change ---
const oldResolutionCallback = resolutionWidget.callback;
resolutionWidget.callback = function (value) {
if (oldResolutionCallback) oldResolutionCallback(value);
checkCustomMode();
};
// --- Add Custom Button ---
// Rename "Swap Dimensions" -> "Custom"
// Note: Node logic adds this button. Previous JS added it. We are replacing previous JS logic.
node.addWidget("button", "Custom", null, () => {
// Unlock widgets
widthWidget.disabled = false;
heightWidget.disabled = false;
// Ensure "Custom" option exists and is selected
if (!resolutionWidget.options.values.includes("Custom")) {
resolutionWidget.options.values.push("Custom");
}
resolutionWidget.value = "Custom";
checkCustomMode();
app.graph.change();
});
// --- Initial sync ---
refreshResolutions();
}
});