From df0a93ecb015026062469304347e7b7d25b4d442 Mon Sep 17 00:00:00 2001
From: space-nuko <24979496+space-nuko@users.noreply.github.com>
Date: Thu, 4 May 2023 20:24:04 -0500
Subject: [PATCH] Refresh combo boxes button
---
src/lib/IComfyInputSlot.ts | 3 +-
src/lib/components/ComfyApp.svelte | 7 +++
src/lib/components/ComfyApp.ts | 32 +++++++----
src/lib/nodes/ComfyActionNodes.ts | 34 +++++++++++
src/lib/nodes/ComfyGraphNode.ts | 33 ++++++++++-
src/lib/nodes/ComfyWidgetNodes.ts | 47 +++++++++-------
src/lib/nodes/index.ts | 2 +-
src/lib/widgets.ts | 10 +++-
src/lib/widgets/ButtonWidget.svelte | 2 +-
src/lib/widgets/ComboWidget.svelte | 84 +++++++++++++++++++---------
src/lib/widgets/GalleryWidget.svelte | 2 +-
src/lib/widgets/RangeWidget.svelte | 2 +-
src/lib/widgets/TextWidget.svelte | 2 +-
13 files changed, 196 insertions(+), 64 deletions(-)
diff --git a/src/lib/IComfyInputSlot.ts b/src/lib/IComfyInputSlot.ts
index 23dc382..612723b 100644
--- a/src/lib/IComfyInputSlot.ts
+++ b/src/lib/IComfyInputSlot.ts
@@ -14,6 +14,7 @@ export type ComfyInputConfig = {
export default interface IComfyInputSlot extends INodeInputSlot {
serialize: boolean,
- defaultWidgetNode?: new (name?: string) => ComfyWidgetNode,
+ defaultWidgetNode: new (name?: string) => ComfyWidgetNode
+ widgetNodeType?: string,
config: ComfyInputConfig, // stores range min/max/step, etc.
}
diff --git a/src/lib/components/ComfyApp.svelte b/src/lib/components/ComfyApp.svelte
index e785f7b..db027f5 100644
--- a/src/lib/components/ComfyApp.svelte
+++ b/src/lib/components/ComfyApp.svelte
@@ -135,6 +135,10 @@
refreshView();
})
+
+ async function doRefreshCombos() {
+ await app.refreshComboInNodes()
+ }
@@ -179,6 +183,9 @@
+
diff --git a/src/lib/components/ComfyApp.ts b/src/lib/components/ComfyApp.ts
index 2d149a8..56667d7 100644
--- a/src/lib/components/ComfyApp.ts
+++ b/src/lib/components/ComfyApp.ts
@@ -23,6 +23,7 @@ import layoutState from "$lib/stores/layoutState";
import { toast } from '@zerodevx/svelte-toast'
import ComfyGraph from "$lib/ComfyGraph";
import { ComfyBackendNode } from "$lib/nodes/ComfyBackendNode";
+import { get } from "svelte/store";
export const COMFYBOX_SERIAL_VERSION = 1;
@@ -616,18 +617,29 @@ export default class ComfyApp {
const def = defs[node.type];
- throw "refreshComboInNodes unimplemented!"
- // for (const widgetNum in node.widgets) {
- // const widget = node.widgets[widgetNum]
+ for (let index = 0; index < node.inputs.length; index++) {
+ const input = node.inputs[index];
+ if ("config" in input) {
+ const comfyInput = input as IComfyInputSlot;
- // if (widget.type == "combo" && def["input"]["required"][widget.name] !== undefined) {
- // widget.options.values = def["input"]["required"][widget.name][0];
+ console.warn("RefreshCombo", comfyInput.defaultWidgetNode, comfyInput)
- // if (!widget.options.values.includes(widget.value)) {
- // widget.value = widget.options.values[0];
- // }
- // }
- // }
+ if (comfyInput.defaultWidgetNode == nodes.ComfyComboNode && def["input"]["required"][comfyInput.name] !== undefined) {
+ comfyInput.config.values = def["input"]["required"][comfyInput.name][0];
+
+ console.warn("RefreshCombo", comfyInput.config.values, def["input"]["required"][comfyInput.name])
+ const inputNode = node.getInputNode(index)
+
+ if (inputNode && "doAutoConfig" in inputNode) {
+ const comfyInputNode = inputNode as nodes.ComfyWidgetNode;
+ comfyInputNode.doAutoConfig(comfyInput)
+ if (!comfyInput.config.values.includes(get(comfyInputNode.value))) {
+ comfyInputNode.setValue(comfyInput.config.defaultValue || comfyInput.config.values[0])
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/src/lib/nodes/ComfyActionNodes.ts b/src/lib/nodes/ComfyActionNodes.ts
index e58a2ba..e7c7427 100644
--- a/src/lib/nodes/ComfyActionNodes.ts
+++ b/src/lib/nodes/ComfyActionNodes.ts
@@ -91,3 +91,37 @@ LiteGraph.registerNodeType({
desc: "Copies its input to its output when an event is received",
type: "actions/copy"
})
+
+export interface ComfySwapActionProperties extends Record {
+}
+
+export class ComfySwapAction extends ComfyGraphNode {
+ override properties: ComfySwapActionProperties = {
+ }
+
+ static slotLayout: SlotLayout = {
+ inputs: [
+ { name: "A", type: "*" },
+ { name: "B", type: "*" },
+ { name: "swap", type: BuiltInSlotType.ACTION }
+ ],
+ outputs: [
+ { name: "B", type: "*" },
+ { name: "A", type: "*" }
+ ],
+ }
+
+ override onAction(action: any, param: any) {
+ const a = this.getInputData(0)
+ const b = this.getInputData(1)
+ this.setOutputData(0, a)
+ this.setOutputData(1, b)
+ };
+}
+
+LiteGraph.registerNodeType({
+ class: ComfySwapAction,
+ title: "Comfy.SwapAction",
+ desc: "Swaps two inputs when triggered",
+ type: "actions/swap"
+})
diff --git a/src/lib/nodes/ComfyGraphNode.ts b/src/lib/nodes/ComfyGraphNode.ts
index 38cc9a5..be3d1d3 100644
--- a/src/lib/nodes/ComfyGraphNode.ts
+++ b/src/lib/nodes/ComfyGraphNode.ts
@@ -1,9 +1,10 @@
import type { ComfyInputConfig } from "$lib/IComfyInputSlot";
import type { SerializedPrompt } from "$lib/components/ComfyApp";
import type ComfyWidget from "$lib/components/widgets/ComfyWidget";
-import { LGraph, LGraphNode } from "@litegraph-ts/core";
+import { LGraph, LGraphNode, LiteGraph, type SerializedLGraphNode } from "@litegraph-ts/core";
import type { SvelteComponentDev } from "svelte/internal";
import type { ComfyWidgetNode } from "./ComfyWidgetNodes";
+import type IComfyInputSlot from "$lib/IComfyInputSlot";
export type DefaultWidgetSpec = {
defaultWidgetNode: new (name?: string) => ComfyWidgetNode,
@@ -21,4 +22,34 @@ export default class ComfyGraphNode extends LGraphNode {
onExecuted?(output: any): void;
defaultWidgets?: DefaultWidgetLayout
+
+ override onSerialize(o: SerializedLGraphNode) {
+ for (let index = 0; index < this.inputs.length; index++) {
+ const input = this.inputs[index]
+ const serInput = o.inputs[index]
+ if ("defaultWidgetNode" in input) {
+ const comfyInput = input as IComfyInputSlot
+ const widgetNode = comfyInput.defaultWidgetNode
+ const ty = Object.values(LiteGraph.registered_node_types)
+ .find(v => v.class === widgetNode)
+ if (ty)
+ (serInput as any).widgetNodeType = ty.type
+ }
+ }
+ }
+
+ override onConfigure(o: SerializedLGraphNode) {
+ for (let index = 0; index < this.inputs.length; index++) {
+ const input = this.inputs[index]
+ const serInput = o.inputs[index]
+ if ("widgetNodeType" in serInput) {
+ const comfyInput = input as IComfyInputSlot
+ const ty: string = serInput.widgetNodeType as any
+ const widgetNode = Object.values(LiteGraph.registered_node_types)
+ .find(v => v.type === ty)
+ if (widgetNode)
+ comfyInput.defaultWidgetNode = widgetNode.class as any
+ }
+ }
+ }
}
diff --git a/src/lib/nodes/ComfyWidgetNodes.ts b/src/lib/nodes/ComfyWidgetNodes.ts
index fce009f..7c127a7 100644
--- a/src/lib/nodes/ComfyWidgetNodes.ts
+++ b/src/lib/nodes/ComfyWidgetNodes.ts
@@ -27,7 +27,7 @@ export abstract class ComfyWidgetNode extends ComfyGraphNode {
abstract properties: ComfyWidgetProperties;
value: Writable
- propsChanged: Writable = writable(true) // dummy to indicate if props changed
+ propsChanged: Writable = writable(0) // dummy to indicate if props changed
unsubscribe: Unsubscriber;
/** Svelte class for the frontend logic */
@@ -119,6 +119,7 @@ export abstract class ComfyWidgetNode extends ComfyGraphNode {
if (this.inputs.length >= this.inputIndex) {
const data = this.getInputData(this.inputIndex)
if (data) { // TODO can "null" be a legitimate value here?
+ console.log(data)
this.setValue(data)
const input = this.getInputLink(this.inputIndex)
input.data = null;
@@ -145,30 +146,33 @@ export abstract class ComfyWidgetNode extends ComfyGraphNode {
inputNode: LGraphNode,
inputIndex: number
): boolean {
- if (this.autoConfig) {
- // Copy properties from default config in input slot
- if ("config" in input) {
- const comfyInput = input as IComfyInputSlot;
- for (const key in comfyInput.config)
- this.setProperty(key, comfyInput.config[key])
-
- if ("defaultValue" in this.properties)
- this.setValue(this.properties.defaultValue)
-
- const widget = layoutState.findLayoutForNode(this.id)
- if (widget && input.name !== "") {
- widget.attrs.title = input.name;
- }
-
- console.debug("Property copy", input, this.properties)
-
- this.setValue(get(this.value))
- }
+ if (this.autoConfig && "config" in input) {
+ this.doAutoConfig(input as IComfyInputSlot)
}
return true;
}
+ doAutoConfig(input: IComfyInputSlot) {
+ // Copy properties from default config in input slot
+ const comfyInput = input as IComfyInputSlot;
+ for (const key in comfyInput.config)
+ this.setProperty(key, comfyInput.config[key])
+
+ if ("defaultValue" in this.properties)
+ this.setValue(this.properties.defaultValue)
+
+ const widget = layoutState.findLayoutForNode(this.id)
+ if (widget && input.name !== "") {
+ widget.attrs.title = input.name;
+ }
+
+ console.debug("Property copy", input, this.properties)
+
+ this.setValue(get(this.value))
+ this.propsChanged.set(get(this.propsChanged) + 1)
+ }
+
onConnectionsChange(
type: LConnectionKind,
slotIndex: number,
@@ -195,12 +199,13 @@ export abstract class ComfyWidgetNode extends ComfyGraphNode {
}
// Force reactivity change so the frontend can be updated with the new props
- this.propsChanged.set(!get(this.propsChanged))
+ this.propsChanged.set(get(this.propsChanged) + 1)
}
clampOneConfig(input: IComfyInputSlot) { }
override onSerialize(o: SerializedLGraphNode) {
+ super.onSerialize(o);
(o as any).comfyValue = get(this.value);
(o as any).shownOutputProperties = this.shownOutputProperties
}
diff --git a/src/lib/nodes/index.ts b/src/lib/nodes/index.ts
index 8c22c73..c2777d1 100644
--- a/src/lib/nodes/index.ts
+++ b/src/lib/nodes/index.ts
@@ -1,5 +1,5 @@
export { default as ComfyReroute } from "./ComfyReroute"
export { ComfyWidgetNode, ComfySliderNode, ComfyComboNode, ComfyTextNode } from "./ComfyWidgetNodes"
-export { ComfyCopyAction } from "./ComfyActionNodes"
+export { ComfyCopyAction, ComfySwapAction } from "./ComfyActionNodes"
export { default as ComfyValueControl } from "./ComfyValueControl"
export { default as ComfySelector } from "./ComfySelector"
diff --git a/src/lib/widgets.ts b/src/lib/widgets.ts
index 93e8a98..e3083aa 100644
--- a/src/lib/widgets.ts
+++ b/src/lib/widgets.ts
@@ -2,7 +2,7 @@ import type { IWidget, LGraphNode } from "@litegraph-js/core";
import ComfyValueControlWidget from "./widgets/ComfyValueControlWidget";
import type { ComfyInputConfig } from "./IComfyInputSlot";
import type IComfyInputSlot from "./IComfyInputSlot";
-import { BuiltInSlotShape } from "@litegraph-ts/core";
+import { BuiltInSlotShape, LiteGraph } from "@litegraph-ts/core";
import { ComfyComboNode, ComfySliderNode, ComfyTextNode } from "./nodes";
type WidgetFactory = (node: LGraphNode, inputName: string, inputData: any) => IComfyInputSlot;
@@ -23,6 +23,14 @@ function addComfyInput(node: LGraphNode, inputName: string, extraInfo: Partial v.class === input.defaultWidgetNode)
+ if (ty)
+ input.widgetNodeType = ty.type
+ }
+
input.serialize = true;
return input;
}
diff --git a/src/lib/widgets/ButtonWidget.svelte b/src/lib/widgets/ButtonWidget.svelte
index de3c972..b2b8b6e 100644
--- a/src/lib/widgets/ButtonWidget.svelte
+++ b/src/lib/widgets/ButtonWidget.svelte
@@ -7,7 +7,7 @@
export let widget: WidgetLayout | null = null;
let node: ComfyButtonNode | null = null;
let nodeValue: Writable | null = null;
- let propsChanged: Writable | null = null;
+ let propsChanged: Writable | null = null;
$: widget && setNodeValue(widget);
diff --git a/src/lib/widgets/ComboWidget.svelte b/src/lib/widgets/ComboWidget.svelte
index da637dc..6d1cedf 100644
--- a/src/lib/widgets/ComboWidget.svelte
+++ b/src/lib/widgets/ComboWidget.svelte
@@ -7,7 +7,7 @@
export let widget: WidgetLayout | null = null;
let node: ComfyComboNode | null = null;
let nodeValue: Writable | null = null;
- let propsChanged: Writable | null = null;
+ let propsChanged: Writable | null = null;
let option: any
export let debug: boolean = false;
@@ -15,8 +15,14 @@
$: widget && setNodeValue(widget);
$: if (nodeValue !== null && (!$propsChanged || $propsChanged)) {
- $nodeValue = option
- setOption($nodeValue)
+ if (node.properties.values.indexOf(option.value) === -1) {
+ setOption($nodeValue)
+ $nodeValue = option
+ }
+ else {
+ $nodeValue = option
+ setOption($nodeValue)
+ }
setNodeValue(widget)
node.properties = node.properties
}
@@ -46,37 +52,65 @@
return "???";
return links[0].data
}
+
+ let lastPropsChanged: number = 0;
+ let werePropsChanged: boolean = false;
+
+ $: if ($propsChanged !== lastPropsChanged) {
+ werePropsChanged = true;
+ lastPropsChanged = $propsChanged;
+ setTimeout(() => (werePropsChanged = false), 2000);
+ }
-
- {#if node !== null && nodeValue !== null}
-
- {/if}
+
+ {#key $propsChanged}
+ {#if node !== null && nodeValue !== null}
+
+ {/if}
+ {/key}
-