119 lines
3.6 KiB
JavaScript
119 lines
3.6 KiB
JavaScript
import { app } from "../../scripts/app.js"
|
|
import { ComfyWidgets } from "../../scripts/widgets.js"
|
|
|
|
const hardLimit = 100
|
|
|
|
// Does most of the regular textarea cleanup, but leaks a ref in domWidget.js -> elementWidgets until the node is removed
|
|
function removeWidget(node, widget) {
|
|
widget.onRemove?.()
|
|
const index = node.widgets.indexOf(widget)
|
|
if (index !== -1)
|
|
node.widgets.splice(index, 1)
|
|
}
|
|
|
|
function removeAllWidgets(node) {
|
|
for (const widget of node.widgets) {
|
|
widget.onRemove?.()
|
|
}
|
|
node.widgets.length = 0
|
|
}
|
|
|
|
// Main logic
|
|
app.registerExtension({
|
|
name: "WTFDebugNode",
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
if (nodeData.name !== "WTFDebugNode") return
|
|
|
|
// Ensure attached links keep their colours
|
|
const origOnConnectionsChange = nodeType.prototype.onConnectionsChange
|
|
nodeType.prototype.onConnectionsChange = function (type, slotIndex, isConnected, link, ioSlot) {
|
|
origOnConnectionsChange?.apply(this, arguments)
|
|
|
|
if (isConnected && link?.type === "*")
|
|
link.type = this.graph.getNodeById(link.origin_id)?.outputs?.[link.origin_slot]?.type
|
|
}
|
|
|
|
// Show the text in the UI
|
|
const origOnExecuted = nodeType.prototype.onExecuted
|
|
nodeType.prototype.onExecuted = function (message) {
|
|
const r = origOnExecuted
|
|
? origOnExecuted?.apply(this, arguments)
|
|
: undefined
|
|
|
|
// Because debug
|
|
console.log(message)
|
|
|
|
// Sanity init
|
|
this.widgets ??= []
|
|
this.serialize_widgets = false
|
|
const baseOpacity = app.canvas.editor_alpha
|
|
|
|
// Clear if invalid
|
|
const itemsLength = parseInt(message?.items?.length)
|
|
if (isNaN(itemsLength)) {
|
|
removeAllWidgets(this)
|
|
return r
|
|
}
|
|
|
|
const isMultiItem = itemsLength > 1
|
|
const wasMultiItem = this.debugNodeLength !== 1
|
|
|
|
// Clean up existing widgets if required
|
|
if (isMultiItem !== wasMultiItem) {
|
|
removeAllWidgets(this)
|
|
}
|
|
// Remove only widgets we can't reuse
|
|
else if (this.debugNodeLength > itemsLength) {
|
|
for (let i = itemsLength; i <= this.debugNodeLength; i++) {
|
|
for (const widget of this.widgets.filter(x => x.name.endsWith(` ${i}`))) {
|
|
removeWidget(this, widget)
|
|
}
|
|
}
|
|
}
|
|
|
|
this.debugNodeLength = itemsLength
|
|
const maxItems = Math.min(itemsLength, hardLimit)
|
|
|
|
// Create / update widget values for each item
|
|
for (let i = 0; i < maxItems; i++) {
|
|
const item = message.items[i]
|
|
const { type, len, shape, firstIterItem, value } = item
|
|
|
|
function processWidget(node, name, value, isMultiline = false) {
|
|
const numberedName = isMultiItem
|
|
? `${name} ${i}`
|
|
: name
|
|
const comfyType = isMultiline
|
|
? ["STRING", { multiline: true }]
|
|
: ["STRING", {}]
|
|
|
|
const current = node.widgets.find(x => x.name === numberedName)
|
|
const widget = current ?? ComfyWidgets.STRING(node, numberedName, comfyType, app).widget
|
|
|
|
widget.options ??= {}
|
|
widget.options.serialize = false
|
|
widget.value = value
|
|
widget.disabled = value == null
|
|
if (isMultiline) {
|
|
widget.element.style.opacity = widget.disabled
|
|
? baseOpacity * 0.5
|
|
: baseOpacity
|
|
}
|
|
}
|
|
|
|
processWidget(this, "type", type)
|
|
processWidget(this, "len()", len)
|
|
processWidget(this, "shape", shape)
|
|
processWidget(this, "type of first iter() item", firstIterItem)
|
|
processWidget(this, "value", value, true)
|
|
}
|
|
|
|
requestAnimationFrame(() => {
|
|
this.onResize?.(this.size)
|
|
})
|
|
|
|
return r
|
|
}
|
|
},
|
|
})
|