When a relay has no inputs connected, use its own mode change as the relay signal.
This commit is contained in:
@@ -238,10 +238,25 @@ Note, you can right-click on a bunch of the rgthree-comfy nodes and select `🛟
|
||||
|
||||
|
||||
## Mute / Bypass Relay
|
||||
> An advanced node that, when working with a **Mute / Bypass Repeater** will relay a mute/bypass/activate signal to the repeater
|
||||
> An advanced node that, when working with a **Mute / Bypass Repeater**, will relay its input nodes'
|
||||
> modes (Mute, Bypass, or Active) to a connected repeater (which would then repeat that mode change
|
||||
> to all of its inputs).
|
||||
> <details>
|
||||
> <summary>ℹ️ <i>More Information</i></summary>
|
||||
> - Useful when you want a specific node or set of nodes to be muted when a different set of nodes are also muted.
|
||||
>
|
||||
> - When all connected input nodes are muted, the relay will set a connected repeater to mute (by
|
||||
> default).
|
||||
> - When all connected input nodes are bypassed, the relay will set a connected repeater to
|
||||
> bypass (by default).
|
||||
> - When _any_ connected input nodes are active, the relay will set a connected repeater to
|
||||
> active (by default).
|
||||
> - **Note:** If no inputs are connected, the relay will set a connected repeater to its mode
|
||||
> _when its own mode is changed_. **Note**, if any inputs are connected, then the above bullets
|
||||
> will occur and the Relay's mode does not matter.
|
||||
> - **Pro Tip:** You can change which signals get sent on the above in the `Properties`.
|
||||
> 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.
|
||||
> </details>
|
||||
|
||||
|
||||
|
||||
@@ -138,8 +138,9 @@ export abstract class RgthreeBaseNode extends LGraphNode {
|
||||
// @ts-ignore - Changing the property to an accessor here seems to work, but ts compiler complains.
|
||||
override set mode(mode: NodeMode) {
|
||||
if (this.mode_ != mode) {
|
||||
const oldMode = this.mode_;
|
||||
this.mode_ = mode;
|
||||
this.onModeChange();
|
||||
this.onModeChange(oldMode, mode);
|
||||
}
|
||||
}
|
||||
override get mode() {
|
||||
@@ -147,7 +148,7 @@ export abstract class RgthreeBaseNode extends LGraphNode {
|
||||
}
|
||||
|
||||
/** When a mode change, we want all connected nodes to match. */
|
||||
onModeChange() {
|
||||
onModeChange(from: NodeMode, to: NodeMode) {
|
||||
// Override
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ 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";
|
||||
|
||||
declare const LiteGraph: typeof TLiteGraph;
|
||||
|
||||
@@ -33,28 +34,30 @@ const MODE_REPEATS = [MODE_MUTE, MODE_BYPASS];
|
||||
const MODE_NOTHING = -99; // MADE THIS UP.
|
||||
|
||||
const MODE_TO_OPTION = new Map([
|
||||
[MODE_ALWAYS, 'ACTIVE'],
|
||||
[MODE_MUTE, 'MUTE'],
|
||||
[MODE_BYPASS, 'BYPASS'],
|
||||
[MODE_NOTHING, 'NOTHING'],
|
||||
[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],
|
||||
["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'],
|
||||
[MODE_MUTE, "on_muted_inputs"],
|
||||
[MODE_BYPASS, "on_bypassed_inputs"],
|
||||
[MODE_ALWAYS, "on_any_active_inputs"],
|
||||
]);
|
||||
|
||||
const logger = rgthree.newLogSession("[NodeModeRelay]");
|
||||
|
||||
/**
|
||||
* Like a BaseCollectorNode, this relay node connects to a Repeater and changes it mode (so it can go
|
||||
* on to mute it's connections).
|
||||
* Like a BaseCollectorNode, this relay node connects to a Repeater node and _relays_ mode changes
|
||||
* changes to the repeater (so it can go on to modify its connections).
|
||||
*/
|
||||
class NodeModeRelay extends BaseCollectorNode {
|
||||
override readonly inputsPassThroughFollowing: PassThroughFollowing = PassThroughFollowing.ALL;
|
||||
@@ -80,9 +83,9 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
|
||||
constructor(title?: string) {
|
||||
super(title);
|
||||
this.properties['on_muted_inputs'] = 'MUTE';
|
||||
this.properties['on_bypassed_inputs'] = 'BYPASS';
|
||||
this.properties['on_any_active_inputs'] = 'ACTIVE';
|
||||
this.properties["on_muted_inputs"] = "MUTE";
|
||||
this.properties["on_bypassed_inputs"] = "BYPASS";
|
||||
this.properties["on_any_active_inputs"] = "ACTIVE";
|
||||
|
||||
this.onConstructed();
|
||||
}
|
||||
@@ -100,6 +103,16 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
return super.onConstructed();
|
||||
}
|
||||
|
||||
override onModeChange(from: NodeMode, to: NodeMode) {
|
||||
super.onModeChange(from, to);
|
||||
// If we aren't connected to anything, then we'll use our mode to relay when it changes.
|
||||
if (this.inputs.length <= 1 && !this.isInputConnected(0) && this.isAnyOutputConnected()) {
|
||||
const [n, v] = logger.infoParts(`Mode change without any inputs; relaying our mode.`);
|
||||
console[n]?.(...v);
|
||||
this.dispatchModeToRepeater(this.mode);
|
||||
}
|
||||
}
|
||||
|
||||
override configure(info: SerializedLGraphNode<LGraphNode>): void {
|
||||
// Patch a small issue (~14h) where multiple OPT_CONNECTIONS may have been created.
|
||||
// https://github.com/rgthree/rgthree-comfy/issues/206
|
||||
@@ -115,14 +128,15 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.properties['on_muted_inputs'] !== 'MUTE' ||
|
||||
this.properties['on_bypassed_inputs'] !== 'BYPASS' ||
|
||||
this.properties['on_any_active_inputs'] != 'ACTIVE') {
|
||||
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']})`;
|
||||
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";
|
||||
@@ -134,9 +148,10 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
override computeSize(out: Vector2) {
|
||||
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') {
|
||||
this.properties["on_muted_inputs"] !== "MUTE" ||
|
||||
this.properties["on_bypassed_inputs"] !== "BYPASS" ||
|
||||
this.properties["on_any_active_inputs"] != "ACTIVE"
|
||||
) {
|
||||
size[1] += 17;
|
||||
}
|
||||
return size;
|
||||
@@ -200,9 +215,19 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
}
|
||||
}
|
||||
|
||||
this.dispatchModeToRepeater(mode);
|
||||
setTimeout(() => {
|
||||
this.stabilize();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the mode to the repeater, checking to see if we're modifying our mode.
|
||||
*/
|
||||
private dispatchModeToRepeater(mode?: NodeMode | -99 | null) {
|
||||
if (mode != null) {
|
||||
const propertyVal = this.properties?.[MODE_TO_PROPERTY.get(mode)||''];
|
||||
const newMode = OPTION_TO_MODE.get(propertyVal)
|
||||
const propertyVal = this.properties?.[MODE_TO_PROPERTY.get(mode) || ""];
|
||||
const newMode = OPTION_TO_MODE.get(propertyVal);
|
||||
mode = (newMode !== null ? newMode : mode) as NodeMode | -99;
|
||||
if (mode !== null && mode !== MODE_NOTHING) {
|
||||
if (this.outputs?.length) {
|
||||
@@ -216,9 +241,6 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.stabilize();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
override getHelp() {
|
||||
@@ -241,6 +263,11 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
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>.
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
getConnectedInputNodesAndFilterPassThroughs,
|
||||
getConnectedOutputNodesAndFilterPassThroughs,
|
||||
} from "./utils.js";
|
||||
import { NodeMode } from "typings/comfy.js";
|
||||
|
||||
declare const LiteGraph: typeof TLiteGraph;
|
||||
|
||||
@@ -172,8 +173,8 @@ class NodeModeRepeater extends BaseCollectorNode {
|
||||
}
|
||||
|
||||
/** When a mode change, we want all connected nodes to match except for connected relays. */
|
||||
override onModeChange() {
|
||||
super.onModeChange();
|
||||
override onModeChange(from: NodeMode, to: NodeMode) {
|
||||
super.onModeChange(from, to);
|
||||
const linkedNodes = getConnectedInputNodesAndFilterPassThroughs(this).filter(node => node.type !== NodeTypesString.NODE_MODE_RELAY);
|
||||
if (linkedNodes.length) {
|
||||
for (const node of linkedNodes) {
|
||||
|
||||
@@ -61,14 +61,15 @@ export class RgthreeBaseNode extends LGraphNode {
|
||||
}
|
||||
set mode(mode) {
|
||||
if (this.mode_ != mode) {
|
||||
const oldMode = this.mode_;
|
||||
this.mode_ = mode;
|
||||
this.onModeChange();
|
||||
this.onModeChange(oldMode, mode);
|
||||
}
|
||||
}
|
||||
get mode() {
|
||||
return this.mode_;
|
||||
}
|
||||
onModeChange() {
|
||||
onModeChange(from, to) {
|
||||
}
|
||||
async handleAction(action) {
|
||||
action;
|
||||
|
||||
@@ -4,36 +4,38 @@ 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'],
|
||||
[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],
|
||||
["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'],
|
||||
[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.properties["on_muted_inputs"] = "MUTE";
|
||||
this.properties["on_bypassed_inputs"] = "BYPASS";
|
||||
this.properties["on_any_active_inputs"] = "ACTIVE";
|
||||
this.onConstructed();
|
||||
}
|
||||
onConstructed() {
|
||||
@@ -47,6 +49,15 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
}, 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(this.mode);
|
||||
}
|
||||
}
|
||||
configure(info) {
|
||||
var _a;
|
||||
if ((_a = info.outputs) === null || _a === void 0 ? void 0 : _a.length) {
|
||||
@@ -59,14 +70,14 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
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') {
|
||||
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']})`;
|
||||
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";
|
||||
@@ -76,9 +87,9 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
}
|
||||
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') {
|
||||
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;
|
||||
@@ -96,7 +107,6 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
}, 500);
|
||||
}
|
||||
stabilize() {
|
||||
var _a, _b;
|
||||
if (!this.graph || !this.isAnyOutputConnected() || !this.isInputConnected(0)) {
|
||||
return;
|
||||
}
|
||||
@@ -116,8 +126,15 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
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 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) {
|
||||
@@ -132,9 +149,6 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.stabilize();
|
||||
}, 500);
|
||||
}
|
||||
getHelp() {
|
||||
return `
|
||||
@@ -156,6 +170,11 @@ class NodeModeRelay extends BaseCollectorNode {
|
||||
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>.
|
||||
|
||||
@@ -92,9 +92,9 @@ class NodeModeRepeater extends BaseCollectorNode {
|
||||
});
|
||||
}
|
||||
}
|
||||
onModeChange() {
|
||||
onModeChange(from, to) {
|
||||
var _a, _b;
|
||||
super.onModeChange();
|
||||
super.onModeChange(from, to);
|
||||
const linkedNodes = getConnectedInputNodesAndFilterPassThroughs(this).filter(node => node.type !== NodeTypesString.NODE_MODE_RELAY);
|
||||
if (linkedNodes.length) {
|
||||
for (const node of linkedNodes) {
|
||||
|
||||
Reference in New Issue
Block a user