Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 48 additions & 90 deletions src/services/litegraphService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import _ from 'lodash'

import { useNodeAnimatedImage } from '@/composables/node/useNodeAnimatedImage'
import { useNodeCanvasImagePreview } from '@/composables/node/useNodeCanvasImagePreview'
import { useNodeImage, useNodeVideo } from '@/composables/node/useNodeImage'
Expand All @@ -19,8 +17,6 @@ import {
} from '@/lib/litegraph/src/litegraph'
import type {
ExportedSubgraphInstance,
ISerialisableNodeInput,
ISerialisableNodeOutput,
ISerialisedNode
} from '@/lib/litegraph/src/types/serialisation'
import type { NodeId } from '@/schemas/comfyWorkflowSchema'
Expand Down Expand Up @@ -293,51 +289,35 @@ export const useLitegraphService = () => {
* and 'localized_name' information from the original node definition.
*/
override configure(data: ISerialisedNode): void {
const RESERVED_KEYS = ['name', 'type', 'shape', 'localized_name']

// Note: input name is unique in a node definition, so we can lookup
// input by name.
const inputByName = new Map<string, ISerialisableNodeInput>(
data.inputs?.map((input) => [input.name, input]) ?? []
)
// Inputs defined by the node definition.
const definedInputNames = new Set(
this.inputs.map((input) => input.name)
)
const definedInputs = this.inputs.map((input) => {
const inputData = inputByName.get(input.name)
return inputData
? {
...inputData,
// Whether the input has associated widget follows the
// original node definition.
..._.pick(input, RESERVED_KEYS.concat('widget'))
}
: input
})
// Extra inputs that potentially dynamically added by custom js logic.
const extraInputs = data.inputs?.filter(
(input) => !definedInputNames.has(input.name)
)
data.inputs = [...definedInputs, ...(extraInputs ?? [])]
const thisInputsByName = new Map(this.inputs?.map((x) => [x.name, x]))

for (const input of data.inputs ?? []) {
const currentInput = thisInputsByName.get(input.name)
if (!currentInput) continue

input.name = currentInput.name
input.type = currentInput.type
input.shape = currentInput.shape
input.localized_name = currentInput.localized_name

// Whether the input has associated widget follows the original node
// definition.
input.widget = currentInput.widget
}

// Note: output name is not unique, so we cannot lookup output by name.
// Use index instead.
data.outputs = _.zip(this.outputs, data.outputs).map(
([output, outputData]) => {
// If there are extra outputs in the serialised node, use them directly.
// There are currently custom nodes that dynamically add outputs via
// js logic.
if (!output) return outputData as ISerialisableNodeOutput

return outputData
? {
...outputData,
..._.pick(output, RESERVED_KEYS)
}
: output
}
)
for (const [index, output] of data.outputs?.entries() ?? []) {
const currentOutput = this.outputs.at(index)
if (!currentOutput) continue

output.name = currentOutput.name
output.type = currentOutput.type
output.shape = currentOutput.shape
output.localized_name = currentOutput.localized_name
}

data.widgets_values = migrateWidgetsValues(
ComfyNode.nodeData.inputs,
Expand Down Expand Up @@ -553,57 +533,35 @@ export const useLitegraphService = () => {
* and 'localized_name' information from the original node definition.
*/
override configure(data: ISerialisedNode): void {
const RESERVED_KEYS = ['name', 'type', 'shape', 'localized_name']

// Note: input name is unique in a node definition, so we can lookup
// input by name.
const inputByName = new Map<string, ISerialisableNodeInput>(
data.inputs?.map((input) => [input.name, input]) ?? []
)
// Inputs defined by the node definition.
const definedInputNames = new Set(
this.inputs.map((input) => input.name)
)
const definedInputs = this.inputs.map((input) => {
const inputData = inputByName.get(input.name)
return inputData
? {
...inputData,
// Whether the input has associated widget follows the
// original node definition.
..._.pick(input, RESERVED_KEYS.concat('widget'))
}
: input
})
// Extra inputs that potentially dynamically added by custom js logic.
const extraInputs = data.inputs?.filter(
(input) => !definedInputNames.has(input.name)
)
data.inputs = [...definedInputs, ...(extraInputs ?? [])]
const thisInputsByName = new Map(this.inputs?.map((x) => [x.name, x]))

for (const input of data.inputs ?? []) {
const currentInput = thisInputsByName.get(input.name)
if (!currentInput) continue

input.name = currentInput.name
input.type = currentInput.type
input.shape = currentInput.shape
input.localized_name = currentInput.localized_name

// Whether the input has associated widget follows the original node
// definition.
input.widget = currentInput.widget
}

// Note: output name is not unique, so we cannot lookup output by name.
// Use index instead.
data.outputs = _.zip(this.outputs, data.outputs).map(
([output, outputData]) => {
// If there are extra outputs in the serialised node, use them directly.
// There are currently custom nodes that dynamically add outputs via
// js logic.
if (!output) return outputData as ISerialisableNodeOutput

return outputData
? {
...outputData,
..._.pick(output, RESERVED_KEYS)
}
: output
}
)

data.widgets_values = migrateWidgetsValues(
ComfyNode.nodeData.inputs,
this.widgets ?? [],
data.widgets_values ?? []
)
for (const [index, output] of data.outputs?.entries() ?? []) {
const currentOutput = this.outputs.at(index)
if (!currentOutput) continue

output.name = currentOutput.name
output.type = currentOutput.type
output.shape = currentOutput.shape
output.localized_name = currentOutput.localized_name
}

super.configure(data)
}
Expand Down
Loading