mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-21 14:59:39 +00:00
[TS] Enable strict mode (#3136)
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import { LGraphCanvas, LiteGraph } from '@comfyorg/litegraph'
|
||||
import { LGraphNode, type NodeId } from '@comfyorg/litegraph/dist/LGraphNode'
|
||||
|
||||
@@ -40,9 +39,11 @@ const Workflow = {
|
||||
Registered: 1,
|
||||
InWorkflow: 2
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
isInUseGroupNode(name) {
|
||||
const id = `${PREFIX}${SEPARATOR}${name}`
|
||||
// Check if lready registered/in use in this workflow
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (app.graph.extra?.groupNodes?.[name]) {
|
||||
if (app.graph.nodes.find((n) => n.type === id)) {
|
||||
return Workflow.InUse.InWorkflow
|
||||
@@ -57,12 +58,14 @@ const Workflow = {
|
||||
if (!extra) app.graph.extra = extra = {}
|
||||
let groupNodes = extra.groupNodes
|
||||
if (!groupNodes) extra.groupNodes = groupNodes = {}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNodes[name] = data
|
||||
}
|
||||
}
|
||||
|
||||
class GroupNodeBuilder {
|
||||
nodes: LGraphNode[]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
nodeData: GroupNodeWorkflowData
|
||||
|
||||
constructor(nodes: LGraphNode[]) {
|
||||
@@ -121,15 +124,18 @@ class GroupNodeBuilder {
|
||||
}
|
||||
|
||||
getNodeData() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const storeLinkTypes = (config) => {
|
||||
// Store link types for dynamically typed nodes e.g. reroutes
|
||||
for (const link of config.links) {
|
||||
const origin = app.graph.getNodeById(link[4])
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const type = origin.outputs[link[1]].type
|
||||
link.push(type)
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const storeExternalLinks = (config) => {
|
||||
// Store any external links to the group in the config so when rebuilding we add extra slots
|
||||
config.external = []
|
||||
@@ -160,6 +166,7 @@ class GroupNodeBuilder {
|
||||
|
||||
// Use the built in copyToClipboard function to generate the node data we need
|
||||
try {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const serialised = serialise(this.nodes, app.canvas.graph)
|
||||
const config = JSON.parse(serialised)
|
||||
|
||||
@@ -186,12 +193,18 @@ export class GroupNodeConfig {
|
||||
primitiveToWidget: {}
|
||||
nodeInputs: {}
|
||||
outputVisibility: any[]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
nodeDef: ComfyNodeDef
|
||||
// @ts-expect-error fixme ts strict error
|
||||
inputs: any[]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
linksFrom: {}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
linksTo: {}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
externalFrom: {}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
constructor(name, nodeData) {
|
||||
this.name = name
|
||||
this.nodeData = nodeData
|
||||
@@ -222,6 +235,7 @@ export class GroupNodeConfig {
|
||||
category: 'group nodes' + (SEPARATOR + source),
|
||||
input: { required: {} },
|
||||
description: `Group node combining ${this.nodeData.nodes
|
||||
// @ts-expect-error fixme ts strict error
|
||||
.map((n) => n.type)
|
||||
.join(', ')}`,
|
||||
python_module: 'custom_nodes.' + this.name,
|
||||
@@ -239,8 +253,10 @@ export class GroupNodeConfig {
|
||||
}
|
||||
|
||||
for (const p of this.#convertedToProcess) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
p()
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.#convertedToProcess = null
|
||||
await app.registerNodeDef(`${PREFIX}${SEPARATOR}` + this.name, this.nodeDef)
|
||||
useNodeDefStore().addNodeDef(this.nodeDef)
|
||||
@@ -258,31 +274,43 @@ export class GroupNodeConfig {
|
||||
// Skip links outside the copy config
|
||||
if (sourceNodeId == null) continue
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!this.linksFrom[sourceNodeId]) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.linksFrom[sourceNodeId] = {}
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!this.linksFrom[sourceNodeId][sourceNodeSlot]) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.linksFrom[sourceNodeId][sourceNodeSlot] = []
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.linksFrom[sourceNodeId][sourceNodeSlot].push(l)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!this.linksTo[targetNodeId]) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.linksTo[targetNodeId] = {}
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.linksTo[targetNodeId][targetNodeSlot] = l
|
||||
}
|
||||
|
||||
if (this.nodeData.external) {
|
||||
for (const ext of this.nodeData.external) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!this.externalFrom[ext[0]]) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.externalFrom[ext[0]] = { [ext[1]]: ext[2] }
|
||||
} else {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.externalFrom[ext[0]][ext[1]] = ext[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
processNode(node, seenInputs, seenOutputs) {
|
||||
const def = this.getNodeDef(node)
|
||||
if (!def) return
|
||||
@@ -293,10 +321,13 @@ export class GroupNodeConfig {
|
||||
if (def.output?.length) this.processNodeOutputs(node, seenOutputs, def)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
getNodeDef(node) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const def = globalDefs[node.type]
|
||||
if (def) return def
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const linksFrom = this.linksFrom[node.index]
|
||||
if (node.type === 'PrimitiveNode') {
|
||||
// Skip as its not linked
|
||||
@@ -307,12 +338,14 @@ export class GroupNodeConfig {
|
||||
// Use the array items
|
||||
const source = node.outputs[0].widget.name
|
||||
const fromTypeName = this.nodeData.nodes[linksFrom['0'][0][2]].type
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const fromType = globalDefs[fromTypeName]
|
||||
const input =
|
||||
fromType.input.required[source] ?? fromType.input.optional[source]
|
||||
type = input[0]
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const def = (this.primitiveDefs[node.index] = {
|
||||
input: {
|
||||
required: {
|
||||
@@ -325,7 +358,9 @@ export class GroupNodeConfig {
|
||||
})
|
||||
return def
|
||||
} else if (node.type === 'Reroute') {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const linksTo = this.linksTo[node.index]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (linksTo && linksFrom && !this.externalFrom[node.index]?.[0]) {
|
||||
// Being used internally
|
||||
return null
|
||||
@@ -341,6 +376,7 @@ export class GroupNodeConfig {
|
||||
rerouteType = input.type
|
||||
}
|
||||
if (input.widget) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const targetDef = globalDefs[node.type]
|
||||
const targetWidget =
|
||||
targetDef.input.required[input.widget.name] ??
|
||||
@@ -373,6 +409,7 @@ export class GroupNodeConfig {
|
||||
}
|
||||
if (rerouteType === '*') {
|
||||
// Check for an external link
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const t = this.externalFrom[node.index]?.[0]
|
||||
if (t) {
|
||||
rerouteType = t
|
||||
@@ -402,10 +439,12 @@ export class GroupNodeConfig {
|
||||
)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
getInputConfig(node, inputName, seenInputs, config, extra?) {
|
||||
const customConfig = this.nodeData.config?.[node.index]?.input?.[inputName]
|
||||
let name =
|
||||
customConfig?.name ??
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.inputs?.find((inp) => inp.name === inputName)?.label ??
|
||||
inputName
|
||||
let key = name
|
||||
@@ -427,6 +466,7 @@ export class GroupNodeConfig {
|
||||
if (config[0] === 'IMAGEUPLOAD') {
|
||||
if (!extra) extra = {}
|
||||
extra.widget =
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.oldToNewWidgetMap[node.index]?.[config[1]?.widget ?? 'image'] ??
|
||||
'image'
|
||||
}
|
||||
@@ -438,19 +478,23 @@ export class GroupNodeConfig {
|
||||
return { name, config, customConfig }
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
processWidgetInputs(inputs, node, inputNames, seenInputs) {
|
||||
const slots = []
|
||||
const converted = new Map()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widgetMap = (this.oldToNewWidgetMap[node.index] = {})
|
||||
for (const inputName of inputNames) {
|
||||
if (useWidgetStore().inputIsWidget(inputs[inputName])) {
|
||||
const convertedIndex = node.inputs?.findIndex(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(inp) => inp.name === inputName && inp.widget?.name === inputName
|
||||
)
|
||||
if (convertedIndex > -1) {
|
||||
// This widget has been converted to a widget
|
||||
// We need to store this in the correct position so link ids line up
|
||||
converted.set(convertedIndex, inputName)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widgetMap[inputName] = null
|
||||
} else {
|
||||
// Normal widget
|
||||
@@ -460,8 +504,11 @@ export class GroupNodeConfig {
|
||||
seenInputs,
|
||||
inputs[inputName]
|
||||
)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeDef.input.required[name] = config
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widgetMap[inputName] = name
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.newToOldWidgetMap[name] = { node, inputName }
|
||||
}
|
||||
} else {
|
||||
@@ -472,11 +519,13 @@ export class GroupNodeConfig {
|
||||
return { converted, slots }
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
checkPrimitiveConnection(link, inputName, inputs) {
|
||||
const sourceNode = this.nodeData.nodes[link[0]]
|
||||
if (sourceNode.type === 'PrimitiveNode') {
|
||||
// Merge link configurations
|
||||
const [sourceNodeId, _, targetNodeId, __] = link
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const primitiveDef = this.primitiveDefs[sourceNodeId]
|
||||
const targetWidget = inputs[inputName]
|
||||
const primitiveConfig = primitiveDef.input.required.value
|
||||
@@ -494,13 +543,16 @@ export class GroupNodeConfig {
|
||||
? { ...inputs[inputName][1] }
|
||||
: {}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let name = this.oldToNewWidgetMap[sourceNodeId]['value']
|
||||
name = name.substr(0, name.length - 6)
|
||||
primitiveConfig[1].control_after_generate = true
|
||||
primitiveConfig[1].control_prefix = name
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let toPrimitive = this.widgetToPrimitive[targetNodeId]
|
||||
if (!toPrimitive) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
toPrimitive = this.widgetToPrimitive[targetNodeId] = {}
|
||||
}
|
||||
if (toPrimitive[inputName]) {
|
||||
@@ -508,15 +560,19 @@ export class GroupNodeConfig {
|
||||
}
|
||||
toPrimitive[inputName] = sourceNodeId
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let toWidget = this.primitiveToWidget[sourceNodeId]
|
||||
if (!toWidget) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
toWidget = this.primitiveToWidget[sourceNodeId] = []
|
||||
}
|
||||
toWidget.push({ nodeId: targetNodeId, inputName })
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
processInputSlots(inputs, node, slots, linksTo, inputMap, seenInputs) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeInputs[node.index] = {}
|
||||
for (let i = 0; i < slots.length; i++) {
|
||||
const inputName = slots[i]
|
||||
@@ -533,21 +589,30 @@ export class GroupNodeConfig {
|
||||
inputs[inputName]
|
||||
)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeInputs[node.index][inputName] = name
|
||||
if (customConfig?.visible === false) continue
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeDef.input.required[name] = config
|
||||
inputMap[i] = this.inputCount++
|
||||
}
|
||||
}
|
||||
|
||||
processConvertedWidgets(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
inputs,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
slots,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
converted,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
linksTo,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
inputMap,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
seenInputs
|
||||
) {
|
||||
// Add converted widgets sorted into their index order (ordered as they were converted) so link ids match up
|
||||
@@ -576,12 +641,17 @@ export class GroupNodeConfig {
|
||||
}
|
||||
)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeDef.input.required[name] = config
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.newToOldWidgetMap[name] = { node, inputName }
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!this.oldToNewWidgetMap[node.index]) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.oldToNewWidgetMap[node.index] = {}
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.oldToNewWidgetMap[node.index][inputName] = name
|
||||
|
||||
inputMap[slots.length + i] = this.inputCount++
|
||||
@@ -589,7 +659,9 @@ export class GroupNodeConfig {
|
||||
}
|
||||
|
||||
#convertedToProcess = []
|
||||
// @ts-expect-error fixme ts strict error
|
||||
processNodeInputs(node, seenInputs, inputs) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const inputMapping = []
|
||||
|
||||
const inputNames = Object.keys(inputs)
|
||||
@@ -601,11 +673,14 @@ export class GroupNodeConfig {
|
||||
inputNames,
|
||||
seenInputs
|
||||
)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const linksTo = this.linksTo[node.index] ?? {}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const inputMap = (this.oldToNewInputMap[node.index] = {})
|
||||
this.processInputSlots(inputs, node, slots, linksTo, inputMap, seenInputs)
|
||||
|
||||
// Converted inputs have to be processed after all other nodes as they'll be at the end of the list
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.#convertedToProcess.push(() =>
|
||||
this.processConvertedWidgets(
|
||||
inputs,
|
||||
@@ -618,17 +693,22 @@ export class GroupNodeConfig {
|
||||
)
|
||||
)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return inputMapping
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
processNodeOutputs(node, seenOutputs, def) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const oldToNew = (this.oldToNewOutputMap[node.index] = {})
|
||||
|
||||
// Add outputs
|
||||
for (let outputId = 0; outputId < def.output.length; outputId++) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const linksFrom = this.linksFrom[node.index]
|
||||
// If this output is linked internally we flag it to hide
|
||||
const hasLink =
|
||||
// @ts-expect-error fixme ts strict error
|
||||
linksFrom?.[outputId] && !this.externalFrom[node.index]?.[outputId]
|
||||
const customConfig =
|
||||
this.nodeData.config?.[node.index]?.output?.[outputId]
|
||||
@@ -638,17 +718,22 @@ export class GroupNodeConfig {
|
||||
continue
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
oldToNew[outputId] = this.nodeDef.output.length
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.newToOldOutputMap[this.nodeDef.output.length] = {
|
||||
node,
|
||||
slot: outputId
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeDef.output.push(def.output[outputId])
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeDef.output_is_list.push(def.output_is_list[outputId])
|
||||
|
||||
let label = customConfig?.name
|
||||
if (!label) {
|
||||
label = def.output_name?.[outputId] ?? def.output[outputId]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const output = node.outputs.find((o) => o.name === label)
|
||||
if (output?.label) {
|
||||
label = output.label
|
||||
@@ -665,10 +750,12 @@ export class GroupNodeConfig {
|
||||
}
|
||||
seenOutputs[name] = 1
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeDef.output_name.push(name)
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
static async registerFromWorkflow(groupNodes, missingNodeTypes) {
|
||||
for (const g in groupNodes) {
|
||||
const groupData = groupNodes[g]
|
||||
@@ -686,6 +773,7 @@ export class GroupNodeConfig {
|
||||
type: `${PREFIX}${SEPARATOR}` + g,
|
||||
action: {
|
||||
text: 'Remove from workflow',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
callback: (e) => {
|
||||
delete groupNodes[g]
|
||||
e.target.textContent = 'Removed'
|
||||
@@ -733,6 +821,7 @@ export class GroupNodeHandler {
|
||||
}
|
||||
|
||||
innerNode.index = innerNodeIndex
|
||||
// @ts-expect-error fixme ts strict error
|
||||
innerNode.getInputNode = (slot) => {
|
||||
// Check if this input is internal or external
|
||||
const externalSlot =
|
||||
@@ -752,17 +841,17 @@ export class GroupNodeHandler {
|
||||
return inputNode
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
innerNode.getInputLink = (slot) => {
|
||||
const externalSlot =
|
||||
this.groupData.oldToNewInputMap[innerNode.index]?.[slot]
|
||||
if (externalSlot != null) {
|
||||
// The inner node is connected via the group node inputs
|
||||
const linkId = this.node.inputs[externalSlot].link
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let link = app.graph.links[linkId]
|
||||
|
||||
// Use the outer link, but update the target to the inner node
|
||||
// @ts-expect-error
|
||||
// TODO: Fix this
|
||||
link = {
|
||||
...link,
|
||||
target_id: innerNode.id,
|
||||
@@ -812,10 +901,14 @@ export class GroupNodeHandler {
|
||||
|
||||
this.node.getInnerNodes = () => {
|
||||
if (!this.innerNodes) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.node.setInnerNodes(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.groupData.nodeData.nodes.map((n, i) => {
|
||||
const innerNode = LiteGraph.createNode(n.type)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
innerNode.configure(n)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
innerNode.id = `${this.node.id}:${i}`
|
||||
return innerNode
|
||||
})
|
||||
@@ -827,36 +920,50 @@ export class GroupNodeHandler {
|
||||
return this.innerNodes
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.node.recreate = async () => {
|
||||
const id = this.node.id
|
||||
const sz = this.node.size
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const nodes = this.node.convertToNodes()
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const groupNode = LiteGraph.createNode(this.node.type)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode.id = id
|
||||
|
||||
// Reuse the existing nodes for this instance
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode.setInnerNodes(nodes)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode[GROUP].populateWidgets()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
app.graph.add(groupNode)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode.setSize([
|
||||
// @ts-expect-error fixme ts strict error
|
||||
Math.max(groupNode.size[0], sz[0]),
|
||||
// @ts-expect-error fixme ts strict error
|
||||
Math.max(groupNode.size[1], sz[1])
|
||||
])
|
||||
|
||||
// Remove all converted nodes and relink them
|
||||
const builder = new GroupNodeBuilder(nodes)
|
||||
const nodeData = builder.getNodeData()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode[GROUP].groupData.nodeData.links = nodeData.links
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode[GROUP].replaceNodes(nodes)
|
||||
return groupNode
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.node.convertToNodes = () => {
|
||||
const addInnerNodes = () => {
|
||||
// Clone the node data so we dont mutate it for other nodes
|
||||
const c = { ...this.groupData.nodeData }
|
||||
c.nodes = [...c.nodes]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const innerNodes = this.node.getInnerNodes()
|
||||
let ids = []
|
||||
for (let i = 0; i < c.nodes.length; i++) {
|
||||
@@ -864,6 +971,7 @@ export class GroupNodeHandler {
|
||||
// Use existing IDs if they are set on the inner nodes
|
||||
// @ts-expect-error id can be string or number
|
||||
if (id == null || isNaN(id)) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
id = undefined
|
||||
} else {
|
||||
ids.push(id)
|
||||
@@ -886,15 +994,21 @@ export class GroupNodeHandler {
|
||||
const innerNode = innerNodes[i]
|
||||
newNodes.push(newNode)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (left == null || newNode.pos[0] < left) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
left = newNode.pos[0]
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (top == null || newNode.pos[1] < top) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
top = newNode.pos[1]
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!newNode.widgets) continue
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const map = this.groupData.oldToNewWidgetMap[innerNode.index]
|
||||
if (map) {
|
||||
const widgets = Object.keys(map)
|
||||
@@ -903,6 +1017,7 @@ export class GroupNodeHandler {
|
||||
const newName = map[oldName]
|
||||
if (!newName) continue
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widgetIndex = this.node.widgets.findIndex(
|
||||
(w) => w.name === newName
|
||||
)
|
||||
@@ -910,20 +1025,28 @@ export class GroupNodeHandler {
|
||||
|
||||
// Populate the main and any linked widgets
|
||||
if (innerNode.type === 'PrimitiveNode') {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (let i = 0; i < newNode.widgets.length; i++) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
newNode.widgets[i].value =
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.node.widgets[widgetIndex + i].value
|
||||
}
|
||||
} else {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const outerWidget = this.node.widgets[widgetIndex]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const newWidget = newNode.widgets.find(
|
||||
(w) => w.name === oldName
|
||||
)
|
||||
if (!newWidget) continue
|
||||
|
||||
newWidget.value = outerWidget.value
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (let w = 0; w < outerWidget.linkedWidgets?.length; w++) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
newWidget.linkedWidgets[w].value =
|
||||
// @ts-expect-error fixme ts strict error
|
||||
outerWidget.linkedWidgets[w].value
|
||||
}
|
||||
}
|
||||
@@ -933,13 +1056,16 @@ export class GroupNodeHandler {
|
||||
|
||||
// Shift each node
|
||||
for (const newNode of newNodes) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
newNode.pos[0] -= left - x
|
||||
// @ts-expect-error fixme ts strict error
|
||||
newNode.pos[1] -= top - y
|
||||
}
|
||||
|
||||
return { newNodes, selectedIds }
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const reconnectInputs = (selectedIds) => {
|
||||
for (const innerNodeIndex in this.groupData.oldToNewInputMap) {
|
||||
const id = selectedIds[innerNodeIndex]
|
||||
@@ -954,11 +1080,13 @@ export class GroupNodeHandler {
|
||||
if (!link) continue
|
||||
// connect this node output to the input of another node
|
||||
const originNode = app.graph.getNodeById(link.origin_id)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
originNode.connect(link.origin_slot, newNode, +innerInputId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const reconnectOutputs = (selectedIds) => {
|
||||
for (
|
||||
let groupOutputId = 0;
|
||||
@@ -973,6 +1101,7 @@ export class GroupNodeHandler {
|
||||
const link = app.graph.links[l]
|
||||
const targetNode = app.graph.getNodeById(link.target_id)
|
||||
const newNode = app.graph.getNodeById(selectedIds[slot.node.index])
|
||||
// @ts-expect-error fixme ts strict error
|
||||
newNode.connect(slot.slot, targetNode, link.target_slot)
|
||||
}
|
||||
}
|
||||
@@ -995,8 +1124,10 @@ export class GroupNodeHandler {
|
||||
const getExtraMenuOptions = this.node.getExtraMenuOptions
|
||||
// @ts-expect-error Should pass patched return value getExtraMenuOptions
|
||||
this.node.getExtraMenuOptions = function (_, options) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
getExtraMenuOptions?.apply(this, arguments)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let optionIndex = options.findIndex((o) => o.content === 'Outputs')
|
||||
if (optionIndex === -1) optionIndex = options.length
|
||||
else optionIndex++
|
||||
@@ -1008,11 +1139,13 @@ export class GroupNodeHandler {
|
||||
content: 'Convert to nodes',
|
||||
// @ts-expect-error
|
||||
callback: () => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return this.convertToNodes()
|
||||
}
|
||||
},
|
||||
{
|
||||
content: 'Manage Group Node',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
callback: () => manageGroupNodes(this.type)
|
||||
}
|
||||
)
|
||||
@@ -1021,6 +1154,7 @@ export class GroupNodeHandler {
|
||||
// Draw custom collapse icon to identity this as a group
|
||||
const onDrawTitleBox = this.node.onDrawTitleBox
|
||||
this.node.onDrawTitleBox = function (ctx, height) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onDrawTitleBox?.apply(this, arguments)
|
||||
|
||||
const fill = ctx.fillStyle
|
||||
@@ -1044,11 +1178,14 @@ export class GroupNodeHandler {
|
||||
const onDrawForeground = node.onDrawForeground
|
||||
const groupData = this.groupData.nodeData
|
||||
node.onDrawForeground = function (ctx) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onDrawForeground?.apply?.(this, arguments)
|
||||
if (
|
||||
// @ts-expect-error fixme ts strict error
|
||||
+app.runningNodeId === this.id &&
|
||||
this.runningInternalNodeId !== null
|
||||
) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const n = groupData.nodes[this.runningInternalNodeId]
|
||||
if (!n) return
|
||||
const message = `Running ${n.title || n.type} (${this.runningInternalNodeId}/${groupData.nodes.length})`
|
||||
@@ -1075,7 +1212,9 @@ export class GroupNodeHandler {
|
||||
// Flag this node as needing to be reset
|
||||
const onExecutionStart = this.node.onExecutionStart
|
||||
this.node.onExecutionStart = function () {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.resetExecution = true
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return onExecutionStart?.apply(this, arguments)
|
||||
}
|
||||
|
||||
@@ -1094,6 +1233,7 @@ export class GroupNodeHandler {
|
||||
const widgetName = self.groupData.oldToNewWidgetMap[n][w]
|
||||
const widget = this.widgets.find((w) => w.name === widgetName)
|
||||
if (widget) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget.type = 'hidden'
|
||||
widget.computeSize = () => [0, -4]
|
||||
}
|
||||
@@ -1101,21 +1241,27 @@ export class GroupNodeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return onNodeCreated?.apply(this, arguments)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function handleEvent(type, getId, getEvent) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const handler = ({ detail }) => {
|
||||
const id = getId(detail)
|
||||
if (!id) return
|
||||
const node = app.graph.getNodeById(id)
|
||||
if (node) return
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const innerNodeIndex = this.innerNodes?.findIndex((n) => n.id == id)
|
||||
if (innerNodeIndex > -1) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.node.runningInternalNodeId = innerNodeIndex
|
||||
api.dispatchCustomEvent(
|
||||
type,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
getEvent(detail, `${this.node.id}`, this.node)
|
||||
)
|
||||
}
|
||||
@@ -1127,14 +1273,18 @@ export class GroupNodeHandler {
|
||||
const executing = handleEvent.call(
|
||||
this,
|
||||
'executing',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(d) => d,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(_, id) => id
|
||||
)
|
||||
|
||||
const executed = handleEvent.call(
|
||||
this,
|
||||
'executed',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(d) => d?.display_node || d?.node,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(d, id, node) => ({
|
||||
...d,
|
||||
node: id,
|
||||
@@ -1145,6 +1295,7 @@ export class GroupNodeHandler {
|
||||
|
||||
const onRemoved = node.onRemoved
|
||||
this.node.onRemoved = function () {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onRemoved?.apply(this, arguments)
|
||||
api.removeEventListener('executing', executing)
|
||||
api.removeEventListener('executed', executed)
|
||||
@@ -1153,6 +1304,7 @@ export class GroupNodeHandler {
|
||||
this.node.refreshComboInNode = (defs) => {
|
||||
// Update combo widget options
|
||||
for (const widgetName in this.groupData.newToOldWidgetMap) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widget = this.node.widgets.find((w) => w.name === widgetName)
|
||||
if (widget?.type === 'combo') {
|
||||
const old = this.groupData.newToOldWidgetMap[widgetName]
|
||||
@@ -1169,7 +1321,9 @@ export class GroupNodeHandler {
|
||||
// @ts-expect-error Widget values
|
||||
!widget.options.values.includes(widget.value)
|
||||
) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget.value = widget.options.values[0]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget.callback(widget.value)
|
||||
}
|
||||
}
|
||||
@@ -1179,6 +1333,7 @@ export class GroupNodeHandler {
|
||||
|
||||
updateInnerWidgets() {
|
||||
for (const newWidgetName in this.groupData.newToOldWidgetMap) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const newWidget = this.node.widgets.find((w) => w.name === newWidgetName)
|
||||
if (!newWidget) continue
|
||||
|
||||
@@ -1191,6 +1346,7 @@ export class GroupNodeHandler {
|
||||
const primitiveLinked = this.groupData.primitiveToWidget[old.node.index]
|
||||
for (const linked of primitiveLinked ?? []) {
|
||||
const node = this.innerNodes[linked.nodeId]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widget = node.widgets.find((w) => w.name === linked.inputName)
|
||||
|
||||
if (widget) {
|
||||
@@ -1206,6 +1362,7 @@ export class GroupNodeHandler {
|
||||
const input = node.inputs[targetSlot]
|
||||
if (input.widget) {
|
||||
const widget = node.widgets?.find(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(w) => w.name === input.widget.name
|
||||
)
|
||||
if (widget) {
|
||||
@@ -1216,6 +1373,7 @@ export class GroupNodeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widget = innerNode.widgets?.find((w) => w.name === old.inputName)
|
||||
if (widget) {
|
||||
widget.value = newValue
|
||||
@@ -1223,12 +1381,14 @@ export class GroupNodeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
populatePrimitive(_node, nodeId, oldName) {
|
||||
// Converted widget, populate primitive if linked
|
||||
const primitiveId = this.groupData.widgetToPrimitive[nodeId]?.[oldName]
|
||||
if (primitiveId == null) return
|
||||
const targetWidgetName =
|
||||
this.groupData.oldToNewWidgetMap[primitiveId]['value']
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const targetWidgetIndex = this.node.widgets.findIndex(
|
||||
(w) => w.name === targetWidgetName
|
||||
)
|
||||
@@ -1237,6 +1397,7 @@ export class GroupNodeHandler {
|
||||
let len = primitiveNode.widgets.length
|
||||
if (
|
||||
len - 1 !==
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.node.widgets[targetWidgetIndex].linkedWidgets?.length
|
||||
) {
|
||||
// Fallback handling for if some reason the primitive has a different number of widgets
|
||||
@@ -1244,6 +1405,7 @@ export class GroupNodeHandler {
|
||||
len = 1
|
||||
}
|
||||
for (let i = 0; i < len; i++) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.node.widgets[targetWidgetIndex + i].value =
|
||||
primitiveNode.widgets[i].value
|
||||
}
|
||||
@@ -1251,6 +1413,7 @@ export class GroupNodeHandler {
|
||||
return true
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
populateReroute(node, nodeId, map) {
|
||||
if (node.type !== 'Reroute') return
|
||||
|
||||
@@ -1267,6 +1430,7 @@ export class GroupNodeHandler {
|
||||
if (v == null) return
|
||||
|
||||
const widgetName = Object.values(map)[0]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widget = this.node.widgets.find((w) => w.name === widgetName)
|
||||
if (widget) {
|
||||
widget.value = v
|
||||
@@ -1306,6 +1470,7 @@ export class GroupNodeHandler {
|
||||
) {
|
||||
// Find the inner widget and shift by the number of linked widgets as they will have been removed too
|
||||
const innerWidget = this.innerNodes[nodeId].widgets?.find(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(w) => w.name === oldName
|
||||
)
|
||||
linkedShift += innerWidget?.linkedWidgets?.length ?? 0
|
||||
@@ -1316,6 +1481,7 @@ export class GroupNodeHandler {
|
||||
|
||||
// Populate the main and any linked widget
|
||||
mainWidget.value = node.widgets_values[i + linkedShift]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (let w = 0; w < mainWidget.linkedWidgets?.length; w++) {
|
||||
this.node.widgets[widgetIndex + w + 1].value =
|
||||
node.widgets_values[i + ++linkedShift]
|
||||
@@ -1324,6 +1490,7 @@ export class GroupNodeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
replaceNodes(nodes) {
|
||||
let top
|
||||
let left
|
||||
@@ -1345,6 +1512,7 @@ export class GroupNodeHandler {
|
||||
this.node.pos = [left, top]
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
linkOutputs(originalNode, nodeId) {
|
||||
if (!originalNode.outputs) return
|
||||
|
||||
@@ -1360,6 +1528,7 @@ export class GroupNodeHandler {
|
||||
const newSlot =
|
||||
this.groupData.oldToNewOutputMap[nodeId]?.[link.origin_slot]
|
||||
if (newSlot != null) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.node.connect(newSlot, targetNode, link.target_slot)
|
||||
}
|
||||
}
|
||||
@@ -1380,6 +1549,7 @@ export class GroupNodeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
static getGroupData(node) {
|
||||
return (node.nodeData ?? node.constructor?.nodeData)?.[GROUP]
|
||||
}
|
||||
@@ -1402,17 +1572,22 @@ export class GroupNodeHandler {
|
||||
|
||||
const groupNode = LiteGraph.createNode(`${PREFIX}${SEPARATOR}${name}`)
|
||||
// Reuse the existing nodes for this instance
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode.setInnerNodes(builder.nodes)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode[GROUP].populateWidgets()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
app.graph.add(groupNode)
|
||||
|
||||
// Remove all converted nodes and relink them
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNode[GROUP].replaceNodes(builder.nodes)
|
||||
return groupNode
|
||||
}
|
||||
}
|
||||
|
||||
function addConvertToGroupOptions() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function addConvertOption(options, index) {
|
||||
const selected = Object.values(app.canvas.selected_nodes ?? {})
|
||||
const disabled =
|
||||
@@ -1425,6 +1600,7 @@ function addConvertToGroupOptions() {
|
||||
})
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function addManageOption(options, index) {
|
||||
const groups = app.graph.extra?.groupNodes
|
||||
const disabled = !groups || !Object.keys(groups).length
|
||||
@@ -1438,6 +1614,7 @@ function addConvertToGroupOptions() {
|
||||
// Add to canvas
|
||||
const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions
|
||||
LGraphCanvas.prototype.getCanvasMenuOptions = function () {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const options = getCanvasMenuOptions.apply(this, arguments)
|
||||
const index =
|
||||
options.findIndex((o) => o?.content === 'Add Group') + 1 || options.length
|
||||
@@ -1449,6 +1626,7 @@ function addConvertToGroupOptions() {
|
||||
// Add to nodes
|
||||
const getNodeMenuOptions = LGraphCanvas.prototype.getNodeMenuOptions
|
||||
LGraphCanvas.prototype.getNodeMenuOptions = function (node) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const options = getNodeMenuOptions.apply(this, arguments)
|
||||
if (!GroupNodeHandler.isGroupNode(node)) {
|
||||
const index =
|
||||
@@ -1505,6 +1683,7 @@ function manageGroupNodes(type?: string) {
|
||||
}
|
||||
|
||||
const id = 'Comfy.GroupNode'
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let globalDefs
|
||||
const ext: ComfyExtension = {
|
||||
name: id,
|
||||
@@ -1567,16 +1746,21 @@ const ext: ComfyExtension = {
|
||||
},
|
||||
nodeCreated(node) {
|
||||
if (GroupNodeHandler.isGroupNode(node)) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node[GROUP] = new GroupNodeHandler(node)
|
||||
|
||||
// Ensure group nodes pasted from other workflows are stored
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (node.title && node[GROUP]?.groupData?.nodeData) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
Workflow.storeGroupNode(node.title, node[GROUP].groupData.nodeData)
|
||||
}
|
||||
}
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
async refreshComboInNodes(defs) {
|
||||
// Re-register group nodes so new ones are created with the correct options
|
||||
// @ts-expect-error fixme ts strict error
|
||||
Object.assign(globalDefs, defs)
|
||||
const nodes = app.graph.extra?.groupNodes
|
||||
if (nodes) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import {
|
||||
type LGraphNode,
|
||||
type LGraphNodeConstructor,
|
||||
@@ -17,6 +16,7 @@ const ORDER: symbol = Symbol()
|
||||
const PREFIX = 'workflow'
|
||||
const SEPARATOR = '>'
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function merge(target, source) {
|
||||
if (typeof target === 'object' && typeof source === 'object') {
|
||||
for (const key in source) {
|
||||
@@ -35,6 +35,7 @@ function merge(target, source) {
|
||||
}
|
||||
|
||||
export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
tabs: Record<
|
||||
'Inputs' | 'Outputs' | 'Widgets',
|
||||
{ tab: HTMLAnchorElement; page: HTMLElement }
|
||||
@@ -52,22 +53,30 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
>
|
||||
>
|
||||
> = {}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
nodeItems: any[]
|
||||
app: ComfyApp
|
||||
// @ts-expect-error fixme ts strict error
|
||||
groupNodeType: LGraphNodeConstructor<LGraphNode>
|
||||
groupNodeDef: any
|
||||
groupData: any
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
innerNodesList: HTMLUListElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widgetsPage: HTMLElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
inputsPage: HTMLElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
outputsPage: HTMLElement
|
||||
draggable: any
|
||||
|
||||
get selectedNodeInnerIndex() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return +this.nodeItems[this.selectedNodeIndex].dataset.nodeindex
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
constructor(app) {
|
||||
super()
|
||||
this.app = app
|
||||
@@ -76,14 +85,18 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
}) as HTMLDialogElement
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
changeTab(tab) {
|
||||
this.tabs[this.selectedTab].tab.classList.remove('active')
|
||||
this.tabs[this.selectedTab].page.classList.remove('active')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.tabs[tab].tab.classList.add('active')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.tabs[tab].page.classList.add('active')
|
||||
this.selectedTab = tab
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
changeNode(index, force?) {
|
||||
if (!force && this.selectedNodeIndex === index) return
|
||||
|
||||
@@ -114,11 +127,13 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
this.groupData = GroupNodeHandler.getGroupData(this.groupNodeType)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
changeGroup(group, reset = true) {
|
||||
this.selectedGroup = group
|
||||
this.getGroupData()
|
||||
|
||||
const nodes = this.groupData.nodeData.nodes
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.nodeItems = nodes.map((n, i) =>
|
||||
$el(
|
||||
'li.draggable-item',
|
||||
@@ -154,6 +169,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
this.changeNode(0)
|
||||
} else {
|
||||
const items = this.draggable.getAllItems()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let index = items.findIndex((item) => item.classList.contains('selected'))
|
||||
if (index === -1) index = this.selectedNodeIndex
|
||||
this.changeNode(index, true)
|
||||
@@ -164,6 +180,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
this.draggable = new DraggableList(this.innerNodesList, 'li')
|
||||
this.draggable.addEventListener(
|
||||
'dragend',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
({ detail: { oldPosition, newPosition } }) => {
|
||||
if (oldPosition === newPosition) return
|
||||
ordered.splice(newPosition, 0, ordered.splice(oldPosition, 1)[0])
|
||||
@@ -186,6 +203,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
value: any
|
||||
}) {
|
||||
const { nodeIndex, section, prop, value } = props
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const groupMod = (this.modifications[this.selectedGroup] ??= {})
|
||||
const nodesMod = (groupMod.nodes ??= {})
|
||||
const nodeMod = (nodesMod[nodeIndex ?? this.selectedNodeInnerIndex] ??= {})
|
||||
@@ -198,10 +216,12 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
getEditElement(section, prop, value, placeholder, checked, checkable = true) {
|
||||
if (value === placeholder) value = ''
|
||||
|
||||
const mods =
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.modifications[this.selectedGroup]?.nodes?.[
|
||||
this.selectedNodeInnerIndex
|
||||
]?.[section]?.[prop]
|
||||
@@ -219,6 +239,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
value,
|
||||
placeholder,
|
||||
type: 'text',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onchange: (e) => {
|
||||
this.storeModification({
|
||||
section,
|
||||
@@ -232,6 +253,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
type: 'checkbox',
|
||||
checked,
|
||||
disabled: !checkable,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onchange: (e) => {
|
||||
this.storeModification({
|
||||
section,
|
||||
@@ -248,6 +270,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
const widgets =
|
||||
this.groupData.oldToNewWidgetMap[this.selectedNodeInnerIndex]
|
||||
const items = Object.keys(widgets ?? {})
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const type = app.graph.extra.groupNodes[this.selectedGroup]
|
||||
const config = type.config?.[this.selectedNodeInnerIndex]?.input
|
||||
this.widgetsPage.replaceChildren(
|
||||
@@ -267,9 +290,11 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
buildInputsPage() {
|
||||
const inputs = this.groupData.nodeInputs[this.selectedNodeInnerIndex]
|
||||
const items = Object.keys(inputs ?? {})
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const type = app.graph.extra.groupNodes[this.selectedGroup]
|
||||
const config = type.config?.[this.selectedNodeInnerIndex]?.input
|
||||
this.inputsPage.replaceChildren(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
...items
|
||||
.map((oldName) => {
|
||||
let value = inputs[oldName]
|
||||
@@ -299,12 +324,14 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
const groupOutputs =
|
||||
this.groupData.oldToNewOutputMap[this.selectedNodeInnerIndex]
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const type = app.graph.extra.groupNodes[this.selectedGroup]
|
||||
const config = type.config?.[this.selectedNodeInnerIndex]?.output
|
||||
const node = this.groupData.nodeData.nodes[this.selectedNodeInnerIndex]
|
||||
const checkable = node.type !== 'PrimitiveNode'
|
||||
this.outputsPage.replaceChildren(
|
||||
...outputs
|
||||
// @ts-expect-error fixme ts strict error
|
||||
.map((type, slot) => {
|
||||
const groupOutputIndex = groupOutputs?.[slot]
|
||||
const oldName = innerNodeDef.output_name?.[slot] ?? type
|
||||
@@ -327,6 +354,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
return !!outputs.length
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
show(type?) {
|
||||
const groupNodes = Object.keys(app.graph.extra?.groupNodes ?? {}).sort(
|
||||
(a, b) => a.localeCompare(b)
|
||||
@@ -348,7 +376,9 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
['Inputs', this.inputsPage],
|
||||
['Widgets', this.widgetsPage],
|
||||
['Outputs', this.outputsPage]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
].reduce((p, [name, page]: [string, HTMLElement]) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
p[name] = {
|
||||
tab: $el('a', {
|
||||
onclick: () => {
|
||||
@@ -367,6 +397,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
$el(
|
||||
'select',
|
||||
{
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onchange: (e) => {
|
||||
this.changeGroup(e.target.value)
|
||||
}
|
||||
@@ -409,6 +440,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
`Are you sure you want to remove the node: "${this.selectedGroup}"`
|
||||
)
|
||||
) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
delete app.graph.extra.groupNodes[this.selectedGroup]
|
||||
LiteGraph.unregisterNodeType(
|
||||
`${PREFIX}${SEPARATOR}` + this.selectedGroup
|
||||
@@ -427,12 +459,14 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
let recreateNodes = []
|
||||
const types = {}
|
||||
for (const g in this.modifications) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const type = app.graph.extra.groupNodes[g]
|
||||
let config = (type.config ??= {})
|
||||
|
||||
let nodeMods = this.modifications[g]?.nodes
|
||||
if (nodeMods) {
|
||||
const keys = Object.keys(nodeMods)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (nodeMods[keys[0]][ORDER]) {
|
||||
// If any node is reordered, they will all need sequencing
|
||||
const orderedNodes = []
|
||||
@@ -440,8 +474,10 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
const orderedConfig = {}
|
||||
|
||||
for (const n of keys) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const order = nodeMods[n][ORDER].order
|
||||
orderedNodes[order] = type.nodes[+n]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
orderedMods[order] = nodeMods[n]
|
||||
orderedNodes[order].index = order
|
||||
}
|
||||
@@ -462,6 +498,7 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
// Rewrite modifications
|
||||
for (const id of keys) {
|
||||
if (config[id]) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
orderedConfig[type.nodes[id].index] = config[id]
|
||||
}
|
||||
delete config[id]
|
||||
@@ -475,16 +512,20 @@ export class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
merge(config, nodeMods)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
types[g] = type
|
||||
|
||||
if (!nodesByType) {
|
||||
nodesByType = app.graph.nodes.reduce((p, n) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
p[n.type] ??= []
|
||||
// @ts-expect-error fixme ts strict error
|
||||
p[n.type].push(n)
|
||||
return p
|
||||
}, {})
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const nodes = nodesByType[`${PREFIX}${SEPARATOR}` + g]
|
||||
if (nodes) recreateNodes.push(...nodes)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import { LGraphGroup } from '@comfyorg/litegraph'
|
||||
import { LGraphCanvas } from '@comfyorg/litegraph'
|
||||
import type { LGraphNode } from '@comfyorg/litegraph'
|
||||
@@ -26,7 +25,9 @@ app.registerExtension({
|
||||
LGraphCanvas.prototype.getCanvasMenuOptions = function (
|
||||
this: LGraphCanvas
|
||||
) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const options = orig.apply(this, arguments)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const group = this.graph.getGroupOnPos(
|
||||
this.graph_mouse[0],
|
||||
this.graph_mouse[1]
|
||||
@@ -38,7 +39,9 @@ app.registerExtension({
|
||||
callback: () => {
|
||||
const group = new LGraphGroup()
|
||||
addNodesToGroup(group, this.selectedItems)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.graph.add(group)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.graph.change()
|
||||
}
|
||||
})
|
||||
@@ -56,6 +59,7 @@ app.registerExtension({
|
||||
disabled: !this.selectedItems?.size,
|
||||
callback: () => {
|
||||
addNodesToGroup(group, this.selectedItems)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.graph.change()
|
||||
}
|
||||
})
|
||||
@@ -65,6 +69,7 @@ app.registerExtension({
|
||||
return options
|
||||
} else {
|
||||
// Add a separator between the default options and the group options
|
||||
// @ts-expect-error fixme ts strict error
|
||||
options.push(null)
|
||||
}
|
||||
|
||||
@@ -85,6 +90,7 @@ app.registerExtension({
|
||||
'Comfy.GroupSelectedNodes.Padding'
|
||||
)
|
||||
group.resizeTo(group.children, padding)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.graph.change()
|
||||
}
|
||||
})
|
||||
@@ -93,6 +99,7 @@ app.registerExtension({
|
||||
content: 'Select Nodes',
|
||||
callback: () => {
|
||||
this.selectNodes(nodesInGroup)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.graph.change()
|
||||
this.canvas.focus()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import { api } from '../../scripts/api'
|
||||
import { app } from '../../scripts/app'
|
||||
import { ComfyApp } from '../../scripts/app'
|
||||
@@ -6,6 +5,7 @@ import { $el, ComfyDialog } from '../../scripts/ui'
|
||||
import { ClipspaceDialog } from './clipspace'
|
||||
|
||||
// Helper function to convert a data URL to a Blob object
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function dataURLToBlob(dataURL) {
|
||||
const parts = dataURL.split(';base64,')
|
||||
const contentType = parts[0].split(':')[1]
|
||||
@@ -18,6 +18,7 @@ function dataURLToBlob(dataURL) {
|
||||
return new Blob([arrayBuffer], { type: contentType })
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function loadImage(imagePath) {
|
||||
return new Promise((resolve) => {
|
||||
const image = new Image()
|
||||
@@ -30,6 +31,7 @@ function loadImage(imagePath) {
|
||||
})
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
async function uploadMask(filepath, formData) {
|
||||
await api
|
||||
.fetchApi('/upload/mask', {
|
||||
@@ -40,7 +42,9 @@ async function uploadMask(filepath, formData) {
|
||||
console.error('Error:', error)
|
||||
})
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']] = new Image()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src = api.apiURL(
|
||||
'/view?' +
|
||||
new URLSearchParams(filepath).toString() +
|
||||
@@ -48,12 +52,15 @@ async function uploadMask(filepath, formData) {
|
||||
app.getRandParam()
|
||||
)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (ComfyApp.clipspace.images)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']] = filepath
|
||||
|
||||
ClipspaceDialog.invalidatePreview()
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function prepare_mask(image, maskCanvas, maskCtx, maskColor) {
|
||||
// paste mask data into alpha channel
|
||||
maskCtx.drawImage(image, 0, 0, maskCanvas.width, maskCanvas.height)
|
||||
@@ -94,32 +101,55 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
static mousedown_x: number | null = null
|
||||
static mousedown_y: number | null = null
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
brush: HTMLDivElement
|
||||
maskCtx: any
|
||||
// @ts-expect-error fixme ts strict error
|
||||
maskCanvas: HTMLCanvasElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
brush_size_slider: HTMLDivElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
brush_opacity_slider: HTMLDivElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
colorButton: HTMLButtonElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
saveButton: HTMLButtonElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
zoom_ratio: number
|
||||
// @ts-expect-error fixme ts strict error
|
||||
pan_x: number
|
||||
// @ts-expect-error fixme ts strict error
|
||||
pan_y: number
|
||||
// @ts-expect-error fixme ts strict error
|
||||
imgCanvas: HTMLCanvasElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
last_display_style: string
|
||||
// @ts-expect-error fixme ts strict error
|
||||
is_visible: boolean
|
||||
// @ts-expect-error fixme ts strict error
|
||||
image: HTMLImageElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
handler_registered: boolean
|
||||
// @ts-expect-error fixme ts strict error
|
||||
brush_slider_input: HTMLInputElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
cursorX: number
|
||||
// @ts-expect-error fixme ts strict error
|
||||
cursorY: number
|
||||
// @ts-expect-error fixme ts strict error
|
||||
mousedown_pan_x: number
|
||||
// @ts-expect-error fixme ts strict error
|
||||
mousedown_pan_y: number
|
||||
// @ts-expect-error fixme ts strict error
|
||||
last_pressure: number
|
||||
// @ts-expect-error fixme ts strict error
|
||||
pointer_type: PointerType
|
||||
// @ts-expect-error fixme ts strict error
|
||||
brush_pointer_type_select: HTMLDivElement
|
||||
|
||||
static getInstance() {
|
||||
if (!MaskEditorDialogOld.instance) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
MaskEditorDialogOld.instance = new MaskEditorDialogOld()
|
||||
}
|
||||
|
||||
@@ -139,6 +169,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
return []
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
createButton(name, callback): HTMLButtonElement {
|
||||
var button = document.createElement('button')
|
||||
button.style.pointerEvents = 'auto'
|
||||
@@ -147,6 +178,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
return button
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
createLeftButton(name, callback) {
|
||||
var button = this.createButton(name, callback)
|
||||
button.style.cssFloat = 'left'
|
||||
@@ -154,6 +186,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
return button
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
createRightButton(name, callback) {
|
||||
var button = this.createButton(name, callback)
|
||||
button.style.cssFloat = 'right'
|
||||
@@ -161,6 +194,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
return button
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
createLeftSlider(self, name, callback): HTMLDivElement {
|
||||
const divElement = document.createElement('div')
|
||||
divElement.id = 'maskeditor-slider'
|
||||
@@ -195,6 +229,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
return divElement
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
createOpacitySlider(self, name, callback): HTMLDivElement {
|
||||
const divElement = document.createElement('div')
|
||||
divElement.id = 'maskeditor-opacity-slider'
|
||||
@@ -339,6 +374,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
this.brush_size_slider = this.createLeftSlider(
|
||||
self,
|
||||
'Thickness',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(event) => {
|
||||
self.brush_size = event.target.value
|
||||
self.updateBrushPreview(self)
|
||||
@@ -348,6 +384,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
this.brush_opacity_slider = this.createOpacitySlider(
|
||||
self,
|
||||
'Opacity',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(event) => {
|
||||
self.brush_opacity = event.target.value
|
||||
if (self.brush_color_mode !== 'negative') {
|
||||
@@ -482,6 +519,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
return this.element.style.display == 'block'
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
invalidateCanvas(orig_image, mask_image) {
|
||||
this.imgCanvas.width = orig_image.width
|
||||
this.imgCanvas.height = orig_image.height
|
||||
@@ -494,10 +532,12 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
willReadFrequently: true
|
||||
})
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
imgCtx.drawImage(orig_image, 0, 0, orig_image.width, orig_image.height)
|
||||
prepare_mask(mask_image, this.maskCanvas, maskCtx, this.getMaskColor())
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
async setImages(imgCanvas) {
|
||||
let self = this
|
||||
|
||||
@@ -510,6 +550,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
|
||||
// image load
|
||||
const alpha_url = new URL(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src
|
||||
)
|
||||
alpha_url.searchParams.delete('channel')
|
||||
@@ -519,6 +560,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
|
||||
// original image load
|
||||
const rgb_url = new URL(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src
|
||||
)
|
||||
rgb_url.searchParams.delete('channel')
|
||||
@@ -591,10 +633,12 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
this.imgCanvas.style.top = top
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
setEventHandler(maskCanvas) {
|
||||
const self = this
|
||||
|
||||
if (!this.handler_registered) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
maskCanvas.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault()
|
||||
})
|
||||
@@ -615,12 +659,15 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
}
|
||||
})
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
maskCanvas.addEventListener('pointerdown', (event) =>
|
||||
this.handlePointerDown(self, event)
|
||||
)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
maskCanvas.addEventListener('pointermove', (event) =>
|
||||
this.draw_move(self, event)
|
||||
)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
maskCanvas.addEventListener('touchmove', (event) =>
|
||||
this.draw_move(self, event)
|
||||
)
|
||||
@@ -726,30 +773,40 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
lasty = -1
|
||||
lasttime = 0
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
static handleKeyDown(event) {
|
||||
const self = MaskEditorDialogOld.instance
|
||||
if (event.key === ']') {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
self.brush_size = Math.min(self.brush_size + 2, 100)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
self.brush_slider_input.value = self.brush_size
|
||||
} else if (event.key === '[') {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
self.brush_size = Math.max(self.brush_size - 2, 1)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
self.brush_slider_input.value = self.brush_size
|
||||
} else if (event.key === 'Enter') {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
self.save()
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
self.updateBrushPreview(self)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
static handlePointerUp(event) {
|
||||
event.preventDefault()
|
||||
|
||||
this.mousedown_x = null
|
||||
this.mousedown_y = null
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
MaskEditorDialogOld.instance.drawing_mode = false
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
updateBrushPreview(self) {
|
||||
const brush = self.brush
|
||||
|
||||
@@ -762,6 +819,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
brush.style.top = centerY - self.brush_size * this.zoom_ratio + 'px'
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
handleWheelEvent(_, event) {
|
||||
event.preventDefault()
|
||||
|
||||
@@ -785,6 +843,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
pointMoveEvent(self, event) {
|
||||
this.cursorX = event.pageX
|
||||
this.cursorY = event.pageY
|
||||
@@ -814,10 +873,12 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
pan_move(self, event) {
|
||||
if (event.buttons == 1) {
|
||||
if (MaskEditorDialogOld.mousedown_x) {
|
||||
let deltaX = MaskEditorDialogOld.mousedown_x - event.clientX
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let deltaY = MaskEditorDialogOld.mousedown_y - event.clientY
|
||||
|
||||
self.pan_x = this.mousedown_pan_x - deltaX
|
||||
@@ -828,6 +889,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
draw_move(self, event) {
|
||||
if (event.ctrlKey || event.shiftKey) {
|
||||
return
|
||||
@@ -922,6 +984,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
} else if (
|
||||
window.TouchEvent &&
|
||||
event instanceof TouchEvent &&
|
||||
// @ts-expect-error fixme ts strict error
|
||||
diff < 20
|
||||
) {
|
||||
brush_size *= this.last_pressure
|
||||
@@ -929,6 +992,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
brush_size = this.brush_size
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (diff > 20 && !this.drawing_mode)
|
||||
// cannot tracking drawing_mode for touch event
|
||||
requestAnimationFrame(() => {
|
||||
@@ -961,6 +1025,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
handlePointerDown(self, event) {
|
||||
if (event.ctrlKey) {
|
||||
if (event.buttons == 1) {
|
||||
@@ -1010,6 +1075,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
init_shape(self, compositionOperation) {
|
||||
self.maskCtx.beginPath()
|
||||
if (compositionOperation == CompositionOperation.SourceOver) {
|
||||
@@ -1021,6 +1087,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
draw_shape(self, x, y, brush_size) {
|
||||
if (self.pointer_type === PointerType.Rect) {
|
||||
self.maskCtx.rect(
|
||||
@@ -1043,7 +1110,9 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
backupCanvas.width = this.image.width
|
||||
backupCanvas.height = this.image.height
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
backupCtx.clearRect(0, 0, backupCanvas.width, backupCanvas.height)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
backupCtx.drawImage(
|
||||
this.maskCanvas,
|
||||
0,
|
||||
@@ -1057,6 +1126,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
)
|
||||
|
||||
// paste mask data into alpha channel
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const backupData = backupCtx.getImageData(
|
||||
0,
|
||||
0,
|
||||
@@ -1074,7 +1144,9 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
backupData.data[i + 2] = 0
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
backupCtx.globalCompositeOperation = CompositionOperation.SourceOver
|
||||
// @ts-expect-error fixme ts strict error
|
||||
backupCtx.putImageData(backupData, 0, 0)
|
||||
|
||||
const formData = new FormData()
|
||||
@@ -1086,13 +1158,17 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
type: 'input'
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (ComfyApp.clipspace.images) ComfyApp.clipspace.images[0] = item
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (ComfyApp.clipspace.widgets) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const index = ComfyApp.clipspace.widgets.findIndex(
|
||||
(obj) => obj.name === 'image'
|
||||
)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (index >= 0) ComfyApp.clipspace.widgets[index].value = item
|
||||
}
|
||||
|
||||
@@ -1104,6 +1180,7 @@ export class MaskEditorDialogOld extends ComfyDialog {
|
||||
type Ref = { filename: string; subfolder?: string; type?: string }
|
||||
|
||||
const original_ref: Ref = {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
filename: original_url.searchParams.get('filename')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import { LGraphCanvas } from '@comfyorg/litegraph'
|
||||
|
||||
import { t } from '@/i18n'
|
||||
@@ -32,6 +31,7 @@ const id = 'Comfy.NodeTemplates'
|
||||
const file = 'comfy.templates.json'
|
||||
|
||||
class ManageTemplates extends ComfyDialog {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
templates: any[]
|
||||
draggedEl: HTMLElement | null
|
||||
saveVisualCue: number | null
|
||||
@@ -65,6 +65,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
const btns = super.createButtons()
|
||||
btns[0].textContent = 'Close'
|
||||
btns[0].onclick = () => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
clearTimeout(this.saveVisualCue)
|
||||
this.close()
|
||||
}
|
||||
@@ -106,11 +107,13 @@ class ManageTemplates extends ComfyDialog {
|
||||
await api.storeUserData(file, templates, { stringify: false })
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
useToastStore().addAlert(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
async importAll() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (const file of this.importInput.files) {
|
||||
if (file.type === 'application/json' || file.name.endsWith('.json')) {
|
||||
const reader = new FileReader()
|
||||
@@ -129,6 +132,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.importInput.value = null
|
||||
|
||||
this.close()
|
||||
@@ -163,6 +167,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
'div',
|
||||
{},
|
||||
this.templates.flatMap((t, i) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let nameInput
|
||||
return [
|
||||
$el(
|
||||
@@ -177,6 +182,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
gap: '5px',
|
||||
backgroundColor: 'var(--comfy-menu-bg)'
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ondragstart: (e) => {
|
||||
this.draggedEl = e.currentTarget
|
||||
e.currentTarget.style.opacity = '0.6'
|
||||
@@ -184,6 +190,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
e.dataTransfer.effectAllowed = 'move'
|
||||
e.dataTransfer.setDragImage(this.emptyImg, 0, 0)
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ondragend: (e) => {
|
||||
e.target.style.opacity = '1'
|
||||
e.currentTarget.style.border = '1px dashed transparent'
|
||||
@@ -192,7 +199,9 @@ class ManageTemplates extends ComfyDialog {
|
||||
// rearrange the elements
|
||||
this.element
|
||||
.querySelectorAll('.templateManagerRow')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
.forEach((el: HTMLElement, i) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
var prev_i = Number.parseInt(el.dataset.id)
|
||||
|
||||
if (el == this.draggedEl && prev_i != i) {
|
||||
@@ -206,6 +215,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
})
|
||||
this.store()
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ondragover: (e) => {
|
||||
e.preventDefault()
|
||||
if (e.currentTarget == this.draggedEl) return
|
||||
@@ -232,6 +242,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
style: {
|
||||
cursor: 'grab'
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onmousedown: (e) => {
|
||||
// enable dragging only from the label
|
||||
if (e.target.localName == 'label')
|
||||
@@ -246,7 +257,9 @@ class ManageTemplates extends ComfyDialog {
|
||||
transitionProperty: 'background-color',
|
||||
transitionDuration: '0s'
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onchange: (e) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
clearTimeout(this.saveVisualCue)
|
||||
var el = e.target
|
||||
var row = el.parentNode.parentNode
|
||||
@@ -262,8 +275,10 @@ class ManageTemplates extends ComfyDialog {
|
||||
el.style.backgroundColor = 'var(--comfy-input-bg)'
|
||||
}, 15)
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onkeypress: (e) => {
|
||||
var el = e.target
|
||||
// @ts-expect-error fixme ts strict error
|
||||
clearTimeout(this.saveVisualCue)
|
||||
el.style.transitionDuration = '0s'
|
||||
el.style.backgroundColor = 'var(--comfy-input-bg)'
|
||||
@@ -287,6 +302,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = $el('a', {
|
||||
href: url,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
download: (nameInput.value || t.name) + '.json',
|
||||
style: { display: 'none' },
|
||||
parent: document.body
|
||||
@@ -305,6 +321,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
color: 'red',
|
||||
fontWeight: 'normal'
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onclick: (e) => {
|
||||
const item = e.target.parentNode.parentNode
|
||||
item.parentNode.removeChild(item)
|
||||
@@ -315,6 +332,7 @@ class ManageTemplates extends ComfyDialog {
|
||||
setTimeout(function () {
|
||||
that.element
|
||||
.querySelectorAll('.templateManagerRow')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
.forEach((el: HTMLElement, i) => {
|
||||
el.dataset.id = i.toString()
|
||||
})
|
||||
@@ -336,22 +354,27 @@ app.registerExtension({
|
||||
setup() {
|
||||
const manage = new ManageTemplates()
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const clipboardAction = async (cb) => {
|
||||
// We use the clipboard functions but dont want to overwrite the current user clipboard
|
||||
// Restore it after we've run our callback
|
||||
const old = localStorage.getItem('litegrapheditor_clipboard')
|
||||
await cb()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
localStorage.setItem('litegrapheditor_clipboard', old)
|
||||
}
|
||||
|
||||
const orig = LGraphCanvas.prototype.getCanvasMenuOptions
|
||||
LGraphCanvas.prototype.getCanvasMenuOptions = function () {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const options = orig.apply(this, arguments)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
options.push(null)
|
||||
options.push({
|
||||
content: `Save Selected as Template`,
|
||||
disabled: !Object.keys(app.canvas.selected_nodes || {}).length,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
callback: async () => {
|
||||
const name = await useDialogService().prompt({
|
||||
title: t('nodeTemplates.saveAsTemplate'),
|
||||
@@ -363,6 +386,7 @@ app.registerExtension({
|
||||
clipboardAction(() => {
|
||||
app.canvas.copyToClipboard()
|
||||
let data = localStorage.getItem('litegrapheditor_clipboard')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
data = JSON.parse(data)
|
||||
const nodeIds = Object.keys(app.canvas.selected_nodes)
|
||||
for (let i = 0; i < nodeIds.length; i++) {
|
||||
@@ -414,6 +438,7 @@ app.registerExtension({
|
||||
}
|
||||
})
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
subItems.push(null, {
|
||||
content: 'Manage',
|
||||
callback: () => manage.show()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import { LGraphCanvas, LiteGraph } from '@comfyorg/litegraph'
|
||||
import { LGraphNode } from '@comfyorg/litegraph'
|
||||
|
||||
@@ -21,6 +20,7 @@ app.registerExtension({
|
||||
isVirtualNode: boolean
|
||||
|
||||
constructor(title?: string) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
super(title)
|
||||
if (!this.properties) {
|
||||
this.properties = { text: '' }
|
||||
@@ -59,6 +59,7 @@ app.registerExtension({
|
||||
groupcolor = LGraphCanvas.node_colors.yellow.groupcolor
|
||||
|
||||
constructor(title?: string) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
super(title)
|
||||
if (!this.properties) {
|
||||
this.properties = { text: '' }
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import type { IContextMenuValue } from '@comfyorg/litegraph'
|
||||
import { LGraphCanvas, LGraphNode, LiteGraph } from '@comfyorg/litegraph'
|
||||
|
||||
@@ -19,6 +18,7 @@ app.registerExtension({
|
||||
static defaultVisibility = false
|
||||
|
||||
constructor(title?: string) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
super(title)
|
||||
if (!this.properties) {
|
||||
this.properties = {}
|
||||
@@ -31,6 +31,7 @@ app.registerExtension({
|
||||
|
||||
this.onAfterGraphConfigured = function () {
|
||||
requestAnimationFrame(() => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.onConnectionsChange(LiteGraph.INPUT, null, true, null)
|
||||
})
|
||||
}
|
||||
@@ -42,19 +43,23 @@ app.registerExtension({
|
||||
if (connected && type === LiteGraph.OUTPUT) {
|
||||
// Ignore wildcard nodes as these will be updated to real types
|
||||
const types = new Set(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.outputs[0].links
|
||||
.map((l) => app.graph.links[l].type)
|
||||
.filter((t) => t !== '*')
|
||||
)
|
||||
if (types.size > 1) {
|
||||
const linksToDisconnect = []
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (let i = 0; i < this.outputs[0].links.length - 1; i++) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const linkId = this.outputs[0].links[i]
|
||||
const link = app.graph.links[linkId]
|
||||
linksToDisconnect.push(link)
|
||||
}
|
||||
for (const link of linksToDisconnect) {
|
||||
const node = app.graph.getNodeById(link.target_id)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.disconnectInput(link.target_slot)
|
||||
}
|
||||
}
|
||||
@@ -72,6 +77,7 @@ app.registerExtension({
|
||||
const link = app.graph.links[linkId]
|
||||
if (!link) return
|
||||
const node = app.graph.getNodeById(link.origin_id)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const type = node.constructor.type
|
||||
if (type === 'Reroute') {
|
||||
if (node === this) {
|
||||
@@ -85,6 +91,7 @@ app.registerExtension({
|
||||
} else {
|
||||
// We've found the end
|
||||
inputNode = currentNode
|
||||
// @ts-expect-error fixme ts strict error
|
||||
inputType = node.outputs[link.origin_slot]?.type ?? null
|
||||
break
|
||||
}
|
||||
@@ -99,8 +106,10 @@ app.registerExtension({
|
||||
const nodes: LGraphNode[] = [this]
|
||||
let outputType = null
|
||||
while (nodes.length) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
currentNode = nodes.pop()
|
||||
const outputs =
|
||||
// @ts-expect-error fixme ts strict error
|
||||
(currentNode.outputs ? currentNode.outputs[0].links : []) || []
|
||||
if (outputs.length) {
|
||||
for (const linkId of outputs) {
|
||||
@@ -110,25 +119,33 @@ app.registerExtension({
|
||||
if (!link) continue
|
||||
|
||||
const node = app.graph.getNodeById(link.target_id)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const type = node.constructor.type
|
||||
|
||||
if (type === 'Reroute') {
|
||||
// Follow reroute nodes
|
||||
// @ts-expect-error fixme ts strict error
|
||||
nodes.push(node)
|
||||
updateNodes.push(node)
|
||||
} else {
|
||||
// We've found an output
|
||||
const nodeOutType =
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.inputs &&
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.inputs[link?.target_slot] &&
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.inputs[link.target_slot].type
|
||||
? node.inputs[link.target_slot].type
|
||||
? // @ts-expect-error fixme ts strict error
|
||||
node.inputs[link.target_slot].type
|
||||
: null
|
||||
if (
|
||||
inputType &&
|
||||
// @ts-expect-error fixme ts strict error
|
||||
!LiteGraph.isValidConnection(inputType, nodeOutType)
|
||||
) {
|
||||
// The output doesnt match our input so disconnect it
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.disconnectInput(link.target_slot)
|
||||
} else {
|
||||
outputType = nodeOutType
|
||||
@@ -149,13 +166,18 @@ app.registerExtension({
|
||||
for (const node of updateNodes) {
|
||||
// If we dont have an input type we are always wildcard but we'll show the output type
|
||||
// This lets you change the output link to a different type and all nodes will update
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.outputs[0].type = inputType || '*'
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.__outputType = displayType
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.outputs[0].name = node.properties.showOutputText
|
||||
? displayType
|
||||
: ''
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.setSize(node.computeSize())
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (const l of node.outputs[0].links || []) {
|
||||
const link = app.graph.links[l]
|
||||
if (link) {
|
||||
@@ -163,6 +185,7 @@ app.registerExtension({
|
||||
|
||||
if (app.configuringGraph) continue
|
||||
const targetNode = app.graph.getNodeById(link.target_id)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const targetInput = targetNode.inputs?.[link.target_slot]
|
||||
if (targetInput?.widget) {
|
||||
const config = getWidgetConfig(targetInput)
|
||||
@@ -185,17 +208,21 @@ app.registerExtension({
|
||||
|
||||
for (const node of updateNodes) {
|
||||
if (widgetConfig && outputType) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.inputs[0].widget = { name: 'value' }
|
||||
// @ts-expect-error fixme ts strict error
|
||||
setWidgetConfig(node.inputs[0], [
|
||||
widgetType ?? displayType,
|
||||
widgetConfig
|
||||
])
|
||||
} else {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
setWidgetConfig(node.inputs[0], null)
|
||||
}
|
||||
}
|
||||
|
||||
if (inputNode) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const link = app.graph.links[inputNode.inputs[0].link]
|
||||
if (link) {
|
||||
link.color = color
|
||||
@@ -205,8 +232,11 @@ app.registerExtension({
|
||||
|
||||
this.clone = function () {
|
||||
const cloned = RerouteNode.prototype.clone.apply(this)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
cloned.removeOutput(0)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
cloned.addOutput(this.properties.showOutputText ? '*' : '', '*')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
cloned.setSize(cloned.computeSize())
|
||||
return cloned
|
||||
}
|
||||
@@ -215,6 +245,7 @@ app.registerExtension({
|
||||
this.isVirtualNode = true
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
getExtraMenuOptions(_, options): IContextMenuValue[] {
|
||||
options.unshift(
|
||||
{
|
||||
@@ -258,6 +289,7 @@ app.registerExtension({
|
||||
]
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
static setDefaultTextVisibility(visible) {
|
||||
RerouteNode.defaultVisibility = visible
|
||||
if (visible) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import { applyTextReplacements } from '@/utils/searchAndReplace'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
@@ -17,11 +16,15 @@ app.registerExtension({
|
||||
// When the SaveImage node is created we want to override the serialization of the output name widget to run our S&R
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const r = onNodeCreated
|
||||
? onNodeCreated.apply(this, arguments)
|
||||
? // @ts-expect-error fixme ts strict error
|
||||
onNodeCreated.apply(this, arguments)
|
||||
: undefined
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widget = this.widgets.find((w) => w.name === 'filename_prefix')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget.serializeValue = () => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return applyTextReplacements(app.graph.nodes, widget.value)
|
||||
}
|
||||
|
||||
@@ -32,7 +35,8 @@ app.registerExtension({
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const r = onNodeCreated
|
||||
? onNodeCreated.apply(this, arguments)
|
||||
? // @ts-expect-error fixme ts strict error
|
||||
onNodeCreated.apply(this, arguments)
|
||||
: undefined
|
||||
|
||||
if (!this.properties || !('Node name for S&R' in this.properties)) {
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
// @ts-strict-ignore
|
||||
import { LGraphCanvas, LiteGraph } from '@comfyorg/litegraph'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let touchZooming
|
||||
let touchCount = 0
|
||||
|
||||
app.registerExtension({
|
||||
name: 'Comfy.SimpleTouchSupport',
|
||||
setup() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let touchDist
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let touchTime
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let lastTouch
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let lastScale
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function getMultiTouchPos(e) {
|
||||
return Math.hypot(
|
||||
e.touches[0].clientX - e.touches[1].clientX,
|
||||
@@ -20,6 +25,7 @@ app.registerExtension({
|
||||
)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function getMultiTouchCenter(e) {
|
||||
return {
|
||||
clientX: (e.touches[0].clientX + e.touches[1].clientX) / 2,
|
||||
@@ -27,6 +33,7 @@ app.registerExtension({
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
app.canvasEl.parentElement.addEventListener(
|
||||
'touchstart',
|
||||
(e: TouchEvent) => {
|
||||
@@ -52,10 +59,12 @@ app.registerExtension({
|
||||
true
|
||||
)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
app.canvasEl.parentElement.addEventListener('touchend', (e: TouchEvent) => {
|
||||
touchCount--
|
||||
|
||||
if (e.touches?.length !== 1) touchZooming = false
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (touchTime && !e.touches?.length) {
|
||||
if (new Date().getTime() - touchTime > 600) {
|
||||
if (e.target === app.canvasEl) {
|
||||
@@ -73,10 +82,12 @@ app.registerExtension({
|
||||
}
|
||||
})
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
app.canvasEl.parentElement.addEventListener(
|
||||
'touchmove',
|
||||
(e) => {
|
||||
touchTime = null
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (e.touches?.length === 2 && lastTouch && !e.ctrlKey && !e.shiftKey) {
|
||||
e.preventDefault() // Prevent browser from zooming when two textareas are touched
|
||||
app.canvas.pointer.isDown = false
|
||||
@@ -89,6 +100,7 @@ app.registerExtension({
|
||||
|
||||
const center = getMultiTouchCenter(e)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let scale = (lastScale * newTouchDist) / touchDist
|
||||
|
||||
const newX = (center.clientX - lastTouch.clientX) / scale
|
||||
@@ -112,6 +124,7 @@ app.registerExtension({
|
||||
|
||||
const newScale = app.canvas.ds.scale
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const convertScaleToOffset = (scale) => [
|
||||
center.clientX / scale - app.canvas.ds.offset[0],
|
||||
center.clientY / scale - app.canvas.ds.offset[1]
|
||||
@@ -135,17 +148,21 @@ app.registerExtension({
|
||||
|
||||
const processMouseDown = LGraphCanvas.prototype.processMouseDown
|
||||
LGraphCanvas.prototype.processMouseDown = function () {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (touchZooming || touchCount) {
|
||||
return
|
||||
}
|
||||
app.canvas.pointer.isDown = false // Prevent context menu from opening on second tap
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return processMouseDown.apply(this, arguments)
|
||||
}
|
||||
|
||||
const processMouseMove = LGraphCanvas.prototype.processMouseMove
|
||||
LGraphCanvas.prototype.processMouseMove = function () {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (touchZooming || touchCount > 1) {
|
||||
return
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return processMouseMove.apply(this, arguments)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import type { IWidget, LGraphNode } from '@comfyorg/litegraph'
|
||||
import type { IStringWidget } from '@comfyorg/litegraph/dist/types/widgets'
|
||||
|
||||
@@ -64,7 +63,9 @@ async function uploadFile(
|
||||
let path = data.name
|
||||
if (data.subfolder) path = data.subfolder + '/' + path
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!audioWidget.options.values.includes(path)) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
audioWidget.options.values.push(path)
|
||||
}
|
||||
|
||||
@@ -78,6 +79,7 @@ async function uploadFile(
|
||||
useToastStore().addAlert(resp.status + ' - ' + resp.statusText)
|
||||
}
|
||||
} catch (error) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
useToastStore().addAlert(error)
|
||||
}
|
||||
}
|
||||
@@ -89,9 +91,11 @@ app.registerExtension({
|
||||
async beforeRegisterNodeDef(nodeType, nodeData) {
|
||||
if (
|
||||
['LoadAudio', 'SaveAudio', 'PreviewAudio'].includes(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
nodeType.prototype.comfyClass
|
||||
)
|
||||
) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
nodeData.input.required.audioUI = ['AUDIO_UI', {}]
|
||||
}
|
||||
},
|
||||
@@ -115,6 +119,7 @@ app.registerExtension({
|
||||
// Populate the audio widget UI on node execution.
|
||||
const onExecuted = node.onExecuted
|
||||
node.onExecuted = function (message: any) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onExecuted?.apply(this, arguments)
|
||||
const audios = message.audio
|
||||
if (!audios) return
|
||||
@@ -133,6 +138,7 @@ app.registerExtension({
|
||||
for (const [nodeId, output] of Object.entries(nodeOutputs)) {
|
||||
const node = app.graph.getNodeById(nodeId)
|
||||
if ('audio' in output) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const audioUIWidget = node.widgets.find(
|
||||
(w) => w.name === 'audioUI'
|
||||
) as unknown as DOMWidget<HTMLAudioElement, string>
|
||||
@@ -157,9 +163,11 @@ app.registerExtension({
|
||||
return {
|
||||
AUDIOUPLOAD(node, inputName: string) {
|
||||
// The widget that allows user to select file.
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const audioWidget = node.widgets.find(
|
||||
(w: IWidget) => w.name === 'audio'
|
||||
) as IStringWidget
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const audioUIWidget = node.widgets.find(
|
||||
(w: IWidget) => w.name === 'audioUI'
|
||||
) as unknown as DOMWidget<HTMLAudioElement, string>
|
||||
@@ -178,6 +186,7 @@ app.registerExtension({
|
||||
// Load saved audio file widget values if restoring from workflow
|
||||
const onGraphConfigured = node.onGraphConfigured
|
||||
node.onGraphConfigured = function () {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onGraphConfigured?.apply(this, arguments)
|
||||
if (audioWidget.value) {
|
||||
onAudioWidgetUpdate()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import { t } from '@/i18n'
|
||||
import { useToastStore } from '@/stores/toastStore'
|
||||
|
||||
@@ -12,7 +11,9 @@ app.registerExtension({
|
||||
getCustomWidgets() {
|
||||
return {
|
||||
WEBCAM(node, inputName) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let res
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node[WEBCAM_READY] = new Promise((resolve) => (res = resolve))
|
||||
|
||||
const container = document.createElement('div')
|
||||
@@ -30,7 +31,9 @@ app.registerExtension({
|
||||
})
|
||||
container.replaceChildren(video)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
setTimeout(() => res(video), 500) // Fallback as loadedmetadata doesnt fire sometimes?
|
||||
// @ts-expect-error fixme ts strict error
|
||||
video.addEventListener('loadedmetadata', () => res(video), false)
|
||||
video.srcObject = stream
|
||||
video.play()
|
||||
@@ -44,10 +47,12 @@ app.registerExtension({
|
||||
if (window.isSecureContext) {
|
||||
label.textContent =
|
||||
'Unable to load webcam, please ensure access is granted:\n' +
|
||||
// @ts-expect-error fixme ts strict error
|
||||
error.message
|
||||
} else {
|
||||
label.textContent =
|
||||
'Unable to load webcam. A secure context is required, if you are not accessing ComfyUI on localhost (127.0.0.1) you will have to enable TLS (https)\n\n' +
|
||||
// @ts-expect-error fixme ts strict error
|
||||
error.message
|
||||
}
|
||||
|
||||
@@ -64,10 +69,15 @@ app.registerExtension({
|
||||
nodeCreated(node) {
|
||||
if ((node.type, node.constructor.comfyClass !== 'WebcamCapture')) return
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let video
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const camera = node.widgets.find((w) => w.name === 'image')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const w = node.widgets.find((w) => w.name === 'width')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const h = node.widgets.find((w) => w.name === 'height')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const captureOnQueue = node.widgets.find(
|
||||
(w) => w.name === 'capture_on_queue'
|
||||
)
|
||||
@@ -101,7 +111,9 @@ app.registerExtension({
|
||||
btn.disabled = true
|
||||
btn.serializeValue = () => undefined
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
camera.serializeValue = async () => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (captureOnQueue.value) {
|
||||
capture()
|
||||
} else if (!node.imgs?.length) {
|
||||
@@ -111,6 +123,7 @@ app.registerExtension({
|
||||
}
|
||||
|
||||
// Upload image to temp storage
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const blob = await new Promise<Blob>((r) => canvas.toBlob(r))
|
||||
const name = `${+new Date()}.png`
|
||||
const file = new File([blob], name)
|
||||
@@ -130,11 +143,15 @@ app.registerExtension({
|
||||
return `webcam/${name} [temp]`
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node[WEBCAM_READY].then((v) => {
|
||||
video = v
|
||||
// If width isnt specified then use video output resolution
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!w.value) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
w.value = video.videoWidth || 640
|
||||
// @ts-expect-error fixme ts strict error
|
||||
h.value = video.videoHeight || 480
|
||||
}
|
||||
btn.disabled = false
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import { LGraphNode, LiteGraph } from '@comfyorg/litegraph'
|
||||
import type {
|
||||
IFoundSlot,
|
||||
@@ -35,10 +34,13 @@ const GET_CONFIG = Symbol()
|
||||
|
||||
const replacePropertyName = 'Run widget replace on values'
|
||||
export class PrimitiveNode extends LGraphNode {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
controlValues: any[]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
lastType: string
|
||||
static category: string
|
||||
constructor(title?: string) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
super(title)
|
||||
this.addOutput('connect to widget input', '*')
|
||||
this.serialize_widgets = true
|
||||
@@ -63,11 +65,14 @@ export class PrimitiveNode extends LGraphNode {
|
||||
|
||||
// For each output link copy our value over the original widget value
|
||||
for (const linkInfo of links) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const node = this.graph.getNodeById(linkInfo.target_id)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const input = node.inputs[linkInfo.target_slot]
|
||||
let widget: IWidget | undefined
|
||||
const widgetName = (input.widget as { name: string }).name
|
||||
if (widgetName) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget = node.widgets.find((w) => w.name === widgetName)
|
||||
}
|
||||
|
||||
@@ -77,6 +82,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
widget.callback(
|
||||
widget.value,
|
||||
app.canvas,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node,
|
||||
app.canvas.graph_mouse,
|
||||
{} as CanvasMouseEvent
|
||||
@@ -91,7 +97,9 @@ export class PrimitiveNode extends LGraphNode {
|
||||
if (widget?.type === 'combo') {
|
||||
widget.options.values = this.outputs[0].widget[GET_CONFIG]()[0]
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!widget.options.values.includes(widget.value as string)) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget.value = widget.options.values[0]
|
||||
;(widget.callback as Function)(widget.value)
|
||||
}
|
||||
@@ -106,6 +114,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
|
||||
// Populate widget values from config data
|
||||
if (this.widgets) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (let i = 0; i < this.widgets_values.length; i++) {
|
||||
const w = this.widgets[i]
|
||||
if (w) {
|
||||
@@ -141,6 +150,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onConnectOutput(
|
||||
slot: number,
|
||||
_type: string,
|
||||
@@ -171,9 +181,11 @@ export class PrimitiveNode extends LGraphNode {
|
||||
return
|
||||
}
|
||||
const linkId = this.outputs[0].links[0]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const link = this.graph.links[linkId]
|
||||
if (!link) return
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const theirNode = this.graph.getNodeById(link.target_id)
|
||||
if (!theirNode || !theirNode.inputs) return
|
||||
|
||||
@@ -188,6 +200,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
widget = input.widget
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const config = widget[GET_CONFIG]?.()
|
||||
if (!config) return
|
||||
|
||||
@@ -198,9 +211,11 @@ export class PrimitiveNode extends LGraphNode {
|
||||
this.outputs[0].widget = widget
|
||||
|
||||
this.#createWidget(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget[CONFIG] ?? config,
|
||||
theirNode,
|
||||
widget.name,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
recreating
|
||||
)
|
||||
}
|
||||
@@ -221,6 +236,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
const [oldWidth, oldHeight] = this.size
|
||||
let widget: IWidget | undefined
|
||||
if (type in ComfyWidgets) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget = (ComfyWidgets[type](this, 'value', inputData, app) || {}).widget
|
||||
} else {
|
||||
// @ts-expect-error InputSpec is not typed correctly
|
||||
@@ -243,6 +259,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
control_value = 'fixed'
|
||||
}
|
||||
addValueControlWidgets(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this,
|
||||
widget,
|
||||
control_value as string,
|
||||
@@ -250,6 +267,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
inputData
|
||||
)
|
||||
let filter = this.widgets_values?.[2]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (filter && this.widgets.length === 3) {
|
||||
// @ts-expect-error change widget type from string to unknown
|
||||
this.widgets[2].value = filter
|
||||
@@ -259,10 +277,13 @@ export class PrimitiveNode extends LGraphNode {
|
||||
// Restore any saved control values
|
||||
const controlValues = this.controlValues
|
||||
if (
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.lastType === this.widgets[0].type &&
|
||||
// @ts-expect-error fixme ts strict error
|
||||
controlValues?.length === this.widgets.length - 1
|
||||
) {
|
||||
for (let i = 0; i < controlValues.length; i++) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.widgets[i + 1].value = controlValues[i]
|
||||
}
|
||||
}
|
||||
@@ -272,6 +293,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
const callback = widget.callback
|
||||
const self = this
|
||||
widget.callback = function () {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const r = callback ? callback.apply(this, arguments) : undefined
|
||||
self.applyToGraph()
|
||||
return r
|
||||
@@ -295,6 +317,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
if (this.onResize) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.onResize(this.size)
|
||||
}
|
||||
})
|
||||
@@ -306,7 +329,9 @@ export class PrimitiveNode extends LGraphNode {
|
||||
this.#removeWidgets()
|
||||
this.#onFirstConnection(true)
|
||||
if (values?.length) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (let i = 0; i < this.widgets?.length; i++)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.widgets[i].value = values[i]
|
||||
}
|
||||
return this.widgets?.[0]
|
||||
@@ -322,8 +347,10 @@ export class PrimitiveNode extends LGraphNode {
|
||||
delete output.widget[CONFIG]
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (links?.length < 2 && hasConfig) {
|
||||
// Copy the widget options from the source
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (links.length) {
|
||||
this.recreateWidget()
|
||||
}
|
||||
@@ -335,11 +362,13 @@ export class PrimitiveNode extends LGraphNode {
|
||||
const isNumber = config1[0] === 'INT' || config1[0] === 'FLOAT'
|
||||
if (!isNumber) return
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (const linkId of links) {
|
||||
const link = app.graph.links[linkId]
|
||||
if (!link) continue // Can be null when removing a node
|
||||
|
||||
const theirNode = app.graph.getNodeById(link.target_id)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const theirInput = theirNode.inputs[link.target_slot]
|
||||
|
||||
// Call is valid connection so it can merge the configs when validating
|
||||
@@ -370,6 +399,7 @@ export class PrimitiveNode extends LGraphNode {
|
||||
#isValidConnection(input: INodeInputSlot, forceUpdate?: boolean) {
|
||||
// Only allow connections where the configs match
|
||||
const output = this.outputs[0]
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const config2 = input.widget[GET_CONFIG]()
|
||||
return !!mergeIfValid.call(
|
||||
this,
|
||||
@@ -397,7 +427,9 @@ export class PrimitiveNode extends LGraphNode {
|
||||
this.controlValues.push(this.widgets[i].value)
|
||||
}
|
||||
setTimeout(() => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
delete this.lastType
|
||||
// @ts-expect-error fixme ts strict error
|
||||
delete this.controlValues
|
||||
}, 15)
|
||||
this.widgets.length = 0
|
||||
@@ -420,6 +452,7 @@ export function getWidgetConfig(slot: INodeInputSlot | INodeOutputSlot) {
|
||||
}
|
||||
|
||||
function getConfig(widgetName: string) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const { nodeData } = this.constructor
|
||||
return (
|
||||
nodeData?.input?.required?.[widgetName] ??
|
||||
@@ -513,7 +546,9 @@ export function convertToInput(
|
||||
...(inputIsOptional ? { shape: LiteGraph.SlotShape.HollowCircle } : {})
|
||||
})
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (const widget of node.widgets) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget.last_y += LiteGraph.NODE_SLOT_HEIGHT
|
||||
}
|
||||
|
||||
@@ -530,7 +565,9 @@ function convertToWidget(node: LGraphNode, widget: IWidget) {
|
||||
const [oldWidth, oldHeight] = node.size
|
||||
node.removeInput(node.inputs.findIndex((i) => i.widget?.name === widget.name))
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (const widget of node.widgets) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget.last_y -= LiteGraph.NODE_SLOT_HEIGHT
|
||||
}
|
||||
|
||||
@@ -562,9 +599,11 @@ export function setWidgetConfig(
|
||||
}
|
||||
|
||||
if ('link' in slot) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const link = app.graph.links[slot.link]
|
||||
if (link) {
|
||||
const originNode = app.graph.getNodeById(link.origin_id)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (isPrimitiveNode(originNode)) {
|
||||
if (config) {
|
||||
originNode.recreateWidget()
|
||||
@@ -588,6 +627,7 @@ export function mergeIfValid(
|
||||
config1 = getWidgetConfig(output)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const customSpec = mergeInputSpec(config1, config2)
|
||||
|
||||
if (customSpec || forceUpdate) {
|
||||
@@ -595,17 +635,24 @@ export function mergeIfValid(
|
||||
output.widget[CONFIG] = customSpec
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widget = recreateWidget?.call(this)
|
||||
// When deleting a node this can be null
|
||||
if (widget) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const min = widget.options.min
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const max = widget.options.max
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (min != null && widget.value < min) widget.value = min
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (max != null && widget.value > max) widget.value = max
|
||||
// @ts-expect-error fixme ts strict error
|
||||
widget.callback(widget.value)
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return { customConfig: customSpec[1] }
|
||||
}
|
||||
|
||||
@@ -622,6 +669,7 @@ app.registerExtension({
|
||||
setup() {
|
||||
app.canvas.getWidgetLinkType = function (widget, node) {
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const nodeDef = nodeDefStore.nodeDefsByName[node.type]
|
||||
const input = nodeDef.inputs[widget.name]
|
||||
return input?.type
|
||||
@@ -675,6 +723,7 @@ app.registerExtension({
|
||||
) {
|
||||
if (!slot.input || !slot.input.widget) return []
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const widget = this.widgets.find((w) => w.name === slot.input.widget.name)
|
||||
if (!widget) return []
|
||||
return [
|
||||
@@ -685,13 +734,15 @@ app.registerExtension({
|
||||
]
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
nodeType.prototype.getExtraMenuOptions = function (
|
||||
this: LGraphNode,
|
||||
_,
|
||||
options
|
||||
) {
|
||||
const r = origGetExtraMenuOptions
|
||||
? origGetExtraMenuOptions.apply(this, arguments)
|
||||
? // @ts-expect-error fixme ts strict error
|
||||
origGetExtraMenuOptions.apply(this, arguments)
|
||||
: undefined
|
||||
|
||||
const getPointerCanvasPos = () => {
|
||||
@@ -700,6 +751,7 @@ app.registerExtension({
|
||||
}
|
||||
|
||||
if (this.widgets) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const { canvasX, canvasY } = getPointerCanvasPos()
|
||||
const widget = this.getWidgetOnPos(canvasX, canvasY)
|
||||
// @ts-expect-error custom widget type
|
||||
@@ -748,10 +800,12 @@ app.registerExtension({
|
||||
options.push({
|
||||
content: 'Convert Widget to Input',
|
||||
submenu: {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
options: toInput
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
options.push(...toInput, null)
|
||||
}
|
||||
}
|
||||
@@ -778,8 +832,11 @@ app.registerExtension({
|
||||
|
||||
for (const input of this.inputs) {
|
||||
if (input.widget) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (!input.widget[GET_CONFIG]) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
input.widget[GET_CONFIG] = () =>
|
||||
// @ts-expect-error fixme ts strict error
|
||||
getConfig.call(this, input.widget.name)
|
||||
}
|
||||
|
||||
@@ -791,6 +848,7 @@ app.registerExtension({
|
||||
// If we are an old converted combo then replace the input type and the stored link data
|
||||
input.type = 'COMBO'
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const link = app.graph.links[input.link]
|
||||
if (link) {
|
||||
link.type = input.type
|
||||
@@ -800,6 +858,7 @@ app.registerExtension({
|
||||
delete input.widget.config
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const w = this.widgets.find((w) => w.name === input.widget.name)
|
||||
if (w) {
|
||||
hideWidget(this, w)
|
||||
@@ -833,14 +892,19 @@ app.registerExtension({
|
||||
const origOnConfigure = nodeType.prototype.onConfigure
|
||||
nodeType.prototype.onConfigure = function (this: LGraphNode) {
|
||||
const r = origOnConfigure
|
||||
? origOnConfigure.apply(this, arguments)
|
||||
? // @ts-expect-error fixme ts strict error
|
||||
origOnConfigure.apply(this, arguments)
|
||||
: undefined
|
||||
if (!app.configuringGraph && this.inputs) {
|
||||
// On copy + paste of nodes, ensure that widget configs are set up
|
||||
for (const input of this.inputs) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (input.widget && !input.widget[GET_CONFIG]) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
input.widget[GET_CONFIG] = () =>
|
||||
// @ts-expect-error fixme ts strict error
|
||||
getConfig.call(this, input.widget.name)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const w = this.widgets.find((w) => w.name === input.widget.name)
|
||||
if (w) {
|
||||
hideWidget(this, w)
|
||||
@@ -868,7 +932,8 @@ app.registerExtension({
|
||||
slot: number
|
||||
) {
|
||||
const r = origOnInputDblClick
|
||||
? origOnInputDblClick.apply(this, arguments)
|
||||
? // @ts-expect-error fixme ts strict error
|
||||
origOnInputDblClick.apply(this, arguments)
|
||||
: undefined
|
||||
|
||||
const input = this.inputs[slot]
|
||||
@@ -876,6 +941,7 @@ app.registerExtension({
|
||||
// Not a widget input or already handled input
|
||||
if (
|
||||
!(input.type in ComfyWidgets) &&
|
||||
// @ts-expect-error fixme ts strict error
|
||||
!(input.widget?.[GET_CONFIG]?.()?.[0] instanceof Array)
|
||||
) {
|
||||
return r //also Not a ComfyWidgets input or combo (do nothing)
|
||||
@@ -884,10 +950,12 @@ app.registerExtension({
|
||||
|
||||
// Create a primitive node
|
||||
const node = LiteGraph.createNode('PrimitiveNode')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
app.graph.add(node)
|
||||
|
||||
// Calculate a position that wont directly overlap another node
|
||||
const pos: [number, number] = [
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.pos[0] - node.size[0] - 30,
|
||||
this.pos[1]
|
||||
]
|
||||
@@ -895,8 +963,11 @@ app.registerExtension({
|
||||
pos[1] += LiteGraph.NODE_TITLE_HEIGHT
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.pos = pos
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.connect(0, this, slot)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
node.title = input.name
|
||||
|
||||
return r
|
||||
@@ -905,6 +976,7 @@ app.registerExtension({
|
||||
registerCustomNodes() {
|
||||
LiteGraph.registerNodeType(
|
||||
'PrimitiveNode',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
Object.assign(PrimitiveNode, {
|
||||
title: 'Primitive'
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user