Various fixes/features

This commit is contained in:
space-nuko
2023-05-17 20:17:00 -05:00
parent fe3efe1154
commit ab54f771b1
22 changed files with 186 additions and 66 deletions

View File

@@ -9,6 +9,7 @@ import type ComfyGraphNode from "./nodes/ComfyGraphNode";
import type IComfyInputSlot from "./IComfyInputSlot"; import type IComfyInputSlot from "./IComfyInputSlot";
import type { ComfyBackendNode } from "./nodes/ComfyBackendNode"; import type { ComfyBackendNode } from "./nodes/ComfyBackendNode";
import type { ComfyComboNode, ComfyWidgetNode } from "./nodes/widgets"; import type { ComfyComboNode, ComfyWidgetNode } from "./nodes/widgets";
import selectionState from "./stores/selectionState";
type ComfyGraphEvents = { type ComfyGraphEvents = {
configured: (graph: LGraph) => void configured: (graph: LGraph) => void
@@ -115,7 +116,7 @@ export default class ComfyGraph extends LGraph {
if (comfyInput.defaultWidgetNode) { if (comfyInput.defaultWidgetNode) {
const widgetNode = LiteGraph.createNode(comfyInput.defaultWidgetNode) const widgetNode = LiteGraph.createNode(comfyInput.defaultWidgetNode)
const inputPos = comfyNode.getConnectionPos(true, index); const inputPos = comfyNode.getConnectionPos(true, index);
this.add(widgetNode) node.graph.add(widgetNode)
widgetNode.connect(0, comfyNode, index); widgetNode.connect(0, comfyNode, index);
widgetNode.collapse(); widgetNode.collapse();
widgetNode.pos = [inputPos[0] - 140, inputPos[1] + LiteGraph.NODE_SLOT_HEIGHT / 2]; widgetNode.pos = [inputPos[0] - 140, inputPos[1] + LiteGraph.NODE_SLOT_HEIGHT / 2];
@@ -150,6 +151,7 @@ export default class ComfyGraph extends LGraph {
} }
override onNodeRemoved(node: LGraphNode, options: LGraphRemoveNodeOptions) { override onNodeRemoved(node: LGraphNode, options: LGraphRemoveNodeOptions) {
selectionState.clear(); // safest option
layoutState.nodeRemoved(node, options); layoutState.nodeRemoved(node, options);
// Handle subgraphs being removed // Handle subgraphs being removed

View File

@@ -17,12 +17,20 @@ export type ComfyNodeDefInputs = {
optional?: Record<string, ComfyNodeDefInput> optional?: Record<string, ComfyNodeDefInput>
} }
export type ComfyNodeDefInput = [ComfyNodeDefInputType, ComfyNodeDefInputOptions | null] export type ComfyNodeDefInput = [ComfyNodeDefInputType, ComfyNodeDefInputOptions | null]
/**
* - Array: Combo widget. Usually the values are strings but they can also be other stuff like booleans.
* - "INT"/"FLOAT"/etc.: Non-combo type widgets. See ComfyWidgets type.
* - other string: Must be an input type, usually something lke "IMAGE" or "LATENT".
*/
export type ComfyNodeDefInputType = any[] | keyof typeof ComfyWidgets | string export type ComfyNodeDefInputType = any[] | keyof typeof ComfyWidgets | string
export type ComfyNodeDefInputOptions = { export type ComfyNodeDefInputOptions = {
forceInput?: boolean forceInput?: boolean
} }
// TODO when comfy refactors // TODO if/when comfy refactors
export type ComfyNodeDefOutput = { export type ComfyNodeDefOutput = {
type: string, type: string,
name: string, name: string,

View File

@@ -61,7 +61,7 @@
} }
</script> </script>
{#if container && children} {#if container && Array.isArray(children)}
{@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(container.id)} {@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(container.id)}
<div class="container {container.attrs.direction} {container.attrs.classes} {classes.join(' ')} z-index{zIndex}" <div class="container {container.attrs.direction} {container.attrs.classes} {classes.join(' ')} z-index{zIndex}"
class:hide-block={container.attrs.containerVariant === "hidden"} class:hide-block={container.attrs.containerVariant === "hidden"}

View File

@@ -55,7 +55,7 @@
}; };
</script> </script>
{#if container && children} {#if container && Array.isArray(children)}
{@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(container.id)} {@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(container.id)}
<div class="container {container.attrs.direction} {container.attrs.classes} {classes.join(' ')} z-index{zIndex}" <div class="container {container.attrs.direction} {container.attrs.classes} {classes.join(' ')} z-index{zIndex}"
class:hide-block={container.attrs.containerVariant === "hidden"} class:hide-block={container.attrs.containerVariant === "hidden"}

View File

@@ -554,7 +554,7 @@ export default class ComfyApp {
} }
runDefaultQueueAction() { runDefaultQueueAction() {
for (const node of this.lGraph.iterateNodesInOrder()) { for (const node of this.lGraph.iterateNodesInOrderRecursive()) {
if ("onDefaultQueueAction" in node) { if ("onDefaultQueueAction" in node) {
(node as ComfyGraphNode).onDefaultQueueAction() (node as ComfyGraphNode).onDefaultQueueAction()
} }
@@ -684,8 +684,7 @@ export default class ComfyApp {
break; break;
} }
for (const n of p.workflow.nodes) { for (const node of this.lGraph.iterateNodesInOrderRecursive()) {
const node = this.lGraph.getNodeByIdRecursive(n.id);
if ("afterQueued" in node) { if ("afterQueued" in node) {
(node as ComfyGraphNode).afterQueued(p, tag); (node as ComfyGraphNode).afterQueued(p, tag);
} }

View File

@@ -9,11 +9,16 @@ function hasTag(node: LGraphNode, tag: string): boolean {
return "tags" in node.properties && node.properties.tags.indexOf(tag) !== -1 return "tags" in node.properties && node.properties.tags.indexOf(tag) !== -1
} }
function isGraphInputOutput(node: LGraphNode): boolean {
return node.is(GraphInput) || node.is(GraphOutput)
}
export function isActiveNode(node: LGraphNode, tag: string | null = null): boolean { export function isActiveNode(node: LGraphNode, tag: string | null = null): boolean {
if (!node) if (!node)
return false; return false;
if (tag && !hasTag(node, tag)) { // Check tags but not on graph inputs/outputs
if (!isGraphInputOutput(node) && (tag && !hasTag(node, tag))) {
console.debug("Skipping tagged node", tag, node.properties.tags, node) console.debug("Skipping tagged node", tag, node.properties.tags, node)
return false; return false;
} }

View File

@@ -30,6 +30,51 @@
// TODO // TODO
} }
function moveTo(delta: number | ((cur: number, total: number) => number)) {
const dragItemID = $selectionState.currentSelection[0];
const entry = $layoutState.allItems[dragItemID];
if (!entry) {
return
}
const dragItem = entry.dragItem;
const containing = entry.parent
if (containing == null || containing.type !== "container") {
return
}
const containingEntry = $layoutState.allItems[containing.id];
const oldIndex = containingEntry.children.findIndex(c => c.id === dragItem.id)
if (oldIndex === -1) {
return;
}
let newIndex: number;
if (typeof delta === "number")
newIndex = oldIndex + delta;
else
newIndex = delta(oldIndex, containingEntry.children.length);
layoutState.moveItem(dragItem, containing as ContainerLayout, newIndex)
$layoutState = $layoutState
}
function moveUp() {
moveTo(-1)
}
function moveDown() {
moveTo(1)
}
function sendToTop() {
moveTo(() => 0)
}
function sendToBottom() {
moveTo((cur: number, total: number) => total - 1)
}
function groupWidgets(horizontal: boolean) { function groupWidgets(horizontal: boolean) {
const items = $selectionState.currentSelection const items = $selectionState.currentSelection
$selectionState.currentSelection = [] $selectionState.currentSelection = []
@@ -110,6 +155,23 @@
{#if showMenu} {#if showMenu}
<Menu {...menuPos} on:click={closeMenu} on:clickoutside={closeMenu}> <Menu {...menuPos} on:click={closeMenu} on:clickoutside={closeMenu}>
<MenuOption
isDisabled={$selectionState.currentSelection.length !== 1}
on:click={() => moveUp()}
text="Move Up" />
<MenuOption
isDisabled={$selectionState.currentSelection.length !== 1}
on:click={() => moveDown()}
text="Move Down" />
<MenuOption
isDisabled={$selectionState.currentSelection.length !== 1}
on:click={() => sendToTop()}
text="Send to Top" />
<MenuOption
isDisabled={$selectionState.currentSelection.length !== 1}
on:click={() => sendToBottom()}
text="Send to Bottom" />
<MenuDivider/>
<MenuOption <MenuOption
isDisabled={$selectionState.currentSelection.length === 0} isDisabled={$selectionState.currentSelection.length === 0}
on:click={() => groupWidgets(false)} on:click={() => groupWidgets(false)}

View File

@@ -1,20 +1,12 @@
<script lang="ts"> <script lang="ts">
import { Block, BlockTitle } from "@gradio/atoms";
import uiState from "$lib/stores/uiState"; import uiState from "$lib/stores/uiState";
import selectionState from "$lib/stores/selectionState"; import selectionState from "$lib/stores/selectionState";
import WidgetContainer from "./WidgetContainer.svelte"
import BlockContainer from "./BlockContainer.svelte" import BlockContainer from "./BlockContainer.svelte"
import AccordionContainer from "./AccordionContainer.svelte" import AccordionContainer from "./AccordionContainer.svelte"
import TabsContainer from "./TabsContainer.svelte" import TabsContainer from "./TabsContainer.svelte"
import { dndzone, SHADOW_ITEM_MARKER_PROPERTY_NAME, SHADOW_PLACEHOLDER_ITEM_ID } from 'svelte-dnd-action';
import {fade} from 'svelte/transition';
// notice - fade in works fine but don't add svelte's fade-out (known issue) // notice - fade in works fine but don't add svelte's fade-out (known issue)
import {cubicIn} from 'svelte/easing'; import { type ContainerLayout } from "$lib/stores/layoutState";
import { flip } from 'svelte/animate';
import layoutState, { type ContainerLayout, type WidgetLayout, type IDragItem } from "$lib/stores/layoutState";
import { startDrag, stopDrag } from "$lib/utils"
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import { isHidden } from "$lib/widgets/utils"; import { isHidden } from "$lib/widgets/utils";
@@ -23,7 +15,7 @@
export let classes: string[] = []; export let classes: string[] = [];
export let showHandles: boolean = false; export let showHandles: boolean = false;
export let isMobile: boolean = false export let isMobile: boolean = false
let attrsChanged: Writable<boolean> | null = null; let attrsChanged: Writable<number> | null = null;
$: if (container) { $: if (container) {
attrsChanged = container.attrsChanged attrsChanged = container.attrsChanged

View File

@@ -42,11 +42,6 @@
imgElem.src = convertComfyOutputToComfyURL(value[0]) imgElem.src = convertComfyOutputToComfyURL(value[0])
} }
$: if (!(_value && _value.length > 0 && imgElem)) {
imgWidth = 1
imgHeight = 1
}
function onChange() { function onChange() {
dispatch("change", value) dispatch("change", value)
} }
@@ -119,6 +114,8 @@
uploaded = false; uploaded = false;
pending_upload = true; pending_upload = true;
imgWidth = 0;
imgHeight = 0;
old_value = _value; old_value = _value;
if (_value == null) if (_value == null)
@@ -177,9 +174,13 @@
uploaded = true; uploaded = true;
} }
$: console.warn(imgWidth, imgHeight, "IMGSIZE!!")
function handle_clear(_e: CustomEvent<null>) { function handle_clear(_e: CustomEvent<null>) {
_value = null; _value = null;
value = []; value = [];
imgWidth = 0;
imgHeight = 0;
dispatch("change", value) dispatch("change", value)
dispatch("clear") dispatch("clear")
} }

View File

@@ -68,7 +68,7 @@
} }
</script> </script>
{#if container && children} {#if container && Array.isArray(children)}
{@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(container.id)} {@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(container.id)}
<div class="container {container.attrs.direction} {container.attrs.classes} {classes.join(' ')} z-index{zIndex}" <div class="container {container.attrs.direction} {container.attrs.classes} {classes.join(' ')} z-index{zIndex}"
class:hide-block={container.attrs.containerVariant === "hidden"} class:hide-block={container.attrs.containerVariant === "hidden"}

View File

@@ -59,7 +59,7 @@ LiteGraph.registerNodeType({
class: ComfyQueueEvents, class: ComfyQueueEvents,
title: "Comfy.QueueEvents", title: "Comfy.QueueEvents",
desc: "Triggers a 'bang' event when a prompt is queued.", desc: "Triggers a 'bang' event when a prompt is queued.",
type: "actions/queue_events" type: "events/queue_events"
}) })
export interface ComfyStoreImagesActionProperties extends ComfyGraphNodeProperties { export interface ComfyStoreImagesActionProperties extends ComfyGraphNodeProperties {
@@ -469,7 +469,7 @@ export class ComfySetNodeModeAdvancedAction extends ComfyGraphNode {
} }
private getModeChanges(action: TagAction, enable: boolean, nodeChanges: Record<string, NodeMode>, widgetChanges: Record<DragItemID, boolean>) { private getModeChanges(action: TagAction, enable: boolean, nodeChanges: Record<string, NodeMode>, widgetChanges: Record<DragItemID, boolean>) {
for (const node of this.graph._nodes) { for (const node of this.graph.iterateNodesInOrderRecursive()) {
if ("tags" in node.properties) { if ("tags" in node.properties) {
const comfyNode = node as ComfyGraphNode; const comfyNode = node as ComfyGraphNode;
const hasTag = comfyNode.properties.tags.indexOf(action.tag) != -1; const hasTag = comfyNode.properties.tags.indexOf(action.tag) != -1;
@@ -482,9 +482,6 @@ export class ComfySetNodeModeAdvancedAction extends ComfyGraphNode {
newMode = NodeMode.NEVER; newMode = NodeMode.NEVER;
} }
nodeChanges[node.id] = newMode nodeChanges[node.id] = newMode
node.changeMode(newMode);
if ("notifyPropsChanged" in node)
(node as ComfyWidgetNode).notifyPropsChanged();
} }
} }
} }
@@ -530,8 +527,7 @@ export class ComfySetNodeModeAdvancedAction extends ComfyGraphNode {
} }
for (const [nodeId, newMode] of Object.entries(nodeChanges)) { for (const [nodeId, newMode] of Object.entries(nodeChanges)) {
// NOTE: Only applies to this subgraph, not parent/child graphs. this.graph.getNodeByIdRecursive(nodeId).changeMode(newMode);
this.graph.getNodeById(nodeId).changeMode(newMode);
} }
const layout = get(layoutState); const layout = get(layoutState);

View File

@@ -5,7 +5,7 @@ import { comfyFileToAnnotatedFilepath, type ComfyBoxImageMetadata } from "$lib/u
export default class ComfyPickImageNode extends ComfyGraphNode { export default class ComfyPickImageNode extends ComfyGraphNode {
static slotLayout: SlotLayout = { static slotLayout: SlotLayout = {
inputs: [ inputs: [
{ name: "images", type: "COMFYBOX_IMAGES" }, { name: "images", type: "COMFYBOX_IMAGES,COMFYBOX_IMAGE" },
], ],
outputs: [ outputs: [
{ name: "image", type: "COMFYBOX_IMAGE" }, { name: "image", type: "COMFYBOX_IMAGE" },
@@ -35,9 +35,13 @@ export default class ComfyPickImageNode extends ComfyGraphNode {
_path: string | null = null; _path: string | null = null;
_index: number = 0; _index: number = 0;
private setValue(value: ComfyBoxImageMetadata[] | null) { private setValue(value: ComfyBoxImageMetadata[] | ComfyBoxImageMetadata | null) {
if (value != null && !Array.isArray(value)) {
value = [value]
this._index = 0;
}
const changed = this._value != value; const changed = this._value != value;
this._value = value; this._value = value as ComfyBoxImageMetadata[];
if (changed) { if (changed) {
if (value && value[this._index] != null) { if (value && value[this._index] != null) {
this._image = value[this._index] this._image = value[this._index]
@@ -55,6 +59,7 @@ export default class ComfyPickImageNode extends ComfyGraphNode {
this.widthWidget.value = 0 this.widthWidget.value = 0
this.heightWidget.value = 0 this.heightWidget.value = 0
} }
console.log("SET", value, this._image, this._path)
} }
} }

View File

@@ -9,7 +9,8 @@ export interface ComfyValueControlProperties extends ComfyGraphNodeProperties {
action: "fixed" | "increment" | "decrement" | "randomize", action: "fixed" | "increment" | "decrement" | "randomize",
min: number, min: number,
max: number, max: number,
step: number step: number,
ignoreStepWhenRandom: boolean
} }
const INT_MAX = 1125899906842624; const INT_MAX = 1125899906842624;
@@ -21,7 +22,8 @@ export default class ComfyValueControl extends ComfyGraphNode {
action: "fixed", action: "fixed",
min: -INT_MAX, min: -INT_MAX,
max: INT_MAX, max: INT_MAX,
step: 1 step: 1,
ignoreStepWhenRandom: false
} }
static slotLayout: SlotLayout = { static slotLayout: SlotLayout = {
@@ -61,15 +63,11 @@ export default class ComfyValueControl extends ComfyGraphNode {
} }
override onExecute() { override onExecute() {
this.setProperty("action", this.getInputData(2) || "fixed")
this.setProperty("min", this.getInputData(3))
this.setProperty("max", this.getInputData(4))
this.setProperty("step", this.getInputData(5) || 1)
if (this._aboutToChange > 0) { if (this._aboutToChange > 0) {
this._aboutToChange -= 1; this._aboutToChange -= 1;
if (this._aboutToChange <= 0) { if (this._aboutToChange <= 0) {
const value = this._aboutToChangeValue; const value = this._aboutToChangeValue;
console.warn("ABOUTTOCHANGE", value)
this._aboutToChange = 0; this._aboutToChange = 0;
this._aboutToChangeValue = null; this._aboutToChangeValue = null;
this.triggerSlot(1, value) this.triggerSlot(1, value)
@@ -82,8 +80,26 @@ export default class ComfyValueControl extends ComfyGraphNode {
if (typeof v !== "number") if (typeof v !== "number")
return return
let min = this.properties.min let action_ = this.getInputData(2);
let max = this.properties.max if (action_ == null)
action_ = "fixed"
let min = this.getInputData(3);
if (min == null)
min = -INT_MAX
let max = this.getInputData(4);
if (max == null)
max = INT_MAX
let step = this.getInputData(5);
if (step == null)
step = 1
this.setProperty("action", action_)
this.setProperty("min", min)
this.setProperty("max", max)
this.setProperty("step", step)
min = this.properties.min
max = this.properties.max
if (min == null) min = -INT_MAX if (min == null) min = -INT_MAX
if (max == null) max = INT_MAX if (max == null) max = INT_MAX
@@ -103,7 +119,8 @@ export default class ComfyValueControl extends ComfyGraphNode {
v -= this.properties.step; v -= this.properties.step;
break; break;
case "randomize": case "randomize":
v = Math.floor(Math.random() * range) * (this.properties.step) + min; const step = this.properties.ignoreStepWhenRandom ? 1 : this.properties.step
v = Math.floor(Math.random() * range) * step + min;
default: default:
break; break;
} }

View File

@@ -113,12 +113,16 @@ export default class ComfyComboNode extends ComfyWidgetNode<string> {
const comfyInput = input as IComfyInputSlot; const comfyInput = input as IComfyInputSlot;
const otherProps = comfyInput.config; const otherProps = comfyInput.config;
console.warn("CHECK COMBO CONNECTION", otherProps, thisProps)
// Ensure combo options match // Ensure combo options match
if (!(otherProps.values instanceof Array)) if (!(otherProps.values instanceof Array))
return false; return false;
if (thisProps.values.find((v, i) => otherProps.values.indexOf(v) === -1)) if (thisProps.values.find((v, i) => otherProps.values.indexOf(v) === -1))
return false; return false;
console.warn("PASSED")
return true; return true;
} }

View File

@@ -72,6 +72,9 @@ export default class ComfyGalleryNode extends ComfyWidgetNode<ComfyBoxImageMetad
} }
override parseValue(param: any): ComfyBoxImageMetadata[] { override parseValue(param: any): ComfyBoxImageMetadata[] {
if (param == null)
return []
const meta = parseWhateverIntoImageMetadata(param) || []; const meta = parseWhateverIntoImageMetadata(param) || [];
console.debug("[ComfyGalleryNode] Received output!", param) console.debug("[ComfyGalleryNode] Received output!", param)
@@ -81,6 +84,7 @@ export default class ComfyGalleryNode extends ComfyWidgetNode<ComfyBoxImageMetad
return currentValue.concat(meta) return currentValue.concat(meta)
} }
else { else {
this.notifyPropsChanged();
return meta; return meta;
} }
} }

View File

@@ -27,6 +27,7 @@ export default class ComfyImageUploadNode extends ComfyWidgetNode<ComfyBoxImageM
override svelteComponentType = ImageUploadWidget; override svelteComponentType = ImageUploadWidget;
override defaultValue = []; override defaultValue = [];
override outputSlotName = "images";
override storeActionName = "store"; override storeActionName = "store";
override saveUserState = false; override saveUserState = false;

View File

@@ -16,6 +16,7 @@ export default class ComfyTextNode extends ComfyWidgetNode<string> {
static slotLayout: SlotLayout = { static slotLayout: SlotLayout = {
inputs: [ inputs: [
{ name: "value", type: "string" },
{ name: "store", type: BuiltInSlotType.ACTION } { name: "store", type: BuiltInSlotType.ACTION }
], ],
outputs: [ outputs: [
@@ -24,6 +25,7 @@ export default class ComfyTextNode extends ComfyWidgetNode<string> {
] ]
} }
override inputSlotName = "value";
override svelteComponentType = TextWidget override svelteComponentType = TextWidget
override defaultValue = ""; override defaultValue = "";

View File

@@ -73,12 +73,14 @@ export default abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
// shownInputProperties: string[] = [] // shownInputProperties: string[] = []
/** Names of properties to add as outputs */ /** Names of properties to add as outputs */
private shownOutputProperties: Record<string, { type: string, index: number }> = {} private shownOutputProperties: Record<string, { type: string, outputName: string }> = {}
outputProperties: { name: string, type: string }[] = [] outputProperties: { name: string, type: string }[] = []
override isBackendNode = false; override isBackendNode = false;
override serialize_widgets = true; override serialize_widgets = true;
// input slots
inputSlotName: string | null = "value";
storeActionName: string | null = "store"; storeActionName: string | null = "store";
// output slots // output slots
@@ -105,15 +107,16 @@ export default abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
} }
addPropertyAsOutput(propertyName: string, type: string) { addPropertyAsOutput(propertyName: string, type: string) {
if (this.shownOutputProperties["@" + propertyName]) if (this.shownOutputProperties[propertyName])
return; return;
if (!(propertyName in this.properties)) { if (!(propertyName in this.properties)) {
throw `No property named ${propertyName} found!` throw `No property named ${propertyName} found!`
} }
this.shownOutputProperties["@" + propertyName] = { type, index: this.outputs.length } const outputName = "@" + propertyName;
this.addOutput("@" + propertyName, type) this.shownOutputProperties[propertyName] = { type, outputName }
this.addOutput(outputName, type)
} }
formatValue(value: any): string { formatValue(value: any): string {
@@ -174,8 +177,11 @@ export default abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
override onPropertyChanged(property: string, value: any, prevValue?: any) { override onPropertyChanged(property: string, value: any, prevValue?: any) {
if (this.shownOutputProperties != null) { if (this.shownOutputProperties != null) {
const data = this.shownOutputProperties[property] const data = this.shownOutputProperties[property]
if (data) if (data) {
this.setOutputData(data.index, value) const index = this.findOutputSlotIndexByName(data.outputName)
if (index !== -1)
this.setOutputData(index, value)
}
} }
} }
@@ -183,6 +189,15 @@ export default abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
* Logic to run if this widget can be treated as output (slider, combo, text) * Logic to run if this widget can be treated as output (slider, combo, text)
*/ */
override onExecute(param: any, options: object) { override onExecute(param: any, options: object) {
if (this.inputSlotName != null) {
const inputIndex = this.findInputSlotIndexByName(this.inputSlotName)
if (inputIndex !== -1) {
const data = this.getInputData(inputIndex)
if (data != null) { // TODO can "null" be a legitimate value here?
this.setValue(data)
}
}
}
if (this.outputSlotName != null) { if (this.outputSlotName != null) {
const outputIndex = this.findOutputSlotIndexByName(this.outputSlotName) const outputIndex = this.findOutputSlotIndexByName(this.outputSlotName)
if (outputIndex !== -1) if (outputIndex !== -1)
@@ -190,7 +205,9 @@ export default abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
} }
for (const propName in this.shownOutputProperties) { for (const propName in this.shownOutputProperties) {
const data = this.shownOutputProperties[propName] const data = this.shownOutputProperties[propName]
this.setOutputData(data.index, this.properties[propName]) const index = this.findOutputSlotIndexByName(data.outputName)
if (index !== -1)
this.setOutputData(index, this.properties[propName])
} }
// Fire a pending change event after one full step of the graph has // Fire a pending change event after one full step of the graph has

View File

@@ -314,7 +314,7 @@ const ALL_ATTRIBUTES: AttributesSpecList = [
location: "widget", location: "widget",
defaultValue: "", defaultValue: "",
editable: true, editable: true,
onChanged: setNodeTitle // onChanged: setNodeTitle
}, },
{ {
name: "hidden", name: "hidden",
@@ -679,6 +679,7 @@ type LayoutStateOps = {
updateChildren: (parent: IDragItem, children: IDragItem[]) => IDragItem[], updateChildren: (parent: IDragItem, children: IDragItem[]) => IDragItem[],
nodeAdded: (node: LGraphNode, options: LGraphAddNodeOptions) => void, nodeAdded: (node: LGraphNode, options: LGraphAddNodeOptions) => void,
nodeRemoved: (node: LGraphNode, options: LGraphRemoveNodeOptions) => void, nodeRemoved: (node: LGraphNode, options: LGraphRemoveNodeOptions) => void,
moveItem: (target: IDragItem, to: ContainerLayout, index?: number) => void,
groupItems: (dragItemIDs: DragItemID[], attrs?: Partial<Attributes>) => ContainerLayout, groupItems: (dragItemIDs: DragItemID[], attrs?: Partial<Attributes>) => ContainerLayout,
ungroup: (container: ContainerLayout) => void, ungroup: (container: ContainerLayout) => void,
findLayoutEntryForNode: (nodeId: ComfyNodeID) => DragItemEntry | null, findLayoutEntryForNode: (nodeId: ComfyNodeID) => DragItemEntry | null,
@@ -922,7 +923,7 @@ function nodeRemoved(node: LGraphNode, options: LGraphRemoveNodeOptions) {
function moveItem(target: IDragItem, to: ContainerLayout, index?: number) { function moveItem(target: IDragItem, to: ContainerLayout, index?: number) {
const state = get(store) const state = get(store)
const entry = state.allItems[target.id] const entry = state.allItems[target.id]
if (entry.parent && entry.parent.id === to.id) if (!entry || (entry.parent && entry.parent.id === to.id && entry.children.indexOf(target) === index))
return; return;
if (entry.parent) { if (entry.parent) {
@@ -1175,6 +1176,7 @@ const layoutStateStore: WritableLayoutStateStore =
updateChildren, updateChildren,
nodeAdded, nodeAdded,
nodeRemoved, nodeRemoved,
moveItem,
groupItems, groupItems,
findLayoutEntryForNode, findLayoutEntryForNode,
findLayoutForNode, findLayoutForNode,

View File

@@ -206,9 +206,10 @@ export function getNodeInfo(nodeId: ComfyNodeID): string {
if (!app || !app.lGraph) if (!app || !app.lGraph)
return String(nodeId); return String(nodeId);
// TODO subgraph support const displayNodeID = nodeId ? (nodeId.split("-")[0]) : String(nodeId);
const title = app.lGraph.getNodeByIdRecursive(nodeId)?.title || String(nodeId); const title = app.lGraph.getNodeByIdRecursive(nodeId)?.title || String(nodeId);
return title + " (" + nodeId + ")" return title + " (" + displayNodeID + ")"
} }
export const debounce = (callback: Function, wait = 250) => { export const debounce = (callback: Function, wait = 250) => {

View File

@@ -3,7 +3,7 @@
import { Block } from "@gradio/atoms"; import { Block } from "@gradio/atoms";
import { TextBox } from "@gradio/form"; import { TextBox } from "@gradio/form";
import Row from "$lib/components/gradio/app/Row.svelte"; import Row from "$lib/components/gradio/app/Row.svelte";
import { get, type Writable } from "svelte/store"; import { get, writable, type Writable } from "svelte/store";
import Modal from "$lib/components/Modal.svelte"; import Modal from "$lib/components/Modal.svelte";
import { Button } from "@gradio/button"; import { Button } from "@gradio/button";
import { Embed as Klecks } from "klecks"; import { Embed as Klecks } from "klecks";
@@ -21,16 +21,18 @@
let nodeValue: Writable<ComfyBoxImageMetadata[]> | null = null; let nodeValue: Writable<ComfyBoxImageMetadata[]> | null = null;
let attrsChanged: Writable<number> | null = null; let attrsChanged: Writable<number> | null = null;
let imgWidth: number = 0; let imgWidth: Writable<number> = writable(0);
let imgHeight: number = 0; let imgHeight: Writable<number> = writable(0);
$: widget && setNodeValue(widget); $: widget && setNodeValue(widget);
$: console.warn("IMGSIZE2!!!", $imgWidth, $imgHeight)
$: if ($nodeValue && $nodeValue.length > 0) { $: if ($nodeValue && $nodeValue.length > 0) {
// TODO improve // TODO improve
if (imgWidth > 0 && imgHeight > 0) { if ($imgWidth > 0 && $imgHeight > 0) {
$nodeValue[0].width = imgWidth $nodeValue[0].width = $imgWidth
$nodeValue[0].height = imgHeight $nodeValue[0].height = $imgHeight
} }
else { else {
$nodeValue[0].width = 0 $nodeValue[0].width = 0
@@ -232,8 +234,8 @@
<div class="wrapper comfy-image-editor"> <div class="wrapper comfy-image-editor">
{#if widget.attrs.variant === "fileUpload" || isMobile} {#if widget.attrs.variant === "fileUpload" || isMobile}
<ImageUpload value={_value} <ImageUpload value={_value}
bind:imgWidth bind:imgWidth={$imgWidth}
bind:imgHeight bind:imgHeight={$imgHeight}
fileCount={"single"} fileCount={"single"}
elem_classes={[]} elem_classes={[]}
style={""} style={""}
@@ -248,8 +250,8 @@
{:else} {:else}
<div class="comfy-image-editor-panel"> <div class="comfy-image-editor-panel">
<ImageUpload value={_value} <ImageUpload value={_value}
bind:imgWidth bind:imgWidth={$imgWidth}
bind:imgHeight bind:imgHeight={$imgHeight}
fileCount={"single"} fileCount={"single"}
elem_classes={[]} elem_classes={[]}
style={""} style={""}