Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4bf3aebd5 | ||
|
|
7306f17499 | ||
|
|
0f9599ca35 | ||
|
|
9076a7f23d | ||
|
|
64ace2c933 | ||
|
|
318201cb4e | ||
|
|
143058b91b | ||
|
|
8f633400c8 | ||
|
|
ab177722be | ||
|
|
db3ab8b112 | ||
|
|
614b690fc5 | ||
|
|
8aca1a39b4 | ||
|
|
5992abe727 | ||
|
|
d899afff89 | ||
|
|
9235482b2b |
@@ -0,0 +1,26 @@
|
||||
name: Publish to Comfy registry
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
paths:
|
||||
- "pyproject.toml"
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
publish-node:
|
||||
name: Publish Custom Node to registry
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository_owner == 'NODE_AUTHOR_OWNER' }}
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Publish Custom Node
|
||||
uses: Comfy-Org/publish-node-action@v1
|
||||
with:
|
||||
## Add your own personal access token to your Github Repository secrets and reference it here.
|
||||
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
|
||||
@@ -1 +1,17 @@
|
||||
# WTF? - a debug node for ComfyUI
|
||||
# WTF? - a debug node for ComfyUI
|
||||
|
||||
This node provides a simple way to view the output of many nodes, without leaving ComfyUI.
|
||||
|
||||
### Simple string
|
||||

|
||||
|
||||
### Tensor
|
||||

|
||||
|
||||
### An OUTPUT_IS_LIST node (Rebatched images)
|
||||

|
||||
|
||||
### A list node without OUTPUT_IS_LIST
|
||||

|
||||
|
||||
_"What's that field?"_
|
||||
|
||||
+2
-2
@@ -68,10 +68,10 @@ class WTFDebugNode:
|
||||
except Exception as e:
|
||||
info["shape"] = str(e)
|
||||
|
||||
info["value"] = str(item) if item != None else None
|
||||
info["value"] = str(item) if item is not None else None
|
||||
out.append(info)
|
||||
|
||||
return { "ui": { "items": out, "length": len(anything) } }
|
||||
return { "ui": { "items": out } }
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"WTFDebugNode": WTFDebugNode,
|
||||
|
||||
+97
-96
@@ -1,117 +1,118 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { ComfyWidgets } from "../../scripts/widgets.js";
|
||||
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)
|
||||
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
|
||||
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") {
|
||||
name: "WTFDebugNode",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name !== "WTFDebugNode") return
|
||||
|
||||
const origOnExecuted = nodeType.prototype.onExecuted;
|
||||
nodeType.prototype.onExecuted = function (message) {
|
||||
const r = origOnExecuted
|
||||
? origOnExecuted?.apply(this, arguments)
|
||||
: undefined
|
||||
// Ensure attached links keep their colours
|
||||
const origOnConnectionsChange = nodeType.prototype.onConnectionsChange
|
||||
nodeType.prototype.onConnectionsChange = function (type, slotIndex, isConnected, link, ioSlot) {
|
||||
origOnConnectionsChange?.apply(this, arguments)
|
||||
|
||||
// Because debug
|
||||
console.log(message)
|
||||
if (isConnected && link?.type === "*")
|
||||
link.type = this.graph.getNodeById(link.origin_id)?.outputs?.[link.origin_slot]?.type
|
||||
}
|
||||
|
||||
// Sanity init
|
||||
this.widgets ??= []
|
||||
this.serialize_widgets = false
|
||||
const baseOpacity = app.canvas.editor_alpha
|
||||
// Show the text in the UI
|
||||
const origOnExecuted = nodeType.prototype.onExecuted
|
||||
nodeType.prototype.onExecuted = function (message) {
|
||||
const r = origOnExecuted
|
||||
? origOnExecuted?.apply(this, arguments)
|
||||
: undefined
|
||||
|
||||
// Clear if invalid
|
||||
const itemsLength = parseInt(message?.items?.length)
|
||||
if (isNaN(itemsLength)) {
|
||||
removeAllWidgets(this)
|
||||
return r
|
||||
}
|
||||
// Because debug
|
||||
console.log(message)
|
||||
|
||||
const isMultiItem = itemsLength > 1
|
||||
const wasMultiItem = this.debugNodeLength !== 1
|
||||
// Sanity init
|
||||
this.widgets ??= []
|
||||
this.serialize_widgets = false
|
||||
const baseOpacity = app.canvas.editor_alpha
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clear if invalid
|
||||
const itemsLength = parseInt(message?.items?.length)
|
||||
if (isNaN(itemsLength)) {
|
||||
removeAllWidgets(this)
|
||||
return r
|
||||
}
|
||||
|
||||
this.debugNodeLength = itemsLength
|
||||
const maxItems = Math.min(itemsLength, hardLimit)
|
||||
const isMultiItem = itemsLength > 1
|
||||
const wasMultiItem = this.debugNodeLength !== 1
|
||||
|
||||
// Create / update widget values for each item
|
||||
for (let i = 0; i < maxItems; i++) {
|
||||
const item = message.items[i]
|
||||
const type = item.type
|
||||
const len = item.len
|
||||
const shape = item.shape
|
||||
const firstIterItem = item.firstIterItem
|
||||
const value = item.value
|
||||
|
||||
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
|
||||
|
||||
if (!widget.options)
|
||||
widget.options = {}
|
||||
widget.options.serialize = false
|
||||
widget.value = value
|
||||
widget.disabled = value === null || value === undefined
|
||||
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(() => {
|
||||
const size = this.computeSize();
|
||||
for (const widget of this.widgets.filter(x => x.element)) {
|
||||
widget.onResize?.(size)
|
||||
}
|
||||
})
|
||||
|
||||
return r
|
||||
}
|
||||
// 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
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[project]
|
||||
name = "debugnode-comfyui"
|
||||
description = "This node provides a simple way to view the output of many nodes, without leaving ComfyUI."
|
||||
version = "1.1.1"
|
||||
license = {file = "LICENSE"}
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/webfiltered/DebugNode-ComfyUI"
|
||||
# Used by Comfy Registry https://comfyregistry.org
|
||||
|
||||
[tool.comfy]
|
||||
PublisherId = "filtered"
|
||||
DisplayName = "DebugNode-ComfyUI"
|
||||
Icon = ""
|
||||
Reference in New Issue
Block a user