Spaces:
Running
on
Zero
Running
on
Zero
| import { app } from "../../scripts/app.js"; | |
| import { PassThroughFollowing, addConnectionLayoutSupport, 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"; | |
| import { fitString } from "./utils_canvas.js"; | |
| import { rgthree } from "./rgthree.js"; | |
| const MODE_ALWAYS = 0; | |
| const MODE_MUTE = 2; | |
| const MODE_BYPASS = 4; | |
| const MODE_REPEATS = [MODE_MUTE, MODE_BYPASS]; | |
| const MODE_NOTHING = -99; | |
| const MODE_TO_OPTION = new Map([ | |
| [MODE_ALWAYS, "ACTIVE"], | |
| [MODE_MUTE, "MUTE"], | |
| [MODE_BYPASS, "BYPASS"], | |
| [MODE_NOTHING, "NOTHING"], | |
| ]); | |
| const OPTION_TO_MODE = new Map([ | |
| ["ACTIVE", MODE_ALWAYS], | |
| ["MUTE", MODE_MUTE], | |
| ["BYPASS", MODE_BYPASS], | |
| ["NOTHING", MODE_NOTHING], | |
| ]); | |
| const MODE_TO_PROPERTY = new Map([ | |
| [MODE_MUTE, "on_muted_inputs"], | |
| [MODE_BYPASS, "on_bypassed_inputs"], | |
| [MODE_ALWAYS, "on_any_active_inputs"], | |
| ]); | |
| const logger = rgthree.newLogSession("[NodeModeRelay]"); | |
| class NodeModeRelay extends BaseCollectorNode { | |
| constructor(title) { | |
| super(title); | |
| this.inputsPassThroughFollowing = PassThroughFollowing.ALL; | |
| this.comfyClass = NodeTypesString.NODE_MODE_RELAY; | |
| this.properties["on_muted_inputs"] = "MUTE"; | |
| this.properties["on_bypassed_inputs"] = "BYPASS"; | |
| this.properties["on_any_active_inputs"] = "ACTIVE"; | |
| this.onConstructed(); | |
| } | |
| onConstructed() { | |
| this.addOutput("REPEATER", "_NODE_REPEATER_", { | |
| color_on: "#Fc0", | |
| color_off: "#a80", | |
| shape: LiteGraph.ARROW_SHAPE, | |
| }); | |
| setTimeout(() => { | |
| this.stabilize(); | |
| }, 500); | |
| return super.onConstructed(); | |
| } | |
| onModeChange(from, to) { | |
| var _a; | |
| super.onModeChange(from, to); | |
| if (this.inputs.length <= 1 && !this.isInputConnected(0) && this.isAnyOutputConnected()) { | |
| const [n, v] = logger.infoParts(`Mode change without any inputs; relaying our mode.`); | |
| (_a = console[n]) === null || _a === void 0 ? void 0 : _a.call(console, ...v); | |
| this.dispatchModeToRepeater(to); | |
| } | |
| } | |
| configure(info) { | |
| var _a; | |
| if ((_a = info.outputs) === null || _a === void 0 ? void 0 : _a.length) { | |
| info.outputs.length = 1; | |
| } | |
| super.configure(info); | |
| } | |
| onDrawForeground(ctx, canvas) { | |
| var _a; | |
| if ((_a = this.flags) === null || _a === void 0 ? void 0 : _a.collapsed) { | |
| return; | |
| } | |
| if (this.properties["on_muted_inputs"] !== "MUTE" || | |
| this.properties["on_bypassed_inputs"] !== "BYPASS" || | |
| this.properties["on_any_active_inputs"] != "ACTIVE") { | |
| let margin = 15; | |
| ctx.textAlign = "left"; | |
| let label = `*(MUTE > ${this.properties["on_muted_inputs"]}, `; | |
| label += `BYPASS > ${this.properties["on_bypassed_inputs"]}, `; | |
| label += `ACTIVE > ${this.properties["on_any_active_inputs"]})`; | |
| ctx.fillStyle = LiteGraph.WIDGET_SECONDARY_TEXT_COLOR; | |
| const oldFont = ctx.font; | |
| ctx.font = "italic " + (LiteGraph.NODE_SUBTEXT_SIZE - 2) + "px Arial"; | |
| ctx.fillText(fitString(ctx, label, this.size[0] - 20), 15, this.size[1] - 6); | |
| ctx.font = oldFont; | |
| } | |
| } | |
| computeSize(out) { | |
| let size = super.computeSize(out); | |
| if (this.properties["on_muted_inputs"] !== "MUTE" || | |
| this.properties["on_bypassed_inputs"] !== "BYPASS" || | |
| this.properties["on_any_active_inputs"] != "ACTIVE") { | |
| size[1] += 17; | |
| } | |
| return size; | |
| } | |
| onConnectOutput(outputIndex, inputType, inputSlot, inputNode, inputIndex) { | |
| var _a, _b; | |
| let canConnect = (_a = super.onConnectOutput) === null || _a === void 0 ? void 0 : _a.call(this, outputIndex, inputType, inputSlot, inputNode, inputIndex); | |
| let nextNode = (_b = getConnectedOutputNodesAndFilterPassThroughs(this, inputNode)[0]) !== null && _b !== void 0 ? _b : inputNode; | |
| return canConnect && nextNode.type === NodeTypesString.NODE_MODE_REPEATER; | |
| } | |
| onConnectionsChange(type, slotIndex, isConnected, link_info, ioSlot) { | |
| super.onConnectionsChange(type, slotIndex, isConnected, link_info, ioSlot); | |
| setTimeout(() => { | |
| this.stabilize(); | |
| }, 500); | |
| } | |
| stabilize() { | |
| if (!this.graph || !this.isAnyOutputConnected() || !this.isInputConnected(0)) { | |
| return; | |
| } | |
| const inputNodes = getConnectedInputNodesAndFilterPassThroughs(this, this, -1, this.inputsPassThroughFollowing); | |
| let mode = undefined; | |
| for (const inputNode of inputNodes) { | |
| if (mode === undefined) { | |
| mode = inputNode.mode; | |
| } | |
| else if (mode === inputNode.mode && MODE_REPEATS.includes(mode)) { | |
| continue; | |
| } | |
| else if (inputNode.mode === MODE_ALWAYS || mode === MODE_ALWAYS) { | |
| mode = MODE_ALWAYS; | |
| } | |
| else { | |
| mode = null; | |
| } | |
| } | |
| this.dispatchModeToRepeater(mode); | |
| setTimeout(() => { | |
| this.stabilize(); | |
| }, 500); | |
| } | |
| dispatchModeToRepeater(mode) { | |
| var _a, _b; | |
| if (mode != null) { | |
| const propertyVal = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[MODE_TO_PROPERTY.get(mode) || ""]; | |
| const newMode = OPTION_TO_MODE.get(propertyVal); | |
| mode = (newMode !== null ? newMode : mode); | |
| if (mode !== null && mode !== MODE_NOTHING) { | |
| if ((_b = this.outputs) === null || _b === void 0 ? void 0 : _b.length) { | |
| const outputNodes = getConnectedOutputNodesAndFilterPassThroughs(this); | |
| for (const outputNode of outputNodes) { | |
| outputNode.mode = mode; | |
| wait(16).then(() => { | |
| outputNode.setDirtyCanvas(true, true); | |
| }); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| getHelp() { | |
| return ` | |
| <p> | |
| This node will relay its input nodes' modes (Mute, Bypass, or Active) to a connected | |
| ${stripRgthree(NodeTypesString.NODE_MODE_REPEATER)} (which would then repeat that mode | |
| change to all of its inputs). | |
| </p> | |
| <ul> | |
| <li><p> | |
| When all connected input nodes are muted, the relay will set a connected repeater to | |
| mute (by default). | |
| </p></li> | |
| <li><p> | |
| When all connected input nodes are bypassed, the relay will set a connected repeater to | |
| bypass (by default). | |
| </p></li> | |
| <li><p> | |
| When any connected input nodes are active, the relay will set a connected repeater to | |
| active (by default). | |
| </p></li> | |
| <li><p> | |
| If no inputs are connected, the relay will set a connected repeater to its mode <i>when | |
| its own mode is changed</i>. <b>Note</b>, if any inputs are connected, then the above | |
| will occur and the Relay's mode does not matter. | |
| </p></li> | |
| </ul> | |
| <p> | |
| Note, you can change which signals get sent on the above in the <code>Properties</code>. | |
| For instance, you could configure an inverse relay which will send a MUTE when any of its | |
| inputs are active (instead of sending an ACTIVE signal), and send an ACTIVE signal when all | |
| of its inputs are muted (instead of sending a MUTE signal), etc. | |
| </p> | |
| `; | |
| } | |
| } | |
| NodeModeRelay.type = NodeTypesString.NODE_MODE_RELAY; | |
| NodeModeRelay.title = NodeTypesString.NODE_MODE_RELAY; | |
| NodeModeRelay["@on_muted_inputs"] = { | |
| type: "combo", | |
| values: ["MUTE", "ACTIVE", "BYPASS", "NOTHING"], | |
| }; | |
| NodeModeRelay["@on_bypassed_inputs"] = { | |
| type: "combo", | |
| values: ["BYPASS", "ACTIVE", "MUTE", "NOTHING"], | |
| }; | |
| NodeModeRelay["@on_any_active_inputs"] = { | |
| type: "combo", | |
| values: ["BYPASS", "ACTIVE", "MUTE", "NOTHING"], | |
| }; | |
| app.registerExtension({ | |
| name: "rgthree.NodeModeRepeaterHelper", | |
| registerCustomNodes() { | |
| addConnectionLayoutSupport(NodeModeRelay, app, [ | |
| ["Left", "Right"], | |
| ["Right", "Left"], | |
| ]); | |
| LiteGraph.registerNodeType(NodeModeRelay.type, NodeModeRelay); | |
| NodeModeRelay.category = NodeModeRelay._category; | |
| }, | |
| }); | |