From 1c330cdb0f463e616fa3d4e108a1205df59e216a Mon Sep 17 00:00:00 2001 From: tritant Date: Thu, 25 Sep 2025 18:15:44 +0200 Subject: [PATCH] add group bypass/mute --- js/orchestratorgroup.js | 102 +++++++++++++++++++++++++++++++++++ js/orchestratorgroupmuter.js | 101 ++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 js/orchestratorgroup.js create mode 100644 js/orchestratorgroupmuter.js diff --git a/js/orchestratorgroup.js b/js/orchestratorgroup.js new file mode 100644 index 0000000..2699497 --- /dev/null +++ b/js/orchestratorgroup.js @@ -0,0 +1,102 @@ +import { app } from "/scripts/app.js"; + +function discoverAndBuildUI(node) { + const existingWidgets = new Set(node.widgets.map(w => w.name)); + let hasChanges = false; + const currentGroupTitles = new Set(app.graph._groups.map(g => g.title)); + const originalWidgetCount = node.widgets.length; + + node.widgets = node.widgets.filter(w => currentGroupTitles.has(w.name)); + if (node.widgets.length !== originalWidgetCount) { + hasChanges = true; + } + + const handleRadioClick = (clickedWidget) => { + if (clickedWidget.value) { + for (const widget of node.widgets) { + if (widget.type === 'toggle' && widget !== clickedWidget) { + widget.value = false; + } + } + } else { + const anyOtherIsEnabled = node.widgets.some(w => w.type === 'toggle' && w.value === true); + if(!anyOtherIsEnabled) { + clickedWidget.value = true; + } + } + for (const widget of node.widgets) { + if (widget.type === 'toggle') { + const group = app.graph._groups.find(g => g.title === widget.name); + if (group) { + const newMode = widget.value ? 0 : 4; + group.recomputeInsideNodes(); + for (const nodeInGroup of group._nodes) { + if (nodeInGroup.mode !== newMode) { + nodeInGroup.mode = newMode; + } + } + } + } + } + app.graph.setDirtyCanvas(true, true); + }; + + for (const group of app.graph._groups) { + if (!existingWidgets.has(group.title)) { + hasChanges = true; + let isInitiallyEnabled = true; + const anyOtherIsEnabled = node.widgets.some(w => w.type === 'toggle' && w.value === true); + if (anyOtherIsEnabled || (group._nodes.length > 0 && group._nodes[0].mode === 4)) { + isInitiallyEnabled = false; + } + node.addWidget("toggle", group.title, isInitiallyEnabled, function (value) { + handleRadioClick(this); + }); + } + } + + const spacerIndex = node.widgets.findIndex(w => w.name === "top_spacer"); + if (spacerIndex !== -1) node.widgets.splice(spacerIndex, 1); + + const toggleExists = node.widgets.some(w => w.type === 'toggle'); + if(toggleExists) { + node.widgets.unshift({ name: "top_spacer", type: "CUSTOM_SPACER", draw: () => {}, computeSize: () => [0, 10] }); + } + + if (hasChanges || (!toggleExists && originalWidgetCount > 0)) { + // --- CORRECTION DU REDIMENSIONNEMENT --- + const currentWidth = node.size[0]; // On mémorise la largeur actuelle + const newComputedSize = node.computeSize(); // On calcule la nouvelle taille nécessaire + node.size = [currentWidth, newComputedSize[1]]; // On applique la nouvelle hauteur mais on garde l'ancienne largeur + + app.graph.setDirtyCanvas(true, true); + } +} + +app.registerExtension({ + name: "Comfy.GroupBypasser.Heartbeat.Radio.Spacer.FixedResize", + + beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "OrchestratorNodeGroupBypasser") { + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + onNodeCreated?.apply(this, arguments); + if (!this.widgets) { + this.widgets = []; + } + this.lastKnownGroupTitles = null; + setTimeout(() => discoverAndBuildUI(this), 100); + }; + + const onDrawBackground = nodeType.prototype.onDrawBackground; + nodeType.prototype.onDrawBackground = function(ctx) { + onDrawBackground?.apply(this, arguments); + const currentGroupTitles = (app.graph._groups?.map(g => g.title) || []).join(); + if (this.lastKnownGroupTitles !== currentGroupTitles) { + this.lastKnownGroupTitles = currentGroupTitles; + discoverAndBuildUI(this); + } + }; + } + }, +}); \ No newline at end of file diff --git a/js/orchestratorgroupmuter.js b/js/orchestratorgroupmuter.js new file mode 100644 index 0000000..508bac1 --- /dev/null +++ b/js/orchestratorgroupmuter.js @@ -0,0 +1,101 @@ +import { app } from "/scripts/app.js"; + +function discoverAndBuildUI(node) { + const existingWidgets = new Set(node.widgets.map(w => w.name)); + let hasChanges = false; + const currentGroupTitles = new Set(app.graph._groups.map(g => g.title)); + const originalWidgetCount = node.widgets.length; + + node.widgets = node.widgets.filter(w => currentGroupTitles.has(w.name)); + if (node.widgets.length !== originalWidgetCount) { + hasChanges = true; + } + + const handleRadioClick = (clickedWidget) => { + if (clickedWidget.value) { + for (const widget of node.widgets) { + if (widget.type === 'toggle' && widget !== clickedWidget) { + widget.value = false; + } + } + } else { + const anyOtherIsEnabled = node.widgets.some(w => w.type === 'toggle' && w.value === true); + if(!anyOtherIsEnabled) { + clickedWidget.value = true; + } + } + for (const widget of node.widgets) { + if (widget.type === 'toggle') { + const group = app.graph._groups.find(g => g.title === widget.name); + if (group) { + const newMode = widget.value ? 0 : 2; + group.recomputeInsideNodes(); + for (const nodeInGroup of group._nodes) { + if (nodeInGroup.mode !== newMode) { + nodeInGroup.mode = newMode; + } + } + } + } + } + app.graph.setDirtyCanvas(true, true); + }; + + for (const group of app.graph._groups) { + if (!existingWidgets.has(group.title)) { + hasChanges = true; + let isInitiallyEnabled = true; + const anyOtherIsEnabled = node.widgets.some(w => w.type === 'toggle' && w.value === true); + if (anyOtherIsEnabled || (group._nodes.length > 0 && group._nodes[0].mode === 2)) { + isInitiallyEnabled = false; + } + node.addWidget("toggle", group.title, isInitiallyEnabled, function (value) { + handleRadioClick(this); + }); + } + } + + const spacerIndex = node.widgets.findIndex(w => w.name === "top_spacer"); + if (spacerIndex !== -1) node.widgets.splice(spacerIndex, 1); + + const toggleExists = node.widgets.some(w => w.type === 'toggle'); + if(toggleExists) { + node.widgets.unshift({ name: "top_spacer", type: "CUSTOM_SPACER", draw: () => {}, computeSize: () => [0, 10] }); + } + + if (hasChanges || (!toggleExists && originalWidgetCount > 0)) { + const currentWidth = node.size[0]; + const newComputedSize = node.computeSize(); + node.size = [currentWidth, newComputedSize[1]]; + + app.graph.setDirtyCanvas(true, true); + } +} + +app.registerExtension({ + name: "Comfy.GroupMuter.Heartbeat.Radio.Spacer.FixedResize", + + beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "OrchestratorNodeGroupMuter") { + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + onNodeCreated?.apply(this, arguments); + if (!this.widgets) { + this.widgets = []; + } + this.lastKnownGroupTitles = null; + setTimeout(() => discoverAndBuildUI(this), 100); + }; + + const onDrawBackground = nodeType.prototype.onDrawBackground; + nodeType.prototype.onDrawBackground = function(ctx) { + onDrawBackground?.apply(this, arguments); + const currentGroupTitles = (app.graph._groups?.map(g => g.title) || []).join(); + if (this.lastKnownGroupTitles !== currentGroupTitles) { + this.lastKnownGroupTitles = currentGroupTitles; + discoverAndBuildUI(this); + } + }; + } + }, +}); \ No newline at end of file