From f0a520b9a1c19ca9250bfd64db3b851e53c30b9b Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Tue, 25 Apr 2023 07:34:27 -0700 Subject: [PATCH] Better seed randomizer --- src/lib/components/ComfyApp.ts | 17 +++---- src/lib/components/ComfyPane.svelte | 45 +++++++++--------- src/lib/nodes/ComfyGraphNode.ts | 8 +--- src/lib/nodes/ComfyImageNodes.ts | 2 +- src/lib/nodes/ComfyKSamplerNodes.ts | 34 ------------- src/lib/nodes/index.ts | 1 - src/lib/stores/widgetState.ts | 20 +++----- src/lib/widgets.ts | 14 +++++- src/lib/widgets/ComfyGalleryWidget.ts | 1 + src/lib/widgets/ComfyValueControlWidget.ts | 55 ++++++++++++++++++++++ src/lib/widgets/ComfyWidget.ts | 3 ++ 11 files changed, 108 insertions(+), 92 deletions(-) delete mode 100644 src/lib/nodes/ComfyKSamplerNodes.ts create mode 100644 src/lib/widgets/ComfyValueControlWidget.ts diff --git a/src/lib/components/ComfyApp.ts b/src/lib/components/ComfyApp.ts index 7d85b31..1c60e34 100644 --- a/src/lib/components/ComfyApp.ts +++ b/src/lib/components/ComfyApp.ts @@ -206,8 +206,6 @@ export default class ComfyApp { private registerNodeTypeOverrides() { ComfyApp.node_type_overrides["SaveImage"] = nodes.ComfySaveImageNode; ComfyApp.node_type_overrides["PreviewImage"] = nodes.ComfyPreviewImageNode; - ComfyApp.node_type_overrides["KSampler"] = nodes.ComfyKSamplerNode; - ComfyApp.node_type_overrides["KSamplerAdvanced"] = nodes.ComfyKSamplerAdvancedNode; } private registerWidgetTypeOverrides() { @@ -389,10 +387,6 @@ export default class ComfyApp { this.api.addEventListener("executing", ({ detail }: CustomEvent) => { queueState.executingUpdated(detail.node); - const node = this.lGraph.getNodeById(detail.node) as ComfyGraphNode; - if (node?.onExecuting) { - node.onExecuting(); - } this.lGraph.setDirtyCanvas(true, false); }); @@ -496,7 +490,10 @@ export default class ComfyApp { if (widgets) { for (let i = 0; i < widgets.length; i++) { const widget = widgets[i]; - if (!widget.options || widget.options.serialize !== false) { + let isVirtual = false; + if ("isVirtual" in widget) + isVirtual = (widget as ComfyWidget).isVirtual; + if ((!widget.options || widget.options.serialize !== false) && !isVirtual) { let value = widget.serializeValue ? await widget.serializeValue(n, i) : widget.value; inputs[widget.name] = value } @@ -575,9 +572,9 @@ export default class ComfyApp { for (const widget of node.widgets) { // Allow widgets to run callbacks after a prompt has been queued // e.g. random seed after every gen - // if (widget.afterQueued) { - // widget.afterQueued(); - // } + if ("afterQueued" in widget) { + (widget as ComfyWidget).afterQueued(); + } } } } diff --git a/src/lib/components/ComfyPane.svelte b/src/lib/components/ComfyPane.svelte index 9c9a114..ae34bb2 100644 --- a/src/lib/components/ComfyPane.svelte +++ b/src/lib/components/ComfyPane.svelte @@ -60,20 +60,18 @@ let ctor: any = null; // custom widgets with TypeScript sources - if (item.isVirtual) { - let override = ComfyApp.widget_type_overrides[item.widget.type] - if (override) { - return override; - } + let override = ComfyApp.widget_type_overrides[item.widget.type] + if (override) { + return override; } // litegraph.ts built-in widgets switch (item.widget.type) { - case "combo": + case "combo": return ComboWidget; - case "number": + case "number": return RangeWidget; - case "text": + case "text": return TextWidget; } @@ -81,8 +79,7 @@ } function updateNodeName(node: LGraphNode, value: string) { - console.log("CHA") - nodeState.nodeStateChanged(node); + nodeState.nodeStateChanged(node); } @@ -98,20 +95,20 @@
{#if $uiState.unlocked} -
- -
+
+ +
{/if} {#each $widgetState[id] as item} @@ -166,7 +163,7 @@ } .node-type { - font-size: smaller; - color: var(--neutral-400); - } + font-size: smaller; + color: var(--neutral-400); + } diff --git a/src/lib/nodes/ComfyGraphNode.ts b/src/lib/nodes/ComfyGraphNode.ts index f6838f6..f3e6f86 100644 --- a/src/lib/nodes/ComfyGraphNode.ts +++ b/src/lib/nodes/ComfyGraphNode.ts @@ -4,12 +4,6 @@ import { LGraphNode } from "@litegraph-ts/core"; export default class ComfyGraphNode extends LGraphNode { isVirtualNode: boolean = false; - /* - * Widgets that aren't a part of the graph, but are used for rendering - * purposes only. - */ - virtualWidgets: ComfyWidget[] = []; - - onExecuting?(): void; + afterQueued?(): void; onExecuted?(output: any): void; } diff --git a/src/lib/nodes/ComfyImageNodes.ts b/src/lib/nodes/ComfyImageNodes.ts index 9a0c739..14d5a32 100644 --- a/src/lib/nodes/ComfyImageNodes.ts +++ b/src/lib/nodes/ComfyImageNodes.ts @@ -20,7 +20,7 @@ class ComfyImageNode extends ComfyGraphNode { constructor(title?: any) { super(title) this._galleryWidget = new ComfyGalleryWidget("Images", [], this); - this.virtualWidgets.push(this._galleryWidget) + this.addCustomWidget(this._galleryWidget); } override onExecuted(output: ComfyImageExecOutput) { diff --git a/src/lib/nodes/ComfyKSamplerNodes.ts b/src/lib/nodes/ComfyKSamplerNodes.ts deleted file mode 100644 index 84e10e1..0000000 --- a/src/lib/nodes/ComfyKSamplerNodes.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { get } from 'svelte/store'; -import ComfyGraphNode from "./ComfyGraphNode"; -import widgetState from "$lib/stores/widgetState" - -/* - * Autorefreshes seed (until bangs/main inlets are implemented) - */ -class ComfyBaseKSamplerNode extends ComfyGraphNode { - constructor(title?: any) { - super(title) - } - - override onExecuting() { - console.log(this); - const widget = widgetState.findWidgetByName(this.id, "seed") - if (!widget) - return; - - // TODO cleanup&remove - let min = widget.widget.options.min; - let max = widget.widget.options.max; - // limit to something that javascript can handle - max = Math.min(1125899906842624, max); - min = Math.max(-1125899906842624, min); - const range = (max - min) / (widget.widget.options.step); - const v = Math.floor(Math.floor(Math.random() * range) * (widget.widget.options.step) + min); - - widget.widget.value = v; - widgetState.widgetStateChanged(this.id, widget.widget); - } -} - -export class ComfyKSamplerNode extends ComfyBaseKSamplerNode {} -export class ComfyKSamplerAdvancedNode extends ComfyBaseKSamplerNode {} diff --git a/src/lib/nodes/index.ts b/src/lib/nodes/index.ts index bab1b7d..e355079 100644 --- a/src/lib/nodes/index.ts +++ b/src/lib/nodes/index.ts @@ -1,3 +1,2 @@ export { default as ComfyReroute } from "./ComfyReroute" export { ComfySaveImageNode, ComfyPreviewImageNode } from "./ComfyImageNodes" -export { ComfyKSamplerNode, ComfyKSamplerAdvancedNode } from "./ComfyKSamplerNodes" diff --git a/src/lib/stores/widgetState.ts b/src/lib/stores/widgetState.ts index 45d4da4..eee11df 100644 --- a/src/lib/stores/widgetState.ts +++ b/src/lib/stores/widgetState.ts @@ -52,19 +52,13 @@ function nodeAdded(node: LGraphNode) { let state = get(store) if (node.widgets) { - for (const widget of node.widgets) { + for (const [index, widget] of node.widgets.entries()) { if (!state[node.id]) state[node.id] = [] - state[node.id].push({ node, widget, value: writable(widget.value), isVirtual: false }) - } - } - - if ("virtualWidgets" in node) { - const comfyNode = node as ComfyGraphNode; - for (const widget of comfyNode.virtualWidgets) { - if (!state[comfyNode.id]) - state[comfyNode.id] = [] - state[comfyNode.id].push({ node, widget, value: writable(widget.value), isVirtual: true }) + let isVirtual = false; + if ("isVirtual" in widget) + isVirtual = (widget as ComfyWidget).isVirtual; + state[node.id].push({ index, node, widget, value: writable(widget.value), isVirtual: isVirtual }) } } @@ -103,11 +97,11 @@ function configureFinished(graph: LGraph) { for (const node of graph.computeExecutionOrder(false, null)) { if (node.widgets_values) { for (const [i, value] of node.widgets_values.entries()) { - if (i < state[node.id].length && !state[node.id][i].isVirtual) { // Virtual widgets always come after real widgets + if (i < state[node.id].length && !state[node.id][i].isVirtual) { state[node.id][i].value.set(value); } else { - console.error("Mismatch in widgets_values!", state[node.id].map(i => i.value), node.widgets_values) + console.error("Mismatch in widgets_values!", node.id, node.type, state[node.id].map(i => get(i.value)), node.widgets_values) break; } } diff --git a/src/lib/widgets.ts b/src/lib/widgets.ts index 991e355..2bf5bab 100644 --- a/src/lib/widgets.ts +++ b/src/lib/widgets.ts @@ -1,5 +1,6 @@ import type { IWidget, LGraphNode } from "@litegraph-js/core"; import type ComfyApp from "$lib/components/ComfyApp"; +import ComfyValueControlWidget from "./widgets/ComfyValueControlWidget"; export interface WidgetData { widget: IWidget, @@ -48,6 +49,15 @@ const INT: WidgetFactory = (node: LGraphNode, inputName: string, inputData: any) }; }; +function seedWidget(node, inputName, inputData, app) { + const seed = INT(node, inputName, inputData, app); + const seedControl = new ComfyValueControlWidget("control_after_generate", "randomize", node, seed.widget); + node.addCustomWidget(seedControl); + + // seed.widget.linkedWidgets = [seedControl]; + return seed; +} + const STRING: WidgetFactory = (node: LGraphNode, inputName: string, inputData: any, app: ComfyApp): WidgetData => { const defaultVal = inputData[1].default || ""; const multiline = !!inputData[1].multiline; @@ -127,8 +137,8 @@ const IMAGEUPLOAD: WidgetFactory = (node: LGraphNode, inputName: string, inputDa export type WidgetRepository = Record export const ComfyWidgets: WidgetRepository = { - "INT:seed": INT, - "INT:noise_seed": INT, + "INT:seed": seedWidget, + "INT:noise_seed": seedWidget, FLOAT, INT, STRING, diff --git a/src/lib/widgets/ComfyGalleryWidget.ts b/src/lib/widgets/ComfyGalleryWidget.ts index 4bf736c..f7a43a4 100644 --- a/src/lib/widgets/ComfyGalleryWidget.ts +++ b/src/lib/widgets/ComfyGalleryWidget.ts @@ -9,4 +9,5 @@ export interface ComfyGalleryWidgetOptions extends WidgetPanelOptions { export default class ComfyGalleryWidget extends ComfyWidget { override type = "comfy/gallery"; + override isVirtual = true; } diff --git a/src/lib/widgets/ComfyValueControlWidget.ts b/src/lib/widgets/ComfyValueControlWidget.ts new file mode 100644 index 0000000..065d6f9 --- /dev/null +++ b/src/lib/widgets/ComfyValueControlWidget.ts @@ -0,0 +1,55 @@ +import type { IEnumWidget, IEnumWidgetOptions, INumberWidget, LGraphNode, WidgetPanelOptions } from "@litegraph-ts/core"; +import ComfyWidget from "./ComfyWidget"; +import type { ComfyImageResult } from "$lib/nodes/ComfySaveImageNode"; +import type ComfyGraphNode from "$lib/nodes/ComfyGraphNode"; +import widgetState from "$lib/stores/widgetState" + +export interface ComfyValueControlWidgetOptions extends IEnumWidgetOptions { +} + +export default class ComfyValueControlWidget extends ComfyWidget { + override type = "combo"; + targetWidget: INumberWidget; + + constructor(name: string, value: string, node: ComfyGraphNode, targetWidget: INumberWidget) { + super(name, value, node) + this.targetWidget = targetWidget; + this.options = { values: ["fixed", "increment", "decrement", "randomize"], serialize: false }; + } + + override afterQueued() { + var v = this.value; + + let min = this.targetWidget.options.min; + let max = this.targetWidget.options.max; + // limit to something that javascript can handle + max = Math.min(1125899906842624, max); + min = Math.max(-1125899906842624, min); + let range = (max - min) / (this.targetWidget.options.step); + + //adjust values based on valueControl Behaviour + switch (v) { + case "fixed": + break; + case "increment": + this.targetWidget.value += this.targetWidget.options.step; + break; + case "decrement": + this.targetWidget.value -= this.targetWidget.options.step; + break; + case "randomize": + this.targetWidget.value = Math.floor(Math.random() * range) * (this.targetWidget.options.step) + min; + default: + break; + } + /*check if values are over or under their respective + * ranges and set them to min or max.*/ + if (this.targetWidget.value < min) + this.targetWidget.value = min; + + if (this.targetWidget.value > max) + this.targetWidget.value = max; + + widgetState.widgetStateChanged(this.node.id, this.targetWidget); + } +} diff --git a/src/lib/widgets/ComfyWidget.ts b/src/lib/widgets/ComfyWidget.ts index ea2d9d3..eec08ab 100644 --- a/src/lib/widgets/ComfyWidget.ts +++ b/src/lib/widgets/ComfyWidget.ts @@ -13,6 +13,7 @@ export default abstract class ComfyWidget implements IWidget implements IWidget, slot: number): Promise; }