Add files via upload
This commit is contained in:
+174
-66
@@ -27,100 +27,208 @@ app.registerExtension({
|
||||
onNodeCreated?.apply(this, arguments);
|
||||
console.log(`[MultiModel] ${nodeClassName} created`);
|
||||
|
||||
// Find widgets (should exist based on Python definition)
|
||||
// --- Віджети ---
|
||||
const modeWidget = this.widgets.find(w => w.name === "mode");
|
||||
const indexWidget = this.widgets.find(w => w.name === "index");
|
||||
|
||||
if (!modeWidget) {
|
||||
console.error(`[MultiModel] ${nodeClassName}: 'mode' widget not found! Cannot apply dynamic visibility.`);
|
||||
return;
|
||||
}
|
||||
if (!indexWidget) {
|
||||
console.error(`[MultiModel] ${nodeClassName}: 'index' widget not found! Cannot apply dynamic visibility.`);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
// Function to update index widget visibility
|
||||
const updateVisibility = (modeValue) => {
|
||||
if (indexWidget) {
|
||||
const shouldBeHidden = (modeValue !== "index"); // Поле повинно бути приховане, якщо режим НЕ "index"
|
||||
// Завжди встановлюємо правильний стан `hidden`
|
||||
const shouldBeHidden = (modeValue !== "index");
|
||||
indexWidget.hidden = shouldBeHidden;
|
||||
console.log(`[MultiModel] ${nodeClassName}: Setting index widget hidden to: ${indexWidget.hidden} (mode is ${modeValue})`);
|
||||
// Запитуємо перемалювання, щоб зміни відобразились
|
||||
app.graph.setDirtyCanvas(true, false);
|
||||
// Можливо, знадобиться примусове оновлення розміру, якщо ComfyUI не робить це автоматично при зміні hidden
|
||||
// this.computeSize();
|
||||
}
|
||||
};
|
||||
|
||||
// Store original callback and wrap it
|
||||
const originalModeCallback = modeWidget.callback;
|
||||
modeWidget.callback = (value) => {
|
||||
console.log(`[MultiModel] ${nodeClassName}: Mode widget callback triggered with value: ${value}`);
|
||||
// Викликаємо оригінальний callback, якщо він існує
|
||||
originalModeCallback?.apply(modeWidget, [value]);
|
||||
updateVisibility(value);
|
||||
};
|
||||
|
||||
// Set initial visibility based on the current mode value
|
||||
// Викликаємо відразу після ініціалізації віджетів
|
||||
console.log(`[MultiModel] ${nodeClassName}: Setting initial visibility for mode: ${modeWidget.value}`);
|
||||
updateVisibility(modeWidget.value);
|
||||
|
||||
// --- Keep dynamic input logic ---
|
||||
// We might want this active even in 'index' mode if the user wants
|
||||
// to visually see which inputs are available, though they aren't used
|
||||
// for selection in that mode.
|
||||
this.updateInputs(); // Initial call to potentially add the first input
|
||||
};
|
||||
|
||||
// --- Dynamic input logic (kept mostly as is) ---
|
||||
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
|
||||
nodeType.prototype.onConnectionsChange = function(type, index, connected, link_info, slot) {
|
||||
onConnectionsChange?.apply(this, arguments);
|
||||
this.scheduleUpdateInputs();
|
||||
};
|
||||
|
||||
nodeType.prototype.scheduleUpdateInputs = debounce(function() {
|
||||
this.updateInputs();
|
||||
}, 100);
|
||||
|
||||
nodeType.prototype.updateInputs = function() {
|
||||
const prefix = "input_";
|
||||
const minInputs = 1;
|
||||
|
||||
let lastConnectedIndex = -1;
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
if (this.inputs[i].name.startsWith(prefix) && this.inputs[i].link != null) {
|
||||
lastConnectedIndex = i;
|
||||
}
|
||||
// --- Динамічні входи (last_empty, last_connected) ---
|
||||
this._input_prefix = "input_";
|
||||
const prefix = this._input_prefix;
|
||||
this._last_input_index = 1;
|
||||
this.last_empty = 0;
|
||||
this.last_connected = null;
|
||||
// Якщо входів немає або немає input_1 — додаємо перший вхід
|
||||
let hasInput1 = false;
|
||||
if (this.inputs && this.inputs.length > 0) {
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
if (this.inputs[i].name === `${prefix}1`) {
|
||||
hasInput1 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasInput1) {
|
||||
this.addInput(`${prefix}1`, "*");
|
||||
}
|
||||
// Оновлюємо індекси для існуючих входів
|
||||
if (this.inputs && this.inputs.length > 0) {
|
||||
let maxIdx = 1;
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
const inp = this.inputs[i];
|
||||
if (inp.name && inp.name.startsWith(prefix)) {
|
||||
const idx = parseInt(inp.name.replace(prefix, ""), 10);
|
||||
if (!isNaN(idx) && idx > maxIdx) maxIdx = idx;
|
||||
if (inp.link != null) this.last_connected = i;
|
||||
}
|
||||
}
|
||||
this._last_input_index = maxIdx;
|
||||
this.last_empty = this.inputs.length - 1;
|
||||
}
|
||||
// --- Зберігаємо попередній стан links ---
|
||||
this._prevLinks = [];
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
this._prevLinks[i] = this.inputs[i].link;
|
||||
}
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
// this.updateInputs(); // закоментовано, бо ця функція більше не використовується
|
||||
|
||||
let removalIndex = this.inputs.length - 1;
|
||||
while (removalIndex > lastConnectedIndex && this.inputs.length > minInputs && removalIndex >= 0) {
|
||||
if (this.inputs[removalIndex].name.startsWith(prefix) && this.inputs[removalIndex].link == null) {
|
||||
if(this.inputs.length > minInputs) {
|
||||
console.log(`[MultiModel] Removing input ${this.inputs[removalIndex].name}`);
|
||||
this.removeInput(removalIndex);
|
||||
// --- Динамічна логіка підключень (last_empty, last_connected) ---
|
||||
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
|
||||
nodeType.prototype.onConnectionsChange = function(type, index, connected, link_info, slot) {
|
||||
onConnectionsChange?.apply(this, arguments);
|
||||
if (this._updatingInputs) return;
|
||||
if (type !== 1) return;
|
||||
const prefix = this._input_prefix || "input_";
|
||||
const wasLinked = this._prevLinks && this._prevLinks[index];
|
||||
const isLinked = this.inputs[index] && this.inputs[index].link;
|
||||
// Додаємо новий вхід тільки якщо було null, а стало не null
|
||||
if (
|
||||
connected &&
|
||||
index === this.last_empty &&
|
||||
wasLinked == null &&
|
||||
isLinked != null
|
||||
) {
|
||||
this._updatingInputs = true;
|
||||
// --- Коректна нумерація ---
|
||||
let maxIdx = 0;
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
const inp = this.inputs[i];
|
||||
if (inp.name && inp.name.startsWith(prefix)) {
|
||||
const idx = parseInt(inp.name.replace(prefix, ""), 10);
|
||||
if (!isNaN(idx) && idx > maxIdx) maxIdx = idx;
|
||||
}
|
||||
}
|
||||
this._last_input_index = maxIdx + 1;
|
||||
this.addInput(`${prefix}${this._last_input_index}`, "*");
|
||||
this.last_connected = this.last_empty;
|
||||
this.last_empty = this.inputs.length - 1;
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
this._updatingInputs = false;
|
||||
}
|
||||
// Якщо відключили будь-який вхід
|
||||
if (!connected) {
|
||||
// Знайти новий last_connected
|
||||
let new_last_connected = null;
|
||||
for (let i = this.inputs.length - 1; i >= 0; i--) {
|
||||
if (this.inputs[i].name.startsWith(prefix) && this.inputs[i].link != null) {
|
||||
new_last_connected = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Видалити всі порожні входи після last_connected, але залишити один (last_empty)
|
||||
let removed = false;
|
||||
for (let i = this.inputs.length - 1; i > new_last_connected + 1; i--) {
|
||||
if (this.inputs[i].name.startsWith(prefix) && this.inputs[i].link == null) {
|
||||
this.removeInput(i);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
this.last_connected = new_last_connected;
|
||||
this.last_empty = this.inputs.length - 1;
|
||||
// Якщо останній вхід зайнятий, додаємо ще один порожній
|
||||
if (
|
||||
this.inputs.length === 0 ||
|
||||
(this.inputs[this.inputs.length - 1].name.startsWith(prefix) && this.inputs[this.inputs.length - 1].link != null)
|
||||
) {
|
||||
// --- Коректна нумерація ---
|
||||
let maxIdx = 0;
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
const inp = this.inputs[i];
|
||||
if (inp.name && inp.name.startsWith(prefix)) {
|
||||
const idx = parseInt(inp.name.replace(prefix, ""), 10);
|
||||
if (!isNaN(idx) && idx > maxIdx) maxIdx = idx;
|
||||
}
|
||||
}
|
||||
this._last_input_index = maxIdx + 1;
|
||||
this.addInput(`${prefix}${this._last_input_index}`, "*");
|
||||
this.last_empty = this.inputs.length - 1;
|
||||
removed = true;
|
||||
}
|
||||
if (removed) {
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
}
|
||||
}
|
||||
// --- Оновлюємо _prevLinks після всіх змін ---
|
||||
this._prevLinks = [];
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
this._prevLinks[i] = this.inputs[i].link;
|
||||
}
|
||||
};
|
||||
// --- Закоментовано стару логіку ---
|
||||
/*
|
||||
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
|
||||
nodeType.prototype.onConnectionsChange = function(type, index, connected, link_info, slot) {
|
||||
onConnectionsChange?.apply(this, arguments);
|
||||
this.scheduleUpdateInputs();
|
||||
};
|
||||
nodeType.prototype.scheduleUpdateInputs = debounce(function() {
|
||||
this.updateInputs();
|
||||
}, 100);
|
||||
nodeType.prototype.updateInputs = function() {
|
||||
const prefix = "input_";
|
||||
const minInputs = 1;
|
||||
// --- Гарантуємо перший слот ---
|
||||
const dynamicInputs = this.inputs.filter(inp => inp.name && inp.name.startsWith(prefix));
|
||||
if (dynamicInputs.length === 0) {
|
||||
const name = `${prefix}1`;
|
||||
this.addInput(name, "*");
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
return;
|
||||
}
|
||||
let lastConnectedIndex = -1;
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
if (this.inputs[i].name.startsWith(prefix) && this.inputs[i].link != null) {
|
||||
lastConnectedIndex = i;
|
||||
}
|
||||
}
|
||||
let removalIndex = this.inputs.length - 1;
|
||||
while (removalIndex > lastConnectedIndex && this.inputs.length > minInputs && removalIndex >= 0) {
|
||||
if (this.inputs[removalIndex].name.startsWith(prefix) && this.inputs[removalIndex].link == null) {
|
||||
if(this.inputs.length > minInputs) {
|
||||
this.removeInput(removalIndex);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
removalIndex--;
|
||||
}
|
||||
removalIndex--;
|
||||
}
|
||||
|
||||
// Add a new input if the last one is connected OR if there are no inputs yet
|
||||
if (this.inputs.length === 0 || (this.inputs[this.inputs.length - 1].name.startsWith(prefix) && this.inputs[this.inputs.length - 1].link != null)) {
|
||||
const nextIndex = this.inputs.length + 1; // 1-based index for name
|
||||
const name = `${prefix}${nextIndex}`;
|
||||
console.log(`[MultiModel] Adding input ${name}`);
|
||||
this.addInput(name, "*");
|
||||
}
|
||||
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
// Add a new input if the last one is connected OR if there are no inputs yet
|
||||
if (dynamicInputs.length > 0 && this.inputs[this.inputs.length - 1].name.startsWith(prefix) && this.inputs[this.inputs.length - 1].link != null) {
|
||||
// Знаходимо найбільший індекс серед динамічних входів
|
||||
const dynamicIndexes = dynamicInputs
|
||||
.map(inp => parseInt(inp.name.replace(prefix, ""), 10))
|
||||
.filter(num => !isNaN(num));
|
||||
const maxIndex = dynamicIndexes.length > 0 ? Math.max(...dynamicIndexes) : 0;
|
||||
const nextIndex = maxIndex + 1;
|
||||
const name = `${prefix}${nextIndex}`;
|
||||
this.addInput(name, "*");
|
||||
}
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
};
|
||||
*/
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user