Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
34 changes: 3 additions & 31 deletions src/core/graph/widgets/dynamicWidgets.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { without } from 'es-toolkit'

import { useChainCallback } from '@/composables/functional/useChainCallback'
import { NodeSlotType } from '@/lib/litegraph/src/types/globalEnums'
import type {
Expand All @@ -10,6 +8,7 @@ import type {
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
import type { LLink } from '@/lib/litegraph/src/LLink'
import { commonType } from '@/lib/litegraph/src/utils/type'
import { transformInputSpecV1ToV2 } from '@/schemas/nodeDef/migration'
import type { ComboInputSpec, InputSpec } from '@/schemas/nodeDefSchema'
import type { InputSpec as InputSpecV2 } from '@/schemas/nodeDef/nodeDefSchemaV2'
Expand All @@ -20,7 +19,6 @@ import {
import { useLitegraphService } from '@/services/litegraphService'
import { app } from '@/scripts/app'
import type { ComfyApp } from '@/scripts/app'
import { isStrings } from '@/utils/typeGuardUtil'

const INLINE_INPUTS = false

Expand Down Expand Up @@ -244,30 +242,6 @@ function changeOutputType(
}
}

function combineTypes(...types: ISlotType[]): ISlotType | undefined {
if (!isStrings(types)) return undefined

const withoutWildcards = without(types, '*')
if (withoutWildcards.length === 0) return '*'

const typeLists: string[][] = withoutWildcards.map((type) => type.split(','))

const combinedTypes = intersection(...typeLists)
if (combinedTypes.length === 0) return undefined

return combinedTypes.join(',')
}

function intersection(...sets: string[][]): string[] {
const itemCounts: Record<string, number> = {}
for (const set of sets)
for (const item of new Set(set))
itemCounts[item] = (itemCounts[item] ?? 0) + 1
return Object.entries(itemCounts)
.filter(([, count]) => count == sets.length)
.map(([key]) => key)
}

function withComfyMatchType(node: LGraphNode): asserts node is MatchTypeNode {
if (node.comfyMatchType) return
node.comfyMatchType = {}
Expand All @@ -290,8 +264,6 @@ function withComfyMatchType(node: LGraphNode): asserts node is MatchTypeNode {
if (!matchGroup) return
if (iscon && linf) {
const { output, subgraphInput } = linf.resolve(this.graph)
//TODO: fix this bug globally. A link type (and therefore color)
//should be the combinedType of origin and target type
const connectingType = (output ?? subgraphInput)?.type
if (connectingType) linf.type = connectingType
}
Expand All @@ -316,14 +288,14 @@ function withComfyMatchType(node: LGraphNode): asserts node is MatchTypeNode {
...connectedTypes.slice(0, idx),
...connectedTypes.slice(idx + 1)
]
const combinedType = combineTypes(
const combinedType = commonType(
...otherConnected,
matchGroup[input.name]
)
if (!combinedType) throw new Error('invalid connection')
input.type = combinedType
})
const outputType = combineTypes(...connectedTypes)
const outputType = commonType(...connectedTypes)
if (!outputType) throw new Error('invalid connection')
this.outputs.forEach((output, idx) => {
if (!(outputGroups?.[idx] == matchKey)) return
Expand Down
7 changes: 5 additions & 2 deletions src/lib/litegraph/src/LGraphNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMuta
import { LayoutSource } from '@/renderer/core/layout/types'
import { adjustColor } from '@/utils/colorUtil'
import type { ColorAdjustOptions } from '@/utils/colorUtil'
import { commonType, toClass } from '@/lib/litegraph/src/utils/type'

import { SUBGRAPH_OUTPUT_ID } from '@/lib/litegraph/src/constants'
import type { DragAndScale } from './DragAndScale'
Expand Down Expand Up @@ -84,7 +85,6 @@ import { findFreeSlotOfType } from './utils/collections'
import { warnDeprecated } from './utils/feedback'
import { distributeSpace } from './utils/spaceDistribution'
import { truncateText } from './utils/textUtils'
import { toClass } from './utils/type'
import { BaseWidget } from './widgets/BaseWidget'
import { toConcreteWidget } from './widgets/widgetMap'
import type { WidgetTypeMap } from './widgets/widgetMap'
Expand Down Expand Up @@ -2832,9 +2832,12 @@ export class LGraphNode
inputNode.disconnectInput(inputIndex, true)
}

const maybeCommonType =
input.type && output.type && commonType(input.type, output.type)

const link = new LLink(
++graph.state.lastLinkId,
input.type || output.type,
maybeCommonType || input.type || output.type,
this.id,
outputIndex,
inputNode.id,
Expand Down
32 changes: 31 additions & 1 deletion src/lib/litegraph/src/utils/type.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { IColorable } from '@/lib/litegraph/src/interfaces'
import { without } from 'es-toolkit'

import type { IColorable, ISlotType } from '@/lib/litegraph/src/interfaces'

/**
* Converts a plain object to a class instance if it is not already an instance of the class.
Expand Down Expand Up @@ -26,3 +28,31 @@ export function isColorable(obj: unknown): obj is IColorable {
'getColorOption' in obj
)
}

export function commonType(...types: ISlotType[]): ISlotType | undefined {
if (!isStrings(types)) return undefined

const withoutWildcards = without(types, '*')
if (withoutWildcards.length === 0) return '*'

const typeLists: string[][] = withoutWildcards.map((type) => type.split(','))

const combinedTypes = intersection(...typeLists)
if (combinedTypes.length === 0) return undefined

return combinedTypes.join(',')
}

function intersection(...sets: string[][]): string[] {
const itemCounts: Record<string, number> = {}
for (const set of sets)
for (const item of new Set(set))
itemCounts[item] = (itemCounts[item] ?? 0) + 1
return Object.entries(itemCounts)
.filter(([, count]) => count == sets.length)
.map(([key]) => key)
}

function isStrings(types: unknown[]): types is string[] {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little conflicted about moving this here, but I think it's good enough.
+ commonType should be in litegraph and should see greater use.
+ Having litegraph reference outside code is bad.
- There's some conflation of litegraph connection types and programming types.
- The function is no longer exported. It's less clear that it's intended as utility.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intent is less important than how it's currently being used, so I support this.
If we had something that was serving as a utility and could be put into the frontend utilities package for use here, that would also be good, but YAGNI.

return types.every((t) => typeof t === 'string')
}
4 changes: 0 additions & 4 deletions src/utils/typeGuardUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,3 @@ export const isResultItemType = (
): value is ResultItemType => {
return value === 'input' || value === 'output' || value === 'temp'
}

export function isStrings(types: unknown[]): types is string[] {
return types.every((t) => typeof t === 'string')
}