From 3e8e59f20ff332fddca4e99a3a11abb4e11ef077 Mon Sep 17 00:00:00 2001 From: Oratorian Date: Tue, 2 Jun 2026 21:49:13 +0200 Subject: [PATCH] Add files via upload --- README.md | 145 +++++++++++ __init__.py | 16 ++ assets/GroupController.png | Bin 0 -> 38834 bytes assets/NodeController.png | Bin 0 -> 35938 bytes js/switchboard.js | 497 +++++++++++++++++++++++++++++++++++++ pyproject.toml | 13 + 6 files changed, 671 insertions(+) create mode 100644 README.md create mode 100644 __init__.py create mode 100644 assets/GroupController.png create mode 100644 assets/NodeController.png create mode 100644 js/switchboard.js create mode 100644 pyproject.toml diff --git a/README.md b/README.md new file mode 100644 index 0000000..cc4d20f --- /dev/null +++ b/README.md @@ -0,0 +1,145 @@ +# 🎛️ Switchboard - Advanced Group/Node Controllers for ComfyUI + +Client-side nodes for enabling/disabling parts of your graph - by hand or from a +wired boolean. A more flexible take on rgthree's *Fast Group Bypasser*. Two +nodes, identical behaviour, different target: + +| Node | Targets | Add list shows | +|------|---------|----------------| +| **Group Controller** | groups, by **title** | the group titles in your graph | +| **Node Controller** | individual nodes, by **id** | nodes as `id: Title` | + +## Install + +Copy this folder into `ComfyUI/custom_nodes/` (final path +`ComfyUI/custom_nodes/comfyui-switchboard/`) and restart ComfyUI, then hard-reload +the browser (Ctrl/Cmd+Shift+R). There are no Python dependencies - these are pure +front-end JavaScript nodes that never run on the server. In the Add-Node menu the +nodes live under the **🎛️ Switchboard** category. + +--- + +## Group Controller + +![Group Controller - a Boolean (true) wired into the "Test" group input keeps the Test group enabled; disable mode is mute](assets/GroupController.png) + +Above: a **Boolean** node (`value = true`) is wired into the controller's **`Test`** +input. The controller drives the **`Test`** group on the right (a Save Image +node). Because the boolean is `true`, the group is **enabled**; if it were +`false`, the group would be **muted** (its `↳ disable as` setting). + +## Node Controller + +![Node Controller - ALL is disabled, but node "8: VAE Decode" stays enabled because a Boolean (true) is wired to it, overriding the master ALL toggle](assets/NodeController.png) + +Above: the **`ALL`** master toggle is set to **disabled**, yet node **`8: VAE +Decode`** is still **enabled** - because a **Boolean** (`true`) is wired to it. +**A connected boolean overrides the `ALL` broadcast.** This is the key behaviour, +described in full below. + +--- + +## Anatomy of the node + +From top to bottom, a controller shows: + +1. **Input sockets (top of the node).** One `BOOLEAN` socket per controlled + target, labelled with the target (the group title, or `id: Title` for nodes). + Wiring is **optional** - see [Boolean inputs](#boolean-inputs). *(Under Nodes + 2.0 the sockets render at the very top of the node, slightly detached from + their matching toggle row - that's a renderer quirk, not a bug.)* +2. **`ALL`** - the **master broadcast** toggle. Flips every *manually-controlled* + target on/off at once (see precedence below). +3. **One row pair per target:** + - **`` toggle** - `enabled` / `disabled` for that target. This is what + a wired boolean drives. + - **`↳ disable as`** - `bypass` or `mute`, i.e. *how* that target turns off. + This stays editable at all times, even while a boolean holds the target on. +4. **`add`** - the **➕ Add group…/node…** dropdown. Pick a target to start + controlling it. Lists only targets not already controlled. +5. **`remove`** - the **➖ Remove group…/node…** dropdown. Drops a target and + **re-enables** it (so removing the controller never strands something + disabled). The right-click menu also has **Remove controlled …** and + **Refresh … list**. + +### What `bypass` vs `mute` do + +- **`bypass`** - the target's nodes are bypassed; data routes *around* them and + the graph still runs. +- **`mute`** - the target's nodes (and everything downstream of them) are muted + and don't execute at all. + +--- + +## Boolean inputs + +Every controlled target has its own `BOOLEAN` input socket. Wiring one is +**optional**. + +- **Not wired** → the target is controlled **manually**: its own toggle and the + `ALL` master toggle. +- **Wired** → the boolean **governs** that target. `True` = `enabled`, + `False` = `disabled` (turned off using that target's `↳ disable as` mode). + +### Precedence - a connected boolean wins + +Once a boolean is connected to a target, **it is authoritative for that target's +on/off state and overrides everything else:** + +| Action | Target with **no** boolean wired | Target **with** a boolean wired | +|--------|----------------------------------|---------------------------------| +| Click the target's toggle | changes it | reverts to the boolean's value | +| Flip the `ALL` master toggle | changes it | **ignored** - boolean still governs | +| Change `↳ disable as` | takes effect | takes effect (controls *how* it disables) | + +This is exactly the **Node Controller** screenshot above: `ALL` is `disabled`, +but `8: VAE Decode` stays `enabled` because its boolean is `true`. Flipping `ALL` +does not touch boolean-governed targets - they only follow their input. + +The boolean updates the target **live** as you flip the upstream value, and is +re-read once more **at queue time**, so the prompt that actually runs always +matches the inputs. + +### What the boolean reads (and its one limitation) + +Enabling/disabling a target changes the **mode** of the underlying node(s) - a +graph operation that happens **before** a prompt is queued. So the controller +reads the upstream boolean's value **in the browser**, by following the wire to +the source node's widget. + +- ✅ Works great for **constant** Boolean/primitive nodes (a `True`/`False` you + set in the UI). +- ❌ Does **not** track a boolean that is *computed at runtime* by another node - + that value doesn't exist until execution, by which point the target's on/off + state is already locked for that run. For runtime-computed gating you'd need a + backend execution-blocking node instead (open an issue if you want that). + +--- + +## Notes + +- **Node Controller targets by id.** Nodes are matched by their stable id, so + retitling a controlled node still works; the `id: Title` label is captured when + you add it. Controllers can't target other controllers. +- **Survives save/load.** All state lives in node properties and is re-applied at + queue time. Older saved Group Controllers are auto-migrated to the current + format. + +## Nodes 2.0 compatibility + +These are client-side (virtual) nodes built on the legacy LiteGraph API - the +same class of node as rgthree's group tools. ComfyUI's **Nodes 2.0** (Vue +renderer) is currently opt-in and keeps a compatibility layer, so these load and +function there (toggles, booleans and queue-time apply all work). Caveats: + +- The **core action** (setting nodes to active/bypass/mute) is graph data, not + rendering - it works regardless of renderer. +- The **UI** uses legacy patterns (virtual node, dynamic widgets/inputs, context + menu) that 2.0 may render inconsistently - e.g. input sockets float to the top + of the node, and links to dynamically-added sockets may draw as straight lines + instead of curves. These are cosmetic. Canvas-draw hooks are deliberately + avoided (a timer replaces `onDrawForeground`) so live input tracking keeps + working. + +A Vue/V3-native rewrite would be the longer-term fix once those APIs are +documented. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..9489bad --- /dev/null +++ b/__init__.py @@ -0,0 +1,16 @@ +"""Switchboard - advanced group/node enable/disable controllers for ComfyUI. + +The actual nodes (Group Controller, Node Controller) are client-side ("virtual") +LiteGraph nodes implemented in ``js/switchboard.js``. They never execute on the +server, so there are no Python node classes here -- we only need to expose the +web directory so ComfyUI serves the JavaScript extension. +""" + +# No server-side nodes: everything happens in the browser graph. +NODE_CLASS_MAPPINGS = {} +NODE_DISPLAY_NAME_MAPPINGS = {} + +# Tell ComfyUI where to find the front-end extension(s). +WEB_DIRECTORY = "./js" + +__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"] diff --git a/assets/GroupController.png b/assets/GroupController.png new file mode 100644 index 0000000000000000000000000000000000000000..7fb3a8d2076e4776fa3c742cc16658871a48bc4e GIT binary patch literal 38834 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 literal 0 HcmV?d00001 diff --git a/js/switchboard.js b/js/switchboard.js new file mode 100644 index 0000000..87bfbb9 --- /dev/null +++ b/js/switchboard.js @@ -0,0 +1,497 @@ +import { app } from "../../scripts/app.js"; + +/** + * Switchboard - Group / Node Controllers + * --------------------------------------- + * Client-side ("virtual") nodes, in the spirit of rgthree's Fast Group Bypasser + * but more flexible. Two node types share one base: + * + * - Group Controller -- targets are GROUPS (by title). + * - Node Controller -- targets are individual NODES (by id). + * + * For each target you get an on/off toggle (drivable by a wired BOOLEAN input) + * plus an independent "disable as" bypass/mute selector, a master broadcast + * toggle, and add/remove dropdowns. + * + * Enabling/disabling a target just changes the *mode* of the underlying node(s) + * -- a pure graph operation, applied immediately on change and again at queue + * time via applyToGraph() so the prompt that runs matches what you see. + */ + +// LiteGraph node modes. +const MODE_ALWAYS = 0; // active / enabled +const MODE_NEVER = 2; // muted +const MODE_BYPASS = 4; // bypassed (route around) + +const CATEGORY = "🎛️ Switchboard"; +const DISABLE_MODES = ["bypass", "mute"]; +// Recognised values from an older single tri-state shape, kept for migration. +const GROUP_STATES = ["enabled", "bypass", "mute"]; +const MODE_WIDGET_LABEL = "↳ disable as"; + +/** Resolve a control's LiteGraph node mode from its enabled flag + disable mode. */ +function controlToMode(control) { + if (control.enabled) return MODE_ALWAYS; + return control.disableMode === "mute" ? MODE_NEVER : MODE_BYPASS; +} + +// ---- group targets --------------------------------------------------------- + +function getGraphGroups() { + const graph = app.graph; + if (!graph) return []; + return graph._groups || graph.groups || []; +} + +/** All group titles currently in the graph, de-duplicated, as {key,label}. */ +function getGroupChoices() { + const seen = new Set(); + const choices = []; + for (const group of getGraphGroups()) { + if (group.title && !seen.has(group.title)) { + seen.add(group.title); + choices.push({ key: group.title, label: group.title }); + } + } + return choices; +} + +/** Set the mode of every node inside groups whose title matches `key`. */ +function applyModeToGroup(key, mode) { + for (const group of getGraphGroups()) { + if (group.title !== key) continue; + // Make sure the group knows which nodes are inside its bounds. + if (typeof group.recomputeInsideNodes === "function") { + group.recomputeInsideNodes(); + } + const nodes = group._nodes || group.nodes || []; + for (const node of nodes) node.mode = mode; + } +} + +// ---- node targets ---------------------------------------------------------- + +function getGraphNodes() { + const graph = app.graph; + if (!graph) return []; + return graph._nodes || graph.nodes || []; +} + +/** Every targetable node as {key:id, label:"id: Title"}, excluding `self` and + * any of our own controller nodes (you can't control a controller). */ +function getNodeChoices(self) { + const choices = []; + for (const node of getGraphNodes()) { + if (node === self) continue; + if (node.constructor && node.constructor.isSwitchboardController) continue; + const name = node.title || node.type || "node"; + choices.push({ key: String(node.id), label: `${node.id}: ${name}` }); + } + return choices; +} + +/** Set the mode of the node whose id matches `key`. Handles both numeric ids + * (classic graphs) and string ids (e.g. subgraph nodes under Nodes 2.0). */ +function applyModeToNode(key, mode) { + const graph = app.graph; + if (!graph || !graph.getNodeById) return; + let node = graph.getNodeById(key); + if (!node && /^\d+$/.test(key)) node = graph.getNodeById(Number(key)); + if (node) node.mode = mode; +} + +/** + * Shared base. Subclasses provide three things via static/overridable members: + * - static targetWord ("group" | "node") for placeholder text + * - _allChoices() -> [{key,label}] of everything targetable right now + * - _applyTo(key, mode) applies a LiteGraph mode to that target + */ +class BaseControllerNode extends LGraphNode { + constructor(title) { + super(title); + + // Virtual: never sent to the server as an executable node. + this.isVirtualNode = true; + // All state lives in `this.properties` (serialized automatically). Widgets + // are rebuilt from properties on load, so don't also persist widget values. + this.serialize_widgets = false; + + if (!this.properties) this.properties = {}; + // controls: array of { key, label, enabled: bool, disableMode: bypass|mute } + if (!this.properties.controls) this.properties.controls = []; + this._normalizeControls(); + + this.size = [260, 120]; + this._buildWidgets(); + } + + get _addPlaceholder() { + return `➕ Add ${this.constructor.targetWord}…`; + } + + get _removePlaceholder() { + return `➖ Remove ${this.constructor.targetWord}…`; + } + + // ---- overridable target hooks (defaults are inert) ----------------------- + + _allChoices() { + return []; + } + + _applyTo(_key, _mode) {} + + // ---- migration / setup --------------------------------------------------- + + /** Backfill defaults and migrate older shapes so saved workflows keep working. + * Target shape: { key, label, enabled, disableMode }. */ + _normalizeControls() { + for (const c of this.properties.controls) { + // Old Group Controller shape used `title` for both key and label. + if (c.key == null && c.title != null) c.key = c.title; + if (c.label == null) c.label = c.title != null ? c.title : c.key; + if (!DISABLE_MODES.includes(c.disableMode)) c.disableMode = "bypass"; + if (typeof c.enabled !== "boolean") { + // Migrate from the single tri-state { state } shape. + if (GROUP_STATES.includes(c.state)) { + c.enabled = c.state === "enabled"; + if (c.state !== "enabled") c.disableMode = c.state; + } else { + c.enabled = true; + } + } + delete c.state; + delete c.title; + } + } + + _availableChoices() { + const used = new Set(this.properties.controls.map((c) => c.key)); + return this._allChoices().filter((choice) => !used.has(choice.key)); + } + + // ---- widget construction ------------------------------------------------- + + _buildWidgets() { + this.widgets = []; + + // 1) Master broadcast: clicking it forces every target on/off. It does NOT + // track individual or boolean-driven changes -- it's an action switch. + // When disabling, each target uses its own bypass/mute mode. + this.addWidget( + "toggle", + "ALL", + this._allEnabled(), + (value) => { + for (const control of this.properties.controls) { + // A connected boolean governs its target -- the master broadcast (and + // manual toggling) is overridden by it, so skip those here. + if (this._hasBooleanInput(control)) continue; + control.enabled = value; + } + this._syncToggles(); + this.applyAll(); + }, + { on: "enabled", off: "disabled" }, + ); + + // 2) Per target: on/off toggle (boolean-driven) + independent "disable as". + for (const control of this.properties.controls) { + this._addControlWidgets(control); + } + + // 3) "Add" combo -- lists targets not yet controlled. + this.addWidget( + "combo", + "add", + this._addPlaceholder, + (value) => { + const choice = this._availableChoices().find((c) => c.label === value); + if (choice) this.addTarget(choice.key, choice.label); + }, + { values: () => [this._addPlaceholder, ...this._availableChoices().map((c) => c.label)] }, + ); + + // 4) "Remove" combo -- only when there's something to remove. + if (this.properties.controls.length) { + this.addWidget( + "combo", + "remove", + this._removePlaceholder, + (value) => { + const control = this.properties.controls.find((c) => c.label === value); + if (control) this.removeTarget(control.key); + }, + { values: () => [this._removePlaceholder, ...this.properties.controls.map((c) => c.label)] }, + ); + } + + this._refreshAddWidget(); + this._syncInputs(); + this.setDirtyCanvas(true, true); + } + + _addControlWidgets(control) { + // On/off toggle -- this is what a wired BOOLEAN input drives. + const toggle = this.addWidget( + "toggle", + control.label, + control.enabled, + (value) => { + control.enabled = value; + this.applyControl(control); + }, + { on: "enabled", off: "disabled" }, + ); + toggle._controlKey = control.key; + + // Independent "disable as" selector -- stays editable even while a boolean + // holds the target enabled, so you can pre-set bypass vs mute per target. + this.addWidget( + "combo", + MODE_WIDGET_LABEL, + control.disableMode, + (value) => { + control.disableMode = value; + this.applyControl(control); // re-applies immediately if currently disabled + }, + { values: DISABLE_MODES }, + ); + } + + // ---- helpers ------------------------------------------------------------- + + _allEnabled() { + const controls = this.properties.controls; + return controls.length > 0 && controls.every((c) => c.enabled); + } + + _syncToggles() { + // Only the on/off toggles mirror state; the "disable as" combos are + // user-owned and never driven by inputs, so they're left alone. + for (const control of this.properties.controls) { + const widget = this.widgets?.find((w) => w._controlKey === control.key); + if (widget) widget.value = control.enabled; + } + } + + _refreshAddWidget() { + const addWidget = this.widgets?.find((w) => w.name === "add"); + if (addWidget) addWidget.value = this._addPlaceholder; + } + + // ---- boolean inputs ------------------------------------------------------ + + /** Ensure exactly one BOOLEAN input per control, matched by label. Reconciles + * by name so existing slots (and their links) survive reload. */ + _syncInputs() { + const wanted = this.properties.controls.map((c) => c.label); + for (let i = (this.inputs?.length || 0) - 1; i >= 0; i--) { + if (!wanted.includes(this.inputs[i].name)) this.removeInput(i); + } + for (const label of wanted) { + if (this.findInputSlot(label) === -1) this.addInput(label, "BOOLEAN"); + } + } + + /** Read the boolean coming into `slot` from the connected upstream node. + * Returns true/false, or null if nothing usable is connected. */ + _readBooleanInput(slot) { + const input = this.inputs?.[slot]; + if (!input || input.link == null) return null; + const link = app.graph.links[input.link]; + if (!link) return null; + const origin = app.graph.getNodeById(link.origin_id); + if (!origin) return null; + // Primitive/Boolean nodes hold their value in a widget (a constant set in + // the UI), which we can read directly on the front-end. + const widgets = origin.widgets || []; + let w = widgets.find((x) => typeof x.value === "boolean"); + if (!w) w = widgets.find((x) => /^(value|boolean|bool)$/i.test(x.name || "")); + if (w) return !!w.value; + // Fall back to a cached output value if the node exposes one. + const out = origin.outputs?.[link.origin_slot]; + if (out && typeof out._data !== "undefined") return !!out._data; + return null; + } + + /** True when this control has a BOOLEAN wired in -- i.e. it's governed by the + * input and should ignore the master broadcast / manual toggling. */ + _hasBooleanInput(control) { + const slot = this.findInputSlot(control.label); + if (slot === -1) return false; + const input = this.inputs?.[slot]; + return !!(input && input.link != null); + } + + /** Pull every connected boolean input into its control's enabled state. */ + _refreshFromInputs() { + let changed = false; + for (const control of this.properties.controls) { + const slot = this.findInputSlot(control.label); + if (slot === -1) continue; + const value = this._readBooleanInput(slot); + if (value === null) continue; // not wired -> leave manual toggle alone + // The boolean drives only on/off; the target keeps its own disable mode. + if (control.enabled !== value) { + control.enabled = value; + changed = true; + } + } + if (changed) this._syncToggles(); + return changed; + } + + _pollInputs() { + if (this._refreshFromInputs()) { + this.applyAll(); + this.setDirtyCanvas(true, true); + } + } + + // ---- public actions ------------------------------------------------------ + + addTarget(key, label) { + if (this.properties.controls.some((c) => c.key === key)) return; + const control = { key, label, enabled: true, disableMode: "bypass" }; + this.properties.controls.push(control); + // Rebuild so the toggle + disable-as combo, BOOLEAN input and "remove" combo + // all appear at once. _buildWidgets() -> _syncInputs() adds the input slot. + this._buildWidgets(); + this.applyControl(control); + this.size[1] = Math.max(this.size[1], this.computeSize()[1]); + this.setDirtyCanvas(true, true); + } + + removeTarget(key) { + const control = this.properties.controls.find((c) => c.key === key); + this.properties.controls = this.properties.controls.filter((c) => c.key !== key); + // Re-enable the target so removing the controller doesn't strand it disabled. + if (control) this._applyTo(key, MODE_ALWAYS); + this._buildWidgets(); + } + + applyControl(control) { + this._applyTo(control.key, controlToMode(control)); + this.setDirtyCanvas(true, true); + } + + applyAll() { + for (const control of this.properties.controls) this.applyControl(control); + } + + // ---- ComfyUI / LiteGraph hooks ------------------------------------------ + + /** Called by ComfyUI during graphToPrompt (queue time). Re-reads any wired + * boolean inputs, then ensures the running graph matches the toggles. */ + applyToGraph() { + this._refreshFromInputs(); + this.applyAll(); + } + + onAdded() { + this.applyAll(); + // Live-track wired boolean inputs with a lightweight timer instead of a + // canvas draw hook. Draw-based hooks (onDrawForeground) don't fire under the + // Nodes 2.0 / Vue renderer; a timer works in both the legacy canvas and Vue. + if (!this._pollTimer) { + this._pollTimer = setInterval(() => this._pollInputs(), 200); + } + } + + onRemoved() { + if (this._pollTimer) { + clearInterval(this._pollTimer); + this._pollTimer = null; + } + } + + onConfigure() { + if (!this.properties.controls) this.properties.controls = []; + this._normalizeControls(); + this._buildWidgets(); + // Defer applying until the rest of the graph (groups/nodes) exists. + setTimeout(() => { + this._refreshFromInputs(); + this.applyAll(); + }, 0); + } + + /** Connecting/disconnecting a boolean input takes effect immediately. */ + onConnectionsChange(type) { + if (type === LiteGraph.INPUT) this._pollInputs(); + } + + getExtraMenuOptions(_, options) { + // IMPORTANT: push into `options` and DO NOT return it. ComfyUI's LiteGraph + // does `options = extra.concat(options)` when this returns truthy -- returning + // the mutated array would duplicate the ENTIRE context menu. + const word = this.constructor.targetWord; + if (this.properties.controls.length) { + options.push({ + content: `Remove controlled ${word}`, + has_submenu: true, + submenu: { + options: this.properties.controls.map((c) => ({ + content: c.label, + callback: () => this.removeTarget(c.key), + })), + }, + }); + } + options.push({ + content: `Refresh ${word} list`, + callback: () => this._buildWidgets(), + }); + } +} + +// ---- concrete controllers -------------------------------------------------- + +class GroupControllerNode extends BaseControllerNode { + static targetWord = "group"; + static isSwitchboardController = true; + + constructor(title = GroupControllerNode.nodeTitle) { + super(title); + } + + _allChoices() { + return getGroupChoices(); + } + + _applyTo(key, mode) { + applyModeToGroup(key, mode); + } +} +GroupControllerNode.nodeTitle = "Group Controller"; + +class NodeControllerNode extends BaseControllerNode { + static targetWord = "node"; + static isSwitchboardController = true; + + constructor(title = NodeControllerNode.nodeTitle) { + super(title); + } + + _allChoices() { + return getNodeChoices(this); + } + + _applyTo(key, mode) { + applyModeToNode(key, mode); + } +} +NodeControllerNode.nodeTitle = "Node Controller"; + +app.registerExtension({ + name: "Switchboard.Controllers", + registerCustomNodes() { + for (const Cls of [GroupControllerNode, NodeControllerNode]) { + Cls.title = Cls.nodeTitle; + Cls.collapsable = true; + LiteGraph.registerNodeType(Cls.nodeTitle, Cls); + Cls.category = CATEGORY; + } + }, +}); diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d8c71e8 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "comfyui-switchboard" +description = "Switchboard - toggle ComfyUI groups or individual nodes on/off (bypass or mute), manually or from a wired boolean. A more flexible take on rgthree's Fast Group Bypasser." +version = "1.0.0" +license = { text = "MIT" } + +[project.urls] +Repository = "https://github.com/oratorian/comfyui-switchboard" + +[tool.comfy] +PublisherId = "Oratorian" +DisplayName = "Switchboard" +Icon = ""