Various fixes/features
This commit is contained in:
Submodule litegraph updated: 2d963a609f...90cbc0fa95
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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"}
|
||||||
|
|||||||
@@ -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"}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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 = "";
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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={""}
|
||||||
|
|||||||
Reference in New Issue
Block a user