Spaces:
Paused
Paused
| import type { INodeInputSlot, INodeOutputSlot, LLink } from "typings/litegraph.js"; | |
| import type { ComfyApp, ComfyNodeConstructor, ComfyObjectInfo } from "typings/comfy.js"; | |
| import { app } from "scripts/app.js"; | |
| import { IoDirection, addConnectionLayoutSupport, followConnectionUntilType } from "./utils.js"; | |
| import { RgthreeBaseServerNode } from "./base_node.js"; | |
| import { NodeTypesString } from "./constants.js"; | |
| import { removeUnusedInputsFromEnd } from "./utils_inputs_outputs.js"; | |
| import { debounce } from "rgthree/common/shared_utils.js"; | |
| class RgthreeAnySwitch extends RgthreeBaseServerNode { | |
| static override title = NodeTypesString.ANY_SWITCH; | |
| static override type = NodeTypesString.ANY_SWITCH; | |
| static comfyClass = NodeTypesString.ANY_SWITCH; | |
| private stabilizeBound = this.stabilize.bind(this); | |
| private nodeType: string | string[] | null = null; | |
| constructor(title = RgthreeAnySwitch.title) { | |
| super(title); | |
| // Adding five. Note, configure will add as many as was in the stored workflow automatically. | |
| this.addAnyInput(5); | |
| } | |
| override onConnectionsChange( | |
| type: number, | |
| slotIndex: number, | |
| isConnected: boolean, | |
| linkInfo: LLink, | |
| ioSlot: INodeOutputSlot | INodeInputSlot, | |
| ) { | |
| super.onConnectionsChange?.(type, slotIndex, isConnected, linkInfo, ioSlot); | |
| this.scheduleStabilize(); | |
| } | |
| onConnectionsChainChange() { | |
| this.scheduleStabilize(); | |
| } | |
| scheduleStabilize(ms = 64) { | |
| return debounce(this.stabilizeBound, ms); | |
| } | |
| private addAnyInput(num = 1) { | |
| for (let i = 0; i < num; i++) { | |
| this.addInput( | |
| `any_${String(this.inputs.length + 1).padStart(2, "0")}`, | |
| (this.nodeType || "*") as string, | |
| ); | |
| } | |
| } | |
| stabilize() { | |
| // First, clean up the dynamic number of inputs. | |
| removeUnusedInputsFromEnd(this, 4); | |
| this.addAnyInput(); | |
| // We prefer the inputs, then the output. | |
| let connectedType = followConnectionUntilType(this, IoDirection.INPUT, undefined, true); | |
| if (!connectedType) { | |
| connectedType = followConnectionUntilType(this, IoDirection.OUTPUT, undefined, true); | |
| } | |
| // TODO: What this doesn't do is broadcast to other nodes when its type changes. Reroute node | |
| // does, but, for now, if this was connected to another Any Switch, say, the second one wouldn't | |
| // change its type when the first does. The user would need to change the connections. | |
| this.nodeType = connectedType?.type || "*"; | |
| for (const input of this.inputs) { | |
| input.type = this.nodeType as string; // So, types can indeed be arrays,, | |
| } | |
| for (const output of this.outputs) { | |
| output.type = this.nodeType as string; // So, types can indeed be arrays,, | |
| output.label = | |
| output.type === "RGTHREE_CONTEXT" | |
| ? "CONTEXT" | |
| : Array.isArray(this.nodeType) || this.nodeType.includes(",") | |
| ? connectedType?.label || String(this.nodeType) | |
| : String(this.nodeType); | |
| } | |
| } | |
| static override setUp(comfyClass: ComfyNodeConstructor, nodeData: ComfyObjectInfo) { | |
| RgthreeBaseServerNode.registerForOverride(comfyClass, nodeData, RgthreeAnySwitch); | |
| addConnectionLayoutSupport(RgthreeAnySwitch, app, [ | |
| ["Left", "Right"], | |
| ["Right", "Left"], | |
| ]); | |
| } | |
| } | |
| app.registerExtension({ | |
| name: "rgthree.AnySwitch", | |
| async beforeRegisterNodeDef( | |
| nodeType: ComfyNodeConstructor, | |
| nodeData: ComfyObjectInfo, | |
| app: ComfyApp, | |
| ) { | |
| if (nodeData.name === "Any Switch (rgthree)") { | |
| RgthreeAnySwitch.setUp(nodeType, nodeData); | |
| } | |
| }, | |
| }); | |