File size: 4,035 Bytes
4450790
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import type { LGraphNode } from "typings/litegraph.js";
import type { RgthreeBaseVirtualNodeConstructor } from "typings/rgthree.js";

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 {
  static override exposedActions = ["Mute all", "Enable all"];

  static override type = NodeTypesString.RANDOM_UNMUTER;
  override comfyClass = 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);
    this.onConstructed();
  }

  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) {
    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) {
    if (this.tempEnabledNode) {
      this.tempEnabledNode.mode = this.modeOff;
      this.tempEnabledNode = null;
    }
  }

  override handleLinkedNodesStabilization(linkedNodes: LGraphNode[]): void {
    // No-op, no widgets.
  }

  override getHelp(): string {
    return `

      <p>

        Use this node to unmute on of its inputs randomly when the graph is queued (and, immediately

        mute it back).

      </p>

      <ul>

        <li><p>

          NOTE: All input nodes MUST be muted to start; if not this node will not randomly unmute

          another. (This is powerful, as the generated image can be dragged in and the chosen input

          will already by unmuted and work w/o any further action.)

        </p></li>

        <li><p>

          TIP: Connect a Repeater's output to this nodes input and place that Repeater on a group

          without any other inputs, and it will mute/unmute the entire group.

        </p></li>

      </ul>

    `;
  }
}

app.registerExtension({
  name: "rgthree.RandomUnmuter",
  registerCustomNodes() {
    RandomUnmuterNode.setUp();
  },
  loadedGraphNode(node: LGraphNode) {
    if (node.type == RandomUnmuterNode.title) {
      (node as any)._tempWidth = node.size[0];
    }
  },
});