diff --git a/js/ModelParamsNodeExt.js b/js/ModelParamsNodeExt.js index 5f7294a..8946106 100644 --- a/js/ModelParamsNodeExt.js +++ b/js/ModelParamsNodeExt.js @@ -5,11 +5,8 @@ import { app } from "/scripts/app.js"; const TARGET_NODE_TYPE = "ModelParamsPipe"; // Цільовий тип вузла, який ми розширюємо -console.log("%c[ModelParamsNodeExt] JS файл завантажився! (v2-dynamic-inputs)", "color: white; background: #007acc; font-weight: bold; padding: 2px 8px; border-radius: 3px;"); // --- Loading js/ModelParamsNodeExt.js --- v2-dynamic-inputs -console.log(`--- Loading extension for ${TARGET_NODE_TYPE} ---`); - app.registerExtension({ name: "MultiModel.ModelParamsPipeNode.Notifier", @@ -18,11 +15,8 @@ app.registerExtension({ // Додаємо базову ініціалізацію та прямий пошук вузлів async setup() { - console.log(`[${TARGET_NODE_TYPE} Notifier] SETUP starting...`); - // Перевіряємо наявність сервісу одразу if (app.HubNodesService) { - console.log(`[${TARGET_NODE_TYPE} Notifier] HubNodesService found during setup`); } else { console.error(`[${TARGET_NODE_TYPE} Notifier] HubNodesService NOT found during setup!`); } @@ -30,30 +24,23 @@ app.registerExtension({ // Зачекаємо, доки граф буде завантажено, і потім проскануємо його const checkForGraph = () => { if (app.graph) { - console.log(`[${TARGET_NODE_TYPE} Notifier] Graph found in setup`); - // Додаємо обробник зміни графу if (app.graph.onNodeAdded && !app.graph._notifier_attached) { const origNodeAdded = app.graph.onNodeAdded; app.graph.onNodeAdded = function(node) { - console.log(`[${TARGET_NODE_TYPE} Notifier] Graph onNodeAdded called for node ID: ${node.id}, type: ${node.type}`); - if (origNodeAdded) { origNodeAdded.call(this, node); } // Перевіряємо, чи це наш цільовий тип if (node.type === TARGET_NODE_TYPE) { - console.log(`[${TARGET_NODE_TYPE} Notifier] Target node added to graph: ID ${node.id}`); - // Викликаємо наш обробник const extension = app.extensions.find(ext => ext.name === "MultiModel.ModelParamsPipeNode.Notifier"); if (extension) { extension.setupNodeMonitoring(node); if (app.HubNodesService) { - console.log(`[${TARGET_NODE_TYPE} Notifier] Notifying service about new graph node: ID ${node.id}`); app.HubNodesService.notifyHubAdded(node); // Пробуємо різні методи оновлення інтерфейсу @@ -70,22 +57,18 @@ app.registerExtension({ }; app.graph._notifier_attached = true; - console.log(`[${TARGET_NODE_TYPE} Notifier] Attached graph.onNodeAdded handler`); } // Зробимо сканування графу з невеликою затримкою для певності setTimeout(() => { if (!app.graph || !app.graph._nodes) { - console.log(`[${TARGET_NODE_TYPE} Notifier] No graph nodes found yet`); return; } const targetNodes = app.graph._nodes.filter(node => node.type === TARGET_NODE_TYPE); - console.log(`[${TARGET_NODE_TYPE} Notifier] Initial graph scan found ${targetNodes.length} target nodes`); const extension = app.extensions.find(ext => ext.name === "MultiModel.ModelParamsPipeNode.Notifier"); if (!extension) { - console.error(`[${TARGET_NODE_TYPE} Notifier] Extension not found in array!`); return; } @@ -95,14 +78,11 @@ app.registerExtension({ // Якщо знайшли хоча б один вузол, спробуємо оновити інтерфейс if (app.HubNodesService) { - console.log(`[${TARGET_NODE_TYPE} Notifier] Found existing node in scan: ID ${node.id}`); } } // Якщо було знайдено вузли, форсуємо оновлення if (targetNodes.length > 0 && app.HubNodesService) { - console.log(`[${TARGET_NODE_TYPE} Notifier] Forcing update after scan found ${targetNodes.length} nodes`); - if (typeof app.HubNodesService.forceUpdates === 'function') { app.HubNodesService.forceUpdates(); } else if (typeof app.HubNodesService.updateWidgets === 'function') { @@ -113,26 +93,20 @@ app.registerExtension({ } }, 500); } else { - console.log(`[${TARGET_NODE_TYPE} Notifier] Graph not available yet, will retry...`); setTimeout(checkForGraph, 500); } }; // Запускаємо перевірку графу checkForGraph(); - - console.log(`[${TARGET_NODE_TYPE} Notifier] SETUP completed`); }, // Встановлення моніторингу title/видалення для вузла setupNodeMonitoring(node, appInstance = app) { if (!node) return false; - console.log(`[${TARGET_NODE_TYPE} Notifier] Setting up monitoring for node ID: ${node.id}`); // --- Встановлюємо моніторинг title --- if (!node.__title_monitored) { - console.log(`[${TARGET_NODE_TYPE} Notifier] Setting up title monitoring for node ID: ${node.id}`); - try { const originalTitle = node.title; @@ -148,11 +122,8 @@ app.registerExtension({ return this._monitored_title; }, set: function(newTitle) { - console.log(`---> [${TARGET_NODE_TYPE} Notifier] title property CHANGED: "${this._monitored_title}" → "${newTitle}" for node ID: ${this.id}`); - // Якщо значення не змінилось, не виконуємо додаткові дії if (this._monitored_title === newTitle) { - console.log(` Title not changed (same value), skipping notification.`); return; } @@ -162,7 +133,6 @@ app.registerExtension({ // Повідомляємо сервіс про перейменування з невеликою затримкою setTimeout(() => { if (appInstance.HubNodesService) { - console.log(` Notifying service about rename for node ID: ${this.id}`); appInstance.HubNodesService.notifyHubRenamed(this); } else { console.error(` HubNodesService not found! Cannot notify rename.`); @@ -174,7 +144,6 @@ app.registerExtension({ }); node.__title_monitored = true; - console.log(`[${TARGET_NODE_TYPE} Notifier] Title property monitored for node ID: ${node.id}`); } catch (error) { console.error(`[${TARGET_NODE_TYPE} Notifier] Error setting up title monitoring:`, error); } @@ -186,11 +155,8 @@ app.registerExtension({ const originalOnRemoved = node.onRemoved; node.onRemoved = function() { - console.log(`[${TARGET_NODE_TYPE} Notifier] Node removed: ID ${this.id}`); - // Повідомляємо сервіс про видалення if (appInstance.HubNodesService) { - console.log(` Notifying service about removal for node ID: ${this.id}`); appInstance.HubNodesService.notifyHubRemoved(this); } else { console.error(` HubNodesService not found! Cannot notify removal.`); @@ -203,7 +169,6 @@ app.registerExtension({ }; node.onRemoved.__isNotifierOverridden = true; - console.log(`[${TARGET_NODE_TYPE} Notifier] onRemoved overridden for node ID: ${node.id}`); } catch (error) { console.error(`[${TARGET_NODE_TYPE} Notifier] Error overriding onRemoved:`, error); } @@ -214,24 +179,19 @@ app.registerExtension({ // Для логування проблемних випадків async nodeCreated(node) { - console.log(`[${TARGET_NODE_TYPE} Notifier] nodeCreated called for node type: ${node ? node.type : 'undefined'}, ID: ${node ? node.id : 'undefined'}`); }, // Для логування проблемних випадків async onNodeAdded(node) { - console.log(`[${TARGET_NODE_TYPE} Notifier] onNodeAdded called for node type: ${node ? node.type : 'undefined'}, ID: ${node ? node.id : 'undefined'}`); }, // Хук для обробки вузлів, що вже існують при завантаженні async loadedGraphNode(node, appInstance) { if (!node) return; - console.log(`[${TARGET_NODE_TYPE} Notifier] loadedGraphNode called for node type: ${node.type}, ID: ${node.id}`); if (node.type === TARGET_NODE_TYPE) { // Встановлюємо моніторинг для існуючого вузла this.setupNodeMonitoring(node, appInstance); } } -}); - -console.log(`--- Extension for ${TARGET_NODE_TYPE} loaded ---`); \ No newline at end of file +}); \ No newline at end of file diff --git a/js/MultiModelSwitch.js b/js/MultiModelSwitch.js index b579e50..13e2db1 100644 --- a/js/MultiModelSwitch.js +++ b/js/MultiModelSwitch.js @@ -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); + }; + */ }; } }, diff --git a/js/active_model.js b/js/active_model.js index 435a6de..05d1ebf 100644 --- a/js/active_model.js +++ b/js/active_model.js @@ -1,4 +1,3 @@ -console.log("%c[ActiveModel] JS файл завантажився! (v2-dynamic-inputs)", "color: white; background: #007acc; font-weight: bold; padding: 2px 8px; border-radius: 3px;"); // --- Loading js/active_model.js --- v2-dynamic-inputs import { app } from "/scripts/app.js"; // Виправлено шлях на абсолютний @@ -16,7 +15,6 @@ class ActiveModel { constructor() { // Цей вузол є переважно контейнером для дій this.properties = {}; - console.log(`[${ActiveModel.title}] CONSTRUCTOR CALLED.`); // Спробуємо знайти та вивести вузли одразу при створенні this.logTargetNodeNames(); } @@ -27,14 +25,7 @@ class ActiveModel { // Функція для пошуку та логування імен цільових вузлів logTargetNodeNames() { - console.log(`[${ActiveModel.title}] Searching for nodes of type '${TARGET_NODE_TYPE}'...`); const nodes = app.graph._nodes.filter(node => node.type === TARGET_NODE_TYPE); - console.log(`[${ActiveModel.title}] Found ${nodes.length} nodes:`); - if (nodes.length > 0) { - nodes.forEach(n => console.log(` - Node ID: ${n.id}, Title: ${n.title}, Current mode: ${n.mode}`)); - } else { - console.log(` (No nodes found)`); - } return nodes; // Повертаємо для можливого використання в onAction } @@ -42,39 +33,27 @@ class ActiveModel { setHubsMode(mode) { const nodes = this.logTargetNodeNames(); if (nodes.length === 0) { - console.log(`[${ActiveModel.title}] No target nodes found to set mode.`); return; // Виходимо, якщо немає цільових вузлів } const modeStr = mode === MODE_ALWAYS ? "ALWAYS" : (mode === MODE_BYPASS ? "BYPASS" : mode); - console.log(`[${ActiveModel.title}] Attempting to set mode to ${modeStr} for ${nodes.length} nodes.`); let changed = false; for (const node of nodes) { - console.log(` - Processing Node ID: ${node.id}, Title: ${node.title}, Current mode: ${node.mode}`); if (node.mode !== mode) { node.mode = mode; - console.log(` - Mode set to: ${node.mode}`); changed = true; - } else { - console.log(` - Mode already set to ${node.mode}. Skipping.`); } } if (changed) { - console.log(`[${ActiveModel.title}] Triggering canvas redraw.`); app.graph.setDirtyCanvas(true, true); - } else { - console.log(`[${ActiveModel.title}] No modes were changed. Skipping redraw.`); } } // Спрощена обробка дій для тестування onAction(action) { - console.log(`[${ActiveModel.title}] === onAction ENTERED === Action: ${action}`); // Просто логуємо знайдені вузли ще раз при виклику дії this.logTargetNodeNames(); - // Логіку зміни режимів поки що прибрали - // if (action === "Bypass All Hubs") { ... } } // Цей вузол не виконує обчислень, тому onExecute може бути порожнім @@ -92,11 +71,9 @@ class ActiveModel { clazz.size = [240, 50]; clazz.category = "MultiModel"; // Змінюємо категорію на основну - console.log(`[${ActiveModel.title}] Attempting to register node type via setUp: ${clazz.type}`); try { // Реєструємо сам клас LiteGraph.registerNodeType(clazz.type, clazz); - console.log(`[${ActiveModel.title}] Node type registration via setUp SUCCESSFUL.`); } catch (e) { console.error(`[${ActiveModel.title}] Node type registration via setUp FAILED:`, e); } @@ -121,7 +98,6 @@ function setHubMode(targetNode, mode) { if (!targetNode) return; const currentMode = targetNode.mode; const modeStr = mode === MODE_ALWAYS ? "ON" : "OFF"; - console.log(`[${NODE_TITLE}] Setting Node ID ${targetNode.id} ('${targetNode.title}') to mode ${modeStr}`); // Якщо ми вмикаємо вузол (MODE_ALWAYS), і при цьому поточний режим НЕ MODE_ALWAYS // (тобто вузол був вимкнений, а тепер ми його вмикаємо) @@ -131,13 +107,8 @@ function setHubMode(targetNode, mode) { const otherActiveNodes = allHubNodes.filter(n => n.id !== targetNode.id && n.mode === MODE_ALWAYS); if (otherActiveNodes.length > 0) { - console.log(`[${NODE_TITLE}] Found ${otherActiveNodes.length} other active nodes, disabling them...`); otherActiveNodes.forEach(node => { node.mode = MODE_BYPASS; - console.log(`[${NODE_TITLE}] Disabled node ID ${node.id} ('${node.title}')`); - - // Оновлюємо віджети всіх байпасерів для цього вузла - updateAllBypasserWidgets(node); }); } } @@ -146,9 +117,6 @@ function setHubMode(targetNode, mode) { if (currentMode !== mode) { targetNode.mode = mode; app.graph.setDirtyCanvas(true, true); - - // Також оновлюємо віджети для цього вузла - updateAllBypasserWidgets(targetNode); } } @@ -156,7 +124,6 @@ function setHubMode(targetNode, mode) { function updateAllBypasserWidgets(targetNode) { if (!targetNode) return; - console.log(`[${NODE_TITLE}] Updating widgets for node ID: ${targetNode.id} in all bypassers`); const bypassers = HubNodesService.bypasserNodes; bypassers.forEach(bypasser => { @@ -176,13 +143,11 @@ function updateAllBypasserWidgets(targetNode) { let changed = false; if (widget.value !== newValue) { - console.log(`[${NODE_TITLE}] Updating widget value in bypasser ID: ${bypasser.id} for node ID: ${targetNode.id} to: ${newValue}`); widget.value = newValue; changed = true; } if (widget.label !== newLabel) { - console.log(`[${NODE_TITLE}] Updating widget label in bypasser ID: ${bypasser.id} for node ID: ${targetNode.id} to: "${newLabel}"`); widget.label = newLabel; changed = true; } @@ -204,7 +169,6 @@ const HubNodesService = { registerBypasserNode(node) { if (!this.bypasserNodes.find(n => n.id === node.id)) { - console.log(`[HubNodesService] Registering bypasser node ID: ${node.id}`); this.bypasserNodes.push(node); this.scheduleUpdate(`registerBypasser_${node.id}`); } @@ -213,7 +177,6 @@ const HubNodesService = { unregisterBypasserNode(node) { const index = this.bypasserNodes.findIndex(n => n.id === node.id); if (index !== -1) { - console.log(`[HubNodesService] Unregistering bypasser node ID: ${node.id}`); this.bypasserNodes.splice(index, 1); // Оновлення не потрібне при видаленні самого байпасера } else { @@ -228,7 +191,6 @@ const HubNodesService = { // --- Нові методи для сповіщень від Hub --- // notifyHubAdded(node) { if (!node) return; - console.log(`[HubNodesService] Hub node added notification received: ID ${node.id}`); if (!this.hubNodes.find(n => n.id === node.id)) { this.hubNodes.push(node); this.hubNodes.sort((a, b) => a.id - b.id); // Підтримуємо сортування @@ -240,7 +202,6 @@ const HubNodesService = { notifyHubRemoved(node) { if (!node) return; - console.log(`[HubNodesService] Hub node removed notification received: ID ${node.id}`); const index = this.hubNodes.findIndex(n => n.id === node.id); if (index !== -1) { this.hubNodes.splice(index, 1); @@ -252,33 +213,23 @@ const HubNodesService = { notifyHubRenamed(node) { if (!node) return; - console.log(`[HubNodesService] Hub node rename notification received: ID ${node.id}`); - // Сам список hubNodes містить посилання на об'єкти вузлів, - // тому оновлювати список не потрібно, зміна title вже відбулася. - // Просто плануємо оновлення віджетів, щоб відобразити нову назву. this.scheduleUpdate(`notifyHubRenamed_${node.id}`); }, // --- Кінець нових методів --- // scheduleUpdate(reason = "unknown") { - console.log(`[HubNodesService] Scheduling update. Reason: ${reason}`); if (this.updateTimeout) { clearTimeout(this.updateTimeout); } this.updateTimeout = setTimeout(() => { - console.log("[HubNodesService] Timeout reached. Running update..."); this.updateTimeout = null; - // Оновлення списку hubNodes більше не потрібне тут - // this.refreshHubNodes(); this.bypasserNodes.forEach(node => { if (node.refreshWidgets) { - console.log(`[HubNodesService] Refreshing widgets for bypasser node ID: ${node.id}`); node.refreshWidgets(); } else { console.warn(`[HubNodesService] Bypasser node ID: ${node.id} missing refreshWidgets method.`); } }); - console.log("[HubNodesService] Update finished."); }, this.updateDelay); } }; @@ -287,7 +238,6 @@ app.registerExtension({ name: "MultiModel.ActiveModel.ServiceDriven", // Оновлено назву розширення setup(appInstance) { - console.log(`[${NODE_TITLE}] === Extension setup CALLED ===`); // Реєструємо сервіс, щоб він був доступний іншим розширенням appInstance.HubNodesService = HubNodesService; HubNodesService.app = appInstance; @@ -304,8 +254,6 @@ app.registerExtension({ // Перевіряємо, чи це наша нода ActiveModel if (node.type === NODE_TYPE) { - console.log(`[${NODE_TITLE}] Our node type was added to graph: ID ${node.id}`); - // Викликаємо обробку ноди для додавання віджетів const extension = appInstance.extensions.find(ext => ext.name === "MultiModel.ActiveModel.ServiceDriven"); if (extension) { @@ -315,7 +263,6 @@ app.registerExtension({ // Оновлюємо віджети з невеликою затримкою setTimeout(() => { if (node.refreshWidgets) { - console.log(`[${NODE_TITLE}] Running refreshWidgets for newly added node ID: ${node.id}`); node.refreshWidgets(); } }, 100); @@ -324,12 +271,10 @@ app.registerExtension({ }; appInstance.graph._activemodel_onNodeAdded_attached = true; - console.log(`[${NODE_TITLE}] Attached our onNodeAdded handler to graph`); } // Початкове сканування потрібне, щоб знайти вузли, які вже існують при завантаженні setTimeout(() => { - console.log("[HubNodesService] Initial node scan after setup."); // Знаходимо існуючі Hub та Bypasser ноди і реєструємо їх let initialHubsFound = 0; let initialBypassersFound = 0; @@ -347,12 +292,10 @@ app.registerExtension({ this.loadedGraphNode(node, appInstance); } }); - console.log(`[HubNodesService] Initial scan found ${initialHubsFound} hubs and ${initialBypassersFound} bypassers.`); // Додаємо окремий виклик для оновлення віджетів для всіх bypassers з більшою затримкою if (initialBypassersFound > 0) { setTimeout(() => { - console.log(`[${NODE_TITLE}] Refreshing widgets for ${initialBypassersFound} bypassers after initial scan`); HubNodesService.bypasserNodes.forEach(node => { if (node && node.refreshWidgets) { node.refreshWidgets(); @@ -360,24 +303,19 @@ app.registerExtension({ }); }, 500); } - - // Оновлення віджетів запланується всередині notifyHubAdded/registerBypasserNode }, 500); }, // loadedGraphNode тепер відповідає ТІЛЬКИ за конфігурацію САМОГО ActiveModel loadedGraphNode(node, appInstance) { if (node.type === NODE_TYPE) { - console.log(`[${NODE_TITLE}] Configuring node instance ID: ${node.id}`); node.app = appInstance; node.IS_BYPASSER_NODE = true; delete node.onAction; // Видаляємо, бо додамо getActions // Визначаємо refreshWidgets node.refreshWidgets = function() { - console.log(`[${NODE_TITLE} ID: ${this.id}] Running refreshWidgets...`); const targetNodes = findTargetNodes(); // Отримуємо з сервісу - console.log(`[${NODE_TITLE} ID: ${this.id}] Got ${targetNodes.length} target nodes from service.`); // Додаємо детальну діагностику if (targetNodes.length === 0) { @@ -398,7 +336,6 @@ app.registerExtension({ // Add/Update widgets targetNodes.forEach(targetNode => { if (!targetNode) { - console.warn(`[${NODE_TITLE} ID: ${this.id}] Found a null/undefined targetNode in the list from service. Skipping.`); return; // Пропускаємо невалідні ноди } const widgetName = `hub_${targetNode.id}`; @@ -483,12 +420,10 @@ app.registerExtension({ // Перевірка на кількість активних вузлів після оновлення віджетів setTimeout(() => { const activeNodes = targetNodes.filter(node => node.mode === MODE_ALWAYS); - console.log(`[${NODE_TITLE} ID: ${this.id}] After refresh: ${activeNodes.length} active nodes`); // Якщо більше одного активного вузла, залишаємо тільки перший // Але не активуємо автоматично вузли, якщо всі вимкнені if (activeNodes.length > 1) { - console.log(`[${NODE_TITLE} ID: ${this.id}] Multiple active nodes (${activeNodes.length}), keeping only the first one...`); // Залишаємо перший вузол активним, інші вимикаємо for (let i = 1; i < activeNodes.length; i++) { setHubMode(activeNodes[i], MODE_BYPASS); @@ -503,8 +438,6 @@ app.registerExtension({ this.graph.setDirtyCanvas(true, false); } }, 100); - - console.log(`[${NODE_TITLE} ID: ${this.id}] refreshWidgets finished.`); }; // Визначаємо дії для контекстного меню @@ -518,30 +451,19 @@ app.registerExtension({ return actions; }; node.logTargetNodeNames = function() { // Додаємо метод до екземпляра - console.log(`[${NODE_TITLE} ID: ${this.id}] Logging target node names...`); const nodes = HubNodesService.getHubNodes(); - console.log(` Found ${nodes.length} nodes via service:`); - if (nodes.length > 0) { - nodes.forEach(n => console.log(` - Node ID: ${n.id}, Title: ${n.title}, Current mode: ${n.mode}`)); - } else { - console.log(` (No nodes found)`); - } }; // Оновлений метод для встановлення режиму всіх хабів node.setAllHubsMode = function(mode) { - console.log(`[${NODE_TITLE} ID: ${this.id}] setAllHubsMode called with mode: ${mode}`); const hubNodes = HubNodesService.getHubNodes(); if (hubNodes.length === 0) { - console.log(`[${NODE_TITLE} ID: ${this.id}] No hub nodes found to set mode.`); return; } if (mode === MODE_ALWAYS) { // Активуємо тільки перший вузол, інші вимикаємо - console.log(`[${NODE_TITLE} ID: ${this.id}] Enabling only the first hub node, disabling others.`); - hubNodes.forEach((node, index) => { const newMode = index === 0 ? MODE_ALWAYS : MODE_BYPASS; @@ -554,30 +476,22 @@ app.registerExtension({ app.graph.setDirtyCanvas(true, true); } else if (mode === MODE_BYPASS) { // Якщо режим BYPASS, вимикаємо всі вузли - console.log(`[${NODE_TITLE} ID: ${this.id}] Disabling all hub nodes.`); - - let changed = false; hubNodes.forEach(node => { if (node.mode !== MODE_BYPASS) { node.mode = MODE_BYPASS; updateAllBypasserWidgets(node); - changed = true; } }); - if (changed) { - app.graph.setDirtyCanvas(true, true); - } + app.graph.setDirtyCanvas(true, true); } }; // Оновлений метод для перемикання вузлів node.toggleAllHubsMode = function() { - console.log(`[${NODE_TITLE} ID: ${this.id}] toggleAllHubsMode called`); const hubNodes = HubNodesService.getHubNodes(); if (hubNodes.length === 0) { - console.log(`[${NODE_TITLE} ID: ${this.id}] No hub nodes found to toggle.`); return; } @@ -586,7 +500,6 @@ app.registerExtension({ if (activeNodes.length === 0) { // Якщо немає активних вузлів, активуємо перший - console.log(`[${NODE_TITLE} ID: ${this.id}] No active nodes, activating the first one.`); if (hubNodes.length > 0) { const node = hubNodes[0]; node.mode = MODE_ALWAYS; @@ -606,8 +519,6 @@ app.registerExtension({ const nextIndex = (currentIndex + 1) % hubNodes.length; const nextNode = hubNodes[nextIndex]; - console.log(`[${NODE_TITLE} ID: ${this.id}] Toggling from node ID ${activeNode.id} to node ID ${nextNode.id}`); - // Активуємо наступний вузол nextNode.mode = MODE_ALWAYS; updateAllBypasserWidgets(nextNode); @@ -618,7 +529,6 @@ app.registerExtension({ // Реєстрація/видалення самого bypasser'а в сервісі node.onAdded = function() { - console.log(`[${NODE_TITLE} ID: ${this.id}] Bypasser node added to graph. Registering with service.`); if (appInstance.HubNodesService) { // Перевіряємо наявність сервісу appInstance.HubNodesService.registerBypasserNode(this); } else { @@ -626,7 +536,6 @@ app.registerExtension({ } }; node.onRemoved = function() { - console.log(`[${NODE_TITLE} ID: ${this.id}] Bypasser node removed from graph. Unregistering from service.`); if (appInstance.HubNodesService) { appInstance.HubNodesService.unregisterBypasserNode(this); } else { @@ -634,15 +543,6 @@ app.registerExtension({ } }; - // Початкова реєстрація, якщо вузол вже існує при завантаженні - if (appInstance.HubNodesService) { - appInstance.HubNodesService.registerBypasserNode(node); - } else { - // Якщо сервіс ще не створено (малоймовірно, але можливо), - // реєстрація відбудеться пізніше через onAdded - console.warn(`[${NODE_TITLE} ID: ${node.id}] Initial registration deferred, HubNodesService not yet available.`); - } - // Початкове оновлення віджетів для цього конкретного вузла setTimeout(() => { if (node.refreshWidgets) node.refreshWidgets(); }, 50); } @@ -663,21 +563,17 @@ app.registerExtension({ node.pos[0] = visible_rect[0] + visible_rect[2] * 0.5 - node.size[0] * 0.5; node.pos[1] = visible_rect[1] + visible_rect[3] * 0.5 - node.size[1] * 0.5; - console.log(`[${NODE_TITLE}] Node created from menu with ID: ${node.id}`); - // Явно налаштуємо ноду після створення з меню if (app.HubNodesService) { // Отримуємо розширення const extension = app.extensions.find(ext => ext.name === "MultiModel.ActiveModel.ServiceDriven"); if (extension) { // Конфігуруємо ноду - console.log(`[${NODE_TITLE}] Manually configuring node created from menu`); extension.loadedGraphNode(node, app); // Оновлюємо віджети з затримкою setTimeout(() => { if (node.refreshWidgets) { - console.log(`[${NODE_TITLE}] Refreshing widgets for node created from menu`); node.refreshWidgets(); } }, 100); @@ -688,10 +584,8 @@ app.registerExtension({ }, nodeRegistered(type, clazz) { - console.log(`[${NODE_TITLE}] nodeRegistered called for type: ${type}`); if (type === NODE_TYPE) { try { - console.log(`[${NODE_TITLE}] Running additional setup for our node type`); ActiveModel.setUp(clazz); } catch (e) { console.error(`[${NODE_TITLE}] Error in additional node setup:`, e); @@ -701,16 +595,12 @@ app.registerExtension({ // Додаємо обробники створення ноди для максимального покриття nodeCreated(node) { - console.log(`[${NODE_TITLE}] nodeCreated called for node type: ${node?.type || 'undefined'}, ID: ${node?.id || 'undefined'}`); - if (node && node.type === NODE_TYPE) { - console.log(`[${NODE_TITLE}] Our node created, configuring it...`); this.loadedGraphNode(node, app); // Запускаємо оновлення віджетів з затримкою setTimeout(() => { if (node.refreshWidgets) { - console.log(`[${NODE_TITLE}] Refreshing widgets after node creation`); node.refreshWidgets(); } }, 100); @@ -718,16 +608,12 @@ app.registerExtension({ }, onNodeAdded(node) { - console.log(`[${NODE_TITLE}] onNodeAdded callback called for node type: ${node?.type || 'undefined'}, ID: ${node?.id || 'undefined'}`); - if (node && node.type === NODE_TYPE) { - console.log(`[${NODE_TITLE}] Our node added via onNodeAdded, configuring it...`); this.loadedGraphNode(node, app); // Запускаємо оновлення віджетів з затримкою setTimeout(() => { if (node.refreshWidgets) { - console.log(`[${NODE_TITLE}] Refreshing widgets after node was added`); node.refreshWidgets(); } }, 100);