Add util method to change mode of nodes so we can manually update subgraphs too. Fixes #556
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user