From 5a98561fe94afcd8261ced43fde509e6a0c258a0 Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Sat, 3 Jun 2023 16:14:30 -0500 Subject: [PATCH] temp linear history mode --- src/lib/components/ComfyApp.ts | 12 +- src/lib/components/ComfyJourneyView.svelte | 175 +++++++++++++----- src/lib/components/ComfyPaneView.svelte | 1 - src/lib/components/JourneyRenderer.svelte | 119 ++++++++---- src/lib/components/Modal.svelte | 5 +- src/lib/components/PromptDisplay.svelte | 26 ++- src/lib/components/WidgetContainer.svelte | 52 +++--- src/lib/components/graph/Graph.svelte | 32 ++-- src/lib/components/graph/GraphStyles.ts | 27 ++- .../modal/RestoreParamsTable.svelte | 114 ++++++++++++ src/lib/nodes/ComfyGraphNode.ts | 2 +- src/lib/restoreParameters.ts | 31 ++-- src/lib/stores/journeyStates.ts | 12 +- src/lib/stores/uiQueueState.ts | 18 +- src/lib/stores/uiState.ts | 4 +- 15 files changed, 468 insertions(+), 162 deletions(-) create mode 100644 src/lib/components/modal/RestoreParamsTable.svelte diff --git a/src/lib/components/ComfyApp.ts b/src/lib/components/ComfyApp.ts index bb10431..008966d 100644 --- a/src/lib/components/ComfyApp.ts +++ b/src/lib/components/ComfyApp.ts @@ -612,6 +612,7 @@ export default class ComfyApp { node.onExecuted(output); } workflow.journey.onExecuted(promptID, nodeID, output, queueEntry); + workflow.journey.set(get(workflow.journey)) } } }); @@ -1032,11 +1033,14 @@ export default class ComfyApp { let journeyNode: JourneyNode | null; - if (get(uiState).autoPushJourney) { + if (get(uiState).saveHistory) { const activeNode = targetWorkflow.journey.getActiveNode(); - if (activeNode != null) { - journeyNode = targetWorkflow.journey.pushPatchOntoActive(targetWorkflow, activeNode); - } + journeyNode = targetWorkflow.journey.pushPatchOntoActive(targetWorkflow, activeNode); + + // if no patch was applied, use currently selected node for prompt image + // output purposes + if (journeyNode == null) + journeyNode = activeNode; } this.processingQueue = true; diff --git a/src/lib/components/ComfyJourneyView.svelte b/src/lib/components/ComfyJourneyView.svelte index 6322fb3..bbc227a 100644 --- a/src/lib/components/ComfyJourneyView.svelte +++ b/src/lib/components/ComfyJourneyView.svelte @@ -3,39 +3,71 @@ tree-like graph. It lets you save incremental changes to your workflow and jump between past and present sets of parameters. --> + +
- -
- -
-
+
+ {#key $journey.version} + + {/key} +
+ +
+
+ {#each MODES as [theMode, icon]} + + + {/each} +
diff --git a/src/lib/components/ComfyPaneView.svelte b/src/lib/components/ComfyPaneView.svelte index fcff94a..46f3ff6 100644 --- a/src/lib/components/ComfyPaneView.svelte +++ b/src/lib/components/ComfyPaneView.svelte @@ -32,7 +32,6 @@ ] function switchMode(newMode: ComfyPaneMode) { - console.warn("switch", mode, newMode) mode = newMode; } diff --git a/src/lib/components/JourneyRenderer.svelte b/src/lib/components/JourneyRenderer.svelte index 67a5dc3..f50e418 100644 --- a/src/lib/components/JourneyRenderer.svelte +++ b/src/lib/components/JourneyRenderer.svelte @@ -1,67 +1,115 @@ + + diff --git a/src/lib/components/Modal.svelte b/src/lib/components/Modal.svelte index 63f82a5..41688f1 100644 --- a/src/lib/components/Modal.svelte +++ b/src/lib/components/Modal.svelte @@ -37,8 +37,11 @@ on:close={close} on:cancel={doClose} on:click|self={close} + on:contextmenu|preventDefault|stopPropagation > -
+
diff --git a/src/lib/components/PromptDisplay.svelte b/src/lib/components/PromptDisplay.svelte index 88cc5d8..ab5d3f7 100644 --- a/src/lib/components/PromptDisplay.svelte +++ b/src/lib/components/PromptDisplay.svelte @@ -10,19 +10,22 @@ import type { Styles } from "@gradio/utils"; import { comfyFileToComfyBoxMetadata, comfyURLToComfyFile, countNewLines } from "$lib/utils"; import ReceiveOutputTargets from "./modal/ReceiveOutputTargets.svelte"; + import RestoreParamsTable from "./modal/RestoreParamsTable.svelte"; import workflowState, { type ComfyBoxWorkflow, type WorkflowReceiveOutputTargets } from "$lib/stores/workflowState"; import type { ComfyReceiveOutputNode } from "$lib/nodes/actions"; import type ComfyApp from "./ComfyApp"; import { TabItem, Tabs } from "@gradio/tabs"; import { type ComfyBoxStdPrompt } from "$lib/ComfyBoxStdPrompt"; import ComfyBoxStdPromptSerializer from "$lib/ComfyBoxStdPromptSerializer"; - import JsonView from "./JsonView.svelte"; - import type { ZodError } from "zod"; + import JsonView from "./JsonView.svelte"; + import type { ZodError } from "zod"; + import { concatRestoreParams, getWorkflowRestoreParams, type RestoreParamTargets, type RestoreParamWorkflowNodeTargets } from "$lib/restoreParameters"; const splitLength = 50; export let prompt: SerializedPromptInputsAll; export let workflow: SerializedAppState | null; + export let restoreParams: RestoreParamTargets = {} export let images: string[] = []; // list of image URLs to ComfyUI's /view? endpoint export let isMobile: boolean = false; export let expandAll: boolean = false; @@ -33,6 +36,14 @@ let stdPromptError: ZodError | null; $: { + restoreParams = {} + + // TODO other sources than serialized workflow + if (workflow != null) { + const workflowParams = getWorkflowRestoreParams(workflow.workflow) + restoreParams = concatRestoreParams(restoreParams, workflowParams); + } + const [result, orig] = new ComfyBoxStdPromptSerializer().serialize(prompt, workflow); if (result.success === true) { stdPrompt = result.data; @@ -44,7 +55,9 @@ } } - let selectedTab: "restore-parameters" | "send-outputs" | "standard-prompt" | "prompt" = "standard-prompt"; + type PromptDisplayTabID = "restore-parameters" | "send-outputs" | "standard-prompt" | "prompt" + + let selectedTab: PromptDisplayTabID = "restore-parameters" let selected_image: number | null = null; @@ -146,15 +159,16 @@ closeModal(); } + + function doRestoreParams(e: CustomEvent) { + }
- - Parameters - + {#if comfyBoxImages.length > 0} diff --git a/src/lib/components/WidgetContainer.svelte b/src/lib/components/WidgetContainer.svelte index 07e9eac..b9443ee 100644 --- a/src/lib/components/WidgetContainer.svelte +++ b/src/lib/components/WidgetContainer.svelte @@ -70,40 +70,34 @@ {#if container} - {#key $attrsChanged} - - {/key} + {:else if widget && widget.node} {@const edit = $uiState.uiUnlocked && $uiState.uiEditMode === "widgets"} {@const hidden = isHidden(widget)} {@const hovered = $uiState.uiUnlocked && $selectionState.currentHovered.has(widget.id)} {@const selected = $uiState.uiUnlocked && $selectionState.currentSelection.includes(widget.id)} - {#key $attrsChanged} - {#key $propsChanged} -
- -
- {#if hidden && edit} -
- {/if} - {#if showHandles || hovered} -
- {/if} - {/key} - {/key} +
+ +
+ {#if hidden && edit} +
+ {/if} + {#if showHandles || hovered} +
+ {/if} {/if} diff --git a/src/lib/nodes/ComfyGraphNode.ts b/src/lib/nodes/ComfyGraphNode.ts index e03204a..e3698e8 100644 --- a/src/lib/nodes/ComfyGraphNode.ts +++ b/src/lib/nodes/ComfyGraphNode.ts @@ -118,7 +118,7 @@ export default class ComfyGraphNode extends LGraphNode { } get dragItem(): WidgetLayout | null { - return layoutStates.getDragItemByNode(this); + return layoutStates.getDragItemByNode(this) as WidgetLayout; } get workflow(): ComfyBoxWorkflow | null { diff --git a/src/lib/restoreParameters.ts b/src/lib/restoreParameters.ts index 2274945..c350077 100644 --- a/src/lib/restoreParameters.ts +++ b/src/lib/restoreParameters.ts @@ -185,24 +185,23 @@ export function getWorkflowRestoreParamsFromWorkflow(workflow: ComfyBoxWorkflow, return result } -export function getWorkflowRestoreParams(workflow: ComfyBoxWorkflow, prompt: SerializedLGraph): RestoreParamWorkflowNodeTargets { +export function getWorkflowRestoreParams(serGraph: SerializedLGraph, noExclude: boolean = false): RestoreParamWorkflowNodeTargets { const result = {} - const graph = workflow.graph; + for (const node of serGraph.nodes) { + if (!isSerializedComfyWidgetNode(node)) + continue; - // Find nodes that correspond to *this* workflow exactly, since we can - // easily match up the nodes between each (their IDs will be the same) - for (const serNode of prompt.nodes) { - const foundNode = graph.getNodeByIdRecursive(serNode.id); - if (isComfyWidgetNode(foundNode) && foundNode.type === serNode.type) { - const finalValue = (serNode as SerializedComfyWidgetNode).comfyValue; - if (finalValue != null) { - const source: RestoreParamSourceWorkflowNode = { - type: "workflow", - finalValue, - } - result[foundNode.id] = source; + if (!noExclude && node.properties.excludeFromJourney) + continue; + + const finalValue = node.comfyValue + if (finalValue != null) { + const source: RestoreParamSourceWorkflowNode = { + type: "workflow", + finalValue, } + result[node.id] = source; } } @@ -250,10 +249,10 @@ export function getBackendRestoreParams(workflow: ComfyBoxWorkflow, prompt: Seri return result } -export default function restoreParameters(workflow: ComfyBoxWorkflow, prompt: SerializedPrompt): RestoreParamTargets { +export default function getRestoreParameters(workflow: ComfyBoxWorkflow, prompt: SerializedPrompt): RestoreParamTargets { const result = {} - const workflowParams = getWorkflowRestoreParams(workflow, prompt.workflow); + const workflowParams = getWorkflowRestoreParams(prompt.workflow); concatRestoreParams(result, workflowParams); const backendParams = getBackendRestoreParams(workflow, prompt); diff --git a/src/lib/stores/journeyStates.ts b/src/lib/stores/journeyStates.ts index 2719f83..0b7ec2e 100644 --- a/src/lib/stores/journeyStates.ts +++ b/src/lib/stores/journeyStates.ts @@ -185,7 +185,8 @@ function create() { if (activeNode == null) { // add root node if (get(store).root != null) { - return; + console.debug("[journeyStates] Root already exists") + return null; } journeyNode = addNode(workflowParams, null); if (showNotification) @@ -196,9 +197,10 @@ function create() { const patch = calculateWorkflowParamsPatch(activeNode, workflowParams); const patchedCount = Object.keys(patch).length; if (patchedCount === 0) { + console.debug("[journeyStates] Patch had no diff") if (showNotification) notify("No changes were made to active parameters yet.", { type: "warning" }) - return; + return null; } journeyNode = addNode(patch, activeNode); if (showNotification) @@ -209,6 +211,7 @@ function create() { selectNode(journeyNode); } + console.debug("[journeyStates] added node", journeyNode) return journeyNode; } @@ -268,6 +271,11 @@ function create() { return; // TODO + store.update(s => { + s.version += 1; + s.activeNodeID = journeyNode.id; + return s; + }) } return { diff --git a/src/lib/stores/uiQueueState.ts b/src/lib/stores/uiQueueState.ts index a361c22..a295478 100644 --- a/src/lib/stores/uiQueueState.ts +++ b/src/lib/stores/uiQueueState.ts @@ -89,6 +89,13 @@ function convertEntry(entry: QueueEntry, status: QueueUIEntryStatus): QueueUIEnt } } +export function getQueueEntryImages(queueEntry: QueueEntry): string[] { + return Object.values(queueEntry.outputs) + .filter(o => o.images) + .flatMap(o => o.images) + .map(convertComfyOutputToComfyURL); +} + function convertPendingEntry(entry: QueueEntry, status: QueueUIEntryStatus): QueueUIEntry { const result = convertEntry(entry, status); @@ -97,10 +104,7 @@ function convertPendingEntry(entry: QueueEntry, status: QueueUIEntryStatus): Que result.images = thumbnails.map(convertComfyOutputToComfyURL); } - const outputs = Object.values(entry.outputs) - .filter(o => o.images) - .flatMap(o => o.images) - .map(convertComfyOutputToComfyURL); + const outputs = getQueueEntryImages(entry); if (outputs) { result.images = result.images.concat(outputs) } @@ -111,11 +115,7 @@ function convertPendingEntry(entry: QueueEntry, status: QueueUIEntryStatus): Que function convertCompletedEntry(entry: CompletedQueueEntry): QueueUIEntry { const result = convertEntry(entry.entry, entry.status); - const images = Object.values(entry.entry.outputs) - .filter(o => o.images) - .flatMap(o => o.images) - .map(convertComfyOutputToComfyURL); - result.images = images + result.images = getQueueEntryImages(entry.entry) if (entry.message) result.submessage = entry.message diff --git a/src/lib/stores/uiState.ts b/src/lib/stores/uiState.ts index 5ee9a00..398616e 100644 --- a/src/lib/stores/uiState.ts +++ b/src/lib/stores/uiState.ts @@ -16,7 +16,7 @@ export type UIState = { activeError: PromptID | null - autoPushJourney: boolean + saveHistory: boolean } type UIStateOps = { @@ -38,7 +38,7 @@ const store: Writable = writable( activeError: null, - autoPushJourney: true + saveHistory: true }) function reconnecting() {