This commit is contained in:
space-nuko
2023-05-02 14:58:02 -07:00
parent 5b4254c054
commit 890c839b4d
8 changed files with 202 additions and 114 deletions

View File

@@ -6,9 +6,10 @@ import TextWidget from "$lib/widgets/TextWidget.svelte";
import type { SvelteComponentDev } from "svelte/internal";
import { ComfyWidgets } from "$lib/widgets";
import { Watch } from "@litegraph-ts/nodes-basic";
import type IComfyInputSlot from "$lib/IComfyInputSlot";
import { writable, type Unsubscriber, type Writable } from "svelte/store";
export interface ComfyWidgetProperties extends Record<string, any> {
value: any,
}
/*
@@ -16,14 +17,20 @@ export interface ComfyWidgetProperties extends Record<string, any> {
* widget is changed, the value of the first output in the node is updated
* in the litegraph instance.
*/
export abstract class ComfyWidgetNode extends ComfyGraphNode {
export abstract class ComfyWidgetNode<T> extends ComfyGraphNode {
abstract properties: ComfyWidgetProperties;
value: Writable<T>
unsubscribe: Unsubscriber;
/** Svelte class for the frontend logic */
abstract svelteComponentType: typeof SvelteComponentDev
/** Compatible litegraph widget types that can be connected to this node */
abstract inputWidgetTypes: string[]
/** If false, user manually set min/max/step, and should not be autoinherited from connected input */
autoConfig: boolean = true;
override isBackendNode = false;
override serialize_widgets = true;
@@ -31,9 +38,10 @@ export abstract class ComfyWidgetNode extends ComfyGraphNode {
override size: Vector2 = [60, 40];
constructor(name?: string) {
super(name)
constructor(name?: string, value: T) {
const color = LGraphCanvas.node_colors["blue"]
super(name)
this.value = writable(value)
this.color ||= color.color
this.bgColor ||= color.bgColor
this.displayWidget = this.addWidget<ITextWidget>(
@@ -41,16 +49,15 @@ export abstract class ComfyWidgetNode extends ComfyGraphNode {
"Value",
""
);
this.unsubscribe = this.value.subscribe(this.onValueUpdated.bind(this))
}
override onPropertyChanged(name: string, value: any) {
if (name == "value") {
this.displayWidget.value = Watch.toString(value)
}
private onValueUpdated(value: any) {
this.displayWidget.value = Watch.toString(value)
}
setValue(value: any) {
this.setProperty("value", value)
this.value.set(value)
}
override onExecute() {
@@ -60,15 +67,54 @@ export abstract class ComfyWidgetNode extends ComfyGraphNode {
// TODO send event to linked nodes
}
onConnectOutput(
outputIndex: number,
inputType: INodeInputSlot["type"],
input: INodeInputSlot,
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])
}
console.debug("Property copy", input, this.properties)
}
return true;
}
clampConfig() {
for (const link of this.getOutputLinks(0)) {
const node = this.graph._nodes_by_id[link.target_id]
if (node) {
const input = node.inputs[link.target_slot]
if (input && "config" in input)
this.clampOneConfig(input as IComfyInputSlot)
}
}
}
clampOneConfig(input: IComfyInputSlot) {}
}
export interface ComfySliderProperties extends ComfyWidgetProperties {
value: number
min: number,
max: number,
step: number,
precision: number
}
export class ComfySliderNode extends ComfyWidgetNode {
export class ComfySliderNode extends ComfyWidgetNode<number> {
override properties: ComfySliderProperties = {
value: 0
min: 0,
max: 10,
step: 1,
precision: 1
}
override svelteComponentType = RangeWidget
@@ -79,6 +125,17 @@ export class ComfySliderNode extends ComfyWidgetNode {
{ name: "value", type: "number" }
]
}
constructor(name?: string) {
super(name, 0)
}
override clampOneConfig(input: IComfyInputSlot) {
this.setProperty("min", Math.max(this.properties.min, input.config.min))
this.setProperty("max", Math.max(this.properties.max, input.config.max))
this.setProperty("step", Math.max(this.properties.step, input.config.step))
this.setProperty("value", Math.max(Math.min(this.properties.value, this.properties.max), this.properties.min))
}
}
LiteGraph.registerNodeType({
@@ -89,14 +146,12 @@ LiteGraph.registerNodeType({
})
export interface ComfyComboProperties extends ComfyWidgetProperties {
options: string[],
value: string
options: string[]
}
export class ComfyComboNode extends ComfyWidgetNode {
export class ComfyComboNode extends ComfyWidgetNode<string> {
override properties: ComfyComboProperties = {
options: ["*"],
value: "*"
options: ["*"]
}
static slotLayout: SlotLayout = {
@@ -107,6 +162,43 @@ export class ComfyComboNode extends ComfyWidgetNode {
override svelteComponentType = ComboWidget
override inputWidgetTypes = ["combo", "enum"]
constructor(name?: string) {
super(name, "*")
}
onConnectOutput(
outputIndex: number,
inputType: INodeInputSlot["type"],
input: INodeInputSlot,
inputNode: LGraphNode,
inputIndex: number
): boolean {
if (!super.onConnectOutput(outputIndex, inputType, input, inputNode, inputIndex))
return false;
const thisProps = this.properties;
const otherProps = inputNode.properties;
// Ensure combo options match
if (!(otherProps.options instanceof Array))
return false;
if (otherProps.options.length !== thisProps.options.length)
return false;
if (otherProps.find((v, i) => thisProps[i] !== v))
return false;
return true;
}
override clampOneConfig(input: IComfyInputSlot) {
if (!(this.properties.value in input.config.values)) {
if (input.config.values.length === 0)
this.setProperty("value", "")
else
this.setProperty("value", input.config.values[0])
}
}
}
LiteGraph.registerNodeType({
@@ -117,12 +209,12 @@ LiteGraph.registerNodeType({
})
export interface ComfyTextProperties extends ComfyWidgetProperties {
value: string
multiline: boolean;
}
export class ComfyTextNode extends ComfyWidgetNode {
export class ComfyTextNode extends ComfyWidgetNode<string> {
override properties: ComfyTextProperties = {
value: ""
multiline: false
}
static slotLayout: SlotLayout = {
@@ -133,6 +225,10 @@ export class ComfyTextNode extends ComfyWidgetNode {
override svelteComponentType = TextWidget
override inputWidgetTypes = ["text"]
constructor(name?: string) {
super(name, "")
}
}
LiteGraph.registerNodeType({