Files
Bjornulf_custom_nodes/web/js/lora_stacks.js
justumen a0bf04c7d6 0.70
2025-02-09 15:44:04 +01:00

110 lines
4.6 KiB
JavaScript

import { app } from "../../../scripts/app.js";
app.registerExtension({
name: "Bjornulf.AllLoraSelector",
async nodeCreated(node) {
if (node.comfyClass === "Bjornulf_AllLoraSelector") {
node.properties = node.properties || {};
const updateLoraInputs = () => {
const initialWidth = node.size[0];
const numLorasWidget = node.widgets.find(w => w.name === "number_of_loras");
if (!numLorasWidget) return;
const numLoras = numLorasWidget.value;
const loraList = node.widgets.find(w => w.name === "lora_1")?.options?.values || [];
// Save existing values
node.widgets.forEach(w => {
if (w.name.startsWith("lora_") || w.name.startsWith("strength_model_") || w.name.startsWith("strength_clip_")) {
node.properties[w.name] = w.value;
}
});
// Remove existing LoRA-related widgets
node.widgets = node.widgets.filter(w =>
!w.name.startsWith("lora_") &&
!w.name.startsWith("strength_model_") &&
!w.name.startsWith("strength_clip_")
);
// Add number_of_loras widget if it doesn't exist
const ensureWidget = (name, type, defaultValue, config) => {
let widget = node.widgets.find(w => w.name === name);
if (!widget) {
widget = node.addWidget(type, name,
node.properties[name] !== undefined ? node.properties[name] : defaultValue,
value => { node.properties[name] = value; },
config
);
}
};
ensureWidget("number_of_loras", "number", 3, { min: 1, max: 20, step: 1 });
// Add LoRA widgets for each slot
for (let i = 1; i <= numLoras; i++) {
const loraName = `lora_${i}`;
const strengthModelName = `strength_model_${i}`;
const strengthClipName = `strength_clip_${i}`;
// Add LoRA selector
node.addWidget("combo", loraName,
node.properties[loraName] || loraList[0],
value => { node.properties[loraName] = value; },
{ values: loraList }
);
// Add strength sliders
node.addWidget("number", strengthModelName,
node.properties[strengthModelName] !== undefined ? node.properties[strengthModelName] : 1.0,
value => { node.properties[strengthModelName] = value; },
{ min: -100.0, max: 100.0, step: 0.01 }
);
node.addWidget("number", strengthClipName,
node.properties[strengthClipName] !== undefined ? node.properties[strengthClipName] : 1.0,
value => { node.properties[strengthClipName] = value; },
{ min: -100.0, max: 100.0, step: 0.01 }
);
}
node.setSize(node.computeSize());
node.size[0] = Math.max(initialWidth, node.size[0]);
};
// Set up number_of_loras widget callback
const numLorasWidget = node.widgets.find(w => w.name === "number_of_loras");
if (numLorasWidget) {
numLorasWidget.callback = () => {
updateLoraInputs();
app.graph.setDirtyCanvas(true);
};
}
// Handle serialization
const originalOnSerialize = node.onSerialize;
node.onSerialize = function(info) {
if (originalOnSerialize) {
originalOnSerialize.call(this, info);
}
info.properties = { ...this.properties };
};
// Handle deserialization
const originalOnConfigure = node.onConfigure;
node.onConfigure = function(info) {
if (originalOnConfigure) {
originalOnConfigure.call(this, info);
}
if (info.properties) {
Object.assign(this.properties, info.properties);
}
updateLoraInputs();
};
// Initial setup
updateLoraInputs();
}
}
});