From fbbc2b853646fd616465a95271f372e2d7d6485f Mon Sep 17 00:00:00 2001 From: rgthree Date: Sat, 16 Aug 2025 01:32:58 -0400 Subject: [PATCH] Add util method to change mode of nodes so we can manually update subgraphs too. Fixes #556 --- pyproject.toml | 2 +- src_web/comfyui/base_node_mode_changer.ts | 6 ++-- src_web/comfyui/fast_actions_button.ts | 8 ++--- src_web/comfyui/fast_groups_muter.ts | 5 ++- src_web/comfyui/feature_group_fast_toggle.ts | 6 ++-- src_web/comfyui/node_mode_relay.ts | 3 +- src_web/comfyui/node_mode_repeater.ts | 7 ++-- src_web/comfyui/power_conductor.ts | 7 ++-- src_web/comfyui/random_unmuter.ts | 6 ++-- src_web/comfyui/utils.ts | 35 ++++++++++++++++++++ web/comfyui/base_node_mode_changer.js | 6 ++-- web/comfyui/fast_actions_button.js | 8 ++--- web/comfyui/fast_groups_muter.js | 5 ++- web/comfyui/feature_group_fast_toggle.js | 6 ++-- web/comfyui/node_mode_relay.js | 4 +-- web/comfyui/node_mode_repeater.js | 8 ++--- web/comfyui/power_conductor.js | 7 ++-- web/comfyui/random_unmuter.js | 6 ++-- web/comfyui/utils.js | 20 +++++++++++ 19 files changed, 104 insertions(+), 51 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1fb159c..896c8e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "rgthree-comfy" description = "Making ComfyUI more comfortable." -version = "1.0.2508160121" +version = "1.0.2508160132" license = { file = "LICENSE" } dependencies = [] diff --git a/src_web/comfyui/base_node_mode_changer.ts b/src_web/comfyui/base_node_mode_changer.ts index b9cd32f..ae1afea 100644 --- a/src_web/comfyui/base_node_mode_changer.ts +++ b/src_web/comfyui/base_node_mode_changer.ts @@ -1,7 +1,7 @@ import type {LGraphNode, IWidget} from "@comfyorg/frontend"; import {BaseAnyInputConnectedNode} from "./base_any_input_connected_node.js"; -import {PassThroughFollowing} from "./utils.js"; +import {changeModeOfNodes, PassThroughFollowing} from "./utils.js"; import {wait} from "rgthree/common/shared_utils.js"; export class BaseNodeModeChanger extends BaseAnyInputConnectedNode { @@ -76,7 +76,7 @@ export class BaseNodeModeChanger extends BaseAnyInputConnectedNode { newValue = this.widgets.every((w) => !w.value || w === widget); } } - linkedNode.mode = (newValue ? this.modeOn : this.modeOff) as 1 | 2 | 3 | 4; + changeModeOfNodes(linkedNode, (newValue ? this.modeOn : this.modeOff)) widget.value = newValue; }; widget.callback = () => { @@ -87,7 +87,7 @@ export class BaseNodeModeChanger extends BaseAnyInputConnectedNode { if (forceValue != null) { const newMode = (forceValue ? this.modeOn : this.modeOff) as 1 | 2 | 3 | 4; if (linkedNode.mode !== newMode) { - linkedNode.mode = newMode; + changeModeOfNodes(linkedNode, newMode); changed = true; } } diff --git a/src_web/comfyui/fast_actions_button.ts b/src_web/comfyui/fast_actions_button.ts index 821b199..6794708 100644 --- a/src_web/comfyui/fast_actions_button.ts +++ b/src_web/comfyui/fast_actions_button.ts @@ -13,7 +13,7 @@ import type {RgthreeBaseVirtualNode} from "./base_node.js"; import {app} from "scripts/app.js"; import {BaseAnyInputConnectedNode} from "./base_any_input_connected_node.js"; import {NodeTypesString} from "./constants.js"; -import {addMenuItem} from "./utils.js"; +import {addMenuItem, changeModeOfNodes} from "./utils.js"; import {rgthree} from "./rgthree.js"; const MODE_ALWAYS = 0; @@ -272,11 +272,11 @@ class FastActionsButton extends BaseAnyInputConnectedNode { } if (node) { if (action === "Mute") { - node.mode = MODE_MUTE; + changeModeOfNodes(node, MODE_MUTE); } else if (action === "Bypass") { - node.mode = MODE_BYPASS; + changeModeOfNodes(node, MODE_BYPASS); } else if (action === "Enable") { - node.mode = MODE_ALWAYS; + changeModeOfNodes(node, MODE_ALWAYS); } // If there's a handleAction, always call it. if ((node as RgthreeBaseVirtualNode).handleAction) { diff --git a/src_web/comfyui/fast_groups_muter.ts b/src_web/comfyui/fast_groups_muter.ts index 642dff8..407c6d9 100644 --- a/src_web/comfyui/fast_groups_muter.ts +++ b/src_web/comfyui/fast_groups_muter.ts @@ -15,6 +15,7 @@ import {NodeTypesString} from "./constants.js"; import {SERVICE as FAST_GROUPS_SERVICE} from "./services/fast_groups_service.js"; import {drawNodeWidget, fitString} from "./utils_canvas.js"; import {RgthreeBaseWidget} from "./utils_widgets.js"; +import { changeModeOfNodes } from "./utils.js"; const PROPERTY_SORT = "sort"; const PROPERTY_SORT_CUSTOM_ALPHA = "customSortAlphabet"; @@ -396,9 +397,7 @@ class FastGroupsToggleRowWidget extends RgthreeBaseWidget<{toggled: boolean}> { newValue = this.node.widgets.every((w) => !w.value || w === this); } } - for (const node of this.group._nodes) { - node.mode = (newValue ? this.node.modeOn : this.node.modeOff) as 1 | 2 | 3 | 4; - } + changeModeOfNodes(this.group._nodes, (newValue ? this.node.modeOn : this.node.modeOff)); this.group.rgthree_hasAnyActiveNode = newValue; this.toggled = newValue; app.graph.setDirtyCanvas(true, false); diff --git a/src_web/comfyui/feature_group_fast_toggle.ts b/src_web/comfyui/feature_group_fast_toggle.ts index 1e55dbc..7ba5dc5 100644 --- a/src_web/comfyui/feature_group_fast_toggle.ts +++ b/src_web/comfyui/feature_group_fast_toggle.ts @@ -9,7 +9,7 @@ import type {AdjustedMouseCustomEvent} from "typings/rgthree.js"; import {app} from "scripts/app.js"; import {rgthree} from "./rgthree.js"; -import {getOutputNodes} from "./utils.js"; +import {changeModeOfNodes, getOutputNodes} from "./utils.js"; import {SERVICE as CONFIG_SERVICE} from "./services/config_service.js"; const BTN_SIZE = 20; @@ -113,9 +113,7 @@ app.registerExtension({ } else { newMode = isAllBypassed ? LiteGraph.ALWAYS : 4; } - for (const node of group._nodes) { - node.mode = newMode; - } + changeModeOfNodes(group._nodes, newMode); } } // Make it such that we're not then moving the group on drag. diff --git a/src_web/comfyui/node_mode_relay.ts b/src_web/comfyui/node_mode_relay.ts index 005c097..aac47b4 100644 --- a/src_web/comfyui/node_mode_relay.ts +++ b/src_web/comfyui/node_mode_relay.ts @@ -13,6 +13,7 @@ import {app} from "scripts/app.js"; import { PassThroughFollowing, addConnectionLayoutSupport, + changeModeOfNodes, getConnectedInputNodesAndFilterPassThroughs, getConnectedOutputNodesAndFilterPassThroughs, } from "./utils.js"; @@ -219,7 +220,7 @@ class NodeModeRelay extends BaseCollectorNode { if (this.outputs?.length) { const outputNodes = getConnectedOutputNodesAndFilterPassThroughs(this); for (const outputNode of outputNodes) { - outputNode.mode = mode; + changeModeOfNodes(outputNode, mode); wait(16).then(() => { outputNode.setDirtyCanvas(true, true); }); diff --git a/src_web/comfyui/node_mode_repeater.ts b/src_web/comfyui/node_mode_repeater.ts index aa82a6e..57f22d5 100644 --- a/src_web/comfyui/node_mode_repeater.ts +++ b/src_web/comfyui/node_mode_repeater.ts @@ -13,6 +13,7 @@ import {NodeTypesString, stripRgthree} from "./constants.js"; import { PassThroughFollowing, addConnectionLayoutSupport, + changeModeOfNodes, getConnectedInputNodesAndFilterPassThroughs, getConnectedOutputNodesAndFilterPassThroughs, } from "./utils.js"; @@ -126,7 +127,7 @@ class NodeModeRepeater extends BaseCollectorNode { } } } else { - inputNode.mode = this.mode; + changeModeOfNodes(inputNode, this.mode); } } @@ -157,7 +158,7 @@ class NodeModeRepeater extends BaseCollectorNode { for (const node of linkedNodes) { if (node.type !== NodeTypesString.NODE_MODE_RELAY) { // Use "to" as there may be other getters in the way to access this.mode directly. - node.mode = to; + changeModeOfNodes(node, to); } } } else if (app.graph._groups?.length) { @@ -168,7 +169,7 @@ class NodeModeRepeater extends BaseCollectorNode { for (const node of group._nodes) { if (node !== this) { // Use "to" as there may be other getters in the way to access this.mode directly. - node.mode = to; + changeModeOfNodes(node, to); } } } diff --git a/src_web/comfyui/power_conductor.ts b/src_web/comfyui/power_conductor.ts index a3ae5fd..6995cb1 100644 --- a/src_web/comfyui/power_conductor.ts +++ b/src_web/comfyui/power_conductor.ts @@ -8,6 +8,7 @@ import {RgthreeBetterButtonWidget} from "./utils_widgets.js"; import {NodeTypesString} from "./constants.js"; import {ComfyWidgets} from "scripts/widgets.js"; import {SERVICE as CONFIG_SERVICE} from "./services/config_service.js"; +import { changeModeOfNodes } from "./utils.js"; const BUILT_INS = { node: { @@ -85,15 +86,15 @@ class ComfyNodeWrapper { } @Exposed mute() { - this.getNode().mode = 2; + changeModeOfNodes(this.getNode(), 2); } @Exposed bypass() { - this.getNode().mode = 4; + changeModeOfNodes(this.getNode(), 4); } @Exposed enable() { - this.getNode().mode = 0; + changeModeOfNodes(this.getNode(), 0); } } diff --git a/src_web/comfyui/random_unmuter.ts b/src_web/comfyui/random_unmuter.ts index 4485f3e..1f951a9 100644 --- a/src_web/comfyui/random_unmuter.ts +++ b/src_web/comfyui/random_unmuter.ts @@ -4,7 +4,7 @@ import {app} from "scripts/app.js"; import {BaseAnyInputConnectedNode} from "./base_any_input_connected_node.js"; import {NodeTypesString} from "./constants.js"; import {rgthree} from "./rgthree.js"; -import {getConnectedInputNodesAndFilterPassThroughs} from "./utils.js"; +import {changeModeOfNodes, getConnectedInputNodesAndFilterPassThroughs} from "./utils.js"; const MODE_MUTE = 2; const MODE_ALWAYS = 0; @@ -67,14 +67,14 @@ class RandomUnmuterNode extends BaseAnyInputConnectedNode { if (allMuted) { this.tempEnabledNode = linkedNodes[Math.floor(Math.random() * linkedNodes.length)] || null; if (this.tempEnabledNode) { - this.tempEnabledNode.mode = this.modeOn; + changeModeOfNodes(this.tempEnabledNode, this.modeOn); } } } } onGraphtoPromptEnd(event: Event) { if (this.tempEnabledNode) { - this.tempEnabledNode.mode = this.modeOff; + changeModeOfNodes(this.tempEnabledNode, this.modeOff); this.tempEnabledNode = null; } } diff --git a/src_web/comfyui/utils.ts b/src_web/comfyui/utils.ts index da75f81..2b94869 100644 --- a/src_web/comfyui/utils.ts +++ b/src_web/comfyui/utils.ts @@ -963,6 +963,41 @@ export function getOutputNodes(nodes: LGraphNode[]) { ); } +/** + * Changes the mode of a node. We must go through this to change a node's mode after the + * introduction of subgraphs, as ComfyUI doesn't update the mode of a node in a subgraph on its own. + */ +export function changeModeOfNodes(nodeOrNodes: LGraphNode | LGraphNode[], mode: LGraphEventMode) { + const nodes = Array.isArray(nodeOrNodes) ? nodeOrNodes : [nodeOrNodes]; + traverseNodesDepthFirst(nodes, (n) => { + n.mode = mode; + }); +} + +/** + * Performs depth-first traversal of nodes and their subgraphs. + * Adapted from ComfyUI Frontend's method. + */ +function traverseNodesDepthFirst(nodes: LGraphNode[], visitor: (n: LGraphNode) => void) { + const stack: Array<{node: LGraphNode}> = nodes.map((node) => ({node})); + + // Process stack iteratively (DFS) + while (stack.length > 0) { + const {node} = stack.pop()!; + visitor(node); + + // If it's a subgraph and we should expand, add children to stack + if (node.isSubgraphNode?.() && node.subgraph) { + // Process children in reverse order to maintain left-to-right DFS processing + // when popping from stack (LIFO). Iterate backwards to avoid array reversal. + const children = node.subgraph.nodes; + for (let i = children.length - 1; i >= 0; i--) { + stack.push({node: children[i]!}); + } + } + } +} + /** * Gets a full color string, including parsing from the LGraphCanvas data. */ diff --git a/web/comfyui/base_node_mode_changer.js b/web/comfyui/base_node_mode_changer.js index ba7f907..8d2b207 100644 --- a/web/comfyui/base_node_mode_changer.js +++ b/web/comfyui/base_node_mode_changer.js @@ -1,5 +1,5 @@ import { BaseAnyInputConnectedNode } from "./base_any_input_connected_node.js"; -import { PassThroughFollowing } from "./utils.js"; +import { changeModeOfNodes, PassThroughFollowing } from "./utils.js"; import { wait } from "../../rgthree/common/shared_utils.js"; export class BaseNodeModeChanger extends BaseAnyInputConnectedNode { constructor(title) { @@ -59,7 +59,7 @@ export class BaseNodeModeChanger extends BaseAnyInputConnectedNode { newValue = this.widgets.every((w) => !w.value || w === widget); } } - linkedNode.mode = (newValue ? this.modeOn : this.modeOff); + changeModeOfNodes(linkedNode, (newValue ? this.modeOn : this.modeOff)); widget.value = newValue; }; widget.callback = () => { @@ -70,7 +70,7 @@ export class BaseNodeModeChanger extends BaseAnyInputConnectedNode { if (forceValue != null) { const newMode = (forceValue ? this.modeOn : this.modeOff); if (linkedNode.mode !== newMode) { - linkedNode.mode = newMode; + changeModeOfNodes(linkedNode, newMode); changed = true; } } diff --git a/web/comfyui/fast_actions_button.js b/web/comfyui/fast_actions_button.js index 5fb633d..3e00ed8 100644 --- a/web/comfyui/fast_actions_button.js +++ b/web/comfyui/fast_actions_button.js @@ -1,7 +1,7 @@ import { app } from "../../scripts/app.js"; import { BaseAnyInputConnectedNode } from "./base_any_input_connected_node.js"; import { NodeTypesString } from "./constants.js"; -import { addMenuItem } from "./utils.js"; +import { addMenuItem, changeModeOfNodes } from "./utils.js"; import { rgthree } from "./rgthree.js"; const MODE_ALWAYS = 0; const MODE_MUTE = 2; @@ -192,13 +192,13 @@ class FastActionsButton extends BaseAnyInputConnectedNode { } if (node) { if (action === "Mute") { - node.mode = MODE_MUTE; + changeModeOfNodes(node, MODE_MUTE); } else if (action === "Bypass") { - node.mode = MODE_BYPASS; + changeModeOfNodes(node, MODE_BYPASS); } else if (action === "Enable") { - node.mode = MODE_ALWAYS; + changeModeOfNodes(node, MODE_ALWAYS); } if (node.handleAction) { if (typeof action !== "string") { diff --git a/web/comfyui/fast_groups_muter.js b/web/comfyui/fast_groups_muter.js index 69743e4..7ce8f08 100644 --- a/web/comfyui/fast_groups_muter.js +++ b/web/comfyui/fast_groups_muter.js @@ -4,6 +4,7 @@ import { NodeTypesString } from "./constants.js"; import { SERVICE as FAST_GROUPS_SERVICE } from "./services/fast_groups_service.js"; import { drawNodeWidget, fitString } from "./utils_canvas.js"; import { RgthreeBaseWidget } from "./utils_widgets.js"; +import { changeModeOfNodes } from "./utils.js"; const PROPERTY_SORT = "sort"; const PROPERTY_SORT_CUSTOM_ALPHA = "customSortAlphabet"; const PROPERTY_MATCH_COLORS = "matchColors"; @@ -319,9 +320,7 @@ class FastGroupsToggleRowWidget extends RgthreeBaseWidget { newValue = this.node.widgets.every((w) => !w.value || w === this); } } - for (const node of this.group._nodes) { - node.mode = (newValue ? this.node.modeOn : this.node.modeOff); - } + changeModeOfNodes(this.group._nodes, (newValue ? this.node.modeOn : this.node.modeOff)); this.group.rgthree_hasAnyActiveNode = newValue; this.toggled = newValue; app.graph.setDirtyCanvas(true, false); diff --git a/web/comfyui/feature_group_fast_toggle.js b/web/comfyui/feature_group_fast_toggle.js index 27deb54..d7fada0 100644 --- a/web/comfyui/feature_group_fast_toggle.js +++ b/web/comfyui/feature_group_fast_toggle.js @@ -1,6 +1,6 @@ import { app } from "../../scripts/app.js"; import { rgthree } from "./rgthree.js"; -import { getOutputNodes } from "./utils.js"; +import { changeModeOfNodes, getOutputNodes } from "./utils.js"; import { SERVICE as CONFIG_SERVICE } from "./services/config_service.js"; const BTN_SIZE = 20; const BTN_MARGIN = [6, 6]; @@ -72,9 +72,7 @@ app.registerExtension({ else { newMode = isAllBypassed ? LiteGraph.ALWAYS : 4; } - for (const node of group._nodes) { - node.mode = newMode; - } + changeModeOfNodes(group._nodes, newMode); } } canvas.selected_group = null; diff --git a/web/comfyui/node_mode_relay.js b/web/comfyui/node_mode_relay.js index 566d314..5daeffb 100644 --- a/web/comfyui/node_mode_relay.js +++ b/web/comfyui/node_mode_relay.js @@ -1,5 +1,5 @@ import { app } from "../../scripts/app.js"; -import { PassThroughFollowing, addConnectionLayoutSupport, getConnectedInputNodesAndFilterPassThroughs, getConnectedOutputNodesAndFilterPassThroughs, } from "./utils.js"; +import { PassThroughFollowing, addConnectionLayoutSupport, changeModeOfNodes, getConnectedInputNodesAndFilterPassThroughs, getConnectedOutputNodesAndFilterPassThroughs, } from "./utils.js"; import { wait } from "../../rgthree/common/shared_utils.js"; import { BaseCollectorNode } from "./base_node_collector.js"; import { NodeTypesString, stripRgthree } from "./constants.js"; @@ -134,7 +134,7 @@ class NodeModeRelay extends BaseCollectorNode { if ((_b = this.outputs) === null || _b === void 0 ? void 0 : _b.length) { const outputNodes = getConnectedOutputNodesAndFilterPassThroughs(this); for (const outputNode of outputNodes) { - outputNode.mode = mode; + changeModeOfNodes(outputNode, mode); wait(16).then(() => { outputNode.setDirtyCanvas(true, true); }); diff --git a/web/comfyui/node_mode_repeater.js b/web/comfyui/node_mode_repeater.js index 7dbea5c..b14c6a7 100644 --- a/web/comfyui/node_mode_repeater.js +++ b/web/comfyui/node_mode_repeater.js @@ -1,7 +1,7 @@ import { app } from "../../scripts/app.js"; import { BaseCollectorNode } from "./base_node_collector.js"; import { NodeTypesString, stripRgthree } from "./constants.js"; -import { PassThroughFollowing, addConnectionLayoutSupport, getConnectedInputNodesAndFilterPassThroughs, getConnectedOutputNodesAndFilterPassThroughs, } from "./utils.js"; +import { PassThroughFollowing, addConnectionLayoutSupport, changeModeOfNodes, getConnectedInputNodesAndFilterPassThroughs, getConnectedOutputNodesAndFilterPassThroughs, } from "./utils.js"; class NodeModeRepeater extends BaseCollectorNode { constructor(title) { super(title); @@ -68,7 +68,7 @@ class NodeModeRepeater extends BaseCollectorNode { } } else { - inputNode.mode = this.mode; + changeModeOfNodes(inputNode, this.mode); } } this.hasTogglerOutput = hasTogglerOutput; @@ -93,7 +93,7 @@ class NodeModeRepeater extends BaseCollectorNode { if (linkedNodes.length) { for (const node of linkedNodes) { if (node.type !== NodeTypesString.NODE_MODE_RELAY) { - node.mode = to; + changeModeOfNodes(node, to); } } } @@ -103,7 +103,7 @@ class NodeModeRepeater extends BaseCollectorNode { if ((_b = group._nodes) === null || _b === void 0 ? void 0 : _b.includes(this)) { for (const node of group._nodes) { if (node !== this) { - node.mode = to; + changeModeOfNodes(node, to); } } } diff --git a/web/comfyui/power_conductor.js b/web/comfyui/power_conductor.js index 0ebe6d8..1d5748c 100644 --- a/web/comfyui/power_conductor.js +++ b/web/comfyui/power_conductor.js @@ -23,6 +23,7 @@ import { RgthreeBetterButtonWidget } from "./utils_widgets.js"; import { NodeTypesString } from "./constants.js"; import { ComfyWidgets } from "../../scripts/widgets.js"; import { SERVICE as CONFIG_SERVICE } from "./services/config_service.js"; +import { changeModeOfNodes } from "./utils.js"; const BUILT_INS = { node: { fn: (query) => { @@ -78,13 +79,13 @@ class ComfyNodeWrapper { return this.getNode().mode; } mute() { - this.getNode().mode = 2; + changeModeOfNodes(this.getNode(), 2); } bypass() { - this.getNode().mode = 4; + changeModeOfNodes(this.getNode(), 4); } enable() { - this.getNode().mode = 0; + changeModeOfNodes(this.getNode(), 0); } } _ComfyNodeWrapper_id = new WeakMap(); diff --git a/web/comfyui/random_unmuter.js b/web/comfyui/random_unmuter.js index 6e83e25..213aa8c 100644 --- a/web/comfyui/random_unmuter.js +++ b/web/comfyui/random_unmuter.js @@ -2,7 +2,7 @@ import { app } from "../../scripts/app.js"; import { BaseAnyInputConnectedNode } from "./base_any_input_connected_node.js"; import { NodeTypesString } from "./constants.js"; import { rgthree } from "./rgthree.js"; -import { getConnectedInputNodesAndFilterPassThroughs } from "./utils.js"; +import { changeModeOfNodes, getConnectedInputNodesAndFilterPassThroughs } from "./utils.js"; const MODE_MUTE = 2; const MODE_ALWAYS = 0; class RandomUnmuterNode extends BaseAnyInputConnectedNode { @@ -52,14 +52,14 @@ class RandomUnmuterNode extends BaseAnyInputConnectedNode { if (allMuted) { this.tempEnabledNode = linkedNodes[Math.floor(Math.random() * linkedNodes.length)] || null; if (this.tempEnabledNode) { - this.tempEnabledNode.mode = this.modeOn; + changeModeOfNodes(this.tempEnabledNode, this.modeOn); } } } } onGraphtoPromptEnd(event) { if (this.tempEnabledNode) { - this.tempEnabledNode.mode = this.modeOff; + changeModeOfNodes(this.tempEnabledNode, this.modeOff); this.tempEnabledNode = null; } } diff --git a/web/comfyui/utils.js b/web/comfyui/utils.js index 41f4c68..85a6ae0 100644 --- a/web/comfyui/utils.js +++ b/web/comfyui/utils.js @@ -640,6 +640,26 @@ export function getOutputNodes(nodes) { return (n.mode != LiteGraph.NEVER && ((_a = n.constructor.nodeData) === null || _a === void 0 ? void 0 : _a.output_node)); })) || []); } +export function changeModeOfNodes(nodeOrNodes, mode) { + const nodes = Array.isArray(nodeOrNodes) ? nodeOrNodes : [nodeOrNodes]; + traverseNodesDepthFirst(nodes, (n) => { + n.mode = mode; + }); +} +function traverseNodesDepthFirst(nodes, visitor) { + var _a; + const stack = nodes.map((node) => ({ node })); + while (stack.length > 0) { + const { node } = stack.pop(); + visitor(node); + if (((_a = node.isSubgraphNode) === null || _a === void 0 ? void 0 : _a.call(node)) && node.subgraph) { + const children = node.subgraph.nodes; + for (let i = children.length - 1; i >= 0; i--) { + stack.push({ node: children[i] }); + } + } + } +} export function getFullColor(color, liteGraphKey = "color") { if (!color) { return "";