Adds a new node: Random Unmuter and addresses #31. Also adds ability to hook into prompting from rgthree global.
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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'),
|
||||
}
|
||||
@@ -87,6 +87,7 @@ class NodeModeRepeater extends BaseCollectorNode {
|
||||
NodeTypesString.NODE_COLLECTOR,
|
||||
NodeTypesString.FAST_ACTIONS_BUTTON,
|
||||
NodeTypesString.REROUTE,
|
||||
NodeTypesString.RANDOM_UNMUTER,
|
||||
].includes(nextNode.type || "")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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'),
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user