Adds a new node: Random Unmuter and addresses #31. Also adds ability to hook into prompting from rgthree global.

This commit is contained in:
rgthree
2023-10-01 16:52:50 -04:00
parent 0034199e76
commit 882f407446
10 changed files with 289 additions and 0 deletions
+10
View File
@@ -44,6 +44,16 @@ export class BaseAnyInputConnectedNode extends RgthreeBaseNode {
return this.schedulePromise;
}
override clone() {
const cloned = super.clone();
while (cloned.inputs.length > 1) {
cloned.removeInput(cloned.inputs.length - 1);
}
if (cloned.inputs[0]) {
cloned.inputs[0].label = '';
}
return cloned;
}
/**
* Ensures we have at least one empty input at the end.
*/
+1
View File
@@ -15,4 +15,5 @@ export const NodeTypesString = {
FAST_ACTIONS_BUTTON: addRgthree('Fast Actions Button'),
NODE_COLLECTOR: addRgthree('Node Collector'),
REROUTE: addRgthree('Reroute'),
RANDOM_UNMUTER: addRgthree('Random Unmuter'),
}
+1
View File
@@ -87,6 +87,7 @@ class NodeModeRepeater extends BaseCollectorNode {
NodeTypesString.NODE_COLLECTOR,
NodeTypesString.FAST_ACTIONS_BUTTON,
NodeTypesString.REROUTE,
NodeTypesString.RANDOM_UNMUTER,
].includes(nextNode.type || "")
);
}
+107
View File
@@ -0,0 +1,107 @@
// / <reference path="../node_modules/litegraph.js/src/litegraph.d.ts" />
// @ts-ignore
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 type {LGraphNode} from './typings/litegraph.js';
import { getConnectedInputNodesAndFilterPassThroughs } from "./utils.js";
const MODE_MUTE = 2;
const MODE_ALWAYS = 0;
class RandomUnmuterNode extends BaseAnyInputConnectedNode {
static override exposedActions = ['Mute all', 'Enable all'];
static override type = NodeTypesString.RANDOM_UNMUTER;
static override title = RandomUnmuterNode.type;
readonly modeOn = MODE_ALWAYS;
readonly modeOff = MODE_MUTE;
tempEnabledNode: LGraphNode | null = null;
processingQueue: boolean = false;
onQueueBound = this.onQueue.bind(this);
onQueueEndBound = this.onQueueEnd.bind(this);
onGraphtoPromptBound = this.onGraphtoPrompt.bind(this);
onGraphtoPromptEndBound = this.onGraphtoPromptEnd.bind(this);
constructor(title = RandomUnmuterNode.title) {
super(title);
rgthree.addEventListener('queue', this.onQueueBound);
rgthree.addEventListener('queue-end', this.onQueueEndBound);
rgthree.addEventListener('graph-to-prompt', this.onGraphtoPromptBound);
rgthree.addEventListener('graph-to-prompt-end', this.onGraphtoPromptEndBound);
}
override onRemoved() {
rgthree.removeEventListener('queue', this.onQueueBound);
rgthree.removeEventListener('queue-end', this.onQueueEndBound);
rgthree.removeEventListener('graph-to-prompt', this.onGraphtoPromptBound);
rgthree.removeEventListener('graph-to-prompt-end', this.onGraphtoPromptEndBound);
}
onQueue(event: Event) {
this.processingQueue = true;
}
onQueueEnd(event: Event) {
this.processingQueue = false;
}
onGraphtoPrompt(event: Event) {
console.log('onQueue', event);
if (!this.processingQueue) {
return;
}
this.tempEnabledNode = null;
// Check that all are muted and, if so, choose one to unmute.
const linkedNodes = getConnectedInputNodesAndFilterPassThroughs(this);
let allMuted = true;
if (linkedNodes.length) {
for (const node of linkedNodes) {
if (node.mode !== this.modeOff) {
allMuted = false;
break;
}
}
if (allMuted) {
this.tempEnabledNode = linkedNodes[Math.floor(Math.random() * linkedNodes.length)] || null;
if (this.tempEnabledNode) {
this.tempEnabledNode.mode = this.modeOn;
}
}
}
}
onGraphtoPromptEnd(event: Event) {
console.log('onQueueEnd', event);
if (this.tempEnabledNode) {
this.tempEnabledNode.mode = this.modeOff;
this.tempEnabledNode = null;
}
}
// override async handleAction(action: string) {
// if (action === 'Mute all') {
// for (const widget of this.widgets) {
// this.forceWidgetOff(widget);
// }
// } else if (action === 'Enable all') {
// for (const widget of this.widgets) {
// this.forceWidgetOn(widget);
// }
// }
// }
}
app.registerExtension({
name: "rgthree.RandomUnmuter",
registerCustomNodes() {
RandomUnmuterNode.setUp(RandomUnmuterNode);
},
loadedGraphNode(node: LGraphNode) {
if (node.type == RandomUnmuterNode.title) {
(node as any)._tempWidth = node.size[0];
}
}
});
+43
View File
@@ -107,11 +107,30 @@ class Rgthree {
// Override the loadGraphData so we can check for bad links and ask the user to fix them.
const that = this;
const queuePrompt = app.queuePrompt as Function;
app.queuePrompt = async function() {
that.fireEvent('queue', {});
let promise = queuePrompt.apply(app, [...arguments]);
that.fireEvent('queue-end', {});
return promise;
}
const graphToPrompt = app.graphToPrompt as Function;
app.graphToPrompt = async function() {
that.fireEvent('graph-to-prompt', {});
let promise = graphToPrompt.apply(app, [...arguments]);
await promise;
that.fireEvent('graph-to-prompt-end', {});
return promise;
}
const clean = app.clean;
app.clean = function() {
document.querySelector('.rgthree-bad-links-alerts-container')?.remove();
clean && clean.call(app, ...arguments);
};
const loadGraphData = app.loadGraphData;
app.loadGraphData = function(graph: serializedLGraph) {
if (this.monitorLinkTimeout) {
@@ -204,7 +223,30 @@ class Rgthree {
}, 100);
loadGraphData && loadGraphData.call(app, ...arguments);
}
}
private readonly eventsToFns = new Map<string, Set<(ev: Event) => void>>();
addEventListener(event: string, fn: (ev: Event) => void) {
if (!this.eventsToFns.has(event)) {
this.eventsToFns.set(event, new Set());
}
this.eventsToFns.get(event)!.add(fn);
}
removeEventListener(event: string, fn: (ev: Event) => void) {
if (this.eventsToFns.has(event)) {
this.eventsToFns.get(event)!.delete(fn);
}
}
fireEvent(event: string, data: any) {
if (this.eventsToFns.has(event)) {
for (let fn of this.eventsToFns.get(event)!) {
const event = new Event(data);
fn(event);
}
}
}
setLogLevel(level: LogLevel) {
@@ -237,3 +279,4 @@ class Rgthree {
export const rgthree = new Rgthree();
// @ts-ignore. Expose it on window because, why not.
window.rgthree = rgthree;
+10
View File
@@ -22,6 +22,16 @@ export class BaseAnyInputConnectedNode extends RgthreeBaseNode {
}
return this.schedulePromise;
}
clone() {
const cloned = super.clone();
while (cloned.inputs.length > 1) {
cloned.removeInput(cloned.inputs.length - 1);
}
if (cloned.inputs[0]) {
cloned.inputs[0].label = '';
}
return cloned;
}
stabilizeInputsOutputs() {
var _a;
const hasEmptyInput = !((_a = this.inputs[this.inputs.length - 1]) === null || _a === void 0 ? void 0 : _a.link);
+1
View File
@@ -12,4 +12,5 @@ export const NodeTypesString = {
FAST_ACTIONS_BUTTON: addRgthree('Fast Actions Button'),
NODE_COLLECTOR: addRgthree('Node Collector'),
REROUTE: addRgthree('Reroute'),
RANDOM_UNMUTER: addRgthree('Random Unmuter'),
};
+1
View File
@@ -25,6 +25,7 @@ class NodeModeRepeater extends BaseCollectorNode {
NodeTypesString.NODE_COLLECTOR,
NodeTypesString.FAST_ACTIONS_BUTTON,
NodeTypesString.REROUTE,
NodeTypesString.RANDOM_UNMUTER,
].includes(nextNode.type || ""));
}
onConnectInput(inputIndex, outputType, outputSlot, outputNode, outputIndex) {
+80
View File
@@ -0,0 +1,80 @@
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";
const MODE_MUTE = 2;
const MODE_ALWAYS = 0;
class RandomUnmuterNode extends BaseAnyInputConnectedNode {
constructor(title = RandomUnmuterNode.title) {
super(title);
this.modeOn = MODE_ALWAYS;
this.modeOff = MODE_MUTE;
this.tempEnabledNode = null;
this.processingQueue = false;
this.onQueueBound = this.onQueue.bind(this);
this.onQueueEndBound = this.onQueueEnd.bind(this);
this.onGraphtoPromptBound = this.onGraphtoPrompt.bind(this);
this.onGraphtoPromptEndBound = this.onGraphtoPromptEnd.bind(this);
rgthree.addEventListener('queue', this.onQueueBound);
rgthree.addEventListener('queue-end', this.onQueueEndBound);
rgthree.addEventListener('graph-to-prompt', this.onGraphtoPromptBound);
rgthree.addEventListener('graph-to-prompt-end', this.onGraphtoPromptEndBound);
}
onRemoved() {
rgthree.removeEventListener('queue', this.onQueueBound);
rgthree.removeEventListener('queue-end', this.onQueueEndBound);
rgthree.removeEventListener('graph-to-prompt', this.onGraphtoPromptBound);
rgthree.removeEventListener('graph-to-prompt-end', this.onGraphtoPromptEndBound);
}
onQueue(event) {
this.processingQueue = true;
}
onQueueEnd(event) {
this.processingQueue = false;
}
onGraphtoPrompt(event) {
console.log('onQueue', event);
if (!this.processingQueue) {
return;
}
this.tempEnabledNode = null;
const linkedNodes = getConnectedInputNodesAndFilterPassThroughs(this);
let allMuted = true;
if (linkedNodes.length) {
for (const node of linkedNodes) {
if (node.mode !== this.modeOff) {
allMuted = false;
break;
}
}
if (allMuted) {
this.tempEnabledNode = linkedNodes[Math.floor(Math.random() * linkedNodes.length)] || null;
if (this.tempEnabledNode) {
this.tempEnabledNode.mode = this.modeOn;
}
}
}
}
onGraphtoPromptEnd(event) {
console.log('onQueueEnd', event);
if (this.tempEnabledNode) {
this.tempEnabledNode.mode = this.modeOff;
this.tempEnabledNode = null;
}
}
}
RandomUnmuterNode.exposedActions = ['Mute all', 'Enable all'];
RandomUnmuterNode.type = NodeTypesString.RANDOM_UNMUTER;
RandomUnmuterNode.title = RandomUnmuterNode.type;
app.registerExtension({
name: "rgthree.RandomUnmuter",
registerCustomNodes() {
RandomUnmuterNode.setUp(RandomUnmuterNode);
},
loadedGraphNode(node) {
if (node.type == RandomUnmuterNode.title) {
node._tempWidth = node.size[0];
}
}
});
+35
View File
@@ -66,6 +66,7 @@ class Rgthree {
this.logger = new LogSession("[rgthree]");
this.monitorBadLinksAlerted = false;
this.monitorLinkTimeout = null;
this.eventsToFns = new Map();
window.addEventListener("keydown", (e) => {
this.ctrlKey = !!e.ctrlKey;
this.altKey = !!e.altKey;
@@ -79,6 +80,21 @@ class Rgthree {
this.shiftKey = !!e.shiftKey;
});
const that = this;
const queuePrompt = app.queuePrompt;
app.queuePrompt = async function () {
that.fireEvent('queue', {});
let promise = queuePrompt.apply(app, [...arguments]);
that.fireEvent('queue-end', {});
return promise;
};
const graphToPrompt = app.graphToPrompt;
app.graphToPrompt = async function () {
that.fireEvent('graph-to-prompt', {});
let promise = graphToPrompt.apply(app, [...arguments]);
await promise;
that.fireEvent('graph-to-prompt-end', {});
return promise;
};
const clean = app.clean;
app.clean = function () {
var _a;
@@ -178,6 +194,25 @@ class Rgthree {
loadGraphData && loadGraphData.call(app, ...arguments);
};
}
addEventListener(event, fn) {
if (!this.eventsToFns.has(event)) {
this.eventsToFns.set(event, new Set());
}
this.eventsToFns.get(event).add(fn);
}
removeEventListener(event, fn) {
if (this.eventsToFns.has(event)) {
this.eventsToFns.get(event).delete(fn);
}
}
fireEvent(event, data) {
if (this.eventsToFns.has(event)) {
for (let fn of this.eventsToFns.get(event)) {
const event = new Event(data);
fn(event);
}
}
}
setLogLevel(level) {
GLOBAL_LOG_LEVEL = level;
}