Bind widget values to special widget nodes

This commit is contained in:
space-nuko
2023-05-03 00:53:29 -07:00
parent 890c839b4d
commit 573970eac6
21 changed files with 89 additions and 725 deletions

View File

@@ -1,18 +1,13 @@
import type { LGraph } from "@litegraph-ts/core";
import nodeState, { type WidgetUIState, type WidgetUIStateStore, type NodeStateStore, type NodeUIState, type NodeUIStateStore } from "./stores/nodeState";
import type { LGraph, LGraphNode } from "@litegraph-ts/core";
import type ComfyApp from "./components/ComfyApp";
import type { Unsubscriber } from "svelte/store";
import type { Unsubscriber, Writable } from "svelte/store";
import type { ComfyWidgetNode } from "./nodes";
type WidgetSubStore = {
store: WidgetUIStateStore,
unsubscribe: Unsubscriber
}
type NodeSubStore = {
store: NodeUIStateStore,
unsubscribe: Unsubscriber
}
/*
* Responsible for watching for and synchronizing state changes from the
* frontend to the litegraph instance.
@@ -29,68 +24,55 @@ type NodeSubStore = {
*/
export default class GraphSync {
graph: LGraph;
private _unsubscribe: Unsubscriber;
private _finalizer: FinalizationRegistry<number>;
// nodeId -> widgetSubStores[]
private stores: Record<string, WidgetSubStore[]> = {}
// nodeId -> widgetSubStore
private stores: Record<string, WidgetSubStore> = {}
constructor(app: ComfyApp) {
this.graph = app.lGraph;
this._unsubscribe = nodeState.subscribe(this.onAllNodeStateChanged.bind(this));
this._finalizer = new FinalizationRegistry((id: number) => {
console.log(`${this} has been garbage collected`);
this._unsubscribe();
});
app.eventBus.on("nodeAdded", this.onNodeAdded.bind(this));
app.eventBus.on("nodeRemoved", this.onNodeRemoved.bind(this));
}
private onAllNodeStateChanged(state: NodeStateStore) {
private onNodeAdded(node: LGraphNode) {
// TODO assumes only a single graph's widget state.
for (let nodeId in state) {
state[nodeId].node.title = state[nodeId].name;
if (!this.stores[nodeId]) {
this.addStores(state[nodeId].widgetStates, nodeId);
}
}
for (let nodeId in this.stores) {
if (!state[nodeId]) {
this.removeStores(nodeId);
}
if ("svelteComponentType" in node) {
this.addStore(node as ComfyWidgetNode);
}
this.graph.setDirtyCanvas(true, true);
}
private addStores(widgetStates: WidgetUIState[], nodeId: string) {
if (this.stores[nodeId]) {
console.warn("Stores already exist!", nodeId, this.stores[nodeId])
private onNodeRemoved(node: LGraphNode) {
if ("svelteComponentType" in node) {
this.removeStore(node as ComfyWidgetNode);
}
this.stores[nodeId] = []
for (const wuis of widgetStates) {
const unsub = wuis.value.subscribe((v) => this.onWidgetStateChanged(wuis, v))
this.stores[nodeId].push({ store: wuis.value, unsubscribe: unsub });
}
console.debug("NEWSTORES", this.stores[nodeId])
this.graph.setDirtyCanvas(true, true);
}
private removeStores(nodeId: string) {
console.debug("DELSTORES", this.stores[nodeId])
for (const ss of this.stores[nodeId]) {
ss.unsubscribe();
private addStore(node: ComfyWidgetNode) {
if (this.stores[node.id]) {
console.warn("[GraphSync] Stores already exist!", node.id, this.stores[node.id])
}
delete this.stores[nodeId]
const unsub = node.value.subscribe((v) => this.onWidgetStateChanged(node, v))
this.stores[node.id] = ({ store: node.value, unsubscribe: unsub });
console.debug("[GraphSync] NEWSTORE", this.stores[node.id])
}
private removeStore(node: ComfyWidgetNode) {
console.debug("[GraphSync] DELSTORE", this.stores[node.id])
this.stores[node.id].unsubscribe()
delete this.stores[node.id]
}
/*
* Fired when a single widget's value changes.
*/
private onWidgetStateChanged(wuis: WidgetUIState, value: any) {
wuis.widget.value = value;
private onWidgetStateChanged(node: ComfyWidgetNode, value: any) {
this.graph.setDirtyCanvas(true, true);
}
}