123 lines
3.8 KiB
JavaScript
123 lines
3.8 KiB
JavaScript
// resolution_machine.js
|
|
import { app } from "../../../scripts/app.js";
|
|
|
|
async function fetchConfig() {
|
|
try {
|
|
const resp = await fetch("/sata/resolution_machine/config");
|
|
if (!resp.ok) {
|
|
console.warn("ResolutionMachine: fetch failed", resp.status);
|
|
return null;
|
|
}
|
|
return await resp.json();
|
|
} catch (e) {
|
|
console.warn("ResolutionMachine: fetch exception", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
app.registerExtension({
|
|
name: "SATA_UtilityNode.ResolutionMachine",
|
|
async nodeCreated(node) {
|
|
if (node.comfyClass !== "Resolution_Machine") return;
|
|
|
|
const cfg = await fetchConfig();
|
|
if (!cfg) return;
|
|
|
|
// find widgets
|
|
let modelW = node.widgets.find(w => w.name === "model");
|
|
let resW = node.widgets.find(w => w.name === "resolution");
|
|
let wW = node.widgets.find(w => w.name === "width");
|
|
let hW = node.widgets.find(w => w.name === "height");
|
|
|
|
if (!modelW || !resW || !wW || !hW) {
|
|
console.warn("ResolutionMachine: widgets missing, check INPUT_TYPES");
|
|
return;
|
|
}
|
|
|
|
// --- rebuild widgets as dropdowns to force combo type ---
|
|
const idxModel = node.widgets.indexOf(modelW);
|
|
node.widgets.splice(idxModel, 1);
|
|
modelW = node.addWidget("combo", "model", "None", () => {}, {
|
|
values: cfg.models.map(m => m.model)
|
|
});
|
|
|
|
const idxRes = node.widgets.indexOf(resW);
|
|
node.widgets.splice(idxRes, 1);
|
|
resW = node.addWidget("combo", "resolution", "Custom (manual)", () => {}, {
|
|
values: ["Custom (manual)"]
|
|
});
|
|
|
|
// helper lookups
|
|
function getResNamesForModel(modelName) {
|
|
const m = cfg.models.find(x => x.model === modelName);
|
|
if (!m) return ["Custom (manual)"];
|
|
const names = m.resolutions.map(r => r.name);
|
|
if (!names.includes("Custom (manual)")) names.push("Custom (manual)");
|
|
return names;
|
|
}
|
|
function findResObj(modelName, resName) {
|
|
const m = cfg.models.find(x => x.model === modelName);
|
|
if (!m) return null;
|
|
return m.resolutions.find(r => r.name === resName) || null;
|
|
}
|
|
|
|
let suppressWH = false;
|
|
function programmaticSetWH(wVal, hVal) {
|
|
suppressWH = true;
|
|
wW.value = wVal;
|
|
hW.value = hVal;
|
|
if (wW.inputEl) wW.inputEl.value = wVal;
|
|
if (hW.inputEl) hW.inputEl.value = hVal;
|
|
setTimeout(() => { suppressWH = false; }, 0);
|
|
}
|
|
|
|
// model handler
|
|
modelW.callback = (newModel) => {
|
|
const names = getResNamesForModel(newModel);
|
|
resW.options.values = names;
|
|
if (!names.includes(resW.value)) {
|
|
resW.value = names[0];
|
|
}
|
|
resW.callback(resW.value); // trigger res change
|
|
node.graph?.setDirtyCanvas(true);
|
|
};
|
|
|
|
// resolution handler
|
|
resW.callback = (newRes) => {
|
|
const modelName = modelW.value;
|
|
const resObj = findResObj(modelName, newRes);
|
|
if (resObj && newRes !== "Custom (manual)") {
|
|
programmaticSetWH(resObj.width, resObj.height);
|
|
if (wW.inputEl) wW.inputEl.disabled = true;
|
|
if (hW.inputEl) hW.inputEl.disabled = true;
|
|
} else {
|
|
if (wW.inputEl) wW.inputEl.disabled = false;
|
|
if (hW.inputEl) hW.inputEl.disabled = false;
|
|
}
|
|
node.graph?.setDirtyCanvas(true);
|
|
};
|
|
|
|
// manual WH handler
|
|
function onManualWH() {
|
|
if (suppressWH) return;
|
|
if (resW.value !== "Custom (manual)") {
|
|
const names = getResNamesForModel(modelW.value);
|
|
if (!names.includes("Custom (manual)")) {
|
|
names.push("Custom (manual)");
|
|
resW.options.values = names;
|
|
}
|
|
resW.value = "Custom (manual)";
|
|
resW.callback("Custom (manual)");
|
|
}
|
|
}
|
|
wW.callback = onManualWH;
|
|
hW.callback = onManualWH;
|
|
|
|
// --- initialize ---
|
|
const firstModel = cfg.models[0]?.model;
|
|
if (firstModel) {
|
|
modelW.value = firstModel;
|
|
modelW.callback(firstModel);
|
|
}
|
|
}
|
|
}); |