Skip to content
Open
Show file tree
Hide file tree
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
446 changes: 424 additions & 22 deletions src/core/graph/widgets/dynamicWidgets.ts

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/extensions/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import './groupNodeManage'
import './groupOptions'
import './load3d'
import './maskeditor'
import './matchType'
import './nodeTemplates'
import './noteNode'
import './previewAny'
Expand Down
155 changes: 0 additions & 155 deletions src/extensions/core/matchType.ts

This file was deleted.

17 changes: 3 additions & 14 deletions src/lib/litegraph/src/LGraphNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ export class LGraphNode
selected?: boolean
showAdvanced?: boolean

declare comfyMatchType?: Record<string, Record<string, string>>
declare comfyClass?: string
declare isVirtualNode?: boolean
applyToGraph?(extraLinks?: LLink[]): void
Expand Down Expand Up @@ -1650,19 +1651,6 @@ export class LGraphNode
this.onInputRemoved?.(slot, slot_info[0])
this.setDirtyCanvas(true, true)
}
spliceInputs(
startIndex: number,
deleteCount = -1,
...toAdd: INodeInputSlot[]
): INodeInputSlot[] {
if (deleteCount < 0) return this.inputs.splice(startIndex)
const ret = this.inputs.splice(startIndex, deleteCount, ...toAdd)
this.inputs.slice(startIndex).forEach((input, index) => {
const link = input.link && this.graph?.links?.get(input.link)
if (link) link.target_slot = startIndex + index
})
return ret
}

/**
* computes the minimum size of a node according to its inputs and output slots
Expand Down Expand Up @@ -3991,7 +3979,8 @@ export class LGraphNode
isValidTarget ||
!slot.isWidgetInputSlot ||
this.#isMouseOverWidget(this.getWidgetFromSlot(slot)) ||
slot.isConnected
slot.isConnected ||
slot.alwaysVisible
) {
ctx.globalAlpha = isValid ? editorAlpha : 0.4 * editorAlpha
slot.draw(ctx, {
Expand Down
1 change: 1 addition & 0 deletions src/lib/litegraph/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ export interface IWidgetLocator {
export interface INodeInputSlot extends INodeSlot {
link: LinkId | null
widget?: IWidgetLocator
alwaysVisible?: boolean

/**
* Internal use only; API is not finalised and may change at any time.
Expand Down
1 change: 1 addition & 0 deletions src/lib/litegraph/src/node/NodeInputSlot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'

export class NodeInputSlot extends NodeSlot implements INodeInputSlot {
link: LinkId | null
alwaysVisible?: boolean

get isWidgetInputSlot(): boolean {
return !!this.widget
Expand Down
19 changes: 13 additions & 6 deletions src/schemas/nodeDefSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ const zRemoteWidgetConfig = z.object({
timeout: z.number().gte(0).optional(),
max_retries: z.number().gte(0).optional()
})
const zWidgetTemplate = z.object({
template_id: z.string(),
allowed_types: z.string().optional()
})
const zMultiSelectOption = z.object({
placeholder: z.string().optional(),
chip: z.boolean().optional()
Expand All @@ -32,7 +28,6 @@ export const zBaseInputOptions = z
hidden: z.boolean().optional(),
advanced: z.boolean().optional(),
widgetType: z.string().optional(),
template: zWidgetTemplate.optional(),
/** Backend-only properties. */
rawLink: z.boolean().optional(),
lazy: z.boolean().optional()
Expand Down Expand Up @@ -230,9 +225,21 @@ export const zComfyNodeDef = z.object({
input_order: z.record(z.array(z.string())).optional()
})

export const zAutogrowOptions = z.object({
...zBaseInputOptions.shape,
template: z.object({
input: zComfyInputsSpec,
names: z.array(z.string()).optional(),
max: z.number().optional(),
//Backend defines as mandatory with min 1, Frontend is more forgiving
min: z.number().optional(),
prefix: z.string().optional()
})
})

export const zDynamicComboInputSpec = z.tuple([
z.literal('COMFY_DYNAMICCOMBO_V3'),
zComboInputOptions.extend({
zBaseInputOptions.extend({
options: z.array(
z.object({
inputs: zComfyInputsSpec,
Expand Down
7 changes: 6 additions & 1 deletion src/services/litegraphService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useNodeCanvasImagePreview } from '@/composables/node/useNodeCanvasImage
import { useNodeImage, useNodeVideo } from '@/composables/node/useNodeImage'
import { addWidgetPromotionOptions } from '@/core/graph/subgraph/proxyWidgetUtils'
import { showSubgraphNodeDialog } from '@/core/graph/subgraph/useSubgraphNodeDialog'
import { applyDynamicInputs } from '@/core/graph/widgets/dynamicWidgets'
import { st, t } from '@/i18n'
import {
LGraphCanvas,
Expand Down Expand Up @@ -92,7 +93,11 @@ export const useLitegraphService = () => {
const widgetConstructor = widgetStore.widgets.get(
inputSpec.widgetType ?? inputSpec.type
)
if (widgetConstructor && !inputSpec.forceInput) return
if (
(widgetConstructor && !inputSpec.forceInput) ||
applyDynamicInputs(node, inputSpec)
)
return

node.addInput(inputName, inputSpec.type, {
shape: inputSpec.isOptional ? RenderShape.HollowCircle : undefined,
Expand Down
4 changes: 4 additions & 0 deletions src/utils/typeGuardUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ 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')
}
Loading
Loading